Commit 7b31d755 authored by Eric Dumazet's avatar Eric Dumazet Committed by Liu Jian
Browse files

netfilter: complete validation of user input

stable inclusion
from stable-v5.10.216
commit cf4bc359b76144a3dd55d7c09464ef4c5f2b2b05
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9QG86
CVE: CVE-2024-35896

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=cf4bc359b76144a3dd55d7c09464ef4c5f2b2b05



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

[ Upstream commit 65acf6e0501ac8880a4f73980d01b5d27648b956 ]

In my recent commit, I missed that do_replace() handlers
use copy_from_sockptr() (which I fixed), followed
by unsafe copy_from_sockptr_offset() calls.

In all functions, we can perform the @optlen validation
before even calling xt_alloc_table_info() with the following
check:

if ((u64)optlen < (u64)tmp.size + sizeof(tmp))
        return -EINVAL;

Fixes: 0c83842df40f ("netfilter: validate user input for expected length")
Reported-by: default avatarsyzbot <syzkaller@googlegroups.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Link: https://lore.kernel.org/r/20240409120741.3538135-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarLiu Jian <liujian56@huawei.com>
parent 3ba375ad
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -965,6 +965,8 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
		return -ENOMEM;
	if (tmp.num_counters == 0)
		return -EINVAL;
	if ((u64)len < (u64)tmp.size + sizeof(tmp))
		return -EINVAL;

	tmp.name[sizeof(tmp.name)-1] = 0;

@@ -1265,6 +1267,8 @@ static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
		return -ENOMEM;
	if (tmp.num_counters == 0)
		return -EINVAL;
	if ((u64)len < (u64)tmp.size + sizeof(tmp))
		return -EINVAL;

	tmp.name[sizeof(tmp.name)-1] = 0;

+4 −0
Original line number Diff line number Diff line
@@ -1119,6 +1119,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
		return -ENOMEM;
	if (tmp.num_counters == 0)
		return -EINVAL;
	if ((u64)len < (u64)tmp.size + sizeof(tmp))
		return -EINVAL;

	tmp.name[sizeof(tmp.name)-1] = 0;

@@ -1505,6 +1507,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
		return -ENOMEM;
	if (tmp.num_counters == 0)
		return -EINVAL;
	if ((u64)len < (u64)tmp.size + sizeof(tmp))
		return -EINVAL;

	tmp.name[sizeof(tmp.name)-1] = 0;

+4 −0
Original line number Diff line number Diff line
@@ -1137,6 +1137,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
		return -ENOMEM;
	if (tmp.num_counters == 0)
		return -EINVAL;
	if ((u64)len < (u64)tmp.size + sizeof(tmp))
		return -EINVAL;

	tmp.name[sizeof(tmp.name)-1] = 0;

@@ -1515,6 +1517,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
		return -ENOMEM;
	if (tmp.num_counters == 0)
		return -EINVAL;
	if ((u64)len < (u64)tmp.size + sizeof(tmp))
		return -EINVAL;

	tmp.name[sizeof(tmp.name)-1] = 0;