call setsid() when called with -c

Prevents command injection via TIOCSTI

https://bugzilla.redhat.com/show_bug.cgi?id=173008
This commit is contained in:
Tim Waugh 2011-06-10 14:13:59 +02:00 committed by Ludwig Nussel
parent a6fdd3f812
commit c6a1746b5f
1 changed files with 35 additions and 5 deletions

View File

@ -157,6 +157,9 @@ static bool simulate_login;
/* If true, change some environment vars to indicate the user su'd to. */ /* If true, change some environment vars to indicate the user su'd to. */
static bool change_environment; static bool change_environment;
/* If true, then don't call setsid() with a command. */
int same_session = 0;
#ifdef USE_PAM #ifdef USE_PAM
static bool _pam_session_opened; static bool _pam_session_opened;
static bool _pam_cred_established; static bool _pam_cred_established;
@ -165,6 +168,7 @@ static bool _pam_cred_established;
static struct option const longopts[] = static struct option const longopts[] =
{ {
{"command", required_argument, NULL, 'c'}, {"command", required_argument, NULL, 'c'},
{"session-command", required_argument, NULL, 'C'},
{"fast", no_argument, NULL, 'f'}, {"fast", no_argument, NULL, 'f'},
{"login", no_argument, NULL, 'l'}, {"login", no_argument, NULL, 'l'},
{"preserve-environment", no_argument, NULL, 'p'}, {"preserve-environment", no_argument, NULL, 'p'},
@ -339,10 +343,23 @@ create_watching_parent (void)
sigemptyset (&action.sa_mask); sigemptyset (&action.sa_mask);
action.sa_flags = 0; action.sa_flags = 0;
sigemptyset (&ourset); sigemptyset (&ourset);
if (sigaddset (&ourset, SIGTERM) if (!same_session)
|| sigaddset (&ourset, SIGALRM) {
|| sigaction (SIGTERM, &action, NULL) if (sigaddset(&ourset, SIGINT) || sigaddset(&ourset, SIGQUIT))
|| sigprocmask (SIG_UNBLOCK, &ourset, NULL)) {
error (0, errno, _("cannot set signal handler"));
caught_signal = true;
}
}
if (!caught_signal && (sigaddset(&ourset, SIGTERM)
|| sigaddset(&ourset, SIGALRM)
|| sigaction(SIGTERM, &action, NULL)
|| sigprocmask(SIG_UNBLOCK, &ourset, NULL))) {
error (0, errno, _("cannot set signal handler"));
caught_signal = true;
}
if (!caught_signal && !same_session && (sigaction(SIGINT, &action, NULL)
|| sigaction(SIGQUIT, &action, NULL)))
{ {
error (0, errno, _("cannot set signal handler")); error (0, errno, _("cannot set signal handler"));
caught_signal = true; caught_signal = true;
@ -764,6 +781,8 @@ Change the effective user id and group id to that of USER.\n\
\n\ \n\
-, -l, --login make the shell a login shell\n\ -, -l, --login make the shell a login shell\n\
-c, --command=COMMAND pass a single COMMAND to the shell with -c\n\ -c, --command=COMMAND pass a single COMMAND to the shell with -c\n\
--session-command=COMMAND pass a single COMMAND to the shell with -c\n\
and do not create a new session\n\
-f, --fast pass -f to the shell (for csh or tcsh)\n\ -f, --fast pass -f to the shell (for csh or tcsh)\n\
-m, --preserve-environment do not reset environment variables\n\ -m, --preserve-environment do not reset environment variables\n\
-p same as -m\n\ -p same as -m\n\
@ -786,6 +805,7 @@ main (int argc, char **argv)
int optc; int optc;
const char *new_user = DEFAULT_USER; const char *new_user = DEFAULT_USER;
char *command = NULL; char *command = NULL;
int request_same_session = 0;
char *shell = NULL; char *shell = NULL;
struct passwd *pw; struct passwd *pw;
struct passwd pw_copy; struct passwd pw_copy;
@ -811,6 +831,11 @@ main (int argc, char **argv)
command = optarg; command = optarg;
break; break;
case 'C':
command = optarg;
request_same_session = 1;
break;
case 'f': case 'f':
fast_startup = true; fast_startup = true;
break; break;
@ -881,6 +906,9 @@ main (int argc, char **argv)
} }
#endif #endif
if (request_same_session || !command || !pw->pw_uid)
same_session = 1;
if (!shell && !change_environment) if (!shell && !change_environment)
shell = getenv ("SHELL"); shell = getenv ("SHELL");
if (shell && getuid () != 0 && restricted_shell (pw->pw_shell)) if (shell && getuid () != 0 && restricted_shell (pw->pw_shell))
@ -902,6 +930,8 @@ main (int argc, char **argv)
#endif #endif
change_identity (pw); change_identity (pw);
if (!same_session)
setsid ();
/* Set environment after pam_open_session, which may put KRB5CCNAME /* Set environment after pam_open_session, which may put KRB5CCNAME
into the pam_env, etc. */ into the pam_env, etc. */