kern/138860: [linux] linux_socketcall() causing buffer overflow

Mateusz Guzik mjguzik at gmail.com
Fri Jan 22 19:40:04 UTC 2010


The following reply was made to PR kern/138860; it has been noted by GNATS.

From: Mateusz Guzik <mjguzik at gmail.com>
To: bug-followup at FreeBSD.org, alexbestms at math.uni-muenster.de
Cc:  
Subject: Re: kern/138860: [linux] linux_socketcall() causing buffer overflow
Date: Fri, 22 Jan 2010 19:30:25 +0000

 Hi,
 
 It looks like the problem is caused by this:
 
 sys/compat/linux/linux_socket.c : do_sa_get() contains the following code:
 	if (*osalen < 2 || *osalen > UCHAR_MAX || !osa)
 		return (EINVAL);
 [..]
 	alloclen = *osalen;
 [..]
 	kosa = malloc(alloclen, mtype, M_WAITOK); // [1]
 
 	if ((error = copyin(osa, kosa, *osalen)))
 		goto out;
 
 	bdom = linux_to_bsd_domain(kosa->sa_family);
 [..]
 	if (bdom == AF_INET)
 		alloclen = sizeof(struct sockaddr_in); // [2]
 
 	sa = (struct sockaddr *) kosa;
 	sa->sa_family = bdom;
 	sa->sa_len = alloclen; // [3]
 
 	*sap = sa;
 	*osalen = alloclen;
 [..]
 --------
 
 *osalen bytes is allocated in [1]. In [2] we override the old value of alloclen
 and use it in assignment ([3]).
 
 So if *osalen is lower than sizeof(struct sockaddr_in), we return struct that is
 too small and contains faked length.
 
 This defeats checks placed in sys/netinet/in_pcb.c : in_pcbbind_setup() and
 leads to overflow by this (line 348 as of r202295):
 [..]
 bzero(&sin->sin_zero, sizeof(sin->sin_zero));
 [..]
 
 --------
 
 Proposed patch:
 
 http://student.agh.edu.pl/~mjguzik/linux_socket.patch
 
 Note: patch also changes return value from EINVAL to EAFNOSUPPORT in case of
 linux_to_bsd_domain's failure to match behaviour of other callers.
 
 Briefly tested with wget, Quake 3 and firefox.
 
 --
 Mateusz Guzik


More information about the freebsd-emulation mailing list