From 8264d2089ad44e449acd258ed61d5b5bdf72c0b4 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Thu, 21 Jul 2022 03:16:15 +0200 Subject: [PATCH] Remove ineffective check for login shell; require -p for suid/sgid In main.c: 158: if(sh.ppid==1) 159: sh.login_sh++; If that was ever valid, it certainly is not now. As far as I know, there is no currently existing system where PID 1 (init or systemd or whatever) is the parent shell of the login shell, even straight after bootup; login shells are invoked via a program like login(1). Plus, there is no guarantee the init process actually has PID 1. This invalidates all use of login_sh that couldn't be replaced by checks for the login_shell option, so this commit does just that. src/cmd/ksh93/include/shell.h: - Remove login_sh flag. src/cmd/ksh93/sh/init.c: - If a login shell was detected, just set the login_shell option. - Remove obsolete check for #! setuid scripts. This was meant to guard against a symlink called '-i' to a setuid script with a hashbang path, which used to give users a root shell. All modern Unixes ignore the setuid bit when they detect a hashbang path. src/cmd/ksh93/SHOPT.sh: - By default, let's require the -p/--privileged invocation option for the setuid/setgid bit on the shell binary to be respected, for all user IDs (>= 0). This is what bash and mksh do, and it seems sensible. (See init.c 1475-1483) --- src/cmd/ksh93/README | 4 ++-- src/cmd/ksh93/SHOPT.sh | 2 +- src/cmd/ksh93/data/msg.c | 1 - src/cmd/ksh93/edit/history.c | 3 +-- src/cmd/ksh93/include/shell.h | 1 - src/cmd/ksh93/sh/fault.c | 2 +- src/cmd/ksh93/sh/init.c | 12 ++---------- src/cmd/ksh93/sh/jobs.c | 2 +- src/cmd/ksh93/sh/main.c | 4 ---- src/cmd/ksh93/sh/xec.c | 1 - 10 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/cmd/ksh93/README b/src/cmd/ksh93/README index 8ac8e10f5..85e153b50 100644 --- a/src/cmd/ksh93/README +++ b/src/cmd/ksh93/README @@ -127,8 +127,8 @@ The options have the following defaults and meanings: OPTIMIZE on Optimize loop invariants for with for and while loops. - P_SUID off If set, all real UIDs, greater than or equal to this - value will require the -p flag to run SUID/SGID scripts. + P_SUID 0 If set, all real UIDs greater than or equal to this value + will require the -p option to run the shell setuid/setgid. RAWONLY on Turn on if the vi line mode doesn't work right unless you do a set -o viraw. diff --git a/src/cmd/ksh93/SHOPT.sh b/src/cmd/ksh93/SHOPT.sh index e0cb0a8b2..b529d1d9b 100644 --- a/src/cmd/ksh93/SHOPT.sh +++ b/src/cmd/ksh93/SHOPT.sh @@ -30,7 +30,7 @@ SHOPT NAMESPACE=1 # allow namespaces SHOPT NOECHOE=0 # turn off 'echo -e' when SHOPT_ECHOPRINT is disabled SHOPT OLDTERMIO= # support both TCGETA and TCGETS SHOPT OPTIMIZE=1 # optimize loop invariants -SHOPT P_SUID= # real UIDs that require -p for set[ug]id (do not set to 0 to turn off) +SHOPT P_SUID=0 # real UIDs >= this value require -p for set[ug]id (to turn off, use empty, not 0) SHOPT RAWONLY=1 # make viraw the only vi mode SHOPT REGRESS= # enable __regress__ builtin and instrumented intercepts for testing SHOPT REMOTE= # enable --rc if running as a remote shell diff --git a/src/cmd/ksh93/data/msg.c b/src/cmd/ksh93/data/msg.c index a308cbba2..ad226e017 100644 --- a/src/cmd/ksh93/data/msg.c +++ b/src/cmd/ksh93/data/msg.c @@ -191,7 +191,6 @@ const char e_suidprofile[] = "/etc/suid_profile"; #if SHOPT_SYSRC const char e_sysrc[] = "/etc/ksh.kshrc"; #endif -const char e_prohibited[] = "login setuid/setgid shells prohibited"; #ifdef BUILD_DTKSH const char e_suidexec[] = SUIDEXECPATH; #else diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c index 3462ce35e..36c710708 100644 --- a/src/cmd/ksh93/edit/history.c +++ b/src/cmd/ksh93/edit/history.c @@ -194,8 +194,7 @@ static void hist_touch(void *handle) /* * open the history file * if HISTNAME is not given and userid==0 then no history file. - * if login_sh and HISTFILE is longer than HIST_MAX bytes then it is - * cleaned up. + * if HISTFILE is longer than HIST_MAX bytes then it is cleaned up. * hist_open() returns 1, if history file is open */ int sh_histinit(void) diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h index bf215ef9b..7f98ab8cb 100644 --- a/src/cmd/ksh93/include/shell.h +++ b/src/cmd/ksh93/include/shell.h @@ -308,7 +308,6 @@ struct Shell_s int savesig; unsigned char *sigflag; /* pointer to signal states */ char intrap; - char login_sh; char forked; char binscript; char funload; diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c index ab2f56d54..16021210e 100644 --- a/src/cmd/ksh93/sh/fault.c +++ b/src/cmd/ksh93/sh/fault.c @@ -675,7 +675,7 @@ noreturn void sh_done(register int sig) tty_cooked(-1); #endif /* SHOPT_VSH || SHOPT_ESH */ #ifdef JOBS - if((sh_isoption(SH_INTERACTIVE) && sh.login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP))) + if((sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_LOGIN_SHELL)) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP))) job_walk(sfstderr, job_hup, SIGHUP, NIL(char**)); #endif /* JOBS */ job_close(); diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c index 227caaa73..d5dbfa37c 100644 --- a/src/cmd/ksh93/sh/init.c +++ b/src/cmd/ksh93/sh/init.c @@ -477,7 +477,7 @@ static void init_radixpoint(void) #endif if(!r && val) { - if(!sh_isstate(SH_INIT) || sh.login_sh==0) + if(!sh_isstate(SH_INIT) || !sh_isoption(SH_LOGIN_SHELL)) errormsg(SH_DICT,0,e_badlocale,val); return; } @@ -1353,7 +1353,7 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) { type = sh_type(*argv); if(type&SH_TYPE_LOGIN) - sh.login_sh = 2; + sh_onoption(SH_LOGIN_SHELL); if(type&SH_TYPE_POSIX) { sh_onoption(SH_POSIX); @@ -1482,14 +1482,6 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) else #endif /* SHOPT_P_SUID */ sh_onoption(SH_PRIVILEGED); -#ifdef SHELLMAGIC - /* careful of #! setuid scripts with name beginning with - */ - if(sh.login_sh && argv[1] && strcmp(argv[0],argv[1])==0) - { - errormsg(SH_DICT,ERROR_exit(1),e_prohibited); - UNREACHABLE(); - } -#endif /*SHELLMAGIC*/ } else sh_offoption(SH_PRIVILEGED); diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c index 4f9a09971..25adeefc7 100644 --- a/src/cmd/ksh93/sh/jobs.c +++ b/src/cmd/ksh93/sh/jobs.c @@ -705,7 +705,7 @@ int job_close(void) errormsg(SH_DICT,0,e_terminate); return(-1); } - else if(running && sh.login_sh) + else if(running && sh_isoption(SH_LOGIN_SHELL)) { errormsg(SH_DICT,0,e_jobsrunning); return(-1); diff --git a/src/cmd/ksh93/sh/main.c b/src/cmd/ksh93/sh/main.c index f944a5fbe..9b0cfbca6 100644 --- a/src/cmd/ksh93/sh/main.c +++ b/src/cmd/ksh93/sh/main.c @@ -155,10 +155,6 @@ int sh_main(int ac, char *av[], Shinit_f userinit) beenhere++; sh_onstate(SH_PROFILE); sh.sigflag[SIGTSTP] |= SH_SIGIGNORE; - if(sh.ppid==1) - sh.login_sh++; - if(sh.login_sh >= 2) - sh_onoption(SH_LOGIN_SHELL); /* decide whether shell is interactive */ if(!sh_isoption(SH_INTERACTIVE) && !sh_isoption(SH_TFLAG) && !sh_isoption(SH_CFLAG) && sh_isoption(SH_SFLAG) && tty_check(0) && tty_check(ERRIO)) diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index 37f138fac..596a237c9 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -2930,7 +2930,6 @@ pid_t _sh_fork(register pid_t parent,int flags,int *jobid) job.jobcontrol = 0; #endif /* JOBS */ job.toclear = 1; - sh.login_sh = 0; sh_offoption(SH_LOGIN_SHELL); sh_onstate(SH_FORKED); #if SHOPT_ACCT