lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <20250610172226.1470741-23-stephen.smalley.work@gmail.com> Date: Tue, 10 Jun 2025 13:21:53 -0400 From: Stephen Smalley <stephen.smalley.work@...il.com> To: selinux@...r.kernel.org Cc: paul@...l-moore.com, omosnace@...hat.com, netdev@...r.kernel.org, Stephen Smalley <stephen.smalley.work@...il.com> Subject: [PATCH v4 22/42] selinux: introduce cred_task_has_perm() Introduce cred_task_has_perm() for checking permissions between a cred and a target task against not only the current SELinux namespace but all ancestor namespaces too. Convert existing cred-task permission checks in the SELinux hook functions to use cred_task_has_perm() instead of calling avc_has_perm(). Signed-off-by: Stephen Smalley <stephen.smalley.work@...il.com> --- security/selinux/avc.c | 44 +++++++++++++++++ security/selinux/hooks.c | 89 +++++++++++++--------------------- security/selinux/include/avc.h | 4 ++ 3 files changed, 81 insertions(+), 56 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 8db199f06a2a..577743a01c5a 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1247,6 +1247,50 @@ int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, return rc; } +static u32 task_sid_obj_for_state(const struct task_struct *p, + const struct selinux_state *state) +{ + const struct task_security_struct *tsec; + u32 sid; + + rcu_read_lock(); + tsec = selinux_cred(__task_cred(p)); + while (tsec->state != state && tsec->parent_cred) + tsec = selinux_cred(tsec->parent_cred); + if (tsec->state == state) + sid = tsec->sid; + else + sid = SECINITSID_UNLABELED; + rcu_read_unlock(); + return sid; +} + +int cred_task_has_perm(const struct cred *cred, const struct task_struct *p, + u16 tclass, u32 requested, + struct common_audit_data *ad) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + u32 tsid; + int rc; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + tsid = task_sid_obj_for_state(p, state); + + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + u32 avc_policy_seqno(struct selinux_state *state) { return state->avc->avc_cache.latest_notif; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1c511d3abac3..93df1d969547 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2154,15 +2154,12 @@ static int selinux_binder_transfer_file(const struct cred *from, static int selinux_ptrace_access_check(struct task_struct *child, unsigned int mode) { - u32 sid = current_sid(); - u32 csid = task_sid_obj(child); - if (mode & PTRACE_MODE_READ) - return avc_has_perm(current_selinux_state, - sid, csid, SECCLASS_FILE, FILE__READ, NULL); + return cred_task_has_perm(current_cred(), child, + SECCLASS_FILE, FILE__READ, NULL); - return avc_has_perm(current_selinux_state, - sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); + return cred_task_has_perm(current_cred(), child, SECCLASS_PROCESS, + PROCESS__PTRACE, NULL); } static int selinux_ptrace_traceme(struct task_struct *parent) @@ -2175,9 +2172,8 @@ static int selinux_ptrace_traceme(struct task_struct *parent) static int selinux_capget(const struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(target), SECCLASS_PROCESS, - PROCESS__GETCAP, NULL); + return cred_task_has_perm(current_cred(), target, SECCLASS_PROCESS, + PROCESS__GETCAP, NULL); } static int selinux_capset(struct cred *new, const struct cred *old, @@ -4436,23 +4432,20 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents) static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETPGID, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETPGID, NULL); } static int selinux_task_getpgid(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__GETPGID, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__GETPGID, NULL); } static int selinux_task_getsid(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__GETSESSION, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__GETSESSION, NULL); } static void selinux_current_getlsmprop_subj(struct lsm_prop *prop) @@ -4468,23 +4461,20 @@ static void selinux_task_getlsmprop_obj(struct task_struct *p, static int selinux_task_setnice(struct task_struct *p, int nice) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETSCHED, NULL); } static int selinux_task_setioprio(struct task_struct *p, int ioprio) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETSCHED, NULL); } static int selinux_task_getioprio(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__GETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__GETSCHED, NULL); } static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred, @@ -4513,56 +4503,43 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, later be used as a safe reset point for the soft limit upon context transitions. See selinux_bprm_committing_creds. */ if (old_rlim->rlim_max != new_rlim->rlim_max) - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), - SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETRLIMIT, NULL); return 0; } static int selinux_task_setscheduler(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETSCHED, NULL); } static int selinux_task_getscheduler(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__GETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__GETSCHED, NULL); } static int selinux_task_movememory(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETSCHED, NULL); } static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { - struct selinux_state *state; - u32 secid; u32 perm; - if (cred) - state = cred_selinux_state(cred); - else - state = current_selinux_state; + if (!cred) + cred = current_cred(); if (!sig) perm = PROCESS__SIGNULL; /* null signal; existence test */ else perm = signal_to_av(sig); - if (!cred) - secid = current_sid(); - else - secid = cred_sid(cred); - return avc_has_perm(state, secid, task_sid_obj(p), - SECCLASS_PROCESS, perm, NULL); + return cred_task_has_perm(cred, p, SECCLASS_PROCESS, perm, NULL); } static void selinux_task_to_inode(struct task_struct *p, @@ -6706,14 +6683,14 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, u32 len; rcu_read_lock(); - tsec = task_security(p); if (p != current) { - error = avc_has_perm(current_selinux_state, - current_sid(), tsec->sid, - SECCLASS_PROCESS, PROCESS__GETATTR, NULL); + error = cred_task_has_perm(current_cred(), p, + SECCLASS_PROCESS, + PROCESS__GETATTR, NULL); if (error) goto err_unlock; } + tsec = task_security(p); switch (attr) { case LSM_ATTR_CURRENT: sid = tsec->sid; diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 833eec9b5fac..ce2d1b71e0a2 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -146,6 +146,10 @@ int avc_has_extended_perms(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, u32 requested, u8 driver, u8 base_perm, u8 perm, struct common_audit_data *ad); +int cred_task_has_perm(const struct cred *cred, const struct task_struct *p, + u16 tclass, u32 requested, + struct common_audit_data *auditdata); + u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 -- 2.49.0
Powered by blists - more mailing lists