Message ID | 20200605193805.36531-1-mortonm@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | security: Add LSM hooks to set*gid syscalls | expand |
On Fri, Jun 05, 2020 at 12:38:05PM -0700, Micah Morton wrote: > The SafeSetID LSM uses the security_task_fix_setuid hook to filter > set*uid() syscalls according to its configured security policy. In > preparation for adding analagous support in the LSM for set*gid() > syscalls, we add the requisite hook here. Tested by putting print > statements in the security_task_fix_setgid hook and seeing them get hit > during kernel boot. > > From: Thomas Cedeno <thomascedeno@google.com> ^^^ this line should be before the commit log body (many tools won't find it here). > Signed-off-by: Thomas Cedeno <thomascedeno@google.com> > Reviewed-by: Micah Morton <mortonm@chromium.org> > --- > NOTE: I (Micah) will send this patch as a pull request to Linus through > my SafeSetID tree if there are no objections. > include/linux/lsm_hook_defs.h | 2 ++ > include/linux/lsm_hooks.h | 9 +++++++++ > include/linux/security.h | 9 +++++++++ > kernel/sys.c | 15 ++++++++++++++- > security/security.c | 6 ++++++ > 5 files changed, 40 insertions(+), 1 deletion(-) > > diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h > index fb3ce6cec997..d5401c09f2d3 100644 > --- a/include/linux/lsm_hook_defs.h > +++ b/include/linux/lsm_hook_defs.h > @@ -191,6 +191,8 @@ LSM_HOOK(int, 0, kernel_post_read_file, struct file *file, char *buf, > loff_t size, enum kernel_read_file_id id) > LSM_HOOK(int, 0, task_fix_setuid, struct cred *new, const struct cred *old, > int flags) > +LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old, > + int flags) > LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid) > LSM_HOOK(int, 0, task_getpgid, struct task_struct *p) > LSM_HOOK(int, 0, task_getsid, struct task_struct *p) > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h > index 3e62dab77699..8012b610fe53 100644 > --- a/include/linux/lsm_hooks.h > +++ b/include/linux/lsm_hooks.h > @@ -659,6 +659,15 @@ > * @old is the set of credentials that are being replaces > * @flags contains one of the LSM_SETID_* values. > * Return 0 on success. > + * @task_fix_setgid: > + * Update the module's state after setting one or more of the group > + * identity attributes of the current process. The @flags parameter > + * indicates which of the set*gid system calls invoked this hook. > + * @new is the set of credentials that will be installed. Modifications > + * should be made to this rather than to @current->cred. > + * @old is the set of credentials that are being replaced. > + * @flags contains one of the LSM_SETID_* values. > + * Return 0 on success. The indenting here appears to be using spaces instead of a tab. Everything else looks okay. (There are a surprising number of gid changing places...)
On Fri, Jun 5, 2020 at 2:25 PM Kees Cook <keescook@chromium.org> wrote: > > On Fri, Jun 05, 2020 at 12:38:05PM -0700, Micah Morton wrote: > > The SafeSetID LSM uses the security_task_fix_setuid hook to filter > > set*uid() syscalls according to its configured security policy. In > > preparation for adding analagous support in the LSM for set*gid() > > syscalls, we add the requisite hook here. Tested by putting print > > statements in the security_task_fix_setgid hook and seeing them get hit > > during kernel boot. > > > > From: Thomas Cedeno <thomascedeno@google.com> > > ^^^ this line should be before the commit log body (many tools won't > find it here). > > > Signed-off-by: Thomas Cedeno <thomascedeno@google.com> > > Reviewed-by: Micah Morton <mortonm@chromium.org> > > --- > > NOTE: I (Micah) will send this patch as a pull request to Linus through > > my SafeSetID tree if there are no objections. > > include/linux/lsm_hook_defs.h | 2 ++ > > include/linux/lsm_hooks.h | 9 +++++++++ > > include/linux/security.h | 9 +++++++++ > > kernel/sys.c | 15 ++++++++++++++- > > security/security.c | 6 ++++++ > > 5 files changed, 40 insertions(+), 1 deletion(-) > > > > diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h > > index fb3ce6cec997..d5401c09f2d3 100644 > > --- a/include/linux/lsm_hook_defs.h > > +++ b/include/linux/lsm_hook_defs.h > > @@ -191,6 +191,8 @@ LSM_HOOK(int, 0, kernel_post_read_file, struct file *file, char *buf, > > loff_t size, enum kernel_read_file_id id) > > LSM_HOOK(int, 0, task_fix_setuid, struct cred *new, const struct cred *old, > > int flags) > > +LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old, > > + int flags) > > LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid) > > LSM_HOOK(int, 0, task_getpgid, struct task_struct *p) > > LSM_HOOK(int, 0, task_getsid, struct task_struct *p) > > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h > > index 3e62dab77699..8012b610fe53 100644 > > --- a/include/linux/lsm_hooks.h > > +++ b/include/linux/lsm_hooks.h > > @@ -659,6 +659,15 @@ > > * @old is the set of credentials that are being replaces > > * @flags contains one of the LSM_SETID_* values. > > * Return 0 on success. > > + * @task_fix_setgid: > > + * Update the module's state after setting one or more of the group > > + * identity attributes of the current process. The @flags parameter > > + * indicates which of the set*gid system calls invoked this hook. > > + * @new is the set of credentials that will be installed. Modifications > > + * should be made to this rather than to @current->cred. > > + * @old is the set of credentials that are being replaced. > > + * @flags contains one of the LSM_SETID_* values. > > + * Return 0 on success. > > The indenting here appears to be using spaces instead of a tab. > > Everything else looks okay. (There are a surprising number of gid > changing places...) Ah thanks! I'll fix those 2 things before doing the pull request. Probably not worth doing a patch resend. Will still give it some time to see if anyone else wants to comment. > > -- > Kees Cook
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index fb3ce6cec997..d5401c09f2d3 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -191,6 +191,8 @@ LSM_HOOK(int, 0, kernel_post_read_file, struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) LSM_HOOK(int, 0, task_fix_setuid, struct cred *new, const struct cred *old, int flags) +LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old, + int flags) LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid) LSM_HOOK(int, 0, task_getpgid, struct task_struct *p) LSM_HOOK(int, 0, task_getsid, struct task_struct *p) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 3e62dab77699..8012b610fe53 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -659,6 +659,15 @@ * @old is the set of credentials that are being replaces * @flags contains one of the LSM_SETID_* values. * Return 0 on success. + * @task_fix_setgid: + * Update the module's state after setting one or more of the group + * identity attributes of the current process. The @flags parameter + * indicates which of the set*gid system calls invoked this hook. + * @new is the set of credentials that will be installed. Modifications + * should be made to this rather than to @current->cred. + * @old is the set of credentials that are being replaced. + * @flags contains one of the LSM_SETID_* values. + * Return 0 on success. * @task_setpgid: * Check permission before setting the process group identifier of the * process @p to @pgid. diff --git a/include/linux/security.h b/include/linux/security.h index b3f2cb21b4f2..2b08a2e49ba6 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -390,6 +390,8 @@ int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id); int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags); +int security_task_fix_setgid(struct cred *new, const struct cred *old, + int flags); int security_task_setpgid(struct task_struct *p, pid_t pgid); int security_task_getpgid(struct task_struct *p); int security_task_getsid(struct task_struct *p); @@ -1034,6 +1036,13 @@ static inline int security_task_fix_setuid(struct cred *new, return cap_task_fix_setuid(new, old, flags); } +static inline int security_task_fix_setgid(struct cred *new, + const struct cred *old, + int flags) +{ + return 0; +} + static inline int security_task_setpgid(struct task_struct *p, pid_t pgid) { return 0; diff --git a/kernel/sys.c b/kernel/sys.c index 891667a49bb7..e65ec850bfae 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -393,6 +393,10 @@ long __sys_setregid(gid_t rgid, gid_t egid) new->sgid = new->egid; new->fsgid = new->egid; + retval = security_task_fix_setgid(new, old, LSM_SETID_RE); + if (retval < 0) + goto error; + return commit_creds(new); error: @@ -435,6 +439,10 @@ long __sys_setgid(gid_t gid) else goto error; + retval = security_task_fix_setgid(new, old, LSM_SETID_ID); + if (retval < 0) + goto error; + return commit_creds(new); error: @@ -756,6 +764,10 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) new->sgid = ksgid; new->fsgid = new->egid; + retval = security_task_fix_setgid(new, old, LSM_SETID_RES); + if (retval < 0) + goto error; + return commit_creds(new); error: @@ -862,7 +874,8 @@ long __sys_setfsgid(gid_t gid) ns_capable(old->user_ns, CAP_SETGID)) { if (!gid_eq(kgid, old->fsgid)) { new->fsgid = kgid; - goto change_okay; + if (security_task_fix_setgid(new,old,LSM_SETID_FS) == 0) + goto change_okay; } } diff --git a/security/security.c b/security/security.c index 11c1a7da4fd1..639324c68dd0 100644 --- a/security/security.c +++ b/security/security.c @@ -1690,6 +1690,12 @@ int security_task_fix_setuid(struct cred *new, const struct cred *old, return call_int_hook(task_fix_setuid, 0, new, old, flags); } +int security_task_fix_setgid(struct cred *new, const struct cred *old, + int flags) +{ + return call_int_hook(task_fix_setgid, 0, new, old, flags); +} + int security_task_setpgid(struct task_struct *p, pid_t pgid) { return call_int_hook(task_setpgid, 0, p, pgid);