/* * setpriv(1) - set various kernel privilege bits and run something * * Copyright (C) 2012 Andy Lutomirski * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "c.h" #include "closestream.h" #include "nls.h" #include "optutils.h" #include "strutils.h" #include "xalloc.h" #include "pathnames.h" #ifndef PR_SET_NO_NEW_PRIVS # define PR_SET_NO_NEW_PRIVS 38 #endif #ifndef PR_GET_NO_NEW_PRIVS # define PR_GET_NO_NEW_PRIVS 39 #endif #define SETPRIV_EXIT_PRIVERR 127 /* how we exit when we fail to set privs */ /* * Note: We are subject to https://bugzilla.redhat.com/show_bug.cgi?id=895105 * and we will therefore have problems if new capabilities are added. Once * that bug is fixed, I'll (Andy Lutomirski) submit a corresponding fix to * setpriv. In the mean time, the code here tries to work reasonably well. */ struct privctx { unsigned int nnp:1, /* no_new_privs */ have_ruid:1, /* real uid */ have_euid:1, /* effective uid */ have_rgid:1, /* real gid */ have_egid:1, /* effective gid */ have_groups:1, /* add groups */ keep_groups:1, /* keep groups */ clear_groups:1, /* remove groups */ have_securebits:1; /* remove groups */ /* uids and gids */ uid_t ruid, euid; gid_t rgid, egid; /* supplementary groups */ size_t num_groups; gid_t *groups; /* caps */ const char *caps_to_inherit; const char *bounding_set; /* securebits */ int securebits; /* LSMs */ const char *selinux_label; const char *apparmor_profile; }; static void __attribute__((__noreturn__)) usage(FILE *out) { fputs(USAGE_HEADER, out); fprintf(out, _(" %s [options] [...]\n"), program_invocation_short_name); fputs(USAGE_SEPARATOR, out); fputs(_("Run a program with different privilege settings.\n"), out); fputs(USAGE_OPTIONS, out); fputs(_(" -d, --dump show current state (and do not exec anything)\n"), out); fputs(_(" --nnp, --no-new-privs disallow granting new privileges\n"), out); fputs(_(" --inh-caps set inheritable capabilities\n"), out); fputs(_(" --bounding-set set capability bounding set\n"), out); fputs(_(" --ruid set real uid\n"), out); fputs(_(" --euid set effective uid\n"), out); fputs(_(" --rgid set real gid\n"), out); fputs(_(" --egid set effective gid\n"), out); fputs(_(" --reuid set real and effective uid\n"), out); fputs(_(" --regid set real and effective gid\n"), out); fputs(_(" --clear-groups clear supplementary groups\n"), out); fputs(_(" --keep-groups keep supplementary groups\n"), out); fputs(_(" --groups set supplementary groups\n"), out); fputs(_(" --securebits set securebits\n"), out); fputs(_(" --selinux-label