Date: Fri, 30 Sep 2011 19:02:41 -0400 From: Jung-uk Kim <jkim@FreeBSD.org> To: freebsd-emulation@FreeBSD.org Cc: security-officer@freebsd.org Subject: Re: HEADS UP: breakage with linux emulation + SA-11:05.unix Message-ID: <201109301902.44281.jkim@FreeBSD.org> In-Reply-To: <201109301803.01010.jkim@FreeBSD.org> References: <4E857719.7060306@freebsd.org> <201109301803.01010.jkim@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_UqkhOqNyGfbBJVR Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline On Friday 30 September 2011 06:02 pm, Jung-uk Kim wrote: > [Removed freebsd-security@] > > On Friday 30 September 2011 04:00 am, FreeBSD Security Officer wrote: > > Hi all, > > > > It appears that the security fix in SA-11:05.unix exposed a bug > > in the linux emulation code: Linux has a different size of > > sockaddr_un than FreeBSD, and the linux emulation code was > > passing socket addresses through without doing any translation > > first. > > > > This appears to break all X-using Linux code -- both applications > > and plugins such as the widely-used flash plugin -- and probably > > other Linux applications too. > > > > I am working on a fix for this and will send an updated advisory > > out as soon as it's ready. > > For the impatient, I have written *unofficial* patch for this > Linuxulator regression. > > Please note that I am posting this patch to this ML only because I > wanted to point out Linuxulator is actually missing very important > feature, i.e., anonymous Unix domain socket. I have updated the patch. It should be slightly more safer than the previous version. This patch is also available from here: http://people.freebsd.org/~jkim/linux_socket.diff Please note this is an *unofficial* fix. Jung-uk Kim --Boundary-00=_UqkhOqNyGfbBJVR Content-Type: text/plain; charset="iso-8859-1"; name="linux_socket.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="linux_socket.diff" Index: sys/compat/linux/linux_socket.c =================================================================== --- sys/compat/linux/linux_socket.c (revision 225884) +++ sys/compat/linux/linux_socket.c (working copy) @@ -96,14 +96,13 @@ static int do_sa_get(struct sockaddr **sap, const struct osockaddr *osa, int *osalen, struct malloc_type *mtype) { - int error=0, bdom; struct sockaddr *sa; struct osockaddr *kosa; - int alloclen; #ifdef INET6 + struct sockaddr_in6 *sin6; int oldv6size; - struct sockaddr_in6 *sin6; #endif + int alloclen, bdom, error, hdrlen, pathlen; if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) return (EINVAL); @@ -133,6 +132,17 @@ do_sa_get(struct sockaddr **sap, const struct osoc goto out; } + if (bdom == AF_LOCAL) { + hdrlen = offsetof(struct sockaddr_un, sun_path); + if (alloclen > hdrlen) { + pathlen = sizeof(struct sockaddr_un) - hdrlen; + alloclen = strnlen(kosa->sa_data, pathlen); + if (alloclen == pathlen) + log(LOG_DEBUG, "long sockaddr_un truncated\n"); + alloclen += hdrlen; + } + } + #ifdef INET6 /* * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, @@ -696,13 +706,26 @@ static int linux_bind(struct thread *td, struct linux_bind_args *args) { struct sockaddr *sa; - int error; + int error, pathlen; error = linux_getsockaddr(&sa, PTRIN(args->name), args->namelen); if (error) return (error); + /* + * XXX Anonymous Unix domain socket not supported. + */ + if (sa->sa_family == AF_LOCAL) { + pathlen = sa->sa_len - offsetof(struct sockaddr_un, sun_path); + if (pathlen <= 0) { + free(sa, M_SONAME); + if (pathlen == 0) + return (0); + return (EINVAL); + } + } + error = kern_bind(td, args->s, sa); free(sa, M_SONAME); if (error == EADDRNOTAVAIL && args->namelen != sizeof(struct sockaddr_in)) @@ -723,13 +746,26 @@ linux_connect(struct thread *td, struct linux_conn struct socket *so; struct sockaddr *sa; u_int fflag; - int error; + int error, pathlen; error = linux_getsockaddr(&sa, (struct osockaddr *)PTRIN(args->name), args->namelen); if (error) return (error); + /* + * XXX Anonymous Unix domain socket not supported. + */ + if (sa->sa_family == AF_LOCAL) { + pathlen = sa->sa_len - offsetof(struct sockaddr_un, sun_path); + if (pathlen <= 0) { + free(sa, M_SONAME); + if (pathlen == 0) + return (ENOENT); + return (EINVAL); + } + } + error = kern_connect(td, args->s, sa); free(sa, M_SONAME); if (error != EISCONN) Index: sys/conf/files =================================================================== --- sys/conf/files (revision 225884) +++ sys/conf/files (working copy) @@ -2548,6 +2548,7 @@ libkern/strlcpy.c standard libkern/strlen.c standard libkern/strncmp.c standard libkern/strncpy.c standard +libkern/strnlen.c standard libkern/strsep.c standard libkern/strspn.c standard libkern/strstr.c standard Index: sys/libkern/strnlen.c =================================================================== --- sys/libkern/strnlen.c (revision 225884) +++ sys/libkern/strnlen.c (working copy) @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/libkern.h> + +size_t +strnlen(const char *s, size_t maxlen) +{ + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) + break; + } + return (len); +} Index: sys/sys/libkern.h =================================================================== --- sys/sys/libkern.h (revision 225884) +++ sys/sys/libkern.h (working copy) @@ -116,6 +116,7 @@ size_t strlen(const char *); int strncasecmp(const char *, const char *, size_t); int strncmp(const char *, const char *, size_t); char *strncpy(char * __restrict, const char * __restrict, size_t); +size_t strnlen(const char *, size_t); char *strsep(char **, const char *delim); size_t strspn(const char *, const char *); char *strstr(const char *, const char *); --Boundary-00=_UqkhOqNyGfbBJVR--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201109301902.44281.jkim>