From: "Serge E. Hallyn" <serue@us.ibm.com>
To: lkml <linux-kernel@vger.kernel.org>
Cc: David Howells <dhowells@redhat.com>,
Ashwin Ganti <ashwin.ganti@gmail.com>, Greg KH <greg@kroah.com>,
rsc@swtch.com, ericvh@gmail.com,
linux-security-module@vger.kernel.org,
Ron Minnich <rminnich@gmail.com>,
jt.beard@gmail.com, Andrew Morton <akpm@linux-foundation.org>,
Andrew Morgan <morgan@kernel.org>,
oleg@us.ibm.com, Eric Paris <eparis@redhat.com>,
"Eric W. Biederman" <ebiederm@xmission.com>
Subject: [PATCH 1/3] p9auth: split core function out of some set*{u,g}id functions
Date: Tue, 20 Apr 2010 20:27:49 -0500 [thread overview]
Message-ID: <20100421012749.GA21338@us.ibm.com> (raw)
Break the core functionality of set{fs,res}{u,g}id into cred_setX
which performs the access checks based on current_cred(), but performs
the requested change on a passed-in cred.
Export the helpers, since p9auth can be compiled as a module. It
might be worth not allowing modular p9auth to avoid having to export
them.
Really the setfs{u,g}id helper isn't needed, but move it as
well to keep the code consistent.
This patch also changes set_user() to use new->user->user_ns. While
technically not needed as all callers should have new->user->user_ns
equal to current_userns(), it is more correct and may prevent surprises
in the future.
Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
---
include/linux/cred.h | 12 +++++
kernel/cred.c | 119 +++++++++++++++++++++++++++++++++++++++++++++
kernel/sys.c | 131 ++++++++------------------------------------------
3 files changed, 151 insertions(+), 111 deletions(-)
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 52507c3..0ce7a50 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -22,6 +22,9 @@ struct user_struct;
struct cred;
struct inode;
+/* defined in sys.c, used in cred_setresuid */
+extern int set_user(struct cred *new);
+
/*
* COW Supplementary groups list
*/
@@ -396,4 +399,13 @@ do { \
*(_fsgid) = __cred->fsgid; \
} while(0)
+#define CRED_SETID_NOFORCE 0
+#define CRED_SETID_FORCE 1
+int cred_setresuid(struct cred *new, uid_t ruid, uid_t euid, uid_t suid,
+ int force);
+int cred_setresgid(struct cred *new, gid_t rgid, gid_t egid, gid_t sgid,
+ int force);
+int cred_setfsuid(struct cred *new, uid_t uid, uid_t *old_fsuid);
+int cred_setfsgid(struct cred *new, gid_t gid, gid_t *old_fsgid);
+
#endif /* _LINUX_CRED_H */
diff --git a/kernel/cred.c b/kernel/cred.c
index e1dbe9e..4fc3284 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -785,6 +785,125 @@ int set_create_files_as(struct cred *new, struct inode *inode)
}
EXPORT_SYMBOL(set_create_files_as);
+int cred_setresuid(struct cred *new, uid_t ruid, uid_t euid, uid_t suid,
+ int force)
+{
+ int retval;
+ const struct cred *old;
+
+ retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
+ if (retval)
+ return retval;
+ old = current_cred();
+
+ if (!force && !capable(CAP_SETUID)) {
+ if (ruid != (uid_t) -1 && ruid != old->uid &&
+ ruid != old->euid && ruid != old->suid)
+ return -EPERM;
+ if (euid != (uid_t) -1 && euid != old->uid &&
+ euid != old->euid && euid != old->suid)
+ return -EPERM;
+ if (suid != (uid_t) -1 && suid != old->uid &&
+ suid != old->euid && suid != old->suid)
+ return -EPERM;
+ }
+
+ if (ruid != (uid_t) -1) {
+ new->uid = ruid;
+ if (ruid != old->uid) {
+ retval = set_user(new);
+ if (retval < 0)
+ return retval;
+ }
+ }
+ if (euid != (uid_t) -1)
+ new->euid = euid;
+ if (suid != (uid_t) -1)
+ new->suid = suid;
+ new->fsuid = new->euid;
+
+ return security_task_fix_setuid(new, old, LSM_SETID_RES);
+}
+EXPORT_SYMBOL_GPL(cred_setresuid);
+
+int cred_setresgid(struct cred *new, gid_t rgid, gid_t egid, gid_t sgid,
+ int force)
+{
+ const struct cred *old = current_cred();
+ int retval;
+
+ retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
+ if (retval)
+ return retval;
+
+ if (!force && !capable(CAP_SETGID)) {
+ if (rgid != (gid_t) -1 && rgid != old->gid &&
+ rgid != old->egid && rgid != old->sgid)
+ return -EPERM;
+ if (egid != (gid_t) -1 && egid != old->gid &&
+ egid != old->egid && egid != old->sgid)
+ return -EPERM;
+ if (sgid != (gid_t) -1 && sgid != old->gid &&
+ sgid != old->egid && sgid != old->sgid)
+ return -EPERM;
+ }
+
+ if (rgid != (gid_t) -1)
+ new->gid = rgid;
+ if (egid != (gid_t) -1)
+ new->egid = egid;
+ if (sgid != (gid_t) -1)
+ new->sgid = sgid;
+ new->fsgid = new->egid;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cred_setresgid);
+
+int cred_setfsuid(struct cred *new, uid_t uid, uid_t *old_fsuid)
+{
+ const struct cred *old;
+
+ old = current_cred();
+ *old_fsuid = old->fsuid;
+
+ if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0)
+ return -EPERM;
+
+ if (uid == old->uid || uid == old->euid ||
+ uid == old->suid || uid == old->fsuid ||
+ capable(CAP_SETUID)) {
+ if (uid != *old_fsuid) {
+ new->fsuid = uid;
+ if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
+ return 0;
+ }
+ }
+ return -EPERM;
+}
+EXPORT_SYMBOL_GPL(cred_setfsuid);
+
+int cred_setfsgid(struct cred *new, gid_t gid, gid_t *old_fsgid)
+{
+ const struct cred *old;
+
+ old = current_cred();
+ *old_fsgid = old->fsgid;
+
+ if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
+ return -EPERM;
+
+ if (gid == old->gid || gid == old->egid ||
+ gid == old->sgid || gid == old->fsgid ||
+ capable(CAP_SETGID)) {
+ if (gid != *old_fsgid) {
+ new->fsgid = gid;
+ return 0;
+ }
+ }
+ return -EPERM;
+}
+EXPORT_SYMBOL_GPL(cred_setfsgid);
+
#ifdef CONFIG_DEBUG_CREDENTIALS
bool creds_are_invalid(const struct cred *cred)
diff --git a/kernel/sys.c b/kernel/sys.c
index 6d1a7e0..78f32eb 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -565,11 +565,11 @@ error:
/*
* change the user struct in a credentials set to match the new UID
*/
-static int set_user(struct cred *new)
+int set_user(struct cred *new)
{
struct user_struct *new_user;
- new_user = alloc_uid(current_user_ns(), new->uid);
+ new_user = alloc_uid(new->user->user_ns, new->uid);
if (!new_user)
return -EAGAIN;
@@ -711,7 +711,6 @@ error:
*/
SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
{
- const struct cred *old;
struct cred *new;
int retval;
@@ -719,45 +718,10 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
if (!new)
return -ENOMEM;
- retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
- if (retval)
- goto error;
- old = current_cred();
+ retval = cred_setresuid(new, ruid, euid, suid, CRED_SETID_NOFORCE);
+ if (retval == 0)
+ return commit_creds(new);
- retval = -EPERM;
- if (!capable(CAP_SETUID)) {
- if (ruid != (uid_t) -1 && ruid != old->uid &&
- ruid != old->euid && ruid != old->suid)
- goto error;
- if (euid != (uid_t) -1 && euid != old->uid &&
- euid != old->euid && euid != old->suid)
- goto error;
- if (suid != (uid_t) -1 && suid != old->uid &&
- suid != old->euid && suid != old->suid)
- goto error;
- }
-
- if (ruid != (uid_t) -1) {
- new->uid = ruid;
- if (ruid != old->uid) {
- retval = set_user(new);
- if (retval < 0)
- goto error;
- }
- }
- if (euid != (uid_t) -1)
- new->euid = euid;
- if (suid != (uid_t) -1)
- new->suid = suid;
- new->fsuid = new->euid;
-
- retval = security_task_fix_setuid(new, old, LSM_SETID_RES);
- if (retval < 0)
- goto error;
-
- return commit_creds(new);
-
-error:
abort_creds(new);
return retval;
}
@@ -779,43 +743,17 @@ SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __u
*/
SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
{
- const struct cred *old;
struct cred *new;
int retval;
new = prepare_creds();
if (!new)
return -ENOMEM;
- old = current_cred();
- retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
- if (retval)
- goto error;
+ retval = cred_setresgid(new, rgid, egid, sgid, CRED_SETID_NOFORCE);
+ if (retval == 0)
+ return commit_creds(new);
- retval = -EPERM;
- if (!capable(CAP_SETGID)) {
- if (rgid != (gid_t) -1 && rgid != old->gid &&
- rgid != old->egid && rgid != old->sgid)
- goto error;
- if (egid != (gid_t) -1 && egid != old->gid &&
- egid != old->egid && egid != old->sgid)
- goto error;
- if (sgid != (gid_t) -1 && sgid != old->gid &&
- sgid != old->egid && sgid != old->sgid)
- goto error;
- }
-
- if (rgid != (gid_t) -1)
- new->gid = rgid;
- if (egid != (gid_t) -1)
- new->egid = egid;
- if (sgid != (gid_t) -1)
- new->sgid = sgid;
- new->fsgid = new->egid;
-
- return commit_creds(new);
-
-error:
abort_creds(new);
return retval;
}
@@ -841,35 +779,20 @@ SYSCALL_DEFINE3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __u
*/
SYSCALL_DEFINE1(setfsuid, uid_t, uid)
{
- const struct cred *old;
struct cred *new;
uid_t old_fsuid;
+ int retval;
new = prepare_creds();
if (!new)
return current_fsuid();
- old = current_cred();
- old_fsuid = old->fsuid;
-
- if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0)
- goto error;
-
- if (uid == old->uid || uid == old->euid ||
- uid == old->suid || uid == old->fsuid ||
- capable(CAP_SETUID)) {
- if (uid != old_fsuid) {
- new->fsuid = uid;
- if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
- goto change_okay;
- }
- }
-error:
- abort_creds(new);
- return old_fsuid;
+ retval = cred_setfsuid(new, uid, &old_fsuid);
+ if (retval == 0)
+ commit_creds(new);
+ else
+ abort_creds(new);
-change_okay:
- commit_creds(new);
return old_fsuid;
}
@@ -878,34 +801,20 @@ change_okay:
*/
SYSCALL_DEFINE1(setfsgid, gid_t, gid)
{
- const struct cred *old;
struct cred *new;
gid_t old_fsgid;
+ int retval;
new = prepare_creds();
if (!new)
return current_fsgid();
- old = current_cred();
- old_fsgid = old->fsgid;
-
- if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
- goto error;
-
- if (gid == old->gid || gid == old->egid ||
- gid == old->sgid || gid == old->fsgid ||
- capable(CAP_SETGID)) {
- if (gid != old_fsgid) {
- new->fsgid = gid;
- goto change_okay;
- }
- }
-error:
- abort_creds(new);
- return old_fsgid;
+ retval = cred_setfsgid(new, gid, &old_fsgid);
+ if (retval == 0)
+ commit_creds(new);
+ else
+ abort_creds(new);
-change_okay:
- commit_creds(new);
return old_fsgid;
}
--
1.7.0.4
next reply other threads:[~2010-04-21 1:27 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-21 1:27 Serge E. Hallyn [this message]
2010-04-21 1:28 ` [PATCH 2/3] p9auth: add CAP_GRANT_ID to authorize use of /dev/caphash Serge E. Hallyn
2010-04-21 2:54 ` Greg KH
[not found] ` <20100421012749.GA21338-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-04-21 1:29 ` [PATCH 3/3] p9auth: add p9auth driver Serge E. Hallyn
2010-04-21 1:29 ` Serge E. Hallyn
[not found] ` <20100421012908.GB24251-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-04-21 3:04 ` Greg KH
2010-04-21 3:04 ` Greg KH
[not found] ` <20100421030406.GB10258-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2010-04-21 3:45 ` Serge E. Hallyn
2010-04-21 3:45 ` Serge E. Hallyn
2010-04-21 4:18 ` Ashwin Ganti
2010-04-21 4:18 ` Ashwin Ganti
2010-04-21 13:47 ` Serge E. Hallyn
2010-04-21 13:47 ` Serge E. Hallyn
[not found] ` <20100421134759.GE16326-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-04-21 14:44 ` Ashwin Ganti
2010-04-21 14:44 ` Ashwin Ganti
2010-04-21 4:45 ` Eric W. Biederman
[not found] ` <m1zl0xo1m9.fsf-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>
2010-04-21 13:21 ` Serge E. Hallyn
2010-04-21 13:21 ` Serge E. Hallyn
2010-04-24 3:36 ` Serge E. Hallyn
2010-04-24 3:36 ` Serge E. Hallyn
2010-04-24 16:25 ` ron minnich
2010-04-24 16:25 ` ron minnich
[not found] ` <n2s13426df11004240925id540ed94mc2ebafada0099ec4-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-04-24 18:01 ` Eric W. Biederman
2010-04-24 18:01 ` Eric W. Biederman
2010-04-25 3:24 ` Serge E. Hallyn
2010-04-21 9:27 ` Alan Cox
2010-04-21 9:27 ` Alan Cox
[not found] ` <20100421102739.6ad932fb-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
2010-04-21 13:39 ` Serge E. Hallyn
2010-04-21 13:39 ` Serge E. Hallyn
2010-04-21 14:19 ` Alan Cox
[not found] ` <20100421151917.5ae20265-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
2010-04-21 15:09 ` Serge E. Hallyn
2010-04-21 15:09 ` Serge E. Hallyn
2010-04-21 19:15 ` Eric W. Biederman
2010-04-21 20:23 ` Serge E. Hallyn
2010-04-22 4:57 ` Kyle Moffett
[not found] ` <w2wf73f7ab81004212157o371c5738o10c8b6ff807ba36a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-04-22 14:36 ` Serge E. Hallyn
2010-04-22 14:36 ` Serge E. Hallyn
2010-04-21 13:55 ` Eric Paris
2010-04-21 13:55 ` Eric Paris
2010-04-21 14:30 ` Serge E. Hallyn
2010-04-21 10:49 ` David Howells
2010-04-21 10:49 ` David Howells
2010-04-21 13:40 ` Serge E. Hallyn
2010-04-21 10:46 ` [PATCH 1/3] p9auth: split core function out of some set*{u,g}id functions David Howells
2010-04-21 13:40 ` Serge E. Hallyn
-- strict thread matches above, loose matches on Subject: below --
2010-04-27 16:41 [PATCH 0/3] p9auth fs: introduction Serge E. Hallyn
2010-04-27 16:42 ` [PATCH 1/3] p9auth: split core function out of some set*{u,g}id functions Serge E. Hallyn
2010-05-04 14:52 ` David Howells
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=20100421012749.GA21338@us.ibm.com \
--to=serue@us.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=ashwin.ganti@gmail.com \
--cc=dhowells@redhat.com \
--cc=ebiederm@xmission.com \
--cc=eparis@redhat.com \
--cc=ericvh@gmail.com \
--cc=greg@kroah.com \
--cc=jt.beard@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=morgan@kernel.org \
--cc=oleg@us.ibm.com \
--cc=rminnich@gmail.com \
--cc=rsc@swtch.com \
/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.