Skip to content

Commit 40eea80

Browse files
aryabinindavem330
authored andcommitted
net: sendmsg: fix NULL pointer dereference
Sasha's report: > While fuzzing with trinity inside a KVM tools guest running the latest -next > kernel with the KASAN patchset, I've stumbled on the following spew: > > [ 4448.949424] ================================================================== > [ 4448.951737] AddressSanitizer: user-memory-access on address 0 > [ 4448.952988] Read of size 2 by thread T19638: > [ 4448.954510] CPU: 28 PID: 19638 Comm: trinity-c76 Not tainted 3.16.0-rc4-next-20140711-sasha-00046-g07d3099-dirty #813 > [ 4448.956823] ffff88046d86ca40 0000000000000000 ffff880082f37e78 ffff880082f37a40 > [ 4448.958233] ffffffffb6e47068 ffff880082f37a68 ffff880082f37a58 ffffffffb242708d > [ 4448.959552] 0000000000000000 ffff880082f37a88 ffffffffb24255b1 0000000000000000 > [ 4448.961266] Call Trace: > [ 4448.963158] dump_stack (lib/dump_stack.c:52) > [ 4448.964244] kasan_report_user_access (mm/kasan/report.c:184) > [ 4448.965507] __asan_load2 (mm/kasan/kasan.c:352) > [ 4448.966482] ? netlink_sendmsg (net/netlink/af_netlink.c:2339) > [ 4448.967541] netlink_sendmsg (net/netlink/af_netlink.c:2339) > [ 4448.968537] ? get_parent_ip (kernel/sched/core.c:2555) > [ 4448.970103] sock_sendmsg (net/socket.c:654) > [ 4448.971584] ? might_fault (mm/memory.c:3741) > [ 4448.972526] ? might_fault (./arch/x86/include/asm/current.h:14 mm/memory.c:3740) > [ 4448.973596] ? verify_iovec (net/core/iovec.c:64) > [ 4448.974522] ___sys_sendmsg (net/socket.c:2096) > [ 4448.975797] ? put_lock_stats.isra.13 (./arch/x86/include/asm/preempt.h:98 kernel/locking/lockdep.c:254) > [ 4448.977030] ? lock_release_holdtime (kernel/locking/lockdep.c:273) > [ 4448.978197] ? lock_release_non_nested (kernel/locking/lockdep.c:3434 (discriminator 1)) > [ 4448.979346] ? check_chain_key (kernel/locking/lockdep.c:2188) > [ 4448.980535] __sys_sendmmsg (net/socket.c:2181) > [ 4448.981592] ? trace_hardirqs_on_caller (kernel/locking/lockdep.c:2600) > [ 4448.982773] ? trace_hardirqs_on (kernel/locking/lockdep.c:2607) > [ 4448.984458] ? syscall_trace_enter (arch/x86/kernel/ptrace.c:1500 (discriminator 2)) > [ 4448.985621] ? trace_hardirqs_on_caller (kernel/locking/lockdep.c:2600) > [ 4448.986754] SyS_sendmmsg (net/socket.c:2201) > [ 4448.987708] tracesys (arch/x86/kernel/entry_64.S:542) > [ 4448.988929] ================================================================== This reports means that we've come to netlink_sendmsg() with msg->msg_name == NULL and msg->msg_namelen > 0. After this report there was no usual "Unable to handle kernel NULL pointer dereference" and this gave me a clue that address 0 is mapped and contains valid socket address structure in it. This bug was introduced in f3d3342 (net: rework recvmsg handler msg_name and msg_namelen logic). Commit message states that: "Set msg->msg_name = NULL if user specified a NULL in msg_name but had a non-null msg_namelen in verify_iovec/verify_compat_iovec. This doesn't affect sendto as it would bail out earlier while trying to copy-in the address." But in fact this affects sendto when address 0 is mapped and contains socket address structure in it. In such case copy-in address will succeed, verify_iovec() function will successfully exit with msg->msg_namelen > 0 and msg->msg_name == NULL. This patch fixes it by setting msg_namelen to 0 if msg_name == NULL. Cc: Hannes Frederic Sowa <[email protected]> Cc: Eric Dumazet <[email protected]> Cc: <[email protected]> Reported-by: Sasha Levin <[email protected]> Signed-off-by: Andrey Ryabinin <[email protected]> Acked-by: Hannes Frederic Sowa <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 86b7987 commit 40eea80

File tree

2 files changed

+8
-7
lines changed

2 files changed

+8
-7
lines changed

net/compat.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,19 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
8585
{
8686
int tot_len;
8787

88-
if (kern_msg->msg_namelen) {
88+
if (kern_msg->msg_name && kern_msg->msg_namelen) {
8989
if (mode == VERIFY_READ) {
9090
int err = move_addr_to_kernel(kern_msg->msg_name,
9191
kern_msg->msg_namelen,
9292
kern_address);
9393
if (err < 0)
9494
return err;
9595
}
96-
if (kern_msg->msg_name)
97-
kern_msg->msg_name = kern_address;
98-
} else
96+
kern_msg->msg_name = kern_address;
97+
} else {
9998
kern_msg->msg_name = NULL;
99+
kern_msg->msg_namelen = 0;
100+
}
100101

101102
tot_len = iov_from_user_compat_to_kern(kern_iov,
102103
(struct compat_iovec __user *)kern_msg->msg_iov,

net/core/iovec.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
3939
{
4040
int size, ct, err;
4141

42-
if (m->msg_namelen) {
42+
if (m->msg_name && m->msg_namelen) {
4343
if (mode == VERIFY_READ) {
4444
void __user *namep;
4545
namep = (void __user __force *) m->msg_name;
@@ -48,10 +48,10 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
4848
if (err < 0)
4949
return err;
5050
}
51-
if (m->msg_name)
52-
m->msg_name = address;
51+
m->msg_name = address;
5352
} else {
5453
m->msg_name = NULL;
54+
m->msg_namelen = 0;
5555
}
5656

5757
size = m->msg_iovlen * sizeof(struct iovec);

0 commit comments

Comments
 (0)