(root)/
util-linux-2.39/
sys-utils/
setpriv.c
       1  /*
       2   * setpriv(1) - set various kernel privilege bits and run something
       3   *
       4   * Copyright (C) 2012 Andy Lutomirski <luto@amacapital.net>
       5   *
       6   * This program is free software; you can redistribute it and/or modify it
       7   * under the terms of the GNU General Public License as published by the
       8   * Free Software Foundation; either version 2, or (at your option) any
       9   * later version.
      10   *
      11   * This program is distributed in the hope that it will be useful, but
      12   * WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU General Public License along
      17   * with this program; if not, write to the Free Software Foundation, Inc.,
      18   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19   */
      20  
      21  #include <cap-ng.h>
      22  #include <errno.h>
      23  #include <getopt.h>
      24  #include <grp.h>
      25  #include <linux/securebits.h>
      26  #include <pwd.h>
      27  #include <stdarg.h>
      28  #include <stdio.h>
      29  #include <stdlib.h>
      30  #include <sys/prctl.h>
      31  #include <sys/types.h>
      32  #include <unistd.h>
      33  
      34  #include "c.h"
      35  #include "caputils.h"
      36  #include "closestream.h"
      37  #include "nls.h"
      38  #include "optutils.h"
      39  #include "strutils.h"
      40  #include "xalloc.h"
      41  #include "pathnames.h"
      42  #include "signames.h"
      43  #include "env.h"
      44  
      45  #ifndef PR_SET_NO_NEW_PRIVS
      46  # define PR_SET_NO_NEW_PRIVS 38
      47  #endif
      48  #ifndef PR_GET_NO_NEW_PRIVS
      49  # define PR_GET_NO_NEW_PRIVS 39
      50  #endif
      51  
      52  #define SETPRIV_EXIT_PRIVERR 127	/* how we exit when we fail to set privs */
      53  
      54  /* The shell to set SHELL env.variable if none is given in the user's passwd entry.  */
      55  #define DEFAULT_SHELL "/bin/sh"
      56  
      57  static gid_t get_group(const char *s, const char *err);
      58  
      59  enum cap_type {
      60  	CAP_TYPE_EFFECTIVE   = CAPNG_EFFECTIVE,
      61  	CAP_TYPE_PERMITTED   = CAPNG_PERMITTED,
      62  	CAP_TYPE_INHERITABLE = CAPNG_INHERITABLE,
      63  	CAP_TYPE_BOUNDING    = CAPNG_BOUNDING_SET,
      64  	CAP_TYPE_AMBIENT     = (1 << 4)
      65  };
      66  
      67  /*
      68   * Note: We are subject to https://bugzilla.redhat.com/show_bug.cgi?id=895105
      69   * and we will therefore have problems if new capabilities are added.  Once
      70   * that bug is fixed, I'll (Andy Lutomirski) submit a corresponding fix to
      71   * setpriv.  In the mean time, the code here tries to work reasonably well.
      72   */
      73  
      74  struct privctx {
      75  	unsigned int
      76  		nnp:1,			/* no_new_privs */
      77  		have_ruid:1,		/* real uid */
      78  		have_euid:1,		/* effective uid */
      79  		have_rgid:1,		/* real gid */
      80  		have_egid:1,		/* effective gid */
      81  		have_passwd:1,		/* passwd entry */
      82  		have_groups:1,		/* add groups */
      83  		keep_groups:1,		/* keep groups */
      84  		clear_groups:1,		/* remove groups */
      85  		init_groups:1,		/* initialize groups */
      86  		reset_env:1,		/* reset environment */
      87  		have_securebits:1;	/* remove groups */
      88  
      89  	/* uids and gids */
      90  	uid_t ruid, euid;
      91  	gid_t rgid, egid;
      92  
      93  	/* real user passwd entry */
      94  	struct passwd passwd;
      95  
      96  	/* supplementary groups */
      97  	size_t num_groups;
      98  	gid_t *groups;
      99  
     100  	/* caps */
     101  	const char *caps_to_inherit;
     102  	const char *ambient_caps;
     103  	const char *bounding_set;
     104  
     105  	/* securebits */
     106  	int securebits;
     107  	/* parent death signal (<0 clear, 0 nothing, >0 signal) */
     108  	int pdeathsig;
     109  
     110  	/* LSMs */
     111  	const char *selinux_label;
     112  	const char *apparmor_profile;
     113  };
     114  
     115  static void __attribute__((__noreturn__)) usage(void)
     116  {
     117  	FILE *out = stdout;
     118  	fputs(USAGE_HEADER, out);
     119  	fprintf(out, _(" %s [options] <program> [<argument>...]\n"),
     120  		program_invocation_short_name);
     121  
     122  	fputs(USAGE_SEPARATOR, out);
     123  	fputs(_("Run a program with different privilege settings.\n"), out);
     124  
     125  	fputs(USAGE_OPTIONS, out);
     126  	fputs(_(" -d, --dump                  show current state (and do not exec)\n"), out);
     127  	fputs(_(" --nnp, --no-new-privs       disallow granting new privileges\n"), out);
     128  	fputs(_(" --ambient-caps <caps,...>   set ambient capabilities\n"), out);
     129  	fputs(_(" --inh-caps <caps,...>       set inheritable capabilities\n"), out);
     130  	fputs(_(" --bounding-set <caps>       set capability bounding set\n"), out);
     131  	fputs(_(" --ruid <uid|user>           set real uid\n"), out);
     132  	fputs(_(" --euid <uid|user>           set effective uid\n"), out);
     133  	fputs(_(" --rgid <gid|user>           set real gid\n"), out);
     134  	fputs(_(" --egid <gid|group>          set effective gid\n"), out);
     135  	fputs(_(" --reuid <uid|user>          set real and effective uid\n"), out);
     136  	fputs(_(" --regid <gid|group>         set real and effective gid\n"), out);
     137  	fputs(_(" --clear-groups              clear supplementary groups\n"), out);
     138  	fputs(_(" --keep-groups               keep supplementary groups\n"), out);
     139  	fputs(_(" --init-groups               initialize supplementary groups\n"), out);
     140  	fputs(_(" --groups <group,...>        set supplementary groups by UID or name\n"), out);
     141  	fputs(_(" --securebits <bits>         set securebits\n"), out);
     142  	fputs(_(" --pdeathsig keep|clear|<signame>\n"
     143  	        "                             set or clear parent death signal\n"), out);
     144  	fputs(_(" --selinux-label <label>     set SELinux label\n"), out);
     145  	fputs(_(" --apparmor-profile <pr>     set AppArmor profile\n"), out);
     146  	fputs(_(" --reset-env                 clear all environment and initialize\n"
     147  		"                               HOME, SHELL, USER, LOGNAME and PATH\n"), out);
     148  
     149  	fputs(USAGE_SEPARATOR, out);
     150  	printf(USAGE_HELP_OPTIONS(29));
     151  	fputs(USAGE_SEPARATOR, out);
     152  	fputs(_(" This tool can be dangerous.  Read the manpage, and be careful.\n"), out);
     153  	printf(USAGE_MAN_TAIL("setpriv(1)"));
     154  
     155  	exit(EXIT_SUCCESS);
     156  }
     157  
     158  static int has_cap(enum cap_type which, unsigned int i)
     159  {
     160  	switch (which) {
     161  	case CAP_TYPE_EFFECTIVE:
     162  	case CAP_TYPE_BOUNDING:
     163  	case CAP_TYPE_INHERITABLE:
     164  	case CAP_TYPE_PERMITTED:
     165  		return capng_have_capability((capng_type_t)which, i);
     166  	case CAP_TYPE_AMBIENT:
     167  		return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET,
     168  				(unsigned long) i, 0UL, 0UL);
     169  	default:
     170  		warnx(_("invalid capability type"));
     171  		return -1;
     172  	}
     173  }
     174  
     175  /* Returns the number of capabilities printed. */
     176  static int print_caps(FILE *f, enum cap_type which)
     177  {
     178  	int i, n = 0, max = cap_last_cap();
     179  
     180  	for (i = 0; i <= max; i++) {
     181  		int ret = has_cap(which, i);
     182  
     183  		if (i == 0 && ret < 0)
     184  			return -1;
     185  
     186  		if (ret == 1) {
     187  			const char *name = capng_capability_to_name(i);
     188  			if (n)
     189  				fputc(',', f);
     190  			if (name)
     191  				fputs(name, f);
     192  			else
     193  				warnx(_("cap %d: libcap-ng is broken"), i);
     194  			n++;
     195  		}
     196  	}
     197  
     198  	return n;
     199  }
     200  
     201  static void dump_one_secbit(int *first, int *bits, int bit, const char *name)
     202  {
     203  	if (*bits & bit) {
     204  		if (*first)
     205  			*first = 0;
     206  		else
     207  			printf(",");
     208  		fputs(name, stdout);
     209  		*bits &= ~bit;
     210  	}
     211  }
     212  
     213  static void dump_securebits(void)
     214  {
     215  	int first = 1;
     216  	int bits = prctl(PR_GET_SECUREBITS, 0, 0, 0, 0);
     217  
     218  	if (bits < 0) {
     219  		warnx(_("getting process secure bits failed"));
     220  		return;
     221  	}
     222  
     223  	printf(_("Securebits: "));
     224  
     225  	dump_one_secbit(&first, &bits, SECBIT_NOROOT, "noroot");
     226  	dump_one_secbit(&first, &bits, SECBIT_NOROOT_LOCKED, "noroot_locked");
     227  	dump_one_secbit(&first, &bits, SECBIT_NO_SETUID_FIXUP,
     228  			"no_setuid_fixup");
     229  	dump_one_secbit(&first, &bits, SECBIT_NO_SETUID_FIXUP_LOCKED,
     230  			"no_setuid_fixup_locked");
     231  	bits &= ~SECBIT_KEEP_CAPS;
     232  	dump_one_secbit(&first, &bits, SECBIT_KEEP_CAPS_LOCKED,
     233  			"keep_caps_locked");
     234  	if (bits) {
     235  		if (first)
     236  			first = 0;
     237  		else
     238  			printf(",");
     239  		printf("0x%x", (unsigned)bits);
     240  	}
     241  
     242  	if (first)
     243  		printf(_("[none]\n"));
     244  	else
     245  		printf("\n");
     246  }
     247  
     248  static void dump_label(const char *name)
     249  {
     250  	char buf[4097];
     251  	ssize_t len;
     252  	int fd, e;
     253  
     254  	fd = open(_PATH_PROC_ATTR_CURRENT, O_RDONLY);
     255  	if (fd == -1) {
     256  		warn(_("cannot open %s"), _PATH_PROC_ATTR_CURRENT);
     257  		return;
     258  	}
     259  
     260  	len = read(fd, buf, sizeof(buf));
     261  	e = errno;
     262  	close(fd);
     263  	if (len < 0) {
     264  		errno = e;
     265  		warn(_("cannot read %s"), name);
     266  		return;
     267  	}
     268  	if (sizeof(buf) - 1 <= (size_t)len) {
     269  		warnx(_("%s: too long"), name);
     270  		return;
     271  	}
     272  
     273  	buf[len] = 0;
     274  	if (0 < len && buf[len - 1] == '\n')
     275  		buf[len - 1] = 0;
     276  	printf("%s: %s\n", name, buf);
     277  }
     278  
     279  static void dump_groups(void)
     280  {
     281  	int n = getgroups(0, NULL);
     282  	gid_t *groups;
     283  
     284  	if (n < 0) {
     285  		warn("getgroups failed");
     286  		return;
     287  	}
     288  
     289  	groups = xmalloc(n * sizeof(gid_t));
     290  	n = getgroups(n, groups);
     291  	if (n < 0) {
     292  		free(groups);
     293  		warn("getgroups failed");
     294  		return;
     295  	}
     296  
     297  	printf(_("Supplementary groups: "));
     298  	if (n == 0)
     299  		printf(_("[none]"));
     300  	else {
     301  		int i;
     302  		for (i = 0; i < n; i++) {
     303  			if (0 < i)
     304  				printf(",");
     305  			printf("%ld", (long)groups[i]);
     306  		}
     307  	}
     308  	printf("\n");
     309  	free(groups);
     310  }
     311  
     312  static void dump_pdeathsig(void)
     313  {
     314  	int pdeathsig;
     315  
     316  	if (prctl(PR_GET_PDEATHSIG, &pdeathsig) != 0) {
     317  		warn(_("get pdeathsig failed"));
     318  		return;
     319  	}
     320  
     321  	printf(_("Parent death signal: "));
     322  	if (pdeathsig && signum_to_signame(pdeathsig) != NULL)
     323  		printf("%s\n", signum_to_signame(pdeathsig));
     324  	else if (pdeathsig)
     325  		printf("%d\n", pdeathsig);
     326  	else
     327  		printf(_("[none]\n"));
     328  }
     329  
     330  static void dump(int dumplevel)
     331  {
     332  	int x;
     333  	uid_t ru, eu, su;
     334  	gid_t rg, eg, sg;
     335  
     336  	if (getresuid(&ru, &eu, &su) == 0) {
     337  		printf(_("uid: %u\n"), ru);
     338  		printf(_("euid: %u\n"), eu);
     339  		/* Saved and fs uids always equal euid. */
     340  		if (3 <= dumplevel)
     341  			printf(_("suid: %u\n"), su);
     342  	} else
     343  		warn(_("getresuid failed"));
     344  
     345  	if (getresgid(&rg, &eg, &sg) == 0) {
     346  		printf("gid: %ld\n", (long)rg);
     347  		printf("egid: %ld\n", (long)eg);
     348  		/* Saved and fs gids always equal egid. */
     349  		if (dumplevel >= 3)
     350  			printf("sgid: %ld\n", (long)sg);
     351  	} else
     352  		warn(_("getresgid failed"));
     353  
     354  	dump_groups();
     355  
     356  	x = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
     357  	if (0 <= x)
     358  		printf("no_new_privs: %d\n", x);
     359  	else
     360  		warn("setting no_new_privs failed");
     361  
     362  	if (2 <= dumplevel) {
     363  		printf(_("Effective capabilities: "));
     364  		if (print_caps(stdout, CAP_TYPE_EFFECTIVE) == 0)
     365  			printf(_("[none]"));
     366  		printf("\n");
     367  
     368  		printf(_("Permitted capabilities: "));
     369  		if (print_caps(stdout, CAP_TYPE_PERMITTED) == 0)
     370  			printf(_("[none]"));
     371  		printf("\n");
     372  	}
     373  
     374  	printf(_("Inheritable capabilities: "));
     375  	if (print_caps(stdout, CAP_TYPE_INHERITABLE) == 0)
     376  		printf(_("[none]"));
     377  	printf("\n");
     378  
     379  	printf(_("Ambient capabilities: "));
     380  	x = print_caps(stdout, CAP_TYPE_AMBIENT);
     381  	if (x == 0)
     382  		printf(_("[none]"));
     383  	if (x < 0)
     384  		printf(_("[unsupported]"));
     385  	printf("\n");
     386  
     387  	printf(_("Capability bounding set: "));
     388  	if (print_caps(stdout, CAP_TYPE_BOUNDING) == 0)
     389  		printf(_("[none]"));
     390  	printf("\n");
     391  
     392  	dump_securebits();
     393  	dump_pdeathsig();
     394  
     395  	if (access(_PATH_SYS_SELINUX, F_OK) == 0)
     396  		dump_label(_("SELinux label"));
     397  
     398  	if (access(_PATH_SYS_APPARMOR, F_OK) == 0) {
     399  		dump_label(_("AppArmor profile"));
     400  	}
     401  }
     402  
     403  static void list_known_caps(void)
     404  {
     405  	int i, max = cap_last_cap();
     406  
     407  	for (i = 0; i <= max; i++) {
     408  		const char *name = capng_capability_to_name(i);
     409  		if (name)
     410  			printf("%s\n", name);
     411  		else
     412  			warnx(_("cap %d: libcap-ng is broken"), i);
     413  	}
     414  }
     415  
     416  static void parse_groups(struct privctx *opts, const char *str)
     417  {
     418  	char *groups = xstrdup(str);
     419  	char *buf = groups;	/* We'll reuse it */
     420  	char *c;
     421  	size_t i = 0;
     422  
     423  	opts->have_groups = 1;
     424  	opts->num_groups = 0;
     425  	while ((c = strsep(&groups, ",")))
     426  		opts->num_groups++;
     427  
     428  	/* Start again */
     429  	strcpy(buf, str);	/* It's exactly the right length */
     430  	groups = buf;
     431  
     432  	opts->groups = xcalloc(opts->num_groups, sizeof(gid_t));
     433  	while ((c = strsep(&groups, ",")))
     434  		opts->groups[i++] = get_group(c, _("Invalid supplementary group id"));
     435  
     436  	free(groups);
     437  }
     438  
     439  static void parse_pdeathsig(struct privctx *opts, const char *str)
     440  {
     441  	if (!strcmp(str, "keep")) {
     442  		if (prctl(PR_GET_PDEATHSIG, &opts->pdeathsig) != 0)
     443  			errx(SETPRIV_EXIT_PRIVERR,
     444  				 _("failed to get parent death signal"));
     445  	} else if (!strcmp(str, "clear")) {
     446  		opts->pdeathsig = -1;
     447  	} else if ((opts->pdeathsig = signame_to_signum(str)) < 0) {
     448  		errx(EXIT_FAILURE, _("unknown signal: %s"), str);
     449  	}
     450  }
     451  
     452  static void do_setresuid(const struct privctx *opts)
     453  {
     454  	uid_t ruid, euid, suid;
     455  	if (getresuid(&ruid, &euid, &suid) != 0)
     456  		err(SETPRIV_EXIT_PRIVERR, _("getresuid failed"));
     457  	if (opts->have_ruid)
     458  		ruid = opts->ruid;
     459  	if (opts->have_euid)
     460  		euid = opts->euid;
     461  
     462  	/* Also copy effective to saved (for paranoia). */
     463  	if (setresuid(ruid, euid, euid) != 0)
     464  		err(SETPRIV_EXIT_PRIVERR, _("setresuid failed"));
     465  }
     466  
     467  static void do_setresgid(const struct privctx *opts)
     468  {
     469  	gid_t rgid, egid, sgid;
     470  	if (getresgid(&rgid, &egid, &sgid) != 0)
     471  		err(SETPRIV_EXIT_PRIVERR, _("getresgid failed"));
     472  	if (opts->have_rgid)
     473  		rgid = opts->rgid;
     474  	if (opts->have_egid)
     475  		egid = opts->egid;
     476  
     477  	/* Also copy effective to saved (for paranoia). */
     478  	if (setresgid(rgid, egid, egid) != 0)
     479  		err(SETPRIV_EXIT_PRIVERR, _("setresgid failed"));
     480  }
     481  
     482  static void bump_cap(unsigned int cap)
     483  {
     484  	if (capng_have_capability(CAPNG_PERMITTED, cap))
     485  		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, cap);
     486  }
     487  
     488  static int cap_update(capng_act_t action,
     489  		enum cap_type type, unsigned int cap)
     490  {
     491  	switch (type) {
     492  		case CAP_TYPE_EFFECTIVE:
     493  		case CAP_TYPE_BOUNDING:
     494  		case CAP_TYPE_INHERITABLE:
     495  		case CAP_TYPE_PERMITTED:
     496  			return capng_update(action, (capng_type_t) type, cap);
     497  		case CAP_TYPE_AMBIENT:
     498  		{
     499  			int ret;
     500  
     501  			if (action == CAPNG_ADD)
     502  				ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE,
     503  						(unsigned long) cap, 0UL, 0UL);
     504  			else
     505  				ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER,
     506  						(unsigned long) cap, 0UL, 0UL);
     507  
     508  			return ret;
     509  		}
     510  		default:
     511  			errx(EXIT_FAILURE, _("unsupported capability type"));
     512  			return -1;
     513  	}
     514  }
     515  
     516  static void do_caps(enum cap_type type, const char *caps)
     517  {
     518  	char *my_caps = xstrdup(caps);
     519  	char *c;
     520  
     521  	while ((c = strsep(&my_caps, ","))) {
     522  		capng_act_t action;
     523  		if (*c == '+')
     524  			action = CAPNG_ADD;
     525  		else if (*c == '-')
     526  			action = CAPNG_DROP;
     527  		else
     528  			errx(EXIT_FAILURE, _("bad capability string"));
     529  
     530  		if (!strcmp(c + 1, "all")) {
     531  			int i;
     532  			/* We can trust the return value from cap_last_cap(),
     533  			 * so use that directly. */
     534  			for (i = 0; i <= cap_last_cap(); i++)
     535  				cap_update(action, type, i);
     536  		} else {
     537  			int cap = capng_name_to_capability(c + 1);
     538  			if (0 <= cap)
     539  				cap_update(action, type, cap);
     540  			else if (sscanf(c + 1, "cap_%d", &cap) == 1
     541  			    && 0 <= cap && cap <= cap_last_cap())
     542  				cap_update(action, type, cap);
     543  			else
     544  				errx(EXIT_FAILURE,
     545  				     _("unknown capability \"%s\""), c + 1);
     546  		}
     547  	}
     548  
     549  	free(my_caps);
     550  }
     551  
     552  static void parse_securebits(struct privctx *opts, const char *arg)
     553  {
     554  	char *buf = xstrdup(arg);
     555  	char *c;
     556  
     557  	opts->have_securebits = 1;
     558  	opts->securebits = prctl(PR_GET_SECUREBITS, 0, 0, 0, 0);
     559  	if (opts->securebits < 0)
     560  		err(SETPRIV_EXIT_PRIVERR, _("getting process secure bits failed"));
     561  
     562  	if (opts->securebits & ~(int)(SECBIT_NOROOT |
     563  				      SECBIT_NOROOT_LOCKED |
     564  				      SECBIT_NO_SETUID_FIXUP |
     565  				      SECBIT_NO_SETUID_FIXUP_LOCKED |
     566  				      SECBIT_KEEP_CAPS |
     567  				      SECBIT_KEEP_CAPS_LOCKED))
     568  		errx(SETPRIV_EXIT_PRIVERR,
     569  		     _("unrecognized securebit set -- refusing to adjust"));
     570  
     571  	while ((c = strsep(&buf, ","))) {
     572  		if (*c != '+' && *c != '-')
     573  			errx(EXIT_FAILURE, _("bad securebits string"));
     574  
     575  		if (!strcmp(c + 1, "all")) {
     576  			if (*c == '-')
     577  				opts->securebits = 0;
     578  			else
     579  				errx(EXIT_FAILURE,
     580  				     _("+all securebits is not allowed"));
     581  		} else {
     582  			int bit;
     583  			if (!strcmp(c + 1, "noroot"))
     584  				bit = SECBIT_NOROOT;
     585  			else if (!strcmp(c + 1, "noroot_locked"))
     586  				bit = SECBIT_NOROOT_LOCKED;
     587  			else if (!strcmp(c + 1, "no_setuid_fixup"))
     588  				bit = SECBIT_NO_SETUID_FIXUP;
     589  			else if (!strcmp(c + 1, "no_setuid_fixup_locked"))
     590  				bit = SECBIT_NO_SETUID_FIXUP_LOCKED;
     591  			else if (!strcmp(c + 1, "keep_caps"))
     592  				errx(EXIT_FAILURE,
     593  				     _("adjusting keep_caps does not make sense"));
     594  			else if (!strcmp(c + 1, "keep_caps_locked"))
     595  				bit = SECBIT_KEEP_CAPS_LOCKED;	/* sigh */
     596  			else
     597  				errx(EXIT_FAILURE, _("unrecognized securebit"));
     598  
     599  			if (*c == '+')
     600  				opts->securebits |= bit;
     601  			else
     602  				opts->securebits &= ~bit;
     603  		}
     604  	}
     605  
     606  	opts->securebits |= SECBIT_KEEP_CAPS;	/* We need it, and it's reset on exec */
     607  
     608  	free(buf);
     609  }
     610  
     611  static void do_selinux_label(const char *label)
     612  {
     613  	int fd;
     614  	size_t len;
     615  
     616  	if (access(_PATH_SYS_SELINUX, F_OK) != 0)
     617  		errx(SETPRIV_EXIT_PRIVERR, _("SELinux is not running"));
     618  
     619  	fd = open(_PATH_PROC_ATTR_EXEC, O_RDWR);
     620  	if (fd == -1)
     621  		err(SETPRIV_EXIT_PRIVERR,
     622  		    _("cannot open %s"), _PATH_PROC_ATTR_EXEC);
     623  
     624  	len = strlen(label);
     625  	errno = 0;
     626  	if (write(fd, label, len) != (ssize_t) len)
     627  		err(SETPRIV_EXIT_PRIVERR,
     628  		    _("write failed: %s"), _PATH_PROC_ATTR_EXEC);
     629  
     630  	if (close(fd) != 0)
     631  		err(SETPRIV_EXIT_PRIVERR,
     632  		    _("close failed: %s"), _PATH_PROC_ATTR_EXEC);
     633  }
     634  
     635  static void do_apparmor_profile(const char *label)
     636  {
     637  	FILE *f;
     638  
     639  	if (access(_PATH_SYS_APPARMOR, F_OK) != 0)
     640  		errx(SETPRIV_EXIT_PRIVERR, _("AppArmor is not running"));
     641  
     642  	f = fopen(_PATH_PROC_ATTR_EXEC, "r+");
     643  	if (!f)
     644  		err(SETPRIV_EXIT_PRIVERR,
     645  		    _("cannot open %s"), _PATH_PROC_ATTR_EXEC);
     646  
     647  	fprintf(f, "exec %s", label);
     648  
     649  	if (close_stream(f) != 0)
     650  		err(SETPRIV_EXIT_PRIVERR,
     651  		    _("write failed: %s"), _PATH_PROC_ATTR_EXEC);
     652  }
     653  
     654  
     655  static void do_reset_environ(struct passwd *pw)
     656  {
     657  	char *term = getenv("TERM");
     658  
     659  	if (term)
     660  		term = xstrdup(term);
     661  #ifdef HAVE_CLEARENV
     662  	clearenv();
     663  #else
     664  	environ = NULL;
     665  #endif
     666  	if (term) {
     667  		xsetenv("TERM", term, 1);
     668  		free(term);
     669  	}
     670  
     671  	if (pw->pw_shell && *pw->pw_shell)
     672  		xsetenv("SHELL", pw->pw_shell, 1);
     673  	else
     674  		xsetenv("SHELL", DEFAULT_SHELL, 1);
     675  
     676  	xsetenv("HOME", pw->pw_dir, 1);
     677  	xsetenv("USER", pw->pw_name, 1);
     678  	xsetenv("LOGNAME", pw->pw_name, 1);
     679  
     680  	if (pw->pw_uid)
     681  		xsetenv("PATH", _PATH_DEFPATH, 1);
     682  	else
     683  		xsetenv("PATH", _PATH_DEFPATH_ROOT, 1);
     684  }
     685  
     686  static uid_t get_user(const char *s, const char *err)
     687  {
     688  	struct passwd *pw;
     689  	long tmp;
     690  	pw = getpwnam(s);
     691  	if (pw)
     692  		return pw->pw_uid;
     693  	tmp = strtol_or_err(s, err);
     694  	return tmp;
     695  }
     696  
     697  static gid_t get_group(const char *s, const char *err)
     698  {
     699  	struct group *gr;
     700  	long tmp;
     701  	gr = getgrnam(s);
     702  	if (gr)
     703  		return gr->gr_gid;
     704  	tmp = strtol_or_err(s, err);
     705  	return tmp;
     706  }
     707  
     708  static struct passwd *get_passwd(const char *s, uid_t *uid, const char *err)
     709  {
     710  	struct passwd *pw;
     711  	long tmp;
     712  	pw = getpwnam(s);
     713  	if (pw) {
     714  		*uid = pw->pw_uid;
     715  	} else {
     716  		tmp = strtol_or_err(s, err);
     717  		*uid = tmp;
     718  		pw = getpwuid(*uid);
     719  	}
     720  	return pw;
     721  }
     722  
     723  static struct passwd *passwd_copy(struct passwd *dst, const struct passwd *src)
     724  {
     725  	struct passwd *rv;
     726  	rv = memcpy(dst, src, sizeof(*dst));
     727  	rv->pw_name = xstrdup(rv->pw_name);
     728  	rv->pw_passwd = xstrdup(rv->pw_passwd);
     729  	rv->pw_gecos = xstrdup(rv->pw_gecos);
     730  	rv->pw_dir = xstrdup(rv->pw_dir);
     731  	rv->pw_shell = xstrdup(rv->pw_shell);
     732  	return rv;
     733  }
     734  
     735  int main(int argc, char **argv)
     736  {
     737  	enum {
     738  		NNP = CHAR_MAX + 1,
     739  		RUID,
     740  		EUID,
     741  		RGID,
     742  		EGID,
     743  		REUID,
     744  		REGID,
     745  		CLEAR_GROUPS,
     746  		KEEP_GROUPS,
     747  		INIT_GROUPS,
     748  		GROUPS,
     749  		INHCAPS,
     750  		AMBCAPS,
     751  		LISTCAPS,
     752  		CAPBSET,
     753  		SECUREBITS,
     754  		PDEATHSIG,
     755  		SELINUX_LABEL,
     756  		APPARMOR_PROFILE,
     757  		RESET_ENV
     758  	};
     759  
     760  	static const struct option longopts[] = {
     761  		{ "dump",             no_argument,       NULL, 'd'              },
     762  		{ "nnp",              no_argument,       NULL, NNP              },
     763  		{ "no-new-privs",     no_argument,       NULL, NNP              },
     764  		{ "inh-caps",         required_argument, NULL, INHCAPS          },
     765  		{ "ambient-caps",     required_argument, NULL, AMBCAPS          },
     766  		{ "list-caps",        no_argument,       NULL, LISTCAPS         },
     767  		{ "ruid",             required_argument, NULL, RUID             },
     768  		{ "euid",             required_argument, NULL, EUID             },
     769  		{ "rgid",             required_argument, NULL, RGID             },
     770  		{ "egid",             required_argument, NULL, EGID             },
     771  		{ "reuid",            required_argument, NULL, REUID            },
     772  		{ "regid",            required_argument, NULL, REGID            },
     773  		{ "clear-groups",     no_argument,       NULL, CLEAR_GROUPS     },
     774  		{ "keep-groups",      no_argument,       NULL, KEEP_GROUPS      },
     775  		{ "init-groups",      no_argument,       NULL, INIT_GROUPS      },
     776  		{ "groups",           required_argument, NULL, GROUPS           },
     777  		{ "bounding-set",     required_argument, NULL, CAPBSET          },
     778  		{ "securebits",       required_argument, NULL, SECUREBITS       },
     779  		{ "pdeathsig",        required_argument, NULL, PDEATHSIG,       },
     780  		{ "selinux-label",    required_argument, NULL, SELINUX_LABEL    },
     781  		{ "apparmor-profile", required_argument, NULL, APPARMOR_PROFILE },
     782  		{ "help",             no_argument,       NULL, 'h'              },
     783  		{ "reset-env",        no_argument,       NULL, RESET_ENV,       },
     784  		{ "version",          no_argument,       NULL, 'V'              },
     785  		{ NULL, 0, NULL, 0 }
     786  	};
     787  
     788  	static const ul_excl_t excl[] = {
     789  		/* keep in same order with enum definitions */
     790  		{CLEAR_GROUPS, KEEP_GROUPS, INIT_GROUPS, GROUPS},
     791  		{0}
     792  	};
     793  	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
     794  
     795  	int c;
     796  	struct privctx opts;
     797  	struct passwd *pw = NULL;
     798  	int dumplevel = 0;
     799  	int total_opts = 0;
     800  	int list_caps = 0;
     801  
     802  	setlocale(LC_ALL, "");
     803  	bindtextdomain(PACKAGE, LOCALEDIR);
     804  	textdomain(PACKAGE);
     805  	close_stdout_atexit();
     806  
     807  	memset(&opts, 0, sizeof(opts));
     808  
     809  	while ((c = getopt_long(argc, argv, "+dhV", longopts, NULL)) != -1) {
     810  		err_exclusive_options(c, longopts, excl, excl_st);
     811  		total_opts++;
     812  		switch (c) {
     813  		case 'd':
     814  			dumplevel++;
     815  			break;
     816  		case NNP:
     817  			if (opts.nnp)
     818  				errx(EXIT_FAILURE,
     819  				     _("duplicate --no-new-privs option"));
     820  			opts.nnp = 1;
     821  			break;
     822  		case RUID:
     823  			if (opts.have_ruid)
     824  				errx(EXIT_FAILURE, _("duplicate ruid"));
     825  			opts.have_ruid = 1;
     826  			pw = get_passwd(optarg, &opts.ruid, _("failed to parse ruid"));
     827  			if (pw) {
     828  				passwd_copy(&opts.passwd, pw);
     829  				opts.have_passwd = 1;
     830  			}
     831  			break;
     832  		case EUID:
     833  			if (opts.have_euid)
     834  				errx(EXIT_FAILURE, _("duplicate euid"));
     835  			opts.have_euid = 1;
     836  			opts.euid = get_user(optarg, _("failed to parse euid"));
     837  			break;
     838  		case REUID:
     839  			if (opts.have_ruid || opts.have_euid)
     840  				errx(EXIT_FAILURE, _("duplicate ruid or euid"));
     841  			opts.have_ruid = opts.have_euid = 1;
     842  			pw = get_passwd(optarg, &opts.ruid, _("failed to parse reuid"));
     843  			opts.euid = opts.ruid;
     844  			if (pw) {
     845  				passwd_copy(&opts.passwd, pw);
     846  				opts.have_passwd = 1;
     847  			}
     848  			break;
     849  		case RGID:
     850  			if (opts.have_rgid)
     851  				errx(EXIT_FAILURE, _("duplicate rgid"));
     852  			opts.have_rgid = 1;
     853  			opts.rgid = get_group(optarg, _("failed to parse rgid"));
     854  			break;
     855  		case EGID:
     856  			if (opts.have_egid)
     857  				errx(EXIT_FAILURE, _("duplicate egid"));
     858  			opts.have_egid = 1;
     859  			opts.egid = get_group(optarg, _("failed to parse egid"));
     860  			break;
     861  		case REGID:
     862  			if (opts.have_rgid || opts.have_egid)
     863  				errx(EXIT_FAILURE, _("duplicate rgid or egid"));
     864  			opts.have_rgid = opts.have_egid = 1;
     865  			opts.rgid = opts.egid = get_group(optarg, _("failed to parse regid"));
     866  			break;
     867  		case CLEAR_GROUPS:
     868  			if (opts.clear_groups)
     869  				errx(EXIT_FAILURE,
     870  				     _("duplicate --clear-groups option"));
     871  			opts.clear_groups = 1;
     872  			break;
     873  		case KEEP_GROUPS:
     874  			if (opts.keep_groups)
     875  				errx(EXIT_FAILURE,
     876  				     _("duplicate --keep-groups option"));
     877  			opts.keep_groups = 1;
     878  			break;
     879  		case INIT_GROUPS:
     880  			if (opts.init_groups)
     881  				errx(EXIT_FAILURE,
     882  				     _("duplicate --init-groups option"));
     883  			opts.init_groups = 1;
     884  			break;
     885  		case GROUPS:
     886  			if (opts.have_groups)
     887  				errx(EXIT_FAILURE,
     888  				     _("duplicate --groups option"));
     889  			parse_groups(&opts, optarg);
     890  			break;
     891  		case PDEATHSIG:
     892  			if (opts.pdeathsig)
     893  				errx(EXIT_FAILURE,
     894  				     _("duplicate --keep-pdeathsig option"));
     895  			parse_pdeathsig(&opts, optarg);
     896  			break;
     897  		case LISTCAPS:
     898  			list_caps = 1;
     899  			break;
     900  		case INHCAPS:
     901  			if (opts.caps_to_inherit)
     902  				errx(EXIT_FAILURE,
     903  				     _("duplicate --inh-caps option"));
     904  			opts.caps_to_inherit = optarg;
     905  			break;
     906  		case AMBCAPS:
     907  			if (opts.ambient_caps)
     908  				errx(EXIT_FAILURE,
     909  				     _("duplicate --ambient-caps option"));
     910  			opts.ambient_caps = optarg;
     911  			break;
     912  		case CAPBSET:
     913  			if (opts.bounding_set)
     914  				errx(EXIT_FAILURE,
     915  				     _("duplicate --bounding-set option"));
     916  			opts.bounding_set = optarg;
     917  			break;
     918  		case SECUREBITS:
     919  			if (opts.have_securebits)
     920  				errx(EXIT_FAILURE,
     921  				     _("duplicate --securebits option"));
     922  			parse_securebits(&opts, optarg);
     923  			break;
     924  		case SELINUX_LABEL:
     925  			if (opts.selinux_label)
     926  				errx(EXIT_FAILURE,
     927  				     _("duplicate --selinux-label option"));
     928  			opts.selinux_label = optarg;
     929  			break;
     930  		case APPARMOR_PROFILE:
     931  			if (opts.apparmor_profile)
     932  				errx(EXIT_FAILURE,
     933  				     _("duplicate --apparmor-profile option"));
     934  			opts.apparmor_profile = optarg;
     935  			break;
     936  		case RESET_ENV:
     937  			opts.reset_env = 1;
     938  			break;
     939  
     940  		case 'h':
     941  			usage();
     942  		case 'V':
     943  			print_version(EXIT_SUCCESS);
     944  		default:
     945  			errtryhelp(EXIT_FAILURE);
     946  		}
     947  	}
     948  
     949  	if (dumplevel) {
     950  		if (total_opts != dumplevel || optind < argc)
     951  			errx(EXIT_FAILURE,
     952  			     _("--dump is incompatible with all other options"));
     953  		dump(dumplevel);
     954  		return EXIT_SUCCESS;
     955  	}
     956  
     957  	if (list_caps) {
     958  		if (total_opts != 1 || optind < argc)
     959  			errx(EXIT_FAILURE,
     960  			     _("--list-caps must be specified alone"));
     961  		list_known_caps();
     962  		return EXIT_SUCCESS;
     963  	}
     964  
     965  	if (argc <= optind)
     966  		errx(EXIT_FAILURE, _("No program specified"));
     967  
     968  	if ((opts.have_rgid || opts.have_egid)
     969  	    && !opts.keep_groups && !opts.clear_groups && !opts.init_groups
     970  	    && !opts.have_groups)
     971  		errx(EXIT_FAILURE,
     972  		     _("--[re]gid requires --keep-groups, --clear-groups, --init-groups, or --groups"));
     973  
     974  	if (opts.init_groups && !opts.have_ruid)
     975  		errx(EXIT_FAILURE,
     976  		     _("--init-groups requires --ruid or --reuid"));
     977  
     978  	if (opts.init_groups && !opts.have_passwd)
     979  		errx(EXIT_FAILURE,
     980  		     _("uid %ld not found, --init-groups requires an user that "
     981  		       "can be found on the system"),
     982  		     (long) opts.ruid);
     983  
     984  	if (opts.reset_env) {
     985  		if (opts.have_passwd)
     986  			/* pwd according to --ruid or --reuid */
     987  			pw = &opts.passwd;
     988  		else
     989  			/* pwd for the current user */
     990  			pw = getpwuid(getuid());
     991  		do_reset_environ(pw);
     992  	}
     993  
     994  	if (opts.nnp && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
     995  		err(EXIT_FAILURE, _("disallow granting new privileges failed"));
     996  
     997  	if (opts.selinux_label)
     998  		do_selinux_label(opts.selinux_label);
     999  	if (opts.apparmor_profile)
    1000  		do_apparmor_profile(opts.apparmor_profile);
    1001  
    1002  	if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
    1003  		err(EXIT_FAILURE, _("keep process capabilities failed"));
    1004  
    1005  	/* We're going to want CAP_SETPCAP, CAP_SETUID, and CAP_SETGID if
    1006  	 * possible.  */
    1007  	bump_cap(CAP_SETPCAP);
    1008  	bump_cap(CAP_SETUID);
    1009  	bump_cap(CAP_SETGID);
    1010  	if (capng_apply(CAPNG_SELECT_CAPS) != 0)
    1011  		err(SETPRIV_EXIT_PRIVERR, _("activate capabilities"));
    1012  
    1013  	if (opts.have_ruid || opts.have_euid) {
    1014  		do_setresuid(&opts);
    1015  		/* KEEPCAPS doesn't work for the effective mask. */
    1016  		if (capng_apply(CAPNG_SELECT_CAPS) != 0)
    1017  			err(SETPRIV_EXIT_PRIVERR, _("reactivate capabilities"));
    1018  	}
    1019  
    1020  	if (opts.have_rgid || opts.have_egid)
    1021  		do_setresgid(&opts);
    1022  
    1023  	if (opts.have_groups) {
    1024  		if (setgroups(opts.num_groups, opts.groups) != 0)
    1025  			err(SETPRIV_EXIT_PRIVERR, _("setgroups failed"));
    1026  	} else if (opts.init_groups) {
    1027  		if (initgroups(opts.passwd.pw_name, opts.passwd.pw_gid) != 0)
    1028  			err(SETPRIV_EXIT_PRIVERR, _("initgroups failed"));
    1029  	} else if (opts.clear_groups) {
    1030  		gid_t x = 0;
    1031  		if (setgroups(0, &x) != 0)
    1032  			err(SETPRIV_EXIT_PRIVERR, _("setgroups failed"));
    1033  	}
    1034  
    1035  	if (opts.have_securebits && prctl(PR_SET_SECUREBITS, opts.securebits, 0, 0, 0) != 0)
    1036  		err(SETPRIV_EXIT_PRIVERR, _("set process securebits failed"));
    1037  
    1038  	if (opts.bounding_set) {
    1039  		do_caps(CAP_TYPE_BOUNDING, opts.bounding_set);
    1040  		errno = EPERM;	/* capng doesn't set errno if we're missing CAP_SETPCAP */
    1041  		if (capng_apply(CAPNG_SELECT_BOUNDS) != 0)
    1042  			err(SETPRIV_EXIT_PRIVERR, _("apply bounding set"));
    1043  	}
    1044  
    1045  	if (opts.caps_to_inherit) {
    1046  		do_caps(CAP_TYPE_INHERITABLE, opts.caps_to_inherit);
    1047  		if (capng_apply(CAPNG_SELECT_CAPS) != 0)
    1048  			err(SETPRIV_EXIT_PRIVERR, _("apply capabilities"));
    1049  	}
    1050  
    1051  	if (opts.ambient_caps) {
    1052  		do_caps(CAP_TYPE_AMBIENT, opts.ambient_caps);
    1053  	}
    1054  
    1055  	/* Clear or set parent death signal */
    1056  	if (opts.pdeathsig && prctl(PR_SET_PDEATHSIG, opts.pdeathsig < 0 ? 0 : opts.pdeathsig) != 0)
    1057  		err(SETPRIV_EXIT_PRIVERR, _("set parent death signal failed"));
    1058  
    1059  	execvp(argv[optind], argv + optind);
    1060  	errexec(argv[optind]);
    1061  }