(linenum→info "unix/slp.c:2238")

glibc/2.7/csu/check_fds.c

    1: /* Copyright (C) 2000, 2002, 2003, 2005 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3: 
    4:    The GNU C Library is free software; you can redistribute it and/or
    5:    modify it under the terms of the GNU Lesser General Public
    6:    License as published by the Free Software Foundation; either
    7:    version 2.1 of the License, or (at your option) any later version.
    8: 
    9:    The GNU C Library is distributed in the hope that it will be useful,
   10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12:    Lesser General Public License for more details.
   13: 
   14:    You should have received a copy of the GNU Lesser General Public
   15:    License along with the GNU C Library; if not, write to the Free
   16:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   17:    02111-1307 USA.  */
   18: 
   19: #include <errno.h>
   20: #include <fcntl.h>
   21: #include <paths.h>
   22: #include <unistd.h>
   23: #include <sys/stat.h>
   24: #include <sys/sysmacros.h>
   25: 
   26: /* Try to get a machine dependent instruction which will make the
   27:    program crash.  This is used in case everything else fails.  */
   28: #include <abort-instr.h>
   29: #ifndef ABORT_INSTRUCTION
   30: /* No such instruction is available.  */
   31: # define ABORT_INSTRUCTION
   32: #endif
   33: 
   34: #include <device-nrs.h>
   35: #include <not-cancel.h>
   36: 
   37: 
   38: /* Should other OSes (e.g., Hurd) have different versions which can
   39:    be written in a better way?  */
   40: static void
   41: check_one_fd (int fd, int mode)
   42: {
   43:   /* Note that fcntl() with this parameter is not a cancellation point.  */
   44:   if (__builtin_expect (__libc_fcntl (fd, F_GETFD), 0) == -1
   45:       && errno == EBADF)
   46:     {
   47:       const char *name;
   48:       dev_t dev;
   49: 
   50:       /* For writable descriptors we use /dev/full.  */
   51:       if ((mode & O_ACCMODE) == O_WRONLY)
   52:         {
   53:           name = _PATH_DEV "full";
   54:           dev = makedev (DEV_FULL_MAJOR, DEV_FULL_MINOR);
   55:         }
   56:       else
   57:         {
   58:           name = _PATH_DEVNULL;
   59:           dev = makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR);
   60:         }
   61: 
   62:       /* Something is wrong with this descriptor, it's probably not
   63:          opened.  Open /dev/null so that the SUID program we are
   64:          about to start does not accidently use this descriptor.  */
   65:       int nullfd = open_not_cancel (name, mode, 0);
   66: 
   67:       /* We are very paranoid here.  With all means we try to ensure
   68:          that we are actually opening the /dev/null device and nothing
   69:          else.
   70: 
   71:          Note that the following code assumes that STDIN_FILENO,
   72:          STDOUT_FILENO, STDERR_FILENO are the three lowest file
   73:          decsriptor numbers, in this order.  */
   74:       struct stat64 st;
   75:       if (__builtin_expect (nullfd != fd, 0)
   76:           || __builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) != 0
   77:           || __builtin_expect (S_ISCHR (st.st_mode), 1) == 0
   78:           || st.st_rdev != dev)
   79:         /* We cannot even give an error message here since it would
   80:            run into the same problems.  */
   81:         while (1)
   82:           /* Try for ever and ever.  */
   83:           ABORT_INSTRUCTION;
   84:     }
   85: }
   86: 
   87: 
   88: void
   89: __libc_check_standard_fds (void)
   90: {
   91:   /* This is really paranoid but some people actually are.  If /dev/null
   92:      should happen to be a symlink to somewhere else and not the device
   93:      commonly known as "/dev/null" we bail out.  We can detect this with
   94:      the O_NOFOLLOW flag for open() but only on some system.  */
   95: #ifndef O_NOFOLLOW
   96: # define O_NOFOLLOW     0
   97: #endif
   98:   /* Check all three standard file descriptors.  */
   99:   check_one_fd (STDIN_FILENO, O_WRONLY | O_NOFOLLOW);
  100:   check_one_fd (STDOUT_FILENO, O_RDONLY | O_NOFOLLOW);
  101:   check_one_fd (STDERR_FILENO, O_RDONLY | O_NOFOLLOW);
  102: }
Syntax (Markdown)