setpriv: dump user and group info
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 4 Jul 2017 16:49:24 +0000 (18:49 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 4 Jul 2017 16:59:11 +0000 (18:59 +0200)
setpriv from util-linux has an option to dump the current state
regarding privilege settings via '--dump'. It prints out information on
the real and effective user and group IDs, supplementary groups, the
no-new-privs flag, the capability sets as well as secure bits.

This patch is the start of supporting this mode. To make introduction of
the '--dump' easier to reason about, its introduction has been split
into multiple patches. This particular one introduces the ability to
print out user and group information of the current process.

function                                             old     new   delta
setpriv_main                                          89     322    +233
getresuid                                              -      41     +41
getresgid                                              -      41     +41
static.setpriv_longopts                               22      29      +7
packed_usage                                       31675   31669      -6
------------------------------------------------------------------------------
(add/remove: 4/0 grow/shrink: 2/1 up/down: 322/-6)            Total: 316 bytes

Patch by Patrick Steinhardt <ps@pks.im>

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
util-linux/setpriv.c

index d15e0d84ec237ec0bcb9ed5fd78506ca8a99a7a1..f21ce6632824547d4fd074470cba0a1396aba42a 100644 (file)
 //config:      help
 //config:        Run a program with different Linux privilege settings.
 //config:        Requires kernel >= 3.5
+//config:
+//config:config FEATURE_SETPRIV_DUMP
+//config:      bool "Support dumping current privilege state"
+//config:      default y
+//config:      depends on SETPRIV
+//config:      help
+//config:        Enables the "--dump" switch to print out the current privilege
+//config:        state. This is helpful for diagnosing problems.
 
 //applet:IF_SETPRIV(APPLET(setpriv, BB_DIR_BIN, BB_SUID_DROP))
 
@@ -24,6 +32,9 @@
 //usage:       "[OPTIONS] PROG [ARGS]"
 //usage:#define setpriv_full_usage "\n\n"
 //usage:       "Run PROG with different privilege settings\n"
+//usage:       IF_FEATURE_SETPRIV_DUMP(
+//usage:     "\n-d,--dump              Show current capabilities"
+//usage:       )
 //usage:     "\n--nnp,--no-new-privs   Ignore setuid/setgid bits and file capabilities"
 
 //setpriv from util-linux 2.28:
 #endif
 
 enum {
+       IF_FEATURE_SETPRIV_DUMP(OPTBIT_DUMP,)
        OPTBIT_NNP,
 
-       OPT_NNP = (1 << OPTBIT_NNP),
+       IF_FEATURE_SETPRIV_DUMP(OPT_DUMP = (1 << OPTBIT_DUMP),)
+       OPT_NNP  = (1 << OPTBIT_NNP),
 };
 
+#if ENABLE_FEATURE_SETPRIV_DUMP
+static int dump(void)
+{
+       uid_t ruid, euid, suid;
+       gid_t rgid, egid, sgid;
+       gid_t *gids;
+       int ngids;
+
+       getresuid(&ruid, &euid, &suid); /* never fails in Linux */
+       getresgid(&rgid, &egid, &sgid); /* never fails in Linux */
+       ngids = 0;
+       gids = bb_getgroups(&ngids, NULL); /* never fails in Linux */
+
+       printf("uid: %u\n", (unsigned)ruid);
+       printf("euid: %u\n", (unsigned)euid);
+       printf("gid: %u\n", (unsigned)rgid);
+       printf("egid: %u\n", (unsigned)egid);
+
+       printf("Supplementary groups: ");
+       if (ngids == 0) {
+               printf("[none]");
+       } else {
+               const char *fmt = ",%u" + 1;
+               int i;
+               for (i = 0; i < ngids; i++) {
+                       printf(fmt, (unsigned)gids[i]);
+                       fmt = ",%u";
+               }
+       }
+       bb_putchar('\n');
+
+       if (ENABLE_FEATURE_CLEAN_UP)
+               free(gids);
+       return EXIT_SUCCESS;
+}
+#endif /* FEATURE_SETPRIV_DUMP */
+
 int setpriv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int setpriv_main(int argc UNUSED_PARAM, char **argv)
 {
        static const char setpriv_longopts[] ALIGN1 =
+               IF_FEATURE_SETPRIV_DUMP(
+               "dump\0"         No_argument    "d"
+               )
                "nnp\0"          No_argument    "\xff"
                "no-new-privs\0" No_argument    "\xff"
                ;
        int opts;
 
        applet_long_options = setpriv_longopts;
-       opts = getopt32(argv, "+");
-
+       opts = getopt32(argv, "+"IF_FEATURE_SETPRIV_DUMP("d"));
        argv += optind;
 
+#if ENABLE_FEATURE_SETPRIV_DUMP
+       if (opts & OPT_DUMP) {
+               if (argv[0] || (opts - OPT_DUMP) != 0)
+                       bb_show_usage();
+               return dump();
+       }
+#endif
        if (opts & OPT_NNP) {
                if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
                        bb_simple_perror_msg_and_die("prctl: NO_NEW_PRIVS");