--- src/cmd/ksh93/data/msg.c +++ src/cmd/ksh93/data/msg.c 2007-04-02 14:59:19.000000000 +0000 @@ -205,7 +205,11 @@ const char e_bash_profile[] = "$HOME/.ba const char e_crondir[] = "/var/spool/cron"; const char e_prohibited[] = "login setuid/setgid shells prohibited"; #if SHOPT_SUID_EXEC +# ifdef THISPROG + const char e_suidexec[] = THISPROG; +# else const char e_suidexec[] = "/etc/suid_exec"; +# endif #endif /* SHOPT_SUID_EXEC */ const char hist_fname[] = "/.sh_history"; const char e_dot[] = "."; --- src/cmd/ksh93/sh/suid_exec.c +++ src/cmd/ksh93/sh/suid_exec.c 2012-02-03 08:36:40.000000000 +0000 @@ -62,10 +62,24 @@ #define FDVERIFY 12 /* used to validate /tmp process */ #undef BLKSIZE #define BLKSIZE sizeof(char*)*1024 -#define THISPROG "/etc/suid_exec" -#define DEFSHELL "/bin/sh" +#ifndef THISPROG +# define THISPROG "/etc/suid_exec" +#endif +#ifndef DEFSHELL +# define DEFSHELL "/bin/sh" +#endif +#if defined(__linux__) +static void error_exit(const char*) __attribute__ ((noreturn)); +#ifndef _lib_setregid +#define _lib_setregid 1 +#endif +#ifndef _lib_setreuid +#define _lib_setreuid 1 +#endif +#else static void error_exit(const char*); +#endif static int in_dir(const char*, const char*); static int endsh(const char*); #ifndef _lib_setregid @@ -76,7 +90,7 @@ static int endsh(const char*); static int mycopy(int, int); static void maketemp(char*); #else - static void setids(int,int,int); + static void setids(int,uid_t,gid_t); #endif /* _lib_setreuid */ static const char version[] = "\n@(#)$Id: suid_exec "SH_RELEASE" $\n"; @@ -221,7 +235,7 @@ int main(int argc,char *argv[]) if(effuid != ruserid) mode |= S_ISUID; } - else if(effuid) + else if(effuid != euserid) { if(effuid != ruserid || setuid(ruserid) < 0) mode = S_ISUID; @@ -233,13 +247,18 @@ int main(int argc,char *argv[]) exec: #endif /* _lib_setreuid */ /* only use SHELL if file is in trusted directory and ends in sh */ +#ifndef __linux__ shell = getenv("SHELL"); if(shell == 0 || !endsh(shell) || ( !in_dir("/bin",shell) && !in_dir("/usr/bin",shell) && - !in_dir("/usr/lbin",shell) && !in_dir("/usr/local/bin",shell))) shell = DEFSHELL; +#else + shell = DEFSHELL; + if(!endsh(shell)) + error_exit(badexec); +#endif argv[0] = command; argv[1] = (char*)devfd; execv(shell,argv); @@ -249,7 +268,7 @@ exec: /* * return true of shell ends in sh of ksh */ - +#ifndef __linux__ static int endsh(register const char *shell) { while(*shell) @@ -262,7 +281,20 @@ static int endsh(register const char *sh return(1); return(0); } - +#else +static int endsh(const char *shell) +{ + char * shx; + while ((shx = getusershell())) { + if (strcmp(shx, shell) == 0) { + endusershell(); + return(1); + } + } + endusershell(); + return(0); +} +#endif /* * return true of shell is in directory @@ -341,16 +373,30 @@ int eaccess(register const char *name, r } #ifdef _lib_setreuid -static void setids(int mode,int owner,int group) +#include +#include +#include +static void setids(int mode,uid_t owner,gid_t group) { - if(mode & S_ISGID) - setregid(rgroupid,group); + if(mode & S_ISGID) { + struct passwd *pwd; + + if (setregid(rgroupid,group)) + error_exit(badexec); + + if (((pwd = getpwuid(owner)) == (struct passwd*)0) || !(pwd->pw_name)) + error_exit(badexec); + + if (initgroups (pwd->pw_name, group)) + error_exit(badexec); + } /* set effective uid even if S_ISUID is not set. This is because * we are *really* executing EUID root at this point. Even if S_ISUID * is not set, the value for owner that is passsed should be correct. */ - setreuid(ruserid,owner); + if (setreuid(ruserid,owner)) + error_exit(badexec); } #else