[PATCH] memory leak in sys_sendmsg()/sys_recvmsg() with MSG_CMSG_COMPAT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



sendmsg()/recvmsg() syscalls from o32/n32 apps to a 64bit kernel will
cause a kernel memory leak if iov_len > UIO_FASTIOV for each syscall!

This is because both sys_sendmsg() and verify_compat_iovec() kmalloc a
new iovec structure.  Only the one from sys_sendmsg() is free'ed.

I wrote a simple test program to confirm this after identifying the
problem:

http://davej.org/programs/testsendmsg.c


Running it shows the leak in the slab:

$ grep '^size-256 ' /proc/slabinfo
size-256           55972  55972    280   14    1 : tunables   32   16    8 : slabdata   3998   3998      0 : globalstat   58914  55972  4001    3    0    0   46    0 : cpustat 3806737   4480 3755027    240
$ ./testsendmsg
iterations=100 vec_size=16 block_size=256
$ grep '^size-256 ' /proc/slabinfo
size-256           56168  56168    280   14    1 : tunables   32   16    8 : slabdata   4012   4012      0 : globalstat   59110  56168  4015    3    0    0   46    0 : cpustat 3853259   4494 3801362    240
$ ./testsendmsg
iterations=100 vec_size=16 block_size=256
$ grep '^size-256 ' /proc/slabinfo
size-256           56378  56378    280   14    1 : tunables   32   16    8 : slabdata   4027   4027      0 : globalstat   59320  56378  4030    3    0    0   46    0 : cpustat 3853910   4509 3801828    240
$ ./testsendmsg
iterations=100 vec_size=16 block_size=256
$ grep '^size-256 ' /proc/slabinfo
size-256           56574  56574    280   14    1 : tunables   32   16    8 : slabdata   4041   4041      0 : globalstat   59516  56574  4044    3    0    0   46    0 : cpustat 3854888   4523 3802620    240
$ ./testsendmsg
iterations=100 vec_size=16 block_size=256
$ grep '^size-256 ' /proc/slabinfo
size-256           56756  56756    280   14    1 : tunables   32   16    8 : slabdata   4054   4054      0 : globalstat   59698  56756  4057    3    0    0   46    0 : cpustat 3856397   4536 3803942    240
$ ./testsendmsg
iterations=100 vec_size=16 block_size=256
$ grep '^size-256 ' /proc/slabinfo
size-256           56966  56966    280   14    1 : tunables   32   16    8 : slabdata   4069   4069      0 : globalstat   59908  56966  4072    3    0    0   46    0 : cpustat 3858528   4551 3805888    240
$ ./testsendmsg
iterations=100 vec_size=16 block_size=256
$ grep '^size-256 ' /proc/slabinfo
size-256           57176  57176    280   14    1 : tunables   32   16    8 : slabdata   4084   4084      0 : globalstat   60118  57176  4087    3    0    0   46    0 : cpustat 3863987   4566 3811162    240
$ ./testsendmsg
iterations=100 vec_size=16 block_size=256
$ grep '^size-256 ' /proc/slabinfo
size-256           57358  57358    280   14    1 : tunables   32   16    8 : slabdata   4097   4097      0 : globalstat   60300  57358  4100    3    0    0   46    0 : cpustat 3864397   4579 3811385    240


Note that the below fix will break solaris_sendmsg()/solaris_recvmsg()
as it also calls verify_compat_iovec() but expects it to malloc
internally.

-- 
Dave Johnson
Starent Networks

=========================

diff -Nru a/net/compat.c b/net/compat.c
--- a/net/compat.c	2005-07-29 16:12:39 -04:00
+++ b/net/compat.c	2005-07-29 16:12:39 -04:00
@@ -91,20 +91,11 @@
 	} else
 		kern_msg->msg_name = NULL;
 
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
 	tot_len = iov_from_user_compat_to_kern(kern_iov,
 					  (struct compat_iovec __user *)kern_msg->msg_iov,
 					  kern_msg->msg_iovlen);
 	if(tot_len >= 0)
 		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
 
 	return tot_len;
 }



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux