Date: Sat, 1 Oct 2011 00:19:28 +0000 From: Alexander Best <arundel@freebsd.org> To: Jung-uk Kim <jkim@FreeBSD.org> Cc: freebsd-emulation@FreeBSD.org, security-officer@freebsd.org Subject: Re: HEADS UP: breakage with linux emulation + SA-11:05.unix Message-ID: <20111001001928.GA16489@freebsd.org> In-Reply-To: <201109301902.44281.jkim@FreeBSD.org> References: <4E857719.7060306@freebsd.org> <201109301803.01010.jkim@FreeBSD.org> <201109301902.44281.jkim@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri Sep 30 11, Jung-uk Kim wrote: > 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 i've applied your patch to a r225888 kernel and it fully fixed flash support for me. also i haven't experienced any issues in connection with the patch. good work! (: cheers. alex > > Please note this is an *unofficial* fix. > > Jung-uk Kim > 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 *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20111001001928.GA16489>