Commit ef5f46b6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull selinux fixes from Paul Moore:

 - Ensure SELinux is always properly accessing its own sock LSM state

 - Only reserve an xattr slot for SELinux if it will be used

 - Fix a SELinux auditing regression in the directory avdcache

* tag 'selinux-pr-20260501' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinux: fix avdcache auditing
  selinux: don't reserve xattr slot when we won't fill it
  selinux: use sk blob accessor in socket permission helpers
parents ee9dce44 f92d5425
Loading
Loading
Loading
Loading
+17 −21
Original line number Diff line number Diff line
@@ -2966,7 +2966,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
{
	const struct cred_security_struct *crsec = selinux_cred(current_cred());
	struct superblock_security_struct *sbsec;
	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
	struct xattr *xattr;
	u32 newsid, clen;
	u16 newsclass;
	int rc;
@@ -2992,6 +2992,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
	    !(sbsec->flags & SBLABEL_MNT))
		return -EOPNOTSUPP;

	xattr = lsm_get_xattr_slot(xattrs, xattr_count);
	if (xattr) {
		rc = security_sid_to_context_force(newsid,
						   &context, &clen);
@@ -3208,15 +3209,13 @@ static inline int task_avdcache_search(struct task_security_struct *tsec,
 * @tsec: the task's security state
 * @isec: the inode associated with the cache entry
 * @avd: the AVD to cache
 * @audited: the permission audit bitmask to cache
 *
 * Update the AVD cache in @tsec with the @avdc and @audited info associated
 * Update the AVD cache in @tsec with the @avd info associated
 * with @isec.
 */
static inline void task_avdcache_update(struct task_security_struct *tsec,
					struct inode_security_struct *isec,
					struct av_decision *avd,
					u32 audited)
					struct av_decision *avd)
{
	int spot;

@@ -3228,9 +3227,7 @@ static inline void task_avdcache_update(struct task_security_struct *tsec,
	spot = (tsec->avdcache.dir_spot + 1) & (TSEC_AVDC_DIR_SIZE - 1);
	tsec->avdcache.dir_spot = spot;
	tsec->avdcache.dir[spot].isid = isec->sid;
	tsec->avdcache.dir[spot].audited = audited;
	tsec->avdcache.dir[spot].allowed = avd->allowed;
	tsec->avdcache.dir[spot].permissive = avd->flags & AVD_FLAGS_PERMISSIVE;
	tsec->avdcache.dir[spot].avd = *avd;
	tsec->avdcache.permissive_neveraudit =
		(avd->flags == (AVD_FLAGS_PERMISSIVE|AVD_FLAGS_NEVERAUDIT));
}
@@ -3251,6 +3248,7 @@ static int selinux_inode_permission(struct inode *inode, int requested)
	struct task_security_struct *tsec;
	struct inode_security_struct *isec;
	struct avdc_entry *avdc;
	struct av_decision avd, *avdp = &avd;
	int rc, rc2;
	u32 audited, denied;

@@ -3272,23 +3270,21 @@ static int selinux_inode_permission(struct inode *inode, int requested)
	rc = task_avdcache_search(tsec, isec, &avdc);
	if (likely(!rc)) {
		/* Cache hit. */
		audited = perms & avdc->audited;
		denied = perms & ~avdc->allowed;
		if (unlikely(denied && enforcing_enabled() &&
			     !avdc->permissive))
		avdp = &avdc->avd;
		denied = perms & ~avdp->allowed;
		if (unlikely(denied) && enforcing_enabled() &&
			!(avdp->flags & AVD_FLAGS_PERMISSIVE))
			rc = -EACCES;
	} else {
		struct av_decision avd;

		/* Cache miss. */
		rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass,
					  perms, 0, &avd);
		audited = avc_audit_required(perms, &avd, rc,
			(requested & MAY_ACCESS) ? FILE__AUDIT_ACCESS : 0,
			&denied);
		task_avdcache_update(tsec, isec, &avd, audited);
					  perms, 0, avdp);
		task_avdcache_update(tsec, isec, avdp);
	}

	audited = avc_audit_required(perms, avdp, rc,
				     (requested & MAY_ACCESS) ?
				     FILE__AUDIT_ACCESS : 0, &denied);
	if (likely(!audited))
		return rc;

@@ -4920,7 +4916,7 @@ static bool sock_skip_has_perm(u32 sid)

static int sock_has_perm(struct sock *sk, u32 perms)
{
	struct sk_security_struct *sksec = sk->sk_security;
	struct sk_security_struct *sksec = selinux_sock(sk);
	struct common_audit_data ad;
	struct lsm_network_audit net;

@@ -6227,7 +6223,7 @@ static unsigned int selinux_ip_postroute(void *priv,

static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_type)
{
	struct sk_security_struct *sksec = sk->sk_security;
	struct sk_security_struct *sksec = selinux_sock(sk);
	struct common_audit_data ad;
	u8 driver;
	u8 xperm;
+1 −3
Original line number Diff line number Diff line
@@ -32,9 +32,7 @@

struct avdc_entry {
	u32 isid; /* inode SID */
	u32 allowed; /* allowed permission bitmask */
	u32 audited; /* audited permission bitmask */
	bool permissive; /* AVC permissive flag */
	struct av_decision avd; /* av decision */
};

struct cred_security_struct {