diff --git a/configure.ac b/configure.ac index 77ceb52f71..d6137f82eb 100644 --- a/configure.ac +++ b/configure.ac @@ -550,7 +550,7 @@ fi AM_CONDITIONAL([USE_PAM], [test "X$with_libpam" = "Xyes"]) AC_ARG_WITH([fcaps], - [AS_HELP_STRING([--with-fcaps], [use file capabilities instead of suid binaries for newuidmap/newgidmap @<:@default=no@:>@])], + [AS_HELP_STRING([--with-fcaps], [use file capabilities instead of suid binaries where possible @<:@default=no@:>@])], [with_fcaps=$withval], [with_fcaps=no]) AM_CONDITIONAL([FCAPS], [test "x$with_fcaps" = "xyes"]) diff --git a/lib/find_new_sub_gids.c b/lib/find_new_sub_gids.c index 3971ce922e..34e7d2eac9 100644 --- a/lib/find_new_sub_gids.c +++ b/lib/find_new_sub_gids.c @@ -10,6 +10,7 @@ #include #include +#include #include "prototypes.h" #include "subordinateio.h" diff --git a/lib/find_new_sub_uids.c b/lib/find_new_sub_uids.c index 65f6815467..639b4a4dfa 100644 --- a/lib/find_new_sub_uids.c +++ b/lib/find_new_sub_uids.c @@ -10,6 +10,7 @@ #include #include +#include #include "prototypes.h" #include "subordinateio.h" diff --git a/lib/pwd_init.c b/lib/pwd_init.c index bd2cfd3ff5..e253da4cec 100644 --- a/lib/pwd_init.c +++ b/lib/pwd_init.c @@ -51,6 +51,7 @@ void pwd_init (void) signal (SIGTERM, SIG_IGN); signal (SIGTSTP, SIG_IGN); signal (SIGTTOU, SIG_IGN); + signal (SIGXFSZ, SIG_IGN); umask (077); } diff --git a/src/Makefile.am b/src/Makefile.am index c935e05b30..423a6576f4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,17 +61,22 @@ noinst_PROGRAMS = sulogin suidusbins = suidbins = -suidubins = chage chfn chsh gpasswd newgrp if WITH_SU suidbins += su endif + +privubins = chage chfn chsh gpasswd newgrp if !WITH_TCB -suidubins += passwd +privubins += passwd endif if ENABLE_SUBIDS -if !FCAPS -suidubins += newgidmap newuidmap +privubins += newgidmap newuidmap endif + +if FCAPS +suidubins = +else +suidubins = $(privubins) endif if WITH_TCB @@ -143,6 +148,16 @@ if WITH_TCB chmod $(sgidperms) $(DESTDIR)$(ubindir)/$$i; \ done endif +if FCAPS + setcap cap_dac_read_search+ep $(DESTDIR)$(ubindir)/chage + setcap cap_setgid,cap_dac_read_search+ep $(DESTDIR)$(ubindir)/newgrp + setcap cap_chown,cap_dac_override,cap_fowner+ep $(DESTDIR)$(ubindir)/chfn + setcap cap_chown,cap_dac_override,cap_fowner+ep $(DESTDIR)$(ubindir)/chsh + setcap cap_chown,cap_dac_override,cap_fowner+ep $(DESTDIR)$(ubindir)/gpasswd +if !WITH_TCB + setcap cap_chown,cap_dac_override,cap_fowner+ep $(DESTDIR)$(ubindir)/passwd +endif +endif if ENABLE_SUBIDS if FCAPS setcap cap_setuid+ep $(DESTDIR)$(ubindir)/newuidmap diff --git a/src/chfn.c b/src/chfn.c index 71875253e9..763ec14805 100644 --- a/src/chfn.c +++ b/src/chfn.c @@ -395,13 +395,7 @@ static void update_gecos(const char *user, char *gecos, const struct option_flag process_selinux = !flags->chroot; - /* - * Before going any further, raise the ulimit to prevent colliding - * into a lowered ulimit, and set the real UID to root to protect - * against unexpected signals. Any keyboard signals are set to be - * ignored. - */ - if (setuid (0) != 0) { + if (geteuid () == 0 && setuid (0) != 0) { fputs (_("Cannot change ID to root.\n"), stderr); SYSLOG(LOG_ERR, "can't setuid(0)"); fail_exit (E_NOPERM, process_selinux); diff --git a/src/chsh.c b/src/chsh.c index fafa9759d6..3d057053e1 100644 --- a/src/chsh.c +++ b/src/chsh.c @@ -375,13 +375,7 @@ static void update_shell (const char *user, char *newshell, const struct option_ process_selinux = !flags->chroot; - /* - * Before going any further, raise the ulimit to prevent - * colliding into a lowered ulimit, and set the real UID - * to root to protect against unexpected signals. Any - * keyboard signals are set to be ignored. - */ - if (setuid (0) != 0) { + if (geteuid () == 0 && setuid (0) != 0) { SYSLOG(LOG_ERR, "can't setuid(0)"); fputs (_("Cannot change ID to root.\n"), stderr); fail_exit (1, process_selinux); diff --git a/src/gpasswd.c b/src/gpasswd.c index bb53087c6f..06351a17b7 100644 --- a/src/gpasswd.c +++ b/src/gpasswd.c @@ -1088,7 +1088,7 @@ int main (int argc, char **argv) * output, etc. */ output: - if (setuid (0) != 0) { + if (geteuid () == 0 && setuid (0) != 0) { fputs (_("Cannot change ID to root.\n"), stderr); SYSLOG(LOG_ERR, "can't setuid(0)"); closelog (); diff --git a/src/passwd.c b/src/passwd.c index b2cac80b00..00a77067e9 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -1197,7 +1197,7 @@ main(int argc, char **argv) exit (E_SUCCESS); } #endif /* USE_PAM */ - if (setuid (0) != 0) { + if (geteuid () == 0 && setuid (0) != 0) { (void) fputs (_("Cannot change ID to root.\n"), stderr); SYSLOG(LOG_ERR, "can't setuid(0)"); closelog ();