mkdir() and security hole

The Beach Bum jfh at rpp386.Dallas.TX.US
Fri Dec 23 10:54:26 AEST 1988


In article <1313 at vsi1.COM> lmb at vicom.COM (Larry Blair) writes:
>I don't what version of Unix you run, but I don't know of one that would
>do ANY disk I/O for the chown, since the mknod would have brought all of
>the elements into core and, being -255, no one else could have caused the
>kernel to de-cache the inodes and buffers.

This is an unwarranted assumption, as we shall see later ...  If you want
to insure the inode will remain cached [ the inode is the only thing
you can really get a handle on, paths are very slippery as it were ] you
would have to open the directory.  The inode would remain resident so
long as the directory were open.  Or, you could chdir() to the new
directory as current directories are also kept in core.  Simply praying
you have enough inode table entries don't cut it.  Inodes are only kept
resident for open file, current directories, root directories, pure
text files currently under execution or with the sticky bit set, and
mounted on directories.  [ Plus the one or two others I forgot, like the
system accounting file ;-) ]

> I'm also pretty sure that there
>is no danger in this case of losing the CPU due to timeout.  I'm sure that
>some kernel hacker can tell us whether nice(-255) can be preempted.

There is obviously a VERY severe misunderstanding of the function of
nice() under System V.  NICE only makes you a preferred process.  The
actual selection for scheduling is based on your CPU usage, your NICE
value, and your priority.  Your priority is adjusted after event wakeups
and during execution every second or so by the clock interrupt.  Your
milage may vary.

First, some accounting numbers to illustrate the point -

  START: Thu Dec 22 18:19:08 1988
  END:   Thu Dec 22 18:22:06 1988
  COMMAND                      START    END          REAL     CPU    MEAN
  NAME         USER   TTYNAME  TIME     TIME       (SECS)  (SECS) SIZE(K)
  ogetty     root     ?        18:08:38 18:30:35  1317.12    0.62  369.80
  #ogetty    root     ?        18:15:23 18:27:43   740.16    0.70  363.66
  #sh        news     ?        18:10:00 18:26:22   982.40    0.08  699.50
  sh         news     ?        18:10:00 18:26:22   981.92    0.16  530.50
  rnews      news     ?        18:18:33 18:23:52   319.20   69.48 1433.70
  #csh       jfh      tty02    23:27:53 18:23:20 68126.72    4.92  623.34
  csh        jfh      tty01    18:15:45 18:23:17   452.32    1.10  745.59
  #csh       root     tty01    18:16:25 18:23:06   400.80    1.94  637.69
  #mkdir     root     tty01    18:19:08 18:22:06   177.60   82.08  386.98
. lc         jfh      tty02    18:21:54 18:21:57     2.94    1.12 1044.84
. #sh        news     ?        18:20:00 18:20:45    45.12    0.08  529.00
. sh         news     ?        18:20:01 18:20:45    44.28    0.26  446.30
. uux        news     ?        18:20:04 18:20:45    40.96    2.08  769.84
. sh         news     ?        18:20:04 18:20:23    18.72    0.02  727.88
. compress   news     ?        18:20:04 18:20:23    18.58    0.22 6068.36
. batch      news     ?        18:20:04 18:20:13     9.12    0.14  463.14
. sh         news     ?        18:20:10 18:20:12     2.04    0.12  393.83
. expr       news     ?        18:20:03 18:20:04     0.72    0.04  526.00

All of the commands marked with a '.' in the first column began and
ended while mkdir was running.  mkdir was running with a NICE of 0,
which for System V is as low as it gets.  You CAN'T set NICE < 0 under
System V [ maybe SVR3? SVR4??? ].  All of the other commands listed were
loaded and executing [ except maybe the getty's ] at the same time as
mkdir.  However, what is most important to notice is that the REAL TIME
and the CPU TIME for mkdir were not equal.  So long as this is true, a
window exists during which another command can enter the job mix and be
executed.

If you would like to know what arguments I used, try mkdir {A..Z}{A..Z},
that should do the trick [ modulo csh syntax ].  The 'lc' in there
should prove interesting as lc had to execute a filename lookup on the
300 or so directories which existed at the time.  Clearly if lc can
execute 300 stat() calls, some bad guy's program would have little
trouble slipping an unlink()/link() pair in there ...

Oh well, so much for the nice() mythology.  Another UNIX legend down the
tubes.  Now excuse me as I go run off and rmdir all 676 of those
directories I just created ;-(
-- 
John F. Haugh II                        +-Quote of the Week:-------------------
VoiceNet: (214) 250-3311   Data: -6272  |"Unix doesn't have bugs,
InterNet: jfh at rpp386.Dallas.TX.US       | Unix is a bug"
UucpNet : <backbone>!killer!rpp386!jfh  +--              -- author forgotten --



More information about the Comp.bugs.sys5 mailing list