security: Add LSM hooks to set*gid syscalls

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.

Signed-off-by: Thomas Cedeno <thomascedeno@google.com>
Signed-off-by: Micah Morton <mortonm@chromium.org>

authored by Thomas Cedeno and committed by Micah Morton 39030e13 3d77e6a8

Changed files
+40 -1
include
kernel
security
+2
include/linux/lsm_hook_defs.h
··· 190 190 loff_t size, enum kernel_read_file_id id) 191 191 LSM_HOOK(int, 0, task_fix_setuid, struct cred *new, const struct cred *old, 192 192 int flags) 193 + LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old, 194 + int flags) 193 195 LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid) 194 196 LSM_HOOK(int, 0, task_getpgid, struct task_struct *p) 195 197 LSM_HOOK(int, 0, task_getsid, struct task_struct *p)
+9
include/linux/lsm_hooks.h
··· 651 651 * @old is the set of credentials that are being replaces 652 652 * @flags contains one of the LSM_SETID_* values. 653 653 * Return 0 on success. 654 + * @task_fix_setgid: 655 + * Update the module's state after setting one or more of the group 656 + * identity attributes of the current process. The @flags parameter 657 + * indicates which of the set*gid system calls invoked this hook. 658 + * @new is the set of credentials that will be installed. Modifications 659 + * should be made to this rather than to @current->cred. 660 + * @old is the set of credentials that are being replaced. 661 + * @flags contains one of the LSM_SETID_* values. 662 + * Return 0 on success. 654 663 * @task_setpgid: 655 664 * Check permission before setting the process group identifier of the 656 665 * process @p to @pgid.
+9
include/linux/security.h
··· 389 389 enum kernel_read_file_id id); 390 390 int security_task_fix_setuid(struct cred *new, const struct cred *old, 391 391 int flags); 392 + int security_task_fix_setgid(struct cred *new, const struct cred *old, 393 + int flags); 392 394 int security_task_setpgid(struct task_struct *p, pid_t pgid); 393 395 int security_task_getpgid(struct task_struct *p); 394 396 int security_task_getsid(struct task_struct *p); ··· 1027 1025 int flags) 1028 1026 { 1029 1027 return cap_task_fix_setuid(new, old, flags); 1028 + } 1029 + 1030 + static inline int security_task_fix_setgid(struct cred *new, 1031 + const struct cred *old, 1032 + int flags) 1033 + { 1034 + return 0; 1030 1035 } 1031 1036 1032 1037 static inline int security_task_setpgid(struct task_struct *p, pid_t pgid)
+14 -1
kernel/sys.c
··· 393 393 new->sgid = new->egid; 394 394 new->fsgid = new->egid; 395 395 396 + retval = security_task_fix_setgid(new, old, LSM_SETID_RE); 397 + if (retval < 0) 398 + goto error; 399 + 396 400 return commit_creds(new); 397 401 398 402 error: ··· 437 433 else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) 438 434 new->egid = new->fsgid = kgid; 439 435 else 436 + goto error; 437 + 438 + retval = security_task_fix_setgid(new, old, LSM_SETID_ID); 439 + if (retval < 0) 440 440 goto error; 441 441 442 442 return commit_creds(new); ··· 764 756 new->sgid = ksgid; 765 757 new->fsgid = new->egid; 766 758 759 + retval = security_task_fix_setgid(new, old, LSM_SETID_RES); 760 + if (retval < 0) 761 + goto error; 762 + 767 763 return commit_creds(new); 768 764 769 765 error: ··· 874 862 ns_capable(old->user_ns, CAP_SETGID)) { 875 863 if (!gid_eq(kgid, old->fsgid)) { 876 864 new->fsgid = kgid; 877 - goto change_okay; 865 + if (security_task_fix_setgid(new,old,LSM_SETID_FS) == 0) 866 + goto change_okay; 878 867 } 879 868 } 880 869
+6
security/security.c
··· 1685 1685 return call_int_hook(task_fix_setuid, 0, new, old, flags); 1686 1686 } 1687 1687 1688 + int security_task_fix_setgid(struct cred *new, const struct cred *old, 1689 + int flags) 1690 + { 1691 + return call_int_hook(task_fix_setgid, 0, new, old, flags); 1692 + } 1693 + 1688 1694 int security_task_setpgid(struct task_struct *p, pid_t pgid) 1689 1695 { 1690 1696 return call_int_hook(task_setpgid, 0, p, pgid);