Bugtraq mailing list archives

Re: [linux-security] Things NOT to put in root's crontab


From: zblaxell () myrus com (Zygo Blaxell)
Date: Thu, 23 May 1996 18:27:20 -0400


Quoted from Philip Guenther:
The race condition in find should be eliminatible by using fchdir()
and passing the '-exec'ed command a simple filename.  You have to keep
open one descriptor for each level descended which should max out at
MAXPATHLEN/2.  That should be within the bounds of modern UNIX systems.

In pseudocode:

cur = open argv[1];
fchdir(cur);
do_dir(cur);

do_dir(int cur) {
    foreach file in "." {
### vulnerability here ###
        int fd = open file;
### vulnerability here ###
        do_stuff_from_command_line;
        if ISDIR(fstat fd) {
            fchdir(fd);
            do_dir(fd);
            fchdir(cur);
        }
    }
}

Correct, except that it is necessary to check that 'open file' didn't
follow a symlink.  Actually, without this check, this pseudocode is much
worse than current find implementations, because it follows *all*
symlinks to directories, no racing necessary.

Here's something that may be cleaner.  In this pseudocode language, all
system calls throw an exception on failure that exits the current
function.

find {
        int first_dir_fd=opendir(.);
        foreach directory on commandline {
                // not necessary to check stuff we're given
                chdir(directory);
                recursively_process_current_directory;
                fchdir(first_dir_fd);
        }
}
recursively_process_current_directory {
        try {
                foreach file in "." {
                        A=lstat(file);
                        do_stuff_from_command_line;
                        if (ISDIR(A)) {
                                int parentwd_fd=opendir(.);
                                B=lstat(.);             //optional
                                chdir(file);
                                C=lstat(.);
                                D=lstat(..);            //optional
                                if (
                                        A!=C            //mandatory
                                        || B!=D         //optional
                                ) {
                                        print_warning;
                                        return error;
                                }
                                recursively_process_current_directory();
                                fchdir(parentwd_fd);
                        }
                }
        }
}

The parts marked 'optional' above I don't think you really need.

All parameters to 'exec' are relative to the current directory.  To
prevent most Unix commands from getting confused, optionally prepend
'./' to each filename.

--
Zygo Blaxell.  Former Unix/soft/hardware guru, U of Waterloo Computer Science
Club.  Current sysadmin for Myrus Design, Inc.  10th place, ACM Intl Collegiate
Programming Contest Finals, 1994.  Administer Linux nets for food, clothing,
and anime.  "I gave up $1000 to avoid working on windoze... *sigh*" - Amy Fong



Current thread: