From d91c1ab470edd94e52bca738e53b5ad0f0247176 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 16 Jun 2023 18:02:43 -0400 Subject: selinux: cleanup the policycap accessor functions In the process of reverting back to directly accessing the global selinux_state pointer we left behind some artifacts in the selinux_policycap_XXX() helper functions. This patch cleans up some of that left-behind cruft. Signed-off-by: Paul Moore --- security/selinux/include/security.h | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) (limited to 'security') diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 3b605f39e040..60eb161a0e5a 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -148,58 +148,45 @@ static inline bool checkreqprot_get(void) static inline bool selinux_policycap_netpeer(void) { - struct selinux_state *state = &selinux_state; - - return READ_ONCE(state->policycap[POLICYDB_CAP_NETPEER]); + return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_NETPEER]); } static inline bool selinux_policycap_openperm(void) { - struct selinux_state *state = &selinux_state; - - return READ_ONCE(state->policycap[POLICYDB_CAP_OPENPERM]); + return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_OPENPERM]); } static inline bool selinux_policycap_extsockclass(void) { - struct selinux_state *state = &selinux_state; - - return READ_ONCE(state->policycap[POLICYDB_CAP_EXTSOCKCLASS]); + return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_EXTSOCKCLASS]); } static inline bool selinux_policycap_alwaysnetwork(void) { - struct selinux_state *state = &selinux_state; - - return READ_ONCE(state->policycap[POLICYDB_CAP_ALWAYSNETWORK]); + return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_ALWAYSNETWORK]); } static inline bool selinux_policycap_cgroupseclabel(void) { - struct selinux_state *state = &selinux_state; - - return READ_ONCE(state->policycap[POLICYDB_CAP_CGROUPSECLABEL]); + return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_CGROUPSECLABEL]); } static inline bool selinux_policycap_nnp_nosuid_transition(void) { - struct selinux_state *state = &selinux_state; - - return READ_ONCE(state->policycap[POLICYDB_CAP_NNP_NOSUID_TRANSITION]); + return READ_ONCE( + selinux_state.policycap[POLICYDB_CAP_NNP_NOSUID_TRANSITION]); } static inline bool selinux_policycap_genfs_seclabel_symlinks(void) { - struct selinux_state *state = &selinux_state; - - return READ_ONCE(state->policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]); + return READ_ONCE( + selinux_state.policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]); } static inline bool selinux_policycap_ioctl_skip_cloexec(void) { - struct selinux_state *state = &selinux_state; - - return READ_ONCE(state->policycap[POLICYDB_CAP_IOCTL_SKIP_CLOEXEC]); + return READ_ONCE( + selinux_state.policycap[POLICYDB_CAP_IOCTL_SKIP_CLOEXEC]); } struct selinux_policy_convert_data; -- cgit v1.2.3 From 5b0eea835d4e9cb5229e696c5763929fc2394f39 Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Tue, 20 Jun 2023 15:12:22 +0200 Subject: selinux: introduce an initial SID for early boot processes Currently, SELinux doesn't allow distinguishing between kernel threads and userspace processes that are started before the policy is first loaded - both get the label corresponding to the kernel SID. The only way a process that persists from early boot can get a meaningful label is by doing a voluntary dyntransition or re-executing itself. Reusing the kernel label for userspace processes is problematic for several reasons: 1. The kernel is considered to be a privileged domain and generally needs to have a wide range of permissions allowed to work correctly, which prevents the policy writer from effectively hardening against early boot processes that might remain running unintentionally after the policy is loaded (they represent a potential extra attack surface that should be mitigated). 2. Despite the kernel being treated as a privileged domain, the policy writer may want to impose certain special limitations on kernel threads that may conflict with the requirements of intentional early boot processes. For example, it is a good hardening practice to limit what executables the kernel can execute as usermode helpers and to confine the resulting usermode helper processes. However, a (legitimate) process surviving from early boot may need to execute a different set of executables. 3. As currently implemented, overlayfs remembers the security context of the process that created an overlayfs mount and uses it to bound subsequent operations on files using this context. If an overlayfs mount is created before the SELinux policy is loaded, these "mounter" checks are made against the kernel context, which may clash with restrictions on the kernel domain (see 2.). To resolve this, introduce a new initial SID (reusing the slot of the former "init" initial SID) that will be assigned to any userspace process started before the policy is first loaded. This is easy to do, as we can simply label any process that goes through the bprm_creds_for_exec LSM hook with the new init-SID instead of propagating the kernel SID from the parent. To provide backwards compatibility for existing policies that are unaware of this new semantic of the "init" initial SID, introduce a new policy capability "userspace_initial_context" and set the "init" SID to the same context as the "kernel" SID unless this capability is set by the policy. Signed-off-by: Ondrej Mosnacek Signed-off-by: Paul Moore --- security/selinux/hooks.c | 28 ++++++++++++++++++++++++ security/selinux/include/initial_sid_to_string.h | 2 +- security/selinux/include/policycap.h | 1 + security/selinux/include/policycap_names.h | 3 ++- security/selinux/include/security.h | 6 +++++ security/selinux/ss/policydb.c | 27 +++++++++++++++++++++++ 6 files changed, 65 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d06e350fedee..b8a8a4f0f2ad 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2288,6 +2288,19 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) new_tsec->keycreate_sid = 0; new_tsec->sockcreate_sid = 0; + /* + * Before policy is loaded, label any task outside kernel space + * as SECINITSID_INIT, so that any userspace tasks surviving from + * early boot end up with a label different from SECINITSID_KERNEL + * (if the policy chooses to set SECINITSID_INIT != SECINITSID_KERNEL). + */ + if (!selinux_initialized()) { + new_tsec->sid = SECINITSID_INIT; + /* also clear the exec_sid just in case */ + new_tsec->exec_sid = 0; + return 0; + } + if (old_tsec->exec_sid) { new_tsec->sid = old_tsec->exec_sid; /* Reset exec SID on execve. */ @@ -4504,6 +4517,21 @@ static int sock_has_perm(struct sock *sk, u32 perms) if (sksec->sid == SECINITSID_KERNEL) return 0; + /* + * Before POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, sockets that + * inherited the kernel context from early boot used to be skipped + * here, so preserve that behavior unless the capability is set. + * + * By setting the capability the policy signals that it is ready + * for this quirk to be fixed. Note that sockets created by a kernel + * thread or a usermode helper executed without a transition will + * still be skipped in this check regardless of the policycap + * setting. + */ + if (!selinux_policycap_userspace_initial_context() && + sksec->sid == SECINITSID_INIT) + return 0; + ad.type = LSM_AUDIT_DATA_NET; ad.u.net = &net; ad.u.net->sk = sk; diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h index ecc6e74fa09b..5e5f0993dac2 100644 --- a/security/selinux/include/initial_sid_to_string.h +++ b/security/selinux/include/initial_sid_to_string.h @@ -10,7 +10,7 @@ static const char *const initial_sid_to_string[] = { NULL, "file", NULL, - NULL, + "init", "any_socket", "port", "netif", diff --git a/security/selinux/include/policycap.h b/security/selinux/include/policycap.h index f35d3458e71d..c7373e6effe5 100644 --- a/security/selinux/include/policycap.h +++ b/security/selinux/include/policycap.h @@ -12,6 +12,7 @@ enum { POLICYDB_CAP_NNP_NOSUID_TRANSITION, POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS, POLICYDB_CAP_IOCTL_SKIP_CLOEXEC, + POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, __POLICYDB_CAP_MAX }; #define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1) diff --git a/security/selinux/include/policycap_names.h b/security/selinux/include/policycap_names.h index 2a87fc3702b8..28e4c9ee2399 100644 --- a/security/selinux/include/policycap_names.h +++ b/security/selinux/include/policycap_names.h @@ -13,7 +13,8 @@ const char *const selinux_policycap_names[__POLICYDB_CAP_MAX] = { "cgroup_seclabel", "nnp_nosuid_transition", "genfs_seclabel_symlinks", - "ioctl_skip_cloexec" + "ioctl_skip_cloexec", + "userspace_initial_context", }; #endif /* _SELINUX_POLICYCAP_NAMES_H_ */ diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 60eb161a0e5a..665c4e5bae99 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -189,6 +189,12 @@ static inline bool selinux_policycap_ioctl_skip_cloexec(void) selinux_state.policycap[POLICYDB_CAP_IOCTL_SKIP_CLOEXEC]); } +static inline bool selinux_policycap_userspace_initial_context(void) +{ + return READ_ONCE( + selinux_state.policycap[POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT]); +} + struct selinux_policy_convert_data; struct selinux_load_state { diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 31b08b34c722..cfe77ef24ee2 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -863,6 +863,8 @@ void policydb_destroy(struct policydb *p) int policydb_load_isids(struct policydb *p, struct sidtab *s) { struct ocontext *head, *c; + bool isid_init_supported = ebitmap_get_bit(&p->policycaps, + POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT); int rc; rc = sidtab_init(s); @@ -886,6 +888,13 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) if (!name) continue; + /* + * Also ignore SECINITSID_INIT if the policy doesn't declare + * support for it + */ + if (sid == SECINITSID_INIT && !isid_init_supported) + continue; + rc = sidtab_set_initial(s, sid, &c->context[0]); if (rc) { pr_err("SELinux: unable to load initial SID %s.\n", @@ -893,6 +902,24 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) sidtab_destroy(s); return rc; } + + /* + * If the policy doesn't support the "userspace_initial_context" + * capability, set SECINITSID_INIT to the same context as + * SECINITSID_KERNEL. This ensures the same behavior as before + * the reintroduction of SECINITSID_INIT, where all tasks + * started before policy load would initially get the context + * corresponding to SECINITSID_KERNEL. + */ + if (sid == SECINITSID_KERNEL && !isid_init_supported) { + rc = sidtab_set_initial(s, SECINITSID_INIT, &c->context[0]); + if (rc) { + pr_err("SELinux: unable to load initial SID %s.\n", + name); + sidtab_destroy(s); + return rc; + } + } } return 0; } -- cgit v1.2.3 From bbea03f474850b3bce329aa3b990b1a4853136f0 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:16 +0200 Subject: selinux: check for multiplication overflow in put_entry() The function is always inlined and most of the time both relevant arguments are compile time constants, allowing compilers to elide the check. Also the function is part of outputting the policy, which is not performance critical. Also convert the type of the third parameter into a size_t, since it should always be a non-negative number of elements. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/policydb.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 74b63ed1173f..6b4ad8e91265 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -366,9 +366,12 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes) return 0; } -static inline int put_entry(const void *buf, size_t bytes, int num, struct policy_file *fp) +static inline int put_entry(const void *buf, size_t bytes, size_t num, struct policy_file *fp) { - size_t len = bytes * num; + size_t len; + + if (unlikely(check_mul_overflow(bytes, num, &len))) + return -EINVAL; if (len > fp->len) return -EINVAL; -- cgit v1.2.3 From f785c54101e01f8e5f84464f8755671246b13794 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:18 +0200 Subject: selinux: avoid avtab overflows Prevent inserting more than the supported U32_MAX number of entries. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/avtab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 6766edc0fe68..7d21de48c28d 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -110,7 +110,7 @@ static int avtab_insert(struct avtab *h, const struct avtab_key *key, struct avtab_node *prev, *cur, *newnode; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h || !h->nslot) + if (!h || !h->nslot || h->nel == U32_MAX) return -EINVAL; hvalue = avtab_hash(key, h->mask); @@ -156,7 +156,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_node *prev, *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h || !h->nslot) + if (!h || !h->nslot || h->nel == U32_MAX) return NULL; hvalue = avtab_hash(key, h->mask); for (prev = NULL, cur = h->htable[hvalue]; -- cgit v1.2.3 From 1f270f1c34127e5a65ba5aaf574f313f0693fcfa Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:24 +0200 Subject: selinux: consistently use u32 as sequence number type in the status code Align the type with the one used in selinux_notify_policy_change() and the sequence member of struct selinux_kernel_status. Signed-off-by: Christian Göttsche [PM: subject line tweaks] Signed-off-by: Paul Moore --- security/selinux/include/security.h | 2 +- security/selinux/status.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 665c4e5bae99..08840aa0782d 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -376,7 +376,7 @@ struct selinux_kernel_status { } __packed; extern void selinux_status_update_setenforce(int enforcing); -extern void selinux_status_update_policyload(int seqno); +extern void selinux_status_update_policyload(u32 seqno); extern void selinux_complete_init(void); extern struct path selinux_null; extern void selnl_notify_setenforce(int val); diff --git a/security/selinux/status.c b/security/selinux/status.c index 19ef929a075c..e436e4975adc 100644 --- a/security/selinux/status.c +++ b/security/selinux/status.c @@ -101,7 +101,7 @@ void selinux_status_update_setenforce(int enforcing) * It updates status of the times of policy reloaded, and current * setting of deny_unknown. */ -void selinux_status_update_policyload(int seqno) +void selinux_status_update_policyload(u32 seqno) { struct selinux_kernel_status *status; -- cgit v1.2.3 From 777ea29c57a078679fdb637919c1794d0d244128 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:25 +0200 Subject: selinux: avoid implicit conversions in the netif code Use the identical type sel_netif_hashfn() returns. Signed-off-by: Christian Göttsche [PM: subject line tweaks] Signed-off-by: Paul Moore --- security/selinux/netif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/netif.c b/security/selinux/netif.c index adbe9bea2d26..43a0d3594b72 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -67,7 +67,7 @@ static inline u32 sel_netif_hashfn(const struct net *ns, int ifindex) static inline struct sel_netif *sel_netif_find(const struct net *ns, int ifindex) { - int idx = sel_netif_hashfn(ns, ifindex); + u32 idx = sel_netif_hashfn(ns, ifindex); struct sel_netif *netif; list_for_each_entry_rcu(netif, &sel_netif_hash[idx], list) @@ -89,7 +89,7 @@ static inline struct sel_netif *sel_netif_find(const struct net *ns, */ static int sel_netif_insert(struct sel_netif *netif) { - int idx; + u32 idx; if (sel_netif_total >= SEL_NETIF_HASH_MAX) return -ENOSPC; -- cgit v1.2.3 From 5f740953ab2f5dcb638a4c8c5e6128533a5d4077 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:26 +0200 Subject: selinux: avoid implicit conversions in the AVC code Use a consistent type of u32 for sequence numbers. Use a non-negative and input parameter matching type for the hash result. Signed-off-by: Christian Göttsche [PM: subject line tweaks] Signed-off-by: Paul Moore --- security/selinux/avc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 1074db66e5ff..cd55479cce25 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -122,7 +122,7 @@ static struct kmem_cache *avc_xperms_data_cachep __ro_after_init; static struct kmem_cache *avc_xperms_decision_cachep __ro_after_init; static struct kmem_cache *avc_xperms_cachep __ro_after_init; -static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) +static inline u32 avc_hash(u32 ssid, u32 tsid, u16 tclass) { return (ssid ^ (tsid<<2) ^ (tclass<<4)) & (AVC_CACHE_SLOTS - 1); } @@ -523,7 +523,7 @@ static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tcl static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) { struct avc_node *node, *ret = NULL; - int hvalue; + u32 hvalue; struct hlist_head *head; hvalue = avc_hash(ssid, tsid, tclass); @@ -566,7 +566,7 @@ static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) return NULL; } -static int avc_latest_notif_update(int seqno, int is_insert) +static int avc_latest_notif_update(u32 seqno, int is_insert) { int ret = 0; static DEFINE_SPINLOCK(notif_lock); @@ -609,7 +609,7 @@ static void avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd, struct avc_xperms_node *xp_node) { struct avc_node *pos, *node = NULL; - int hvalue; + u32 hvalue; unsigned long flag; spinlock_t *lock; struct hlist_head *head; @@ -654,9 +654,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) { struct common_audit_data *ad = a; struct selinux_audit_data *sad = ad->selinux_audit_data; - u32 av = sad->audited; + u32 av = sad->audited, perm; const char *const *perms; - int i, perm; + u32 i; audit_log_format(ab, "avc: %s ", sad->denied ? "denied" : "granted"); @@ -833,7 +833,8 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, struct extended_perms_decision *xpd, u32 flags) { - int hvalue, rc = 0; + u32 hvalue; + int rc = 0; unsigned long flag; struct avc_node *pos, *node, *orig = NULL; struct hlist_head *head; -- cgit v1.2.3 From a13479bb3c9d559fceb075986d8e0154a7eabbb1 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:27 +0200 Subject: selinux: avoid implicit conversions in the LSM hooks Use the identical types in assignments of local variables for the destination. Merge tail calls into return statements. Avoid using leading underscores for function local variable. Signed-off-by: Christian Göttsche [PM: subject line tweaks] Signed-off-by: Paul Moore --- security/selinux/hooks.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b8a8a4f0f2ad..fff50604abce 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1125,7 +1125,7 @@ static inline int default_protocol_dgram(int protocol) static inline u16 socket_type_to_security_class(int family, int type, int protocol) { - int extsockclass = selinux_policycap_extsockclass(); + bool extsockclass = selinux_policycap_extsockclass(); switch (family) { case PF_UNIX: @@ -5027,15 +5027,13 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { - int err; + int err, peerlbl_active, secmark_active; struct sk_security_struct *sksec = sk->sk_security; u16 family = sk->sk_family; u32 sk_sid = sksec->sid; struct common_audit_data ad; struct lsm_network_audit net = {0,}; char *addrp; - u8 secmark_active; - u8 peerlbl_active; if (family != PF_INET && family != PF_INET6) return 0; @@ -5498,11 +5496,11 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) static int selinux_secmark_relabel_packet(u32 sid) { - const struct task_security_struct *__tsec; + const struct task_security_struct *tsec; u32 tsid; - __tsec = selinux_cred(current_cred()); - tsid = __tsec->sid; + tsec = selinux_cred(current_cred()); + tsid = tsec->sid; return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); @@ -6000,8 +5998,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) { - int err; - int perms; + u32 perms; switch (cmd) { case IPC_INFO: @@ -6024,8 +6021,7 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) return 0; } - err = ipc_has_perm(msq, perms); - return err; + return ipc_has_perm(msq, perms); } static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) @@ -6130,8 +6126,7 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) /* Note, at this point, shp is locked down */ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd) { - int perms; - int err; + u32 perms; switch (cmd) { case IPC_INFO: @@ -6158,8 +6153,7 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd) return 0; } - err = ipc_has_perm(shp, perms); - return err; + return ipc_has_perm(shp, perms); } static int selinux_shm_shmat(struct kern_ipc_perm *shp, @@ -6928,7 +6922,7 @@ static int selinux_uring_override_creds(const struct cred *new) */ static int selinux_uring_sqpoll(void) { - int sid = current_sid(); + u32 sid = current_sid(); return avc_has_perm(sid, sid, SECCLASS_IO_URING, IO_URING__SQPOLL, NULL); -- cgit v1.2.3 From 7128578c79a73760305f89ff975047c124919dfc Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:29 +0200 Subject: selinux: use consistent type for AV rule specifier The specifier for avtab keys is always supplied with a type of u16, either as a macro to security_compute_sid() or the member specified of the struct avtab_key. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/avtab.c | 2 +- security/selinux/ss/avtab.h | 2 +- security/selinux/ss/services.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 7d21de48c28d..8d7c14ca27a2 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -248,7 +248,7 @@ struct avtab_node *avtab_search_node(struct avtab *h, } struct avtab_node* -avtab_search_node_next(struct avtab_node *node, int specified) +avtab_search_node_next(struct avtab_node *node, u16 specified) { struct avtab_node *cur; diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index d6742fd9c560..f265e9da18e2 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -111,7 +111,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_node *avtab_search_node(struct avtab *h, const struct avtab_key *key); -struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); +struct avtab_node *avtab_search_node_next(struct avtab_node *node, u16 specified); #define MAX_AVTAB_HASH_BITS 16 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 78946b71c1c1..83b85536cd2b 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1694,7 +1694,7 @@ static void filename_compute_type(struct policydb *policydb, static int security_compute_sid(u32 ssid, u32 tsid, u16 orig_tclass, - u32 specified, + u16 specified, const char *objname, u32 *out_sid, bool kern) -- cgit v1.2.3 From 0e83c9c6fb0d7d2fddd2cd02575d7ad157e12837 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:31 +0200 Subject: selinux: fix implicit conversions in the symtab hashtab_init() takes an u32 as size parameter type. Signed-off-by: Christian Göttsche [PM: subject line tweaks] Signed-off-by: Paul Moore --- security/selinux/ss/symtab.c | 2 +- security/selinux/ss/symtab.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index c42a6648a07d..7a77571fb275 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c @@ -37,7 +37,7 @@ static const struct hashtab_key_params symtab_key_params = { .cmp = symcmp, }; -int symtab_init(struct symtab *s, unsigned int size) +int symtab_init(struct symtab *s, u32 size) { s->nprim = 0; return hashtab_init(&s->table, size); diff --git a/security/selinux/ss/symtab.h b/security/selinux/ss/symtab.h index f2614138d0cd..3033c4db6cb6 100644 --- a/security/selinux/ss/symtab.h +++ b/security/selinux/ss/symtab.h @@ -17,7 +17,7 @@ struct symtab { u32 nprim; /* number of primary names in table */ }; -int symtab_init(struct symtab *s, unsigned int size); +int symtab_init(struct symtab *s, u32 size); int symtab_insert(struct symtab *s, char *name, void *datum); void *symtab_search(struct symtab *s, const char *name); -- cgit v1.2.3 From c867248cf451964a14c64b4ca232055f117df9c1 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 6 Jul 2023 15:23:34 +0200 Subject: selinux: avoid implicit conversions regarding enforcing status Use the type bool as parameter type in selinux_status_update_setenforce(). The related function enforcing_enabled() returns the type bool, while the struct selinux_kernel_status member enforcing uses an u32. Signed-off-by: Christian Göttsche [PM: subject line tweaks] Signed-off-by: Paul Moore --- security/selinux/include/security.h | 2 +- security/selinux/selinuxfs.c | 7 ++++--- security/selinux/status.c | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'security') diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 08840aa0782d..6b8b8fc3badd 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -375,7 +375,7 @@ struct selinux_kernel_status { */ } __packed; -extern void selinux_status_update_setenforce(int enforcing); +extern void selinux_status_update_setenforce(bool enforcing); extern void selinux_status_update_policyload(u32 seqno); extern void selinux_complete_init(void); extern struct path selinux_null; diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index bad1f6b685fd..f79e96f0f221 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -138,7 +138,8 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, { char *page = NULL; ssize_t length; - int old_value, new_value; + int scan_value; + bool old_value, new_value; if (count >= PAGE_SIZE) return -ENOMEM; @@ -152,10 +153,10 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, return PTR_ERR(page); length = -EINVAL; - if (sscanf(page, "%d", &new_value) != 1) + if (sscanf(page, "%d", &scan_value) != 1) goto out; - new_value = !!new_value; + new_value = !!scan_value; old_value = enforcing_enabled(); if (new_value != old_value) { diff --git a/security/selinux/status.c b/security/selinux/status.c index e436e4975adc..dffca22ce6f7 100644 --- a/security/selinux/status.c +++ b/security/selinux/status.c @@ -76,7 +76,7 @@ struct page *selinux_kernel_status_page(void) * * It updates status of the current enforcing/permissive mode. */ -void selinux_status_update_setenforce(int enforcing) +void selinux_status_update_setenforce(bool enforcing) { struct selinux_kernel_status *status; @@ -87,7 +87,7 @@ void selinux_status_update_setenforce(int enforcing) status->sequence++; smp_wmb(); - status->enforcing = enforcing; + status->enforcing = enforcing ? 1 : 0; smp_wmb(); status->sequence++; -- cgit v1.2.3 From 90aa4f5e92f2797c3c86e05f588ab277b0e0ba39 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Tue, 18 Jul 2023 13:13:35 -0400 Subject: selinux: de-brand SELinux Change "NSA SELinux" to just "SELinux" in Kconfig help text and comments. While NSA was the original primary developer and continues to help maintain SELinux, SELinux has long since transitioned to a wide community of developers and maintainers. SELinux has been part of the mainline Linux kernel for nearly 20 years now [1] and has received contributions from many individuals and organizations. [1] https://lore.kernel.org/lkml/Pine.LNX.4.44.0308082228470.1852-100000@home.osdl.org/ Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/Kconfig | 16 ++++++++-------- security/selinux/hooks.c | 2 +- security/selinux/include/objsec.h | 2 +- security/selinux/xfrm.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'security') diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 95a186ec0fcb..c275115b5088 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -1,16 +1,16 @@ # SPDX-License-Identifier: GPL-2.0-only config SECURITY_SELINUX - bool "NSA SELinux Support" + bool "SELinux Support" depends on SECURITY_NETWORK && AUDIT && NET && INET select NETWORK_SECMARK default n help - This selects NSA Security-Enhanced Linux (SELinux). + This selects Security-Enhanced Linux (SELinux). You will also need a policy configuration and a labeled filesystem. If you are unsure how to answer this question, answer N. config SECURITY_SELINUX_BOOTPARAM - bool "NSA SELinux boot parameter" + bool "SELinux boot parameter" depends on SECURITY_SELINUX default n help @@ -24,11 +24,11 @@ config SECURITY_SELINUX_BOOTPARAM If you are unsure how to answer this question, answer N. config SECURITY_SELINUX_DEVELOP - bool "NSA SELinux Development Support" + bool "SELinux Development Support" depends on SECURITY_SELINUX default y help - This enables the development support option of NSA SELinux, + This enables the development support option of SELinux, which is useful for experimenting with SELinux and developing policies. If unsure, say Y. With this option enabled, the kernel will start in permissive mode (log everything, deny nothing) @@ -38,7 +38,7 @@ config SECURITY_SELINUX_DEVELOP /sys/fs/selinux/enforce. config SECURITY_SELINUX_AVC_STATS - bool "NSA SELinux AVC Statistics" + bool "SELinux AVC Statistics" depends on SECURITY_SELINUX default y help @@ -47,7 +47,7 @@ config SECURITY_SELINUX_AVC_STATS tools such as avcstat. config SECURITY_SELINUX_SIDTAB_HASH_BITS - int "NSA SELinux sidtab hashtable size" + int "SELinux sidtab hashtable size" depends on SECURITY_SELINUX range 8 13 default 9 @@ -59,7 +59,7 @@ config SECURITY_SELINUX_SIDTAB_HASH_BITS will ensure that lookups times are short and stable. config SECURITY_SELINUX_SID2STR_CACHE_SIZE - int "NSA SELinux SID to context string translation cache size" + int "SELinux SID to context string translation cache size" depends on SECURITY_SELINUX default 256 help diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fff50604abce..9aa60ce23209 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * NSA Security-Enhanced Linux (SELinux) security module + * Security-Enhanced Linux (SELinux) security module * * This file contains the SELinux hook function implementations. * diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 2953132408bf..8f50e8fe0488 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * NSA Security-Enhanced Linux (SELinux) security module + * Security-Enhanced Linux (SELinux) security module * * This file contains the SELinux security data structures for kernel objects. * diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 1fca42c4d0ae..95fcd2d3433e 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * NSA Security-Enhanced Linux (SELinux) security module + * Security-Enhanced Linux (SELinux) security module * * This file contains the SELinux XFRM hook function implementations. * -- cgit v1.2.3 From 08a12b39e289fedf755afbc81de44a5cd1286b4b Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Tue, 18 Jul 2023 20:06:27 +0200 Subject: selinux: drop avtab_search() avtab_search() shares the same logic with avtab_search_node(), except that it returns, if found, a pointer to the struct avtab_node member datum instead of the node itself. Since the member is an embedded struct, and not a pointer, the returned value of avtab_search() and avtab_search_node() will always in unison either be NULL or non-NULL. Drop avtab_search() and replace its calls by avtab_search_node() to deduplicate logic and adopt the only caller caring for the type of the returned value accordingly. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/avtab.c | 32 -------------------------------- security/selinux/ss/avtab.h | 1 - security/selinux/ss/conditional.c | 4 ++-- security/selinux/ss/services.c | 13 ++++++------- 4 files changed, 8 insertions(+), 42 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 8d7c14ca27a2..5fd439c5b8a4 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -180,38 +180,6 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, return avtab_insert_node(h, hvalue, prev, key, datum); } -struct avtab_datum *avtab_search(struct avtab *h, const struct avtab_key *key) -{ - int hvalue; - struct avtab_node *cur; - u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - - if (!h || !h->nslot) - return NULL; - - hvalue = avtab_hash(key, h->mask); - for (cur = h->htable[hvalue]; cur; - cur = cur->next) { - if (key->source_type == cur->key.source_type && - key->target_type == cur->key.target_type && - key->target_class == cur->key.target_class && - (specified & cur->key.specified)) - return &cur->datum; - - if (key->source_type < cur->key.source_type) - break; - if (key->source_type == cur->key.source_type && - key->target_type < cur->key.target_type) - break; - if (key->source_type == cur->key.source_type && - key->target_type == cur->key.target_type && - key->target_class < cur->key.target_class) - break; - } - - return NULL; -} - /* This search function returns a node pointer, and can be used in * conjunction with avtab_search_next_node() */ diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index f265e9da18e2..c2b88430c916 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -90,7 +90,6 @@ struct avtab { void avtab_init(struct avtab *h); int avtab_alloc(struct avtab *, u32); int avtab_alloc_dup(struct avtab *new, const struct avtab *orig); -struct avtab_datum *avtab_search(struct avtab *h, const struct avtab_key *k); void avtab_destroy(struct avtab *h); void avtab_hash_eval(struct avtab *h, const char *tag); diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index b156c181c3c1..81ff676f209a 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -272,7 +272,7 @@ static int cond_insertf(struct avtab *a, const struct avtab_key *k, * cond_te_avtab. */ if (k->specified & AVTAB_TYPE) { - if (avtab_search(&p->te_avtab, k)) { + if (avtab_search_node(&p->te_avtab, k)) { pr_err("SELinux: type rule already exists outside of a conditional.\n"); return -EINVAL; } @@ -304,7 +304,7 @@ static int cond_insertf(struct avtab *a, const struct avtab_key *k, } } } else { - if (avtab_search(&p->te_cond_avtab, k)) { + if (avtab_search_node(&p->te_cond_avtab, k)) { pr_err("SELinux: conflicting type rules when adding type rule for true.\n"); return -EINVAL; } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 83b85536cd2b..fa47e4e38935 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1706,8 +1706,7 @@ static int security_compute_sid(u32 ssid, struct context *scontext, *tcontext, newcontext; struct sidtab_entry *sentry, *tentry; struct avtab_key avkey; - struct avtab_datum *avdatum; - struct avtab_node *node; + struct avtab_node *avnode, *node; u16 tclass; int rc = 0; bool sock; @@ -1815,22 +1814,22 @@ retry: avkey.target_type = tcontext->type; avkey.target_class = tclass; avkey.specified = specified; - avdatum = avtab_search(&policydb->te_avtab, &avkey); + avnode = avtab_search_node(&policydb->te_avtab, &avkey); /* If no permanent rule, also check for enabled conditional rules */ - if (!avdatum) { + if (!avnode) { node = avtab_search_node(&policydb->te_cond_avtab, &avkey); for (; node; node = avtab_search_node_next(node, specified)) { if (node->key.specified & AVTAB_ENABLED) { - avdatum = &node->datum; + avnode = node; break; } } } - if (avdatum) { + if (avnode) { /* Use the type from the type transition/member/change rule. */ - newcontext.type = avdatum->u.data; + newcontext.type = avnode->datum.u.data; } /* if we have a objname this is a file trans check so check those rules */ -- cgit v1.2.3 From e5faa839c3eee199447573c4e227daeb76d402cf Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Tue, 18 Jul 2023 21:00:24 +0200 Subject: selinux: add missing newlines in pr_err() statements The kernel print statements do not append an implicit newline to format strings. Signed-off-by: Christian Göttsche [PM: subject line tweak] Signed-off-by: Paul Moore --- security/selinux/hooks.c | 2 +- security/selinux/ss/policydb.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9aa60ce23209..dc51f28815b0 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2930,7 +2930,7 @@ static int selinux_inode_init_security_anon(struct inode *inode, struct inode_security_struct *context_isec = selinux_inode(context_inode); if (context_isec->initialized != LABEL_INITIALIZED) { - pr_err("SELinux: context_inode is not initialized"); + pr_err("SELinux: context_inode is not initialized\n"); return -EACCES; } diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index cfe77ef24ee2..61e0e5000025 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -1687,7 +1687,7 @@ static int user_bounds_sanity_check(void *key, void *datum, void *datap) if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { pr_err("SELinux: user %s: " - "too deep or looped boundary", + "too deep or looped boundary\n", (char *) key); return -EINVAL; } @@ -1766,7 +1766,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) if (upper->attribute) { pr_err("SELinux: type %s: " - "bounded by attribute %s", + "bounded by attribute %s\n", (char *) key, sym_name(p, SYM_TYPES, upper->value - 1)); return -EINVAL; @@ -3675,7 +3675,7 @@ int policydb_write(struct policydb *p, void *fp) info = policydb_lookup_compat(p->policyvers); if (!info) { pr_err("SELinux: compatibility lookup failed for policy " - "version %d", p->policyvers); + "version %d\n", p->policyvers); return -EINVAL; } -- cgit v1.2.3 From 0fe53224bf5be183d263f262212c06ff00c69ca4 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Wed, 19 Jul 2023 11:12:50 -0400 Subject: selinux: update my email address Update my email address; MAINTAINERS was updated some time ago. Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/avc.c | 2 +- security/selinux/hooks.c | 2 +- security/selinux/include/avc.h | 2 +- security/selinux/include/avc_ss.h | 2 +- security/selinux/include/objsec.h | 2 +- security/selinux/include/security.h | 2 +- security/selinux/ss/avtab.c | 2 +- security/selinux/ss/avtab.h | 2 +- security/selinux/ss/constraint.h | 2 +- security/selinux/ss/context.h | 2 +- security/selinux/ss/ebitmap.c | 2 +- security/selinux/ss/ebitmap.h | 2 +- security/selinux/ss/hashtab.c | 2 +- security/selinux/ss/hashtab.h | 2 +- security/selinux/ss/mls.c | 2 +- security/selinux/ss/mls.h | 2 +- security/selinux/ss/mls_types.h | 2 +- security/selinux/ss/policydb.c | 2 +- security/selinux/ss/policydb.h | 2 +- security/selinux/ss/services.c | 2 +- security/selinux/ss/services.h | 2 +- security/selinux/ss/sidtab.c | 2 +- security/selinux/ss/sidtab.h | 2 +- security/selinux/ss/symtab.c | 2 +- security/selinux/ss/symtab.h | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) (limited to 'security') diff --git a/security/selinux/avc.c b/security/selinux/avc.c index cd55479cce25..32eb67fb3e42 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -2,7 +2,7 @@ /* * Implementation of the kernel access vector cache (AVC). * - * Authors: Stephen Smalley, + * Authors: Stephen Smalley, * James Morris * * Update: KaiGai, Kohei diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index dc51f28815b0..a85a9f52e0c3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4,7 +4,7 @@ * * This file contains the SELinux hook function implementations. * - * Authors: Stephen Smalley, + * Authors: Stephen Smalley, * Chris Vance, * Wayne Salamon, * James Morris diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 9e055f74daf6..8f0aa66ccb13 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -2,7 +2,7 @@ /* * Access vector cache interface for object managers. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SELINUX_AVC_H_ #define _SELINUX_AVC_H_ diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index b9668be7b443..88b139e086c4 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h @@ -2,7 +2,7 @@ /* * Access vector cache interface for the security server. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SELINUX_AVC_SS_H_ #define _SELINUX_AVC_SS_H_ diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 8f50e8fe0488..8159fd53c3de 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -4,7 +4,7 @@ * * This file contains the SELinux security data structures for kernel objects. * - * Author(s): Stephen Smalley, + * Author(s): Stephen Smalley, * Chris Vance, * Wayne Salamon, * James Morris diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 6b8b8fc3badd..668e393a9709 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -2,7 +2,7 @@ /* * Security server interface. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, * */ diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 5fd439c5b8a4..32f92da00b0e 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -1,7 +1,7 @@ /* * Implementation of the access vector table type. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* Updated: Frank Mayer and Karl MacMillan diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index c2b88430c916..2ef5d1ae2844 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -6,7 +6,7 @@ * table is used to represent the type enforcement * tables. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* Updated: Frank Mayer and Karl MacMillan diff --git a/security/selinux/ss/constraint.h b/security/selinux/ss/constraint.h index 4e563be9ef5f..f76eb3128ad5 100644 --- a/security/selinux/ss/constraint.h +++ b/security/selinux/ss/constraint.h @@ -11,7 +11,7 @@ * process from labeling an object with a different user * identity. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SS_CONSTRAINT_H_ #define _SS_CONSTRAINT_H_ diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index aed704b8c642..1f59468c0759 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h @@ -11,7 +11,7 @@ * security server and can be changed without affecting * clients of the security server. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SS_CONTEXT_H_ #define _SS_CONTEXT_H_ diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index d31b87be9a1e..77875ad355f7 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -2,7 +2,7 @@ /* * Implementation of the extensible bitmap type. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* * Updated: Hewlett-Packard diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index e5b57dc3fc53..e3c807cfad90 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h @@ -10,7 +10,7 @@ * an explicitly specified starting bit position within * the total bitmap. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SS_EBITMAP_H_ #define _SS_EBITMAP_H_ diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 3fb8f9026e9b..30532ec319ce 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -2,7 +2,7 @@ /* * Implementation of the hash table type. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #include #include diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h index 043a773bf0b7..9dac6da45b98 100644 --- a/security/selinux/ss/hashtab.h +++ b/security/selinux/ss/hashtab.h @@ -6,7 +6,7 @@ * functions for hash computation and key comparison are * provided by the creator of the table. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SS_HASHTAB_H_ #define _SS_HASHTAB_H_ diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 99571b19d4a9..b2c6c846ea03 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -2,7 +2,7 @@ /* * Implementation of the multi-level security (MLS) policy. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 15cacde0ff61..107681dd1824 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h @@ -2,7 +2,7 @@ /* * Multi-level security (MLS) policy operations. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h index 7d48d5e52233..f492cf148891 100644 --- a/security/selinux/ss/mls_types.h +++ b/security/selinux/ss/mls_types.h @@ -2,7 +2,7 @@ /* * Type definitions for the multi-level security (MLS) policy. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 61e0e5000025..b903a4dfdce1 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -2,7 +2,7 @@ /* * Implementation of the policy database. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 6b4ad8e91265..b97cda489753 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -3,7 +3,7 @@ * A policy database (policydb) specifies the * configuration data for the security policy. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index fa47e4e38935..2c5be06fbada 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2,7 +2,7 @@ /* * Implementation of the security services. * - * Authors : Stephen Smalley, + * Authors : Stephen Smalley, * James Morris * * Updated: Trusted Computer Solutions, Inc. diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index 8a9b85f44b66..ed2ee6600467 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h @@ -2,7 +2,7 @@ /* * Implementation of the security services. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SS_SERVICES_H_ #define _SS_SERVICES_H_ diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index 38d25173aebd..d8ead463b8df 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -2,7 +2,7 @@ /* * Implementation of the SID table type. * - * Original author: Stephen Smalley, + * Original author: Stephen Smalley, * Author: Ondrej Mosnacek, * * Copyright (C) 2018 Red Hat, Inc. diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index 72810a080e77..22258201cd14 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h @@ -3,7 +3,7 @@ * A security identifier table (sidtab) is a lookup table * of security context structures indexed by SID value. * - * Original author: Stephen Smalley, + * Original author: Stephen Smalley, * Author: Ondrej Mosnacek, * * Copyright (C) 2018 Red Hat, Inc. diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 7a77571fb275..43d7f0319ccd 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c @@ -2,7 +2,7 @@ /* * Implementation of the symbol table type. * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #include #include diff --git a/security/selinux/ss/symtab.h b/security/selinux/ss/symtab.h index 3033c4db6cb6..0a3b5de79a0f 100644 --- a/security/selinux/ss/symtab.h +++ b/security/selinux/ss/symtab.h @@ -5,7 +5,7 @@ * is arbitrary. The symbol table type is implemented * using the hash table type (hashtab). * - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SS_SYMTAB_H_ #define _SS_SYMTAB_H_ -- cgit v1.2.3 From dd51fcd42fd6bf37608f54303b974b47f73c1490 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Wed, 19 Jul 2023 13:37:49 +0200 Subject: selinux: introduce and use lsm_ad_net_init*() helpers Perf traces of network-related workload shows a measurable overhead inside the network-related selinux hooks while zeroing the lsm_network_audit struct. In most cases we can delay the initialization of such structure to the usage point, avoiding such overhead in a few cases. Additionally, the audit code accesses the IP address information only for AF_INET* families, and selinux_parse_skb() will fill-out the relevant fields in such cases. When the family field is zeroed or the initialization is followed by the mentioned parsing, the zeroing can be limited to the sk, family and netif fields. By factoring out the audit-data initialization to new helpers, this patch removes some duplicate code and gives small but measurable performance gain under UDP flood. Signed-off-by: Paolo Abeni Signed-off-by: Paul Moore --- security/selinux/hooks.c | 84 +++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 41 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a85a9f52e0c3..6f53fa71fbdb 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -224,6 +224,31 @@ static inline u32 cred_sid(const struct cred *cred) return tsec->sid; } +static void __ad_net_init(struct common_audit_data *ad, + struct lsm_network_audit *net, + int ifindex, struct sock *sk, u16 family) +{ + ad->type = LSM_AUDIT_DATA_NET; + ad->u.net = net; + net->netif = ifindex; + net->sk = sk; + net->family = family; +} + +static void ad_net_init_from_sk(struct common_audit_data *ad, + struct lsm_network_audit *net, + struct sock *sk) +{ + __ad_net_init(ad, net, 0, sk, 0); +} + +static void ad_net_init_from_iif(struct common_audit_data *ad, + struct lsm_network_audit *net, + int ifindex, u16 family) +{ + __ad_net_init(ad, net, ifindex, 0, family); +} + /* * get the objective security ID of a task */ @@ -4512,7 +4537,7 @@ static int sock_has_perm(struct sock *sk, u32 perms) { struct sk_security_struct *sksec = sk->sk_security; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; if (sksec->sid == SECINITSID_KERNEL) return 0; @@ -4532,9 +4557,7 @@ static int sock_has_perm(struct sock *sk, u32 perms) sksec->sid == SECINITSID_INIT) return 0; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->sk = sk; + ad_net_init_from_sk(&ad, &net, sk); return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms, &ad); @@ -4927,12 +4950,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, struct sk_security_struct *sksec_other = other->sk_security; struct sk_security_struct *sksec_new = newsk->sk_security; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; int err; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->sk = other; + ad_net_init_from_sk(&ad, &net, other); err = avc_has_perm(sksec_sock->sid, sksec_other->sid, sksec_other->sclass, @@ -4959,11 +4980,9 @@ static int selinux_socket_unix_may_send(struct socket *sock, struct sk_security_struct *ssec = sock->sk->sk_security; struct sk_security_struct *osec = other->sk->sk_security; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->sk = other->sk; + ad_net_init_from_sk(&ad, &net, other->sk); return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, &ad); @@ -4999,13 +5018,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, struct sk_security_struct *sksec = sk->sk_security; u32 sk_sid = sksec->sid; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; char *addrp; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->netif = skb->skb_iif; - ad.u.net->family = family; + ad_net_init_from_iif(&ad, &net, skb->skb_iif, family); err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); if (err) return err; @@ -5032,7 +5048,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) u16 family = sk->sk_family; u32 sk_sid = sksec->sid; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; char *addrp; if (family != PF_INET && family != PF_INET6) @@ -5054,10 +5070,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (!secmark_active && !peerlbl_active) return 0; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->netif = skb->skb_iif; - ad.u.net->family = family; + ad_net_init_from_iif(&ad, &net, skb->skb_iif, family); err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); if (err) return err; @@ -5227,7 +5240,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, u16 family = sk->sk_family; struct sk_security_struct *sksec = sk->sk_security; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; int err; /* handle mapped IPv4 packets arriving via IPv6 sockets */ @@ -5263,9 +5276,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, /* Other association peer SIDs are checked to enforce * consistency among the peer SIDs. */ - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->sk = asoc->base.sk; + ad_net_init_from_sk(&ad, &net, asoc->base.sk); err = avc_has_perm(sksec->peer_sid, asoc->peer_secid, sksec->sclass, SCTP_SOCKET__ASSOCIATION, &ad); @@ -5610,7 +5621,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, char *addrp; u32 peer_sid; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; int secmark_active, peerlbl_active; if (!selinux_policycap_netpeer()) @@ -5626,10 +5637,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, return NF_DROP; ifindex = state->in->ifindex; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->netif = ifindex; - ad.u.net->family = family; + ad_net_init_from_iif(&ad, &net, ifindex, family); if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) return NF_DROP; @@ -5709,7 +5717,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, struct sock *sk; struct sk_security_struct *sksec; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; u8 proto = 0; sk = skb_to_full_sk(skb); @@ -5717,10 +5725,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, return NF_ACCEPT; sksec = sk->sk_security; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->netif = state->out->ifindex; - ad.u.net->family = state->pf; + ad_net_init_from_iif(&ad, &net, state->out->ifindex, state->pf); if (selinux_parse_skb(skb, &ad, NULL, 0, &proto)) return NF_DROP; @@ -5745,7 +5750,7 @@ static unsigned int selinux_ip_postroute(void *priv, int ifindex; struct sock *sk; struct common_audit_data ad; - struct lsm_network_audit net = {0,}; + struct lsm_network_audit net; char *addrp; int secmark_active, peerlbl_active; @@ -5842,10 +5847,7 @@ static unsigned int selinux_ip_postroute(void *priv, } ifindex = state->out->ifindex; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->netif = ifindex; - ad.u.net->family = family; + ad_net_init_from_iif(&ad, &net, ifindex, family); if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) return NF_DROP; -- cgit v1.2.3 From 55a0e73806ec64279ea31d57b2116672631696a8 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Tue, 18 Jul 2023 20:49:19 +0200 Subject: selinux: introduce SECURITY_SELINUX_DEBUG configuration The policy database code contains several debug output statements related to hashtable utilization. Those are guarded by the macro DEBUG_HASHES, which is neither documented nor set anywhere. Introduce a new Kconfig configuration guarding this and potential other future debugging related code. Disable the setting by default. Suggested-by: Paul Moore Signed-off-by: Christian Göttsche [PM: fixed line lengths in the help text] Signed-off-by: Paul Moore --- security/selinux/Kconfig | 9 +++++++++ security/selinux/ss/policydb.c | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index c275115b5088..d30348fbe0df 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -68,3 +68,12 @@ config SECURITY_SELINUX_SID2STR_CACHE_SIZE conversion. Setting this option to 0 disables the cache completely. If unsure, keep the default value. + +config SECURITY_SELINUX_DEBUG + bool "SELinux kernel debugging support" + depends on SECURITY_SELINUX + default n + help + This enables debugging code designed to help SELinux kernel + developers, unless you know what this does in the kernel code you + should leave this disabled. diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index b903a4dfdce1..dc66868ff62c 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -41,7 +41,7 @@ #include "mls.h" #include "services.h" -#ifdef DEBUG_HASHES +#ifdef CONFIG_SECURITY_SELINUX_DEBUG static const char *const symtab_name[SYM_NUM] = { "common prefixes", "classes", @@ -678,7 +678,7 @@ static int (*const index_f[SYM_NUM]) (void *key, void *datum, void *datap) = { cat_index, }; -#ifdef DEBUG_HASHES +#ifdef CONFIG_SECURITY_SELINUX_DEBUG static void hash_eval(struct hashtab *h, const char *hash_name) { struct hashtab_info info; @@ -701,7 +701,7 @@ static void symtab_hash_eval(struct symtab *s) static inline void hash_eval(struct hashtab *h, const char *hash_name) { } -#endif +#endif /* CONFIG_SECURITY_SELINUX_DEBUG */ /* * Define the other val_to_name and val_to_struct arrays @@ -725,7 +725,7 @@ static int policydb_index(struct policydb *p) pr_debug("SELinux: %d classes, %d rules\n", p->p_classes.nprim, p->te_avtab.nel); -#ifdef DEBUG_HASHES +#ifdef CONFIG_SECURITY_SELINUX_DEBUG avtab_hash_eval(&p->te_avtab, "rules"); symtab_hash_eval(p->symtab); #endif -- cgit v1.2.3 From 3876043ad9f7ff5fa3e506ea9673641971e46d8b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 20 Jul 2023 16:26:34 -0400 Subject: selinux: fix a 0/NULL mistmatch in ad_net_init_from_iif() Use a NULL instead of a zero to resolve a int/pointer mismatch. Cc: Paolo Abeni Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202307210332.4AqFZfzI-lkp@intel.com/ Fixes: dd51fcd42fd6 ("selinux: introduce and use lsm_ad_net_init*() helpers") Acked-by: Paolo Abeni Signed-off-by: Paul Moore --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6f53fa71fbdb..5194f12def97 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -246,7 +246,7 @@ static void ad_net_init_from_iif(struct common_audit_data *ad, struct lsm_network_audit *net, int ifindex, u16 family) { - __ad_net_init(ad, net, ifindex, 0, family); + __ad_net_init(ad, net, ifindex, NULL, family); } /* -- cgit v1.2.3 From 19c5b015d1b9122393151134879dcfcf0ae6057a Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Fri, 28 Jul 2023 17:01:49 +0200 Subject: selinux: log about VM being executable by default In case virtual memory is being marked as executable by default, SELinux checks regarding explicit potential dangerous use are disabled. Inform the user about it. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/hooks.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5194f12def97..7cd687284563 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7265,6 +7265,8 @@ static __init int selinux_init(void) cred_init_security(); default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); + if (!default_noexec) + pr_notice("SELinux: virtual memory is executable by default\n"); avc_init(); -- cgit v1.2.3 From f01dd5904519574017a4938ffb4424b31ba79cf3 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Fri, 28 Jul 2023 17:19:31 +0200 Subject: selinux: move debug functions into debug configuration avtab_hash_eval() and hashtab_stat() are only used in policydb.c when the configuration SECURITY_SELINUX_DEBUG is enabled. Move the function definitions under that configuration as well and provide empty definitions in case SECURITY_SELINUX_DEBUG is disabled, to avoid using #ifdef in the callers. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/avtab.c | 2 ++ security/selinux/ss/avtab.h | 7 +++++++ security/selinux/ss/hashtab.c | 3 ++- security/selinux/ss/hashtab.h | 6 ++++++ security/selinux/ss/policydb.c | 5 +++-- 5 files changed, 20 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 32f92da00b0e..243e5dabfa86 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -322,6 +322,7 @@ int avtab_alloc_dup(struct avtab *new, const struct avtab *orig) return avtab_alloc_common(new, orig->nslot); } +#ifdef CONFIG_SECURITY_SELINUX_DEBUG void avtab_hash_eval(struct avtab *h, const char *tag) { int i, chain_len, slots_used, max_chain_len; @@ -352,6 +353,7 @@ void avtab_hash_eval(struct avtab *h, const char *tag) tag, h->nel, slots_used, h->nslot, max_chain_len, chain2_len_sum); } +#endif /* CONFIG_SECURITY_SELINUX_DEBUG */ static const uint16_t spec_order[] = { AVTAB_ALLOWED, diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 2ef5d1ae2844..3c3904bf02b0 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -91,7 +91,14 @@ void avtab_init(struct avtab *h); int avtab_alloc(struct avtab *, u32); int avtab_alloc_dup(struct avtab *new, const struct avtab *orig); void avtab_destroy(struct avtab *h); + +#ifdef CONFIG_SECURITY_SELINUX_DEBUG void avtab_hash_eval(struct avtab *h, const char *tag); +#else +static inline void avtab_hash_eval(struct avtab *h, const char *tag) +{ +} +#endif struct policydb; int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 30532ec319ce..e3747b5dd3e7 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -103,7 +103,7 @@ int hashtab_map(struct hashtab *h, return 0; } - +#ifdef CONFIG_SECURITY_SELINUX_DEBUG void hashtab_stat(struct hashtab *h, struct hashtab_info *info) { u32 i, chain_len, slots_used, max_chain_len; @@ -129,6 +129,7 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info) info->slots_used = slots_used; info->max_chain_len = max_chain_len; } +#endif /* CONFIG_SECURITY_SELINUX_DEBUG */ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, int (*copy)(struct hashtab_node *new, diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h index 9dac6da45b98..f9713b56d3d0 100644 --- a/security/selinux/ss/hashtab.h +++ b/security/selinux/ss/hashtab.h @@ -142,7 +142,13 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, int (*destroy)(void *k, void *d, void *args), void *args); +#ifdef CONFIG_SECURITY_SELINUX_DEBUG /* Fill info with some hash table statistics */ void hashtab_stat(struct hashtab *h, struct hashtab_info *info); +#else +static inline void hashtab_stat(struct hashtab *h, struct hashtab_info *info) +{ +} +#endif #endif /* _SS_HASHTAB_H */ diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index dc66868ff62c..a424997c79eb 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -701,6 +701,9 @@ static void symtab_hash_eval(struct symtab *s) static inline void hash_eval(struct hashtab *h, const char *hash_name) { } +static inline void symtab_hash_eval(struct symtab *s) +{ +} #endif /* CONFIG_SECURITY_SELINUX_DEBUG */ /* @@ -725,10 +728,8 @@ static int policydb_index(struct policydb *p) pr_debug("SELinux: %d classes, %d rules\n", p->p_classes.nprim, p->te_avtab.nel); -#ifdef CONFIG_SECURITY_SELINUX_DEBUG avtab_hash_eval(&p->te_avtab, "rules"); symtab_hash_eval(p->symtab); -#endif p->class_val_to_struct = kcalloc(p->p_classes.nprim, sizeof(*p->class_val_to_struct), -- cgit v1.2.3 From c17c55c2d1ab19db289b566bba98b53e35e5e261 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Fri, 28 Jul 2023 17:54:53 +0200 Subject: selinux: use identical iterator type in hashtab_duplicate() Use the identical type u32 for the loop iterator. Signed-off-by: Christian Göttsche [PM: remove extra whitespace in subject] Signed-off-by: Paul Moore --- security/selinux/ss/hashtab.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index e3747b5dd3e7..ac5cdddfbf78 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -138,7 +138,8 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, void *args) { struct hashtab_node *cur, *tmp, *tail; - int i, rc; + u32 i; + int rc; memset(new, 0, sizeof(*new)); -- cgit v1.2.3 From fd5a90ff1e95671e5b22dfa88d7359729b6c42b7 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Fri, 28 Jul 2023 17:54:54 +0200 Subject: selinux: avoid implicit conversions in mls code Use u32 for ebitmap bits and sensitivity levels, char for the default range of a class. Signed-off-by: Christian Göttsche [PM: description tweaks] Signed-off-by: Paul Moore --- security/selinux/ss/mls.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index b2c6c846ea03..cd38f5913b63 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -45,7 +45,7 @@ int mls_compute_context_len(struct policydb *p, struct context *context) len = 1; /* for the beginning ":" */ for (l = 0; l < 2; l++) { - int index_sens = context->range.level[l].sens; + u32 index_sens = context->range.level[l].sens; len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1)); /* categories */ @@ -240,7 +240,8 @@ int mls_context_to_sid(struct policydb *pol, char *sensitivity, *cur_cat, *next_cat, *rngptr; struct level_datum *levdatum; struct cat_datum *catdatum, *rngdatum; - int l, rc, i; + u32 i; + int l, rc; char *rangep[2]; if (!pol->mls_enabled) { @@ -451,7 +452,8 @@ int mls_convert_context(struct policydb *oldp, struct level_datum *levdatum; struct cat_datum *catdatum; struct ebitmap_node *node; - int l, i; + u32 i; + int l; if (!oldp->mls_enabled || !newp->mls_enabled) return 0; @@ -495,7 +497,7 @@ int mls_compute_sid(struct policydb *p, struct range_trans rtr; struct mls_range *r; struct class_datum *cladatum; - int default_range = 0; + char default_range = 0; if (!p->mls_enabled) return 0; -- cgit v1.2.3 From c50e125d057152bc68dfd5669b73611343653eb7 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Fri, 28 Jul 2023 17:54:56 +0200 Subject: selinux: avoid implicit conversions in services code Use u32 as the output parameter type in security_get_classes() and security_get_permissions(), based on the type of the symtab nprim member. Declare the read-only class string parameter of security_get_permissions() const. Avoid several implicit conversions by using the identical type for the destination. Use the type identical to the source for local variables. Signed-off-by: Christian Göttsche [PM: cleanup extra whitespace in subject] Signed-off-by: Paul Moore --- security/selinux/include/security.h | 4 ++-- security/selinux/selinuxfs.c | 7 ++++--- security/selinux/ss/services.c | 23 ++++++++++++----------- 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'security') diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 668e393a9709..074d439fe9ad 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -312,9 +312,9 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, u32 *peer_sid); int security_get_classes(struct selinux_policy *policy, - char ***classes, int *nclasses); + char ***classes, u32 *nclasses); int security_get_permissions(struct selinux_policy *policy, - char *class, char ***perms, int *nperms); + const char *class, char ***perms, u32 *nperms); int security_get_reject_unknown(void); int security_get_allow_unknown(void); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index f79e96f0f221..b969e87fd870 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1798,7 +1798,8 @@ static int sel_make_perm_files(struct selinux_policy *newpolicy, char *objclass, int classvalue, struct dentry *dir) { - int i, rc, nperms; + u32 i, nperms; + int rc; char **perms; rc = security_get_permissions(newpolicy, objclass, &perms, &nperms); @@ -1868,8 +1869,8 @@ static int sel_make_classes(struct selinux_policy *newpolicy, struct dentry *class_dir, unsigned long *last_class_ino) { - - int rc, nclasses, i; + u32 i, nclasses; + int rc; char **classes; rc = security_get_classes(newpolicy, &classes, &nclasses); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 2c5be06fbada..3ec0bb39c234 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -856,7 +856,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) struct sidtab *sidtab; struct sidtab_entry *old_entry, *new_entry; struct type_datum *type; - int index; + u32 index; int rc; if (!selinux_initialized()) @@ -1511,7 +1511,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, return -ENOMEM; if (!selinux_initialized()) { - int i; + u32 i; for (i = 1; i < SECINITSID_NUM; i++) { const char *s = initial_sid_to_string[i]; @@ -2821,7 +2821,6 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, { struct policydb *policydb = &policy->policydb; struct sidtab *sidtab = policy->sidtab; - int len; u16 sclass; struct genfs *genfs; struct ocontext *c; @@ -2843,7 +2842,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, return -ENOENT; for (c = genfs->head; c; c = c->next) { - len = strlen(c->u.name); + size_t len = strlen(c->u.name); if ((!c->v.sclass || sclass == c->v.sclass) && (strncmp(c->u.name, path, len) == 0)) break; @@ -3331,7 +3330,7 @@ static int get_classes_callback(void *k, void *d, void *args) { struct class_datum *datum = d; char *name = k, **classes = args; - int value = datum->value - 1; + u32 value = datum->value - 1; classes[value] = kstrdup(name, GFP_ATOMIC); if (!classes[value]) @@ -3341,7 +3340,7 @@ static int get_classes_callback(void *k, void *d, void *args) } int security_get_classes(struct selinux_policy *policy, - char ***classes, int *nclasses) + char ***classes, u32 *nclasses) { struct policydb *policydb; int rc; @@ -3357,7 +3356,8 @@ int security_get_classes(struct selinux_policy *policy, rc = hashtab_map(&policydb->p_classes.table, get_classes_callback, *classes); if (rc) { - int i; + u32 i; + for (i = 0; i < *nclasses; i++) kfree((*classes)[i]); kfree(*classes); @@ -3371,7 +3371,7 @@ static int get_permissions_callback(void *k, void *d, void *args) { struct perm_datum *datum = d; char *name = k, **perms = args; - int value = datum->value - 1; + u32 value = datum->value - 1; perms[value] = kstrdup(name, GFP_ATOMIC); if (!perms[value]) @@ -3381,10 +3381,11 @@ static int get_permissions_callback(void *k, void *d, void *args) } int security_get_permissions(struct selinux_policy *policy, - char *class, char ***perms, int *nperms) + const char *class, char ***perms, u32 *nperms) { struct policydb *policydb; - int rc, i; + u32 i; + int rc; struct class_datum *match; policydb = &policy->policydb; @@ -3599,7 +3600,7 @@ err: /* Check to see if the rule contains any selinux fields */ int selinux_audit_rule_known(struct audit_krule *rule) { - int i; + u32 i; for (i = 0; i < rule->field_count; i++) { struct audit_field *f = &rule->fields[i]; -- cgit v1.2.3 From 64f18f8a8c091f1f8fdc4805bafaffd15b588b23 Mon Sep 17 00:00:00 2001 From: Xiu Jianfeng Date: Fri, 4 Aug 2023 03:46:52 +0000 Subject: selinux: update comment on selinux_hooks[] After commit f22f9aaf6c3d ("selinux: remove the runtime disable functionality"), the comment on selinux_hooks[] is out-of-date, remove the last paragraph about runtime disable functionality. Signed-off-by: Xiu Jianfeng Signed-off-by: Paul Moore --- security/selinux/hooks.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7cd687284563..cf787eaca755 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6963,10 +6963,6 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd) * hooks ("allocating" hooks). * * Please follow block comment delimiters in the list to keep this order. - * - * This ordering is needed for SELinux runtime disable to work at least somewhat - * safely. Breaking the ordering rules above might lead to NULL pointer derefs - * when disabling SELinux at runtime. */ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), -- cgit v1.2.3 From 2b86e04bce141311c3a68940be2c8d5984274fca Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 7 Aug 2023 20:05:18 +0200 Subject: selinux: use GFP_KERNEL while reading binary policy Use GFP_KERNEL instead of GFP_ATOMIC while reading a binary policy in sens_read() and cat_read(), similar to surrounding code. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/policydb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index a424997c79eb..bb850b608dc6 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -1597,7 +1597,7 @@ static int sens_read(struct policydb *p, struct symtab *s, void *fp) __le32 buf[2]; u32 len; - levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC); + levdatum = kzalloc(sizeof(*levdatum), GFP_KERNEL); if (!levdatum) return -ENOMEM; @@ -1608,12 +1608,12 @@ static int sens_read(struct policydb *p, struct symtab *s, void *fp) len = le32_to_cpu(buf[0]); levdatum->isalias = le32_to_cpu(buf[1]); - rc = str_read(&key, GFP_ATOMIC, fp, len); + rc = str_read(&key, GFP_KERNEL, fp, len); if (rc) goto bad; rc = -ENOMEM; - levdatum->level = kmalloc(sizeof(*levdatum->level), GFP_ATOMIC); + levdatum->level = kmalloc(sizeof(*levdatum->level), GFP_KERNEL); if (!levdatum->level) goto bad; @@ -1638,7 +1638,7 @@ static int cat_read(struct policydb *p, struct symtab *s, void *fp) __le32 buf[3]; u32 len; - catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC); + catdatum = kzalloc(sizeof(*catdatum), GFP_KERNEL); if (!catdatum) return -ENOMEM; @@ -1650,7 +1650,7 @@ static int cat_read(struct policydb *p, struct symtab *s, void *fp) catdatum->value = le32_to_cpu(buf[1]); catdatum->isalias = le32_to_cpu(buf[2]); - rc = str_read(&key, GFP_ATOMIC, fp, len); + rc = str_read(&key, GFP_KERNEL, fp, len); if (rc) goto bad; -- cgit v1.2.3 From 817199e006e514e6c39a17ed2e9fece1bd56b898 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Mon, 7 Aug 2023 22:57:22 -0400 Subject: selinux: revert SECINITSID_INIT support This commit reverts 5b0eea835d4e ("selinux: introduce an initial SID for early boot processes") as it was found to cause problems on distros with old SELinux userspace tools/libraries, specifically Ubuntu 16.04. Hopefully we will be able to re-add this functionality at a later date, but let's revert this for now to help ensure a stable and backwards compatible SELinux tree. Link: https://lore.kernel.org/selinux/87edkseqf8.fsf@mail.lhotse Acked-by: Ondrej Mosnacek Signed-off-by: Paul Moore --- security/selinux/hooks.c | 28 ------------------------ security/selinux/include/initial_sid_to_string.h | 2 +- security/selinux/include/policycap.h | 1 - security/selinux/include/policycap_names.h | 1 - security/selinux/include/security.h | 6 ----- security/selinux/ss/policydb.c | 27 ----------------------- 6 files changed, 1 insertion(+), 64 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index cf787eaca755..7138083c5bef 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2313,19 +2313,6 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) new_tsec->keycreate_sid = 0; new_tsec->sockcreate_sid = 0; - /* - * Before policy is loaded, label any task outside kernel space - * as SECINITSID_INIT, so that any userspace tasks surviving from - * early boot end up with a label different from SECINITSID_KERNEL - * (if the policy chooses to set SECINITSID_INIT != SECINITSID_KERNEL). - */ - if (!selinux_initialized()) { - new_tsec->sid = SECINITSID_INIT; - /* also clear the exec_sid just in case */ - new_tsec->exec_sid = 0; - return 0; - } - if (old_tsec->exec_sid) { new_tsec->sid = old_tsec->exec_sid; /* Reset exec SID on execve. */ @@ -4542,21 +4529,6 @@ static int sock_has_perm(struct sock *sk, u32 perms) if (sksec->sid == SECINITSID_KERNEL) return 0; - /* - * Before POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, sockets that - * inherited the kernel context from early boot used to be skipped - * here, so preserve that behavior unless the capability is set. - * - * By setting the capability the policy signals that it is ready - * for this quirk to be fixed. Note that sockets created by a kernel - * thread or a usermode helper executed without a transition will - * still be skipped in this check regardless of the policycap - * setting. - */ - if (!selinux_policycap_userspace_initial_context() && - sksec->sid == SECINITSID_INIT) - return 0; - ad_net_init_from_sk(&ad, &net, sk); return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms, diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h index 5e5f0993dac2..ecc6e74fa09b 100644 --- a/security/selinux/include/initial_sid_to_string.h +++ b/security/selinux/include/initial_sid_to_string.h @@ -10,7 +10,7 @@ static const char *const initial_sid_to_string[] = { NULL, "file", NULL, - "init", + NULL, "any_socket", "port", "netif", diff --git a/security/selinux/include/policycap.h b/security/selinux/include/policycap.h index c7373e6effe5..f35d3458e71d 100644 --- a/security/selinux/include/policycap.h +++ b/security/selinux/include/policycap.h @@ -12,7 +12,6 @@ enum { POLICYDB_CAP_NNP_NOSUID_TRANSITION, POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS, POLICYDB_CAP_IOCTL_SKIP_CLOEXEC, - POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, __POLICYDB_CAP_MAX }; #define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1) diff --git a/security/selinux/include/policycap_names.h b/security/selinux/include/policycap_names.h index 28e4c9ee2399..49bbe120d173 100644 --- a/security/selinux/include/policycap_names.h +++ b/security/selinux/include/policycap_names.h @@ -14,7 +14,6 @@ const char *const selinux_policycap_names[__POLICYDB_CAP_MAX] = { "nnp_nosuid_transition", "genfs_seclabel_symlinks", "ioctl_skip_cloexec", - "userspace_initial_context", }; #endif /* _SELINUX_POLICYCAP_NAMES_H_ */ diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 074d439fe9ad..a9de89af8fdc 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -189,12 +189,6 @@ static inline bool selinux_policycap_ioctl_skip_cloexec(void) selinux_state.policycap[POLICYDB_CAP_IOCTL_SKIP_CLOEXEC]); } -static inline bool selinux_policycap_userspace_initial_context(void) -{ - return READ_ONCE( - selinux_state.policycap[POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT]); -} - struct selinux_policy_convert_data; struct selinux_load_state { diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index bb850b608dc6..cd44b13b8d3f 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -864,8 +864,6 @@ void policydb_destroy(struct policydb *p) int policydb_load_isids(struct policydb *p, struct sidtab *s) { struct ocontext *head, *c; - bool isid_init_supported = ebitmap_get_bit(&p->policycaps, - POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT); int rc; rc = sidtab_init(s); @@ -889,13 +887,6 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) if (!name) continue; - /* - * Also ignore SECINITSID_INIT if the policy doesn't declare - * support for it - */ - if (sid == SECINITSID_INIT && !isid_init_supported) - continue; - rc = sidtab_set_initial(s, sid, &c->context[0]); if (rc) { pr_err("SELinux: unable to load initial SID %s.\n", @@ -903,24 +894,6 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) sidtab_destroy(s); return rc; } - - /* - * If the policy doesn't support the "userspace_initial_context" - * capability, set SECINITSID_INIT to the same context as - * SECINITSID_KERNEL. This ensures the same behavior as before - * the reintroduction of SECINITSID_INIT, where all tasks - * started before policy load would initially get the context - * corresponding to SECINITSID_KERNEL. - */ - if (sid == SECINITSID_KERNEL && !isid_init_supported) { - rc = sidtab_set_initial(s, SECINITSID_INIT, &c->context[0]); - if (rc) { - pr_err("SELinux: unable to load initial SID %s.\n", - name); - sidtab_destroy(s); - return rc; - } - } } return 0; } -- cgit v1.2.3 From df9d4749250dd8ed56a91336c3c54ea7a52fd1c7 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 7 Aug 2023 19:11:42 +0200 Subject: selinux: avoid implicit conversions in avtab code Return u32 from avtab_hash() instead of int, since the hashing is done on u32 and the result is used as an index on the hash array. Use the type of the limit in for loops. Avoid signed to unsigned conversion of multiplication result in avtab_hash_eval() and perform multiplication in destination type. Use unsigned loop iterator for index operations, to avoid sign extension. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/avtab.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 243e5dabfa86..86d98a8e291b 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -29,7 +29,7 @@ static struct kmem_cache *avtab_xperms_cachep __ro_after_init; /* Based on MurmurHash3, written by Austin Appleby and placed in the * public domain. */ -static inline int avtab_hash(const struct avtab_key *keyp, u32 mask) +static inline u32 avtab_hash(const struct avtab_key *keyp, u32 mask) { static const u32 c1 = 0xcc9e2d51; static const u32 c2 = 0x1b873593; @@ -66,7 +66,7 @@ static inline int avtab_hash(const struct avtab_key *keyp, u32 mask) } static struct avtab_node* -avtab_insert_node(struct avtab *h, int hvalue, +avtab_insert_node(struct avtab *h, u32 hvalue, struct avtab_node *prev, const struct avtab_key *key, const struct avtab_datum *datum) { @@ -106,7 +106,7 @@ avtab_insert_node(struct avtab *h, int hvalue, static int avtab_insert(struct avtab *h, const struct avtab_key *key, const struct avtab_datum *datum) { - int hvalue; + u32 hvalue; struct avtab_node *prev, *cur, *newnode; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); @@ -152,7 +152,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, const struct avtab_key *key, const struct avtab_datum *datum) { - int hvalue; + u32 hvalue; struct avtab_node *prev, *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); @@ -186,7 +186,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_node *avtab_search_node(struct avtab *h, const struct avtab_key *key) { - int hvalue; + u32 hvalue; struct avtab_node *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); @@ -246,7 +246,7 @@ avtab_search_node_next(struct avtab_node *node, u16 specified) void avtab_destroy(struct avtab *h) { - int i; + u32 i; struct avtab_node *cur, *temp; if (!h) @@ -325,7 +325,7 @@ int avtab_alloc_dup(struct avtab *new, const struct avtab *orig) #ifdef CONFIG_SECURITY_SELINUX_DEBUG void avtab_hash_eval(struct avtab *h, const char *tag) { - int i, chain_len, slots_used, max_chain_len; + u32 i, chain_len, slots_used, max_chain_len; unsigned long long chain2_len_sum; struct avtab_node *cur; @@ -344,7 +344,7 @@ void avtab_hash_eval(struct avtab *h, const char *tag) if (chain_len > max_chain_len) max_chain_len = chain_len; - chain2_len_sum += chain_len * chain_len; + chain2_len_sum += (unsigned long long)chain_len * chain_len; } } @@ -374,13 +374,13 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, { __le16 buf16[4]; u16 enabled; - u32 items, items2, val, vers = pol->policyvers; + u32 items, items2, val, i; struct avtab_key key; struct avtab_datum datum; struct avtab_extended_perms xperms; __le32 buf32[ARRAY_SIZE(xperms.perms.p)]; - int i, rc; - unsigned set; + int rc; + unsigned int set, vers = pol->policyvers; memset(&key, 0, sizeof(struct avtab_key)); memset(&datum, 0, sizeof(struct avtab_datum)); @@ -616,7 +616,7 @@ int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp) int avtab_write(struct policydb *p, struct avtab *a, void *fp) { - unsigned int i; + u32 i; int rc = 0; struct avtab_node *cur; __le32 buf[1]; -- cgit v1.2.3 From 002903e1d10fd8c9e215d88e0c71f609a4af5755 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 7 Aug 2023 19:11:37 +0200 Subject: selinux: update type for number of class permissions in services code Security classes have only up to 32 permissions, hence using an u16 is sufficient (while improving padding in struct selinux_mapping). Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/services.c | 2 +- security/selinux/ss/services.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 3ec0bb39c234..dacec2ebdcd7 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -97,7 +97,6 @@ static int selinux_set_mapping(struct policydb *pol, struct selinux_map *out_map) { u16 i, j; - unsigned k; bool print_unknown_handle = false; /* Find number of classes in the input mapping */ @@ -117,6 +116,7 @@ static int selinux_set_mapping(struct policydb *pol, while (map[j].name) { const struct security_class_mapping *p_in = map + (j++); struct selinux_mapping *p_out = out_map->mapping + j; + u16 k; /* An empty class string skips ahead */ if (!strcmp(p_in->name, "")) { diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index ed2ee6600467..d24b0a3d198e 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h @@ -12,7 +12,7 @@ /* Mapping for a single class */ struct selinux_mapping { u16 value; /* policy value for class */ - unsigned int num_perms; /* number of permissions in class */ + u16 num_perms; /* number of permissions in class */ u32 perms[sizeof(u32) * 8]; /* policy values for permissions */ }; -- cgit v1.2.3 From aa4b60518280834529f75cb7667ffac91967abea Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 7 Aug 2023 19:11:38 +0200 Subject: selinux: make left shifts well defined The loops upper bound represent the number of permissions used (for the current class or in general). The limit for this is 32, thus we might left shift of one less, 31. Shifting a base of 1 results in undefined behavior; use (u32)1 as base. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/services.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index dacec2ebdcd7..1eeffc66ea7d 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -207,22 +207,22 @@ static void map_decision(struct selinux_map *map, for (i = 0, result = 0; i < n; i++) { if (avd->allowed & mapping->perms[i]) - result |= 1<perms[i]) - result |= 1<allowed = result; for (i = 0, result = 0; i < n; i++) if (avd->auditallow & mapping->perms[i]) - result |= 1<auditallow = result; for (i = 0, result = 0; i < n; i++) { if (avd->auditdeny & mapping->perms[i]) - result |= 1<perms[i]) - result |= 1<auditdeny = result; } } -- cgit v1.2.3 From 97842c56b8c80bb43f30ffbecbde0e512025e3ce Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 7 Aug 2023 19:11:39 +0200 Subject: selinux: avoid implicit conversions in selinuxfs code Use umode_t as parameter type for sel_make_inode(), which assigns the value to the member i_mode of struct inode. Use identical and unsigned types for loop iterators. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/selinuxfs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index b969e87fd870..107b028d5e40 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -97,7 +97,7 @@ static int selinux_fs_info_create(struct super_block *sb) static void selinux_fs_info_free(struct super_block *sb) { struct selinux_fs_info *fsi = sb->s_fs_info; - int i; + unsigned int i; if (fsi) { for (i = 0; i < fsi->bool_num; i++) @@ -1075,8 +1075,8 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) u32 sid, *sids = NULL; ssize_t length; char *newcon; - int i, rc; - u32 len, nsids; + int rc; + u32 i, len, nsids; length = avc_has_perm(current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_USER, @@ -1192,7 +1192,7 @@ out: return length; } -static struct inode *sel_make_inode(struct super_block *sb, int mode) +static struct inode *sel_make_inode(struct super_block *sb, umode_t mode) { struct inode *ret = new_inode(sb); @@ -1613,7 +1613,7 @@ static int sel_make_avc_files(struct dentry *dir) { struct super_block *sb = dir->d_sb; struct selinux_fs_info *fsi = sb->s_fs_info; - int i; + unsigned int i; static const struct tree_descr files[] = { { "cache_threshold", &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR }, @@ -1649,7 +1649,7 @@ static int sel_make_ss_files(struct dentry *dir) { struct super_block *sb = dir->d_sb; struct selinux_fs_info *fsi = sb->s_fs_info; - int i; + unsigned int i; static const struct tree_descr files[] = { { "sidtab_hash_stats", &sel_sidtab_hash_stats_ops, S_IRUGO }, }; @@ -1700,7 +1700,7 @@ static const struct file_operations sel_initcon_ops = { static int sel_make_initcon_files(struct dentry *dir) { - int i; + unsigned int i; for (i = 1; i <= SECINITSID_NUM; i++) { struct inode *inode; -- cgit v1.2.3 From dee15375484326a684377d6e741fc222a80a15bb Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 7 Aug 2023 19:11:40 +0200 Subject: selinux: avoid implicit conversions in policydb code Use the identical type for local variables, e.g. loop counters. Declare members of struct policydb_compat_info unsigned to consistently use unsigned iterators. They hold read-only non-negative numbers in the global variable policydb_compat. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/ss/policydb.c | 69 ++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 32 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index cd44b13b8d3f..28bd75dc6f71 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -55,9 +55,9 @@ static const char *const symtab_name[SYM_NUM] = { #endif struct policydb_compat_info { - int version; - int sym_num; - int ocon_num; + unsigned int version; + unsigned int sym_num; + unsigned int ocon_num; }; /* These need to be updated if SYM_NUM or OCON_NUM changes */ @@ -159,9 +159,9 @@ static const struct policydb_compat_info policydb_compat[] = { }, }; -static const struct policydb_compat_info *policydb_lookup_compat(int version) +static const struct policydb_compat_info *policydb_lookup_compat(unsigned int version) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) { if (policydb_compat[i].version == version) @@ -359,7 +359,7 @@ static int role_tr_destroy(void *key, void *datum, void *p) return 0; } -static void ocontext_destroy(struct ocontext *c, int i) +static void ocontext_destroy(struct ocontext *c, unsigned int i) { if (!c) return; @@ -782,7 +782,7 @@ void policydb_destroy(struct policydb *p) { struct ocontext *c, *ctmp; struct genfs *g, *gtmp; - int i; + u32 i; struct role_allow *ra, *lra = NULL; for (i = 0; i < SYM_NUM; i++) { @@ -1128,8 +1128,8 @@ static int common_read(struct policydb *p, struct symtab *s, void *fp) char *key = NULL; struct common_datum *comdatum; __le32 buf[4]; - u32 len, nel; - int i, rc; + u32 i, len, nel; + int rc; comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL); if (!comdatum) @@ -1194,13 +1194,13 @@ static int type_set_read(struct type_set *t, void *fp) static int read_cons_helper(struct policydb *p, struct constraint_node **nodep, - int ncons, int allowxtarget, void *fp) + u32 ncons, int allowxtarget, void *fp) { struct constraint_node *c, *lc; struct constraint_expr *e, *le; __le32 buf[3]; - u32 nexpr; - int rc, i, j, depth; + u32 i, j, nexpr; + int rc, depth; lc = NULL; for (i = 0; i < ncons; i++) { @@ -1292,8 +1292,8 @@ static int class_read(struct policydb *p, struct symtab *s, void *fp) char *key = NULL; struct class_datum *cladatum; __le32 buf[6]; - u32 len, len2, ncons, nel; - int i, rc; + u32 i, len, len2, ncons, nel; + int rc; cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL); if (!cladatum) @@ -1386,7 +1386,8 @@ static int role_read(struct policydb *p, struct symtab *s, void *fp) { char *key = NULL; struct role_datum *role; - int rc, to_read = 2; + int rc; + unsigned int to_read = 2; __le32 buf[3]; u32 len; @@ -1442,7 +1443,8 @@ static int type_read(struct policydb *p, struct symtab *s, void *fp) { char *key = NULL; struct type_datum *typdatum; - int rc, to_read = 3; + int rc; + unsigned int to_read = 3; __le32 buf[4]; u32 len; @@ -1516,7 +1518,8 @@ static int user_read(struct policydb *p, struct symtab *s, void *fp) { char *key = NULL; struct user_datum *usrdatum; - int rc, to_read = 2; + int rc; + unsigned int to_read = 2; __le32 buf[3]; u32 len; @@ -1657,7 +1660,7 @@ static int user_bounds_sanity_check(void *key, void *datum, void *datap) upper = user = datum; while (upper->bounds) { struct ebitmap_node *node; - unsigned long bit; + u32 bit; if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { pr_err("SELinux: user %s: " @@ -1693,7 +1696,7 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap) upper = role = datum; while (upper->bounds) { struct ebitmap_node *node; - unsigned long bit; + u32 bit; if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { pr_err("SELinux: role %s: " @@ -1808,9 +1811,9 @@ static int range_read(struct policydb *p, void *fp) { struct range_trans *rt = NULL; struct mls_range *r = NULL; - int i, rc; + int rc; __le32 buf[2]; - u32 nel; + u32 i, nel; if (p->policyvers < POLICYDB_VERSION_MLS) return 0; @@ -2056,9 +2059,9 @@ out: static int filename_trans_read(struct policydb *p, void *fp) { - u32 nel; + u32 nel, i; __le32 buf[1]; - int rc, i; + int rc; if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) return 0; @@ -2097,8 +2100,8 @@ static int filename_trans_read(struct policydb *p, void *fp) static int genfs_read(struct policydb *p, void *fp) { - int i, j, rc; - u32 nel, nel2, len, len2; + int rc; + u32 i, j, nel, nel2, len, len2; __le32 buf[1]; struct ocontext *l, *c; struct ocontext *newc = NULL; @@ -2211,8 +2214,9 @@ out: static int ocontext_read(struct policydb *p, const struct policydb_compat_info *info, void *fp) { - int i, j, rc; - u32 nel, len; + int rc; + unsigned int i; + u32 j, nel, len; __be64 prefixbuf[1]; __le32 buf[3]; struct ocontext *l, *c; @@ -2403,9 +2407,9 @@ int policydb_read(struct policydb *p, void *fp) struct role_allow *ra, *lra; struct role_trans_key *rtk = NULL; struct role_trans_datum *rtd = NULL; - int i, j, rc; + int rc; __le32 buf[4]; - u32 len, nprim, nel, perm; + u32 i, j, len, nprim, nel, perm; char *policydb_str; const struct policydb_compat_info *info; @@ -3256,7 +3260,8 @@ static int (*const write_f[SYM_NUM]) (void *key, void *datum, void *datap) = { static int ocontext_write(struct policydb *p, const struct policydb_compat_info *info, void *fp) { - unsigned int i, j, rc; + unsigned int i, j; + int rc; size_t nel, len; __be64 prefixbuf[1]; __le32 buf[3]; @@ -3605,10 +3610,10 @@ static int filename_trans_write(struct policydb *p, void *fp) */ int policydb_write(struct policydb *p, void *fp) { - unsigned int i, num_syms; + unsigned int num_syms; int rc; __le32 buf[4]; - u32 config; + u32 config, i; size_t len; const struct policydb_compat_info *info; -- cgit v1.2.3 From e49be9bc7c1bd1125933f42a157ca9a2812e3797 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 7 Aug 2023 19:11:41 +0200 Subject: selinux: use unsigned iterator in nlmsgtab code Use an unsigned type as loop iterator. Signed-off-by: Christian Göttsche Signed-off-by: Paul Moore --- security/selinux/nlmsgtab.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 2ee7b4ed43ef..8ff670cf1ee5 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -153,7 +153,8 @@ static const struct nlmsg_perm nlmsg_audit_perms[] = { static int nlmsg_perm(u16 nlmsg_type, u32 *perm, const struct nlmsg_perm *tab, size_t tabsize) { - int i, err = -EINVAL; + unsigned int i; + int err = -EINVAL; for (i = 0; i < tabsize/sizeof(struct nlmsg_perm); i++) if (nlmsg_type == tab[i].nlmsg_type) { -- cgit v1.2.3 From 1df83cbf23a27174aee6ea5e52462f03f7e48a10 Mon Sep 17 00:00:00 2001 From: Andrew Kanner Date: Tue, 15 Aug 2023 22:59:17 +0200 Subject: selinux: prevent KMSAN warning in selinux_inet_conn_request() KMSAN reports the following issue: [ 81.822503] ===================================================== [ 81.823222] BUG: KMSAN: uninit-value in selinux_inet_conn_request+0x2c8/0x4b0 [ 81.823891] selinux_inet_conn_request+0x2c8/0x4b0 [ 81.824385] security_inet_conn_request+0xc0/0x160 [ 81.824886] tcp_v4_route_req+0x30e/0x490 [ 81.825343] tcp_conn_request+0xdc8/0x3400 [ 81.825813] tcp_v4_conn_request+0x134/0x190 [ 81.826292] tcp_rcv_state_process+0x1f4/0x3b40 [ 81.826797] tcp_v4_do_rcv+0x9ca/0xc30 [ 81.827236] tcp_v4_rcv+0x3bf5/0x4180 [ 81.827670] ip_protocol_deliver_rcu+0x822/0x1230 [ 81.828174] ip_local_deliver_finish+0x259/0x370 [ 81.828667] ip_local_deliver+0x1c0/0x450 [ 81.829105] ip_sublist_rcv+0xdc1/0xf50 [ 81.829534] ip_list_rcv+0x72e/0x790 [ 81.829941] __netif_receive_skb_list_core+0x10d5/0x1180 [ 81.830499] netif_receive_skb_list_internal+0xc41/0x1190 [ 81.831064] napi_complete_done+0x2c4/0x8b0 [ 81.831532] e1000_clean+0x12bf/0x4d90 [ 81.831983] __napi_poll+0xa6/0x760 [ 81.832391] net_rx_action+0x84c/0x1550 [ 81.832831] __do_softirq+0x272/0xa6c [ 81.833239] __irq_exit_rcu+0xb7/0x1a0 [ 81.833654] irq_exit_rcu+0x17/0x40 [ 81.834044] common_interrupt+0x8d/0xa0 [ 81.834494] asm_common_interrupt+0x2b/0x40 [ 81.834949] default_idle+0x17/0x20 [ 81.835356] arch_cpu_idle+0xd/0x20 [ 81.835766] default_idle_call+0x43/0x70 [ 81.836210] do_idle+0x258/0x800 [ 81.836581] cpu_startup_entry+0x26/0x30 [ 81.837002] __pfx_ap_starting+0x0/0x10 [ 81.837444] secondary_startup_64_no_verify+0x17a/0x17b [ 81.837979] [ 81.838166] Local variable nlbl_type.i created at: [ 81.838596] selinux_inet_conn_request+0xe3/0x4b0 [ 81.839078] security_inet_conn_request+0xc0/0x160 KMSAN warning is reproducible with: * netlabel_mgmt_protocount is 0 (e.g. netlbl_enabled() returns 0) * CONFIG_SECURITY_NETWORK_XFRM may be set or not * CONFIG_KMSAN=y * `ssh USER@HOSTNAME /bin/date` selinux_skb_peerlbl_sid() will call selinux_xfrm_skb_sid(), then fall to selinux_netlbl_skbuff_getsid() which will not initialize nlbl_type, but it will be passed to: err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); and checked by KMSAN, although it will not be used inside security_net_peersid_resolve() (at least now), since this function will check either (xfrm_sid == SECSID_NULL) or (nlbl_sid == SECSID_NULL) first and return before using uninitialized nlbl_type. Signed-off-by: Andrew Kanner [PM: subject line tweak, removed 'fixes' tag as code is not broken] Signed-off-by: Paul Moore --- security/selinux/netlabel.c | 1 + 1 file changed, 1 insertion(+) (limited to 'security') diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 528f5186e912..8f182800e412 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -198,6 +198,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, struct netlbl_lsm_secattr secattr; if (!netlbl_enabled()) { + *type = NETLBL_NLTYPE_NONE; *sid = SECSID_NULL; return 0; } -- cgit v1.2.3