From 72e89f50084c6dbc58a00aeedf92c450dc1a8b1c Mon Sep 17 00:00:00 2001 From: Richard Haines Date: Tue, 13 Feb 2018 20:53:21 +0000 Subject: security: Add support for SCTP security hooks The SCTP security hooks are explained in: Documentation/security/LSM-sctp.rst Signed-off-by: Richard Haines Signed-off-by: Paul Moore --- include/linux/security.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'include/linux/security.h') diff --git a/include/linux/security.h b/include/linux/security.h index 73f1ef625d40..2ff5f5777a53 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -115,6 +115,7 @@ struct xfrm_policy; struct xfrm_state; struct xfrm_user_sec_ctx; struct seq_file; +struct sctp_endpoint; #ifdef CONFIG_MMU extern unsigned long mmap_min_addr; @@ -1229,6 +1230,11 @@ int security_tun_dev_create(void); int security_tun_dev_attach_queue(void *security); int security_tun_dev_attach(struct sock *sk, void *security); int security_tun_dev_open(void *security); +int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb); +int security_sctp_bind_connect(struct sock *sk, int optname, + struct sockaddr *address, int addrlen); +void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, + struct sock *newsk); #else /* CONFIG_SECURITY_NETWORK */ static inline int security_unix_stream_connect(struct sock *sock, @@ -1421,6 +1427,25 @@ static inline int security_tun_dev_open(void *security) { return 0; } + +static inline int security_sctp_assoc_request(struct sctp_endpoint *ep, + struct sk_buff *skb) +{ + return 0; +} + +static inline int security_sctp_bind_connect(struct sock *sk, int optname, + struct sockaddr *address, + int addrlen) +{ + return 0; +} + +static inline void security_sctp_sk_clone(struct sctp_endpoint *ep, + struct sock *sk, + struct sock *newsk) +{ +} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND -- cgit v1.2.3 From 6b4f3d01052a479c7ebbe99d52a663558dc1be2a Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Fri, 8 Sep 2017 12:40:01 -0400 Subject: usb, signal, security: only pass the cred, not the secid, to kill_pid_info_as_cred and security_task_kill commit d178bc3a708f39cbfefc3fab37032d3f2511b4ec ("user namespace: usb: make usb urbs user namespace aware (v2)") changed kill_pid_info_as_uid to kill_pid_info_as_cred, saving and passing a cred structure instead of uids. Since the secid can be obtained from the cred, drop the secid fields from the usb_dev_state and async structures, and drop the secid argument to kill_pid_info_as_cred. Replace the secid argument to security_task_kill with the cred. Update SELinux, Smack, and AppArmor to use the cred, which avoids the need for Smack and AppArmor to use a secid at all in this hook. Further changes to Smack might still be required to take full advantage of this change, since it should now be possible to perform capability checking based on the supplied cred. The changes to Smack and AppArmor have only been compile-tested. Signed-off-by: Stephen Smalley Acked-by: Paul Moore Acked-by: Casey Schaufler Acked-by: Greg Kroah-Hartman Acked-by: John Johansen Signed-off-by: James Morris --- drivers/usb/core/devio.c | 10 ++-------- include/linux/lsm_hooks.h | 5 +++-- include/linux/sched/signal.h | 2 +- include/linux/security.h | 4 ++-- kernel/signal.c | 6 +++--- security/apparmor/lsm.c | 17 ++++++++++++----- security/security.c | 4 ++-- security/selinux/hooks.c | 7 +++++-- security/smack/smack_lsm.c | 12 +++++------- 9 files changed, 35 insertions(+), 32 deletions(-) (limited to 'include/linux/security.h') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index d526595bc959..76e16c5251b9 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -65,7 +65,6 @@ struct usb_dev_state { const struct cred *cred; void __user *disccontext; unsigned long ifclaimed; - u32 secid; u32 disabled_bulk_eps; bool privileges_dropped; unsigned long interface_allowed_mask; @@ -95,7 +94,6 @@ struct async { struct usb_memory *usbm; unsigned int mem_usage; int status; - u32 secid; u8 bulk_addr; u8 bulk_status; }; @@ -586,7 +584,6 @@ static void async_completed(struct urb *urb) struct usb_dev_state *ps = as->ps; struct siginfo sinfo; struct pid *pid = NULL; - u32 secid = 0; const struct cred *cred = NULL; int signr; @@ -602,7 +599,6 @@ static void async_completed(struct urb *urb) sinfo.si_addr = as->userurb; pid = get_pid(as->pid); cred = get_cred(as->cred); - secid = as->secid; } snoop(&urb->dev->dev, "urb complete\n"); snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, @@ -618,7 +614,7 @@ static void async_completed(struct urb *urb) spin_unlock(&ps->lock); if (signr) { - kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred, secid); + kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred); put_pid(pid); put_cred(cred); } @@ -1013,7 +1009,6 @@ static int usbdev_open(struct inode *inode, struct file *file) init_waitqueue_head(&ps->wait); ps->disc_pid = get_pid(task_pid(current)); ps->cred = get_current_cred(); - security_task_getsecid(current, &ps->secid); smp_wmb(); list_add_tail(&ps->list, &dev->filelist); file->private_data = ps; @@ -1727,7 +1722,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb as->ifnum = ifnum; as->pid = get_pid(task_pid(current)); as->cred = get_current_cred(); - security_task_getsecid(current, &as->secid); snoop_urb(ps->dev, as->userurb, as->urb->pipe, as->urb->transfer_buffer_length, 0, SUBMIT, NULL, 0); @@ -2617,7 +2611,7 @@ static void usbdev_remove(struct usb_device *udev) sinfo.si_code = SI_ASYNCIO; sinfo.si_addr = ps->disccontext; kill_pid_info_as_cred(ps->discsignr, &sinfo, - ps->disc_pid, ps->cred, ps->secid); + ps->disc_pid, ps->cred); } } } diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 7161d8e7ee79..e0ac011d07a5 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -672,7 +672,8 @@ * @p contains the task_struct for process. * @info contains the signal information. * @sig contains the signal value. - * @secid contains the sid of the process where the signal originated + * @cred contains the cred of the process where the signal originated, or + * NULL if the current task is the originator. * Return 0 if permission is granted. * @task_prctl: * Check permission before performing a process control operation on the @@ -1564,7 +1565,7 @@ union security_list_options { int (*task_getscheduler)(struct task_struct *p); int (*task_movememory)(struct task_struct *p); int (*task_kill)(struct task_struct *p, struct siginfo *info, - int sig, u32 secid); + int sig, const struct cred *cred); int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); void (*task_to_inode)(struct task_struct *p, struct inode *inode); diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 23b4f9cb82db..a7ce74c74e49 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -319,7 +319,7 @@ extern int force_sig_info(int, struct siginfo *, struct task_struct *); extern int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp); extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid); extern int kill_pid_info_as_cred(int, struct siginfo *, struct pid *, - const struct cred *, u32); + const struct cred *); extern int kill_pgrp(struct pid *pid, int sig, int priv); extern int kill_pid(struct pid *pid, int sig, int priv); extern __must_check bool do_notify_parent(struct task_struct *, int); diff --git a/include/linux/security.h b/include/linux/security.h index 73f1ef625d40..3f5fd988ee87 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -347,7 +347,7 @@ int security_task_setscheduler(struct task_struct *p); int security_task_getscheduler(struct task_struct *p); int security_task_movememory(struct task_struct *p); int security_task_kill(struct task_struct *p, struct siginfo *info, - int sig, u32 secid); + int sig, const struct cred *cred); int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); void security_task_to_inode(struct task_struct *p, struct inode *inode); @@ -1010,7 +1010,7 @@ static inline int security_task_movememory(struct task_struct *p) static inline int security_task_kill(struct task_struct *p, struct siginfo *info, int sig, - u32 secid) + const struct cred *cred) { return 0; } diff --git a/kernel/signal.c b/kernel/signal.c index c6e4c83dc090..b033292f4beb 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -770,7 +770,7 @@ static int check_kill_permission(int sig, struct siginfo *info, } } - return security_task_kill(t, info, sig, 0); + return security_task_kill(t, info, sig, NULL); } /** @@ -1361,7 +1361,7 @@ static int kill_as_cred_perm(const struct cred *cred, /* like kill_pid_info(), but doesn't use uid/euid of "current" */ int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid, - const struct cred *cred, u32 secid) + const struct cred *cred) { int ret = -EINVAL; struct task_struct *p; @@ -1380,7 +1380,7 @@ int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid, ret = -EPERM; goto out_unlock; } - ret = security_task_kill(p, info, sig, secid); + ret = security_task_kill(p, info, sig, cred); if (ret) goto out_unlock; diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 9a65eeaf7dfa..77bdfa7f8428 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -717,16 +717,23 @@ static int apparmor_task_setrlimit(struct task_struct *task, } static int apparmor_task_kill(struct task_struct *target, struct siginfo *info, - int sig, u32 secid) + int sig, const struct cred *cred) { struct aa_label *cl, *tl; int error; - if (secid) - /* TODO: after secid to label mapping is done. - * Dealing with USB IO specific behavior + if (cred) { + /* + * Dealing with USB IO specific behavior */ - return 0; + cl = aa_get_newest_cred_label(cred); + tl = aa_get_task_label(target); + error = aa_may_signal(cl, tl, sig); + aa_put_label(cl); + aa_put_label(tl); + return error; + } + cl = __begin_current_label_crit_section(); tl = aa_get_task_label(target); error = aa_may_signal(cl, tl, sig); diff --git a/security/security.c b/security/security.c index 1cd8526cb0b7..14c291910d25 100644 --- a/security/security.c +++ b/security/security.c @@ -1114,9 +1114,9 @@ int security_task_movememory(struct task_struct *p) } int security_task_kill(struct task_struct *p, struct siginfo *info, - int sig, u32 secid) + int sig, const struct cred *cred) { - return call_int_hook(task_kill, 0, p, info, sig, secid); + return call_int_hook(task_kill, 0, p, info, sig, cred); } int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8644d864e3c1..8abd542c6b7c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4036,16 +4036,19 @@ static int selinux_task_movememory(struct task_struct *p) } static int selinux_task_kill(struct task_struct *p, struct siginfo *info, - int sig, u32 secid) + int sig, const struct cred *cred) { + u32 secid; u32 perm; if (!sig) perm = PROCESS__SIGNULL; /* null signal; existence test */ else perm = signal_to_av(sig); - if (!secid) + if (!cred) secid = current_sid(); + else + secid = cred_sid(cred); return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL); } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 03fdecba93bb..feada2665322 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2228,15 +2228,13 @@ static int smack_task_movememory(struct task_struct *p) * @p: the task object * @info: unused * @sig: unused - * @secid: identifies the smack to use in lieu of current's + * @cred: identifies the cred to use in lieu of current's * * Return 0 if write access is permitted * - * The secid behavior is an artifact of an SELinux hack - * in the USB code. Someday it may go away. */ static int smack_task_kill(struct task_struct *p, struct siginfo *info, - int sig, u32 secid) + int sig, const struct cred *cred) { struct smk_audit_info ad; struct smack_known *skp; @@ -2252,17 +2250,17 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, * Sending a signal requires that the sender * can write the receiver. */ - if (secid == 0) { + if (cred == NULL) { rc = smk_curacc(tkp, MAY_DELIVER, &ad); rc = smk_bu_task(p, MAY_DELIVER, rc); return rc; } /* - * If the secid isn't 0 we're dealing with some USB IO + * If the cred isn't NULL we're dealing with some USB IO * specific behavior. This is not clean. For one thing * we can't take privilege into account. */ - skp = smack_from_secid(secid); + skp = smk_of_task(cred->security); rc = smk_access(skp, tkp, MAY_DELIVER, &ad); rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc); return rc; -- cgit v1.2.3 From aefad9593ec5ad4aae5346253a8b646364cd7317 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 22 Mar 2018 20:52:43 -0500 Subject: sem/security: Pass kern_ipc_perm not sem_array into the sem security hooks All of the implementations of security hooks that take sem_array only access sem_perm the struct kern_ipc_perm member. This means the dependencies of the sem security hooks can be simplified by passing the kern_ipc_perm member of sem_array. Making this change will allow struct sem and struct sem_array to become private to ipc/sem.c. Signed-off-by: "Eric W. Biederman" --- include/linux/lsm_hooks.h | 10 +++++----- include/linux/security.h | 21 ++++++++++----------- ipc/sem.c | 19 ++++++++----------- security/security.c | 10 +++++----- security/selinux/hooks.c | 28 ++++++++++++++-------------- security/smack/smack_lsm.c | 22 +++++++++++----------- 6 files changed, 53 insertions(+), 57 deletions(-) (limited to 'include/linux/security.h') diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 7161d8e7ee79..e4a94863a88c 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1592,11 +1592,11 @@ union security_list_options { int (*shm_shmat)(struct shmid_kernel *shp, char __user *shmaddr, int shmflg); - int (*sem_alloc_security)(struct sem_array *sma); - void (*sem_free_security)(struct sem_array *sma); - int (*sem_associate)(struct sem_array *sma, int semflg); - int (*sem_semctl)(struct sem_array *sma, int cmd); - int (*sem_semop)(struct sem_array *sma, struct sembuf *sops, + int (*sem_alloc_security)(struct kern_ipc_perm *sma); + void (*sem_free_security)(struct kern_ipc_perm *sma); + int (*sem_associate)(struct kern_ipc_perm *sma, int semflg); + int (*sem_semctl)(struct kern_ipc_perm *sma, int cmd); + int (*sem_semop)(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter); int (*netlink_send)(struct sock *sk, struct sk_buff *skb); diff --git a/include/linux/security.h b/include/linux/security.h index 73f1ef625d40..fa7adac4b99a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -36,7 +36,6 @@ struct linux_binprm; struct cred; struct rlimit; struct siginfo; -struct sem_array; struct sembuf; struct kern_ipc_perm; struct audit_context; @@ -368,11 +367,11 @@ void security_shm_free(struct shmid_kernel *shp); int security_shm_associate(struct shmid_kernel *shp, int shmflg); int security_shm_shmctl(struct shmid_kernel *shp, int cmd); int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg); -int security_sem_alloc(struct sem_array *sma); -void security_sem_free(struct sem_array *sma); -int security_sem_associate(struct sem_array *sma, int semflg); -int security_sem_semctl(struct sem_array *sma, int cmd); -int security_sem_semop(struct sem_array *sma, struct sembuf *sops, +int security_sem_alloc(struct kern_ipc_perm *sma); +void security_sem_free(struct kern_ipc_perm *sma); +int security_sem_associate(struct kern_ipc_perm *sma, int semflg); +int security_sem_semctl(struct kern_ipc_perm *sma, int cmd); +int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter); void security_d_instantiate(struct dentry *dentry, struct inode *inode); int security_getprocattr(struct task_struct *p, char *name, char **value); @@ -1103,25 +1102,25 @@ static inline int security_shm_shmat(struct shmid_kernel *shp, return 0; } -static inline int security_sem_alloc(struct sem_array *sma) +static inline int security_sem_alloc(struct kern_ipc_perm *sma) { return 0; } -static inline void security_sem_free(struct sem_array *sma) +static inline void security_sem_free(struct kern_ipc_perm *sma) { } -static inline int security_sem_associate(struct sem_array *sma, int semflg) +static inline int security_sem_associate(struct kern_ipc_perm *sma, int semflg) { return 0; } -static inline int security_sem_semctl(struct sem_array *sma, int cmd) +static inline int security_sem_semctl(struct kern_ipc_perm *sma, int cmd) { return 0; } -static inline int security_sem_semop(struct sem_array *sma, +static inline int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter) { diff --git a/ipc/sem.c b/ipc/sem.c index a4af04979fd2..01f5c63670ae 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -265,7 +265,7 @@ static void sem_rcu_free(struct rcu_head *head) struct kern_ipc_perm *p = container_of(head, struct kern_ipc_perm, rcu); struct sem_array *sma = container_of(p, struct sem_array, sem_perm); - security_sem_free(sma); + security_sem_free(&sma->sem_perm); kvfree(sma); } @@ -495,7 +495,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params) sma->sem_perm.key = key; sma->sem_perm.security = NULL; - retval = security_sem_alloc(sma); + retval = security_sem_alloc(&sma->sem_perm); if (retval) { kvfree(sma); return retval; @@ -535,10 +535,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params) */ static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg) { - struct sem_array *sma; - - sma = container_of(ipcp, struct sem_array, sem_perm); - return security_sem_associate(sma, semflg); + return security_sem_associate(ipcp, semflg); } /* @@ -1209,7 +1206,7 @@ static int semctl_stat(struct ipc_namespace *ns, int semid, if (ipcperms(ns, &sma->sem_perm, S_IRUGO)) goto out_unlock; - err = security_sem_semctl(sma, cmd); + err = security_sem_semctl(&sma->sem_perm, cmd); if (err) goto out_unlock; @@ -1300,7 +1297,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum, return -EACCES; } - err = security_sem_semctl(sma, SETVAL); + err = security_sem_semctl(&sma->sem_perm, SETVAL); if (err) { rcu_read_unlock(); return -EACCES; @@ -1354,7 +1351,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, if (ipcperms(ns, &sma->sem_perm, cmd == SETALL ? S_IWUGO : S_IRUGO)) goto out_rcu_wakeup; - err = security_sem_semctl(sma, cmd); + err = security_sem_semctl(&sma->sem_perm, cmd); if (err) goto out_rcu_wakeup; @@ -1545,7 +1542,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid, sma = container_of(ipcp, struct sem_array, sem_perm); - err = security_sem_semctl(sma, cmd); + err = security_sem_semctl(&sma->sem_perm, cmd); if (err) goto out_unlock1; @@ -1962,7 +1959,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops, goto out_free; } - error = security_sem_semop(sma, sops, nsops, alter); + error = security_sem_semop(&sma->sem_perm, sops, nsops, alter); if (error) { rcu_read_unlock(); goto out_free; diff --git a/security/security.c b/security/security.c index 1cd8526cb0b7..d3b9aeb6b73b 100644 --- a/security/security.c +++ b/security/security.c @@ -1220,27 +1220,27 @@ int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmfl return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg); } -int security_sem_alloc(struct sem_array *sma) +int security_sem_alloc(struct kern_ipc_perm *sma) { return call_int_hook(sem_alloc_security, 0, sma); } -void security_sem_free(struct sem_array *sma) +void security_sem_free(struct kern_ipc_perm *sma) { call_void_hook(sem_free_security, sma); } -int security_sem_associate(struct sem_array *sma, int semflg) +int security_sem_associate(struct kern_ipc_perm *sma, int semflg) { return call_int_hook(sem_associate, 0, sma, semflg); } -int security_sem_semctl(struct sem_array *sma, int cmd) +int security_sem_semctl(struct kern_ipc_perm *sma, int cmd) { return call_int_hook(sem_semctl, 0, sma, cmd); } -int security_sem_semop(struct sem_array *sma, struct sembuf *sops, +int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter) { return call_int_hook(sem_semop, 0, sma, sops, nsops, alter); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8644d864e3c1..cce994e9fc0a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5767,53 +5767,53 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, } /* Semaphore security operations */ -static int selinux_sem_alloc_security(struct sem_array *sma) +static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) { struct ipc_security_struct *isec; struct common_audit_data ad; u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM); + rc = ipc_alloc_security(sma, SECCLASS_SEM); if (rc) return rc; - isec = sma->sem_perm.security; + isec = sma->security; ad.type = LSM_AUDIT_DATA_IPC; - ad.u.ipc_id = sma->sem_perm.key; + ad.u.ipc_id = sma->key; rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, SEM__CREATE, &ad); if (rc) { - ipc_free_security(&sma->sem_perm); + ipc_free_security(sma); return rc; } return 0; } -static void selinux_sem_free_security(struct sem_array *sma) +static void selinux_sem_free_security(struct kern_ipc_perm *sma) { - ipc_free_security(&sma->sem_perm); + ipc_free_security(sma); } -static int selinux_sem_associate(struct sem_array *sma, int semflg) +static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) { struct ipc_security_struct *isec; struct common_audit_data ad; u32 sid = current_sid(); - isec = sma->sem_perm.security; + isec = sma->security; ad.type = LSM_AUDIT_DATA_IPC; - ad.u.ipc_id = sma->sem_perm.key; + ad.u.ipc_id = sma->key; return avc_has_perm(sid, isec->sid, SECCLASS_SEM, SEM__ASSOCIATE, &ad); } /* Note, at this point, sma is locked down */ -static int selinux_sem_semctl(struct sem_array *sma, int cmd) +static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd) { int err; u32 perms; @@ -5851,11 +5851,11 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd) return 0; } - err = ipc_has_perm(&sma->sem_perm, perms); + err = ipc_has_perm(sma, perms); return err; } -static int selinux_sem_semop(struct sem_array *sma, +static int selinux_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter) { u32 perms; @@ -5865,7 +5865,7 @@ static int selinux_sem_semop(struct sem_array *sma, else perms = SEM__READ; - return ipc_has_perm(&sma->sem_perm, perms); + return ipc_has_perm(sma, perms); } static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 03fdecba93bb..0402b8c1aec1 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3077,9 +3077,9 @@ static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, * * Returns a pointer to the smack value */ -static struct smack_known *smack_of_sem(struct sem_array *sma) +static struct smack_known *smack_of_sem(struct kern_ipc_perm *sma) { - return (struct smack_known *)sma->sem_perm.security; + return (struct smack_known *)sma->security; } /** @@ -3088,9 +3088,9 @@ static struct smack_known *smack_of_sem(struct sem_array *sma) * * Returns 0 */ -static int smack_sem_alloc_security(struct sem_array *sma) +static int smack_sem_alloc_security(struct kern_ipc_perm *sma) { - struct kern_ipc_perm *isp = &sma->sem_perm; + struct kern_ipc_perm *isp = sma; struct smack_known *skp = smk_of_current(); isp->security = skp; @@ -3103,9 +3103,9 @@ static int smack_sem_alloc_security(struct sem_array *sma) * * Clears the blob pointer */ -static void smack_sem_free_security(struct sem_array *sma) +static void smack_sem_free_security(struct kern_ipc_perm *sma) { - struct kern_ipc_perm *isp = &sma->sem_perm; + struct kern_ipc_perm *isp = sma; isp->security = NULL; } @@ -3117,7 +3117,7 @@ static void smack_sem_free_security(struct sem_array *sma) * * Returns 0 if current has the requested access, error code otherwise */ -static int smk_curacc_sem(struct sem_array *sma, int access) +static int smk_curacc_sem(struct kern_ipc_perm *sma, int access) { struct smack_known *ssp = smack_of_sem(sma); struct smk_audit_info ad; @@ -3125,7 +3125,7 @@ static int smk_curacc_sem(struct sem_array *sma, int access) #ifdef CONFIG_AUDIT smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); - ad.a.u.ipc_id = sma->sem_perm.id; + ad.a.u.ipc_id = sma->id; #endif rc = smk_curacc(ssp, access, &ad); rc = smk_bu_current("sem", ssp, access, rc); @@ -3139,7 +3139,7 @@ static int smk_curacc_sem(struct sem_array *sma, int access) * * Returns 0 if current has the requested access, error code otherwise */ -static int smack_sem_associate(struct sem_array *sma, int semflg) +static int smack_sem_associate(struct kern_ipc_perm *sma, int semflg) { int may; @@ -3154,7 +3154,7 @@ static int smack_sem_associate(struct sem_array *sma, int semflg) * * Returns 0 if current has the requested access, error code otherwise */ -static int smack_sem_semctl(struct sem_array *sma, int cmd) +static int smack_sem_semctl(struct kern_ipc_perm *sma, int cmd) { int may; @@ -3198,7 +3198,7 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd) * * Returns 0 if access is allowed, error code otherwise */ -static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops, +static int smack_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter) { return smk_curacc_sem(sma, MAY_READWRITE); -- cgit v1.2.3 From 7191adff2a5566efb139c79ea03eda3d0520d44a Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 22 Mar 2018 21:08:27 -0500 Subject: shm/security: Pass kern_ipc_perm not shmid_kernel into the shm security hooks All of the implementations of security hooks that take shmid_kernel only access shm_perm the struct kern_ipc_perm member. This means the dependencies of the shm security hooks can be simplified by passing the kern_ipc_perm member of shmid_kernel.. Making this change will allow struct shmid_kernel to become private to ipc/shm.c. Signed-off-by: "Eric W. Biederman" --- include/linux/lsm_hooks.h | 10 +++++----- include/linux/security.h | 21 ++++++++++----------- ipc/shm.c | 17 +++++++---------- security/security.c | 10 +++++----- security/selinux/hooks.c | 28 ++++++++++++++-------------- security/smack/smack_lsm.c | 22 +++++++++++----------- 6 files changed, 52 insertions(+), 56 deletions(-) (limited to 'include/linux/security.h') diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index e4a94863a88c..cac7a8082c43 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1585,11 +1585,11 @@ union security_list_options { struct task_struct *target, long type, int mode); - int (*shm_alloc_security)(struct shmid_kernel *shp); - void (*shm_free_security)(struct shmid_kernel *shp); - int (*shm_associate)(struct shmid_kernel *shp, int shmflg); - int (*shm_shmctl)(struct shmid_kernel *shp, int cmd); - int (*shm_shmat)(struct shmid_kernel *shp, char __user *shmaddr, + int (*shm_alloc_security)(struct kern_ipc_perm *shp); + void (*shm_free_security)(struct kern_ipc_perm *shp); + int (*shm_associate)(struct kern_ipc_perm *shp, int shmflg); + int (*shm_shmctl)(struct kern_ipc_perm *shp, int cmd); + int (*shm_shmat)(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg); int (*sem_alloc_security)(struct kern_ipc_perm *sma); diff --git a/include/linux/security.h b/include/linux/security.h index fa7adac4b99a..f390755808ea 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -49,7 +49,6 @@ struct qstr; struct iattr; struct fown_struct; struct file_operations; -struct shmid_kernel; struct msg_msg; struct msg_queue; struct xattr; @@ -362,11 +361,11 @@ int security_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg); int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode); -int security_shm_alloc(struct shmid_kernel *shp); -void security_shm_free(struct shmid_kernel *shp); -int security_shm_associate(struct shmid_kernel *shp, int shmflg); -int security_shm_shmctl(struct shmid_kernel *shp, int cmd); -int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg); +int security_shm_alloc(struct kern_ipc_perm *shp); +void security_shm_free(struct kern_ipc_perm *shp); +int security_shm_associate(struct kern_ipc_perm *shp, int shmflg); +int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd); +int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg); int security_sem_alloc(struct kern_ipc_perm *sma); void security_sem_free(struct kern_ipc_perm *sma); int security_sem_associate(struct kern_ipc_perm *sma, int semflg); @@ -1077,26 +1076,26 @@ static inline int security_msg_queue_msgrcv(struct msg_queue *msq, return 0; } -static inline int security_shm_alloc(struct shmid_kernel *shp) +static inline int security_shm_alloc(struct kern_ipc_perm *shp) { return 0; } -static inline void security_shm_free(struct shmid_kernel *shp) +static inline void security_shm_free(struct kern_ipc_perm *shp) { } -static inline int security_shm_associate(struct shmid_kernel *shp, +static inline int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) { return 0; } -static inline int security_shm_shmctl(struct shmid_kernel *shp, int cmd) +static inline int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd) { return 0; } -static inline int security_shm_shmat(struct shmid_kernel *shp, +static inline int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg) { return 0; diff --git a/ipc/shm.c b/ipc/shm.c index 4643865e9171..387a786e7be1 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -181,7 +181,7 @@ static void shm_rcu_free(struct rcu_head *head) rcu); struct shmid_kernel *shp = container_of(ptr, struct shmid_kernel, shm_perm); - security_shm_free(shp); + security_shm_free(&shp->shm_perm); kvfree(shp); } @@ -554,7 +554,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) shp->mlock_user = NULL; shp->shm_perm.security = NULL; - error = security_shm_alloc(shp); + error = security_shm_alloc(&shp->shm_perm); if (error) { kvfree(shp); return error; @@ -635,10 +635,7 @@ no_file: */ static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg) { - struct shmid_kernel *shp; - - shp = container_of(ipcp, struct shmid_kernel, shm_perm); - return security_shm_associate(shp, shmflg); + return security_shm_associate(ipcp, shmflg); } /* @@ -835,7 +832,7 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, shp = container_of(ipcp, struct shmid_kernel, shm_perm); - err = security_shm_shmctl(shp, cmd); + err = security_shm_shmctl(&shp->shm_perm, cmd); if (err) goto out_unlock1; @@ -934,7 +931,7 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid, if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) goto out_unlock; - err = security_shm_shmctl(shp, cmd); + err = security_shm_shmctl(&shp->shm_perm, cmd); if (err) goto out_unlock; @@ -978,7 +975,7 @@ static int shmctl_do_lock(struct ipc_namespace *ns, int shmid, int cmd) } audit_ipc_obj(&(shp->shm_perm)); - err = security_shm_shmctl(shp, cmd); + err = security_shm_shmctl(&shp->shm_perm, cmd); if (err) goto out_unlock1; @@ -1348,7 +1345,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, if (ipcperms(ns, &shp->shm_perm, acc_mode)) goto out_unlock; - err = security_shm_shmat(shp, shmaddr, shmflg); + err = security_shm_shmat(&shp->shm_perm, shmaddr, shmflg); if (err) goto out_unlock; diff --git a/security/security.c b/security/security.c index d3b9aeb6b73b..77b69bd6f234 100644 --- a/security/security.c +++ b/security/security.c @@ -1195,27 +1195,27 @@ int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode); } -int security_shm_alloc(struct shmid_kernel *shp) +int security_shm_alloc(struct kern_ipc_perm *shp) { return call_int_hook(shm_alloc_security, 0, shp); } -void security_shm_free(struct shmid_kernel *shp) +void security_shm_free(struct kern_ipc_perm *shp) { call_void_hook(shm_free_security, shp); } -int security_shm_associate(struct shmid_kernel *shp, int shmflg) +int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) { return call_int_hook(shm_associate, 0, shp, shmflg); } -int security_shm_shmctl(struct shmid_kernel *shp, int cmd) +int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd) { return call_int_hook(shm_shmctl, 0, shp, cmd); } -int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg) +int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg) { return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index cce994e9fc0a..14f9e6c08273 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5674,53 +5674,53 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, } /* Shared Memory security operations */ -static int selinux_shm_alloc_security(struct shmid_kernel *shp) +static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) { struct ipc_security_struct *isec; struct common_audit_data ad; u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM); + rc = ipc_alloc_security(shp, SECCLASS_SHM); if (rc) return rc; - isec = shp->shm_perm.security; + isec = shp->security; ad.type = LSM_AUDIT_DATA_IPC; - ad.u.ipc_id = shp->shm_perm.key; + ad.u.ipc_id = shp->key; rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, SHM__CREATE, &ad); if (rc) { - ipc_free_security(&shp->shm_perm); + ipc_free_security(shp); return rc; } return 0; } -static void selinux_shm_free_security(struct shmid_kernel *shp) +static void selinux_shm_free_security(struct kern_ipc_perm *shp) { - ipc_free_security(&shp->shm_perm); + ipc_free_security(shp); } -static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) +static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) { struct ipc_security_struct *isec; struct common_audit_data ad; u32 sid = current_sid(); - isec = shp->shm_perm.security; + isec = shp->security; ad.type = LSM_AUDIT_DATA_IPC; - ad.u.ipc_id = shp->shm_perm.key; + ad.u.ipc_id = shp->key; return avc_has_perm(sid, isec->sid, SECCLASS_SHM, SHM__ASSOCIATE, &ad); } /* Note, at this point, shp is locked down */ -static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd) +static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd) { int perms; int err; @@ -5749,11 +5749,11 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd) return 0; } - err = ipc_has_perm(&shp->shm_perm, perms); + err = ipc_has_perm(shp, perms); return err; } -static int selinux_shm_shmat(struct shmid_kernel *shp, +static int selinux_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg) { u32 perms; @@ -5763,7 +5763,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, else perms = SHM__READ | SHM__WRITE; - return ipc_has_perm(&shp->shm_perm, perms); + return ipc_has_perm(shp, perms); } /* Semaphore security operations */ diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0402b8c1aec1..a3398c7f32c9 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2950,9 +2950,9 @@ static void smack_msg_msg_free_security(struct msg_msg *msg) * * Returns a pointer to the smack value */ -static struct smack_known *smack_of_shm(struct shmid_kernel *shp) +static struct smack_known *smack_of_shm(struct kern_ipc_perm *shp) { - return (struct smack_known *)shp->shm_perm.security; + return (struct smack_known *)shp->security; } /** @@ -2961,9 +2961,9 @@ static struct smack_known *smack_of_shm(struct shmid_kernel *shp) * * Returns 0 */ -static int smack_shm_alloc_security(struct shmid_kernel *shp) +static int smack_shm_alloc_security(struct kern_ipc_perm *shp) { - struct kern_ipc_perm *isp = &shp->shm_perm; + struct kern_ipc_perm *isp = shp; struct smack_known *skp = smk_of_current(); isp->security = skp; @@ -2976,9 +2976,9 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp) * * Clears the blob pointer */ -static void smack_shm_free_security(struct shmid_kernel *shp) +static void smack_shm_free_security(struct kern_ipc_perm *shp) { - struct kern_ipc_perm *isp = &shp->shm_perm; + struct kern_ipc_perm *isp = shp; isp->security = NULL; } @@ -2990,7 +2990,7 @@ static void smack_shm_free_security(struct shmid_kernel *shp) * * Returns 0 if current has the requested access, error code otherwise */ -static int smk_curacc_shm(struct shmid_kernel *shp, int access) +static int smk_curacc_shm(struct kern_ipc_perm *shp, int access) { struct smack_known *ssp = smack_of_shm(shp); struct smk_audit_info ad; @@ -2998,7 +2998,7 @@ static int smk_curacc_shm(struct shmid_kernel *shp, int access) #ifdef CONFIG_AUDIT smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); - ad.a.u.ipc_id = shp->shm_perm.id; + ad.a.u.ipc_id = shp->id; #endif rc = smk_curacc(ssp, access, &ad); rc = smk_bu_current("shm", ssp, access, rc); @@ -3012,7 +3012,7 @@ static int smk_curacc_shm(struct shmid_kernel *shp, int access) * * Returns 0 if current has the requested access, error code otherwise */ -static int smack_shm_associate(struct shmid_kernel *shp, int shmflg) +static int smack_shm_associate(struct kern_ipc_perm *shp, int shmflg) { int may; @@ -3027,7 +3027,7 @@ static int smack_shm_associate(struct shmid_kernel *shp, int shmflg) * * Returns 0 if current has the requested access, error code otherwise */ -static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd) +static int smack_shm_shmctl(struct kern_ipc_perm *shp, int cmd) { int may; @@ -3062,7 +3062,7 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd) * * Returns 0 if current has the requested access, error code otherwise */ -static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, +static int smack_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg) { int may; -- cgit v1.2.3 From d8c6e8543294428426578d74dc7aaf121e762d58 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 22 Mar 2018 21:22:26 -0500 Subject: msg/security: Pass kern_ipc_perm not msg_queue into the msg_queue security hooks All of the implementations of security hooks that take msg_queue only access q_perm the struct kern_ipc_perm member. This means the dependencies of the msg_queue security hooks can be simplified by passing the kern_ipc_perm member of msg_queue. Making this change will allow struct msg_queue to become private to ipc/msg.c. Signed-off-by: "Eric W. Biederman" --- include/linux/lsm_hooks.h | 12 ++++++------ include/linux/security.h | 25 ++++++++++++------------- ipc/msg.c | 18 ++++++++---------- security/security.c | 12 ++++++------ security/selinux/hooks.c | 36 ++++++++++++++++++------------------ security/smack/smack_lsm.c | 24 ++++++++++++------------ 6 files changed, 62 insertions(+), 65 deletions(-) (limited to 'include/linux/security.h') diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index cac7a8082c43..bde167fa2c51 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1575,13 +1575,13 @@ union security_list_options { int (*msg_msg_alloc_security)(struct msg_msg *msg); void (*msg_msg_free_security)(struct msg_msg *msg); - int (*msg_queue_alloc_security)(struct msg_queue *msq); - void (*msg_queue_free_security)(struct msg_queue *msq); - int (*msg_queue_associate)(struct msg_queue *msq, int msqflg); - int (*msg_queue_msgctl)(struct msg_queue *msq, int cmd); - int (*msg_queue_msgsnd)(struct msg_queue *msq, struct msg_msg *msg, + int (*msg_queue_alloc_security)(struct kern_ipc_perm *msq); + void (*msg_queue_free_security)(struct kern_ipc_perm *msq); + int (*msg_queue_associate)(struct kern_ipc_perm *msq, int msqflg); + int (*msg_queue_msgctl)(struct kern_ipc_perm *msq, int cmd); + int (*msg_queue_msgsnd)(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg); - int (*msg_queue_msgrcv)(struct msg_queue *msq, struct msg_msg *msg, + int (*msg_queue_msgrcv)(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode); diff --git a/include/linux/security.h b/include/linux/security.h index f390755808ea..128e1e4a5346 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -50,7 +50,6 @@ struct iattr; struct fown_struct; struct file_operations; struct msg_msg; -struct msg_queue; struct xattr; struct xfrm_sec_ctx; struct mm_struct; @@ -353,13 +352,13 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag); void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid); int security_msg_msg_alloc(struct msg_msg *msg); void security_msg_msg_free(struct msg_msg *msg); -int security_msg_queue_alloc(struct msg_queue *msq); -void security_msg_queue_free(struct msg_queue *msq); -int security_msg_queue_associate(struct msg_queue *msq, int msqflg); -int security_msg_queue_msgctl(struct msg_queue *msq, int cmd); -int security_msg_queue_msgsnd(struct msg_queue *msq, +int security_msg_queue_alloc(struct kern_ipc_perm *msq); +void security_msg_queue_free(struct kern_ipc_perm *msq); +int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg); +int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd); +int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg); -int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, +int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode); int security_shm_alloc(struct kern_ipc_perm *shp); void security_shm_free(struct kern_ipc_perm *shp); @@ -1043,32 +1042,32 @@ static inline int security_msg_msg_alloc(struct msg_msg *msg) static inline void security_msg_msg_free(struct msg_msg *msg) { } -static inline int security_msg_queue_alloc(struct msg_queue *msq) +static inline int security_msg_queue_alloc(struct kern_ipc_perm *msq) { return 0; } -static inline void security_msg_queue_free(struct msg_queue *msq) +static inline void security_msg_queue_free(struct kern_ipc_perm *msq) { } -static inline int security_msg_queue_associate(struct msg_queue *msq, +static inline int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) { return 0; } -static inline int security_msg_queue_msgctl(struct msg_queue *msq, int cmd) +static inline int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) { return 0; } -static inline int security_msg_queue_msgsnd(struct msg_queue *msq, +static inline int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) { return 0; } -static inline int security_msg_queue_msgrcv(struct msg_queue *msq, +static inline int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode) diff --git a/ipc/msg.c b/ipc/msg.c index 0dcc6699dc53..cdfab0825fce 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -101,7 +101,7 @@ static void msg_rcu_free(struct rcu_head *head) struct kern_ipc_perm *p = container_of(head, struct kern_ipc_perm, rcu); struct msg_queue *msq = container_of(p, struct msg_queue, q_perm); - security_msg_queue_free(msq); + security_msg_queue_free(&msq->q_perm); kvfree(msq); } @@ -127,7 +127,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params) msq->q_perm.key = key; msq->q_perm.security = NULL; - retval = security_msg_queue_alloc(msq); + retval = security_msg_queue_alloc(&msq->q_perm); if (retval) { kvfree(msq); return retval; @@ -258,9 +258,7 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) */ static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg) { - struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); - - return security_msg_queue_associate(msq, msgflg); + return security_msg_queue_associate(ipcp, msgflg); } SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg) @@ -380,7 +378,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, msq = container_of(ipcp, struct msg_queue, q_perm); - err = security_msg_queue_msgctl(msq, cmd); + err = security_msg_queue_msgctl(&msq->q_perm, cmd); if (err) goto out_unlock1; @@ -502,7 +500,7 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid, if (ipcperms(ns, &msq->q_perm, S_IRUGO)) goto out_unlock; - err = security_msg_queue_msgctl(msq, cmd); + err = security_msg_queue_msgctl(&msq->q_perm, cmd); if (err) goto out_unlock; @@ -718,7 +716,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg, list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) { if (testmsg(msg, msr->r_msgtype, msr->r_mode) && - !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, + !security_msg_queue_msgrcv(&msq->q_perm, msg, msr->r_tsk, msr->r_msgtype, msr->r_mode)) { list_del(&msr->r_list); @@ -784,7 +782,7 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext, goto out_unlock0; } - err = security_msg_queue_msgsnd(msq, msg, msgflg); + err = security_msg_queue_msgsnd(&msq->q_perm, msg, msgflg); if (err) goto out_unlock0; @@ -960,7 +958,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) list_for_each_entry(msg, &msq->q_messages, m_list) { if (testmsg(msg, *msgtyp, mode) && - !security_msg_queue_msgrcv(msq, msg, current, + !security_msg_queue_msgrcv(&msq->q_perm, msg, current, *msgtyp, mode)) { if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) { *msgtyp = msg->m_type - 1; diff --git a/security/security.c b/security/security.c index 77b69bd6f234..02d734e69955 100644 --- a/security/security.c +++ b/security/security.c @@ -1163,33 +1163,33 @@ void security_msg_msg_free(struct msg_msg *msg) call_void_hook(msg_msg_free_security, msg); } -int security_msg_queue_alloc(struct msg_queue *msq) +int security_msg_queue_alloc(struct kern_ipc_perm *msq) { return call_int_hook(msg_queue_alloc_security, 0, msq); } -void security_msg_queue_free(struct msg_queue *msq) +void security_msg_queue_free(struct kern_ipc_perm *msq) { call_void_hook(msg_queue_free_security, msq); } -int security_msg_queue_associate(struct msg_queue *msq, int msqflg) +int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) { return call_int_hook(msg_queue_associate, 0, msq, msqflg); } -int security_msg_queue_msgctl(struct msg_queue *msq, int cmd) +int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) { return call_int_hook(msg_queue_msgctl, 0, msq, cmd); } -int security_msg_queue_msgsnd(struct msg_queue *msq, +int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) { return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg); } -int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, +int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode) { return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 14f9e6c08273..925e546b5a87 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5532,52 +5532,52 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) } /* message queue security operations */ -static int selinux_msg_queue_alloc_security(struct msg_queue *msq) +static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) { struct ipc_security_struct *isec; struct common_audit_data ad; u32 sid = current_sid(); int rc; - rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ); + rc = ipc_alloc_security(msq, SECCLASS_MSGQ); if (rc) return rc; - isec = msq->q_perm.security; + isec = msq->security; ad.type = LSM_AUDIT_DATA_IPC; - ad.u.ipc_id = msq->q_perm.key; + ad.u.ipc_id = msq->key; rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, MSGQ__CREATE, &ad); if (rc) { - ipc_free_security(&msq->q_perm); + ipc_free_security(msq); return rc; } return 0; } -static void selinux_msg_queue_free_security(struct msg_queue *msq) +static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq) { - ipc_free_security(&msq->q_perm); + ipc_free_security(msq); } -static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) +static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) { struct ipc_security_struct *isec; struct common_audit_data ad; u32 sid = current_sid(); - isec = msq->q_perm.security; + isec = msq->security; ad.type = LSM_AUDIT_DATA_IPC; - ad.u.ipc_id = msq->q_perm.key; + ad.u.ipc_id = msq->key; return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, MSGQ__ASSOCIATE, &ad); } -static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) +static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) { int err; int perms; @@ -5602,11 +5602,11 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) return 0; } - err = ipc_has_perm(&msq->q_perm, perms); + err = ipc_has_perm(msq, perms); return err; } -static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg) +static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) { struct ipc_security_struct *isec; struct msg_security_struct *msec; @@ -5614,7 +5614,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, u32 sid = current_sid(); int rc; - isec = msq->q_perm.security; + isec = msq->security; msec = msg->security; /* @@ -5632,7 +5632,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, } ad.type = LSM_AUDIT_DATA_IPC; - ad.u.ipc_id = msq->q_perm.key; + ad.u.ipc_id = msq->key; /* Can this process write to the queue? */ rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, @@ -5649,7 +5649,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, return rc; } -static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, +static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode) { @@ -5659,11 +5659,11 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, u32 sid = task_sid(target); int rc; - isec = msq->q_perm.security; + isec = msq->security; msec = msg->security; ad.type = LSM_AUDIT_DATA_IPC; - ad.u.ipc_id = msq->q_perm.key; + ad.u.ipc_id = msq->key; rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, MSGQ__READ, &ad); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index a3398c7f32c9..d960c2ea8d79 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3210,9 +3210,9 @@ static int smack_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, * * Returns 0 */ -static int smack_msg_queue_alloc_security(struct msg_queue *msq) +static int smack_msg_queue_alloc_security(struct kern_ipc_perm *msq) { - struct kern_ipc_perm *kisp = &msq->q_perm; + struct kern_ipc_perm *kisp = msq; struct smack_known *skp = smk_of_current(); kisp->security = skp; @@ -3225,9 +3225,9 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq) * * Clears the blob pointer */ -static void smack_msg_queue_free_security(struct msg_queue *msq) +static void smack_msg_queue_free_security(struct kern_ipc_perm *msq) { - struct kern_ipc_perm *kisp = &msq->q_perm; + struct kern_ipc_perm *kisp = msq; kisp->security = NULL; } @@ -3238,9 +3238,9 @@ static void smack_msg_queue_free_security(struct msg_queue *msq) * * Returns a pointer to the smack label entry */ -static struct smack_known *smack_of_msq(struct msg_queue *msq) +static struct smack_known *smack_of_msq(struct kern_ipc_perm *msq) { - return (struct smack_known *)msq->q_perm.security; + return (struct smack_known *)msq->security; } /** @@ -3250,7 +3250,7 @@ static struct smack_known *smack_of_msq(struct msg_queue *msq) * * return 0 if current has access, error otherwise */ -static int smk_curacc_msq(struct msg_queue *msq, int access) +static int smk_curacc_msq(struct kern_ipc_perm *msq, int access) { struct smack_known *msp = smack_of_msq(msq); struct smk_audit_info ad; @@ -3258,7 +3258,7 @@ static int smk_curacc_msq(struct msg_queue *msq, int access) #ifdef CONFIG_AUDIT smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); - ad.a.u.ipc_id = msq->q_perm.id; + ad.a.u.ipc_id = msq->id; #endif rc = smk_curacc(msp, access, &ad); rc = smk_bu_current("msq", msp, access, rc); @@ -3272,7 +3272,7 @@ static int smk_curacc_msq(struct msg_queue *msq, int access) * * Returns 0 if current has the requested access, error code otherwise */ -static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg) +static int smack_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) { int may; @@ -3287,7 +3287,7 @@ static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg) * * Returns 0 if current has the requested access, error code otherwise */ -static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd) +static int smack_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) { int may; @@ -3321,7 +3321,7 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd) * * Returns 0 if current has the requested access, error code otherwise */ -static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, +static int smack_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) { int may; @@ -3340,7 +3340,7 @@ static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, * * Returns 0 if current has read and write access, error code otherwise */ -static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, +static int smack_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode) { return smk_curacc_msq(msq, MAY_READWRITE); -- cgit v1.2.3 From 3ec30113264a7bcd389f51d1738e42da0f41bb5a Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 8 Jan 2018 13:36:19 -0800 Subject: security: Add a cred_getsecid hook For IMA purposes, we want to be able to obtain the prepared secid in the bprm structure before the credentials are committed. Add a cred_getsecid hook that makes this possible. Signed-off-by: Matthew Garrett Acked-by: Paul Moore Cc: Paul Moore Cc: Stephen Smalley Cc: Casey Schaufler Signed-off-by: Mimi Zohar --- include/linux/lsm_hooks.h | 6 ++++++ include/linux/security.h | 1 + security/security.c | 7 +++++++ security/selinux/hooks.c | 6 ++++++ security/smack/smack_lsm.c | 18 ++++++++++++++++++ 5 files changed, 38 insertions(+) (limited to 'include/linux/security.h') diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index e0ac011d07a5..bbc6a1240b2e 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -554,6 +554,10 @@ * @new points to the new credentials. * @old points to the original credentials. * Transfer data from original creds to new creds + * @cred_getsecid: + * Retrieve the security identifier of the cred structure @c + * @c contains the credentials, secid will be placed into @secid. + * In case of failure, @secid will be set to zero. * @kernel_act_as: * Set the credentials for a kernel service to act as (subjective context). * @new points to the credentials to be modified. @@ -1542,6 +1546,7 @@ union security_list_options { int (*cred_prepare)(struct cred *new, const struct cred *old, gfp_t gfp); void (*cred_transfer)(struct cred *new, const struct cred *old); + void (*cred_getsecid)(const struct cred *c, u32 *secid); int (*kernel_act_as)(struct cred *new, u32 secid); int (*kernel_create_files_as)(struct cred *new, struct inode *inode); int (*kernel_module_request)(char *kmod_name); @@ -1825,6 +1830,7 @@ struct security_hook_heads { struct list_head cred_free; struct list_head cred_prepare; struct list_head cred_transfer; + struct list_head cred_getsecid; struct list_head kernel_act_as; struct list_head kernel_create_files_as; struct list_head kernel_read_file; diff --git a/include/linux/security.h b/include/linux/security.h index 3f5fd988ee87..116b8717a98c 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -324,6 +324,7 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); void security_cred_free(struct cred *cred); int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); void security_transfer_creds(struct cred *new, const struct cred *old); +void security_cred_getsecid(const struct cred *c, u32 *secid); int security_kernel_act_as(struct cred *new, u32 secid); int security_kernel_create_files_as(struct cred *new, struct inode *inode); int security_kernel_module_request(char *kmod_name); diff --git a/security/security.c b/security/security.c index 14c291910d25..957e8bee3554 100644 --- a/security/security.c +++ b/security/security.c @@ -1005,6 +1005,13 @@ void security_transfer_creds(struct cred *new, const struct cred *old) call_void_hook(cred_transfer, new, old); } +void security_cred_getsecid(const struct cred *c, u32 *secid) +{ + *secid = 0; + call_void_hook(cred_getsecid, c, secid); +} +EXPORT_SYMBOL(security_cred_getsecid); + int security_kernel_act_as(struct cred *new, u32 secid) { return call_int_hook(kernel_act_as, 0, new, secid); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8abd542c6b7c..b7d4473edbde 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3844,6 +3844,11 @@ static void selinux_cred_transfer(struct cred *new, const struct cred *old) *tsec = *old_tsec; } +static void selinux_cred_getsecid(const struct cred *c, u32 *secid) +{ + *secid = cred_sid(c); +} + /* * set the security data for a kernel service * - all the creation contexts are set to unlabelled @@ -6482,6 +6487,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(cred_free, selinux_cred_free), LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare), LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer), + LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid), LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as), LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as), LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index feada2665322..ed20d36c1149 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2049,6 +2049,23 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) /* cbs copy rule list */ } +/** + * smack_cred_getsecid - get the secid corresponding to a creds structure + * @c: the object creds + * @secid: where to put the result + * + * Sets the secid to contain a u32 version of the smack label. + */ +static void smack_cred_getsecid(const struct cred *c, u32 *secid) +{ + struct smack_known *skp; + + rcu_read_lock(); + skp = smk_of_task(c->security); + *secid = skp->smk_secid; + rcu_read_unlock(); +} + /** * smack_kernel_act_as - Set the subjective context in a set of credentials * @new: points to the set of credentials to be modified. @@ -4733,6 +4750,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(cred_free, smack_cred_free), LSM_HOOK_INIT(cred_prepare, smack_cred_prepare), LSM_HOOK_INIT(cred_transfer, smack_cred_transfer), + LSM_HOOK_INIT(cred_getsecid, smack_cred_getsecid), LSM_HOOK_INIT(kernel_act_as, smack_kernel_act_as), LSM_HOOK_INIT(kernel_create_files_as, smack_kernel_create_files_as), LSM_HOOK_INIT(task_setpgid, smack_task_setpgid), -- cgit v1.2.3