[ advisories | exploits | discussions | news | conventions | security tools | texts & papers ]
 main menu
- feedback
- advertising
- privacy
- FightAIDS
- newsletter
- news
 
 discussions
- read forum
- new topic
- search
 

 meetings
- meetings list
- recent additions
- add your info
 
 top 100 sites
- visit top sites
- sign up now
- members
 
 webmasters

- add your url
- add domain
- search box
- link to us

 
 projects
- our projects
- free email
 
 m4d network
- security software
- secureroot
- m4d.com
Home : Advisories : Linux binary compatability mode can cause system compromise in FreeBSD

Title: Linux binary compatability mode can cause system compromise in FreeBSD
Released by: FreeBSD
Date: 29th August 2000
Printable version: Click here
-----BEGIN PGP SIGNED MESSAGE-----



=============================================================================

FreeBSD-SA-00:42                                           Security Advisory

                                                                FreeBSD, Inc.



Topic:          Linux binary compatability mode can cause system compromise



Category:       core

Module:         kernel

Announced:      2000-08-28

Credits:        Boris Nikolaus 

Affects:        FreeBSD 3.x, 4.x and 5.x prior to the correction date

Corrected:      2000-07-23 (FreeBSD 5.0-CURRENT)

                2000-07-29 (FreeBSD 4.1-STABLE)

2000-08-24 (FreeBSD 3.5-STABLE)

FreeBSD only:   Yes



I.   Background



FreeBSD is binary-compatible with the Linux operating system through a

loadable kernel module/optional kernel component.



II.  Problem Description



The linux binary-compatability module implements a "shadow" filesystem

hierarchy rooted in /compat/linux, which is overlayed against the

regular filesystem hierarchy so that Linux binaries "see" files in the

shadow hierarchy which can mask the native files.



Filenames in this shadow hierarchy are treated incorrectly by the

linux kernel module under certain circumstances, and a kernel stack

overflow leading to a system compromise by an unprivileged user may be

possible when very long filenames are used. This is only possible when

the linux kernel module is loaded, or the equivalent functionality is

statically compiled into the kernel. It is not enabled by default.



This vulnerability was fixed just after the release of FreeBSD

4.1-RELEASE, and 3.5-RELEASE is also vulnerable.



III. Impact



Local users may be able to obtain root privileges on the system when

linux compatability mode is enabled.



IV.  Workaround



To determine whether the linux compatability module has been loaded,

execute the following command as root and look for a 'linux.ko' entry:



# kldstat

 Id Refs Address    Size     Name

  1    7 0xc0100000 270be0   kernel

  2    1 0xc0371000 5540     vesa.ko

  3    1 0xc0377000 10094    randomdev.ko

  4    1 0xc0e17000 4e000    nfs.ko

  5    1 0xc0e83000 11000    linux.ko



If present, unload the "linux" module by executing the following

command as root:



# kldunload linux



For safety, remove the /modules/linux.ko file to prevent it being

reloaded accidentally, and add or change the following line in

/etc/rc.conf:



linux_enable="NO"       # Linux binary compatibility loaded at startup (or NO).



If the module is not loaded, to determine whether the functionality

has been statically compiled into the kernel, check the kernel

configuration file for the following line:



options    COMPAT_LINUX



If present, remove and recompile the kernel as described in

http://www.freebsd.org/handbook/kernelconfig.html and reboot the

system.



V.   Solution



One of the following:



1) Upgrade your vulnerable FreeBSD system to 3.5-STABLE, 4.1-STABLE or

5.0-CURRENT after the respective correction dates.



2) Apply the patch below and recompile your kernel.



Either save this advisory to a file, or download the patch and

detached PGP signature from the following locations, and verify the

signature using your PGP utility.



http://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:42/linux.patch

http://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:42/linux.patch.asc



# cd /usr/src/sys/i386/linux

# patch -p < /path/to/patch_or_advisory



