Commit 1dbae189 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents 3ea67c4f 1df83cbf
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
# 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
@@ -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.
+9 −8
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
/*
 * Implementation of the kernel access vector cache (AVC).
 *
 * Authors:  Stephen Smalley, <sds@tycho.nsa.gov>
 * Authors:  Stephen Smalley, <stephen.smalley.work@gmail.com>
 *	     James Morris <jmorris@redhat.com>
 *
 * Update:   KaiGai, Kohei <kaigai@ak.jp.nec.com>
@@ -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;
+58 −64
Original line number Diff line number Diff line
// 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();

+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
/*
 * Access vector cache interface for object managers.
 *
 * Author : Stephen Smalley, <sds@tycho.nsa.gov>
 * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
 */
#ifndef _SELINUX_AVC_H_
#define _SELINUX_AVC_H_
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
/*
 * Access vector cache interface for the security server.
 *
 * Author : Stephen Smalley, <sds@tycho.nsa.gov>
 * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
 */
#ifndef _SELINUX_AVC_SS_H_
#define _SELINUX_AVC_SS_H_
Loading