amd from the amd-920824upl102-6.i386.rpm file distributed with RedHat Linux 4.1 does not honor the nodev option for NFS filesystems and probably other mount types, allowing any user access to the device files in /dev on a system, provided that they have root access to another linux box on the network. In addition, the default amd.conf from RH 4.1 maps /net/* to NFS mounting, which makes the bug in amd an easily accessible security hole. The Exploit: A friend of mine who has an account on my machine found a major security hole in amd when he decided to play a prank on me involving /dev/dsp at odd hours, but found I had denied access to /dev/dsp and /dev/audio. He assumed that I had forgotten to put the options nosuid and nodev in the amd mapping for NFS (the default RedHat 4.1 mapping, which *does* have opts=nosuid,nodev), so he created a char device on his machine with major number 14 and minor 3, permissions 666, exported the directory it was in via NFS, and logged into my machine. He used the /net/* amd mapping to mount the directory, and then used the char device in the NFS-mounted filesystem to play sounds, although /proc/mounts and /etc/mtab displayed it as mounted nodev. This exploit works for block and char devices. It could be used to do more malicious acts than merely play sounds, such as scan /dev/mem for passwords, change file permissions or the contents of /etc/shadow with a raw disk editor, and sundry and various other bad things. This bug may affect any other distributions that include amd, but both the exploit and the bug have only been tested on RedHat 4.1. The Fix: A one-character typo in the linux-specific header file for amd prevents it from actually passing the nodev option to the kernel. --- amd-upl102/config/os-linux.h.bad Mon Apr 7 16:41:51 1997 +++ amd-upl102/config/os-linux.h Mon Apr 7 16:42:19 1997 @@ -252,7 +252,7 @@ #define M_RDONLY 1 /* mount read-only */ #define M_NOSUID 2 /* ignore suid and sgid bits */ -#define M_NONDEV 4 /* disallow access to device special files */ +#define M_NODEV 4 /* disallow access to device special files */ #define M_NOEXEC 8 /* disallow program execution */ #define M_SYNC 16 /* writes are synced at once */ #define M_REMOUNT 32 /* alter flags of a mounted FS */ That''s it. Evidently M_NODEV was defined to something else elsewhere, otherwise amd shouldn''t have compiled. Brad Keryan keryan@andrew.cmu.edu http://fatale.res.cmu.edu/
Jeff Uphoff
1997-Apr-08 06:50 UTC
Re: [linux-security] amd 920824upl102 ignores the nodev option
"BMK" == Bradley M Keryan <keryan@andrew.cmu.edu> writes: BMK> #define M_RDONLY 1 /* mount read-only */ BMK> #define M_NOSUID 2 /* ignore suid and sgid bits */ BMK> -#define M_NONDEV 4 /* disallow access to device special files */ BMK> +#define M_NODEV 4 /* disallow access to device special files */ BMK> #define M_NOEXEC 8 /* disallow program execution */ BMK> #define M_SYNC 16 /* writes are synced at once */ BMK> #define M_REMOUNT 32 /* alter flags of a mounted FS */ BMK> That''s it. Evidently M_NODEV was defined to something else elsewhere, BMK> otherwise amd shouldn''t have compiled. Actually, no. From amd/mount_fs.c: struct opt_tab mnt_flags[] = { { "ro", M_RDONLY }, #ifdef M_CACHE { "nocache", M_NOCACHE }, #endif /* M_CACHE */ #ifdef M_GRPID { "grpid", M_GRPID }, #endif /* M_GRPID */ #ifdef M_MULTI { "multi", M_MULTI }, #endif /* M_MULTI */ #ifdef M_NODEV { "nodev", M_NODEV }, #endif /* M_NODEV */ ... If M_NODEV is not defined then amd appears to just assume that the nodev option isn''t honored. I''ve not parsed all the logic to this yet; there''s also some fun in config/mount_linux.c: #define MS_RDONLY 1 /* mount read-only */ #define MS_NOSUID 2 /* ignore suid and sgid bits */ #define MS_NODEV 4 /* disallow access to device special files */ #define MS_NOEXEC 8 /* disallow program execution */ #define MS_SYNC 16 /* writes are synced at once */ #define MS_REMOUNT 32 /* alter flags of a mounted FS */ struct opt_map { const char *opt; /* option name */ int inv; /* true if flag value should be inverted */ int mask; /* flag mask value */ }; const struct opt_map opt_map[] { { "defaults", 0, 0 }, { "ro", 0, MS_RDONLY }, { "rw", 1, MS_RDONLY }, { "exec", 1, MS_NOEXEC }, { "noexec", 0, MS_NOEXEC }, { "suid", 1, MS_NOSUID }, { "nosuid", 0, MS_NOSUID }, { "dev", 1, MS_NODEV }, { "nodev", 0, MS_NODEV }, { "sync", 0, MS_SYNC }, { "async", 1, MS_SYNC }, #ifdef MS_NOSUB { "sub", 1, MS_NOSUB }, { "nosub", 0, MS_NOSUB }, #endif { NULL, 0, 0 } }; The #defines used above can be found in <linux/fs.h> and those are probably what should be used, vice these local definitions. --Up.
Jeff Uphoff
1997-Apr-08 11:07 UTC
Re: [linux-security] amd 920824upl102 ignores the nodev option
[Note to linux-security moderators: Feel free to forward this posting, possibly together with background information from previous postings, on to linux-alert.] Pending an official fix release from Red Hat, I have built a patched RPM for ''amd'' that honors the "nodev" option correctly. Both the source and binary RPM''s are available, PGP signed by me (for those that consider me "trustworthy"), from: ftp://linux.nrao.edu/pub/linux/packages/SRPMS/amd-920824upl102-6u.src.rpm ftp://linux.nrao.edu/pub/linux/packages/RPMS/i386/amd-920824upl102-6u.i386.rpm These RPM''s were built from the amd-920824upl102-6.src.rpm, as distributed with Red Hat 4.1, on a 2.0.29 system running RH 4.1 (+ all available updates). The only change from the Red Hat distributed version is a patch with the one-liner fix that makes "nodev" work correctly. (I have tested this new ''amd'' binary and it correctly squashes devices when instructed to.) --Up. -- Jeff Uphoff - Scientific Programming Analyst | juphoff@nrao.edu National Radio Astronomy Observatory | juphoff@bofh.org.uk Charlottesville, VA, USA | jeff.uphoff@linux.org PGP key available at: http://www.cv.nrao.edu/~juphoff/