[ Recompile your kernel as described in

http://www.freebsd.org/handbook/kernelconfig.html and reboot the

system ]



    Index: linux_misc.c

    ===================================================================

    RCS file: /home/ncvs/src/sys/i386/linux/linux_misc.c,v

    retrieving revision 1.77.2.3

    retrieving revision 1.77.2.4

    diff -u -r1.77.2.3 -r1.77.2.4

    --- linux_misc.c 2000/07/20 05:31:56 1.77.2.3

    +++ linux_misc.c 2000/07/30 05:36:11 1.77.2.4

    @@ -954,6 +954,8 @@

     tv[1].tv_usec = 0;

     /* so that utimes can copyin */

     tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv));

    + if (tvp == NULL)

    + return (ENAMETOOLONG);

     if ((error = copyout(tv, tvp, sizeof(tv))))

         return error;

     bsdutimes.tptr = tvp;

    Index: linux_util.c

    ===================================================================

    RCS file: /home/ncvs/src/sys/i386/linux/linux_util.c,v

    retrieving revision 1.9.2.1

    retrieving revision 1.9.2.2

    diff -u -r1.9.2.1 -r1.9.2.2

    --- linux_util.c 2000/07/07 01:23:45 1.9.2.1

    +++ linux_util.c 2000/07/30 05:36:11 1.9.2.2

    @@ -162,7 +162,10 @@

     else {

     sz = &ptr[len] - buf;

     *pbuf = stackgap_alloc(sgp, sz + 1);

    - error = copyout(buf, *pbuf, sz);

    + if (*pbuf != NULL)

    + error = copyout(buf, *pbuf, sz);

    + else

    + error = ENAMETOOLONG;

     free(buf, M_TEMP);

     }



    Index: linux_util.h

    ===================================================================

    RCS file: /home/ncvs/src/sys/i386/linux/linux_util.h,v

    retrieving revision 1.10

    retrieving revision 1.10.2.1

    diff -u -r1.10 -r1.10.2.1

    --- linux_util.h 1999/12/04 11:10:22 1.10

    +++ linux_util.h 2000/07/30 05:36:11 1.10.2.1

    @@ -56,29 +56,27 @@

     static __inline caddr_t stackgap_init(void);

     static __inline void *stackgap_alloc(caddr_t *, size_t);



    +#define szsigcode (*(curproc->p_sysent->sv_szsigcode))

    +

     static __inline caddr_t

     stackgap_init()

     {

    -#define szsigcode (*(curproc->p_sysent->sv_szsigcode))

     return (caddr_t)(PS_STRINGS - szsigcode - SPARE_USRSPACE);

     }



    -

     static __inline void *

     stackgap_alloc(sgp, sz)

     caddr_t *sgp;

     size_t   sz;

     {

    - void *p = (void *) *sgp;

    - *sgp += ALIGN(sz);

    + void *p = (void *) *sgp;

    +

    + sz = ALIGN(sz);

    + if (*sgp + sz > (caddr_t)(PS_STRINGS - szsigcode))

    + return NULL;

    + *sgp += sz;

     return p;

     }

    -

    -#ifdef DEBUG_LINUX

    -#define DPRINTF(a)      printf a;

    -#else

    -#define DPRINTF(a)

    -#endif



     extern const char linux_emul_path[];



-----BEGIN PGP SIGNATURE-----

Version: 2.6.2



iQCVAwUBOaq1wFUuHi5z0oilAQFcVQQAlYhhDM6T/qEDqVTvG9yr9mv++LVGqqRE

SI4MEbmwbV5NvmFqTM2OzGpKsUaAy9gEfA5mjVKR+PRFoY7g68heFGAKWSRHmgs5

ramrzVxBHOeviaHeAXpH7LgJOdFo8EwhqehLtv+M0I5n9JJjPvAEWXG9cdiYXTto

pKJAPVXr9NU=

=r8gN

-----END PGP SIGNATURE-----








(C) 1999-2000 All rights reserved.