All of lore.kernel.org
 help / color / mirror / Atom feed
From: yumkam@gmail.com (Yuriy M. Kaminskiy)
To: util-linux@vger.kernel.org
Subject: Re: [PATCH] setpriv: Add --init-groups option
Date: Wed, 31 May 2017 22:46:05 +0300	[thread overview]
Message-ID: <m3mv9sernm.fsf@gmail.com> (raw)
In-Reply-To: 20170531160117.27803-1-sebastian.schrader@ossmail.de

Sebastian Schrader
<sebastian.schrader@ossmail.de> writes:

> Add an --init-groups option which initializes the supplementary groups
> from the system's group database (e.g /etc/group) using initgroups(3).
> ---
>  sys-utils/setpriv.1 |  8 +++++++
>  sys-utils/setpriv.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 66 insertions(+), 5 deletions(-)
>
> diff --git a/sys-utils/setpriv.1 b/sys-utils/setpriv.1
> index bf18fe050..be97c0799 100644
> --- a/sys-utils/setpriv.1
> +++ b/sys-utils/setpriv.1
> @@ -52,6 +52,14 @@ Preserve supplementary groups.  Only useful in conjunction with
>  .BR \-\-egid ", or"
>  .BR \-\-regid .
>  .TP
> +.B \-\-init\-groups
> +Initialize supplementary groups using
> +.BR initgroups "(3)."
> +Only useful in conjunction with
> +.BR \-\-ruid
> +or
> +.BR \-\-reuid .
> +.TP
>  .BR \-\-list\-caps
>  List all known capabilities.  This option must be specified alone.
>  .TP
> diff --git a/sys-utils/setpriv.c b/sys-utils/setpriv.c
> index 2129115a0..618119385 100644
> --- a/sys-utils/setpriv.c
> +++ b/sys-utils/setpriv.c
> @@ -62,15 +62,20 @@ struct privctx {
>  		have_euid:1,		/* effective uid */
>  		have_rgid:1,		/* real gid */
>  		have_egid:1,		/* effective gid */
> +		have_passwd:1,		/* passwd entry */
>  		have_groups:1,		/* add groups */
>  		keep_groups:1,		/* keep groups */
>  		clear_groups:1,		/* remove groups */
> +		init_groups:1,		/* initialize groups */
>  		have_securebits:1;	/* remove groups */
>  
>  	/* uids and gids */
>  	uid_t ruid, euid;
>  	gid_t rgid, egid;
>  
> +	/* real user passwd entry */
> +	struct passwd passwd;
> +
>  	/* supplementary groups */
>  	size_t num_groups;
>  	gid_t *groups;
> @@ -109,6 +114,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
>  	fputs(_(" --regid <gid>            set real and effective gid\n"), out);
>  	fputs(_(" --clear-groups           clear supplementary groups\n"), out);
>  	fputs(_(" --keep-groups            keep supplementary groups\n"), out);
> +	fputs(_(" --init-groups            initialize supplementary groups\n"), out);
>  	fputs(_(" --groups <group,...>     set supplementary groups\n"), out);
>  	fputs(_(" --securebits <bits>      set securebits\n"), out);
>  	fputs(_(" --selinux-label <label>  set SELinux label\n"), out);
> @@ -580,6 +586,21 @@ static gid_t get_group(const char *s, const char *err)
>  	return tmp;
>  }
>  
> +static struct passwd *get_passwd(const char *s, uid_t *uid, const char *err)
> +{
> +	struct passwd *pw;
> +	long tmp;
> +	pw = getpwnam(s);
> +	if (pw) {
> +		*uid = pw->pw_uid;
> +	} else {
> +		tmp = strtol_or_err(s, err);
> +		*uid = tmp;
> +		pw = getpwuid(*uid);
> +	}
> +	return pw;
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	enum {
> @@ -592,6 +613,7 @@ int main(int argc, char **argv)
>  		REGID,
>  		CLEAR_GROUPS,
>  		KEEP_GROUPS,
> +		INIT_GROUPS,
>  		GROUPS,
>  		INHCAPS,
>  		LISTCAPS,
> @@ -615,6 +637,7 @@ int main(int argc, char **argv)
>  		{ "regid",            required_argument, NULL, REGID            },
>  		{ "clear-groups",     no_argument,       NULL, CLEAR_GROUPS     },
>  		{ "keep-groups",      no_argument,       NULL, KEEP_GROUPS      },
> +		{ "init-groups",      no_argument,       NULL, INIT_GROUPS      },
>  		{ "groups",           required_argument, NULL, GROUPS           },
>  		{ "bounding-set",     required_argument, NULL, CAPBSET          },
>  		{ "securebits",       required_argument, NULL, SECUREBITS       },
> @@ -627,13 +650,14 @@ int main(int argc, char **argv)
>  
>  	static const ul_excl_t excl[] = {
>  		/* keep in same order with enum definitions */
> -		{CLEAR_GROUPS, KEEP_GROUPS, GROUPS},
> +		{CLEAR_GROUPS, KEEP_GROUPS, INIT_GROUPS, GROUPS},
>  		{0}
>  	};
>  	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
>  
>  	int c;
>  	struct privctx opts;
> +	struct passwd *pw = NULL;
>  	int dumplevel = 0;
>  	int total_opts = 0;
>  	int list_caps = 0;
> @@ -662,7 +686,11 @@ int main(int argc, char **argv)
>  			if (opts.have_ruid)
>  				errx(EXIT_FAILURE, _("duplicate ruid"));
>  			opts.have_ruid = 1;
> -			opts.ruid = get_user(optarg, _("failed to parse ruid"));
> +			pw = get_passwd(optarg, &opts.ruid, _("failed to parse ruid"));
> +			if (pw) {
> +				memcpy(&opts.passwd, pw, sizeof(opts.passwd));

This looks somewhat fragile. E.g. with
   setpriv --ruid foo --euid bar ...
second call to getpw{nam,id} can overwrite/free memory pointed by opts.passwd.pw_name

> +				opts.have_passwd = 1;
> +			}
>  			break;
>  		case EUID:
>  			if (opts.have_euid)
> @@ -674,7 +702,12 @@ int main(int argc, char **argv)
>  			if (opts.have_ruid || opts.have_euid)
>  				errx(EXIT_FAILURE, _("duplicate ruid or euid"));
>  			opts.have_ruid = opts.have_euid = 1;
> -			opts.ruid = opts.euid = get_user(optarg, _("failed to parse reuid"));
> +			pw = get_passwd(optarg, &opts.ruid, _("failed to parse reuid"));
> +			opts.euid = opts.ruid;
> +			if (pw) {
> +				memcpy(&opts.passwd, pw, sizeof(opts.passwd));
> +				opts.have_passwd = 1;
> +			}
>  			break;
>  		case RGID:
>  			if (opts.have_rgid)
> @@ -706,6 +739,12 @@ int main(int argc, char **argv)
>  				     _("duplicate --keep-groups option"));
>  			opts.keep_groups = 1;
>  			break;
> +		case INIT_GROUPS:
> +			if (opts.init_groups)
> +				errx(EXIT_FAILURE,
> +				     _("duplicate --init-groups option"));
> +			opts.init_groups = 1;
> +			break;
>  		case GROUPS:
>  			if (opts.have_groups)
>  				errx(EXIT_FAILURE,
> @@ -775,9 +814,20 @@ int main(int argc, char **argv)
>  		errx(EXIT_FAILURE, _("No program specified"));
>  
>  	if ((opts.have_rgid || opts.have_egid)
> -	    && !opts.keep_groups && !opts.clear_groups && !opts.have_groups)
> +	    && !opts.keep_groups && !opts.clear_groups && !opts.init_groups
> +	    && !opts.have_groups)
> +		errx(EXIT_FAILURE,
> +		     _("--[re]gid requires --keep-groups, --clear-groups, --init-groups, or --groups"));
> +
> +	if (opts.init_groups && !opts.have_ruid)
> +		errx(EXIT_FAILURE,
> +		     _("--init-groups requires --ruid or --reuid"));
> +
> +	if (opts.init_groups && !opts.have_passwd)
>  		errx(EXIT_FAILURE,
> -		     _("--[re]gid requires --keep-groups, --clear-groups, or --groups"));
> +		     _("uid %ld not found, --init-groups requires an user that "
> +		       "can be found on the system"),
> +		     (long) opts.ruid);
>  
>  	if (opts.nnp && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
>  		err(EXIT_FAILURE, _("disallow granting new privileges failed"));
> @@ -811,6 +861,9 @@ int main(int argc, char **argv)
>  	if (opts.have_groups) {
>  		if (setgroups(opts.num_groups, opts.groups) != 0)
>  			err(SETPRIV_EXIT_PRIVERR, _("setgroups failed"));
> +	} else if (opts.init_groups) {
> +		if (initgroups(opts.passwd.pw_name, opts.passwd.pw_gid) != 0)
> +			err(SETPRIV_EXIT_PRIVERR, _("initgroups failed"));
>  	} else if (opts.clear_groups) {
>  		gid_t x = 0;
>  		if (setgroups(0, &x) != 0)


  reply	other threads:[~2017-05-31 19:46 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-31 16:01 [PATCH] setpriv: Add --init-groups option Sebastian Schrader
2017-05-31 19:46 ` Yuriy M. Kaminskiy [this message]
2017-06-01 14:52   ` Sebastian Schrader
2017-06-01 14:52     ` Sebastian Schrader
2017-06-05 11:44       ` Karel Zak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m3mv9sernm.fsf@gmail.com \
    --to=yumkam@gmail.com \
    --cc=util-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.