Commit 4909724b authored by Alexandra Kossovsky's avatar Alexandra Kossovsky Committed by David S. Miller

[COMPAT] net: SIOCGIFCONF data corruption

From: Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>

From http://bugzilla.kernel.org/show_bug.cgi?id=4746

There is user data corruption when using ioctl(SIOCGIFCONF) in 32-bit
application running amd64 kernel. I do not think that this problem is
exploitable, but any data corruption may lead to security problems.
Following code demonstrates the problem

#include <stdint.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/ioctl.h>

char buf[256];

main()
{
	int s = socket(AF_INET, SOCK_DGRAM, 0);
	struct ifconf req;
	int i;

	req.ifc_buf = buf;
	req.ifc_len = 41;

	printf("Result %d\n", ioctl(s, SIOCGIFCONF, &req));
	printf("Len %d\n", req.ifc_len);
	for (i = 41; i < 256; i++)
		if (buf[i] != 0)
			printf("Byte %d is corrupted\n", i);
}
	
Steps to reproduce:
Compile the code above into 32-bit elf and run it. You'll get
Result 0
Len 32
Byte 48 is corrupted
Byte 52 is corrupted
Byte 53 is corrupted
Byte 54 is corrupted
Byte 55 is corrupted
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fb0d366b
...@@ -686,7 +686,8 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -686,7 +686,8 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
ifr = ifc.ifc_req; ifr = ifc.ifc_req;
ifr32 = compat_ptr(ifc32.ifcbuf); ifr32 = compat_ptr(ifc32.ifcbuf);
for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; for (i = 0, j = 0;
i + sizeof (struct ifreq32) < ifc32.ifc_len && j < ifc.ifc_len;
i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
if (copy_in_user(ifr32, ifr, sizeof (struct ifreq32))) if (copy_in_user(ifr32, ifr, sizeof (struct ifreq32)))
return -EFAULT; return -EFAULT;
...@@ -702,10 +703,7 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -702,10 +703,7 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32)); i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32));
ifc32.ifc_len = i; ifc32.ifc_len = i;
} else { } else {
if (i <= ifc32.ifc_len) ifc32.ifc_len = i;
ifc32.ifc_len = i;
else
ifc32.ifc_len = i - sizeof (struct ifreq32);
} }
if (copy_to_user(compat_ptr(arg), &ifc32, sizeof(struct ifconf32))) if (copy_to_user(compat_ptr(arg), &ifc32, sizeof(struct ifconf32)))
return -EFAULT; return -EFAULT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment