Commit f0847b77 authored by Eric Dumazet's avatar Eric Dumazet Committed by Yongqiang Liu
Browse files

net: add copy_safe_from_sockptr() helper

mainline inclusion
from mainline-v6.9
commit 6309863b31dd80317cd7d6824820b44e254e2a9c
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9U9YN
CVE: CVE-2024-36915

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6309863b31dd80317cd7d6824820b44e254e2a9c



--------------------------------

copy_from_sockptr() helper is unsafe, unless callers
did the prior check against user provided optlen.

Too many callers get this wrong, lets add a helper to
fix them and avoid future copy/paste bugs.

Instead of :

   if (optlen < sizeof(opt)) {
       err = -EINVAL;
       break;
   }
   if (copy_from_sockptr(&opt, optval, sizeof(opt)) {
       err = -EFAULT;
       break;
   }

Use :

   err = copy_safe_from_sockptr(&opt, sizeof(opt),
                                optval, optlen);
   if (err)
       break;

Conflicts:
	include/linux/sockptr.h
[There are only context conficts, no code logic conflicts]
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20240408082845.3957374-2-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarWang Wensheng <wangwensheng4@huawei.com>
Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
parent a41e8dae
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -50,11 +50,36 @@ static inline int copy_from_sockptr_offset(void *dst, sockptr_t src,
	return 0;
}

/* Deprecated.
 * This is unsafe, unless caller checked user provided optlen.
 * Prefer copy_safe_from_sockptr() instead.
 */
static inline int copy_from_sockptr(void *dst, sockptr_t src, size_t size)
{
	return copy_from_sockptr_offset(dst, src, 0, size);
}

/**
 * copy_safe_from_sockptr: copy a struct from sockptr
 * @dst:   Destination address, in kernel space. This buffer must be @ksize
 *         bytes long.
 * @ksize: Size of @dst struct.
 * @optval: Source address. (in user or kernel space)
 * @optlen: Size of @optval data.
 *
 * Returns:
 *  * -EINVAL: @optlen < @ksize
 *  * -EFAULT: access to userspace failed.
 *  * 0 : @ksize bytes were copied
 */
static inline int copy_safe_from_sockptr(void *dst, size_t ksize,
					 sockptr_t optval, unsigned int optlen)
{
	if (optlen < ksize)
		return -EINVAL;
	return copy_from_sockptr(dst, optval, ksize);
}

static inline int copy_to_sockptr_offset(sockptr_t dst, size_t offset,
		const void *src, size_t size)
{