From: ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org (Eric W. Biederman)
To: Josh Triplett <josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
Cc: Andrew Morton
<akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>,
Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>,
mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-man-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
Date: Sat, 15 Nov 2014 09:37:27 -0600 [thread overview]
Message-ID: <87d28osceg.fsf@x220.int.ebiederm.org> (raw)
In-Reply-To: <0895c1f268bc0b01cc6c8ed4607d7c3953f49728.1416041823.git.josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org> (Josh Triplett's message of "Sat, 15 Nov 2014 01:01:02 -0800")
Josh Triplett <josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org> writes:
> Currently, unprivileged processes (without CAP_SETGID) cannot call
> setgroups at all. In particular, processes with a set of supplementary
> groups cannot further drop permissions without obtaining elevated
> permissions first.
>
> Allow unprivileged processes to call setgroups with a subset of their
> current groups; only require CAP_SETGID to add a group the process does
> not currently have.
A couple of questions.
- Is there precedence in other unix flavors for this?
- What motiviates this change?
- Have you looked to see if anything might for bug compatibilty
require applications not to be able to drop supplementary groups?
> The kernel already maintains the list of supplementary group IDs in
> sorted order, and setgroups already needs to sort the new list, so this
> just requires a linear comparison of the two sorted lists.
>
> This moves the CAP_SETGID test from setgroups into set_current_groups.
>
> Tested via the following test program:
>
> #include <err.h>
> #include <grp.h>
> #include <stdio.h>
> #include <sys/types.h>
> #include <unistd.h>
>
> void run_id(void)
> {
> pid_t p = fork();
> switch (p) {
> case -1:
> err(1, "fork");
> case 0:
> execl("/usr/bin/id", "id", NULL);
> err(1, "exec");
> default:
> if (waitpid(p, NULL, 0) < 0)
> err(1, "waitpid");
> }
> }
>
> int main(void)
> {
> gid_t list1[] = { 1, 2, 3, 4, 5 };
> gid_t list2[] = { 2, 3, 4 };
> run_id();
> if (setgroups(5, list1) < 0)
> err(1, "setgroups 1");
> run_id();
> if (setresgid(1, 1, 1) < 0)
> err(1, "setresgid");
> if (setresuid(1, 1, 1) < 0)
> err(1, "setresuid");
> run_id();
> if (setgroups(3, list2) < 0)
> err(1, "setgroups 2");
> run_id();
> if (setgroups(5, list1) < 0)
> err(1, "setgroups 3");
> run_id();
>
> return 0;
> }
>
> Without this patch, the test program gets EPERM from the second
> setgroups call, after dropping root privileges. With this patch, the
> test program successfully drops groups 1 and 5, but then gets EPERM from
> the third setgroups call, since that call attempts to add groups the
> process does not currently have.
>
> Signed-off-by: Josh Triplett <josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
> ---
> kernel/groups.c | 33 ++++++++++++++++++++++++++++++---
> kernel/uid16.c | 2 --
> 2 files changed, 30 insertions(+), 5 deletions(-)
>
> diff --git a/kernel/groups.c b/kernel/groups.c
> index f0667e7..fe7367d 100644
> --- a/kernel/groups.c
> +++ b/kernel/groups.c
> @@ -153,6 +153,29 @@ int groups_search(const struct group_info *group_info, kgid_t grp)
> return 0;
> }
>
> +/* Compare two sorted group lists; return true if the first is a subset of the
> + * second.
> + */
> +static bool is_subset(const struct group_info *g1, const struct group_info *g2)
> +{
> + unsigned int i, j;
> +
> + for (i = 0, j = 0; i < g1->ngroups; i++) {
> + kgid_t gid1 = GROUP_AT(g1, i);
> + kgid_t gid2;
> + for (; j < g2->ngroups; j++) {
> + gid2 = GROUP_AT(g2, j);
> + if (gid_lte(gid1, gid2))
> + break;
> + }
> + if (j >= g2->ngroups || !gid_eq(gid1, gid2))
> + return false;
> + j++;
> + }
> +
> + return true;
> +}
> +
> /**
> * set_groups_sorted - Change a group subscription in a set of credentials
> * @new: The newly prepared set of credentials to alter
> @@ -189,11 +212,17 @@ int set_current_groups(struct group_info *group_info)
> {
> struct cred *new;
>
> + groups_sort(group_info);
> new = prepare_creds();
> if (!new)
> return -ENOMEM;
> + if (!ns_capable(current_user_ns(), CAP_SETGID)
> + && !is_subset(group_info, new->group_info)) {
> + abort_creds(new);
> + return -EPERM;
> + }
>
> - set_groups(new, group_info);
> + set_groups_sorted(new, group_info);
> return commit_creds(new);
> }
>
> @@ -233,8 +262,6 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
> struct group_info *group_info;
> int retval;
>
> - if (!ns_capable(current_user_ns(), CAP_SETGID))
> - return -EPERM;
> if ((unsigned)gidsetsize > NGROUPS_MAX)
> return -EINVAL;
>
> diff --git a/kernel/uid16.c b/kernel/uid16.c
> index 602e5bb..b27e167 100644
> --- a/kernel/uid16.c
> +++ b/kernel/uid16.c
> @@ -176,8 +176,6 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
> struct group_info *group_info;
> int retval;
>
> - if (!ns_capable(current_user_ns(), CAP_SETGID))
> - return -EPERM;
> if ((unsigned)gidsetsize > NGROUPS_MAX)
> return -EINVAL;
WARNING: multiple messages have this Message-ID (diff)
From: ebiederm@xmission.com (Eric W. Biederman)
To: Josh Triplett <josh@joshtriplett.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Kees Cook <keescook@chromium.org>,
mtk.manpages@gmail.com, linux-api@vger.kernel.org,
linux-man@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
Date: Sat, 15 Nov 2014 09:37:27 -0600 [thread overview]
Message-ID: <87d28osceg.fsf@x220.int.ebiederm.org> (raw)
In-Reply-To: <0895c1f268bc0b01cc6c8ed4607d7c3953f49728.1416041823.git.josh@joshtriplett.org> (Josh Triplett's message of "Sat, 15 Nov 2014 01:01:02 -0800")
Josh Triplett <josh@joshtriplett.org> writes:
> Currently, unprivileged processes (without CAP_SETGID) cannot call
> setgroups at all. In particular, processes with a set of supplementary
> groups cannot further drop permissions without obtaining elevated
> permissions first.
>
> Allow unprivileged processes to call setgroups with a subset of their
> current groups; only require CAP_SETGID to add a group the process does
> not currently have.
A couple of questions.
- Is there precedence in other unix flavors for this?
- What motiviates this change?
- Have you looked to see if anything might for bug compatibilty
require applications not to be able to drop supplementary groups?
> The kernel already maintains the list of supplementary group IDs in
> sorted order, and setgroups already needs to sort the new list, so this
> just requires a linear comparison of the two sorted lists.
>
> This moves the CAP_SETGID test from setgroups into set_current_groups.
>
> Tested via the following test program:
>
> #include <err.h>
> #include <grp.h>
> #include <stdio.h>
> #include <sys/types.h>
> #include <unistd.h>
>
> void run_id(void)
> {
> pid_t p = fork();
> switch (p) {
> case -1:
> err(1, "fork");
> case 0:
> execl("/usr/bin/id", "id", NULL);
> err(1, "exec");
> default:
> if (waitpid(p, NULL, 0) < 0)
> err(1, "waitpid");
> }
> }
>
> int main(void)
> {
> gid_t list1[] = { 1, 2, 3, 4, 5 };
> gid_t list2[] = { 2, 3, 4 };
> run_id();
> if (setgroups(5, list1) < 0)
> err(1, "setgroups 1");
> run_id();
> if (setresgid(1, 1, 1) < 0)
> err(1, "setresgid");
> if (setresuid(1, 1, 1) < 0)
> err(1, "setresuid");
> run_id();
> if (setgroups(3, list2) < 0)
> err(1, "setgroups 2");
> run_id();
> if (setgroups(5, list1) < 0)
> err(1, "setgroups 3");
> run_id();
>
> return 0;
> }
>
> Without this patch, the test program gets EPERM from the second
> setgroups call, after dropping root privileges. With this patch, the
> test program successfully drops groups 1 and 5, but then gets EPERM from
> the third setgroups call, since that call attempts to add groups the
> process does not currently have.
>
> Signed-off-by: Josh Triplett <josh@joshtriplett.org>
> ---
> kernel/groups.c | 33 ++++++++++++++++++++++++++++++---
> kernel/uid16.c | 2 --
> 2 files changed, 30 insertions(+), 5 deletions(-)
>
> diff --git a/kernel/groups.c b/kernel/groups.c
> index f0667e7..fe7367d 100644
> --- a/kernel/groups.c
> +++ b/kernel/groups.c
> @@ -153,6 +153,29 @@ int groups_search(const struct group_info *group_info, kgid_t grp)
> return 0;
> }
>
> +/* Compare two sorted group lists; return true if the first is a subset of the
> + * second.
> + */
> +static bool is_subset(const struct group_info *g1, const struct group_info *g2)
> +{
> + unsigned int i, j;
> +
> + for (i = 0, j = 0; i < g1->ngroups; i++) {
> + kgid_t gid1 = GROUP_AT(g1, i);
> + kgid_t gid2;
> + for (; j < g2->ngroups; j++) {
> + gid2 = GROUP_AT(g2, j);
> + if (gid_lte(gid1, gid2))
> + break;
> + }
> + if (j >= g2->ngroups || !gid_eq(gid1, gid2))
> + return false;
> + j++;
> + }
> +
> + return true;
> +}
> +
> /**
> * set_groups_sorted - Change a group subscription in a set of credentials
> * @new: The newly prepared set of credentials to alter
> @@ -189,11 +212,17 @@ int set_current_groups(struct group_info *group_info)
> {
> struct cred *new;
>
> + groups_sort(group_info);
> new = prepare_creds();
> if (!new)
> return -ENOMEM;
> + if (!ns_capable(current_user_ns(), CAP_SETGID)
> + && !is_subset(group_info, new->group_info)) {
> + abort_creds(new);
> + return -EPERM;
> + }
>
> - set_groups(new, group_info);
> + set_groups_sorted(new, group_info);
> return commit_creds(new);
> }
>
> @@ -233,8 +262,6 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
> struct group_info *group_info;
> int retval;
>
> - if (!ns_capable(current_user_ns(), CAP_SETGID))
> - return -EPERM;
> if ((unsigned)gidsetsize > NGROUPS_MAX)
> return -EINVAL;
>
> diff --git a/kernel/uid16.c b/kernel/uid16.c
> index 602e5bb..b27e167 100644
> --- a/kernel/uid16.c
> +++ b/kernel/uid16.c
> @@ -176,8 +176,6 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
> struct group_info *group_info;
> int retval;
>
> - if (!ns_capable(current_user_ns(), CAP_SETGID))
> - return -EPERM;
> if ((unsigned)gidsetsize > NGROUPS_MAX)
> return -EINVAL;
next prev parent reply other threads:[~2014-11-15 15:37 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-15 9:00 [PATCH 1/2] groups: Factor out a function to set a pre-sorted group list Josh Triplett
2014-11-15 9:00 ` Josh Triplett
2014-11-15 9:01 ` [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups Josh Triplett
[not found] ` <0895c1f268bc0b01cc6c8ed4607d7c3953f49728.1416041823.git.josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
2014-11-15 15:37 ` Eric W. Biederman [this message]
2014-11-15 15:37 ` Eric W. Biederman
[not found] ` <87d28osceg.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
2014-11-15 19:29 ` Josh Triplett
2014-11-15 19:29 ` Josh Triplett
2014-11-15 20:06 ` Andy Lutomirski
2014-11-15 20:06 ` Andy Lutomirski
[not found] ` <CALCETrUM=GqsOumTmDMF4B5GS1w=x56t41eE-2xW1bBOfUz02w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-15 20:20 ` Josh Triplett
2014-11-15 20:20 ` Josh Triplett
2014-11-16 2:05 ` Theodore Ts'o
2014-11-16 2:05 ` Theodore Ts'o
[not found] ` <20141116020511.GB5507-AKGzg7BKzIDYtjvyW6yDsg@public.gmane.org>
2014-11-16 2:35 ` Josh Triplett
2014-11-16 2:35 ` Josh Triplett
[not found] ` <6C690A2C-8EB1-421A-94C3-9803AFB95760-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
2014-11-16 3:08 ` Eric W. Biederman
2014-11-16 3:08 ` Eric W. Biederman
[not found] ` <87vbmfq1uw.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
2014-11-16 5:07 ` Josh Triplett
2014-11-16 5:07 ` Josh Triplett
2014-11-16 13:32 ` Theodore Ts'o
2014-11-16 13:32 ` Theodore Ts'o
[not found] ` <20141116133230.GA32030-AKGzg7BKzIDYtjvyW6yDsg@public.gmane.org>
2014-11-16 15:42 ` Andy Lutomirski
2014-11-16 15:42 ` Andy Lutomirski
[not found] ` <CALCETrUPsH_So2Mgk38Fe_pjp5Y+cgjzCUe7fzFcnsFzivHeNA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-16 19:12 ` Josh Triplett
2014-11-16 19:12 ` Josh Triplett
2014-11-16 19:09 ` Josh Triplett
2014-11-16 19:09 ` Josh Triplett
2014-11-16 3:40 ` Theodore Ts'o
2014-11-16 3:40 ` Theodore Ts'o
[not found] ` <20141116034005.GC5507-AKGzg7BKzIDYtjvyW6yDsg@public.gmane.org>
2014-11-16 4:52 ` Josh Triplett
2014-11-16 4:52 ` Josh Triplett
2014-11-17 11:37 ` One Thousand Gnomes
2014-11-17 11:37 ` One Thousand Gnomes
[not found] ` <20141117113734.396798e6-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
2014-11-17 18:07 ` Andy Lutomirski
2014-11-17 18:07 ` Andy Lutomirski
[not found] ` <CALCETrXi1qHyu4_U7cbROB74n461nBZ9R7=0kfhR8-VFAwOF1w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-17 22:11 ` Eric W.Biederman
2014-11-17 22:11 ` Eric W.Biederman
[not found] ` <0b65fd07-48ea-483b-8fd5-fd84d0bff881-2ueSQiBKiTY7tOexoI0I+QC/G2K4zDHf@public.gmane.org>
2014-11-17 22:22 ` Andy Lutomirski
2014-11-17 22:22 ` Andy Lutomirski
[not found] ` <CALCETrWXC5dMOXTTBOiq4Cv+yjqbA_UdmAN-TDmNAJUo+ABxtg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-17 22:37 ` josh-iaAMLnmF4UmaiuxdJuQwMA
2014-11-17 22:37 ` josh
2014-11-18 0:56 ` Casey Schaufler
2014-11-17 18:06 ` Casey Schaufler
[not found] ` <546A3942.5040906-iSGtlc1asvQWG2LlvL+J4A@public.gmane.org>
2014-11-17 18:31 ` Andy Lutomirski
2014-11-17 18:31 ` Andy Lutomirski
2014-11-17 18:46 ` Andy Lutomirski
2014-11-17 18:51 ` Casey Schaufler
[not found] ` <546A43CE.2030706-iSGtlc1asvQWG2LlvL+J4A@public.gmane.org>
2014-11-27 16:59 ` [CFT][PATCH] userns: Avoid problems with negative groups Eric W. Biederman
2014-11-27 16:59 ` Eric W. Biederman
[not found] ` <87lhmwwpey.fsf_-_-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
2014-11-27 20:52 ` Andy Lutomirski
2014-11-27 20:52 ` Andy Lutomirski
2014-11-27 20:52 ` Andy Lutomirski
[not found] ` <CALCETrUuWDq2akKfb50AiPHeDDWzPW7ijz1QwnuNiskyZbBEfA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-28 5:21 ` Eric W. Biederman
2014-11-28 5:21 ` Eric W. Biederman
2014-11-28 5:21 ` Eric W. Biederman
[not found] ` <87wq6frjcw.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
2014-11-28 5:22 ` [CFT][PATCH v2] " Eric W. Biederman
2014-11-28 5:22 ` Eric W. Biederman
2014-11-28 15:11 ` [CFT][PATCH] " Andy Lutomirski
2014-11-28 15:11 ` Andy Lutomirski
2014-11-28 15:11 ` Andy Lutomirski
[not found] ` <CALCETrX2s-7iaLMEKLQsExTEp3JyoAPQG44p0v5wkeED3-6dQA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-28 16:34 ` Eric W. Biederman
2014-11-28 16:34 ` Eric W. Biederman
[not found] ` <874mtjp9m1.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
2014-11-28 17:11 ` Andy Lutomirski
2014-11-28 17:11 ` Andy Lutomirski
2014-11-28 16:34 ` Eric W. Biederman
[not found] ` <CALCETrVn4gVXp7F=5h-bkN5VWuRMG9BoxgeQfKhX4+ZXxGE=wQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-17 22:41 ` [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups Eric W.Biederman
2014-11-17 22:41 ` Eric W.Biederman
[not found] ` <9f43a787-165e-4256-a097-f7691204d9d6-2ueSQiBKiTY7tOexoI0I+QC/G2K4zDHf@public.gmane.org>
2014-11-17 22:50 ` Andy Lutomirski
2014-11-17 22:50 ` Andy Lutomirski
[not found] ` <CALCETrU2tXM5sKx=L-K6=ARkvqefkcZHW3_RGhsgfc31FuWxJg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-17 23:13 ` josh-iaAMLnmF4UmaiuxdJuQwMA
2014-11-17 23:13 ` josh
[not found] ` <3ccec8a13019b5e8ce7b1d7889677b778b070dc8.1416041823.git.josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
2014-11-15 9:01 ` [PATCH manpages] getgroups.2: Document unprivileged setgroups calls Josh Triplett
2014-11-15 9:01 ` Josh Triplett
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=87d28osceg.fsf@x220.int.ebiederm.org \
--to=ebiederm-as9lmozglivwk0htik3j/w@public.gmane.org \
--cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
--cc=josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org \
--cc=keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
--cc=linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-man-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.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.