diff options
author | Chip Salzenberg <chip@pobox.com> | 1999-04-06 19:32:40 +0000 |
---|---|---|
committer | Todd Rinaldo <toddr@cpanel.net> | 2019-10-19 07:03:08 -0500 |
commit | 8393453d7039ab6d0d3a6abce4de9f9d1532211e (patch) | |
tree | c394b14a1a73400598a89caf35a48c5f1c3dd337 | |
parent | ecd2912d7ea6d6a6d18794059cd75e9fc0c0736f (diff) | |
download | perl-8393453d7039ab6d0d3a6abce4de9f9d1532211e.tar.gz |
Disable setuid execution if 'nosuid' mount option specified.
(Original fix from Jarkko; hand-hackery of Configure by Chip.)
p4raw-id: //depot/maint-5.004/perl@3222
-rwxr-xr-x | Configure | 77 | ||||
-rw-r--r-- | config_h.SH | 49 | ||||
-rw-r--r-- | perl.c | 92 |
3 files changed, 218 insertions, 0 deletions
@@ -408,6 +408,13 @@ d_sockpair='' sockethdr='' socketlib='' d_statblks='' +d_fstatfs='' +d_statfs='' +d_statfsflags='' +d_fstatvfs='' +d_statvfs='' +d_getmntent='' +d_hasmntopt='' d_stdio_cnt_lval='' d_stdio_ptr_lval='' d_stdiobase='' @@ -483,6 +490,7 @@ i_locale='' i_malloc='' i_math='' i_memory='' +i_mntent='' i_ndbm='' i_neterrno='' i_niin='' @@ -507,11 +515,13 @@ i_bsdioctl='' i_sysfilio='' i_sysioctl='' i_syssockio='' +i_sysmount='' i_sysndir='' i_sysparam='' i_sysresrc='' i_sysselct='' i_sysstat='' +i_sysstatvfs='' i_systimes='' i_systypes='' i_sysun='' @@ -6069,6 +6079,23 @@ eval $inlibc set chsize d_chsize eval $inlibc +hasfield='varname=$1; struct=$2; field=$3; shift; shift; shift; +while $test $# -ge 2; do + case "$1" in + $define) echo "#include <$2>";; + esac ; + shift 2; +done > try.c; +echo "int main () { struct $struct foo; foo.$field = 0; }" >> try.c; +if eval $cc $optimize $ccflags -c try.c >/dev/null 2>&1; then + val="$define"; +else + val="$undef"; +fi; +set $varname; +eval $setvar; +$rm -f try.c try.o' + : check for const keyword echo " " echo 'Checking to see if your C compiler knows about "const"...' >&4 @@ -9533,6 +9560,10 @@ eval $inhdr set math.h i_math eval $inhdr +: see if this is a mntent.h system +set mntent.h i_mntent +eval $inhdr + : see if ndbm.h is available set ndbm.h t_ndbm eval $inhdr @@ -9871,6 +9902,38 @@ eval $setvar set sys/param.h i_sysparam eval $inhdr +: see if this is a sys/mount.h system +set sys/mount.h i_sysmount +eval $inhdr + +: see if statfs exists +set statfs d_statfs +eval $inlibc + +: see if fstatfs exists +set fstatfs d_fstatfs +eval $inlibc + +: see if statfs knows about mount flags +set d_statfsflags statfs f_flags $i_sysparam sys/param.h $i_sysmount sys/mount.h +eval $hasfield + +: see if statvfs exists +set statvfs d_statvfs +eval $inlibc + +: see if fstatvfs exists +set fstatvfs d_fstatvfs +eval $inlibc + +: see if getmntent exists +set getmntent d_getmntent +eval $inlibc + +: see if hasmntopt exists +set hasmntopt d_hasmntopt +eval $inlibc + : see if sys/resource.h has to be included set sys/resource.h i_sysresrc eval $inhdr @@ -9883,6 +9946,10 @@ eval $inhdr set sys/types.h i_systypes eval $inhdr +: see if this is a sys/statvfs.h system +set sys/statvfs.h i_sysstatvfs +eval $inhdr + : see if this is a sys/un.h system set sys/un.h i_sysun eval $inhdr @@ -10248,12 +10315,16 @@ d_flock='$d_flock' d_fork='$d_fork' d_fpathconf='$d_fpathconf' d_fsetpos='$d_fsetpos' +d_fstatfs='$d_fstatfs' +d_fstatvfs='$d_fstatvfs' d_ftime='$d_ftime' d_getgrps='$d_getgrps' d_setgrps='$d_setgrps' d_gethent='$d_gethent' d_gethname='$d_gethname' d_getlogin='$d_getlogin' +d_getmntent='$d_getmntent' +d_hasmntopt='$d_hasmntopt' d_getpgid='$d_getpgid' d_getpgrp2='$d_getpgrp2' d_getpgrp='$d_getpgrp' @@ -10347,6 +10418,9 @@ d_sigsetjmp='$d_sigsetjmp' d_socket='$d_socket' d_sockpair='$d_sockpair' d_statblks='$d_statblks' +d_statfs='$d_statfs' +d_statfsflags='$d_statfsflags' +d_statvfs='$d_statvfs' d_stdio_cnt_lval='$d_stdio_cnt_lval' d_stdio_ptr_lval='$d_stdio_ptr_lval' d_stdiobase='$d_stdiobase' @@ -10438,6 +10512,7 @@ i_locale='$i_locale' i_malloc='$i_malloc' i_math='$i_math' i_memory='$i_memory' +i_mntent='$i_mntent' i_ndbm='$i_ndbm' i_neterrno='$i_neterrno' i_niin='$i_niin' @@ -10454,12 +10529,14 @@ i_sysfile='$i_sysfile' i_sysfilio='$i_sysfilio' i_sysin='$i_sysin' i_sysioctl='$i_sysioctl' +i_sysmount='$i_sysmount' i_sysndir='$i_sysndir' i_sysparam='$i_sysparam' i_sysresrc='$i_sysresrc' i_sysselct='$i_sysselct' i_syssockio='$i_syssockio' i_sysstat='$i_sysstat' +i_sysstatvfs='$i_sysstatvfs' i_systime='$i_systime' i_systimek='$i_systimek' i_systimes='$i_systimes' diff --git a/config_h.SH b/config_h.SH index f8963a9638..c2486f638e 100644 --- a/config_h.SH +++ b/config_h.SH @@ -1260,6 +1260,24 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un- */ #$i_systypes I_SYS_TYPES /**/ +/* I_MNTENT: + * This symbol, if defined, indicates that <mntent.h> exists and + * should be included. + */ +#$i_mntent I_MNTENT /**/ + +/* I_SYS_MOUNT: + * This symbol, if defined, indicates that <sys/mount.h> exists and + * should be included. + */ +#$i_sysmount I_SYS_MOUNT /**/ + +/* I_SYS_STATVFS: + * This symbol, if defined, indicates that <sys/statvfs.h> exists and + * should be included. + */ +#$i_sysstatvfs I_SYS_STATVFS /**/ + /* I_SYS_UN: * This symbol, if defined, indicates to the C program that it should * include <sys/un.h> to get UNIX domain socket definitions. @@ -1623,6 +1641,37 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un- */ #$d_sfio USE_SFIO /**/ +/* HAS_FSTATFS: + * This symbol, if defined, indicates that the fstatfs routine is + * available to do stat filesystems of file descriptors. + */ +/* HAS_STRUCT_STATFS_FLAGS: + * This symbol, if defined, indicates that the struct statfs + * does have the f_flags member containing the mount flags of + * the filesystem holding the file. + * This kind of struct statfs is coming from sys/mount.h (BSD) + * and not from sys/statfs.h (SYSV). + */ +#$d_fstatfs HAS_FSTATFS /**/ +#$d_statfsflags HAS_STRUCT_STATFS_FLAGS /**/ + +/* HAS_FSTATVFS: + * This symbol, if defined, indicates that the fstatvfs routine is + * available to do stat filesystems of file descriptors. + */ +#$d_fstatvfs HAS_FSTATVFS /**/ + +/* HAS_GETMNTENT: + * This symbol, if defined, indicates that the getmntent routine is + * available to enumerate mounted filesystems. + */ +/* HAS_HASMNTOPT: + * This symbol, if defined, indicates that the hasmntopt routine is + * available to check options on mounted filesystems. + */ +#$d_getmntent HAS_GETMNTENT /**/ +#$d_hasmntopt HAS_HASMNTOPT /**/ + /* Sigjmp_buf: * This is the buffer type to be used with Sigsetjmp and Siglongjmp. */ @@ -20,6 +20,20 @@ #include <unistd.h> #endif +#ifdef IAMSUID + +#ifdef I_SYS_STATVFS +# include <sys/statvfs.h> /* for f?statvfs() */ +#endif +#ifdef I_SYS_MOUNT +# include <sys/mount.h> /* for *BSD f?statfs() */ +#endif +#ifdef I_MNTENT +# include <mntent.h> /* for getmntent() */ +#endif + +#endif /* IAMSUID */ + #if !defined(STANDARD_C) && !defined(HAS_GETENV_PROTOTYPE) char *getenv _((char *)); /* Usually in <stdlib.h> */ #endif @@ -79,6 +93,9 @@ static void open_script _((char *, bool, SV *)); static void perldoc_ref _((void)); static void usage _((char *)); static void validate_suid _((char *, char*)); +#ifdef IAMSUID +static int fd_on_nosuid_fs _((int)); +#endif static I32 read_e_script _((int idx, SV *buf_sv, int maxlen)); static int fdscript = -1; @@ -1889,6 +1906,10 @@ char *scriptname; croak("Can't swap uid and euid"); /* really paranoid */ if (Stat(SvPVX(GvSV(curcop->cop_filegv)),&tmpstatbuf) < 0) croak("Permission denied"); /* testing full pathname here */ +#if defined(IAMSUID) && !defined(NO_NOSUID_CHECK) + if (fd_on_nosuid_fs(PerlIO_fileno(rsfp))) + croak("Permission denied"); +#endif #if defined(IAMSUID) && defined(__NetBSD__) /* XXX Other BSD 4.4-derived BSDs? FreeBSD, OpenBSD, BSDI, MachTen? */ @@ -2688,3 +2709,74 @@ my_exit_jump() JMPENV_JUMP(2); } + +#ifdef IAMSUID +static int +fd_on_nosuid_fs(int fd) +{ + int on_nosuid = 0; + int check_okay = 0; +/* + * Preferred order: fstatvfs(), fstatfs(), getmntent(). + * fstatvfs() is UNIX98. + * fstatfs() is BSD. + * getmntent() is O(number-of-mounted-filesystems) and can hang. + */ + +# ifdef HAS_FSTATVFS + struct statvfs stfs; + check_okay = fstatvfs(fd, &stfs) == 0; + on_nosuid = check_okay && (stfs.f_flag & ST_NOSUID); +# else +# if defined(HAS_FSTATFS) && defined(HAS_STRUCT_STATFS_FLAGS) + struct statfs stfs; + check_okay = fstatfs(fd, &stfs) == 0; +# undef PERL_MOUNT_NOSUID +# if !defined(PERL_MOUNT_NOSUID) && defined(MNT_NOSUID) +# define PERL_MOUNT_NOSUID MNT_NOSUID +# endif +# if !defined(PERL_MOUNT_NOSUID) && defined(MS_NOSUID) +# define PERL_MOUNT_NOSUID MS_NOSUID +# endif +# if !defined(PERL_MOUNT_NOSUID) && defined(M_NOSUID) +# define PERL_MOUNT_NOSUID M_NOSUID +# endif +# ifdef PERL_MOUNT_NOSUID + on_nosuid = check_okay && (stfs.f_flags & PERL_MOUNT_NOSUID); +# endif +# else +# if defined(HAS_GETMNTENT) && defined(HAS_HASMNTOPT) && defined(MNTOPT_NOSUID) + + /* perlsdio.h might have disabled these */ +# undef fopen +# undef fclose + + void *mtab = fopen("/etc/mtab", "r"); + struct mntent *entry; + struct stat stb, fsb; + + if (mtab && (fstat(fd, &stb) == 0)) { + while (entry = getmntent(mtab)) { + if (stat(entry->mnt_dir, &fsb) == 0 + && fsb.st_dev == stb.st_dev) + { + /* found the filesystem */ + check_okay = 1; + if (hasmntopt(entry, MNTOPT_NOSUID)) + on_nosuid = 1; + break; + } /* A single fs may well fail its stat(). */ + } + } + if (mtab) + fclose(mtab); + +# endif /* mntent */ +# endif /* statfs */ +# endif /* statvfs */ + + if (!check_okay) + croak("Can't check filesystem of script \"%s\"", origfilename); + return on_nosuid; +} +#endif /* IAMSUID */ |