Way to stop /tmp races

From: Pavel Machek (pavelat_private)
Date: Sat Mar 21 1998 - 11:37:10 PST

  • Next message: Ben Laurie: "Re: apache+ssl 1.13 symlink problem"

    Hi!
    
    Maybe I have a way to stop /tmp races, at expense of relatively small
    semantic change. Trick is to modify open() to force O_EXCL if it is
    under /tmp. Code follows, it is pretty short.
    
    Share and enjoy,
    
                                                                    Pavel
    PS: Special question for solar designer:
      You have patch for similar purpose, but it was kernel patch. How did
    you solve:
    
    A: (victim)                     B: (attacker)
                                    > /tmp/file
                                    chmod 666 file
    writes data to /tmp/file
    closes /tmp/file
                                    changes data in /tmp/file
    reads back spoofed data
    
    ? [Sorry if it is stupid question.]
    
    PPS: This is linux-specific, but at least like libc change it can be
    done on any unix I know of.
    
    /*
     * Ok, we'll close some of those nasty /tmp races.
     *
     * Copyright 1998 Pavel Machek <pavelat_private>,
     *                 distribute under General Public License, version 2
     *
     * To use: gcc safetmp.c -shared -o libsafetmp.so
     * then either export LD_PRELOAD=/full_path/libsafetmp.so
     * or if you are root and *DARING*
     *            echo "/full_path/libsafetmp.so" > /etc/ld.so.preload
     *
     * Version 0.0.1. Should work on Linux, should be possible to make it
     *                      work on other systems.
     */
    
    #include <stdarg.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <syslog.h>
    
    int
    open( const char *pathname, int flags, ... )
    {
    int ret;
    const char *s;
    mode_t mode = 0;
    va_list ap;
    va_start( ap, flags );
    
    if (flags & O_CREAT)
      mode = va_arg( ap, mode_t );
    
    s = pathname;
    if (*s == '/') {
      while( *s == '/' )
        s++;
      if ((!strncmp( s, "tmp/", 4)) &&
          ((flags & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC)) &&
          (!(flags & O_EXCL))) {
        syslog( LOG_INFO, "Insecure open: %d tries to open(%s,%d,%d)\n", getpid(), pathname, flags, mode );
        unlink( pathname );
        flags |= O_EXCL;
      }
    }
    
    return __open( pathname, flags, mode );
    
    va_end( ap );
    return ret;
    }
    
    
    
    --
    I'm really pavelat_private         Pavel
    Look at http://atrey.karlin.mff.cuni.cz/~pavel/ ;-).
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:47:00 PDT