From ed5d44d42c95e8a13bb54e614d2269c8740667f9 Mon Sep 17 00:00:00 2001 From: Frederick Lawler Date: Mon, 15 Aug 2022 11:20:28 -0500 Subject: selinux: Implement userns_create hook Unprivileged user namespace creation is an intended feature to enable sandboxing, however this feature is often used to as an initial step to perform a privilege escalation attack. This patch implements a new user_namespace { create } access control permission to restrict which domains allow or deny user namespace creation. This is necessary for system administrators to quickly protect their systems while waiting for vulnerability patches to be applied. This permission can be used in the following way: allow domA_t domA_t : user_namespace { create }; Signed-off-by: Frederick Lawler Signed-off-by: Paul Moore --- security/selinux/hooks.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 79573504783b..b9f1078450b3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4221,6 +4221,14 @@ static void selinux_task_to_inode(struct task_struct *p, spin_unlock(&isec->lock); } +static int selinux_userns_create(const struct cred *cred) +{ + u32 sid = current_sid(); + + return avc_has_perm(&selinux_state, sid, sid, SECCLASS_USER_NAMESPACE, + USER_NAMESPACE__CREATE, NULL); +} + /* Returns error only if unable to parse addresses */ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct common_audit_data *ad, u8 *proto) @@ -7111,6 +7119,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(task_movememory, selinux_task_movememory), LSM_HOOK_INIT(task_kill, selinux_task_kill), LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode), + LSM_HOOK_INIT(userns_create, selinux_userns_create), LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission), LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid), -- cgit v1.2.3 From f4d653dcaa4e4056e1630423e6a8ece4869b544f Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 10 Aug 2022 15:55:36 -0400 Subject: selinux: implement the security_uring_cmd() LSM hook Add a SELinux access control for the iouring IORING_OP_URING_CMD command. This includes the addition of a new permission in the existing "io_uring" object class: "cmd". The subject of the new permission check is the domain of the process requesting access, the object is the open file which points to the device/file that is the target of the IORING_OP_URING_CMD operation. A sample policy rule is shown below: allow :io_uring { cmd }; Cc: stable@vger.kernel.org Fixes: ee692a21e9bf ("fs,io_uring: add infrastructure for uring-cmd") Signed-off-by: Paul Moore --- security/selinux/hooks.c | 24 ++++++++++++++++++++++++ security/selinux/include/classmap.h | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 79573504783b..03bca97c8b29 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -91,6 +91,7 @@ #include #include #include +#include #include "avc.h" #include "objsec.h" @@ -6987,6 +6988,28 @@ static int selinux_uring_sqpoll(void) return avc_has_perm(&selinux_state, sid, sid, SECCLASS_IO_URING, IO_URING__SQPOLL, NULL); } + +/** + * selinux_uring_cmd - check if IORING_OP_URING_CMD is allowed + * @ioucmd: the io_uring command structure + * + * Check to see if the current domain is allowed to execute an + * IORING_OP_URING_CMD against the device/file specified in @ioucmd. + * + */ +static int selinux_uring_cmd(struct io_uring_cmd *ioucmd) +{ + struct file *file = ioucmd->file; + struct inode *inode = file_inode(file); + struct inode_security_struct *isec = selinux_inode(inode); + struct common_audit_data ad; + + ad.type = LSM_AUDIT_DATA_FILE; + ad.u.file = file; + + return avc_has_perm(&selinux_state, current_sid(), isec->sid, + SECCLASS_IO_URING, IO_URING__CMD, &ad); +} #endif /* CONFIG_IO_URING */ /* @@ -7231,6 +7254,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { #ifdef CONFIG_IO_URING LSM_HOOK_INIT(uring_override_creds, selinux_uring_override_creds), LSM_HOOK_INIT(uring_sqpoll, selinux_uring_sqpoll), + LSM_HOOK_INIT(uring_cmd, selinux_uring_cmd), #endif /* diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index ff757ae5f253..1c2f41ff4e55 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -253,7 +253,7 @@ const struct security_class_mapping secclass_map[] = { { "anon_inode", { COMMON_FILE_PERMS, NULL } }, { "io_uring", - { "override_creds", "sqpoll", NULL } }, + { "override_creds", "sqpoll", "cmd", NULL } }, { NULL } }; -- cgit v1.2.3 From c8e477c649b40c1a073b7a843d89e51dc0037db7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 30 Jan 2022 19:57:52 -0500 Subject: ->getprocattr(): attribute name is const char *, TYVM... cast of ->d_name.name to char * is completely wrong - nothing is allowed to modify its contents. Reviewed-by: Christian Brauner (Microsoft) Acked-by: Paul Moore Acked-by: Casey Schaufler Signed-off-by: Al Viro --- fs/proc/base.c | 2 +- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 4 ++-- security/apparmor/lsm.c | 2 +- security/security.c | 4 ++-- security/selinux/hooks.c | 2 +- security/smack/smack_lsm.c | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/fs/proc/base.c b/fs/proc/base.c index 93f7e3d971e4..e347b8ce140c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2728,7 +2728,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, return -ESRCH; length = security_getprocattr(task, PROC_I(inode)->op.lsm, - (char*)file->f_path.dentry->d_name.name, + file->f_path.dentry->d_name.name, &p); put_task_struct(task); if (length > 0) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 806448173033..03360d27bedf 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -253,7 +253,7 @@ LSM_HOOK(int, 0, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb) LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, struct inode *inode) -LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, char *name, +LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, char **value) LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size) LSM_HOOK(int, 0, ismaclabel, const char *name) diff --git a/include/linux/security.h b/include/linux/security.h index 1bc362cb413f..93488c01d9bd 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -461,7 +461,7 @@ 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, const char *lsm, char *name, +int security_getprocattr(struct task_struct *p, const char *lsm, const char *name, char **value); int security_setprocattr(const char *lsm, const char *name, void *value, size_t size); @@ -1301,7 +1301,7 @@ static inline void security_d_instantiate(struct dentry *dentry, { } static inline int security_getprocattr(struct task_struct *p, const char *lsm, - char *name, char **value) + const char *name, char **value) { return -EINVAL; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index e29cade7b662..f56070270c69 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -614,7 +614,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path, return error; } -static int apparmor_getprocattr(struct task_struct *task, char *name, +static int apparmor_getprocattr(struct task_struct *task, const char *name, char **value) { int error = -ENOENT; diff --git a/security/security.c b/security/security.c index 14d30fec8a00..d8227531e2fd 100644 --- a/security/security.c +++ b/security/security.c @@ -2057,8 +2057,8 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) } EXPORT_SYMBOL(security_d_instantiate); -int security_getprocattr(struct task_struct *p, const char *lsm, char *name, - char **value) +int security_getprocattr(struct task_struct *p, const char *lsm, + const char *name, char **value) { struct security_hook_list *hp; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 79573504783b..c8168d19fb96 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6327,7 +6327,7 @@ static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode) } static int selinux_getprocattr(struct task_struct *p, - char *name, char **value) + const char *name, char **value) { const struct task_security_struct *__tsec; u32 sid; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 001831458fa2..434b348d8fcd 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3479,7 +3479,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * * Returns the length of the smack label or an error code */ -static int smack_getprocattr(struct task_struct *p, char *name, char **value) +static int smack_getprocattr(struct task_struct *p, const char *name, char **value) { struct smack_known *skp = smk_of_task_struct_obj(p); char *cp; -- cgit v1.2.3 From 09b71adab09570fcc715ff31a6835d0e445e4a54 Mon Sep 17 00:00:00 2001 From: Xu Panda Date: Mon, 12 Sep 2022 09:17:19 +0000 Subject: selinux: remove the unneeded result variable Return the value avc_has_perm() directly instead of storing it in another redundant variable. Reported-by: Zeal Robot Signed-off-by: Xu Panda [PM: subject line tweak] Signed-off-by: Paul Moore --- security/selinux/hooks.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 79573504783b..6e87abbae47c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5986,7 +5986,6 @@ 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; isec = selinux_ipc(msq); ipc_init_security(isec, SECCLASS_MSGQ); @@ -5994,10 +5993,9 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - rc = avc_has_perm(&selinux_state, - sid, isec->sid, SECCLASS_MSGQ, - MSGQ__CREATE, &ad); - return rc; + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_MSGQ, + MSGQ__CREATE, &ad); } static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) @@ -6125,7 +6123,6 @@ 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; isec = selinux_ipc(shp); ipc_init_security(isec, SECCLASS_SHM); @@ -6133,10 +6130,9 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - rc = avc_has_perm(&selinux_state, - sid, isec->sid, SECCLASS_SHM, - SHM__CREATE, &ad); - return rc; + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_SHM, + SHM__CREATE, &ad); } static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) @@ -6210,7 +6206,6 @@ 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; isec = selinux_ipc(sma); ipc_init_security(isec, SECCLASS_SEM); @@ -6218,10 +6213,9 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - rc = avc_has_perm(&selinux_state, - sid, isec->sid, SECCLASS_SEM, - SEM__CREATE, &ad); - return rc; + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_SEM, + SEM__CREATE, &ad); } static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) -- cgit v1.2.3