2.22.1-3: enable su(1) and runuser(1)

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2012-11-01 15:09:04 +01:00
parent 2adc0e74a6
commit 7443d56081
15 changed files with 2847 additions and 2 deletions

View File

@ -0,0 +1,203 @@
From 6273784aa4f40121b3963b41df0986044eeaced0 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Tue, 28 Aug 2012 16:32:28 +0200
Subject: [PATCH 200/208] su: add --group and --supp-group options
These options allow to specify alternative groups. The command
su(1) has to be executed by root. The implementation is based on
Fedora runuser(1) command.
For example:
# su --group=kzak --supp-group=uuidd -
# id
uid=0(root) gid=1000(kzak) groups=0(root),985(uuidd),1000(kzak)
non-root user:
$ su --group=kzak -
su: only root can specify alternative groups
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/su.1 | 6 +++++
login-utils/su.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 75 insertions(+), 4 deletions(-)
diff --git a/login-utils/su.1 b/login-utils/su.1
index 598cebd..59e1731 100644
--- a/login-utils/su.1
+++ b/login-utils/su.1
@@ -59,6 +59,12 @@ Pass
to the shell which may or may not be useful depending on the
shell.
.TP
+\fB\-g\fR, \fB\-\-group\fR=\fIgroup\fR\fR
+specify the primary group, this option is allowed for root user only
+.TP
+\fB\-G\fR, \fB\-\-supp-group\fR=\fIgroup\fR\fR
+specify a supplemental group, this option is allowed for root user only
+.TP
\fB\-\fR, \fB\-l\fR, \fB\-\-login\fR
Starts the shell as login shell with an environment similar to a real
login:
diff --git a/login-utils/su.c b/login-utils/su.c
index c6b8bce..f11c757 100644
--- a/login-utils/su.c
+++ b/login-utils/su.c
@@ -110,6 +110,8 @@ static struct option const longopts[] =
{"login", no_argument, NULL, 'l'},
{"preserve-environment", no_argument, NULL, 'p'},
{"shell", required_argument, NULL, 's'},
+ {"group", required_argument, NULL, 'g'},
+ {"supp-group", required_argument, NULL, 'G'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{NULL, 0, NULL, 0}
@@ -424,11 +426,18 @@ modify_environment (const struct passwd *pw, const char *shell)
/* Become the user and group(s) specified by PW. */
static void
-init_groups (const struct passwd *pw)
+init_groups (const struct passwd *pw, gid_t *groups, int num_groups)
{
int retval;
+
errno = 0;
- if (initgroups (pw->pw_name, pw->pw_gid) == -1)
+
+ if (num_groups)
+ retval = setgroups (num_groups, groups);
+ else
+ retval = initgroups (pw->pw_name, pw->pw_gid);
+
+ if (retval == -1)
{
cleanup_pam (PAM_ABORT);
err (EXIT_FAILURE, _("cannot set groups"));
@@ -535,6 +544,8 @@ usage (int status)
-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\
+ -g --group=group specify the primary group\n\
+ -G --supp-group=group specify a supplemental group\n\
-f, --fast pass -f to the shell (for csh or tcsh)\n\
-m, --preserve-environment do not reset environment variables\n\
-p same as -m\n\
@@ -556,6 +567,19 @@ void load_config(void)
logindefs_load_file(_PATH_LOGINDEFS);
}
+/*
+ * Returns 1 if the current user is not root
+ */
+static int
+evaluate_uid(void)
+{
+ uid_t ruid = getuid();
+ uid_t euid = geteuid();
+
+ /* if we're really root and aren't running setuid */
+ return (uid_t) 0 == ruid && ruid == euid ? 0 : 1;
+}
+
int
main (int argc, char **argv)
{
@@ -566,6 +590,11 @@ main (int argc, char **argv)
char *shell = NULL;
struct passwd *pw;
struct passwd pw_copy;
+ struct group *gr;
+ gid_t groups[NGROUPS_MAX];
+ int num_supp_groups = 0;
+ int use_gid = 0;
+ int restricted;
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
@@ -575,7 +604,7 @@ main (int argc, char **argv)
simulate_login = false;
change_environment = true;
- while ((optc = getopt_long (argc, argv, "c:flmps:hV", longopts, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "c:fg:G:lmps:hV", longopts, NULL)) != -1)
{
switch (optc)
{
@@ -592,6 +621,26 @@ main (int argc, char **argv)
fast_startup = true;
break;
+ case 'g':
+ gr = getgrnam(optarg);
+ if (!gr)
+ errx(EXIT_FAILURE, _("group %s does not exist"), optarg);
+ use_gid = 1;
+ groups[0] = gr->gr_gid;
+ break;
+
+ case 'G':
+ num_supp_groups++;
+ if (num_supp_groups >= NGROUPS_MAX)
+ errx(EXIT_FAILURE,
+ _("can't specify more than %d supplemental groups"),
+ NGROUPS_MAX - 1);
+ gr = getgrnam(optarg);
+ if (!gr)
+ errx(EXIT_FAILURE, _("group %s does not exist"), optarg);
+ groups[num_supp_groups] = gr->gr_gid;
+ break;
+
case 'l':
simulate_login = true;
break;
@@ -617,6 +666,8 @@ main (int argc, char **argv)
}
}
+ restricted = evaluate_uid ();
+
if (optind < argc && !strcmp (argv[optind], "-"))
{
simulate_login = true;
@@ -625,6 +676,9 @@ main (int argc, char **argv)
if (optind < argc)
new_user = argv[optind++];
+ if ((num_supp_groups || use_gid) && restricted)
+ errx(EXIT_FAILURE, _("only root can specify alternative groups"));
+
logindefs_load_defaults = load_config;
pw = getpwnam (new_user);
@@ -648,6 +702,17 @@ main (int argc, char **argv)
: DEFAULT_SHELL);
endpwent ();
+ if (num_supp_groups && !use_gid)
+ {
+ pw->pw_gid = groups[1];
+ memmove (groups, groups + 1, sizeof(gid_t) * num_supp_groups);
+ }
+ else if (use_gid)
+ {
+ pw->pw_gid = groups[0];
+ num_supp_groups++;
+ }
+
authenticate (pw);
if (request_same_session || !command || !pw->pw_uid)
@@ -666,7 +731,7 @@ main (int argc, char **argv)
}
shell = xstrdup (shell ? shell : pw->pw_shell);
- init_groups (pw);
+ init_groups (pw, groups, num_supp_groups);
create_watching_parent ();
/* Now we're in the child. */
--
1.7.11.7

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,450 @@
From d8c2f623ab9d9e7da1490244cb8c77c3017545dc Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 29 Aug 2012 17:34:26 +0200
Subject: [PATCH 202/208] runuser: new command (derived from su(1))
This command is based on su(1), the differences:
- based on Fedora runuser su(1) patch
- not installed with suid rights
- allowed for root users only
- don't ask for password
- uses PAM session, for example:
$ cat /etc/pam.d/runuser
auth sufficient pam_rootok.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session required pam_unix.so
$ cat /etc/pam.d/runuser-l
auth include runuser
session optional pam_keyinit.so force revoke
session include runuser
Signed-off-by: Karel Zak <kzak@redhat.com>
---
.gitignore | 1 +
configure.ac | 9 ++
login-utils/Makemodule.am | 13 +++
login-utils/runuser.1 | 230 ++++++++++++++++++++++++++++++++++++++++++++++
login-utils/runuser.c | 7 ++
login-utils/su-common.c | 51 ++++++++--
6 files changed, 303 insertions(+), 8 deletions(-)
create mode 100644 login-utils/runuser.1
create mode 100644 login-utils/runuser.c
#diff --git a/.gitignore b/.gitignore
#index fbc5636..5be008f 100644
#--- a/.gitignore
#+++ b/.gitignore
#@@ -138,6 +138,7 @@ tests/run.sh.trs
# /resizepart
# /rev
# /rtcwake
#+/runuser
# /sample-mkfs
# /sample-partitions
# /sample-superblocks
diff --git a/configure.ac b/configure.ac
index 87e85fa..83ef6ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1149,6 +1149,15 @@ UL_REQUIRES_HAVE([su], [security_pam_misc_h], [PAM header file])
AM_CONDITIONAL(BUILD_SU, test "x$build_su" = xyes)
+AC_ARG_ENABLE([runuser],
+ AS_HELP_STRING([--disable-runuser], [do not build runuser]),
+ [], enable_runuser=yes
+)
+UL_BUILD_INIT([runuser])
+UL_REQUIRES_HAVE([runuser], [security_pam_misc_h], [PAM header file])
+AM_CONDITIONAL(BUILD_RUNUSER, test "x$build_runuser" = xyes)
+
+
AC_ARG_ENABLE([schedutils],
AS_HELP_STRING([--disable-schedutils], [do not build chrt, ionice, teskset]),
[], enable_schedutils=yes
diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
index b918f00..e26d9a7 100644
--- a/login-utils/Makemodule.am
+++ b/login-utils/Makemodule.am
@@ -93,6 +93,19 @@ su_LDADD = $(LDADD) -lpam -lpam_misc
endif
+if BUILD_RUNUSER
+bin_PROGRAMS += runuser
+dist_man_MANS += login-utils/runuser.1
+runuser_SOURCES = \
+ login-utils/runuser.c \
+ login-utils/su-common.c \
+ login-utils/su-common.h \
+ login-utils/logindefs.c \
+ login-utils/logindefs.h
+runuser_LDADD = $(LDADD) -lpam -lpam_misc
+endif
+
+
if BUILD_NEWGRP
usrbin_exec_PROGRAMS += newgrp
dist_man_MANS += login-utils/newgrp.1
diff --git a/login-utils/runuser.1 b/login-utils/runuser.1
new file mode 100644
index 0000000..66ad1c4
--- /dev/null
+++ b/login-utils/runuser.1
@@ -0,0 +1,230 @@
+.TH RUNUSER "1" "August 2012" "util-linux" "User Commands"
+.SH NAME
+runuser \- run a command with substitute user and group ID
+.SH SYNOPSIS
+.B runuser
+[options...] [\-] [user [args...]]
+.SH DESCRIPTION
+.B runuser
+allows to run commands with substitute user and group ID.
+The difference between the commands
+.B runuser
+and
+.B su
+is that
+.B runuser
+does not ask for password, because it may be executed by root user only.
+The command
+.B runuser
+does not have to be installed with suid permissions.
+.PP
+When called without arguments
+.B runuser
+defaults to running an interactive shell as
+.IR root .
+.PP
+For backward compatibility
+.B runuser
+defaults to not change the current directory and to only set the
+environment variables
+.B HOME
+and
+.B SHELL
+(plus
+.B USER
+and
+.B LOGNAME
+if the target
+.I user
+is not root). It is recommended to always use the
+.B \-\-login
+option (instead it's shortcut
+.BR \- )
+to avoid side effects caused by mixing environments.
+.PP
+This version of
+.B runuser
+uses PAM for session management.
+.SH OPTIONS
+.TP
+\fB\-c\fR \fIcommand\fR, \fB\-\-command\fR=\fIcommand\fR
+Pass
+.I command
+to the shell with the
+.B \-c
+option.
+.TP
+\fB\-\-session\-command\fR=\fIcommand\fR
+Same as
+.B \-c
+but do not create a new session (discouraged).
+.TP
+\fB\-f\fR, \fB\-\-fast\fR
+Pass
+.B \-f
+to the shell which may or may not be useful depending on the
+shell.
+.TP
+\fB\-g\fR, \fB\-\-group\fR=\fIgroup\fR\fR
+specify the primary group, this option is allowed for root user only
+.TP
+\fB\-G\fR, \fB\-\-supp-group\fR=\fIgroup\fR\fR
+specify a supplemental group, this option is allowed for root user only
+.TP
+\fB\-\fR, \fB\-l\fR, \fB\-\-login\fR
+Starts the shell as login shell with an environment similar to a real
+login:
+.RS 10
+.TP
+o
+clears all environment variables except for
+.B TERM
+.TP
+o
+initializes the environment variables
+.BR HOME ,
+.BR SHELL ,
+.BR USER ,
+.BR LOGNAME ,
+.B PATH
+.TP
+o
+changes to the target user's home directory
+.TP
+o
+sets argv[0] of the shell to
+.RB ' \- '
+in order to make the shell a login shell
+.RE
+.TP
+\fB\-m\fR, \fB\-p\fR, \fB\-\-preserve-environment\fR
+Preserves the whole environment, ie does not set
+.BR HOME ,
+.BR SHELL ,
+.B USER
+nor
+.BR LOGNAME .
+.TP
+\fB\-s\fR \fISHELL\fR, \fB\-\-shell\fR=\fISHELL\fR
+Runs the specified shell instead of the default. The shell to run is
+selected according to the following rules in order:
+.RS 10
+.TP
+o
+the shell specified with
+.B \-\-shell
+.TP
+o
+The shell specified in the environment variable
+.B SHELL
+if the
+.B \-\-preserve-environment
+option is used.
+.TP
+o
+the shell listed in the passwd entry of the target user
+.TP
+o
+/bin/sh
+.RE
+.IP
+If the target user has a restricted shell (i.e. not listed in
+/etc/shells) the
+.B \-\-shell
+option and the
+.B SHELL
+environment variables are ignored unless the calling user is root.
+.TP
+\fB\-\-help\fR
+Display help text and exit.
+.TP
+\fB\-\-version\fR
+Display version information and exit.
+.SH CONFIG FILES
+.B runuser
+reads the
+.I /etc/default/runuser
+and
+.I /etc/login.defs
+configuration files. The following configuration items are relevant
+for
+.BR runuser :
+.PP
+.B ENV_PATH
+(string)
+.RS 4
+Defines the PATH environment variable for a regular user. The
+default value is
+.IR /usr/local/bin:\:/bin:\:/usr/bin .
+.RE
+.PP
+.B ENV_ROOTPATH
+(string)
+.br
+.B ENV_SUPATH
+(string)
+.RS 4
+Defines the PATH environment variable for root. The default value is
+.IR /usr/local/sbin:\:/usr/local/bin:\:/sbin:\:/bin:\:/usr/sbin:\:/usr/bin .
+.RE
+.PP
+.B ALWAYS_SET_PATH
+(boolean)
+.RS 4
+If set to
+.I yes
+and \-\-login and \-\-preserve\-environment were not specified
+.B runuser
+initializes
+.BR PATH .
+.RE
+.SH EXIT STATUS
+.B runuser
+normally returns the exit status of the command it executed. If the
+command was killed by a signal,
+.B runuser
+returns the number of the signal plus 128.
+.PP
+Exit status generated by
+.B runuser
+itself:
+.RS 10
+.TP
+1
+Generic error before executing the requested command
+.TP
+126
+The requested command could not be executed
+.TP
+127
+The requested command could was not found
+.RE
+.SH FILES
+.PD 0
+.TP 17
+/etc/pam.d/runuser
+default PAM configuration file
+.TP
+/etc/pam.d/runuser-l
+PAM configuration file if \-\-login is specified
+.TP
+/etc/default/runuser
+runuser specific logindef config file
+.TP
+/etc/login.defs
+global logindef config file
+.PD 1
+.SH "SEE ALSO"
+.BR pam (8),
+.BR shells (5),
+.BR login.defs (5),
+.BR su (1)
+.SH AUTHOR
+Derived from coreutils' su which was based on an implemenation from
+David MacKenzie and Fedora runuser command from Dan Walsh.
+.SH AVAILABILITY
+The runuser command is part of the util-linux package and is
+available from
+.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
+Linux Kernel Archive
+.UE .
diff --git a/login-utils/runuser.c b/login-utils/runuser.c
new file mode 100644
index 0000000..d4f37f4
--- /dev/null
+++ b/login-utils/runuser.c
@@ -0,0 +1,7 @@
+
+#include "su-common.h"
+
+int main(int argc, char **argv)
+{
+ return su_main(argc, argv, RUNUSER_MODE);
+}
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index f1f46aa..770f455 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -65,8 +65,14 @@ enum
#include "env.h"
/* name of the pam configuration files. separate configs for su and su - */
-#define PAM_SERVICE_NAME "su"
-#define PAM_SERVICE_NAME_L "su-l"
+#define PAM_SRVNAME_SU "su"
+#define PAM_SRVNAME_SU_L "su-l"
+
+#define PAM_SRVNAME_RUNUSER "runuser"
+#define PAM_SRVNAME_RUNUSER_L "runuser-l"
+
+#define _PATH_LOGINDEFS_SU "/etc/defaults/su"
+#define _PATH_LOGINDEFS_RUNUSER "/etc/defaults/runuser"
#define is_pam_failure(_rc) ((_rc) != PAM_SUCCESS)
@@ -106,6 +112,8 @@ static bool _pam_cred_established;
static sig_atomic_t volatile caught_signal = false;
static pam_handle_t *pamh = NULL;
+static int restricted = 1; /* zero for root user */
+
static struct option const longopts[] =
{
{"command", required_argument, NULL, 'c'},
@@ -146,7 +154,8 @@ log_su (struct passwd const *pw, bool successful)
openlog (program_invocation_short_name, 0 , LOG_AUTH);
syslog (LOG_NOTICE, "%s(to %s) %s on %s",
- successful ? "" : "FAILED SU ",
+ successful ? "" :
+ su_mode == RUNUSER_MODE ? "FAILED RUNUSER " : "FAILED SU ",
new_user, old_user, tty);
closelog ();
}
@@ -315,11 +324,19 @@ static void
authenticate (const struct passwd *pw)
{
const struct passwd *lpw;
- const char *cp;
+ const char *cp, *srvname = NULL;
int retval;
- retval = pam_start (simulate_login ? PAM_SERVICE_NAME_L : PAM_SERVICE_NAME,
- pw->pw_name, &conv, &pamh);
+ switch (su_mode) {
+ case SU_MODE:
+ srvname = simulate_login ? PAM_SRVNAME_SU_L : PAM_SRVNAME_SU;
+ break;
+ case RUNUSER_MODE:
+ srvname = simulate_login ? PAM_SRVNAME_RUNUSER_L : PAM_SRVNAME_RUNUSER;
+ break;
+ }
+
+ retval = pam_start (srvname, pw->pw_name, &conv, &pamh);
if (is_pam_failure(retval))
goto done;
@@ -344,6 +361,17 @@ authenticate (const struct passwd *pw)
goto done;
}
+ if (su_mode == RUNUSER_MODE)
+ {
+ /*
+ * This is the only difference between runuser(1) and su(1). The command
+ * runuser(1) does not required authentication, because user is root.
+ */
+ if (restricted)
+ errx(EXIT_FAILURE, _("may not be used by non-root users"));
+ return;
+ }
+
retval = pam_authenticate (pamh, 0);
if (is_pam_failure(retval))
goto done;
@@ -567,7 +595,15 @@ usage (int status)
static
void load_config(void)
{
- logindefs_load_file("/etc/default/su");
+ switch (su_mode) {
+ case SU_MODE:
+ logindefs_load_file(_PATH_LOGINDEFS_SU);
+ break;
+ case RUNUSER_MODE:
+ logindefs_load_file(_PATH_LOGINDEFS_RUNUSER);
+ break;
+ }
+
logindefs_load_file(_PATH_LOGINDEFS);
}
@@ -598,7 +634,6 @@ su_main (int argc, char **argv, int mode)
gid_t groups[NGROUPS_MAX];
int num_supp_groups = 0;
int use_gid = 0;
- int restricted;
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
--
1.7.11.7

View File

@ -0,0 +1,68 @@
From 8f33f59e72bef913068f9a80338f12d8d4434010 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 5 Sep 2012 11:13:34 +0200
Subject: [PATCH 203/208] su: more robust getpwuid() for GNU Hurt [coreutils
71b7ddc]
Let's support GNU Hurd over-engineering where a process can exist
without UID and getuid() returns -1 and sets errno.
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/su-common.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index 770f455..a253dda 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -129,6 +129,26 @@ static struct option const longopts[] =
{NULL, 0, NULL, 0}
};
+
+static struct passwd *
+current_getpwuid(void)
+{
+ uid_t ruid;
+
+ /* GNU Hurd implementation has an extension where a process can exist in a
+ * non-conforming environment, and thus be outside the realms of POSIX
+ * process identifiers; on this platform, getuid() fails with a status of
+ * (uid_t)(-1) and sets errno if a program is run from a non-conforming
+ * environment.
+ *
+ * http://austingroupbugs.net/view.php?id=511
+ */
+ errno = 0;
+ ruid = getuid ();
+
+ return errno == 0 ? getpwuid (ruid) : NULL;
+}
+
/* Log the fact that someone has run su to the user given by PW;
if SUCCESSFUL is true, they gave the correct password, etc. */
@@ -145,8 +165,8 @@ log_su (struct passwd const *pw, bool successful)
{
/* getlogin can fail -- usually due to lack of utmp entry.
Resort to getpwuid. */
- struct passwd *pwd = getpwuid (getuid ());
- old_user = (pwd ? pwd->pw_name : "");
+ struct passwd *pwd = current_getpwuid();
+ old_user = pwd ? pwd->pw_name : "";
}
tty = ttyname (STDERR_FILENO);
if (!tty)
@@ -353,7 +373,7 @@ authenticate (const struct passwd *pw)
goto done;
}
- lpw = getpwuid (getuid ());
+ lpw = current_getpwuid ();
if (lpw && lpw->pw_name)
{
retval = pam_set_item (pamh, PAM_RUSER, (const void *) lpw->pw_name);
--
1.7.11.7

View File

@ -0,0 +1,33 @@
From 589e24a625c5e83805e95b917eaf3bf1be64369e Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 5 Sep 2012 11:21:07 +0200
Subject: [PATCH 204/208] su: verify writing to streams was successful
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/su-common.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index a253dda..1f97328 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -63,6 +63,7 @@ enum
#include "nls.h"
#include "pathnames.h"
#include "env.h"
+#include "closestream.h"
/* name of the pam configuration files. separate configs for su and su - */
#define PAM_SRVNAME_SU "su"
@@ -658,6 +659,7 @@ su_main (int argc, char **argv, int mode)
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
+ atexit(close_stdout);
su_mode = mode;
fast_startup = false;
--
1.7.11.7

View File

@ -0,0 +1,60 @@
From bea3752e9d048895b6750e2d0d8ce72fed20cef9 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 5 Sep 2012 11:26:20 +0200
Subject: [PATCH 205/208] su: move long options to main()
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/su-common.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index 1f97328..778738f 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -115,21 +115,6 @@ static pam_handle_t *pamh = NULL;
static int restricted = 1; /* zero for root user */
-static struct option const longopts[] =
-{
- {"command", required_argument, NULL, 'c'},
- {"session-command", required_argument, NULL, 'C'},
- {"fast", no_argument, NULL, 'f'},
- {"login", no_argument, NULL, 'l'},
- {"preserve-environment", no_argument, NULL, 'p'},
- {"shell", required_argument, NULL, 's'},
- {"group", required_argument, NULL, 'g'},
- {"supp-group", required_argument, NULL, 'G'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {NULL, 0, NULL, 0}
-};
-
static struct passwd *
current_getpwuid(void)
@@ -656,6 +641,20 @@ su_main (int argc, char **argv, int mode)
int num_supp_groups = 0;
int use_gid = 0;
+ static const struct option longopts[] = {
+ {"command", required_argument, NULL, 'c'},
+ {"session-command", required_argument, NULL, 'C'},
+ {"fast", no_argument, NULL, 'f'},
+ {"login", no_argument, NULL, 'l'},
+ {"preserve-environment", no_argument, NULL, 'p'},
+ {"shell", required_argument, NULL, 's'},
+ {"group", required_argument, NULL, 'g'},
+ {"supp-group", required_argument, NULL, 'G'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
--
1.7.11.7

View File

@ -0,0 +1,40 @@
From 1fe22a730b1a6595c6da9ea8cd58594337e66dc3 Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <ooprala@redhat.com>
Date: Tue, 11 Sep 2012 16:39:17 +0200
Subject: [PATCH 206/208] su: add segmentation fault reporting of the child
process
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Child processes that ended with segmentation fault previously
indicated this with return status only. The report is now more
verbose if core dump is allowed.
Improved-by: Pádraig Brady <P@draigBrady.com>
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
---
login-utils/su-common.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index 778738f..118e080 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -300,7 +300,12 @@ create_watching_parent (void)
}
if (pid != (pid_t)-1)
if (WIFSIGNALED (status))
- status = WTERMSIG (status) + 128;
+ {
+ status = WTERMSIG (status) + 128;
+ if (WCOREDUMP (status))
+ fprintf (stderr, _("%s (core dumped)\n"),
+ strsignal (WTERMSIG (status)));
+ }
else
status = WEXITSTATUS (status);
else
--
1.7.11.7

View File

@ -0,0 +1,26 @@
From 2f3cb337e1cda9e897480f256453f369914380b3 Mon Sep 17 00:00:00 2001
From: Vitezslav Cizek <vcizek@suse.cz>
Date: Mon, 1 Oct 2012 14:48:16 +0200
Subject: [PATCH 207/208] su: fixed a typo in pam error message
Signed-off-by: Vitezslav Cizek <vcizek@suse.cz>
---
login-utils/su-common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index 118e080..ea6864e 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -223,7 +223,7 @@ create_watching_parent (void)
if (is_pam_failure(retval))
{
cleanup_pam (retval);
- errx (EXIT_FAILURE, _("cannot not open session: %s"),
+ errx (EXIT_FAILURE, _("cannot open session: %s"),
pam_strerror (pamh, retval));
}
else
--
1.7.11.7

View File

@ -0,0 +1,281 @@
From f0c57c2b1129b17e68e54d08421d1f209f1b6c57 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 13 Sep 2012 11:58:00 +0200
Subject: [PATCH 208/208] runuser: add -u to not execute shell
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/runuser.1 | 20 ++++---
login-utils/su-common.c | 138 +++++++++++++++++++++++++++++++-----------------
login-utils/su.1 | 1 +
3 files changed, 105 insertions(+), 54 deletions(-)
diff --git a/login-utils/runuser.1 b/login-utils/runuser.1
index 66ad1c4..4620165 100644
--- a/login-utils/runuser.1
+++ b/login-utils/runuser.1
@@ -3,10 +3,21 @@
runuser \- run a command with substitute user and group ID
.SH SYNOPSIS
.B runuser
-[options...] [\-] [user [args...]]
+[options] -u
+.IR user
+.IR "command " [ argument ...]
+.LP
+.B runuser
+[options] [-]
+[
+.IR "user " [ argument ...]
+]
.SH DESCRIPTION
.B runuser
allows to run commands with substitute user and group ID.
+If the option \fB\-u\fR not given, fallback to
+.B su
+compatible semantic and shell is executed.
The difference between the commands
.B runuser
and
@@ -36,12 +47,7 @@ and
.B LOGNAME
if the target
.I user
-is not root). It is recommended to always use the
-.B \-\-login
-option (instead it's shortcut
-.BR \- )
-to avoid side effects caused by mixing environments.
-.PP
+is not root).
This version of
.B runuser
uses PAM for session management.
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index ea6864e..4e1f6b2 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -439,7 +439,8 @@ modify_environment (const struct passwd *pw, const char *shell)
if (term)
xsetenv ("TERM", term, 1);
xsetenv ("HOME", pw->pw_dir, 1);
- xsetenv ("SHELL", shell, 1);
+ if (shell)
+ xsetenv ("SHELL", shell, 1);
xsetenv ("USER", pw->pw_name, 1);
xsetenv ("LOGNAME", pw->pw_name, 1);
set_path(pw);
@@ -451,7 +452,8 @@ modify_environment (const struct passwd *pw, const char *shell)
if (change_environment)
{
xsetenv ("HOME", pw->pw_dir, 1);
- xsetenv ("SHELL", shell, 1);
+ if (shell)
+ xsetenv ("SHELL", shell, 1);
if (getlogindefs_bool ("ALWAYS_SET_PATH", 0))
set_path(pw);
@@ -571,35 +573,47 @@ restricted_shell (const char *shell)
static void __attribute__((__noreturn__))
usage (int status)
{
- if (status != EXIT_SUCCESS)
- fprintf (stderr, _("Try `%s --help' for more information.\n"),
- program_invocation_short_name);
- else
- {
- fputs(USAGE_HEADER, stdout);
- printf (_(" %s [options] [-] [USER [arg]...]\n"), program_invocation_short_name);
- fputs (_("\n\
- Change the effective user id and group id to that of USER.\n\
- A mere - implies -l. If USER not given, assume root.\n"), stdout);
- fputs(USAGE_OPTIONS, stdout);
- fputs (_("\
- -, -l, --login make the shell a login shell\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\
- -g --group=group specify the primary group\n\
- -G --supp-group=group specify a supplemental group\n\
- -f, --fast pass -f to the shell (for csh or tcsh)\n\
- -m, --preserve-environment do not reset environment variables\n\
- -p same as -m\n\
- -s, --shell <shell> run shell if /etc/shells allows it\n\
-"), stdout);
-
- fputs(USAGE_SEPARATOR, stdout);
- fputs(USAGE_HELP, stdout);
- fputs(USAGE_VERSION, stdout);
- printf(USAGE_MAN_TAIL("su(1)"));
- }
+ if (su_mode == RUNUSER_MODE) {
+ fputs(USAGE_HEADER, stdout);
+ printf (_(" %s [options] -u <USER> COMMAND\n"), program_invocation_short_name);
+ printf (_(" %s [options] [-] [USER [arg]...]\n"), program_invocation_short_name);
+ fputs (_("\n"
+ "Run COMMAND with the effective <user> id and group id. If -u not\n"
+ "given, fallback to su(1) compatible semantic and shell is executed.\n"
+ "The options -l, -c, -f, -s are mutually exclusive to -u.\n"), stdout);
+
+ fputs(USAGE_OPTIONS, stdout);
+
+ fputs (_(
+ " -u, --user <user> username\n"), stdout);
+
+ } else {
+ fputs(USAGE_HEADER, stdout);
+ printf (_(" %s [options] [-] [USER [arg]...]\n"), program_invocation_short_name);
+ fputs (_("\n"
+ "Change the effective user id and group id to that of USER.\n"
+ "A mere - implies -l. If USER not given, assume root.\n"), stdout);
+
+ fputs(USAGE_OPTIONS, stdout);
+ }
+
+ fputs (_(
+ " -m, -p, --preserve-environment do not reset environment variables\n"
+ " -g, --group <group> specify the primary group\n"
+ " -G, --supp-group <group> specify a supplemental group\n\n"), stdout);
+
+ fputs (_(
+ " -, -l, --login make the shell a login shell\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"
+ " -s, --shell <shell> run shell if /etc/shells allows it\n"), stdout);
+
+ fputs(USAGE_SEPARATOR, stdout);
+ fputs(USAGE_HELP, stdout);
+ fputs(USAGE_VERSION, stdout);
+ printf(USAGE_MAN_TAIL(su_mode == SU_MODE ? "su(1)" : "runuser(1)"));
exit (status);
}
@@ -635,7 +649,7 @@ int
su_main (int argc, char **argv, int mode)
{
int optc;
- const char *new_user = DEFAULT_USER;
+ const char *new_user = DEFAULT_USER, *runuser_user = NULL;
char *command = NULL;
int request_same_session = 0;
char *shell = NULL;
@@ -655,6 +669,7 @@ su_main (int argc, char **argv, int mode)
{"shell", required_argument, NULL, 's'},
{"group", required_argument, NULL, 'g'},
{"supp-group", required_argument, NULL, 'G'},
+ {"user", required_argument, NULL, 'u'}, /* runuser only */
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{NULL, 0, NULL, 0}
@@ -670,7 +685,7 @@ su_main (int argc, char **argv, int mode)
simulate_login = false;
change_environment = true;
- while ((optc = getopt_long (argc, argv, "c:fg:G:lmps:hV", longopts, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "+c:fg:G:lmps:u:hV", longopts, NULL)) != -1)
{
switch (optc)
{
@@ -720,6 +735,12 @@ su_main (int argc, char **argv, int mode)
shell = optarg;
break;
+ case 'u':
+ if (su_mode != RUNUSER_MODE)
+ usage (EXIT_FAILURE);
+ runuser_user = optarg;
+ break;
+
case 'h':
usage(0);
@@ -739,8 +760,21 @@ su_main (int argc, char **argv, int mode)
simulate_login = true;
++optind;
}
- if (optind < argc)
+
+ /* if not "-u <user>" specified then fallback to classic su(1) */
+ if (!runuser_user && optind < argc)
new_user = argv[optind++];
+ else {
+ /* runuser -u <command> */
+ new_user = runuser_user;
+ if (shell || fast_startup || command || simulate_login) {
+ errx(EXIT_FAILURE,
+ _("options --{shell,fast,command,session-command,login} and "
+ "--user are mutually exclusive."));
+ }
+ if (optind == argc)
+ errx(EXIT_FAILURE, _("COMMAND not specified."));
+ }
if ((num_supp_groups || use_gid) && restricted)
errx(EXIT_FAILURE, _("only root can specify alternative groups"));
@@ -784,18 +818,23 @@ su_main (int argc, char **argv, int mode)
if (request_same_session || !command || !pw->pw_uid)
same_session = 1;
- if (!shell && !change_environment)
- shell = getenv ("SHELL");
- if (shell && getuid () != 0 && restricted_shell (pw->pw_shell))
- {
- /* The user being su'd to has a nonstandard shell, and so is
- probably a uucp account or has restricted access. Don't
- compromise the account by allowing access with a standard
- shell. */
- warnx (_("using restricted shell %s"), pw->pw_shell);
- shell = NULL;
- }
- shell = xstrdup (shell ? shell : pw->pw_shell);
+ /* initialize shell variable only if "-u <user>" not specified */
+ if (runuser_user) {
+ shell = NULL;
+ } else {
+ if (!shell && !change_environment)
+ shell = getenv ("SHELL");
+ if (shell && getuid () != 0 && restricted_shell (pw->pw_shell))
+ {
+ /* The user being su'd to has a nonstandard shell, and so is
+ probably a uucp account or has restricted access. Don't
+ compromise the account by allowing access with a standard
+ shell. */
+ warnx (_("using restricted shell %s"), pw->pw_shell);
+ shell = NULL;
+ }
+ shell = xstrdup (shell ? shell : pw->pw_shell);
+ }
init_groups (pw, groups, num_supp_groups);
@@ -814,7 +853,12 @@ su_main (int argc, char **argv, int mode)
if (simulate_login && chdir (pw->pw_dir) != 0)
warn (_("warning: cannot change directory to %s"), pw->pw_dir);
- run_shell (shell, command, argv + optind, max (0, argc - optind));
+ if (shell)
+ run_shell (shell, command, argv + optind, max (0, argc - optind));
+ else {
+ execvp(argv[optind], &argv[optind]);
+ err(EXIT_FAILURE, _("executing %s failed"), argv[optind]);
+ }
}
// vim: sw=2 cinoptions=>4,n-2,{2,^-2,\:2,=2,g0,h2,p5,t0,+2,(0,u0,w1,m1
diff --git a/login-utils/su.1 b/login-utils/su.1
index 59e1731..c82b941 100644
--- a/login-utils/su.1
+++ b/login-utils/su.1
@@ -216,6 +216,7 @@ command specific logindef config file
global logindef config file
.PD 1
.SH "SEE ALSO"
+.BR runuser (8),
.BR pam (8),
.BR shells (5),
.BR login.defs (5)
--
1.7.11.7

View File

@ -0,0 +1,26 @@
From 69658513d00635048f5de76ed73f4a43a61d374d Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 1 Nov 2012 13:12:02 +0100
Subject: [PATCH] build-sys: move runuser to sbin dir
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/Makemodule.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
index e26d9a7..0d8e8b1 100644
--- a/login-utils/Makemodule.am
+++ b/login-utils/Makemodule.am
@@ -94,7 +94,7 @@ endif
if BUILD_RUNUSER
-bin_PROGRAMS += runuser
+sbin_PROGRAMS += runuser
dist_man_MANS += login-utils/runuser.1
runuser_SOURCES = \
login-utils/runuser.c \
--
1.7.11.7

View File

@ -0,0 +1,4 @@
#%PAM-1.0
auth include runuser
session optional pam_keyinit.so force revoke
session include runuser

5
util-linux-runuser.pamd Normal file
View File

@ -0,0 +1,5 @@
#%PAM-1.0
auth sufficient pam_rootok.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session required pam_unix.so

6
util-linux-su-l.pamd Normal file
View File

@ -0,0 +1,6 @@
#%PAM-1.0
auth include su
account include su
password include su
session optional pam_keyinit.so force revoke
session include su

14
util-linux-su.pamd Normal file
View File

@ -0,0 +1,14 @@
#%PAM-1.0
auth sufficient pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth sufficient pam_wheel.so trust use_uid
# Uncomment the following line to require a user to be in the "wheel" group.
#auth required pam_wheel.so use_uid
auth include system-auth
auth include postlogin
account sufficient pam_succeed_if.so uid = 0 use_uid quiet
account include system-auth
password include system-auth
session include system-auth
session include postlogin
session optional pam_xauth.so

View File

@ -2,7 +2,7 @@
Summary: A collection of basic system utilities
Name: util-linux
Version: 2.22.1
Release: 2%{?dist}
Release: 3%{?dist}
License: GPLv2 and GPLv2+ and GPLv3+ and LGPLv2+ and BSD with advertising and Public Domain
Group: System Environment/Base
URL: http://en.wikipedia.org/wiki/Util-linux
@ -24,6 +24,11 @@ BuildRequires: popt-devel
BuildRequires: libutempter-devel
Buildrequires: systemd-devel
# because backported su(1) and runuser(1) patches
BuildRequires: automake
BuildRequires: autoconf
BuildRequires: libtool
### Sources
Source0: ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.22/util-linux-%{upstream_version}.tar.xz
Source1: util-linux-login.pamd
@ -33,8 +38,14 @@ Source4: util-linux-60-raw.rules
Source8: nologin.c
Source9: nologin.8
Source11: http://downloads.sourceforge.net/floppyutil/floppy-%{floppyver}.tar.bz2
Source12: util-linux-su.pamd
Source13: util-linux-su-l.pamd
Source14: util-linux-runuser.pamd
Source15: util-linux-runuser-l.pamd
### Obsoletes & Conflicts & Provides
# su(1) and runuser(1) merged into util-linux v2.22
Conflicts: coreutils < 8.20
# eject has been merged into util-linux v2.22
Obsoletes: eject <= 2.1.5
Provides: eject = 2.1.6
@ -99,6 +110,20 @@ Patch109: 0009-fsck.cramfs-compile-with-DINCLUDE_FS_TESTS-for-make-.patch
Patch110: 0010-login-fix-compiler-warning-Wunused-result.patch
Patch111: 0011-misc-make-readlink-usage-more-robust.patch
### Upstream patches from master branch (will be v2.23) for su(1) and new
### runuser(1) implementation. This is required for the recent coreutils where
### is no more su(1).
###
Patch200: 0200-su-add-group-and-supp-group-options.patch
Patch201: 0201-su-move-generic-su-code-to-su-common.c.patch
Patch202: 0202-runuser-new-command-derived-from-su-1.patch
Patch203: 0203-su-more-robust-getpwuid-for-GNU-Hurt-coreutils-71b7d.patch
Patch204: 0204-su-verify-writing-to-streams-was-successful.patch
Patch205: 0205-su-move-long-options-to-main.patch
Patch206: 0206-su-add-segmentation-fault-reporting-of-the-child-pro.patch
Patch207: 0207-su-fixed-a-typo-in-pam-error-message.patch
Patch208: 0208-runuser-add-u-to-not-execute-shell.patch
Patch209: 0209-build-sys-move-runuser-to-sbin-dir.patch
%description
The util-linux package contains a large variety of low-level system
@ -228,9 +253,22 @@ cp %{SOURCE8} %{SOURCE9} .
%patch110 -p1
%patch111 -p1
%patch200 -p1
%patch201 -p1
%patch202 -p1
%patch203 -p1
%patch204 -p1
%patch205 -p1
%patch206 -p1
%patch207 -p1
%patch208 -p1
%patch209 -p1
%build
unset LINGUAS || :
./autogen.sh
export CFLAGS="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 $RPM_OPT_FLAGS"
export SUID_CFLAGS="-fpie"
export SUID_LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now"
@ -242,7 +280,6 @@ export SUID_LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now"
--enable-chfn-chsh \
--enable-write \
--enable-raw \
--disable-su \
--with-udev \
--with-selinux \
--with-audit \
@ -327,6 +364,10 @@ chmod 755 ${RPM_BUILD_ROOT}%{_bindir}/sunhostid
install -m 644 %{SOURCE2} ./remote
install -m 644 %{SOURCE3} ./chsh
install -m 644 %{SOURCE3} ./chfn
install -m 644 %{SOURCE12} ./su
install -m 644 %{SOURCE13} ./su-l
install -m 644 %{SOURCE14} ./runuser
install -m 644 %{SOURCE15} ./runuser-l
popd
}
@ -485,10 +526,15 @@ fi
%config(noreplace) %{_sysconfdir}/pam.d/chsh
%config(noreplace) %{_sysconfdir}/pam.d/login
%config(noreplace) %{_sysconfdir}/pam.d/remote
%config(noreplace) %{_sysconfdir}/pam.d/su
%config(noreplace) %{_sysconfdir}/pam.d/su-l
%config(noreplace) %{_sysconfdir}/pam.d/runuser
%config(noreplace) %{_sysconfdir}/pam.d/runuser-l
%config(noreplace) %{_prefix}/lib/udev/rules.d
%attr(4755,root,root) %{_bindir}/mount
%attr(4755,root,root) %{_bindir}/umount
%attr(4755,root,root) %{_bindir}/su
%attr(755,root,root) %{_bindir}/login
%attr(4711,root,root) %{_bindir}/chfn
%attr(4711,root,root) %{_bindir}/chsh
@ -574,10 +620,12 @@ fi
%{_mandir}/man1/rename.1*
%{_mandir}/man1/renice.1*
%{_mandir}/man1/rev.1*
%{_mandir}/man1/runuser.1*
%{_mandir}/man1/script.1*
%{_mandir}/man1/scriptreplay.1*
%{_mandir}/man1/setsid.1*
%{_mandir}/man1/setterm.1*
%{_mandir}/man1/su.1*
%{_mandir}/man1/tailf.1*
%{_mandir}/man1/taskset.1*
%{_mandir}/man1/ul.1*
@ -653,6 +701,7 @@ fi
%{_sbindir}/readprofile
%{_sbindir}/resizepart
%{_sbindir}/rtcwake
%{_sbindir}/runuser
%{_sbindir}/sulogin
%{_sbindir}/swaplabel
%{_sbindir}/swapoff
@ -754,6 +803,10 @@ fi
%changelog
* Thu Nov 1 2012 Karel Zak <kzak@redhat.com> 2.22.1-3
- backport upstream runuser(1)
- enable su(1)
* Thu Nov 1 2012 Karel Zak <kzak@redhat.com> 2.22.1-2
- apply pathes from upstream stable/v2.22 branch
- fix #865961 - wipefs -a should use O_EXCL