diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-30 17:51:16 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-30 17:51:16 +0200 |
commit | 1dbae189873066e817fe94b4e4ac7c8c42b51d77 (patch) | |
tree | f2323eef50fab4578685aadeaa70c1ad528eba61 /security/selinux/hooks.c | |
parent | Merge tag 'audit-pr-20230829' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff) | |
parent | selinux: prevent KMSAN warning in selinux_inet_conn_request() (diff) | |
download | linux-1dbae189873066e817fe94b4e4ac7c8c42b51d77.tar.xz linux-1dbae189873066e817fe94b4e4ac7c8c42b51d77.zip |
Merge tag 'selinux-pr-20230829' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux updates from Paul Moore:
"Thirty three SELinux patches, which is a pretty big number for us, but
there isn't really anything scary in here; in fact we actually manage
to remove 10 lines of code with this :)
- Promote the SELinux DEBUG_HASHES macro to CONFIG_SECURITY_SELINUX_DEBUG
The DEBUG_HASHES macro was a buried SELinux specific preprocessor
debug macro that was a problem waiting to happen. Promoting the
debug macro to a proper Kconfig setting should help both improve
the visibility of the feature as well enable improved test
coverage. We've moved some additional debug functions under the
CONFIG_SECURITY_SELINUX_DEBUG flag and we may see more work in the
future.
- Emit a pr_notice() message if virtual memory is executable by default
As this impacts the SELinux access control policy enforcement, if
the system's configuration is such that virtual memory is
executable by default we print a single line notice to the console.
- Drop avtab_search() in favor of avtab_search_node()
Both functions are nearly identical so we removed avtab_search()
and converted the callers to avtab_search_node().
- Add some SELinux network auditing helpers
The helpers not only reduce a small amount of code duplication, but
they provide an opportunity to improve UDP flood performance
slightly by delaying initialization of the audit data in some
cases.
- Convert GFP_ATOMIC allocators to GFP_KERNEL when reading SELinux policy
There were two SELinux policy load helper functions that were
allocating memory using GFP_ATOMIC, they have been converted to
GFP_KERNEL.
- Quiet a KMSAN warning in selinux_inet_conn_request()
A one-line error path (re)set patch that resolves a KMSAN warning.
It is important to note that this doesn't represent a real bug in
the current code, but it quiets KMSAN and arguably hardens the code
against future changes.
- Cleanup the policy capability accessor functions
This is a follow-up to the patch which reverted SELinux to using a
global selinux_state pointer. This patch cleans up some artifacts
of that change and turns each accessor into a one-line READ_ONCE()
call into the policy capabilities array.
- A number of patches from Christian Göttsche
Christian submitted almost two-thirds of the patches in this pull
request as he worked to harden the SELinux code against type
differences, variable overflows, etc.
- Support for separating early userspace from the kernel in policy,
with a later revert
We did have a patch that added a new userspace initial SID which
would allow SELinux to distinguish between early user processes
created before the initial policy load and the kernel itself.
Unfortunately additional post-merge testing revealed a problematic
interaction with an old SELinux userspace on an old version of
Ubuntu so we've reverted the patch until we can resolve the
compatibility issue.
- Remove some outdated comments dealing with LSM hook registration
When we removed the runtime disable functionality we forgot to
remove some old comments discussing the importance of LSM hook
registration ordering.
- Minor administrative changes
Stephen Smalley updated his email address and "debranded" SELinux
from "NSA SELinux" to simply "SELinux". We've come a long way from
the original NSA submission and I would consider SELinux a true
community project at this point so removing the NSA branding just
makes sense"
* tag 'selinux-pr-20230829' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: (33 commits)
selinux: prevent KMSAN warning in selinux_inet_conn_request()
selinux: use unsigned iterator in nlmsgtab code
selinux: avoid implicit conversions in policydb code
selinux: avoid implicit conversions in selinuxfs code
selinux: make left shifts well defined
selinux: update type for number of class permissions in services code
selinux: avoid implicit conversions in avtab code
selinux: revert SECINITSID_INIT support
selinux: use GFP_KERNEL while reading binary policy
selinux: update comment on selinux_hooks[]
selinux: avoid implicit conversions in services code
selinux: avoid implicit conversions in mls code
selinux: use identical iterator type in hashtab_duplicate()
selinux: move debug functions into debug configuration
selinux: log about VM being executable by default
selinux: fix a 0/NULL mistmatch in ad_net_init_from_iif()
selinux: introduce SECURITY_SELINUX_DEBUG configuration
selinux: introduce and use lsm_ad_net_init*() helpers
selinux: update my email address
selinux: add missing newlines in pr_err() statements
...
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 122 |
1 files changed, 58 insertions, 64 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3363716ee80a..89f3e7c7a596 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1,10 +1,10 @@ // 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. * - * Authors: Stephen Smalley, <sds@tycho.nsa.gov> + * Authors: Stephen Smalley, <stephen.smalley.work@gmail.com> * Chris Vance, <cvance@nai.com> * Wayne Salamon, <wsalamon@nai.com> * James Morris <jmorris@redhat.com> @@ -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, NULL, family); +} + /* * get the objective security ID of a task */ @@ -1125,7 +1150,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: @@ -2938,7 +2963,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; } @@ -4517,14 +4542,12 @@ 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; - 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); @@ -4917,12 +4940,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, @@ -4949,11 +4970,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); @@ -4989,13 +5008,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; @@ -5017,15 +5033,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,}; + struct lsm_network_audit net; char *addrp; - u8 secmark_active; - u8 peerlbl_active; if (family != PF_INET && family != PF_INET6) return 0; @@ -5046,10 +5060,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; @@ -5219,7 +5230,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 */ @@ -5255,9 +5266,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); @@ -5488,11 +5497,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); @@ -5602,7 +5611,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()) @@ -5618,10 +5627,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; @@ -5701,7 +5707,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); @@ -5709,10 +5715,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; @@ -5737,7 +5740,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; @@ -5834,10 +5837,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; @@ -5990,8 +5990,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: @@ -6014,8 +6013,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) @@ -6120,8 +6118,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: @@ -6148,8 +6145,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, @@ -6918,7 +6914,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); @@ -6957,10 +6953,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), @@ -7260,6 +7252,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(); |