From patchwork Thu Jan 2 16:44:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924622 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f180.google.com (mail-qt1-f180.google.com [209.85.160.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 768BA14EC46 for ; Thu, 2 Jan 2025 16:45:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836348; cv=none; b=tiWK8iGCNu9s9BpaMYEpagfbxBHbUyDBCoKVid1P3zJKtneIb14UFSvaZXPKwR4Bu4FrbV8PUUn69judKOLQ50uEo9hRKxFjxD9qHVoSfwOyis9DknPI8Aoasb/iqOB2aljwXYOli2NrmbX6F4zhzWW3i0pEhKkHRwiJm8oxTxo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836348; c=relaxed/simple; bh=HBn3jGxRLrbLXuCSIoTKaTzkaQXCs2+6WcOGZ6UP8uk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ndCc4NT5xvQiVlQaPwMc1Du5I8tumYILAeX7l/ELEKdMX8r8hUAJ65jMwo5fNLfreCnHsEj5hEv6l8zijkqXzij5KMZ0mk2MOwUXEEC5JzqTGaT0QTaRTyHE/+QR9Wcub4l6JJqv200fLAp9wXn2oce8OCMPjTqkLdecmZLwjWU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Yv1fCMtW; arc=none smtp.client-ip=209.85.160.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Yv1fCMtW" Received: by mail-qt1-f180.google.com with SMTP id d75a77b69052e-467a1d43821so109999531cf.1 for ; Thu, 02 Jan 2025 08:45:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836335; x=1736441135; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2wf7bP+6KOVMd0LKhPodCfWccB0rvFnHb+OWPXGWrAQ=; b=Yv1fCMtWs1gXCLPxaQtf+bNcxomGF7tsiuIVRdQKC1ueYgBwjaC/WnNrFeD24+R41f +OfaTvyXYilWon81L6WFlPTPjUKxME7EdmLkCzZykw9mZbd2B88xcCrthXXxbFM4a3AO J9OTI81oUJaLLpQ1t0irzFmPoK4WuIbOWt+/ZOre5lMC6kLT0MdSskJ4p+pZdzjrgC1H FqhLRhST2usYHM+xEY4rU4aT9n3v3FTf2QcbBp5/hdTzygGmtqpv3RWWC3MFpbcjC7rh MhAb6l2YSsm5gY5H9+VgN6Vu+eF86lBE166YFjrBgD98sVVimACZvULhxTFR+bPeDamm +9gA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836335; x=1736441135; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2wf7bP+6KOVMd0LKhPodCfWccB0rvFnHb+OWPXGWrAQ=; b=aHQ974WIAPziAoGdhs4DtrTzdjQb2CK+NRrmvkPty3D7WO6bZjWWBtCf2iCSt42S0R mqMmkOkv186c3XvNK/2073hor5KTeO/rmVSI0rywzp2qO2qojaJXvlAPoY+IshG8fsd5 /YUQ19LAp5y0o9HOiAUpUT6uTC0WIk/ffVPvxBU+AF3cC+j/oUrw7XoOcEwOqo1WMIXc essyntxQqx5azVa9ECYbNHuDpNysxE7nw8Y6jGlQgvz/AIY19rERuNHyr1XR7lBSScko 5ERjIpvN2czMK/02kltqTOxnojWXD3Ts/w2qFAIgCBr3m4d2Rg0wI0kZs2E89SYsJ10x N6IQ== X-Gm-Message-State: AOJu0YxV43dAeIL9s0xbx7gid2s7/l0yGe2ESEaG3LGK9imgiFluYIRA LwRncKLRiPlEZCvjYQaouyhN57W7manOB6dIldfw/RAZfqzk0nzVDdixNw== X-Gm-Gg: ASbGncvmWPJ+mqSRgqKc9Mw2xuAX4fqvsXKk3wzxQ9e3ZGoUkFypXKBkNQ/Ynn7kk1V SgFceIfdVPLegLGTmx0p0DJjM+qylDYGdAr2ViUFohYeo7UxaQPjZgs4XYA33fcnSySV1Mmpce1 VhmCn2fex3ZoAO9pkiWVoEV5gSSJdmMC44jkHhlnueC7AXrKSJEQFiLPqEODjRCpqDsl9lx/Ze/ /wGcIV3ah67gcpe0z5wsRrNugDre31uYwfAa+ZCOaaaWAIY4vZeHvF1HiMlLk0Sp1Y1q87miwkE +QNRqvTEYBIVuTWs3q6V/DckVmfO0Da8FIV8IGQKTRU8Qu2dOcBReOLAZ9J/OH7AmzizIg== X-Google-Smtp-Source: AGHT+IGYhTRKG//9YvtiWOU0VwgyKJnaDrcpCA2ScgMHLQVUgcPQfSkOWXLkP24aueB66s7TptXnOA== X-Received: by 2002:ac8:5fc5:0:b0:462:b7c9:10e with SMTP id d75a77b69052e-46a3aff2e4amr873596571cf.13.1735836333133; Thu, 02 Jan 2025 08:45:33 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.31 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:31 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 01/44] selinux: restore passing of selinux_state Date: Thu, 2 Jan 2025 11:44:26 -0500 Message-Id: <20250102164509.25606-2-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This reverts commit e67b79850fcc4eb5 ("selinux: stop passing selinux_state pointers and their offspring"). This change is necessary in order to support SELinux namespaces. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 196 +++++---- security/selinux/hooks.c | 549 +++++++++++++++---------- security/selinux/ibpkey.c | 2 +- security/selinux/ima.c | 37 +- security/selinux/include/avc.h | 41 +- security/selinux/include/avc_ss.h | 3 +- security/selinux/include/conditional.h | 4 +- security/selinux/include/ima.h | 11 +- security/selinux/include/security.h | 159 ++++--- security/selinux/netif.c | 2 +- security/selinux/netlabel.c | 17 +- security/selinux/netnode.c | 4 +- security/selinux/netport.c | 2 +- security/selinux/selinuxfs.c | 206 ++++++---- security/selinux/ss/services.c | 347 +++++++++------- security/selinux/ss/services.h | 1 + security/selinux/status.c | 44 +- security/selinux/xfrm.c | 20 +- 18 files changed, 988 insertions(+), 657 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index cc0b0af20296..effa0accefc5 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -93,7 +93,7 @@ struct selinux_avc { static struct selinux_avc selinux_avc; -void selinux_avc_init(void) +void selinux_avc_init(struct selinux_avc **avc) { int i; @@ -104,16 +104,18 @@ void selinux_avc_init(void) } atomic_set(&selinux_avc.avc_cache.active_nodes, 0); atomic_set(&selinux_avc.avc_cache.lru_hint, 0); + *avc = &selinux_avc; } -unsigned int avc_get_cache_threshold(void) +unsigned int avc_get_cache_threshold(struct selinux_avc *avc) { - return selinux_avc.avc_cache_threshold; + return avc->avc_cache_threshold; } -void avc_set_cache_threshold(unsigned int cache_threshold) +void avc_set_cache_threshold(struct selinux_avc *avc, + unsigned int cache_threshold) { - selinux_avc.avc_cache_threshold = cache_threshold; + avc->avc_cache_threshold = cache_threshold; } static struct avc_callback_node *avc_callbacks __ro_after_init; @@ -140,7 +142,7 @@ void __init avc_init(void) avc_xperms_data_cachep = KMEM_CACHE(extended_perms_data, SLAB_PANIC); } -int avc_get_hash_stats(char *page) +int avc_get_hash_stats(struct selinux_avc *avc, char *page) { int i, chain_len, max_chain_len, slots_used; struct avc_node *node; @@ -151,7 +153,7 @@ int avc_get_hash_stats(char *page) slots_used = 0; max_chain_len = 0; for (i = 0; i < AVC_CACHE_SLOTS; i++) { - head = &selinux_avc.avc_cache.slots[i]; + head = &avc->avc_cache.slots[i]; if (!hlist_empty(head)) { slots_used++; chain_len = 0; @@ -166,7 +168,7 @@ int avc_get_hash_stats(char *page) return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n" "longest chain: %d\n", - atomic_read(&selinux_avc.avc_cache.active_nodes), + atomic_read(&avc->avc_cache.active_nodes), slots_used, AVC_CACHE_SLOTS, max_chain_len); } @@ -404,7 +406,8 @@ static inline u32 avc_xperms_audit_required(u32 requested, return audited; } -static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass, +static inline int avc_xperms_audit(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, u32 requested, struct av_decision *avd, struct extended_perms_decision *xpd, u8 perm, int result, @@ -416,7 +419,7 @@ static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass, requested, avd, xpd, perm, result, &denied); if (likely(!audited)) return 0; - return slow_avc_audit(ssid, tsid, tclass, requested, + return slow_avc_audit(state, ssid, tsid, tclass, requested, audited, denied, result, ad); } @@ -428,29 +431,30 @@ static void avc_node_free(struct rcu_head *rhead) avc_cache_stats_incr(frees); } -static void avc_node_delete(struct avc_node *node) +static void avc_node_delete(struct selinux_avc *avc, struct avc_node *node) { hlist_del_rcu(&node->list); call_rcu(&node->rhead, avc_node_free); - atomic_dec(&selinux_avc.avc_cache.active_nodes); + atomic_dec(&avc->avc_cache.active_nodes); } -static void avc_node_kill(struct avc_node *node) +static void avc_node_kill(struct selinux_avc *avc, struct avc_node *node) { avc_xperms_free(node->ae.xp_node); kmem_cache_free(avc_node_cachep, node); avc_cache_stats_incr(frees); - atomic_dec(&selinux_avc.avc_cache.active_nodes); + atomic_dec(&avc->avc_cache.active_nodes); } -static void avc_node_replace(struct avc_node *new, struct avc_node *old) +static void avc_node_replace(struct selinux_avc *avc, + struct avc_node *new, struct avc_node *old) { hlist_replace_rcu(&old->list, &new->list); call_rcu(&old->rhead, avc_node_free); - atomic_dec(&selinux_avc.avc_cache.active_nodes); + atomic_dec(&avc->avc_cache.active_nodes); } -static inline int avc_reclaim_node(void) +static inline int avc_reclaim_node(struct selinux_avc *avc) { struct avc_node *node; int hvalue, try, ecx; @@ -459,17 +463,17 @@ static inline int avc_reclaim_node(void) spinlock_t *lock; for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) { - hvalue = atomic_inc_return(&selinux_avc.avc_cache.lru_hint) & + hvalue = atomic_inc_return(&avc->avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1); - head = &selinux_avc.avc_cache.slots[hvalue]; - lock = &selinux_avc.avc_cache.slots_lock[hvalue]; + head = &avc->avc_cache.slots[hvalue]; + lock = &avc->avc_cache.slots_lock[hvalue]; if (!spin_trylock_irqsave(lock, flags)) continue; rcu_read_lock(); hlist_for_each_entry(node, head, list) { - avc_node_delete(node); + avc_node_delete(avc, node); avc_cache_stats_incr(reclaims); ecx++; if (ecx >= AVC_CACHE_RECLAIM) { @@ -485,7 +489,7 @@ static inline int avc_reclaim_node(void) return ecx; } -static struct avc_node *avc_alloc_node(void) +static struct avc_node *avc_alloc_node(struct selinux_avc *avc) { struct avc_node *node; @@ -496,9 +500,9 @@ static struct avc_node *avc_alloc_node(void) INIT_HLIST_NODE(&node->list); avc_cache_stats_incr(allocations); - if (atomic_inc_return(&selinux_avc.avc_cache.active_nodes) > - selinux_avc.avc_cache_threshold) - avc_reclaim_node(); + if (atomic_inc_return(&avc->avc_cache.active_nodes) > + avc->avc_cache_threshold) + avc_reclaim_node(avc); out: return node; @@ -512,14 +516,15 @@ static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tcl memcpy(&node->ae.avd, avd, sizeof(node->ae.avd)); } -static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) +static inline struct avc_node *avc_search_node(struct selinux_avc *avc, + u32 ssid, u32 tsid, u16 tclass) { struct avc_node *node, *ret = NULL; u32 hvalue; struct hlist_head *head; hvalue = avc_hash(ssid, tsid, tclass); - head = &selinux_avc.avc_cache.slots[hvalue]; + head = &avc->avc_cache.slots[hvalue]; hlist_for_each_entry_rcu(node, head, list) { if (ssid == node->ae.ssid && tclass == node->ae.tclass && @@ -534,6 +539,7 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) /** * avc_lookup - Look up an AVC entry. + * @avc: the access vector cache * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class @@ -544,12 +550,13 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) * then this function returns the avc_node. * Otherwise, this function returns NULL. */ -static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) +static struct avc_node *avc_lookup(struct selinux_avc *avc, + u32 ssid, u32 tsid, u16 tclass) { struct avc_node *node; avc_cache_stats_incr(lookups); - node = avc_search_node(ssid, tsid, tclass); + node = avc_search_node(avc, ssid, tsid, tclass); if (node) return node; @@ -558,7 +565,8 @@ static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) return NULL; } -static int avc_latest_notif_update(u32 seqno, int is_insert) +static int avc_latest_notif_update(struct selinux_avc *avc, + u32 seqno, int is_insert) { int ret = 0; static DEFINE_SPINLOCK(notif_lock); @@ -566,14 +574,14 @@ static int avc_latest_notif_update(u32 seqno, int is_insert) spin_lock_irqsave(¬if_lock, flag); if (is_insert) { - if (seqno < selinux_avc.avc_cache.latest_notif) { + if (seqno < avc->avc_cache.latest_notif) { pr_warn("SELinux: avc: seqno %d < latest_notif %d\n", - seqno, selinux_avc.avc_cache.latest_notif); + seqno, avc->avc_cache.latest_notif); ret = -EAGAIN; } } else { - if (seqno > selinux_avc.avc_cache.latest_notif) - selinux_avc.avc_cache.latest_notif = seqno; + if (seqno > avc->avc_cache.latest_notif) + avc->avc_cache.latest_notif = seqno; } spin_unlock_irqrestore(¬if_lock, flag); @@ -582,6 +590,7 @@ static int avc_latest_notif_update(u32 seqno, int is_insert) /** * avc_insert - Insert an AVC entry. + * @avc: the access vector cache * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class @@ -597,7 +606,7 @@ static int avc_latest_notif_update(u32 seqno, int is_insert) * revocation notification, then the function copies * the access vectors into a cache entry. */ -static void avc_insert(u32 ssid, u32 tsid, u16 tclass, +static void avc_insert(struct selinux_avc *avc, u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd, struct avc_xperms_node *xp_node) { struct avc_node *pos, *node = NULL; @@ -606,28 +615,28 @@ static void avc_insert(u32 ssid, u32 tsid, u16 tclass, spinlock_t *lock; struct hlist_head *head; - if (avc_latest_notif_update(avd->seqno, 1)) + if (avc_latest_notif_update(avc, avd->seqno, 1)) return; - node = avc_alloc_node(); + node = avc_alloc_node(avc); if (!node) return; avc_node_populate(node, ssid, tsid, tclass, avd); if (avc_xperms_populate(node, xp_node)) { - avc_node_kill(node); + avc_node_kill(avc, node); return; } hvalue = avc_hash(ssid, tsid, tclass); - head = &selinux_avc.avc_cache.slots[hvalue]; - lock = &selinux_avc.avc_cache.slots_lock[hvalue]; + head = &avc->avc_cache.slots[hvalue]; + lock = &avc->avc_cache.slots_lock[hvalue]; spin_lock_irqsave(lock, flag); hlist_for_each_entry(pos, head, list) { if (pos->ae.ssid == ssid && pos->ae.tsid == tsid && pos->ae.tclass == tclass) { - avc_node_replace(node, pos); + avc_node_replace(avc, node, pos); goto found; } } @@ -694,14 +703,14 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) u32 tcontext_len; int rc; - rc = security_sid_to_context(sad->ssid, &scontext, + rc = security_sid_to_context(sad->state, sad->ssid, &scontext, &scontext_len); if (rc) audit_log_format(ab, " ssid=%d", sad->ssid); else audit_log_format(ab, " scontext=%s", scontext); - rc = security_sid_to_context(sad->tsid, &tcontext, + rc = security_sid_to_context(sad->state, sad->tsid, &tcontext, &tcontext_len); if (rc) audit_log_format(ab, " tsid=%d", sad->tsid); @@ -719,7 +728,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) kfree(scontext); /* in case of invalid context report also the actual context string */ - rc = security_sid_to_context_inval(sad->ssid, &scontext, + rc = security_sid_to_context_inval(sad->state, sad->ssid, &scontext, &scontext_len); if (!rc && scontext) { if (scontext_len && scontext[scontext_len - 1] == '\0') @@ -729,7 +738,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) kfree(scontext); } - rc = security_sid_to_context_inval(sad->tsid, &scontext, + rc = security_sid_to_context_inval(sad->state, sad->tsid, &scontext, &scontext_len); if (!rc && scontext) { if (scontext_len && scontext[scontext_len - 1] == '\0') @@ -745,7 +754,8 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) * Note that it is non-blocking and can be called from under * rcu_read_lock(). */ -noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, +noinline int slow_avc_audit(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, u32 requested, u32 audited, u32 denied, int result, struct common_audit_data *a) { @@ -767,6 +777,7 @@ noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, sad.audited = audited; sad.denied = denied; sad.result = result; + sad.state = state; a->selinux_audit_data = &sad; @@ -804,6 +815,7 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events) /** * avc_update_node - Update an AVC entry + * @avc: the access vector cache * @event : Updating event * @perms : Permission mask bits * @driver: xperm driver information @@ -820,7 +832,8 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events) * otherwise, this function updates the AVC entry. The original AVC-entry object * will release later by RCU. */ -static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, +static int avc_update_node(struct selinux_avc *avc, + u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, u32 tsid, u16 tclass, u32 seqno, struct extended_perms_decision *xpd, u32 flags) @@ -832,7 +845,7 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, struct hlist_head *head; spinlock_t *lock; - node = avc_alloc_node(); + node = avc_alloc_node(avc); if (!node) { rc = -ENOMEM; goto out; @@ -841,8 +854,8 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, /* Lock the target slot */ hvalue = avc_hash(ssid, tsid, tclass); - head = &selinux_avc.avc_cache.slots[hvalue]; - lock = &selinux_avc.avc_cache.slots_lock[hvalue]; + head = &avc->avc_cache.slots[hvalue]; + lock = &avc->avc_cache.slots_lock[hvalue]; spin_lock_irqsave(lock, flag); @@ -858,7 +871,7 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, if (!orig) { rc = -ENOENT; - avc_node_kill(node); + avc_node_kill(avc, node); goto out_unlock; } @@ -871,7 +884,7 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, if (orig->ae.xp_node) { rc = avc_xperms_populate(node, orig->ae.xp_node); if (rc) { - avc_node_kill(node); + avc_node_kill(avc, node); goto out_unlock; } } @@ -901,12 +914,12 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, case AVC_CALLBACK_ADD_XPERMS: rc = avc_add_xperms_decision(node, xpd); if (rc) { - avc_node_kill(node); + avc_node_kill(avc, node); goto out_unlock; } break; } - avc_node_replace(node, orig); + avc_node_replace(avc, node, orig); out_unlock: spin_unlock_irqrestore(lock, flag); out: @@ -915,8 +928,9 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, /** * avc_flush - Flush the cache + * @avc: the access vector cache */ -static void avc_flush(void) +static void avc_flush(struct selinux_avc *avc) { struct hlist_head *head; struct avc_node *node; @@ -925,8 +939,8 @@ static void avc_flush(void) int i; for (i = 0; i < AVC_CACHE_SLOTS; i++) { - head = &selinux_avc.avc_cache.slots[i]; - lock = &selinux_avc.avc_cache.slots_lock[i]; + head = &avc->avc_cache.slots[i]; + lock = &avc->avc_cache.slots_lock[i]; spin_lock_irqsave(lock, flag); /* @@ -935,7 +949,7 @@ static void avc_flush(void) */ rcu_read_lock(); hlist_for_each_entry(node, head, list) - avc_node_delete(node); + avc_node_delete(avc, node); rcu_read_unlock(); spin_unlock_irqrestore(lock, flag); } @@ -943,14 +957,15 @@ static void avc_flush(void) /** * avc_ss_reset - Flush the cache and revalidate migrated permissions. + * @avc: the access vector cache * @seqno: policy sequence number */ -int avc_ss_reset(u32 seqno) +int avc_ss_reset(struct selinux_avc *avc, u32 seqno) { struct avc_callback_node *c; int rc = 0, tmprc; - avc_flush(); + avc_flush(avc); for (c = avc_callbacks; c; c = c->next) { if (c->events & AVC_CALLBACK_RESET) { @@ -962,12 +977,13 @@ int avc_ss_reset(u32 seqno) } } - avc_latest_notif_update(seqno, 0); + avc_latest_notif_update(avc, seqno, 0); return rc; } /** * avc_compute_av - Add an entry to the AVC based on the security policy + * @state: SELinux state pointer * @ssid: subject * @tsid: object/target * @tclass: object class @@ -978,16 +994,18 @@ int avc_ss_reset(u32 seqno) * fails. Don't inline this, since it's the slow-path and just results in a * bigger stack frame. */ -static noinline void avc_compute_av(u32 ssid, u32 tsid, u16 tclass, +static noinline void avc_compute_av(struct selinux_state *state, u32 ssid, + u32 tsid, u16 tclass, struct av_decision *avd, struct avc_xperms_node *xp_node) { INIT_LIST_HEAD(&xp_node->xpd_head); - security_compute_av(ssid, tsid, tclass, avd, &xp_node->xp); - avc_insert(ssid, tsid, tclass, avd, xp_node); + security_compute_av(state, ssid, tsid, tclass, avd, &xp_node->xp); + avc_insert(state->avc, ssid, tsid, tclass, avd, xp_node); } -static noinline int avc_denied(u32 ssid, u32 tsid, +static noinline int avc_denied(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, u32 requested, u8 driver, u8 xperm, unsigned int flags, struct av_decision *avd) @@ -995,11 +1013,11 @@ static noinline int avc_denied(u32 ssid, u32 tsid, if (flags & AVC_STRICT) return -EACCES; - if (enforcing_enabled() && + if (enforcing_enabled(state) && !(avd->flags & AVD_FLAGS_PERMISSIVE)) return -EACCES; - avc_update_node(AVC_CALLBACK_GRANT, requested, driver, + avc_update_node(state->avc, AVC_CALLBACK_GRANT, requested, driver, xperm, ssid, tsid, tclass, avd->seqno, NULL, flags); return 0; } @@ -1011,7 +1029,8 @@ static noinline int avc_denied(u32 ssid, u32 tsid, * as-is the case with ioctls, then multiple may be chained together and the * driver field is used to specify which set contains the permission. */ -int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, +int avc_has_extended_perms(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, u32 requested, u8 driver, u8 xperm, struct common_audit_data *ad) { struct avc_node *node; @@ -1032,9 +1051,9 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, rcu_read_lock(); - node = avc_lookup(ssid, tsid, tclass); + node = avc_lookup(state->avc, ssid, tsid, tclass); if (unlikely(!node)) { - avc_compute_av(ssid, tsid, tclass, &avd, xp_node); + avc_compute_av(state, ssid, tsid, tclass, &avd, xp_node); } else { memcpy(&avd, &node->ae.avd, sizeof(avd)); xp_node = node->ae.xp_node; @@ -1058,10 +1077,10 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, goto decision; } rcu_read_unlock(); - security_compute_xperms_decision(ssid, tsid, tclass, + security_compute_xperms_decision(state, ssid, tsid, tclass, driver, &local_xpd); rcu_read_lock(); - avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested, + avc_update_node(state->avc, AVC_CALLBACK_ADD_XPERMS, requested, driver, xperm, ssid, tsid, tclass, avd.seqno, &local_xpd, 0); } else { @@ -1075,12 +1094,12 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, decision: denied = requested & ~(avd.allowed); if (unlikely(denied)) - rc = avc_denied(ssid, tsid, tclass, requested, + rc = avc_denied(state, ssid, tsid, tclass, requested, driver, xperm, AVC_EXTENDED_PERMS, &avd); rcu_read_unlock(); - rc2 = avc_xperms_audit(ssid, tsid, tclass, requested, + rc2 = avc_xperms_audit(state, ssid, tsid, tclass, requested, &avd, xpd, xperm, rc, ad); if (rc2) return rc2; @@ -1089,6 +1108,7 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, /** * avc_perm_nonode - Add an entry to the AVC + * @state: SELinux state pointer * @ssid: subject * @tsid: object/target * @tclass: object class @@ -1100,23 +1120,25 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, * unlikely and needs extra stack space for the new node that we generate, so * don't inline it. */ -static noinline int avc_perm_nonode(u32 ssid, u32 tsid, u16 tclass, +static noinline int avc_perm_nonode(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, u32 requested, unsigned int flags, struct av_decision *avd) { u32 denied; struct avc_xperms_node xp_node; - avc_compute_av(ssid, tsid, tclass, avd, &xp_node); + avc_compute_av(state, ssid, tsid, tclass, avd, &xp_node); denied = requested & ~(avd->allowed); if (unlikely(denied)) - return avc_denied(ssid, tsid, tclass, requested, 0, 0, + return avc_denied(state, ssid, tsid, tclass, requested, 0, 0, flags, avd); return 0; } /** * avc_has_perm_noaudit - Check permissions but perform no auditing. + * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class @@ -1135,7 +1157,8 @@ static noinline int avc_perm_nonode(u32 ssid, u32 tsid, u16 tclass, * auditing, e.g. in cases where a lock must be held for the check but * should be released for the auditing. */ -inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, +inline int avc_has_perm_noaudit(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, u32 requested, unsigned int flags, struct av_decision *avd) @@ -1147,10 +1170,10 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, return -EACCES; rcu_read_lock(); - node = avc_lookup(ssid, tsid, tclass); + node = avc_lookup(state->avc, ssid, tsid, tclass); if (unlikely(!node)) { rcu_read_unlock(); - return avc_perm_nonode(ssid, tsid, tclass, requested, + return avc_perm_nonode(state, ssid, tsid, tclass, requested, flags, avd); } denied = requested & ~node->ae.avd.allowed; @@ -1158,13 +1181,14 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, rcu_read_unlock(); if (unlikely(denied)) - return avc_denied(ssid, tsid, tclass, requested, 0, 0, + return avc_denied(state, ssid, tsid, tclass, requested, 0, 0, flags, avd); return 0; } /** * avc_has_perm - Check permissions and perform any appropriate auditing. + * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class @@ -1179,23 +1203,23 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, * permissions are granted, -%EACCES if any permissions are denied, or * another -errno upon other errors. */ -int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, +int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, u32 requested, struct common_audit_data *auditdata) { struct av_decision avd; int rc, rc2; - rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, + rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0, &avd); - rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, + rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc, auditdata); if (rc2) return rc2; return rc; } -u32 avc_policy_seqno(void) +u32 avc_policy_seqno(struct selinux_state *state) { - return selinux_avc.avc_cache.latest_notif; + return state->avc->avc_cache.latest_notif; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 617f54abb640..ec8e746ec67e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -287,7 +287,7 @@ static int __inode_security_revalidate(struct inode *inode, * inode_doinit_with_dentry() will recheck with * isec->lock held. */ - if (selinux_initialized() && + if (selinux_initialized(&selinux_state) && data_race(isec->initialized != LABEL_INITIALIZED)) { if (!may_sleep) return -ECHILD; @@ -433,12 +433,14 @@ static int may_context_mount_sb_relabel(u32 sid, const struct task_security_struct *tsec = selinux_cred(cred); int rc; - rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, + rc = avc_has_perm(&selinux_state, + tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, + rc = avc_has_perm(&selinux_state, + tsec->sid, sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, NULL); return rc; } @@ -449,12 +451,14 @@ static int may_context_mount_inode_relabel(u32 sid, { const struct task_security_struct *tsec = selinux_cred(cred); int rc; - rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, + rc = avc_has_perm(&selinux_state, + tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, + rc = avc_has_perm(&selinux_state, + sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, NULL); return rc; } @@ -537,7 +541,7 @@ static int sb_check_xattr_support(struct super_block *sb) fallback: /* No xattr support - try to fallback to genfs if possible. */ - rc = security_genfs_sid(sb->s_type->name, "/", + rc = security_genfs_sid(&selinux_state, sb->s_type->name, "/", SECCLASS_DIR, &sid); if (rc) return -EOPNOTSUPP; @@ -648,7 +652,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, mutex_lock(&sbsec->lock); - if (!selinux_initialized()) { + if (!selinux_initialized(&selinux_state)) { if (!opts) { /* Defer initialization until selinux_complete_init, after the initial policy is loaded and the security @@ -747,7 +751,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, * Determine the labeling behavior to use for this * filesystem type. */ - rc = security_fs_use(sb); + rc = security_fs_use(&selinux_state, sb); if (rc) { pr_warn("%s: security_fs_use(%s) returned %d\n", __func__, sb->s_type->name, rc); @@ -772,7 +776,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, } if (sbsec->behavior == SECURITY_FS_USE_XATTR) { sbsec->behavior = SECURITY_FS_USE_MNTPOINT; - rc = security_transition_sid(current_sid(), + rc = security_transition_sid(&selinux_state, + current_sid(), current_sid(), SECCLASS_FILE, NULL, &sbsec->mntpoint_sid); @@ -930,7 +935,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, * if the parent was able to be mounted it clearly had no special lsm * mount options. thus we can safely deal with this superblock later */ - if (!selinux_initialized()) { + if (!selinux_initialized(&selinux_state)) { if (kern_flags & SECURITY_LSM_NATIVE_LABELS) { newsbsec->flags |= SE_SBNATIVE; *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS; @@ -957,7 +962,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, if (newsbsec->behavior == SECURITY_FS_USE_NATIVE && !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) { - rc = security_fs_use(newsb); + rc = security_fs_use(&selinux_state, newsb); if (rc) goto out; } @@ -1006,7 +1011,7 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts) if (!s) return -EINVAL; - if (!selinux_initialized()) { + if (!selinux_initialized(&selinux_state)) { pr_warn("SELinux: Unable to set superblock options before the security server is initialized\n"); return -EINVAL; } @@ -1043,7 +1048,7 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts) WARN_ON(1); return -EINVAL; } - rc = security_context_str_to_sid(s, dst_sid, GFP_KERNEL); + rc = security_context_str_to_sid(&selinux_state, s, dst_sid, GFP_KERNEL); if (rc) pr_warn("SELinux: security_context_str_to_sid (%s) failed with errno=%d\n", s, rc); @@ -1060,7 +1065,8 @@ static int show_sid(struct seq_file *m, u32 sid) u32 len; int rc; - rc = security_sid_to_context(sid, &context, &len); + rc = security_sid_to_context(&selinux_state, sid, + &context, &len); if (!rc) { bool has_comma = strchr(context, ','); @@ -1083,7 +1089,7 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) if (!(sbsec->flags & SE_SBINITIALIZED)) return 0; - if (!selinux_initialized()) + if (!selinux_initialized(&selinux_state)) return 0; if (sbsec->flags & FSCONTEXT_MNT) { @@ -1337,7 +1343,7 @@ static int selinux_genfs_get_sid(struct dentry *dentry, path++; } } - rc = security_genfs_sid(sb->s_type->name, + rc = security_genfs_sid(&selinux_state, sb->s_type->name, path, tclass, sid); if (rc == -ENOENT) { /* No match in policy, mark as unlabeled. */ @@ -1392,7 +1398,7 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry, return 0; } - rc = security_context_to_sid_default(context, rc, sid, + rc = security_context_to_sid_default(&selinux_state, context, rc, sid, def_sid, GFP_NOFS); if (rc) { char *dev = inode->i_sb->s_id; @@ -1502,7 +1508,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent sid = sbsec->sid; /* Try to obtain a transition SID. */ - rc = security_transition_sid(task_sid, sid, + rc = security_transition_sid(&selinux_state, task_sid, sid, sclass, NULL, &sid); if (rc) goto out; @@ -1647,9 +1653,11 @@ static int cred_has_capability(const struct cred *cred, return -EINVAL; } - rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); + rc = avc_has_perm_noaudit(&selinux_state, + sid, sid, sclass, av, 0, &avd); if (!(opts & CAP_OPT_NOAUDIT)) { - int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad); + int rc2 = avc_audit(&selinux_state, + sid, sid, sclass, av, &avd, rc, &ad); if (rc2) return rc2; } @@ -1673,7 +1681,8 @@ static int inode_has_perm(const struct cred *cred, sid = cred_sid(cred); isec = selinux_inode(inode); - return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); + return avc_has_perm(&selinux_state, + sid, isec->sid, isec->sclass, perms, adp); } /* Same as inode_has_perm, but pass explicit audit data containing @@ -1746,7 +1755,8 @@ static int file_has_perm(const struct cred *cred, ad.u.file = file; if (sid != fsec->sid) { - rc = avc_has_perm(sid, fsec->sid, + rc = avc_has_perm(&selinux_state, + sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); @@ -1789,7 +1799,7 @@ selinux_determine_inode_label(const struct task_security_struct *tsec, *_new_isid = tsec->create_sid; } else { const struct inode_security_struct *dsec = inode_security(dir); - return security_transition_sid(tsec->sid, + return security_transition_sid(&selinux_state, tsec->sid, dsec->sid, tclass, name, _new_isid); } @@ -1817,7 +1827,8 @@ static int may_create(struct inode *dir, ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = dentry; - rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, + rc = avc_has_perm(&selinux_state, + sid, dsec->sid, SECCLASS_DIR, DIR__ADD_NAME | DIR__SEARCH, &ad); if (rc) @@ -1828,11 +1839,13 @@ static int may_create(struct inode *dir, if (rc) return rc; - rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); + rc = avc_has_perm(&selinux_state, + sid, newsid, tclass, FILE__CREATE, &ad); if (rc) return rc; - return avc_has_perm(newsid, sbsec->sid, + return avc_has_perm(&selinux_state, + newsid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, &ad); } @@ -1861,7 +1874,8 @@ static int may_link(struct inode *dir, av = DIR__SEARCH; av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); - rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad); + rc = avc_has_perm(&selinux_state, + sid, dsec->sid, SECCLASS_DIR, av, &ad); if (rc) return rc; @@ -1881,7 +1895,8 @@ static int may_link(struct inode *dir, return 0; } - rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad); + rc = avc_has_perm(&selinux_state, + sid, isec->sid, isec->sclass, av, &ad); return rc; } @@ -1905,16 +1920,19 @@ static inline int may_rename(struct inode *old_dir, ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = old_dentry; - rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, + rc = avc_has_perm(&selinux_state, + sid, old_dsec->sid, SECCLASS_DIR, DIR__REMOVE_NAME | DIR__SEARCH, &ad); if (rc) return rc; - rc = avc_has_perm(sid, old_isec->sid, + rc = avc_has_perm(&selinux_state, + sid, old_isec->sid, old_isec->sclass, FILE__RENAME, &ad); if (rc) return rc; if (old_is_dir && new_dir != old_dir) { - rc = avc_has_perm(sid, old_isec->sid, + rc = avc_has_perm(&selinux_state, + sid, old_isec->sid, old_isec->sclass, DIR__REPARENT, &ad); if (rc) return rc; @@ -1924,13 +1942,15 @@ static inline int may_rename(struct inode *old_dir, av = DIR__ADD_NAME | DIR__SEARCH; if (d_is_positive(new_dentry)) av |= DIR__REMOVE_NAME; - rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad); + rc = avc_has_perm(&selinux_state, + sid, new_dsec->sid, SECCLASS_DIR, av, &ad); if (rc) return rc; if (d_is_positive(new_dentry)) { new_isec = backing_inode_security(new_dentry); new_is_dir = d_is_dir(new_dentry); - rc = avc_has_perm(sid, new_isec->sid, + rc = avc_has_perm(&selinux_state, + sid, new_isec->sid, new_isec->sclass, (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad); if (rc) @@ -1950,7 +1970,8 @@ static int superblock_has_perm(const struct cred *cred, u32 sid = cred_sid(cred); sbsec = selinux_superblock(sb); - return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); + return avc_has_perm(&selinux_state, + sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); } /* Convert a Linux mode and permission mask to an access vector. */ @@ -2024,7 +2045,8 @@ static inline u32 open_file_to_av(struct file *file) static int selinux_binder_set_context_mgr(const struct cred *mgr) { - return avc_has_perm(current_sid(), cred_sid(mgr), SECCLASS_BINDER, + return avc_has_perm(&selinux_state, + current_sid(), cred_sid(mgr), SECCLASS_BINDER, BINDER__SET_CONTEXT_MGR, NULL); } @@ -2037,20 +2059,22 @@ static int selinux_binder_transaction(const struct cred *from, int rc; if (mysid != fromsid) { - rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, + rc = avc_has_perm(&selinux_state, + mysid, fromsid, SECCLASS_BINDER, BINDER__IMPERSONATE, NULL); if (rc) return rc; } - return avc_has_perm(fromsid, tosid, + return avc_has_perm(&selinux_state, fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, NULL); } static int selinux_binder_transfer_binder(const struct cred *from, const struct cred *to) { - return avc_has_perm(cred_sid(from), cred_sid(to), + return avc_has_perm(&selinux_state, + cred_sid(from), cred_sid(to), SECCLASS_BINDER, BINDER__TRANSFER, NULL); } @@ -2070,7 +2094,8 @@ static int selinux_binder_transfer_file(const struct cred *from, ad.u.path = file->f_path; if (sid != fsec->sid) { - rc = avc_has_perm(sid, fsec->sid, + rc = avc_has_perm(&selinux_state, + sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); @@ -2088,7 +2113,8 @@ static int selinux_binder_transfer_file(const struct cred *from, return 0; isec = backing_inode_security(dentry); - return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), + return avc_has_perm(&selinux_state, + sid, isec->sid, isec->sclass, file_to_av(file), &ad); } @@ -2099,24 +2125,26 @@ static int selinux_ptrace_access_check(struct task_struct *child, u32 csid = task_sid_obj(child); if (mode & PTRACE_MODE_READ) - return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, - NULL); + return avc_has_perm(&selinux_state, + sid, csid, SECCLASS_FILE, FILE__READ, NULL); - return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, - NULL); + return avc_has_perm(&selinux_state, + sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); } static int selinux_ptrace_traceme(struct task_struct *parent) { - return avc_has_perm(task_sid_obj(parent), task_sid_obj(current), + return avc_has_perm(&selinux_state, + task_sid_obj(parent), task_sid_obj(current), SECCLASS_PROCESS, PROCESS__PTRACE, NULL); } static int selinux_capget(const struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - return avc_has_perm(current_sid(), task_sid_obj(target), - SECCLASS_PROCESS, PROCESS__GETCAP, NULL); + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(target), SECCLASS_PROCESS, + PROCESS__GETCAP, NULL); } static int selinux_capset(struct cred *new, const struct cred *old, @@ -2124,7 +2152,8 @@ static int selinux_capset(struct cred *new, const struct cred *old, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) { - return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + cred_sid(old), cred_sid(new), SECCLASS_PROCESS, PROCESS__SETCAP, NULL); } @@ -2191,18 +2220,21 @@ static int selinux_syslog(int type) switch (type) { case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ - return avc_has_perm(current_sid(), SECINITSID_KERNEL, + return avc_has_perm(&selinux_state, + current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL); case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ /* Set level of messages printed to console */ case SYSLOG_ACTION_CONSOLE_LEVEL: - return avc_has_perm(current_sid(), SECINITSID_KERNEL, + return avc_has_perm(&selinux_state, + current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, NULL); } /* All other syslog types */ - return avc_has_perm(current_sid(), SECINITSID_KERNEL, + return avc_has_perm(&selinux_state, + current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL); } @@ -2262,7 +2294,8 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm, av |= PROCESS2__NNP_TRANSITION; if (nosuid) av |= PROCESS2__NOSUID_TRANSITION; - rc = avc_has_perm(old_tsec->sid, new_tsec->sid, + rc = avc_has_perm(&selinux_state, + old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS2, av, NULL); if (!rc) return 0; @@ -2273,7 +2306,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm, * i.e. SIDs that are guaranteed to only be allowed a subset * of the permissions of the current SID. */ - rc = security_bounded_transition(old_tsec->sid, + rc = security_bounded_transition(&selinux_state, old_tsec->sid, new_tsec->sid); if (!rc) return 0; @@ -2319,7 +2352,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) * early boot end up with a label different from SECINITSID_KERNEL * (if the policy chooses to set SECINITSID_INIT != SECINITSID_KERNEL). */ - if (!selinux_initialized()) { + if (!selinux_initialized(&selinux_state)) { new_tsec->sid = SECINITSID_INIT; /* also clear the exec_sid just in case */ new_tsec->exec_sid = 0; @@ -2337,7 +2370,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) return rc; } else { /* Check for a default transition on this program. */ - rc = security_transition_sid(old_tsec->sid, + rc = security_transition_sid(&selinux_state, old_tsec->sid, isec->sid, SECCLASS_PROCESS, NULL, &new_tsec->sid); if (rc) @@ -2356,25 +2389,29 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) ad.u.file = bprm->file; if (new_tsec->sid == old_tsec->sid) { - rc = avc_has_perm(old_tsec->sid, isec->sid, + rc = avc_has_perm(&selinux_state, + old_tsec->sid, isec->sid, SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); if (rc) return rc; } else { /* Check permissions for the transition. */ - rc = avc_has_perm(old_tsec->sid, new_tsec->sid, + rc = avc_has_perm(&selinux_state, + old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); if (rc) return rc; - rc = avc_has_perm(new_tsec->sid, isec->sid, + rc = avc_has_perm(&selinux_state, + new_tsec->sid, isec->sid, SECCLASS_FILE, FILE__ENTRYPOINT, &ad); if (rc) return rc; /* Check for shared state */ if (bprm->unsafe & LSM_UNSAFE_SHARE) { - rc = avc_has_perm(old_tsec->sid, new_tsec->sid, + rc = avc_has_perm(&selinux_state, + old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__SHARE, NULL); if (rc) @@ -2386,7 +2423,8 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) if (bprm->unsafe & LSM_UNSAFE_PTRACE) { u32 ptsid = ptrace_parent_sid(); if (ptsid != 0) { - rc = avc_has_perm(ptsid, new_tsec->sid, + rc = avc_has_perm(&selinux_state, + ptsid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); if (rc) @@ -2400,7 +2438,8 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) /* Enable secure mode for SIDs transitions unless the noatsecure permission is granted between the two SIDs, i.e. ahp returns 0. */ - rc = avc_has_perm(old_tsec->sid, new_tsec->sid, + rc = avc_has_perm(&selinux_state, + old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__NOATSECURE, NULL); bprm->secureexec |= !!rc; @@ -2492,7 +2531,8 @@ static void selinux_bprm_committing_creds(const struct linux_binprm *bprm) * higher than the default soft limit for cases where the default is * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. */ - rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, + rc = avc_has_perm(&selinux_state, + new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__RLIMITINH, NULL); if (rc) { /* protect against do_prlimit() */ @@ -2531,7 +2571,8 @@ static void selinux_bprm_committed_creds(const struct linux_binprm *bprm) * This must occur _after_ the task SID has been updated so that any * kill done after the flush will be checked against the new SID. */ - rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); + rc = avc_has_perm(&selinux_state, + osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); if (rc) { clear_itimer(); @@ -2885,7 +2926,7 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode, if (xattr_name) *xattr_name = XATTR_NAME_SELINUX; - return security_sid_to_context(newsid, (char **)ctx, + return security_sid_to_context(&selinux_state, newsid, (char **)ctx, ctxlen); } @@ -2938,12 +2979,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, isec->initialized = LABEL_INITIALIZED; } - if (!selinux_initialized() || + if (!selinux_initialized(&selinux_state) || !(sbsec->flags & SBLABEL_MNT)) return -EOPNOTSUPP; if (xattr) { - rc = security_sid_to_context_force(newsid, + rc = security_sid_to_context_force(&selinux_state, newsid, &context, &clen); if (rc) return rc; @@ -2964,7 +3005,7 @@ static int selinux_inode_init_security_anon(struct inode *inode, struct inode_security_struct *isec; int rc; - if (unlikely(!selinux_initialized())) + if (unlikely(!selinux_initialized(&selinux_state))) return 0; isec = selinux_inode(inode); @@ -2988,7 +3029,7 @@ static int selinux_inode_init_security_anon(struct inode *inode, } else { isec->sclass = SECCLASS_ANON_INODE; rc = security_transition_sid( - sid, sid, + &selinux_state, sid, sid, isec->sclass, name, &isec->sid); if (rc) return rc; @@ -3003,7 +3044,8 @@ static int selinux_inode_init_security_anon(struct inode *inode, ad.type = LSM_AUDIT_DATA_ANONINODE; ad.u.anonclass = name ? (const char *)name->name : "?"; - return avc_has_perm(sid, + return avc_has_perm(&selinux_state, + sid, isec->sid, isec->sclass, FILE__CREATE, @@ -3071,7 +3113,8 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode, if (IS_ERR(isec)) return PTR_ERR(isec); - return avc_has_perm(sid, isec->sid, isec->sclass, FILE__READ, &ad); + return avc_has_perm(&selinux_state, + sid, isec->sid, isec->sclass, FILE__READ, &ad); } static noinline int audit_inode_permission(struct inode *inode, @@ -3084,7 +3127,8 @@ static noinline int audit_inode_permission(struct inode *inode, ad.type = LSM_AUDIT_DATA_INODE; ad.u.inode = inode; - return slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms, + return slow_avc_audit(&selinux_state, + current_sid(), isec->sid, isec->sclass, perms, audited, denied, result, &ad); } @@ -3115,7 +3159,8 @@ static int selinux_inode_permission(struct inode *inode, int mask) if (IS_ERR(isec)) return PTR_ERR(isec); - rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, + rc = avc_has_perm_noaudit(&selinux_state, + sid, isec->sid, isec->sclass, perms, 0, &avd); audited = avc_audit_required(perms, &avd, rc, from_access ? FILE__AUDIT_ACCESS : 0, @@ -3207,7 +3252,7 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, if (strcmp(name, XATTR_NAME_SELINUX)) return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); - if (!selinux_initialized()) + if (!selinux_initialized(&selinux_state)) return (inode_owner_or_capable(idmap, inode) ? 0 : -EPERM); sbsec = selinux_superblock(inode->i_sb); @@ -3221,12 +3266,13 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, ad.u.dentry = dentry; isec = backing_inode_security(dentry); - rc = avc_has_perm(sid, isec->sid, isec->sclass, + rc = avc_has_perm(&selinux_state, + sid, isec->sid, isec->sclass, FILE__RELABELFROM, &ad); if (rc) return rc; - rc = security_context_to_sid(value, size, &newsid, + rc = security_context_to_sid(&selinux_state, value, size, &newsid, GFP_KERNEL); if (rc == -EINVAL) { if (!has_cap_mac_admin(true)) { @@ -3255,23 +3301,25 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, return rc; } - rc = security_context_to_sid_force(value, + rc = security_context_to_sid_force(&selinux_state, value, size, &newsid); } if (rc) return rc; - rc = avc_has_perm(sid, newsid, isec->sclass, + rc = avc_has_perm(&selinux_state, + sid, newsid, isec->sclass, FILE__RELABELTO, &ad); if (rc) return rc; - rc = security_validate_transition(isec->sid, newsid, + rc = security_validate_transition(&selinux_state, isec->sid, newsid, sid, isec->sclass); if (rc) return rc; - return avc_has_perm(newsid, + return avc_has_perm(&selinux_state, + newsid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, @@ -3311,7 +3359,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, return; } - if (!selinux_initialized()) { + if (!selinux_initialized(&selinux_state)) { /* If we haven't even been initialized, then we can't validate * against a policy, so leave the label as invalid. It may * resolve to a valid label on the next revalidation try if @@ -3320,7 +3368,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, return; } - rc = security_context_to_sid_force(value, size, + rc = security_context_to_sid_force(&selinux_state, value, size, &newsid); if (rc) { pr_err("SELinux: unable to map context to SID" @@ -3358,7 +3406,7 @@ static int selinux_inode_removexattr(struct mnt_idmap *idmap, if (strcmp(name, XATTR_NAME_SELINUX)) return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); - if (!selinux_initialized()) + if (!selinux_initialized(&selinux_state)) return 0; /* No one is allowed to remove a SELinux security label. @@ -3428,7 +3476,7 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap, * If we're not initialized yet, then we can't validate contexts, so * just let vfs_getxattr fall back to using the on-disk xattr. */ - if (!selinux_initialized() || + if (!selinux_initialized(&selinux_state) || strcmp(name, XATTR_SELINUX_SUFFIX)) return -EOPNOTSUPP; @@ -3443,10 +3491,11 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap, */ isec = inode_security(inode); if (has_cap_mac_admin(false)) - error = security_sid_to_context_force(isec->sid, &context, + error = security_sid_to_context_force(&selinux_state, + isec->sid, &context, &size); else - error = security_sid_to_context(isec->sid, + error = security_sid_to_context(&selinux_state, isec->sid, &context, &size); if (error) return error; @@ -3478,7 +3527,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, if (!value || !size) return -EACCES; - rc = security_context_to_sid(value, size, &newsid, + rc = security_context_to_sid(&selinux_state, value, size, &newsid, GFP_KERNEL); if (rc) return rc; @@ -3495,7 +3544,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t { const int len = sizeof(XATTR_NAME_SELINUX); - if (!selinux_initialized()) + if (!selinux_initialized(&selinux_state)) return 0; if (buffer && len <= buffer_size) @@ -3537,8 +3586,10 @@ static int selinux_inode_copy_up_xattr(struct dentry *dentry, const char *name) * xattrs up. Instead, filter out SELinux-related xattrs following * policy load. */ - if (selinux_initialized() && !strcmp(name, XATTR_NAME_SELINUX)) + if (selinux_initialized(&selinux_state) && + !strcmp(name, XATTR_NAME_SELINUX)) return -ECANCELED; /* Discard */ + /* * Any other attribute apart from SELINUX is not claimed, supported * by selinux. @@ -3573,7 +3624,7 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, return rc; } - rc = security_context_to_sid(context, clen, &parent_sid, + rc = security_context_to_sid(&selinux_state, context, clen, &parent_sid, GFP_KERNEL); kfree(context); if (rc) @@ -3588,14 +3639,14 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, q.name = kn->name; q.hash_len = hashlen_string(kn_dir, kn->name); - rc = security_transition_sid(tsec->sid, + rc = security_transition_sid(&selinux_state, tsec->sid, parent_sid, secclass, &q, &newsid); if (rc) return rc; } - rc = security_sid_to_context_force(newsid, + rc = security_sid_to_context_force(&selinux_state, newsid, &context, &clen); if (rc) return rc; @@ -3635,7 +3686,7 @@ static int selinux_file_permission(struct file *file, int mask) isec = inode_security(inode); if (sid == fsec->sid && fsec->isid == isec->sid && - fsec->pseqno == avc_policy_seqno()) + fsec->pseqno == avc_policy_seqno(&selinux_state)) /* No change since file_open check. */ return 0; @@ -3676,7 +3727,8 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, ad.u.op->path = file->f_path; if (ssid != fsec->sid) { - rc = avc_has_perm(ssid, fsec->sid, + rc = avc_has_perm(&selinux_state, + ssid, fsec->sid, SECCLASS_FD, FD__USE, &ad); @@ -3688,7 +3740,8 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, return 0; isec = inode_security(inode); - rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, + rc = avc_has_extended_perms(&selinux_state, + ssid, isec->sid, isec->sclass, requested, driver, xperm, &ad); out: return rc; @@ -3784,7 +3837,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared * private file mapping that will also be writable. * This has an additional check. */ - rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, + rc = avc_has_perm(&selinux_state, + sid, sid, SECCLASS_PROCESS, PROCESS__EXECMEM, NULL); if (rc) goto error; @@ -3814,7 +3868,8 @@ static int selinux_mmap_addr(unsigned long addr) if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { u32 sid = current_sid(); - rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, + rc = avc_has_perm(&selinux_state, + sid, sid, SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, NULL); } @@ -3862,11 +3917,13 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, */ if (vma->vm_start >= vma->vm_mm->start_brk && vma->vm_end <= vma->vm_mm->brk) { - rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, + rc = avc_has_perm(&selinux_state, + sid, sid, SECCLASS_PROCESS, PROCESS__EXECHEAP, NULL); } else if (!vma->vm_file && (vma_is_initial_stack(vma) || vma_is_stack_for_current(vma))) { - rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, + rc = avc_has_perm(&selinux_state, + sid, sid, SECCLASS_PROCESS, PROCESS__EXECSTACK, NULL); } else if (vma->vm_file && vma->anon_vma) { /* @@ -3958,7 +4015,8 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, else perm = signal_to_av(signum); - return avc_has_perm(fsec->fown_sid, sid, + return avc_has_perm(&selinux_state, + fsec->fown_sid, sid, SECCLASS_PROCESS, perm, NULL); } @@ -3984,7 +4042,7 @@ static int selinux_file_open(struct file *file) * struct as its SID. */ fsec->isid = isec->sid; - fsec->pseqno = avc_policy_seqno(); + fsec->pseqno = avc_policy_seqno(&selinux_state); /* * Since the inode label or policy seqno may have changed * between the selinux_inode_permission check and the saving @@ -4003,7 +4061,8 @@ static int selinux_task_alloc(struct task_struct *task, { u32 sid = current_sid(); - return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); + return avc_has_perm(&selinux_state, + sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); } /* @@ -4050,7 +4109,8 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid) u32 sid = current_sid(); int ret; - ret = avc_has_perm(sid, secid, + ret = avc_has_perm(&selinux_state, + sid, secid, SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__USE_AS_OVERRIDE, NULL); @@ -4074,7 +4134,8 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) u32 sid = current_sid(); int ret; - ret = avc_has_perm(sid, isec->sid, + ret = avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__CREATE_FILES_AS, NULL); @@ -4091,7 +4152,8 @@ static int selinux_kernel_module_request(char *kmod_name) ad.type = LSM_AUDIT_DATA_KMOD; ad.u.kmod_name = kmod_name; - return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, + return avc_has_perm(&selinux_state, + current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, &ad); } @@ -4105,7 +4167,8 @@ static int selinux_kernel_module_from_file(struct file *file) /* init_module */ if (file == NULL) - return avc_has_perm(sid, sid, SECCLASS_SYSTEM, + return avc_has_perm(&selinux_state, + sid, sid, SECCLASS_SYSTEM, SYSTEM__MODULE_LOAD, NULL); /* finit_module */ @@ -4115,13 +4178,15 @@ static int selinux_kernel_module_from_file(struct file *file) fsec = selinux_file(file); if (sid != fsec->sid) { - rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); + rc = avc_has_perm(&selinux_state, + sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); if (rc) return rc; } isec = inode_security(file_inode(file)); - return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_SYSTEM, SYSTEM__MODULE_LOAD, &ad); } @@ -4159,19 +4224,22 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents) static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETPGID, NULL); } static int selinux_task_getpgid(struct task_struct *p) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__GETPGID, NULL); } static int selinux_task_getsid(struct task_struct *p) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__GETSESSION, NULL); } @@ -4188,19 +4256,22 @@ static void selinux_task_getlsmprop_obj(struct task_struct *p, static int selinux_task_setnice(struct task_struct *p, int nice) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); } static int selinux_task_setioprio(struct task_struct *p, int ioprio) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); } static int selinux_task_getioprio(struct task_struct *p) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__GETSCHED, NULL); } @@ -4215,7 +4286,8 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre av |= PROCESS__SETRLIMIT; if (flags & LSM_PRLIMIT_READ) av |= PROCESS__GETRLIMIT; - return avc_has_perm(cred_sid(cred), cred_sid(tcred), + return avc_has_perm(&selinux_state, + cred_sid(cred), cred_sid(tcred), SECCLASS_PROCESS, av, NULL); } @@ -4229,7 +4301,8 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, later be used as a safe reset point for the soft limit upon context transitions. See selinux_bprm_committing_creds. */ if (old_rlim->rlim_max != new_rlim->rlim_max) - return avc_has_perm(current_sid(), task_sid_obj(p), + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); return 0; @@ -4237,19 +4310,22 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, static int selinux_task_setscheduler(struct task_struct *p) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); } static int selinux_task_getscheduler(struct task_struct *p) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__GETSCHED, NULL); } static int selinux_task_movememory(struct task_struct *p) { - return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS, + return avc_has_perm(&selinux_state, + current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); } @@ -4267,7 +4343,8 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info, secid = current_sid(); else secid = cred_sid(cred); - return avc_has_perm(secid, task_sid_obj(p), SECCLASS_PROCESS, perm, NULL); + return avc_has_perm(&selinux_state, + secid, task_sid_obj(p), SECCLASS_PROCESS, perm, NULL); } static void selinux_task_to_inode(struct task_struct *p, @@ -4287,8 +4364,8 @@ static int selinux_userns_create(const struct cred *cred) { u32 sid = current_sid(); - return avc_has_perm(sid, sid, SECCLASS_USER_NAMESPACE, - USER_NAMESPACE__CREATE, NULL); + return avc_has_perm(&selinux_state, sid, sid, SECCLASS_USER_NAMESPACE, + USER_NAMESPACE__CREATE, NULL); } /* Returns error only if unable to parse addresses */ @@ -4546,7 +4623,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) if (unlikely(err)) return -EACCES; - err = security_net_peersid_resolve(nlbl_sid, + err = security_net_peersid_resolve(&selinux_state, nlbl_sid, nlbl_type, xfrm_sid, sid); if (unlikely(err)) { pr_warn( @@ -4575,7 +4652,7 @@ static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid) int err = 0; if (skb_sid != SECSID_NULL) - err = security_sid_mls_copy(sk_sid, skb_sid, + err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid, conn_sid); else *conn_sid = sk_sid; @@ -4593,7 +4670,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, return 0; } - return security_transition_sid(tsec->sid, tsec->sid, + return security_transition_sid(&selinux_state, tsec->sid, tsec->sid, secclass, NULL, socksid); } @@ -4631,7 +4708,8 @@ static int sock_has_perm(struct sock *sk, u32 perms) ad_net_init_from_sk(&ad, &net, sk); - return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms, + return avc_has_perm(&selinux_state, + current_sid(), sksec->sid, sksec->sclass, perms, &ad); } @@ -4651,7 +4729,8 @@ static int selinux_socket_create(int family, int type, if (rc) return rc; - return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); + return avc_has_perm(&selinux_state, + tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); } static int selinux_socket_post_create(struct socket *sock, int family, @@ -4787,7 +4866,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in snum, &sid); if (err) goto out; - err = avc_has_perm(sksec->sid, sid, + err = avc_has_perm(&selinux_state, + sksec->sid, sid, sksec->sclass, SOCKET__NAME_BIND, &ad); if (err) @@ -4826,7 +4906,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in else ad.u.net->v6info.saddr = addr6->sin6_addr; - err = avc_has_perm(sksec->sid, sid, + err = avc_has_perm(&selinux_state, + sksec->sid, sid, sksec->sclass, node_perm, &ad); if (err) goto out; @@ -4924,7 +5005,8 @@ static int selinux_socket_connect_helper(struct socket *sock, ad.u.net = &net; ad.u.net->dport = htons(snum); ad.u.net->family = address->sa_family; - err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); + err = avc_has_perm(&selinux_state, + sksec->sid, sid, sksec->sclass, perm, &ad); if (err) return err; } @@ -5034,7 +5116,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, ad_net_init_from_sk(&ad, &net, other); - err = avc_has_perm(sksec_sock->sid, sksec_other->sid, + err = avc_has_perm(&selinux_state, + sksec_sock->sid, sksec_other->sid, sksec_other->sclass, UNIX_STREAM_SOCKET__CONNECTTO, &ad); if (err) @@ -5042,7 +5125,7 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, /* server child socket */ sksec_new->peer_sid = sksec_sock->sid; - err = security_sid_mls_copy(sksec_other->sid, + err = security_sid_mls_copy(&selinux_state, sksec_other->sid, sksec_sock->sid, &sksec_new->sid); if (err) return err; @@ -5063,7 +5146,8 @@ static int selinux_socket_unix_may_send(struct socket *sock, ad_net_init_from_sk(&ad, &net, other->sk); - return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, + return avc_has_perm(&selinux_state, + ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, &ad); } @@ -5078,7 +5162,8 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, err = sel_netif_sid(ns, ifindex, &if_sid); if (err) return err; - err = avc_has_perm(peer_sid, if_sid, + err = avc_has_perm(&selinux_state, + peer_sid, if_sid, SECCLASS_NETIF, NETIF__INGRESS, ad); if (err) return err; @@ -5086,7 +5171,8 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, err = sel_netnode_sid(addrp, family, &node_sid); if (err) return err; - return avc_has_perm(peer_sid, node_sid, + return avc_has_perm(&selinux_state, + peer_sid, node_sid, SECCLASS_NODE, NODE__RECVFROM, ad); } @@ -5106,7 +5192,8 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, return err; if (selinux_secmark_enabled()) { - err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, + err = avc_has_perm(&selinux_state, + sk_sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) return err; @@ -5166,7 +5253,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) selinux_netlbl_err(skb, family, err, 0); return err; } - err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, + err = avc_has_perm(&selinux_state, + sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); if (err) { selinux_netlbl_err(skb, family, err, 0); @@ -5175,7 +5263,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) } if (secmark_active) { - err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, + err = avc_has_perm(&selinux_state, + sk_sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) return err; @@ -5201,7 +5290,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, if (peer_sid == SECSID_NULL) return -ENOPROTOOPT; - err = security_sid_to_context(peer_sid, &scontext, + err = security_sid_to_context(&selinux_state, peer_sid, &scontext, &scontext_len); if (err) return err; @@ -5351,7 +5440,8 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, * consistency among the peer SIDs. */ ad_net_init_from_sk(&ad, &net, asoc->base.sk); - err = avc_has_perm(sksec->peer_sid, asoc->peer_secid, + err = avc_has_perm(&selinux_state, + sksec->peer_sid, asoc->peer_secid, sksec->sclass, SCTP_SOCKET__ASSOCIATION, &ad); if (err) @@ -5581,8 +5671,9 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) static int selinux_secmark_relabel_packet(u32 sid) { - return avc_has_perm(current_sid(), sid, SECCLASS_PACKET, PACKET__RELABELTO, - NULL); + return avc_has_perm(&selinux_state, + current_sid(), sid, SECCLASS_PACKET, + PACKET__RELABELTO, NULL); } static void selinux_secmark_refcount_inc(void) @@ -5620,7 +5711,8 @@ static int selinux_tun_dev_create(void) * connections unlike traditional sockets - check the TUN driver to * get a better understanding of why this socket is special */ - return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, + return avc_has_perm(&selinux_state, + sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, NULL); } @@ -5628,7 +5720,8 @@ static int selinux_tun_dev_attach_queue(void *security) { struct tun_security_struct *tunsec = selinux_tun_dev(security); - return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET, + return avc_has_perm(&selinux_state, + current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__ATTACH_QUEUE, NULL); } @@ -5656,11 +5749,13 @@ static int selinux_tun_dev_open(void *security) u32 sid = current_sid(); int err; - err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET, + err = avc_has_perm(&selinux_state, + sid, tunsec->sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__RELABELFROM, NULL); if (err) return err; - err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, + err = avc_has_perm(&selinux_state, + sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__RELABELTO, NULL); if (err) return err; @@ -5711,7 +5806,8 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, } if (secmark_active) - if (avc_has_perm(peer_sid, skb->secmark, + if (avc_has_perm(&selinux_state, + peer_sid, skb->secmark, SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) return NF_DROP; @@ -5788,7 +5884,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, return NF_DROP; if (selinux_secmark_enabled()) - if (avc_has_perm(sksec->sid, skb->secmark, + if (avc_has_perm(&selinux_state, + sksec->sid, skb->secmark, SECCLASS_PACKET, PACKET__SEND, &ad)) return NF_DROP_ERR(-ECONNREFUSED); @@ -5910,7 +6007,8 @@ static unsigned int selinux_ip_postroute(void *priv, return NF_DROP; if (secmark_active) - if (avc_has_perm(peer_sid, skb->secmark, + if (avc_has_perm(&selinux_state, + peer_sid, skb->secmark, SECCLASS_PACKET, secmark_perm, &ad)) return NF_DROP_ERR(-ECONNREFUSED); @@ -5920,13 +6018,15 @@ static unsigned int selinux_ip_postroute(void *priv, if (sel_netif_sid(state->net, ifindex, &if_sid)) return NF_DROP; - if (avc_has_perm(peer_sid, if_sid, + if (avc_has_perm(&selinux_state, + peer_sid, if_sid, SECCLASS_NETIF, NETIF__EGRESS, &ad)) return NF_DROP_ERR(-ECONNREFUSED); if (sel_netnode_sid(addrp, family, &node_sid)) return NF_DROP; - if (avc_has_perm(peer_sid, node_sid, + if (avc_has_perm(&selinux_state, + peer_sid, node_sid, SECCLASS_NODE, NODE__SENDTO, &ad)) return NF_DROP_ERR(-ECONNREFUSED); } @@ -5951,8 +6051,9 @@ static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_t driver = nlmsg_type >> 8; xperm = nlmsg_type & 0xff; - return avc_has_extended_perms(current_sid(), sksec->sid, sksec->sclass, - perms, driver, xperm, &ad); + return avc_has_extended_perms(&selinux_state, current_sid(), + sksec->sid, sksec->sclass, perms, + driver, xperm, &ad); } static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) @@ -5996,8 +6097,8 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) sk->sk_protocol, nlh->nlmsg_type, secclass_map[sclass - 1].name, task_pid_nr(current), current->comm); - if (enforcing_enabled() && - !security_get_allow_unknown()) + if (enforcing_enabled(&selinux_state) && + !security_get_allow_unknown(&selinux_state)) return rc; rc = 0; } else if (rc == -ENOENT) { @@ -6036,7 +6137,8 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = ipc_perms->key; - return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); + return avc_has_perm(&selinux_state, + sid, isec->sid, isec->sclass, perms, &ad); } static int selinux_msg_msg_alloc_security(struct msg_msg *msg) @@ -6062,7 +6164,8 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_MSGQ, MSGQ__CREATE, &ad); } @@ -6077,7 +6180,8 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_MSGQ, MSGQ__ASSOCIATE, &ad); } @@ -6089,7 +6193,8 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) case IPC_INFO: case MSG_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(current_sid(), SECINITSID_KERNEL, + return avc_has_perm(&selinux_state, + current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); case IPC_STAT: case MSG_STAT: @@ -6128,7 +6233,7 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m * Compute new sid based on current process and * message queue this message will be stored in */ - rc = security_transition_sid(sid, isec->sid, + rc = security_transition_sid(&selinux_state, sid, isec->sid, SECCLASS_MSG, NULL, &msec->sid); if (rc) return rc; @@ -6138,15 +6243,18 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m ad.u.ipc_id = msq->key; /* Can this process write to the queue? */ - rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, + rc = avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_MSGQ, MSGQ__WRITE, &ad); if (!rc) /* Can this process send the message */ - rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG, + rc = avc_has_perm(&selinux_state, + sid, msec->sid, SECCLASS_MSG, MSG__SEND, &ad); if (!rc) /* Can the message be put in the queue? */ - rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ, + rc = avc_has_perm(&selinux_state, + msec->sid, isec->sid, SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad); return rc; @@ -6168,10 +6276,12 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - rc = avc_has_perm(sid, isec->sid, + rc = avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_MSGQ, MSGQ__READ, &ad); if (!rc) - rc = avc_has_perm(sid, msec->sid, + rc = avc_has_perm(&selinux_state, + sid, msec->sid, SECCLASS_MSG, MSG__RECEIVE, &ad); return rc; } @@ -6189,7 +6299,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - return avc_has_perm(sid, isec->sid, SECCLASS_SHM, + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_SHM, SHM__CREATE, &ad); } @@ -6204,7 +6315,8 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - return avc_has_perm(sid, isec->sid, SECCLASS_SHM, + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_SHM, SHM__ASSOCIATE, &ad); } @@ -6217,7 +6329,8 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd) case IPC_INFO: case SHM_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(current_sid(), SECINITSID_KERNEL, + return avc_has_perm(&selinux_state, + current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); case IPC_STAT: case SHM_STAT: @@ -6267,7 +6380,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - return avc_has_perm(sid, isec->sid, SECCLASS_SEM, + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_SEM, SEM__CREATE, &ad); } @@ -6282,7 +6396,8 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - return avc_has_perm(sid, isec->sid, SECCLASS_SEM, + return avc_has_perm(&selinux_state, + sid, isec->sid, SECCLASS_SEM, SEM__ASSOCIATE, &ad); } @@ -6296,7 +6411,8 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd) case IPC_INFO: case SEM_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(current_sid(), SECINITSID_KERNEL, + return avc_has_perm(&selinux_state, + current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); case GETPID: case GETNCNT: @@ -6383,7 +6499,8 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, rcu_read_lock(); tsec = selinux_cred(__task_cred(p)); if (p != current) { - error = avc_has_perm(current_sid(), tsec->sid, + error = avc_has_perm(&selinux_state, + current_sid(), tsec->sid, SECCLASS_PROCESS, PROCESS__GETATTR, NULL); if (error) goto err_unlock; @@ -6418,7 +6535,7 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, return 0; } - error = security_sid_to_context(sid, value, &len); + error = security_sid_to_context(&selinux_state, sid, value, &len); if (error) return error; return len; @@ -6441,23 +6558,28 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) */ switch (attr) { case LSM_ATTR_EXEC: - error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, + error = avc_has_perm(&selinux_state, + mysid, mysid, SECCLASS_PROCESS, PROCESS__SETEXEC, NULL); break; case LSM_ATTR_FSCREATE: - error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, + error = avc_has_perm(&selinux_state, + mysid, mysid, SECCLASS_PROCESS, PROCESS__SETFSCREATE, NULL); break; case LSM_ATTR_KEYCREATE: - error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, + error = avc_has_perm(&selinux_state, + mysid, mysid, SECCLASS_PROCESS, PROCESS__SETKEYCREATE, NULL); break; case LSM_ATTR_SOCKCREATE: - error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, + error = avc_has_perm(&selinux_state, + mysid, mysid, SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, NULL); break; case LSM_ATTR_CURRENT: - error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, + error = avc_has_perm(&selinux_state, + mysid, mysid, SECCLASS_PROCESS, PROCESS__SETCURRENT, NULL); break; default: @@ -6473,7 +6595,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) str[size-1] = 0; size--; } - error = security_context_to_sid(value, size, + error = security_context_to_sid(&selinux_state, value, size, &sid, GFP_KERNEL); if (error == -EINVAL && attr == LSM_ATTR_FSCREATE) { if (!has_cap_mac_admin(true)) { @@ -6499,8 +6621,9 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) return error; } - error = security_context_to_sid_force(value, size, - &sid); + error = security_context_to_sid_force( + &selinux_state, + value, size, &sid); } if (error) return error; @@ -6523,7 +6646,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) tsec->create_sid = sid; } else if (attr == LSM_ATTR_KEYCREATE) { if (sid) { - error = avc_has_perm(mysid, sid, + error = avc_has_perm(&selinux_state, mysid, sid, SECCLASS_KEY, KEY__CREATE, NULL); if (error) goto abort_change; @@ -6537,13 +6660,15 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) goto abort_change; if (!current_is_single_threaded()) { - error = security_bounded_transition(tsec->sid, sid); + error = security_bounded_transition(&selinux_state, + tsec->sid, sid); if (error) goto abort_change; } /* Check permissions for the transition. */ - error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, + error = avc_has_perm(&selinux_state, + tsec->sid, sid, SECCLASS_PROCESS, PROCESS__DYNTRANSITION, NULL); if (error) goto abort_change; @@ -6552,7 +6677,8 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) Otherwise, leave SID unchanged and fail. */ ptsid = ptrace_parent_sid(); if (ptsid != 0) { - error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, + error = avc_has_perm(&selinux_state, + ptsid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); if (error) goto abort_change; @@ -6642,7 +6768,8 @@ static int selinux_ismaclabel(const char *name) static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { - return security_sid_to_context(secid, secdata, seclen); + return security_sid_to_context(&selinux_state, secid, + secdata, seclen); } static int selinux_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, @@ -6653,7 +6780,7 @@ static int selinux_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) { - return security_context_to_sid(secdata, seclen, + return security_context_to_sid(&selinux_state, secdata, seclen, secid, GFP_KERNEL); } @@ -6760,7 +6887,8 @@ static int selinux_key_permission(key_ref_t key_ref, key = key_ref_to_ptr(key_ref); ksec = selinux_key(key); - return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL); + return avc_has_perm(&selinux_state, + sid, ksec->sid, SECCLASS_KEY, perm, NULL); } static int selinux_key_getsecurity(struct key *key, char **_buffer) @@ -6770,7 +6898,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) unsigned len; int rc; - rc = security_sid_to_context(ksec->sid, + rc = security_sid_to_context(&selinux_state, ksec->sid, &context, &len); if (!rc) rc = len; @@ -6784,7 +6912,8 @@ static int selinux_watch_key(struct key *key) struct key_security_struct *ksec = selinux_key(key); u32 sid = current_sid(); - return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL); + return avc_has_perm(&selinux_state, + sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL); } #endif #endif @@ -6806,7 +6935,8 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val) ibpkey.subnet_prefix = subnet_prefix; ibpkey.pkey = pkey_val; ad.u.ibpkey = &ibpkey; - return avc_has_perm(sec->sid, sid, + return avc_has_perm(&selinux_state, + sec->sid, sid, SECCLASS_INFINIBAND_PKEY, INFINIBAND_PKEY__ACCESS, &ad); } @@ -6820,7 +6950,7 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, struct ib_security_struct *sec = ib_sec; struct lsm_ibendport_audit ibendport; - err = security_ib_endport_sid(dev_name, port_num, + err = security_ib_endport_sid(&selinux_state, dev_name, port_num, &sid); if (err) @@ -6830,7 +6960,8 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, ibendport.dev_name = dev_name; ibendport.port = port_num; ad.u.ibendport = &ibendport; - return avc_has_perm(sec->sid, sid, + return avc_has_perm(&selinux_state, + sec->sid, sid, SECCLASS_INFINIBAND_ENDPORT, INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad); } @@ -6853,11 +6984,13 @@ static int selinux_bpf(int cmd, union bpf_attr *attr, switch (cmd) { case BPF_MAP_CREATE: - ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, + ret = avc_has_perm(&selinux_state, + sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, NULL); break; case BPF_PROG_LOAD: - ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, + ret = avc_has_perm(&selinux_state, + sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, NULL); break; default: @@ -6897,14 +7030,16 @@ static int bpf_fd_pass(const struct file *file, u32 sid) if (file->f_op == &bpf_map_fops) { map = file->private_data; bpfsec = map->security; - ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, + ret = avc_has_perm(&selinux_state, + sid, bpfsec->sid, SECCLASS_BPF, bpf_map_fmode_to_av(file->f_mode), NULL); if (ret) return ret; } else if (file->f_op == &bpf_prog_fops) { prog = file->private_data; bpfsec = prog->aux->security; - ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, + ret = avc_has_perm(&selinux_state, + sid, bpfsec->sid, SECCLASS_BPF, BPF__PROG_RUN, NULL); if (ret) return ret; @@ -6918,7 +7053,8 @@ static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) struct bpf_security_struct *bpfsec; bpfsec = map->security; - return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, + return avc_has_perm(&selinux_state, + sid, bpfsec->sid, SECCLASS_BPF, bpf_map_fmode_to_av(fmode), NULL); } @@ -6928,7 +7064,8 @@ static int selinux_bpf_prog(struct bpf_prog *prog) struct bpf_security_struct *bpfsec; bpfsec = prog->aux->security; - return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, + return avc_has_perm(&selinux_state, + sid, bpfsec->sid, SECCLASS_BPF, BPF__PROG_RUN, NULL); } @@ -7035,7 +7172,7 @@ static int selinux_perf_event_open(struct perf_event_attr *attr, int type) else return -EINVAL; - return avc_has_perm(sid, sid, SECCLASS_PERF_EVENT, + return avc_has_perm(&selinux_state, sid, sid, SECCLASS_PERF_EVENT, requested, NULL); } @@ -7054,7 +7191,7 @@ static int selinux_perf_event_read(struct perf_event *event) struct perf_event_security_struct *perfsec = event->security; u32 sid = current_sid(); - return avc_has_perm(sid, perfsec->sid, + return avc_has_perm(&selinux_state, sid, perfsec->sid, SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL); } @@ -7063,7 +7200,7 @@ static int selinux_perf_event_write(struct perf_event *event) struct perf_event_security_struct *perfsec = event->security; u32 sid = current_sid(); - return avc_has_perm(sid, perfsec->sid, + return avc_has_perm(&selinux_state, sid, perfsec->sid, SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL); } #endif @@ -7078,7 +7215,7 @@ static int selinux_perf_event_write(struct perf_event *event) */ static int selinux_uring_override_creds(const struct cred *new) { - return avc_has_perm(current_sid(), cred_sid(new), + return avc_has_perm(&selinux_state, current_sid(), cred_sid(new), SECCLASS_IO_URING, IO_URING__OVERRIDE_CREDS, NULL); } @@ -7092,7 +7229,7 @@ static int selinux_uring_sqpoll(void) { u32 sid = current_sid(); - return avc_has_perm(sid, sid, + return avc_has_perm(&selinux_state, sid, sid, SECCLASS_IO_URING, IO_URING__SQPOLL, NULL); } @@ -7114,7 +7251,7 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd) ad.type = LSM_AUDIT_DATA_FILE; ad.u.file = file; - return avc_has_perm(current_sid(), isec->sid, + return avc_has_perm(&selinux_state, current_sid(), isec->sid, SECCLASS_IO_URING, IO_URING__CMD, &ad); } #endif /* CONFIG_IO_URING */ @@ -7428,8 +7565,8 @@ static __init int selinux_init(void) pr_info("SELinux: Initializing.\n"); memset(&selinux_state, 0, sizeof(selinux_state)); - enforcing_set(selinux_enforcing_boot); - selinux_avc_init(); + enforcing_set(&selinux_state, selinux_enforcing_boot); + selinux_avc_init(&selinux_state.avc); mutex_init(&selinux_state.status_lock); mutex_init(&selinux_state.policy_mutex); diff --git a/security/selinux/ibpkey.c b/security/selinux/ibpkey.c index 48f537b41c58..5839ca7bb9c7 100644 --- a/security/selinux/ibpkey.c +++ b/security/selinux/ibpkey.c @@ -141,7 +141,7 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid) return 0; } - ret = security_ib_pkey_sid(subnet_prefix, pkey_num, + ret = security_ib_pkey_sid(&selinux_state, subnet_prefix, pkey_num, sid); if (ret) goto out; diff --git a/security/selinux/ima.c b/security/selinux/ima.c index aa34da9b0aeb..08f89f212422 100644 --- a/security/selinux/ima.c +++ b/security/selinux/ima.c @@ -15,10 +15,12 @@ /* * selinux_ima_collect_state - Read selinux configuration settings * + * @state: selinux_state + * * On success returns the configuration settings string. * On error, returns NULL. */ -static char *selinux_ima_collect_state(void) +static char *selinux_ima_collect_state(struct selinux_state *state) { const char *on = "=1;", *off = "=0;"; char *buf; @@ -37,27 +39,26 @@ static char *selinux_ima_collect_state(void) rc = strscpy(buf, "initialized", buf_len); WARN_ON(rc < 0); - rc = strlcat(buf, selinux_initialized() ? on : off, buf_len); + rc = strlcat(buf, selinux_initialized(state) ? on : off, buf_len); WARN_ON(rc >= buf_len); rc = strlcat(buf, "enforcing", buf_len); WARN_ON(rc >= buf_len); - rc = strlcat(buf, enforcing_enabled() ? on : off, buf_len); + rc = strlcat(buf, enforcing_enabled(state) ? on : off, buf_len); WARN_ON(rc >= buf_len); rc = strlcat(buf, "checkreqprot", buf_len); WARN_ON(rc >= buf_len); - rc = strlcat(buf, checkreqprot_get() ? on : off, buf_len); + rc = strlcat(buf, checkreqprot_get(state) ? on : off, buf_len); WARN_ON(rc >= buf_len); for (i = 0; i < __POLICYDB_CAP_MAX; i++) { rc = strlcat(buf, selinux_policycap_names[i], buf_len); WARN_ON(rc >= buf_len); - rc = strlcat(buf, selinux_state.policycap[i] ? on : off, - buf_len); + rc = strlcat(buf, state->policycap[i] ? on : off, buf_len); WARN_ON(rc >= buf_len); } @@ -66,17 +67,19 @@ static char *selinux_ima_collect_state(void) /* * selinux_ima_measure_state_locked - Measure SELinux state and hash of policy + * + * @state: selinux state struct */ -void selinux_ima_measure_state_locked(void) +void selinux_ima_measure_state_locked(struct selinux_state *state) { char *state_str = NULL; void *policy = NULL; size_t policy_len; int rc = 0; - lockdep_assert_held(&selinux_state.policy_mutex); + lockdep_assert_held(&state->policy_mutex); - state_str = selinux_ima_collect_state(); + state_str = selinux_ima_collect_state(state); if (!state_str) { pr_err("SELinux: %s: failed to read state.\n", __func__); return; @@ -91,10 +94,10 @@ void selinux_ima_measure_state_locked(void) /* * Measure SELinux policy only after initialization is completed. */ - if (!selinux_initialized()) + if (!selinux_initialized(state)) return; - rc = security_read_state_kernel(&policy, &policy_len); + rc = security_read_state_kernel(state, &policy, &policy_len); if (rc) { pr_err("SELinux: %s: failed to read policy %d.\n", __func__, rc); return; @@ -109,12 +112,14 @@ void selinux_ima_measure_state_locked(void) /* * selinux_ima_measure_state - Measure SELinux state and hash of policy + * + * @state: selinux state struct */ -void selinux_ima_measure_state(void) +void selinux_ima_measure_state(struct selinux_state *state) { - lockdep_assert_not_held(&selinux_state.policy_mutex); + lockdep_assert_not_held(&state->policy_mutex); - mutex_lock(&selinux_state.policy_mutex); - selinux_ima_measure_state_locked(); - mutex_unlock(&selinux_state.policy_mutex); + mutex_lock(&state->policy_mutex); + selinux_ima_measure_state_locked(state); + mutex_unlock(&state->policy_mutex); } diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 96a614d47df8..9c6d9c5e727e 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -53,6 +53,7 @@ struct selinux_audit_data { u32 audited; u32 denied; int result; + struct selinux_state *state; } __randomize_layout; /* @@ -94,11 +95,13 @@ static inline u32 avc_audit_required(u32 requested, struct av_decision *avd, return audited; } -int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, u32 audited, - u32 denied, int result, struct common_audit_data *a); +int slow_avc_audit(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, + u32 requested, u32 audited, u32 denied, int result, + struct common_audit_data *a); /** * avc_audit - Audit the granting or denial of permissions. + * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class @@ -116,30 +119,32 @@ int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, u32 audited, * be performed under a lock, to allow the lock to be released * before calling the auditing code. */ -static inline int avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, - struct av_decision *avd, int result, - struct common_audit_data *a) +static inline int avc_audit(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 requested, struct av_decision *avd, + int result, struct common_audit_data *a) { u32 audited, denied; audited = avc_audit_required(requested, avd, result, 0, &denied); if (likely(!audited)) return 0; - return slow_avc_audit(ssid, tsid, tclass, requested, audited, denied, - result, a); + return slow_avc_audit(state, ssid, tsid, tclass, requested, audited, + denied, result, a); } #define AVC_STRICT 1 /* Ignore permissive mode. */ #define AVC_EXTENDED_PERMS 2 /* update extended permissions */ -int avc_has_perm_noaudit(u32 ssid, u32 tsid, u16 tclass, u32 requested, - unsigned int flags, struct av_decision *avd); +int avc_has_perm_noaudit(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 requested, unsigned int flags, + struct av_decision *avd); -int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, u32 requested, - struct common_audit_data *auditdata); +int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *auditdata); -int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, - u8 driver, u8 perm, struct common_audit_data *ad); +int avc_has_extended_perms(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 requested, u8 driver, u8 perm, + struct common_audit_data *ad); -u32 avc_policy_seqno(void); +u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 #define AVC_CALLBACK_TRY_REVOKE 2 @@ -154,9 +159,11 @@ u32 avc_policy_seqno(void); int avc_add_callback(int (*callback)(u32 event), u32 events); /* Exported to selinuxfs */ -int avc_get_hash_stats(char *page); -unsigned int avc_get_cache_threshold(void); -void avc_set_cache_threshold(unsigned int cache_threshold); +struct selinux_avc; +int avc_get_hash_stats(struct selinux_avc *avc, char *page); +unsigned int avc_get_cache_threshold(struct selinux_avc *avc); +void avc_set_cache_threshold(struct selinux_avc *avc, + unsigned int cache_threshold); #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index 48ad64d54032..4dc2ddd0de7d 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h @@ -10,7 +10,8 @@ #include -int avc_ss_reset(u32 seqno); +struct selinux_avc; +int avc_ss_reset(struct selinux_avc *avc, u32 seqno); /* Class/perm mapping support */ struct security_class_mapping { diff --git a/security/selinux/include/conditional.h b/security/selinux/include/conditional.h index 5910bb7c2eca..8fd195363ea4 100644 --- a/security/selinux/include/conditional.h +++ b/security/selinux/include/conditional.h @@ -16,8 +16,8 @@ int security_get_bools(struct selinux_policy *policy, u32 *len, char ***names, int **values); -int security_set_bools(u32 len, int *values); +int security_set_bools(struct selinux_state *state, u32 len, int *values); -int security_get_bool_value(u32 index); +int security_get_bool_value(struct selinux_state *state, u32 index); #endif diff --git a/security/selinux/include/ima.h b/security/selinux/include/ima.h index 38ab302f5946..37c7394de893 100644 --- a/security/selinux/include/ima.h +++ b/security/selinux/include/ima.h @@ -14,13 +14,16 @@ #include "security.h" #ifdef CONFIG_IMA -extern void selinux_ima_measure_state(void); -extern void selinux_ima_measure_state_locked(void); +extern void selinux_ima_measure_state(struct selinux_state *selinux_state); +extern void +selinux_ima_measure_state_locked(struct selinux_state *selinux_state); #else -static inline void selinux_ima_measure_state(void) +static inline void +selinux_ima_measure_state(struct selinux_state *selinux_state) { } -static inline void selinux_ima_measure_state_locked(void) +static inline void +selinux_ima_measure_state_locked(struct selinux_state *selinux_state) { } #endif diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 10949df22fa4..bf223dcc7e0f 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -88,6 +88,7 @@ extern int selinux_enabled_boot; /* limitation of boundary depth */ #define POLICYDB_BOUNDS_MAXDEPTH 4 +struct selinux_avc; struct selinux_policy; struct selinux_state { @@ -100,48 +101,49 @@ struct selinux_state { struct page *status_page; struct mutex status_lock; + struct selinux_avc *avc; struct selinux_policy __rcu *policy; struct mutex policy_mutex; } __randomize_layout; -void selinux_avc_init(void); +void selinux_avc_init(struct selinux_avc **avc); extern struct selinux_state selinux_state; -static inline bool selinux_initialized(void) +static inline bool selinux_initialized(const struct selinux_state *state) { /* do a synchronized load to avoid race conditions */ - return smp_load_acquire(&selinux_state.initialized); + return smp_load_acquire(&state->initialized); } -static inline void selinux_mark_initialized(void) +static inline void selinux_mark_initialized(struct selinux_state *state) { /* do a synchronized write to avoid race conditions */ - smp_store_release(&selinux_state.initialized, true); + smp_store_release(&state->initialized, true); } #ifdef CONFIG_SECURITY_SELINUX_DEVELOP -static inline bool enforcing_enabled(void) +static inline bool enforcing_enabled(struct selinux_state *state) { - return READ_ONCE(selinux_state.enforcing); + return READ_ONCE(state->enforcing); } -static inline void enforcing_set(bool value) +static inline void enforcing_set(struct selinux_state *state, bool value) { - WRITE_ONCE(selinux_state.enforcing, value); + WRITE_ONCE(state->enforcing, value); } #else -static inline bool enforcing_enabled(void) +static inline bool enforcing_enabled(struct selinux_state *state) { return true; } -static inline void enforcing_set(bool value) +static inline void enforcing_set(struct selinux_state *state, bool value) { } #endif -static inline bool checkreqprot_get(void) +static inline bool checkreqprot_get(const struct selinux_state *state) { /* non-zero/true checkreqprot values are no longer supported */ return 0; @@ -209,14 +211,18 @@ struct selinux_load_state { struct selinux_policy_convert_data *convert_data; }; -int security_mls_enabled(void); -int security_load_policy(void *data, size_t len, +int security_mls_enabled(struct selinux_state *state); +int security_load_policy(struct selinux_state *state, void *data, size_t len, struct selinux_load_state *load_state); -void selinux_policy_commit(struct selinux_load_state *load_state); -void selinux_policy_cancel(struct selinux_load_state *load_state); -int security_read_policy(void **data, size_t *len); -int security_read_state_kernel(void **data, size_t *len); -int security_policycap_supported(unsigned int req_cap); +void selinux_policy_commit(struct selinux_state *state, + struct selinux_load_state *load_state); +void selinux_policy_cancel(struct selinux_state *state, + struct selinux_load_state *load_state); +int security_read_policy(struct selinux_state *state, void **data, size_t *len); +int security_read_state_kernel(struct selinux_state *state, void **data, + size_t *len); +int security_policycap_supported(struct selinux_state *state, + unsigned int req_cap); #define SEL_VEC_MAX 32 struct av_decision { @@ -253,74 +259,91 @@ struct extended_perms { /* definitions of av_decision.flags */ #define AVD_FLAGS_PERMISSIVE 0x0001 -void security_compute_av(u32 ssid, u32 tsid, u16 tclass, - struct av_decision *avd, +void security_compute_av(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, struct av_decision *avd, struct extended_perms *xperms); -void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass, u8 driver, +void security_compute_xperms_decision(struct selinux_state *state, u32 ssid, + u32 tsid, u16 tclass, u8 driver, struct extended_perms_decision *xpermd); -void security_compute_av_user(u32 ssid, u32 tsid, u16 tclass, - struct av_decision *avd); +void security_compute_av_user(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, struct av_decision *avd); -int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, - const struct qstr *qstr, u32 *out_sid); +int security_transition_sid(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, const struct qstr *qstr, u32 *out_sid); -int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, - const char *objname, u32 *out_sid); +int security_transition_sid_user(struct selinux_state *state, u32 ssid, + u32 tsid, u16 tclass, const char *objname, + u32 *out_sid); -int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid); +int security_member_sid(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 *out_sid); -int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid); +int security_change_sid(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 *out_sid); -int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len); +int security_sid_to_context(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len); -int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len); +int security_sid_to_context_force(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len); -int security_sid_to_context_inval(u32 sid, char **scontext, u32 *scontext_len); +int security_sid_to_context_inval(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len); -int security_context_to_sid(const char *scontext, u32 scontext_len, - u32 *out_sid, gfp_t gfp); +int security_context_to_sid(struct selinux_state *state, const char *scontext, + u32 scontext_len, u32 *out_sid, gfp_t gfp); -int security_context_str_to_sid(const char *scontext, u32 *out_sid, gfp_t gfp); +int security_context_str_to_sid(struct selinux_state *state, + const char *scontext, u32 *out_sid, gfp_t gfp); -int security_context_to_sid_default(const char *scontext, u32 scontext_len, +int security_context_to_sid_default(struct selinux_state *state, + const char *scontext, u32 scontext_len, u32 *out_sid, u32 def_sid, gfp_t gfp_flags); -int security_context_to_sid_force(const char *scontext, u32 scontext_len, +int security_context_to_sid_force(struct selinux_state *state, + const char *scontext, u32 scontext_len, u32 *sid); -int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel); +int security_get_user_sids(struct selinux_state *state, u32 callsid, + char *username, u32 **sids, u32 *nel); -int security_port_sid(u8 protocol, u16 port, u32 *out_sid); +int security_port_sid(struct selinux_state *state, u8 protocol, u16 port, + u32 *out_sid); -int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid); +int security_ib_pkey_sid(struct selinux_state *state, u64 subnet_prefix, + u16 pkey_num, u32 *out_sid); -int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid); +int security_ib_endport_sid(struct selinux_state *state, const char *dev_name, + u8 port_num, u32 *out_sid); -int security_netif_sid(char *name, u32 *if_sid); +int security_netif_sid(struct selinux_state *state, char *name, u32 *if_sid); -int security_node_sid(u16 domain, void *addr, u32 addrlen, u32 *out_sid); +int security_node_sid(struct selinux_state *state, u16 domain, void *addr, + u32 addrlen, u32 *out_sid); -int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, - u16 tclass); +int security_validate_transition(struct selinux_state *state, u32 oldsid, + u32 newsid, u32 tasksid, u16 tclass); -int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid, - u16 tclass); +int security_validate_transition_user(struct selinux_state *state, u32 oldsid, + u32 newsid, u32 tasksid, u16 tclass); -int security_bounded_transition(u32 oldsid, u32 newsid); +int security_bounded_transition(struct selinux_state *state, u32 oldsid, + u32 newsid); -int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); +int security_sid_mls_copy(struct selinux_state *state, u32 sid, u32 mls_sid, + u32 *new_sid); -int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, u32 xfrm_sid, - u32 *peer_sid); +int security_net_peersid_resolve(struct selinux_state *state, u32 nlbl_sid, + u32 nlbl_type, u32 xfrm_sid, u32 *peer_sid); int security_get_classes(struct selinux_policy *policy, char ***classes, u32 *nclasses); int security_get_permissions(struct selinux_policy *policy, const char *class, char ***perms, u32 *nperms); -int security_get_reject_unknown(void); -int security_get_allow_unknown(void); +int security_get_reject_unknown(struct selinux_state *state); +int security_get_allow_unknown(struct selinux_state *state); #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ @@ -331,28 +354,32 @@ int security_get_allow_unknown(void); #define SECURITY_FS_USE_NATIVE 7 /* use native label support */ #define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */ -int security_fs_use(struct super_block *sb); +int security_fs_use(struct selinux_state *state, struct super_block *sb); -int security_genfs_sid(const char *fstype, const char *path, u16 sclass, - u32 *sid); +int security_genfs_sid(struct selinux_state *state, const char *fstype, + const char *path, u16 sclass, u32 *sid); int selinux_policy_genfs_sid(struct selinux_policy *policy, const char *fstype, const char *path, u16 sclass, u32 *sid); #ifdef CONFIG_NETLABEL -int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, +int security_netlbl_secattr_to_sid(struct selinux_state *state, + struct netlbl_lsm_secattr *secattr, u32 *sid); -int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr); +int security_netlbl_sid_to_secattr(struct selinux_state *state, u32 sid, + struct netlbl_lsm_secattr *secattr); #else static inline int -security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, u32 *sid) +security_netlbl_secattr_to_sid(struct selinux_state *state, + struct netlbl_lsm_secattr *secattr, u32 *sid) { return -EIDRM; } static inline int -security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) +security_netlbl_sid_to_secattr(struct selinux_state *state, u32 sid, + struct netlbl_lsm_secattr *secattr) { return -ENOENT; } @@ -363,7 +390,7 @@ const char *security_get_initial_sid_context(u32 sid); /* * status notifier using mmap interface */ -extern struct page *selinux_kernel_status_page(void); +extern struct page *selinux_kernel_status_page(struct selinux_state *state); #define SELINUX_KERNEL_STATUS_VERSION 1 struct selinux_kernel_status { @@ -377,8 +404,10 @@ struct selinux_kernel_status { */ } __packed; -extern void selinux_status_update_setenforce(bool enforcing); -extern void selinux_status_update_policyload(u32 seqno); +extern void selinux_status_update_setenforce(struct selinux_state *state, + bool enforcing); +extern void selinux_status_update_policyload(struct selinux_state *state, + u32 seqno); extern void selinux_complete_init(void); extern struct path selinux_null; extern void selnl_notify_setenforce(int val); @@ -388,6 +417,6 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); extern void avtab_cache_init(void); extern void ebitmap_cache_init(void); extern void hashtab_cache_init(void); -extern int security_sidtab_hash_stats(char *page); +extern int security_sidtab_hash_stats(struct selinux_state *state, char *page); #endif /* _SELINUX_SECURITY_H_ */ diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 43a0d3594b72..6d0c7bc9be15 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -153,7 +153,7 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) goto out; } - ret = security_netif_sid(dev->name, sid); + ret = security_netif_sid(&selinux_state, dev->name, sid); if (ret != 0) goto out; new = kzalloc(sizeof(*new), GFP_ATOMIC); diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index d51dfe892312..b858b46fd4b4 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -47,7 +47,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, { int rc; - rc = security_netlbl_secattr_to_sid(secattr, sid); + rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid); if (rc == 0 && (secattr->flags & NETLBL_SECATTR_CACHEABLE) && (secattr->flags & NETLBL_SECATTR_CACHE)) @@ -79,7 +79,8 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) if (secattr == NULL) return ERR_PTR(-ENOMEM); - rc = security_netlbl_sid_to_secattr(sksec->sid, secattr); + rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid, + secattr); if (rc != 0) { netlbl_secattr_free(secattr); return ERR_PTR(rc); @@ -251,7 +252,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, if (secattr == NULL) { secattr = &secattr_storage; netlbl_secattr_init(secattr); - rc = security_netlbl_sid_to_secattr(sid, secattr); + rc = security_netlbl_sid_to_secattr(&selinux_state, sid, + secattr); if (rc != 0) goto skbuff_setsid_return; } @@ -288,7 +290,8 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, return 0; netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(asoc->secid, &secattr); + rc = security_netlbl_sid_to_secattr(&selinux_state, + asoc->secid, &secattr); if (rc != 0) goto assoc_request_return; @@ -336,7 +339,8 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) return 0; netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(req->secid, &secattr); + rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid, + &secattr); if (rc != 0) goto inet_conn_request_return; rc = netlbl_req_setattr(req, &secattr); @@ -469,7 +473,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, perm = RAWIP_SOCKET__RECVFROM; } - rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); + rc = avc_has_perm(&selinux_state, + sksec->sid, nlbl_sid, sksec->sclass, perm, ad); if (rc == 0) return 0; diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 5c8c77e50aad..0ac7df9a9367 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -204,13 +204,13 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) new = kzalloc(sizeof(*new), GFP_ATOMIC); switch (family) { case PF_INET: - ret = security_node_sid(PF_INET, + ret = security_node_sid(&selinux_state, PF_INET, addr, sizeof(struct in_addr), sid); if (new) new->nsec.addr.ipv4 = *(__be32 *)addr; break; case PF_INET6: - ret = security_node_sid(PF_INET6, + ret = security_node_sid(&selinux_state, PF_INET6, addr, sizeof(struct in6_addr), sid); if (new) new->nsec.addr.ipv6 = *(struct in6_addr *)addr; diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 2e22ad9c2bd0..8eec6347cf01 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c @@ -148,7 +148,7 @@ static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid) return 0; } - ret = security_port_sid(protocol, pnum, sid); + ret = security_port_sid(&selinux_state, protocol, pnum, sid); if (ret != 0) goto out; new = kzalloc(sizeof(*new), GFP_ATOMIC); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 1efb9a57d181..792a042add28 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -77,6 +77,7 @@ struct selinux_fs_info { bool policy_opened; struct dentry *policycap_dir; unsigned long last_ino; + struct selinux_state *state; struct super_block *sb; }; @@ -89,6 +90,7 @@ static int selinux_fs_info_create(struct super_block *sb) return -ENOMEM; fsi->last_ino = SEL_INO_NEXT - 1; + fsi->state = &selinux_state; fsi->sb = sb; sb->s_fs_info = fsi; return 0; @@ -123,11 +125,12 @@ static void selinux_fs_info_free(struct super_block *sb) static ssize_t sel_read_enforce(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; char tmpbuf[TMPBUFLEN]; ssize_t length; length = scnprintf(tmpbuf, TMPBUFLEN, "%d", - enforcing_enabled()); + enforcing_enabled(fsi->state)); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } @@ -136,6 +139,8 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *page = NULL; ssize_t length; int scan_value; @@ -158,9 +163,10 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, new_value = !!scan_value; - old_value = enforcing_enabled(); + old_value = enforcing_enabled(state); if (new_value != old_value) { - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETENFORCE, NULL); if (length) @@ -171,15 +177,15 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, new_value, old_value, from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); - enforcing_set(new_value); + enforcing_set(state, new_value); if (new_value) - avc_ss_reset(0); + avc_ss_reset(state->avc, 0); selnl_notify_setenforce(new_value); - selinux_status_update_setenforce(new_value); + selinux_status_update_setenforce(state, new_value); if (!new_value) call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL); - selinux_ima_measure_state(); + selinux_ima_measure_state(state); } length = count; out: @@ -199,12 +205,14 @@ static const struct file_operations sel_enforce_ops = { static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char tmpbuf[TMPBUFLEN]; ssize_t length; ino_t ino = file_inode(filp)->i_ino; int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ? - security_get_reject_unknown() : - !security_get_allow_unknown(); + security_get_reject_unknown(state) : + !security_get_allow_unknown(state); length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); @@ -217,7 +225,8 @@ static const struct file_operations sel_handle_unknown_ops = { static int sel_open_handle_status(struct inode *inode, struct file *filp) { - struct page *status = selinux_kernel_status_page(); + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; + struct page *status = selinux_kernel_status_page(fsi->state); if (!status) return -ENOMEM; @@ -342,11 +351,12 @@ static struct dentry *sel_make_swapover_dir(struct super_block *sb, static ssize_t sel_read_mls(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; char tmpbuf[TMPBUFLEN]; ssize_t length; length = scnprintf(tmpbuf, TMPBUFLEN, "%d", - security_mls_enabled()); + security_mls_enabled(fsi->state)); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } @@ -363,14 +373,16 @@ struct policy_load_memory { static int sel_open_policy(struct inode *inode, struct file *filp) { struct selinux_fs_info *fsi = inode->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; struct policy_load_memory *plm = NULL; int rc; BUG_ON(filp->private_data); - mutex_lock(&selinux_state.policy_mutex); + mutex_lock(&fsi->state->policy_mutex); - rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, + rc = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); if (rc) goto err; @@ -384,7 +396,7 @@ static int sel_open_policy(struct inode *inode, struct file *filp) if (!plm) goto err; - rc = security_read_policy(&plm->data, &plm->len); + rc = security_read_policy(state, &plm->data, &plm->len); if (rc) goto err; @@ -398,11 +410,11 @@ static int sel_open_policy(struct inode *inode, struct file *filp) filp->private_data = plm; - mutex_unlock(&selinux_state.policy_mutex); + mutex_unlock(&fsi->state->policy_mutex); return 0; err: - mutex_unlock(&selinux_state.policy_mutex); + mutex_unlock(&fsi->state->policy_mutex); if (plm) vfree(plm->data); @@ -431,7 +443,8 @@ static ssize_t sel_read_policy(struct file *filp, char __user *buf, struct policy_load_memory *plm = filp->private_data; int ret; - ret = avc_has_perm(current_sid(), SECINITSID_SECURITY, + ret = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); if (ret) return ret; @@ -571,7 +584,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct selinux_fs_info *fsi; + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; struct selinux_load_state load_state; ssize_t length; void *data = NULL; @@ -583,9 +596,9 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, if (!count) return -EINVAL; - mutex_lock(&selinux_state.policy_mutex); - - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + mutex_lock(&fsi->state->policy_mutex); + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); if (length) goto out; @@ -600,7 +613,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, goto out; } - length = security_load_policy(data, count, &load_state); + length = security_load_policy(fsi->state, data, count, &load_state); if (length) { pr_warn_ratelimited("SELinux: failed to load policy\n"); goto out; @@ -609,11 +622,11 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, length = sel_make_policy_nodes(fsi, load_state.policy); if (length) { pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n"); - selinux_policy_cancel(&load_state); + selinux_policy_cancel(fsi->state, &load_state); goto out; } - selinux_policy_commit(&load_state); + selinux_policy_commit(fsi->state, &load_state); length = count; audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, "auid=%u ses=%u lsm=selinux res=1", @@ -621,7 +634,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, audit_get_sessionid(current)); out: - mutex_unlock(&selinux_state.policy_mutex); + mutex_unlock(&fsi->state->policy_mutex); vfree(data); return length; } @@ -633,20 +646,23 @@ static const struct file_operations sel_load_ops = { static ssize_t sel_write_context(struct file *file, char *buf, size_t size) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *canon = NULL; u32 sid, len; ssize_t length; - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL); if (length) goto out; - length = security_context_to_sid(buf, size, &sid, GFP_KERNEL); + length = security_context_to_sid(state, buf, size, &sid, GFP_KERNEL); if (length) goto out; - length = security_sid_to_context(sid, &canon, &len); + length = security_sid_to_context(state, sid, &canon, &len); if (length) goto out; @@ -667,22 +683,25 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; char tmpbuf[TMPBUFLEN]; ssize_t length; length = scnprintf(tmpbuf, TMPBUFLEN, "%u", - checkreqprot_get()); + checkreqprot_get(fsi->state)); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; char *page; ssize_t length; unsigned int new_value; - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, NULL); if (length) @@ -713,7 +732,7 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, comm, current->pid); } - selinux_ima_measure_state(); + selinux_ima_measure_state(fsi->state); out: kfree(page); @@ -729,13 +748,16 @@ static ssize_t sel_write_validatetrans(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *oldcon = NULL, *newcon = NULL, *taskcon = NULL; char *req = NULL; u32 osid, nsid, tsid; u16 tclass; int rc; - rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, + rc = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL); if (rc) goto out; @@ -773,19 +795,19 @@ static ssize_t sel_write_validatetrans(struct file *file, if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4) goto out; - rc = security_context_str_to_sid(oldcon, &osid, GFP_KERNEL); + rc = security_context_str_to_sid(state, oldcon, &osid, GFP_KERNEL); if (rc) goto out; - rc = security_context_str_to_sid(newcon, &nsid, GFP_KERNEL); + rc = security_context_str_to_sid(state, newcon, &nsid, GFP_KERNEL); if (rc) goto out; - rc = security_context_str_to_sid(taskcon, &tsid, GFP_KERNEL); + rc = security_context_str_to_sid(state, taskcon, &tsid, GFP_KERNEL); if (rc) goto out; - rc = security_validate_transition_user(osid, nsid, tsid, tclass); + rc = security_validate_transition_user(state, osid, nsid, tsid, tclass); if (!rc) rc = count; out: @@ -855,13 +877,16 @@ static const struct file_operations transaction_ops = { static ssize_t sel_write_access(struct file *file, char *buf, size_t size) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *scon = NULL, *tcon = NULL; u32 ssid, tsid; u16 tclass; struct av_decision avd; ssize_t length; - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL); if (length) goto out; @@ -880,15 +905,15 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL); + length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); if (length) goto out; - length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL); + length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); if (length) goto out; - security_compute_av_user(ssid, tsid, tclass, &avd); + security_compute_av_user(state, ssid, tsid, tclass, &avd); length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%x %x %x %x %u %x", @@ -903,6 +928,8 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) static ssize_t sel_write_create(struct file *file, char *buf, size_t size) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *scon = NULL, *tcon = NULL; char *namebuf = NULL, *objname = NULL; u32 ssid, tsid, newsid; @@ -912,7 +939,8 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) u32 len; int nargs; - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, NULL); if (length) @@ -968,20 +996,20 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) objname = namebuf; } - length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL); + length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); if (length) goto out; - length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL); + length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); if (length) goto out; - length = security_transition_sid_user(ssid, tsid, tclass, + length = security_transition_sid_user(state, ssid, tsid, tclass, objname, &newsid); if (length) goto out; - length = security_sid_to_context(newsid, &newcon, &len); + length = security_sid_to_context(state, newsid, &newcon, &len); if (length) goto out; @@ -1004,6 +1032,8 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *scon = NULL, *tcon = NULL; u32 ssid, tsid, newsid; u16 tclass; @@ -1011,7 +1041,8 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) char *newcon = NULL; u32 len; - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, NULL); if (length) @@ -1031,19 +1062,19 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL); + length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); if (length) goto out; - length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL); + length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); if (length) goto out; - length = security_change_sid(ssid, tsid, tclass, &newsid); + length = security_change_sid(state, ssid, tsid, tclass, &newsid); if (length) goto out; - length = security_sid_to_context(newsid, &newcon, &len); + length = security_sid_to_context(state, newsid, &newcon, &len); if (length) goto out; @@ -1062,6 +1093,8 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) static ssize_t sel_write_user(struct file *file, char *buf, size_t size) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *con = NULL, *user = NULL, *ptr; u32 sid, *sids = NULL; ssize_t length; @@ -1073,7 +1106,8 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) " This will not be supported in the future; please update your" " userspace.\n", current->comm, current->pid); - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_USER, NULL); if (length) @@ -1093,18 +1127,18 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s", con, user) != 2) goto out; - length = security_context_str_to_sid(con, &sid, GFP_KERNEL); + length = security_context_str_to_sid(state, con, &sid, GFP_KERNEL); if (length) goto out; - length = security_get_user_sids(sid, user, &sids, &nsids); + length = security_get_user_sids(state, sid, user, &sids, &nsids); if (length) goto out; length = sprintf(buf, "%u", nsids) + 1; ptr = buf + length; for (i = 0; i < nsids; i++) { - rc = security_sid_to_context(sids[i], &newcon, &len); + rc = security_sid_to_context(state, sids[i], &newcon, &len); if (rc) { length = rc; goto out; @@ -1128,6 +1162,8 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) static ssize_t sel_write_member(struct file *file, char *buf, size_t size) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *scon = NULL, *tcon = NULL; u32 ssid, tsid, newsid; u16 tclass; @@ -1135,7 +1171,8 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) char *newcon = NULL; u32 len; - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, NULL); if (length) @@ -1155,19 +1192,19 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL); + length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); if (length) goto out; - length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL); + length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); if (length) goto out; - length = security_member_sid(ssid, tsid, tclass, &newsid); + length = security_member_sid(state, ssid, tsid, tclass, &newsid); if (length) goto out; - length = security_sid_to_context(newsid, &newcon, &len); + length = security_sid_to_context(state, newsid, &newcon, &len); if (length) goto out; @@ -1209,7 +1246,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; const char *name = filep->f_path.dentry->d_name.name; - mutex_lock(&selinux_state.policy_mutex); + mutex_lock(&fsi->state->policy_mutex); ret = -EINVAL; if (index >= fsi->bool_num || strcmp(name, @@ -1221,21 +1258,21 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, if (!page) goto out_unlock; - cur_enforcing = security_get_bool_value(index); + cur_enforcing = security_get_bool_value(fsi->state, index); if (cur_enforcing < 0) { ret = cur_enforcing; goto out_unlock; } length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, fsi->bool_pending_values[index]); - mutex_unlock(&selinux_state.policy_mutex); + mutex_unlock(&fsi->state->policy_mutex); ret = simple_read_from_buffer(buf, count, ppos, page, length); out_free: free_page((unsigned long)page); return ret; out_unlock: - mutex_unlock(&selinux_state.policy_mutex); + mutex_unlock(&fsi->state->policy_mutex); goto out_free; } @@ -1260,9 +1297,10 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, if (IS_ERR(page)) return PTR_ERR(page); - mutex_lock(&selinux_state.policy_mutex); + mutex_lock(&fsi->state->policy_mutex); - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETBOOL, NULL); if (length) @@ -1284,7 +1322,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, length = count; out: - mutex_unlock(&selinux_state.policy_mutex); + mutex_unlock(&fsi->state->policy_mutex); kfree(page); return length; } @@ -1315,9 +1353,10 @@ static ssize_t sel_commit_bools_write(struct file *filep, if (IS_ERR(page)) return PTR_ERR(page); - mutex_lock(&selinux_state.policy_mutex); + mutex_lock(&fsi->state->policy_mutex); - length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + length = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETBOOL, NULL); if (length) @@ -1329,14 +1368,14 @@ static ssize_t sel_commit_bools_write(struct file *filep, length = 0; if (new_value && fsi->bool_pending_values) - length = security_set_bools(fsi->bool_num, + length = security_set_bools(fsi->state, fsi->bool_num, fsi->bool_pending_values); if (!length) length = count; out: - mutex_unlock(&selinux_state.policy_mutex); + mutex_unlock(&fsi->state->policy_mutex); kfree(page); return length; } @@ -1413,11 +1452,13 @@ static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_ static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char tmpbuf[TMPBUFLEN]; ssize_t length; length = scnprintf(tmpbuf, TMPBUFLEN, "%u", - avc_get_cache_threshold()); + avc_get_cache_threshold(state->avc)); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } @@ -1426,11 +1467,14 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *page; ssize_t ret; unsigned int new_value; - ret = avc_has_perm(current_sid(), SECINITSID_SECURITY, + ret = avc_has_perm(&selinux_state, + current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETSECPARAM, NULL); if (ret) @@ -1451,7 +1495,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, if (sscanf(page, "%u", &new_value) != 1) goto out; - avc_set_cache_threshold(new_value); + avc_set_cache_threshold(state->avc, new_value); ret = count; out: @@ -1462,6 +1506,8 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *page; ssize_t length; @@ -1469,7 +1515,7 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, if (!page) return -ENOMEM; - length = avc_get_hash_stats(page); + length = avc_get_hash_stats(state->avc, page); if (length >= 0) length = simple_read_from_buffer(buf, count, ppos, page, length); free_page((unsigned long)page); @@ -1480,6 +1526,8 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, static ssize_t sel_read_sidtab_hash_stats(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; char *page; ssize_t length; @@ -1487,7 +1535,7 @@ static ssize_t sel_read_sidtab_hash_stats(struct file *filp, char __user *buf, if (!page) return -ENOMEM; - length = security_sidtab_hash_stats(page); + length = security_sidtab_hash_stats(state, page); if (length >= 0) length = simple_read_from_buffer(buf, count, ppos, page, length); @@ -1653,12 +1701,13 @@ static int sel_make_ss_files(struct dentry *dir) static ssize_t sel_read_initcon(struct file *file, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; char *con; u32 sid, len; ssize_t ret; sid = file_inode(file)->i_ino&SEL_INO_MASK; - ret = security_sid_to_context(sid, &con, &len); + ret = security_sid_to_context(fsi->state, sid, &con, &len); if (ret) return ret; @@ -1752,12 +1801,13 @@ static const struct file_operations sel_perm_ops = { static ssize_t sel_read_policycap(struct file *file, char __user *buf, size_t count, loff_t *ppos) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; int value; char tmpbuf[TMPBUFLEN]; ssize_t length; unsigned long i_ino = file_inode(file)->i_ino; - value = security_policycap_supported(i_ino & SEL_INO_MASK); + value = security_policycap_supported(fsi->state, i_ino & SEL_INO_MASK); length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); @@ -2171,7 +2221,7 @@ static int __init init_sel_fs(void) * Try to pre-allocate the status page, so the sequence number of the * initial policy load can be stored. */ - (void) selinux_kernel_status_page(); + (void) selinux_kernel_status_page(&selinux_state); return err; } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 55fdc7ca232b..7d6fd08dcb7d 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -235,16 +235,16 @@ static void map_decision(struct selinux_map *map, } } -int security_mls_enabled(void) +int security_mls_enabled(struct selinux_state *state) { int mls_enabled; struct selinux_policy *policy; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); mls_enabled = policy->policydb.mls_enabled; rcu_read_unlock(); return mls_enabled; @@ -715,7 +715,8 @@ static void context_struct_compute_av(struct policydb *policydb, tclass, avd); } -static int security_validtrans_handle_fail(struct selinux_policy *policy, +static int security_validtrans_handle_fail(struct selinux_state *state, + struct selinux_policy *policy, struct sidtab_entry *oentry, struct sidtab_entry *nentry, struct sidtab_entry *tentry, @@ -741,12 +742,13 @@ static int security_validtrans_handle_fail(struct selinux_policy *policy, kfree(n); kfree(t); - if (!enforcing_enabled()) + if (!enforcing_enabled(state)) return 0; return -EPERM; } -static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, +static int security_compute_validatetrans(struct selinux_state *state, + u32 oldsid, u32 newsid, u32 tasksid, u16 orig_tclass, bool user) { struct selinux_policy *policy; @@ -761,12 +763,12 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, int rc = 0; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -813,7 +815,8 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, if (user) rc = -EPERM; else - rc = security_validtrans_handle_fail(policy, + rc = security_validtrans_handle_fail(state, + policy, oentry, nentry, tentry, @@ -828,17 +831,19 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, return rc; } -int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid, +int security_validate_transition_user(struct selinux_state *state, + u32 oldsid, u32 newsid, u32 tasksid, u16 tclass) { - return security_compute_validatetrans(oldsid, newsid, tasksid, + return security_compute_validatetrans(state, oldsid, newsid, tasksid, tclass, true); } -int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, +int security_validate_transition(struct selinux_state *state, + u32 oldsid, u32 newsid, u32 tasksid, u16 orig_tclass) { - return security_compute_validatetrans(oldsid, newsid, tasksid, + return security_compute_validatetrans(state, oldsid, newsid, tasksid, orig_tclass, false); } @@ -848,10 +853,12 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, * It returns 0, if @newsid is bounded by @oldsid. * Otherwise, it returns error code. * + * @state: SELinux state * @oldsid : current security identifier * @newsid : destinated security identifier */ -int security_bounded_transition(u32 old_sid, u32 new_sid) +int security_bounded_transition(struct selinux_state *state, + u32 old_sid, u32 new_sid) { struct selinux_policy *policy; struct policydb *policydb; @@ -861,11 +868,11 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) u32 index; int rc; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -1006,7 +1013,8 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd, } } -void security_compute_xperms_decision(u32 ssid, +void security_compute_xperms_decision(struct selinux_state *state, + u32 ssid, u32 tsid, u16 orig_tclass, u8 driver, @@ -1030,10 +1038,10 @@ void security_compute_xperms_decision(u32 ssid, memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p)); rcu_read_lock(); - if (!selinux_initialized()) + if (!selinux_initialized(state)) goto allow; - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -1092,6 +1100,7 @@ void security_compute_xperms_decision(u32 ssid, /** * security_compute_av - Compute access vector decisions. + * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier * @orig_tclass: target security class @@ -1101,7 +1110,8 @@ void security_compute_xperms_decision(u32 ssid, * Compute a set of access vector decisions based on the * SID pair (@ssid, @tsid) for the permissions in @tclass. */ -void security_compute_av(u32 ssid, +void security_compute_av(struct selinux_state *state, + u32 ssid, u32 tsid, u16 orig_tclass, struct av_decision *avd, @@ -1114,10 +1124,10 @@ void security_compute_av(u32 ssid, struct context *scontext = NULL, *tcontext = NULL; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); avd_init(policy, avd); xperms->len = 0; - if (!selinux_initialized()) + if (!selinux_initialized(state)) goto allow; policydb = &policy->policydb; @@ -1159,7 +1169,8 @@ void security_compute_av(u32 ssid, goto out; } -void security_compute_av_user(u32 ssid, +void security_compute_av_user(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd) @@ -1170,9 +1181,9 @@ void security_compute_av_user(u32 ssid, struct context *scontext = NULL, *tcontext = NULL; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); avd_init(policy, avd); - if (!selinux_initialized()) + if (!selinux_initialized(state)) goto allow; policydb = &policy->policydb; @@ -1288,19 +1299,19 @@ static int sidtab_entry_to_string(struct policydb *p, #include "initial_sid_to_string.h" -int security_sidtab_hash_stats(char *page) +int security_sidtab_hash_stats(struct selinux_state *state, char *page) { struct selinux_policy *policy; int rc; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { pr_err("SELinux: %s: called before initial load_policy\n", __func__); return -EINVAL; } rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); rc = sidtab_hash_stats(policy->sidtab, page); rcu_read_unlock(); @@ -1314,7 +1325,8 @@ const char *security_get_initial_sid_context(u32 sid) return initial_sid_to_string[sid]; } -static int security_sid_to_context_core(u32 sid, char **scontext, +static int security_sid_to_context_core(struct selinux_state *state, + u32 sid, char **scontext, u32 *scontext_len, int force, int only_invalid) { @@ -1328,7 +1340,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext, *scontext = NULL; *scontext_len = 0; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { if (sid <= SECINITSID_NUM) { char *scontextp; const char *s; @@ -1360,7 +1372,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext, return -EINVAL; } rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -1388,6 +1400,7 @@ static int security_sid_to_context_core(u32 sid, char **scontext, /** * security_sid_to_context - Obtain a context for a given SID. + * @state: SELinux state * @sid: security identifier, SID * @scontext: security context * @scontext_len: length in bytes @@ -1396,22 +1409,24 @@ static int security_sid_to_context_core(u32 sid, char **scontext, * into a dynamically allocated string of the correct size. Set @scontext * to point to this string and set @scontext_len to the length of the string. */ -int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len) +int security_sid_to_context(struct selinux_state *state, + u32 sid, char **scontext, u32 *scontext_len) { - return security_sid_to_context_core(sid, scontext, + return security_sid_to_context_core(state, sid, scontext, scontext_len, 0, 0); } -int security_sid_to_context_force(u32 sid, +int security_sid_to_context_force(struct selinux_state *state, u32 sid, char **scontext, u32 *scontext_len) { - return security_sid_to_context_core(sid, scontext, + return security_sid_to_context_core(state, sid, scontext, scontext_len, 1, 0); } /** * security_sid_to_context_inval - Obtain a context for a given SID if it * is invalid. + * @state: SELinux state * @sid: security identifier, SID * @scontext: security context * @scontext_len: length in bytes @@ -1422,10 +1437,10 @@ int security_sid_to_context_force(u32 sid, * this string (or NULL if the context is valid) and set @scontext_len to * the length of the string (or 0 if the context is valid). */ -int security_sid_to_context_inval(u32 sid, +int security_sid_to_context_inval(struct selinux_state *state, u32 sid, char **scontext, u32 *scontext_len) { - return security_sid_to_context_core(sid, scontext, + return security_sid_to_context_core(state, sid, scontext, scontext_len, 1, 1); } @@ -1510,7 +1525,8 @@ static int string_to_context_struct(struct policydb *pol, return rc; } -static int security_context_to_sid_core(const char *scontext, u32 scontext_len, +static int security_context_to_sid_core(struct selinux_state *state, + const char *scontext, u32 scontext_len, u32 *sid, u32 def_sid, gfp_t gfp_flags, int force) { @@ -1530,9 +1546,8 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, if (!scontext2) return -ENOMEM; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { u32 i; - for (i = 1; i < SECINITSID_NUM; i++) { const char *s = initial_sid_to_string[i]; @@ -1555,7 +1570,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, } retry: rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; rc = string_to_context_struct(policydb, sidtab, scontext2, @@ -1587,6 +1602,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, /** * security_context_to_sid - Obtain a SID for a given security context. + * @state: SELinux state * @scontext: security context * @scontext_len: length in bytes * @sid: security identifier, SID @@ -1597,16 +1613,18 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient * memory is available, or 0 on success. */ -int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid, +int security_context_to_sid(struct selinux_state *state, + const char *scontext, u32 scontext_len, u32 *sid, gfp_t gfp) { - return security_context_to_sid_core(scontext, scontext_len, + return security_context_to_sid_core(state, scontext, scontext_len, sid, SECSID_NULL, gfp, 0); } -int security_context_str_to_sid(const char *scontext, u32 *sid, gfp_t gfp) +int security_context_str_to_sid(struct selinux_state *state, + const char *scontext, u32 *sid, gfp_t gfp) { - return security_context_to_sid(scontext, strlen(scontext), + return security_context_to_sid(state, scontext, strlen(scontext), sid, gfp); } @@ -1614,6 +1632,7 @@ int security_context_str_to_sid(const char *scontext, u32 *sid, gfp_t gfp) * security_context_to_sid_default - Obtain a SID for a given security context, * falling back to specified default if needed. * + * @state: SELinux state * @scontext: security context * @scontext_len: length in bytes * @sid: security identifier, SID @@ -1629,21 +1648,24 @@ int security_context_str_to_sid(const char *scontext, u32 *sid, gfp_t gfp) * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient * memory is available, or 0 on success. */ -int security_context_to_sid_default(const char *scontext, u32 scontext_len, +int security_context_to_sid_default(struct selinux_state *state, + const char *scontext, u32 scontext_len, u32 *sid, u32 def_sid, gfp_t gfp_flags) { - return security_context_to_sid_core(scontext, scontext_len, + return security_context_to_sid_core(state, scontext, scontext_len, sid, def_sid, gfp_flags, 1); } -int security_context_to_sid_force(const char *scontext, u32 scontext_len, +int security_context_to_sid_force(struct selinux_state *state, + const char *scontext, u32 scontext_len, u32 *sid) { - return security_context_to_sid_core(scontext, scontext_len, + return security_context_to_sid_core(state, scontext, scontext_len, sid, SECSID_NULL, GFP_KERNEL, 1); } static int compute_sid_handle_invalid_context( + struct selinux_state *state, struct selinux_policy *policy, struct sidtab_entry *sentry, struct sidtab_entry *tentry, @@ -1676,7 +1698,7 @@ static int compute_sid_handle_invalid_context( kfree(s); kfree(t); kfree(n); - if (!enforcing_enabled()) + if (!enforcing_enabled(state)) return 0; return -EACCES; } @@ -1711,7 +1733,8 @@ static void filename_compute_type(struct policydb *policydb, } } -static int security_compute_sid(u32 ssid, +static int security_compute_sid(struct selinux_state *state, + u32 ssid, u32 tsid, u16 orig_tclass, u16 specified, @@ -1731,7 +1754,7 @@ static int security_compute_sid(u32 ssid, int rc = 0; bool sock; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { switch (orig_tclass) { case SECCLASS_PROCESS: /* kernel value */ *out_sid = ssid; @@ -1749,7 +1772,7 @@ static int security_compute_sid(u32 ssid, rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); if (kern) { tclass = unmap_class(&policy->map, orig_tclass); @@ -1883,7 +1906,7 @@ static int security_compute_sid(u32 ssid, /* Check the validity of the context. */ if (!policydb_context_isvalid(policydb, &newcontext)) { - rc = compute_sid_handle_invalid_context(policy, sentry, + rc = compute_sid_handle_invalid_context(state, policy, sentry, tentry, tclass, &newcontext); if (rc) @@ -1905,6 +1928,7 @@ static int security_compute_sid(u32 ssid, /** * security_transition_sid - Compute the SID for a new subject/object. + * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class @@ -1917,24 +1941,27 @@ static int security_compute_sid(u32 ssid, * if insufficient memory is available, or %0 if the new SID was * computed successfully. */ -int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, +int security_transition_sid(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, const struct qstr *qstr, u32 *out_sid) { - return security_compute_sid(ssid, tsid, tclass, + return security_compute_sid(state, ssid, tsid, tclass, AVTAB_TRANSITION, qstr ? qstr->name : NULL, out_sid, true); } -int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, +int security_transition_sid_user(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, const char *objname, u32 *out_sid) { - return security_compute_sid(ssid, tsid, tclass, + return security_compute_sid(state, ssid, tsid, tclass, AVTAB_TRANSITION, objname, out_sid, false); } /** * security_member_sid - Compute the SID for member selection. + * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class @@ -1946,18 +1973,20 @@ int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, * if insufficient memory is available, or %0 if the SID was * computed successfully. */ -int security_member_sid(u32 ssid, +int security_member_sid(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, u32 *out_sid) { - return security_compute_sid(ssid, tsid, tclass, + return security_compute_sid(state, ssid, tsid, tclass, AVTAB_MEMBER, NULL, out_sid, false); } /** * security_change_sid - Compute the SID for object relabeling. + * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class @@ -1969,23 +1998,26 @@ int security_member_sid(u32 ssid, * if insufficient memory is available, or %0 if the SID was * computed successfully. */ -int security_change_sid(u32 ssid, +int security_change_sid(struct selinux_state *state, + u32 ssid, u32 tsid, u16 tclass, u32 *out_sid) { - return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL, + return security_compute_sid(state, + ssid, tsid, tclass, AVTAB_CHANGE, NULL, out_sid, false); } static inline int convert_context_handle_invalid_context( + struct selinux_state *state, struct policydb *policydb, struct context *context) { char *s; u32 len; - if (enforcing_enabled()) + if (enforcing_enabled(state)) return -EINVAL; if (!context_struct_to_string(policydb, context, &s, &len)) { @@ -2103,7 +2135,8 @@ int services_convert_context(struct convert_context_args *args, /* Check the validity of the new context. */ if (!policydb_context_isvalid(args->newp, newc)) { - rc = convert_context_handle_invalid_context(args->oldp, oldc); + rc = convert_context_handle_invalid_context(args->state, + args->oldp, oldc); if (rc) goto bad; } @@ -2122,7 +2155,8 @@ int services_convert_context(struct convert_context_args *args, return 0; } -static void security_load_policycaps(struct selinux_policy *policy) +static void security_load_policycaps(struct selinux_state *state, + struct selinux_policy *policy) { struct policydb *p; unsigned int i; @@ -2130,8 +2164,8 @@ static void security_load_policycaps(struct selinux_policy *policy) p = &policy->policydb; - for (i = 0; i < ARRAY_SIZE(selinux_state.policycap); i++) - WRITE_ONCE(selinux_state.policycap[i], + for (i = 0; i < ARRAY_SIZE(state->policycap); i++) + WRITE_ONCE(state->policycap[i], ebitmap_get_bit(&p->policycaps, i)); for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++) @@ -2167,9 +2201,9 @@ static void selinux_policy_cond_free(struct selinux_policy *policy) kfree(policy); } -void selinux_policy_cancel(struct selinux_load_state *load_state) +void selinux_policy_cancel(struct selinux_state *state, + struct selinux_load_state *load_state) { - struct selinux_state *state = &selinux_state; struct selinux_policy *oldpolicy; oldpolicy = rcu_dereference_protected(state->policy, @@ -2180,20 +2214,21 @@ void selinux_policy_cancel(struct selinux_load_state *load_state) kfree(load_state->convert_data); } -static void selinux_notify_policy_change(u32 seqno) +static void selinux_notify_policy_change(struct selinux_state *state, + u32 seqno) { /* Flush external caches and notify userspace of policy load */ - avc_ss_reset(seqno); + avc_ss_reset(state->avc, seqno); selnl_notify_policyload(seqno); - selinux_status_update_policyload(seqno); + selinux_status_update_policyload(state, seqno); selinux_netlbl_cache_invalidate(); selinux_xfrm_notify_policyload(); - selinux_ima_measure_state_locked(); + selinux_ima_measure_state_locked(state); } -void selinux_policy_commit(struct selinux_load_state *load_state) +void selinux_policy_commit(struct selinux_state *state, + struct selinux_load_state *load_state) { - struct selinux_state *state = &selinux_state; struct selinux_policy *oldpolicy, *newpolicy = load_state->policy; unsigned long flags; u32 seqno; @@ -2226,15 +2261,15 @@ void selinux_policy_commit(struct selinux_load_state *load_state) } /* Load the policycaps from the new policy */ - security_load_policycaps(newpolicy); + security_load_policycaps(state, newpolicy); - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { /* * After first policy load, the security server is * marked as initialized and ready to handle requests and * any objects created prior to policy load are then labeled. */ - selinux_mark_initialized(); + selinux_mark_initialized(state); selinux_complete_init(); } @@ -2244,11 +2279,12 @@ void selinux_policy_commit(struct selinux_load_state *load_state) kfree(load_state->convert_data); /* Notify others of the policy change */ - selinux_notify_policy_change(seqno); + selinux_notify_policy_change(state, seqno); } /** * security_load_policy - Load a security policy configuration. + * @state: SELinux state * @data: binary policy data * @len: length of data in bytes * @load_state: policy load state @@ -2258,10 +2294,9 @@ void selinux_policy_commit(struct selinux_load_state *load_state) * This function will flush the access vector cache after * loading the new policy. */ -int security_load_policy(void *data, size_t len, +int security_load_policy(struct selinux_state *state, void *data, size_t len, struct selinux_load_state *load_state) { - struct selinux_state *state = &selinux_state; struct selinux_policy *newpolicy, *oldpolicy; struct selinux_policy_convert_data *convert_data; int rc = 0; @@ -2293,7 +2328,7 @@ int security_load_policy(void *data, size_t len, goto err_mapping; } - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { /* First policy load, so no need to preserve state from old policy */ load_state->policy = newpolicy; load_state->convert_data = NULL; @@ -2321,6 +2356,7 @@ int security_load_policy(void *data, size_t len, goto err_free_isids; } + convert_data->args.state = state; convert_data->args.oldp = &oldpolicy->policydb; convert_data->args.newp = &newpolicy->policydb; @@ -2394,11 +2430,13 @@ static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c, /** * security_port_sid - Obtain the SID for a port. + * @state: SELinux state * @protocol: protocol number * @port: port number * @out_sid: security identifier */ -int security_port_sid(u8 protocol, u16 port, u32 *out_sid) +int security_port_sid(struct selinux_state *state, + u8 protocol, u16 port, u32 *out_sid) { struct selinux_policy *policy; struct policydb *policydb; @@ -2406,7 +2444,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid) struct ocontext *c; int rc; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { *out_sid = SECINITSID_PORT; return 0; } @@ -2414,7 +2452,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid) retry: rc = 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -2446,11 +2484,13 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid) /** * security_ib_pkey_sid - Obtain the SID for a pkey. + * @state: SELinux state * @subnet_prefix: Subnet Prefix * @pkey_num: pkey number * @out_sid: security identifier */ -int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid) +int security_ib_pkey_sid(struct selinux_state *state, + u64 subnet_prefix, u16 pkey_num, u32 *out_sid) { struct selinux_policy *policy; struct policydb *policydb; @@ -2458,7 +2498,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid) struct ocontext *c; int rc; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { *out_sid = SECINITSID_UNLABELED; return 0; } @@ -2466,7 +2506,7 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid) retry: rc = 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -2498,11 +2538,13 @@ int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid) /** * security_ib_endport_sid - Obtain the SID for a subnet management interface. + * @state: SELinux state * @dev_name: device name * @port_num: port number * @out_sid: security identifier */ -int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid) +int security_ib_endport_sid(struct selinux_state *state, + const char *dev_name, u8 port_num, u32 *out_sid) { struct selinux_policy *policy; struct policydb *policydb; @@ -2510,7 +2552,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid) struct ocontext *c; int rc; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { *out_sid = SECINITSID_UNLABELED; return 0; } @@ -2518,7 +2560,7 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid) retry: rc = 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -2551,10 +2593,12 @@ int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid) /** * security_netif_sid - Obtain the SID for a network interface. + * @state: SELinux state * @name: interface name * @if_sid: interface SID */ -int security_netif_sid(char *name, u32 *if_sid) +int security_netif_sid(struct selinux_state *state, + char *name, u32 *if_sid) { struct selinux_policy *policy; struct policydb *policydb; @@ -2562,7 +2606,7 @@ int security_netif_sid(char *name, u32 *if_sid) int rc; struct ocontext *c; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { *if_sid = SECINITSID_NETIF; return 0; } @@ -2570,7 +2614,7 @@ int security_netif_sid(char *name, u32 *if_sid) retry: rc = 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -2612,12 +2656,14 @@ static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask) /** * security_node_sid - Obtain the SID for a node (host). + * @state: SELinux state * @domain: communication domain aka address family * @addrp: address * @addrlen: address length in bytes * @out_sid: security identifier */ -int security_node_sid(u16 domain, +int security_node_sid(struct selinux_state *state, + u16 domain, void *addrp, u32 addrlen, u32 *out_sid) @@ -2628,14 +2674,14 @@ int security_node_sid(u16 domain, int rc; struct ocontext *c; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { *out_sid = SECINITSID_NODE; return 0; } retry: rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -2699,6 +2745,7 @@ int security_node_sid(u16 domain, /** * security_get_user_sids - Obtain reachable SIDs for a user. + * @state: SELinux state * @fromsid: starting SID * @username: username * @sids: array of reachable SIDs for user @@ -2711,7 +2758,8 @@ int security_node_sid(u16 domain, * number of elements in the array. */ -int security_get_user_sids(u32 fromsid, +int security_get_user_sids(struct selinux_state *state, + u32 fromsid, char *username, u32 **sids, u32 *nel) @@ -2730,7 +2778,7 @@ int security_get_user_sids(u32 fromsid, *sids = NULL; *nel = 0; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; mysids = kcalloc(maxnel, sizeof(*mysids), GFP_KERNEL); @@ -2740,7 +2788,7 @@ int security_get_user_sids(u32 fromsid, retry: mynel = 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -2806,7 +2854,8 @@ int security_get_user_sids(u32 fromsid, } for (i = 0, j = 0; i < mynel; i++) { struct av_decision dummy_avd; - rc = avc_has_perm_noaudit(fromsid, mysids[i], + rc = avc_has_perm_noaudit(state, + fromsid, mysids[i], SECCLASS_PROCESS, /* kernel value */ PROCESS__TRANSITION, AVC_STRICT, &dummy_avd); @@ -2878,6 +2927,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, /** * security_genfs_sid - Obtain a SID for a file in a filesystem + * @state: SELinux state * @fstype: filesystem type * @path: path from root of mount * @orig_sclass: file security class @@ -2886,7 +2936,8 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, * Acquire policy_rwlock before calling __security_genfs_sid() and release * it afterward. */ -int security_genfs_sid(const char *fstype, +int security_genfs_sid(struct selinux_state *state, + const char *fstype, const char *path, u16 orig_sclass, u32 *sid) @@ -2894,14 +2945,14 @@ int security_genfs_sid(const char *fstype, struct selinux_policy *policy; int retval; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { *sid = SECINITSID_UNLABELED; return 0; } do { rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); retval = __security_genfs_sid(policy, fstype, path, orig_sclass, sid); rcu_read_unlock(); @@ -2921,9 +2972,10 @@ int selinux_policy_genfs_sid(struct selinux_policy *policy, /** * security_fs_use - Determine how to handle labeling for a filesystem. + * @state: SELinux state * @sb: superblock in question */ -int security_fs_use(struct super_block *sb) +int security_fs_use(struct selinux_state *state, struct super_block *sb) { struct selinux_policy *policy; struct policydb *policydb; @@ -2933,7 +2985,7 @@ int security_fs_use(struct super_block *sb) struct superblock_security_struct *sbsec = selinux_superblock(sb); const char *fstype = sb->s_type->name; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { sbsec->behavior = SECURITY_FS_USE_NONE; sbsec->sid = SECINITSID_UNLABELED; return 0; @@ -2941,7 +2993,7 @@ int security_fs_use(struct super_block *sb) retry: rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -3034,14 +3086,13 @@ int security_get_bools(struct selinux_policy *policy, } -int security_set_bools(u32 len, int *values) +int security_set_bools(struct selinux_state *state, u32 len, int *values) { - struct selinux_state *state = &selinux_state; struct selinux_policy *newpolicy, *oldpolicy; int rc; u32 i, seqno = 0; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return -EINVAL; oldpolicy = rcu_dereference_protected(state->policy, @@ -3102,22 +3153,23 @@ int security_set_bools(u32 len, int *values) selinux_policy_cond_free(oldpolicy); /* Notify others of the policy change */ - selinux_notify_policy_change(seqno); + selinux_notify_policy_change(state, seqno); return 0; } -int security_get_bool_value(u32 index) +int security_get_bool_value(struct selinux_state *state, + u32 index) { struct selinux_policy *policy; struct policydb *policydb; int rc; u32 len; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; rc = -EFAULT; @@ -3164,7 +3216,8 @@ static int security_preserve_bools(struct selinux_policy *oldpolicy, * security_sid_mls_copy() - computes a new sid based on the given * sid and the mls portion of mls_sid. */ -int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) +int security_sid_mls_copy(struct selinux_state *state, + u32 sid, u32 mls_sid, u32 *new_sid) { struct selinux_policy *policy; struct policydb *policydb; @@ -3176,7 +3229,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) u32 len; int rc; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { *new_sid = sid; return 0; } @@ -3186,7 +3239,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) context_init(&newcon); rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -3220,7 +3273,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) /* Check the validity of the new context. */ if (!policydb_context_isvalid(policydb, &newcon)) { - rc = convert_context_handle_invalid_context(policydb, + rc = convert_context_handle_invalid_context(state, policydb, &newcon); if (rc) { if (!context_struct_to_string(policydb, &newcon, &s, @@ -3254,6 +3307,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) /** * security_net_peersid_resolve - Compare and resolve two network peer SIDs + * @state: SELinux state * @nlbl_sid: NetLabel SID * @nlbl_type: NetLabel labeling protocol type * @xfrm_sid: XFRM SID @@ -3273,7 +3327,8 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) * multiple, inconsistent labels | - | SECSID_NULL * */ -int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, +int security_net_peersid_resolve(struct selinux_state *state, + u32 nlbl_sid, u32 nlbl_type, u32 xfrm_sid, u32 *peer_sid) { @@ -3301,11 +3356,11 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, return 0; } - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -3448,31 +3503,31 @@ int security_get_permissions(struct selinux_policy *policy, return rc; } -int security_get_reject_unknown(void) +int security_get_reject_unknown(struct selinux_state *state) { struct selinux_policy *policy; int value; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); value = policy->policydb.reject_unknown; rcu_read_unlock(); return value; } -int security_get_allow_unknown(void) +int security_get_allow_unknown(struct selinux_state *state) { struct selinux_policy *policy; int value; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); value = policy->policydb.allow_unknown; rcu_read_unlock(); return value; @@ -3480,6 +3535,7 @@ int security_get_allow_unknown(void) /** * security_policycap_supported - Check for a specific policy capability + * @state: SELinux state * @req_cap: capability * * Description: @@ -3488,16 +3544,17 @@ int security_get_allow_unknown(void) * supported, false (0) if it isn't supported. * */ -int security_policycap_supported(unsigned int req_cap) +int security_policycap_supported(struct selinux_state *state, + unsigned int req_cap) { struct selinux_policy *policy; int rc; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); rc = ebitmap_get_bit(&policy->policydb.policycaps, req_cap); rcu_read_unlock(); @@ -3534,7 +3591,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, *rule = NULL; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return -EOPNOTSUPP; switch (field) { @@ -3659,7 +3716,7 @@ int selinux_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *vru return -ENOENT; } - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); @@ -3812,6 +3869,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, /** * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID + * @state: SELinux state * @secattr: the NetLabel packet security attributes * @sid: the SELinux SID * @@ -3825,7 +3883,8 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, * failure. * */ -int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, +int security_netlbl_secattr_to_sid(struct selinux_state *state, + struct netlbl_lsm_secattr *secattr, u32 *sid) { struct selinux_policy *policy; @@ -3835,7 +3894,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, struct context *ctx; struct context ctx_new; - if (!selinux_initialized()) { + if (!selinux_initialized(state)) { *sid = SECSID_NULL; return 0; } @@ -3843,7 +3902,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, retry: rc = 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; sidtab = policy->sidtab; @@ -3893,6 +3952,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, /** * security_netlbl_sid_to_secattr - Convert a SELinux SID to a NetLabel secattr + * @state: SELinux state * @sid: the SELinux SID * @secattr: the NetLabel packet security attributes * @@ -3901,18 +3961,19 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, * Returns zero on success, negative values on failure. * */ -int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) +int security_netlbl_sid_to_secattr(struct selinux_state *state, + u32 sid, struct netlbl_lsm_secattr *secattr) { struct selinux_policy *policy; struct policydb *policydb; int rc; struct context *ctx; - if (!selinux_initialized()) + if (!selinux_initialized(state)) return 0; rcu_read_lock(); - policy = rcu_dereference(selinux_state.policy); + policy = rcu_dereference(state->policy); policydb = &policy->policydb; rc = -ENOENT; @@ -3962,13 +4023,14 @@ static int __security_read_policy(struct selinux_policy *policy, /** * security_read_policy - read the policy. + * @state: selinux_state * @data: binary policy data * @len: length of data in bytes * */ -int security_read_policy(void **data, size_t *len) +int security_read_policy(struct selinux_state *state, + void **data, size_t *len) { - struct selinux_state *state = &selinux_state; struct selinux_policy *policy; policy = rcu_dereference_protected( @@ -3986,6 +4048,7 @@ int security_read_policy(void **data, size_t *len) /** * security_read_state_kernel - read the policy. + * @state: selinux_state * @data: binary policy data * @len: length of data in bytes * @@ -3995,10 +4058,10 @@ int security_read_policy(void **data, size_t *len) * * This function must be called with policy_mutex held. */ -int security_read_state_kernel(void **data, size_t *len) +int security_read_state_kernel(struct selinux_state *state, + void **data, size_t *len) { int err; - struct selinux_state *state = &selinux_state; struct selinux_policy *policy; policy = rcu_dereference_protected( diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index 93358e7a649c..8696f9300529 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h @@ -31,6 +31,7 @@ struct selinux_policy { } __randomize_layout; struct convert_context_args { + struct selinux_state *state; struct policydb *oldp; struct policydb *newp; }; diff --git a/security/selinux/status.c b/security/selinux/status.c index dffca22ce6f7..e9ba1dae06e1 100644 --- a/security/selinux/status.c +++ b/security/selinux/status.c @@ -39,21 +39,21 @@ * It returns a reference to selinux_status_page. If the status page is * not allocated yet, it also tries to allocate it at the first time. */ -struct page *selinux_kernel_status_page(void) +struct page *selinux_kernel_status_page(struct selinux_state *state) { struct selinux_kernel_status *status; struct page *result = NULL; - mutex_lock(&selinux_state.status_lock); - if (!selinux_state.status_page) { - selinux_state.status_page = alloc_page(GFP_KERNEL|__GFP_ZERO); + mutex_lock(&state->status_lock); + if (!state->status_page) { + state->status_page = alloc_page(GFP_KERNEL|__GFP_ZERO); - if (selinux_state.status_page) { - status = page_address(selinux_state.status_page); + if (state->status_page) { + status = page_address(state->status_page); status->version = SELINUX_KERNEL_STATUS_VERSION; status->sequence = 0; - status->enforcing = enforcing_enabled(); + status->enforcing = enforcing_enabled(state); /* * NOTE: the next policyload event shall set * a positive value on the status->policyload, @@ -62,11 +62,11 @@ struct page *selinux_kernel_status_page(void) */ status->policyload = 0; status->deny_unknown = - !security_get_allow_unknown(); + !security_get_allow_unknown(state); } } - result = selinux_state.status_page; - mutex_unlock(&selinux_state.status_lock); + result = state->status_page; + mutex_unlock(&state->status_lock); return result; } @@ -76,13 +76,14 @@ struct page *selinux_kernel_status_page(void) * * It updates status of the current enforcing/permissive mode. */ -void selinux_status_update_setenforce(bool enforcing) +void selinux_status_update_setenforce(struct selinux_state *state, + bool enforcing) { struct selinux_kernel_status *status; - mutex_lock(&selinux_state.status_lock); - if (selinux_state.status_page) { - status = page_address(selinux_state.status_page); + mutex_lock(&state->status_lock); + if (state->status_page) { + status = page_address(state->status_page); status->sequence++; smp_wmb(); @@ -92,7 +93,7 @@ void selinux_status_update_setenforce(bool enforcing) smp_wmb(); status->sequence++; } - mutex_unlock(&selinux_state.status_lock); + mutex_unlock(&state->status_lock); } /* @@ -101,22 +102,23 @@ void selinux_status_update_setenforce(bool enforcing) * It updates status of the times of policy reloaded, and current * setting of deny_unknown. */ -void selinux_status_update_policyload(u32 seqno) +void selinux_status_update_policyload(struct selinux_state *state, + u32 seqno) { struct selinux_kernel_status *status; - mutex_lock(&selinux_state.status_lock); - if (selinux_state.status_page) { - status = page_address(selinux_state.status_page); + mutex_lock(&state->status_lock); + if (state->status_page) { + status = page_address(state->status_page); status->sequence++; smp_wmb(); status->policyload = seqno; - status->deny_unknown = !security_get_allow_unknown(); + status->deny_unknown = !security_get_allow_unknown(state); smp_wmb(); status->sequence++; } - mutex_unlock(&selinux_state.status_lock); + mutex_unlock(&state->status_lock); } diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 90ec4ef1b082..83a94ca4d738 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -97,12 +97,13 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, ctx->ctx_len = str_len; memcpy(ctx->ctx_str, &uctx[1], str_len); ctx->ctx_str[str_len] = '\0'; - rc = security_context_to_sid(ctx->ctx_str, str_len, + rc = security_context_to_sid(&selinux_state, ctx->ctx_str, str_len, &ctx->ctx_sid, gfp); if (rc) goto err; - rc = avc_has_perm(current_sid(), ctx->ctx_sid, + rc = avc_has_perm(&selinux_state, + current_sid(), ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); if (rc) goto err; @@ -136,7 +137,8 @@ static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx) if (!ctx) return 0; - return avc_has_perm(current_sid(), ctx->ctx_sid, + return avc_has_perm(&selinux_state, + current_sid(), ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); } @@ -158,7 +160,8 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) if (!selinux_authorizable_ctx(ctx)) return -EINVAL; - rc = avc_has_perm(fl_secid, ctx->ctx_sid, + rc = avc_has_perm(&selinux_state, + fl_secid, ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL); return (rc == -EACCES ? -ESRCH : rc); } @@ -199,7 +202,7 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, /* We don't need a separate SA Vs. policy polmatch check since the SA * is now of the same label as the flow and a flow Vs. policy polmatch * check had already happened in selinux_xfrm_policy_lookup() above. */ - return (avc_has_perm(flic_sid, state_sid, + return (avc_has_perm(&selinux_state, flic_sid, state_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, NULL) ? 0 : 1); } @@ -349,7 +352,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, if (secid == 0) return -EINVAL; - rc = security_sid_to_context(secid, &ctx_str, + rc = security_sid_to_context(&selinux_state, secid, &ctx_str, &str_len); if (rc) return rc; @@ -418,7 +421,8 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, /* This check even when there's no association involved is intended, * according to Trent Jaeger, to make sure a process can't engage in * non-IPsec communication unless explicitly allowed by policy. */ - return avc_has_perm(sk_sid, peer_sid, + return avc_has_perm(&selinux_state, + sk_sid, peer_sid, SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad); } @@ -461,6 +465,6 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, /* This check even when there's no association involved is intended, * according to Trent Jaeger, to make sure a process can't engage in * non-IPsec communication unless explicitly allowed by policy. */ - return avc_has_perm(sk_sid, SECINITSID_UNLABELED, + return avc_has_perm(&selinux_state, sk_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad); } From patchwork Thu Jan 2 16:44:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924619 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f178.google.com (mail-qt1-f178.google.com [209.85.160.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2F1C65674E for ; Thu, 2 Jan 2025 16:45:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836343; cv=none; b=jP7GuSCLHbmcfpmgA2akqklXqiEJEO4sbUjlBTtzAiMPf5Abj47sRvj9lhoE5M3YWBnvI76jkhroVlmuWvbbvIWPHSTHaNF4kKUv9D4cbEeQecrS9cTJj3GIyAmN/UJtm76GmRAwseXMNxRO9UHdiW2EUVpLdK4j5Weera87GVc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836343; c=relaxed/simple; bh=ddt75JMWirLWecqKjnS76ZO08C4RC9X45567CB+EL0E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gtleRL+LJhSJep8YTAZWV+R6WhyAGVl0EUFiBHtUoZFgP8PZYIIFptxCTqc+rY3gZJbEa9pk8xFzR7Eb7J9eruLYTtHpqeaySOAJokjaNhsoFMyg9YX0LxY8krfwhV57GIS+VTYigLkeD31V2uwu0tgst9hIANgErlQ81pEuJWk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Ioy+6crp; arc=none smtp.client-ip=209.85.160.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ioy+6crp" Received: by mail-qt1-f178.google.com with SMTP id d75a77b69052e-46741855f9bso103437251cf.2 for ; Thu, 02 Jan 2025 08:45:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836335; x=1736441135; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tNGFBcaEy7n9Hg2LBf77IaXrRV+YkP8AoVkuchbwl2M=; b=Ioy+6crpcn6f44XfzL5Io0a2q6PADd/9IjVvmLX6xwP6lBQr56mnoQwOOc8fo/kJFg qt3uCCD1iHAP3PWylSA5oaxtzouYWR2/T6Dk/lrzcqem4b7pKbCy29xdFkzIX87j4e0j jmYjd0EeHnIXY+G/bglEvIrG/WdYbVk0wb2E8AZsIWFKjGzQynlwKYSYBArPnPjK5xi+ gpQIKGg3zHf3n60SenpYrlbww5uhdBV6LX3hFNch1QM5cQFMLfejh5wmtD+7USRU6AjT 0b7pZJiel0Am9rL0y2RxlfUtuFuxkd7sKVXXZQgA8VpmSIjnEnTxWpW2nTxoC1F8s6d3 TF3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836335; x=1736441135; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tNGFBcaEy7n9Hg2LBf77IaXrRV+YkP8AoVkuchbwl2M=; b=pH+aCuKgpAqXl6WcZxYmsJR7uE4CapKBcr2ZBWFlNhp2VFruUx7Efxjjf/AaKvu76O q5ww5ETGoRqS24hsyc4INfdArCWAnKfgV7mxi/OAuUEQbENAp+DQIAIkmQ7ReeCVjIId XdPH3CSsbt+JvuBHwioHW0aIhkY0vxJNh3yCIWjDs7pCgFxifz5bHQ5NGWvmHnjg6tgO j12oFZf+ALFPUMKlEbpC2Mmq5EtevWXkSZODKCJpOXUcBhf2K/0zor+HFL0ct4Y9KYQ4 qd8BJT1XzP9aBxZ6hosEO5zkT3ASW0ZDeM7ZCMch70j6M3eFt6fTx3Kj8jJAFJWtbjTD sY5A== X-Gm-Message-State: AOJu0YzeNNb2b55B4W5181VCrO2pYtNcG4eJLJDc5gPtCD6ErgXDN/Pu w4rD/xZmvToyfUtTbB/v0806o89i/AN3UM8IA8mtnSE3DsVS5E8u3M4v/w== X-Gm-Gg: ASbGncsHxZmXzrcjonlXsWpgZdozaziAfGk95oSA6XjIARggTn4iyKOwQuvdaOQsGZB PQDvJem+zs/p2ogR5NWRJZKLNhTvy1UFHAUwhyblcgCcoWURQhFN/lO6xqNB7ITxQh681cGFSTN 06KagDl2izRJNHEB4Cbn4ekL6utKGvDA8CmgzxURPhdsF7ffkeZBOxgmIE8FwhOZBimgRvNTatV ovCo/FN3vRFF/3qkEApRrgHL//v9kJoGRpcR/G1klmKX+xvTVgRKVwpoY1B4nil6+80iqwNSApG 9u3ZFgqmcKpuJZ2xjQkh6NofaF/mS0GDNVnutj2biMv8IIvWwqJLlx8lT5PbhpgU7TelvQ== X-Google-Smtp-Source: AGHT+IET3KZbI7lJqnLcgcFnJFlHiwfCxkAw7hzOqy9Qm9YxyZ7LCnntkP+ZSqDSTpIjOU+atCNVig== X-Received: by 2002:ac8:5ac6:0:b0:467:6692:c18b with SMTP id d75a77b69052e-46a4a8b303bmr760353301cf.5.1735836334050; Thu, 02 Jan 2025 08:45:34 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.33 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:33 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 02/44] selinux: introduce current_selinux_state Date: Thu, 2 Jan 2025 11:44:27 -0500 Message-Id: <20250102164509.25606-3-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Rename selinux_state to init_selinux_state, make it static, and introduce a current_selinux_state pointer initialized to it that can be used everywhere we were previously directly referencing selinux_state. This is in preparation for future changes where multiple selinux states (aka namespaces) will be supported and current_selinux_state will refer to the correct one for the current process. Note that passing the current selinux state is not correct for all hooks; some hooks will need to be adjusted to pass the selinux state associated with an open file, a network namespace or socket, etc, since not all hooks are invoked in process context and some hooks operate in the context of a cred that may differ from current's cred. Fixing all of these cases is left to future changes, once we introduce the support for multiple selinux namespaces. This change by itself should have no effect on SELinux behavior or APIs (userspace or LSM). Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 413 ++++++++++++++-------------- security/selinux/ibpkey.c | 2 +- security/selinux/include/security.h | 32 ++- security/selinux/netif.c | 2 +- security/selinux/netlabel.c | 12 +- security/selinux/netnode.c | 4 +- security/selinux/netport.c | 2 +- security/selinux/selinuxfs.c | 36 +-- security/selinux/ss/services.c | 4 +- security/selinux/xfrm.c | 16 +- 10 files changed, 267 insertions(+), 256 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ec8e746ec67e..400e4dec90a5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -108,7 +108,8 @@ #define SELINUX_INODE_INIT_XATTRS 1 -struct selinux_state selinux_state; +static struct selinux_state init_selinux_state; +struct selinux_state *current_selinux_state; /* SECMARK reference count */ static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); @@ -287,7 +288,7 @@ static int __inode_security_revalidate(struct inode *inode, * inode_doinit_with_dentry() will recheck with * isec->lock held. */ - if (selinux_initialized(&selinux_state) && + if (selinux_initialized(current_selinux_state) && data_race(isec->initialized != LABEL_INITIALIZED)) { if (!may_sleep) return -ECHILD; @@ -433,13 +434,13 @@ static int may_context_mount_sb_relabel(u32 sid, const struct task_security_struct *tsec = selinux_cred(cred); int rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, tsec->sid, sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, NULL); return rc; @@ -451,13 +452,13 @@ static int may_context_mount_inode_relabel(u32 sid, { const struct task_security_struct *tsec = selinux_cred(cred); int rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, NULL); return rc; @@ -541,7 +542,7 @@ static int sb_check_xattr_support(struct super_block *sb) fallback: /* No xattr support - try to fallback to genfs if possible. */ - rc = security_genfs_sid(&selinux_state, sb->s_type->name, "/", + rc = security_genfs_sid(current_selinux_state, sb->s_type->name, "/", SECCLASS_DIR, &sid); if (rc) return -EOPNOTSUPP; @@ -652,7 +653,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, mutex_lock(&sbsec->lock); - if (!selinux_initialized(&selinux_state)) { + if (!selinux_initialized(current_selinux_state)) { if (!opts) { /* Defer initialization until selinux_complete_init, after the initial policy is loaded and the security @@ -751,7 +752,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, * Determine the labeling behavior to use for this * filesystem type. */ - rc = security_fs_use(&selinux_state, sb); + rc = security_fs_use(current_selinux_state, sb); if (rc) { pr_warn("%s: security_fs_use(%s) returned %d\n", __func__, sb->s_type->name, rc); @@ -776,7 +777,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, } if (sbsec->behavior == SECURITY_FS_USE_XATTR) { sbsec->behavior = SECURITY_FS_USE_MNTPOINT; - rc = security_transition_sid(&selinux_state, + rc = security_transition_sid(current_selinux_state, current_sid(), current_sid(), SECCLASS_FILE, NULL, @@ -935,7 +936,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, * if the parent was able to be mounted it clearly had no special lsm * mount options. thus we can safely deal with this superblock later */ - if (!selinux_initialized(&selinux_state)) { + if (!selinux_initialized(current_selinux_state)) { if (kern_flags & SECURITY_LSM_NATIVE_LABELS) { newsbsec->flags |= SE_SBNATIVE; *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS; @@ -962,7 +963,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, if (newsbsec->behavior == SECURITY_FS_USE_NATIVE && !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) { - rc = security_fs_use(&selinux_state, newsb); + rc = security_fs_use(current_selinux_state, newsb); if (rc) goto out; } @@ -1011,7 +1012,7 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts) if (!s) return -EINVAL; - if (!selinux_initialized(&selinux_state)) { + if (!selinux_initialized(current_selinux_state)) { pr_warn("SELinux: Unable to set superblock options before the security server is initialized\n"); return -EINVAL; } @@ -1048,7 +1049,8 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts) WARN_ON(1); return -EINVAL; } - rc = security_context_str_to_sid(&selinux_state, s, dst_sid, GFP_KERNEL); + rc = security_context_str_to_sid(current_selinux_state, s, dst_sid, + GFP_KERNEL); if (rc) pr_warn("SELinux: security_context_str_to_sid (%s) failed with errno=%d\n", s, rc); @@ -1065,7 +1067,7 @@ static int show_sid(struct seq_file *m, u32 sid) u32 len; int rc; - rc = security_sid_to_context(&selinux_state, sid, + rc = security_sid_to_context(current_selinux_state, sid, &context, &len); if (!rc) { bool has_comma = strchr(context, ','); @@ -1089,7 +1091,7 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) if (!(sbsec->flags & SE_SBINITIALIZED)) return 0; - if (!selinux_initialized(&selinux_state)) + if (!selinux_initialized(current_selinux_state)) return 0; if (sbsec->flags & FSCONTEXT_MNT) { @@ -1343,7 +1345,7 @@ static int selinux_genfs_get_sid(struct dentry *dentry, path++; } } - rc = security_genfs_sid(&selinux_state, sb->s_type->name, + rc = security_genfs_sid(current_selinux_state, sb->s_type->name, path, tclass, sid); if (rc == -ENOENT) { /* No match in policy, mark as unlabeled. */ @@ -1398,8 +1400,8 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry, return 0; } - rc = security_context_to_sid_default(&selinux_state, context, rc, sid, - def_sid, GFP_NOFS); + rc = security_context_to_sid_default(current_selinux_state, context, rc, + sid, def_sid, GFP_NOFS); if (rc) { char *dev = inode->i_sb->s_id; unsigned long ino = inode->i_ino; @@ -1508,7 +1510,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent sid = sbsec->sid; /* Try to obtain a transition SID. */ - rc = security_transition_sid(&selinux_state, task_sid, sid, + rc = security_transition_sid(current_selinux_state, task_sid, sid, sclass, NULL, &sid); if (rc) goto out; @@ -1653,10 +1655,10 @@ static int cred_has_capability(const struct cred *cred, return -EINVAL; } - rc = avc_has_perm_noaudit(&selinux_state, + rc = avc_has_perm_noaudit(current_selinux_state, sid, sid, sclass, av, 0, &avd); if (!(opts & CAP_OPT_NOAUDIT)) { - int rc2 = avc_audit(&selinux_state, + int rc2 = avc_audit(current_selinux_state, sid, sid, sclass, av, &avd, rc, &ad); if (rc2) return rc2; @@ -1681,7 +1683,7 @@ static int inode_has_perm(const struct cred *cred, sid = cred_sid(cred); isec = selinux_inode(inode); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, isec->sclass, perms, adp); } @@ -1755,7 +1757,7 @@ static int file_has_perm(const struct cred *cred, ad.u.file = file; if (sid != fsec->sid) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, fsec->sid, SECCLASS_FD, FD__USE, @@ -1799,7 +1801,7 @@ selinux_determine_inode_label(const struct task_security_struct *tsec, *_new_isid = tsec->create_sid; } else { const struct inode_security_struct *dsec = inode_security(dir); - return security_transition_sid(&selinux_state, tsec->sid, + return security_transition_sid(current_selinux_state, tsec->sid, dsec->sid, tclass, name, _new_isid); } @@ -1827,7 +1829,7 @@ static int may_create(struct inode *dir, ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = dentry; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, dsec->sid, SECCLASS_DIR, DIR__ADD_NAME | DIR__SEARCH, &ad); @@ -1839,12 +1841,12 @@ static int may_create(struct inode *dir, if (rc) return rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, newsid, tclass, FILE__CREATE, &ad); if (rc) return rc; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, newsid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, &ad); @@ -1874,7 +1876,7 @@ static int may_link(struct inode *dir, av = DIR__SEARCH; av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, dsec->sid, SECCLASS_DIR, av, &ad); if (rc) return rc; @@ -1895,7 +1897,7 @@ static int may_link(struct inode *dir, return 0; } - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, isec->sid, isec->sclass, av, &ad); return rc; } @@ -1920,18 +1922,18 @@ static inline int may_rename(struct inode *old_dir, ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = old_dentry; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, old_dsec->sid, SECCLASS_DIR, DIR__REMOVE_NAME | DIR__SEARCH, &ad); if (rc) return rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, old_isec->sid, old_isec->sclass, FILE__RENAME, &ad); if (rc) return rc; if (old_is_dir && new_dir != old_dir) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, old_isec->sid, old_isec->sclass, DIR__REPARENT, &ad); if (rc) @@ -1942,14 +1944,14 @@ static inline int may_rename(struct inode *old_dir, av = DIR__ADD_NAME | DIR__SEARCH; if (d_is_positive(new_dentry)) av |= DIR__REMOVE_NAME; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, new_dsec->sid, SECCLASS_DIR, av, &ad); if (rc) return rc; if (d_is_positive(new_dentry)) { new_isec = backing_inode_security(new_dentry); new_is_dir = d_is_dir(new_dentry); - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, new_isec->sid, new_isec->sclass, (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad); @@ -1970,7 +1972,7 @@ static int superblock_has_perm(const struct cred *cred, u32 sid = cred_sid(cred); sbsec = selinux_superblock(sb); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); } @@ -2045,7 +2047,7 @@ static inline u32 open_file_to_av(struct file *file) static int selinux_binder_set_context_mgr(const struct cred *mgr) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), cred_sid(mgr), SECCLASS_BINDER, BINDER__SET_CONTEXT_MGR, NULL); } @@ -2059,21 +2061,21 @@ static int selinux_binder_transaction(const struct cred *from, int rc; if (mysid != fromsid) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, mysid, fromsid, SECCLASS_BINDER, BINDER__IMPERSONATE, NULL); if (rc) return rc; } - return avc_has_perm(&selinux_state, fromsid, tosid, + return avc_has_perm(current_selinux_state, fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, NULL); } static int selinux_binder_transfer_binder(const struct cred *from, const struct cred *to) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, cred_sid(from), cred_sid(to), SECCLASS_BINDER, BINDER__TRANSFER, NULL); @@ -2094,7 +2096,7 @@ static int selinux_binder_transfer_file(const struct cred *from, ad.u.path = file->f_path; if (sid != fsec->sid) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, fsec->sid, SECCLASS_FD, FD__USE, @@ -2113,7 +2115,7 @@ static int selinux_binder_transfer_file(const struct cred *from, return 0; isec = backing_inode_security(dentry); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, isec->sclass, file_to_av(file), &ad); } @@ -2125,16 +2127,16 @@ static int selinux_ptrace_access_check(struct task_struct *child, u32 csid = task_sid_obj(child); if (mode & PTRACE_MODE_READ) - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, csid, SECCLASS_FILE, FILE__READ, NULL); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); } static int selinux_ptrace_traceme(struct task_struct *parent) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, task_sid_obj(parent), task_sid_obj(current), SECCLASS_PROCESS, PROCESS__PTRACE, NULL); } @@ -2142,7 +2144,7 @@ static int selinux_ptrace_traceme(struct task_struct *parent) static int selinux_capget(const struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(target), SECCLASS_PROCESS, PROCESS__GETCAP, NULL); } @@ -2152,7 +2154,7 @@ static int selinux_capset(struct cred *new, const struct cred *old, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, cred_sid(old), cred_sid(new), SECCLASS_PROCESS, PROCESS__SETCAP, NULL); } @@ -2220,20 +2222,20 @@ static int selinux_syslog(int type) switch (type) { case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL); case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ /* Set level of messages printed to console */ case SYSLOG_ACTION_CONSOLE_LEVEL: - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, NULL); } /* All other syslog types */ - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL); } @@ -2294,7 +2296,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm, av |= PROCESS2__NNP_TRANSITION; if (nosuid) av |= PROCESS2__NOSUID_TRANSITION; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS2, av, NULL); if (!rc) @@ -2306,7 +2308,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm, * i.e. SIDs that are guaranteed to only be allowed a subset * of the permissions of the current SID. */ - rc = security_bounded_transition(&selinux_state, old_tsec->sid, + rc = security_bounded_transition(current_selinux_state, old_tsec->sid, new_tsec->sid); if (!rc) return 0; @@ -2352,7 +2354,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) * early boot end up with a label different from SECINITSID_KERNEL * (if the policy chooses to set SECINITSID_INIT != SECINITSID_KERNEL). */ - if (!selinux_initialized(&selinux_state)) { + if (!selinux_initialized(current_selinux_state)) { new_tsec->sid = SECINITSID_INIT; /* also clear the exec_sid just in case */ new_tsec->exec_sid = 0; @@ -2370,7 +2372,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) return rc; } else { /* Check for a default transition on this program. */ - rc = security_transition_sid(&selinux_state, old_tsec->sid, + rc = security_transition_sid(current_selinux_state, old_tsec->sid, isec->sid, SECCLASS_PROCESS, NULL, &new_tsec->sid); if (rc) @@ -2389,20 +2391,20 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) ad.u.file = bprm->file; if (new_tsec->sid == old_tsec->sid) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, old_tsec->sid, isec->sid, SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); if (rc) return rc; } else { /* Check permissions for the transition. */ - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); if (rc) return rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, new_tsec->sid, isec->sid, SECCLASS_FILE, FILE__ENTRYPOINT, &ad); if (rc) @@ -2410,7 +2412,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) /* Check for shared state */ if (bprm->unsafe & LSM_UNSAFE_SHARE) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__SHARE, NULL); @@ -2423,7 +2425,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) if (bprm->unsafe & LSM_UNSAFE_PTRACE) { u32 ptsid = ptrace_parent_sid(); if (ptsid != 0) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, ptsid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); @@ -2438,7 +2440,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) /* Enable secure mode for SIDs transitions unless the noatsecure permission is granted between the two SIDs, i.e. ahp returns 0. */ - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__NOATSECURE, NULL); @@ -2531,7 +2533,7 @@ static void selinux_bprm_committing_creds(const struct linux_binprm *bprm) * higher than the default soft limit for cases where the default is * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. */ - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__RLIMITINH, NULL); if (rc) { @@ -2571,7 +2573,7 @@ static void selinux_bprm_committed_creds(const struct linux_binprm *bprm) * This must occur _after_ the task SID has been updated so that any * kill done after the flush will be checked against the new SID. */ - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); if (rc) { clear_itimer(); @@ -2926,7 +2928,7 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode, if (xattr_name) *xattr_name = XATTR_NAME_SELINUX; - return security_sid_to_context(&selinux_state, newsid, (char **)ctx, + return security_sid_to_context(current_selinux_state, newsid, (char **)ctx, ctxlen); } @@ -2979,12 +2981,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, isec->initialized = LABEL_INITIALIZED; } - if (!selinux_initialized(&selinux_state) || + if (!selinux_initialized(current_selinux_state) || !(sbsec->flags & SBLABEL_MNT)) return -EOPNOTSUPP; if (xattr) { - rc = security_sid_to_context_force(&selinux_state, newsid, + rc = security_sid_to_context_force(current_selinux_state, newsid, &context, &clen); if (rc) return rc; @@ -3005,7 +3007,7 @@ static int selinux_inode_init_security_anon(struct inode *inode, struct inode_security_struct *isec; int rc; - if (unlikely(!selinux_initialized(&selinux_state))) + if (unlikely(!selinux_initialized(current_selinux_state))) return 0; isec = selinux_inode(inode); @@ -3029,7 +3031,7 @@ static int selinux_inode_init_security_anon(struct inode *inode, } else { isec->sclass = SECCLASS_ANON_INODE; rc = security_transition_sid( - &selinux_state, sid, sid, + current_selinux_state, sid, sid, isec->sclass, name, &isec->sid); if (rc) return rc; @@ -3044,7 +3046,7 @@ static int selinux_inode_init_security_anon(struct inode *inode, ad.type = LSM_AUDIT_DATA_ANONINODE; ad.u.anonclass = name ? (const char *)name->name : "?"; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, isec->sclass, @@ -3113,7 +3115,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode, if (IS_ERR(isec)) return PTR_ERR(isec); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, isec->sclass, FILE__READ, &ad); } @@ -3127,7 +3129,7 @@ static noinline int audit_inode_permission(struct inode *inode, ad.type = LSM_AUDIT_DATA_INODE; ad.u.inode = inode; - return slow_avc_audit(&selinux_state, + return slow_avc_audit(current_selinux_state, current_sid(), isec->sid, isec->sclass, perms, audited, denied, result, &ad); } @@ -3159,7 +3161,7 @@ static int selinux_inode_permission(struct inode *inode, int mask) if (IS_ERR(isec)) return PTR_ERR(isec); - rc = avc_has_perm_noaudit(&selinux_state, + rc = avc_has_perm_noaudit(current_selinux_state, sid, isec->sid, isec->sclass, perms, 0, &avd); audited = avc_audit_required(perms, &avd, rc, @@ -3252,7 +3254,7 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, if (strcmp(name, XATTR_NAME_SELINUX)) return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); - if (!selinux_initialized(&selinux_state)) + if (!selinux_initialized(current_selinux_state)) return (inode_owner_or_capable(idmap, inode) ? 0 : -EPERM); sbsec = selinux_superblock(inode->i_sb); @@ -3266,13 +3268,13 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, ad.u.dentry = dentry; isec = backing_inode_security(dentry); - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, isec->sid, isec->sclass, FILE__RELABELFROM, &ad); if (rc) return rc; - rc = security_context_to_sid(&selinux_state, value, size, &newsid, + rc = security_context_to_sid(current_selinux_state, value, size, &newsid, GFP_KERNEL); if (rc == -EINVAL) { if (!has_cap_mac_admin(true)) { @@ -3301,24 +3303,24 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, return rc; } - rc = security_context_to_sid_force(&selinux_state, value, + rc = security_context_to_sid_force(current_selinux_state, value, size, &newsid); } if (rc) return rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, newsid, isec->sclass, FILE__RELABELTO, &ad); if (rc) return rc; - rc = security_validate_transition(&selinux_state, isec->sid, newsid, + rc = security_validate_transition(current_selinux_state, isec->sid, newsid, sid, isec->sclass); if (rc) return rc; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, newsid, sbsec->sid, SECCLASS_FILESYSTEM, @@ -3359,7 +3361,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, return; } - if (!selinux_initialized(&selinux_state)) { + if (!selinux_initialized(current_selinux_state)) { /* If we haven't even been initialized, then we can't validate * against a policy, so leave the label as invalid. It may * resolve to a valid label on the next revalidation try if @@ -3368,7 +3370,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, return; } - rc = security_context_to_sid_force(&selinux_state, value, size, + rc = security_context_to_sid_force(current_selinux_state, value, size, &newsid); if (rc) { pr_err("SELinux: unable to map context to SID" @@ -3406,7 +3408,7 @@ static int selinux_inode_removexattr(struct mnt_idmap *idmap, if (strcmp(name, XATTR_NAME_SELINUX)) return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); - if (!selinux_initialized(&selinux_state)) + if (!selinux_initialized(current_selinux_state)) return 0; /* No one is allowed to remove a SELinux security label. @@ -3476,7 +3478,7 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap, * If we're not initialized yet, then we can't validate contexts, so * just let vfs_getxattr fall back to using the on-disk xattr. */ - if (!selinux_initialized(&selinux_state) || + if (!selinux_initialized(current_selinux_state) || strcmp(name, XATTR_SELINUX_SUFFIX)) return -EOPNOTSUPP; @@ -3491,11 +3493,11 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap, */ isec = inode_security(inode); if (has_cap_mac_admin(false)) - error = security_sid_to_context_force(&selinux_state, + error = security_sid_to_context_force(current_selinux_state, isec->sid, &context, &size); else - error = security_sid_to_context(&selinux_state, isec->sid, + error = security_sid_to_context(current_selinux_state, isec->sid, &context, &size); if (error) return error; @@ -3527,7 +3529,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, if (!value || !size) return -EACCES; - rc = security_context_to_sid(&selinux_state, value, size, &newsid, + rc = security_context_to_sid(current_selinux_state, value, size, &newsid, GFP_KERNEL); if (rc) return rc; @@ -3544,7 +3546,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t { const int len = sizeof(XATTR_NAME_SELINUX); - if (!selinux_initialized(&selinux_state)) + if (!selinux_initialized(current_selinux_state)) return 0; if (buffer && len <= buffer_size) @@ -3586,7 +3588,7 @@ static int selinux_inode_copy_up_xattr(struct dentry *dentry, const char *name) * xattrs up. Instead, filter out SELinux-related xattrs following * policy load. */ - if (selinux_initialized(&selinux_state) && + if (selinux_initialized(current_selinux_state) && !strcmp(name, XATTR_NAME_SELINUX)) return -ECANCELED; /* Discard */ @@ -3624,8 +3626,8 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, return rc; } - rc = security_context_to_sid(&selinux_state, context, clen, &parent_sid, - GFP_KERNEL); + rc = security_context_to_sid(current_selinux_state, context, clen, + &parent_sid, GFP_KERNEL); kfree(context); if (rc) return rc; @@ -3639,14 +3641,14 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, q.name = kn->name; q.hash_len = hashlen_string(kn_dir, kn->name); - rc = security_transition_sid(&selinux_state, tsec->sid, + rc = security_transition_sid(current_selinux_state, tsec->sid, parent_sid, secclass, &q, &newsid); if (rc) return rc; } - rc = security_sid_to_context_force(&selinux_state, newsid, + rc = security_sid_to_context_force(current_selinux_state, newsid, &context, &clen); if (rc) return rc; @@ -3686,7 +3688,7 @@ static int selinux_file_permission(struct file *file, int mask) isec = inode_security(inode); if (sid == fsec->sid && fsec->isid == isec->sid && - fsec->pseqno == avc_policy_seqno(&selinux_state)) + fsec->pseqno == avc_policy_seqno(current_selinux_state)) /* No change since file_open check. */ return 0; @@ -3727,7 +3729,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, ad.u.op->path = file->f_path; if (ssid != fsec->sid) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, ssid, fsec->sid, SECCLASS_FD, FD__USE, @@ -3740,7 +3742,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, return 0; isec = inode_security(inode); - rc = avc_has_extended_perms(&selinux_state, + rc = avc_has_extended_perms(current_selinux_state, ssid, isec->sid, isec->sclass, requested, driver, xperm, &ad); out: @@ -3837,7 +3839,7 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared * private file mapping that will also be writable. * This has an additional check. */ - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, sid, SECCLASS_PROCESS, PROCESS__EXECMEM, NULL); if (rc) @@ -3868,7 +3870,7 @@ static int selinux_mmap_addr(unsigned long addr) if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { u32 sid = current_sid(); - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, sid, SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, NULL); } @@ -3917,12 +3919,12 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, */ if (vma->vm_start >= vma->vm_mm->start_brk && vma->vm_end <= vma->vm_mm->brk) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, sid, SECCLASS_PROCESS, PROCESS__EXECHEAP, NULL); } else if (!vma->vm_file && (vma_is_initial_stack(vma) || vma_is_stack_for_current(vma))) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, sid, SECCLASS_PROCESS, PROCESS__EXECSTACK, NULL); } else if (vma->vm_file && vma->anon_vma) { @@ -4015,7 +4017,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, else perm = signal_to_av(signum); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, fsec->fown_sid, sid, SECCLASS_PROCESS, perm, NULL); } @@ -4042,7 +4044,7 @@ static int selinux_file_open(struct file *file) * struct as its SID. */ fsec->isid = isec->sid; - fsec->pseqno = avc_policy_seqno(&selinux_state); + fsec->pseqno = avc_policy_seqno(current_selinux_state); /* * Since the inode label or policy seqno may have changed * between the selinux_inode_permission check and the saving @@ -4061,7 +4063,7 @@ static int selinux_task_alloc(struct task_struct *task, { u32 sid = current_sid(); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); } @@ -4109,7 +4111,7 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid) u32 sid = current_sid(); int ret; - ret = avc_has_perm(&selinux_state, + ret = avc_has_perm(current_selinux_state, sid, secid, SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__USE_AS_OVERRIDE, @@ -4134,7 +4136,7 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) u32 sid = current_sid(); int ret; - ret = avc_has_perm(&selinux_state, + ret = avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__CREATE_FILES_AS, @@ -4152,7 +4154,7 @@ static int selinux_kernel_module_request(char *kmod_name) ad.type = LSM_AUDIT_DATA_KMOD; ad.u.kmod_name = kmod_name; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, &ad); } @@ -4167,7 +4169,7 @@ static int selinux_kernel_module_from_file(struct file *file) /* init_module */ if (file == NULL) - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, sid, SECCLASS_SYSTEM, SYSTEM__MODULE_LOAD, NULL); @@ -4178,14 +4180,14 @@ static int selinux_kernel_module_from_file(struct file *file) fsec = selinux_file(file); if (sid != fsec->sid) { - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); if (rc) return rc; } isec = inode_security(file_inode(file)); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_SYSTEM, SYSTEM__MODULE_LOAD, &ad); } @@ -4224,21 +4226,21 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents) static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETPGID, NULL); } static int selinux_task_getpgid(struct task_struct *p) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__GETPGID, NULL); } static int selinux_task_getsid(struct task_struct *p) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__GETSESSION, NULL); } @@ -4256,21 +4258,21 @@ static void selinux_task_getlsmprop_obj(struct task_struct *p, static int selinux_task_setnice(struct task_struct *p, int nice) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); } static int selinux_task_setioprio(struct task_struct *p, int ioprio) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); } static int selinux_task_getioprio(struct task_struct *p) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__GETSCHED, NULL); } @@ -4286,7 +4288,7 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre av |= PROCESS__SETRLIMIT; if (flags & LSM_PRLIMIT_READ) av |= PROCESS__GETRLIMIT; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, cred_sid(cred), cred_sid(tcred), SECCLASS_PROCESS, av, NULL); } @@ -4301,7 +4303,7 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, later be used as a safe reset point for the soft limit upon context transitions. See selinux_bprm_committing_creds. */ if (old_rlim->rlim_max != new_rlim->rlim_max) - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); @@ -4310,21 +4312,21 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, static int selinux_task_setscheduler(struct task_struct *p) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); } static int selinux_task_getscheduler(struct task_struct *p) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__GETSCHED, NULL); } static int selinux_task_movememory(struct task_struct *p) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), task_sid_obj(p), SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); } @@ -4343,7 +4345,7 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info, secid = current_sid(); else secid = cred_sid(cred); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, secid, task_sid_obj(p), SECCLASS_PROCESS, perm, NULL); } @@ -4364,7 +4366,7 @@ static int selinux_userns_create(const struct cred *cred) { u32 sid = current_sid(); - return avc_has_perm(&selinux_state, sid, sid, SECCLASS_USER_NAMESPACE, + return avc_has_perm(current_selinux_state, sid, sid, SECCLASS_USER_NAMESPACE, USER_NAMESPACE__CREATE, NULL); } @@ -4623,7 +4625,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) if (unlikely(err)) return -EACCES; - err = security_net_peersid_resolve(&selinux_state, nlbl_sid, + err = security_net_peersid_resolve(current_selinux_state, nlbl_sid, nlbl_type, xfrm_sid, sid); if (unlikely(err)) { pr_warn( @@ -4652,7 +4654,7 @@ static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid) int err = 0; if (skb_sid != SECSID_NULL) - err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid, + err = security_sid_mls_copy(current_selinux_state, sk_sid, skb_sid, conn_sid); else *conn_sid = sk_sid; @@ -4670,7 +4672,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, return 0; } - return security_transition_sid(&selinux_state, tsec->sid, tsec->sid, + return security_transition_sid(current_selinux_state, tsec->sid, tsec->sid, secclass, NULL, socksid); } @@ -4708,7 +4710,7 @@ static int sock_has_perm(struct sock *sk, u32 perms) ad_net_init_from_sk(&ad, &net, sk); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), sksec->sid, sksec->sclass, perms, &ad); } @@ -4729,7 +4731,7 @@ static int selinux_socket_create(int family, int type, if (rc) return rc; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); } @@ -4866,7 +4868,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in snum, &sid); if (err) goto out; - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sksec->sid, sid, sksec->sclass, SOCKET__NAME_BIND, &ad); @@ -4906,7 +4908,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in else ad.u.net->v6info.saddr = addr6->sin6_addr; - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sksec->sid, sid, sksec->sclass, node_perm, &ad); if (err) @@ -5005,7 +5007,7 @@ static int selinux_socket_connect_helper(struct socket *sock, ad.u.net = &net; ad.u.net->dport = htons(snum); ad.u.net->family = address->sa_family; - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sksec->sid, sid, sksec->sclass, perm, &ad); if (err) return err; @@ -5116,7 +5118,7 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, ad_net_init_from_sk(&ad, &net, other); - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sksec_sock->sid, sksec_other->sid, sksec_other->sclass, UNIX_STREAM_SOCKET__CONNECTTO, &ad); @@ -5125,7 +5127,7 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, /* server child socket */ sksec_new->peer_sid = sksec_sock->sid; - err = security_sid_mls_copy(&selinux_state, sksec_other->sid, + err = security_sid_mls_copy(current_selinux_state, sksec_other->sid, sksec_sock->sid, &sksec_new->sid); if (err) return err; @@ -5146,7 +5148,7 @@ static int selinux_socket_unix_may_send(struct socket *sock, ad_net_init_from_sk(&ad, &net, other->sk); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, &ad); } @@ -5162,7 +5164,7 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, err = sel_netif_sid(ns, ifindex, &if_sid); if (err) return err; - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, peer_sid, if_sid, SECCLASS_NETIF, NETIF__INGRESS, ad); if (err) @@ -5171,7 +5173,7 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, err = sel_netnode_sid(addrp, family, &node_sid); if (err) return err; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, peer_sid, node_sid, SECCLASS_NODE, NODE__RECVFROM, ad); } @@ -5192,7 +5194,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, return err; if (selinux_secmark_enabled()) { - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sk_sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) @@ -5253,7 +5255,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) selinux_netlbl_err(skb, family, err, 0); return err; } - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); if (err) { @@ -5263,7 +5265,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) } if (secmark_active) { - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sk_sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) @@ -5290,7 +5292,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, if (peer_sid == SECSID_NULL) return -ENOPROTOOPT; - err = security_sid_to_context(&selinux_state, peer_sid, &scontext, + err = security_sid_to_context(current_selinux_state, peer_sid, &scontext, &scontext_len); if (err) return err; @@ -5440,7 +5442,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, * consistency among the peer SIDs. */ ad_net_init_from_sk(&ad, &net, asoc->base.sk); - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sksec->peer_sid, asoc->peer_secid, sksec->sclass, SCTP_SOCKET__ASSOCIATION, &ad); @@ -5671,7 +5673,7 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) static int selinux_secmark_relabel_packet(u32 sid) { - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); } @@ -5711,7 +5713,7 @@ static int selinux_tun_dev_create(void) * connections unlike traditional sockets - check the TUN driver to * get a better understanding of why this socket is special */ - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, NULL); } @@ -5720,7 +5722,7 @@ static int selinux_tun_dev_attach_queue(void *security) { struct tun_security_struct *tunsec = selinux_tun_dev(security); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__ATTACH_QUEUE, NULL); } @@ -5749,12 +5751,12 @@ static int selinux_tun_dev_open(void *security) u32 sid = current_sid(); int err; - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sid, tunsec->sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__RELABELFROM, NULL); if (err) return err; - err = avc_has_perm(&selinux_state, + err = avc_has_perm(current_selinux_state, sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__RELABELTO, NULL); if (err) @@ -5806,7 +5808,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, } if (secmark_active) - if (avc_has_perm(&selinux_state, + if (avc_has_perm(current_selinux_state, peer_sid, skb->secmark, SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) return NF_DROP; @@ -5884,7 +5886,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, return NF_DROP; if (selinux_secmark_enabled()) - if (avc_has_perm(&selinux_state, + if (avc_has_perm(current_selinux_state, sksec->sid, skb->secmark, SECCLASS_PACKET, PACKET__SEND, &ad)) return NF_DROP_ERR(-ECONNREFUSED); @@ -6007,7 +6009,7 @@ static unsigned int selinux_ip_postroute(void *priv, return NF_DROP; if (secmark_active) - if (avc_has_perm(&selinux_state, + if (avc_has_perm(current_selinux_state, peer_sid, skb->secmark, SECCLASS_PACKET, secmark_perm, &ad)) return NF_DROP_ERR(-ECONNREFUSED); @@ -6018,14 +6020,14 @@ static unsigned int selinux_ip_postroute(void *priv, if (sel_netif_sid(state->net, ifindex, &if_sid)) return NF_DROP; - if (avc_has_perm(&selinux_state, + if (avc_has_perm(current_selinux_state, peer_sid, if_sid, SECCLASS_NETIF, NETIF__EGRESS, &ad)) return NF_DROP_ERR(-ECONNREFUSED); if (sel_netnode_sid(addrp, family, &node_sid)) return NF_DROP; - if (avc_has_perm(&selinux_state, + if (avc_has_perm(current_selinux_state, peer_sid, node_sid, SECCLASS_NODE, NODE__SENDTO, &ad)) return NF_DROP_ERR(-ECONNREFUSED); @@ -6051,7 +6053,7 @@ static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_t driver = nlmsg_type >> 8; xperm = nlmsg_type & 0xff; - return avc_has_extended_perms(&selinux_state, current_sid(), + return avc_has_extended_perms(current_selinux_state, current_sid(), sksec->sid, sksec->sclass, perms, driver, xperm, &ad); } @@ -6097,8 +6099,8 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) sk->sk_protocol, nlh->nlmsg_type, secclass_map[sclass - 1].name, task_pid_nr(current), current->comm); - if (enforcing_enabled(&selinux_state) && - !security_get_allow_unknown(&selinux_state)) + if (enforcing_enabled(current_selinux_state) && + !security_get_allow_unknown(current_selinux_state)) return rc; rc = 0; } else if (rc == -ENOENT) { @@ -6137,7 +6139,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = ipc_perms->key; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, isec->sclass, perms, &ad); } @@ -6164,7 +6166,7 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_MSGQ, MSGQ__CREATE, &ad); } @@ -6180,7 +6182,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_MSGQ, MSGQ__ASSOCIATE, &ad); } @@ -6193,7 +6195,7 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) case IPC_INFO: case MSG_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); case IPC_STAT: @@ -6233,7 +6235,7 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m * Compute new sid based on current process and * message queue this message will be stored in */ - rc = security_transition_sid(&selinux_state, sid, isec->sid, + rc = security_transition_sid(current_selinux_state, sid, isec->sid, SECCLASS_MSG, NULL, &msec->sid); if (rc) return rc; @@ -6243,17 +6245,17 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m ad.u.ipc_id = msq->key; /* Can this process write to the queue? */ - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_MSGQ, MSGQ__WRITE, &ad); if (!rc) /* Can this process send the message */ - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, msec->sid, SECCLASS_MSG, MSG__SEND, &ad); if (!rc) /* Can the message be put in the queue? */ - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, msec->sid, isec->sid, SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad); @@ -6276,11 +6278,11 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_MSGQ, MSGQ__READ, &ad); if (!rc) - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sid, msec->sid, SECCLASS_MSG, MSG__RECEIVE, &ad); return rc; @@ -6299,7 +6301,7 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_SHM, SHM__CREATE, &ad); } @@ -6315,7 +6317,7 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_SHM, SHM__ASSOCIATE, &ad); } @@ -6329,7 +6331,7 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd) case IPC_INFO: case SHM_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); case IPC_STAT: @@ -6380,7 +6382,7 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_SEM, SEM__CREATE, &ad); } @@ -6396,7 +6398,7 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, isec->sid, SECCLASS_SEM, SEM__ASSOCIATE, &ad); } @@ -6411,7 +6413,7 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd) case IPC_INFO: case SEM_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); case GETPID: @@ -6499,7 +6501,7 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, rcu_read_lock(); tsec = selinux_cred(__task_cred(p)); if (p != current) { - error = avc_has_perm(&selinux_state, + error = avc_has_perm(current_selinux_state, current_sid(), tsec->sid, SECCLASS_PROCESS, PROCESS__GETATTR, NULL); if (error) @@ -6535,7 +6537,7 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, return 0; } - error = security_sid_to_context(&selinux_state, sid, value, &len); + error = security_sid_to_context(current_selinux_state, sid, value, &len); if (error) return error; return len; @@ -6558,27 +6560,27 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) */ switch (attr) { case LSM_ATTR_EXEC: - error = avc_has_perm(&selinux_state, + error = avc_has_perm(current_selinux_state, mysid, mysid, SECCLASS_PROCESS, PROCESS__SETEXEC, NULL); break; case LSM_ATTR_FSCREATE: - error = avc_has_perm(&selinux_state, + error = avc_has_perm(current_selinux_state, mysid, mysid, SECCLASS_PROCESS, PROCESS__SETFSCREATE, NULL); break; case LSM_ATTR_KEYCREATE: - error = avc_has_perm(&selinux_state, + error = avc_has_perm(current_selinux_state, mysid, mysid, SECCLASS_PROCESS, PROCESS__SETKEYCREATE, NULL); break; case LSM_ATTR_SOCKCREATE: - error = avc_has_perm(&selinux_state, + error = avc_has_perm(current_selinux_state, mysid, mysid, SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, NULL); break; case LSM_ATTR_CURRENT: - error = avc_has_perm(&selinux_state, + error = avc_has_perm(current_selinux_state, mysid, mysid, SECCLASS_PROCESS, PROCESS__SETCURRENT, NULL); break; @@ -6595,7 +6597,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) str[size-1] = 0; size--; } - error = security_context_to_sid(&selinux_state, value, size, + error = security_context_to_sid(current_selinux_state, value, size, &sid, GFP_KERNEL); if (error == -EINVAL && attr == LSM_ATTR_FSCREATE) { if (!has_cap_mac_admin(true)) { @@ -6622,7 +6624,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) return error; } error = security_context_to_sid_force( - &selinux_state, + current_selinux_state, value, size, &sid); } if (error) @@ -6646,7 +6648,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) tsec->create_sid = sid; } else if (attr == LSM_ATTR_KEYCREATE) { if (sid) { - error = avc_has_perm(&selinux_state, mysid, sid, + error = avc_has_perm(current_selinux_state, mysid, sid, SECCLASS_KEY, KEY__CREATE, NULL); if (error) goto abort_change; @@ -6660,14 +6662,14 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) goto abort_change; if (!current_is_single_threaded()) { - error = security_bounded_transition(&selinux_state, + error = security_bounded_transition(current_selinux_state, tsec->sid, sid); if (error) goto abort_change; } /* Check permissions for the transition. */ - error = avc_has_perm(&selinux_state, + error = avc_has_perm(current_selinux_state, tsec->sid, sid, SECCLASS_PROCESS, PROCESS__DYNTRANSITION, NULL); if (error) @@ -6677,7 +6679,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) Otherwise, leave SID unchanged and fail. */ ptsid = ptrace_parent_sid(); if (ptsid != 0) { - error = avc_has_perm(&selinux_state, + error = avc_has_perm(current_selinux_state, ptsid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); if (error) @@ -6768,7 +6770,7 @@ static int selinux_ismaclabel(const char *name) static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { - return security_sid_to_context(&selinux_state, secid, + return security_sid_to_context(current_selinux_state, secid, secdata, seclen); } @@ -6780,7 +6782,7 @@ static int selinux_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) { - return security_context_to_sid(&selinux_state, secdata, seclen, + return security_context_to_sid(current_selinux_state, secdata, seclen, secid, GFP_KERNEL); } @@ -6887,7 +6889,7 @@ static int selinux_key_permission(key_ref_t key_ref, key = key_ref_to_ptr(key_ref); ksec = selinux_key(key); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, ksec->sid, SECCLASS_KEY, perm, NULL); } @@ -6898,7 +6900,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) unsigned len; int rc; - rc = security_sid_to_context(&selinux_state, ksec->sid, + rc = security_sid_to_context(current_selinux_state, ksec->sid, &context, &len); if (!rc) rc = len; @@ -6912,7 +6914,7 @@ static int selinux_watch_key(struct key *key) struct key_security_struct *ksec = selinux_key(key); u32 sid = current_sid(); - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL); } #endif @@ -6935,7 +6937,7 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val) ibpkey.subnet_prefix = subnet_prefix; ibpkey.pkey = pkey_val; ad.u.ibpkey = &ibpkey; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sec->sid, sid, SECCLASS_INFINIBAND_PKEY, INFINIBAND_PKEY__ACCESS, &ad); @@ -6950,7 +6952,7 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, struct ib_security_struct *sec = ib_sec; struct lsm_ibendport_audit ibendport; - err = security_ib_endport_sid(&selinux_state, dev_name, port_num, + err = security_ib_endport_sid(current_selinux_state, dev_name, port_num, &sid); if (err) @@ -6960,7 +6962,7 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, ibendport.dev_name = dev_name; ibendport.port = port_num; ad.u.ibendport = &ibendport; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sec->sid, sid, SECCLASS_INFINIBAND_ENDPORT, INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad); @@ -6984,12 +6986,12 @@ static int selinux_bpf(int cmd, union bpf_attr *attr, switch (cmd) { case BPF_MAP_CREATE: - ret = avc_has_perm(&selinux_state, + ret = avc_has_perm(current_selinux_state, sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, NULL); break; case BPF_PROG_LOAD: - ret = avc_has_perm(&selinux_state, + ret = avc_has_perm(current_selinux_state, sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, NULL); break; @@ -7030,7 +7032,7 @@ static int bpf_fd_pass(const struct file *file, u32 sid) if (file->f_op == &bpf_map_fops) { map = file->private_data; bpfsec = map->security; - ret = avc_has_perm(&selinux_state, + ret = avc_has_perm(current_selinux_state, sid, bpfsec->sid, SECCLASS_BPF, bpf_map_fmode_to_av(file->f_mode), NULL); if (ret) @@ -7038,7 +7040,7 @@ static int bpf_fd_pass(const struct file *file, u32 sid) } else if (file->f_op == &bpf_prog_fops) { prog = file->private_data; bpfsec = prog->aux->security; - ret = avc_has_perm(&selinux_state, + ret = avc_has_perm(current_selinux_state, sid, bpfsec->sid, SECCLASS_BPF, BPF__PROG_RUN, NULL); if (ret) @@ -7053,7 +7055,7 @@ static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) struct bpf_security_struct *bpfsec; bpfsec = map->security; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, bpfsec->sid, SECCLASS_BPF, bpf_map_fmode_to_av(fmode), NULL); } @@ -7064,7 +7066,7 @@ static int selinux_bpf_prog(struct bpf_prog *prog) struct bpf_security_struct *bpfsec; bpfsec = prog->aux->security; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sid, bpfsec->sid, SECCLASS_BPF, BPF__PROG_RUN, NULL); } @@ -7172,7 +7174,7 @@ static int selinux_perf_event_open(struct perf_event_attr *attr, int type) else return -EINVAL; - return avc_has_perm(&selinux_state, sid, sid, SECCLASS_PERF_EVENT, + return avc_has_perm(current_selinux_state, sid, sid, SECCLASS_PERF_EVENT, requested, NULL); } @@ -7191,7 +7193,7 @@ static int selinux_perf_event_read(struct perf_event *event) struct perf_event_security_struct *perfsec = event->security; u32 sid = current_sid(); - return avc_has_perm(&selinux_state, sid, perfsec->sid, + return avc_has_perm(current_selinux_state, sid, perfsec->sid, SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL); } @@ -7200,7 +7202,7 @@ static int selinux_perf_event_write(struct perf_event *event) struct perf_event_security_struct *perfsec = event->security; u32 sid = current_sid(); - return avc_has_perm(&selinux_state, sid, perfsec->sid, + return avc_has_perm(current_selinux_state, sid, perfsec->sid, SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL); } #endif @@ -7215,7 +7217,7 @@ static int selinux_perf_event_write(struct perf_event *event) */ static int selinux_uring_override_creds(const struct cred *new) { - return avc_has_perm(&selinux_state, current_sid(), cred_sid(new), + return avc_has_perm(current_selinux_state, current_sid(), cred_sid(new), SECCLASS_IO_URING, IO_URING__OVERRIDE_CREDS, NULL); } @@ -7229,7 +7231,7 @@ static int selinux_uring_sqpoll(void) { u32 sid = current_sid(); - return avc_has_perm(&selinux_state, sid, sid, + return avc_has_perm(current_selinux_state, sid, sid, SECCLASS_IO_URING, IO_URING__SQPOLL, NULL); } @@ -7251,7 +7253,7 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd) ad.type = LSM_AUDIT_DATA_FILE; ad.u.file = file; - return avc_has_perm(&selinux_state, current_sid(), isec->sid, + return avc_has_perm(current_selinux_state, current_sid(), isec->sid, SECCLASS_IO_URING, IO_URING__CMD, &ad); } #endif /* CONFIG_IO_URING */ @@ -7564,11 +7566,12 @@ static __init int selinux_init(void) { pr_info("SELinux: Initializing.\n"); - memset(&selinux_state, 0, sizeof(selinux_state)); - enforcing_set(&selinux_state, selinux_enforcing_boot); - selinux_avc_init(&selinux_state.avc); - mutex_init(&selinux_state.status_lock); - mutex_init(&selinux_state.policy_mutex); + memset(&init_selinux_state, 0, sizeof(init_selinux_state)); + enforcing_set(&init_selinux_state, selinux_enforcing_boot); + selinux_avc_init(&init_selinux_state.avc); + mutex_init(&init_selinux_state.status_lock); + mutex_init(&init_selinux_state.policy_mutex); + current_selinux_state = &init_selinux_state; /* Set the security state for the initial task. */ cred_init_security(); diff --git a/security/selinux/ibpkey.c b/security/selinux/ibpkey.c index 5839ca7bb9c7..6492e57f1c53 100644 --- a/security/selinux/ibpkey.c +++ b/security/selinux/ibpkey.c @@ -141,7 +141,7 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid) return 0; } - ret = security_ib_pkey_sid(&selinux_state, subnet_prefix, pkey_num, + ret = security_ib_pkey_sid(current_selinux_state, subnet_prefix, pkey_num, sid); if (ret) goto out; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index bf223dcc7e0f..14aa2cbb391a 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -108,7 +108,7 @@ struct selinux_state { void selinux_avc_init(struct selinux_avc **avc); -extern struct selinux_state selinux_state; +extern struct selinux_state *current_selinux_state; static inline bool selinux_initialized(const struct selinux_state *state) { @@ -151,57 +151,65 @@ static inline bool checkreqprot_get(const struct selinux_state *state) static inline bool selinux_policycap_netpeer(void) { - return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_NETPEER]); + return READ_ONCE( + current_selinux_state->policycap[POLICYDB_CAP_NETPEER]); } static inline bool selinux_policycap_openperm(void) { - return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_OPENPERM]); + return READ_ONCE( + current_selinux_state->policycap[POLICYDB_CAP_OPENPERM]); } static inline bool selinux_policycap_extsockclass(void) { - return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_EXTSOCKCLASS]); + return READ_ONCE( + current_selinux_state->policycap[POLICYDB_CAP_EXTSOCKCLASS]); } static inline bool selinux_policycap_alwaysnetwork(void) { - return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_ALWAYSNETWORK]); + return READ_ONCE( + current_selinux_state->policycap[POLICYDB_CAP_ALWAYSNETWORK]); } static inline bool selinux_policycap_cgroupseclabel(void) { - return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_CGROUPSECLABEL]); + return READ_ONCE( + current_selinux_state->policycap[POLICYDB_CAP_CGROUPSECLABEL]); } static inline bool selinux_policycap_nnp_nosuid_transition(void) { return READ_ONCE( - selinux_state.policycap[POLICYDB_CAP_NNP_NOSUID_TRANSITION]); + current_selinux_state + ->policycap[POLICYDB_CAP_NNP_NOSUID_TRANSITION]); } static inline bool selinux_policycap_genfs_seclabel_symlinks(void) { return READ_ONCE( - selinux_state.policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]); + current_selinux_state + ->policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]); } static inline bool selinux_policycap_ioctl_skip_cloexec(void) { - return READ_ONCE( - selinux_state.policycap[POLICYDB_CAP_IOCTL_SKIP_CLOEXEC]); + return READ_ONCE(current_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]); + current_selinux_state + ->policycap[POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT]); } static inline bool selinux_policycap_netlink_xperm(void) { return READ_ONCE( - selinux_state.policycap[POLICYDB_CAP_NETLINK_XPERM]); + current_selinux_state->policycap[POLICYDB_CAP_NETLINK_XPERM]); } struct selinux_policy_convert_data; diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 6d0c7bc9be15..5f0d20031784 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -153,7 +153,7 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) goto out; } - ret = security_netif_sid(&selinux_state, dev->name, sid); + ret = security_netif_sid(current_selinux_state, dev->name, sid); if (ret != 0) goto out; new = kzalloc(sizeof(*new), GFP_ATOMIC); diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index b858b46fd4b4..e35c224145a4 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -47,7 +47,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, { int rc; - rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid); + rc = security_netlbl_secattr_to_sid(current_selinux_state, secattr, sid); if (rc == 0 && (secattr->flags & NETLBL_SECATTR_CACHEABLE) && (secattr->flags & NETLBL_SECATTR_CACHE)) @@ -79,7 +79,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) if (secattr == NULL) return ERR_PTR(-ENOMEM); - rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid, + rc = security_netlbl_sid_to_secattr(current_selinux_state, sksec->sid, secattr); if (rc != 0) { netlbl_secattr_free(secattr); @@ -252,7 +252,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, if (secattr == NULL) { secattr = &secattr_storage; netlbl_secattr_init(secattr); - rc = security_netlbl_sid_to_secattr(&selinux_state, sid, + rc = security_netlbl_sid_to_secattr(current_selinux_state, sid, secattr); if (rc != 0) goto skbuff_setsid_return; @@ -290,7 +290,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, return 0; netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(&selinux_state, + rc = security_netlbl_sid_to_secattr(current_selinux_state, asoc->secid, &secattr); if (rc != 0) goto assoc_request_return; @@ -339,7 +339,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) return 0; netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid, + rc = security_netlbl_sid_to_secattr(current_selinux_state, req->secid, &secattr); if (rc != 0) goto inet_conn_request_return; @@ -473,7 +473,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, perm = RAWIP_SOCKET__RECVFROM; } - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, sksec->sid, nlbl_sid, sksec->sclass, perm, ad); if (rc == 0) return 0; diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 0ac7df9a9367..7683c7f28421 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -204,13 +204,13 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) new = kzalloc(sizeof(*new), GFP_ATOMIC); switch (family) { case PF_INET: - ret = security_node_sid(&selinux_state, PF_INET, + ret = security_node_sid(current_selinux_state, PF_INET, addr, sizeof(struct in_addr), sid); if (new) new->nsec.addr.ipv4 = *(__be32 *)addr; break; case PF_INET6: - ret = security_node_sid(&selinux_state, PF_INET6, + ret = security_node_sid(current_selinux_state, PF_INET6, addr, sizeof(struct in6_addr), sid); if (new) new->nsec.addr.ipv6 = *(struct in6_addr *)addr; diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 8eec6347cf01..bd35a7c96264 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c @@ -148,7 +148,7 @@ static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid) return 0; } - ret = security_port_sid(&selinux_state, protocol, pnum, sid); + ret = security_port_sid(current_selinux_state, protocol, pnum, sid); if (ret != 0) goto out; new = kzalloc(sizeof(*new), GFP_ATOMIC); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 792a042add28..5de86b2b3378 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -90,7 +90,7 @@ static int selinux_fs_info_create(struct super_block *sb) return -ENOMEM; fsi->last_ino = SEL_INO_NEXT - 1; - fsi->state = &selinux_state; + fsi->state = current_selinux_state; fsi->sb = sb; sb->s_fs_info = fsi; return 0; @@ -165,7 +165,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, old_value = enforcing_enabled(state); if (new_value != old_value) { - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETENFORCE, NULL); @@ -381,7 +381,7 @@ static int sel_open_policy(struct inode *inode, struct file *filp) mutex_lock(&fsi->state->policy_mutex); - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); if (rc) @@ -443,9 +443,9 @@ static ssize_t sel_read_policy(struct file *filp, char __user *buf, struct policy_load_memory *plm = filp->private_data; int ret; - ret = avc_has_perm(&selinux_state, + ret = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, - SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); + SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); if (ret) return ret; @@ -597,7 +597,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, return -EINVAL; mutex_lock(&fsi->state->policy_mutex); - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); if (length) @@ -652,7 +652,7 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) u32 sid, len; ssize_t length; - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL); if (length) @@ -700,7 +700,7 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, ssize_t length; unsigned int new_value; - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, NULL); @@ -756,7 +756,7 @@ static ssize_t sel_write_validatetrans(struct file *file, u16 tclass; int rc; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL); if (rc) @@ -885,7 +885,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) struct av_decision avd; ssize_t length; - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL); if (length) @@ -939,7 +939,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) u32 len; int nargs; - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, NULL); @@ -1041,7 +1041,7 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) char *newcon = NULL; u32 len; - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, NULL); @@ -1106,7 +1106,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) " This will not be supported in the future; please update your" " userspace.\n", current->comm, current->pid); - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_USER, NULL); @@ -1171,7 +1171,7 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) char *newcon = NULL; u32 len; - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, NULL); @@ -1299,7 +1299,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, mutex_lock(&fsi->state->policy_mutex); - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETBOOL, NULL); @@ -1355,7 +1355,7 @@ static ssize_t sel_commit_bools_write(struct file *filep, mutex_lock(&fsi->state->policy_mutex); - length = avc_has_perm(&selinux_state, + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETBOOL, NULL); @@ -1473,7 +1473,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, ssize_t ret; unsigned int new_value; - ret = avc_has_perm(&selinux_state, + ret = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETSECPARAM, NULL); @@ -2221,7 +2221,7 @@ static int __init init_sel_fs(void) * Try to pre-allocate the status page, so the sequence number of the * initial policy load can be stored. */ - (void) selinux_kernel_status_page(&selinux_state); + (void) selinux_kernel_status_page(current_selinux_state); return err; } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 7d6fd08dcb7d..db6c17bb274d 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -3579,7 +3579,7 @@ void selinux_audit_rule_free(void *vrule) int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, gfp_t gfp) { - struct selinux_state *state = &selinux_state; + struct selinux_state *state = current_selinux_state; struct selinux_policy *policy; struct policydb *policydb; struct selinux_audit_rule *tmprule; @@ -3704,7 +3704,7 @@ int selinux_audit_rule_known(struct audit_krule *rule) int selinux_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *vrule) { - struct selinux_state *state = &selinux_state; + struct selinux_state *state = current_selinux_state; struct selinux_policy *policy; struct context *ctxt; struct mls_level *level; diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 83a94ca4d738..4d1647ba8e5f 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -97,12 +97,12 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, ctx->ctx_len = str_len; memcpy(ctx->ctx_str, &uctx[1], str_len); ctx->ctx_str[str_len] = '\0'; - rc = security_context_to_sid(&selinux_state, ctx->ctx_str, str_len, + rc = security_context_to_sid(current_selinux_state, ctx->ctx_str, str_len, &ctx->ctx_sid, gfp); if (rc) goto err; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, current_sid(), ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); if (rc) @@ -137,7 +137,7 @@ static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx) if (!ctx) return 0; - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, current_sid(), ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); @@ -160,7 +160,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) if (!selinux_authorizable_ctx(ctx)) return -EINVAL; - rc = avc_has_perm(&selinux_state, + rc = avc_has_perm(current_selinux_state, fl_secid, ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL); return (rc == -EACCES ? -ESRCH : rc); @@ -202,7 +202,7 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, /* We don't need a separate SA Vs. policy polmatch check since the SA * is now of the same label as the flow and a flow Vs. policy polmatch * check had already happened in selinux_xfrm_policy_lookup() above. */ - return (avc_has_perm(&selinux_state, flic_sid, state_sid, + return (avc_has_perm(current_selinux_state, flic_sid, state_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, NULL) ? 0 : 1); } @@ -352,7 +352,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, if (secid == 0) return -EINVAL; - rc = security_sid_to_context(&selinux_state, secid, &ctx_str, + rc = security_sid_to_context(current_selinux_state, secid, &ctx_str, &str_len); if (rc) return rc; @@ -421,7 +421,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, /* This check even when there's no association involved is intended, * according to Trent Jaeger, to make sure a process can't engage in * non-IPsec communication unless explicitly allowed by policy. */ - return avc_has_perm(&selinux_state, + return avc_has_perm(current_selinux_state, sk_sid, peer_sid, SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad); } @@ -465,6 +465,6 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, /* This check even when there's no association involved is intended, * according to Trent Jaeger, to make sure a process can't engage in * non-IPsec communication unless explicitly allowed by policy. */ - return avc_has_perm(&selinux_state, sk_sid, SECINITSID_UNLABELED, + return avc_has_perm(current_selinux_state, sk_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad); } From patchwork Thu Jan 2 16:44:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924612 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f173.google.com (mail-qk1-f173.google.com [209.85.222.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4969113CFA6 for ; Thu, 2 Jan 2025 16:45:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836340; cv=none; b=UKGgV6M3vP11xDHBWHXT8QsK6MaNAljlGj7sAH4VIplpfvRk8YVzsx2TsZNq/BbAehXJF07C2yqFDrXsDqE0FFRL4EZMr2tauRy/kxPyDPrle3FUzEtIfsmcVjEF79gZ2sLDQfA1HFu9pV+Yz9uvP8M/66KkVvqhcRbRIvlkk9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836340; c=relaxed/simple; bh=IsM5WUBdwx2sXP82lwtcu8Gn3w3qglI+dLVRJkh3qCU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Hbvuto3jzJb+YBPkpmHoOdKAvy20hEeqjAI4+LJb7+/K0VlDRq0DvQxve2W7hArnxl/p3rAm+9zHjz93BewKLvcK8tRPb2juRkAOOnWkvc6elyJT55AtdPe2pa8TSilFDO1fL9Mj2t4yzOmQJq+Iaa8JYefUbtRwjOyS9DDiGTQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=NBbOekNW; arc=none smtp.client-ip=209.85.222.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NBbOekNW" Received: by mail-qk1-f173.google.com with SMTP id af79cd13be357-7b98a2e3b3eso562802585a.2 for ; Thu, 02 Jan 2025 08:45:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836335; x=1736441135; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sj/qraAyiwVXRUTldMCrvrVxR9Q3PGrd1d31XBZBmtg=; b=NBbOekNWXX1VcijDYk+gxg3stNuru0SJq/dFlQTTIFoNeFNE3i/7z0DxWKqvpyrS7p /2TdFXksO3/D8ilBpP7eR67eBeUF+Q1P4sbMxQuOjfcqHHh7rN8T1V1L/RR7bzp8lxbi 9pJvXfgxxZqkJV5rYhvu/sdSTP+YBIYQ6O5LfDFQiQ1vDyYjUu47XdF9Oz98onbIOhXO OGKUl7cM72YVFOaQbUn5mLrKGjKy6yp919DDcbWlZ13zRNswRTrDpR/6stM6Rk0tvx4n lZXDrqKfhjSuyIXDKiefE7e8E28cSZLM7b70rBxBisMDRhidAO3PAcKdS50920OVWnyG /7XA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836335; x=1736441135; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sj/qraAyiwVXRUTldMCrvrVxR9Q3PGrd1d31XBZBmtg=; b=C/+0BxIVLVj0iQFyuWKvdNJ1oWYJxPKiXdbiEiuR7pmuHw9bhceKo6kaQj9eeHF/nQ JHHAp9KqDpOqHn1vXGtmbrcY3+BxYQfNvCqjHolfwwlT7a118eGvCA6FwZmcCpujstM5 9KiLkq8J4hfZIwr/NkJOpn/rP3gOa6qfedv+nUeJ55FGRmb28kYNK8O6PMH13dcgqhCm rkQDJqzu8HVGXS0OQK657RHdC4Su3Zyd6X21VDm2FL82JAXsQ9e6NQQO5GhAmcBlJmNe rBD+u/3SzIZgI0aWGpxf49IppF8K4X97N/kTYVTIfK4qDD1IIIoKp8cBixAvqZ4a4/C2 7SpQ== X-Gm-Message-State: AOJu0Yxsks7QlqPJL6RG5HCnRFqdBdLbw4DgkdOmHCg+sDpXC0s/Xftf ZFE6b3mFLQi95WtmAyZb+b4oLX0Nl0WiCcJ35ykOhCknLIb5mrPwgHpNdA== X-Gm-Gg: ASbGncsIx59Ed6tdmMYM1LajqVLaFMaiwhCJPN0IDu6MjIgMN+s1ywmcUxZsadmvZbr bJwgOA7vxsXBmkjN/pua4bYI0ANR/O6r4jGCinorkrBc2iPAoP1BpoOlpVG+bmSNEPUpPTnZJAe MD4N2hiNuXfvERuDDG4oib4ZI7gSM7CKu5LL1mv21TESBqWoUatV2gMRFa7v7f7RWNSijLEopUB 0X9NgSwEUjSIiqPuwC90Wb1ZB9Z8PhWNAVC3YMoVeyUiXyhkQmFYZb8LatXU0K1RaEOvy7ydjdR xqt4eZpIW4AE+be/AOY7NhPlKLpQMYDXCjLD8xv2936cckmelWZU+sBcxTypTfnOykhOWw== X-Google-Smtp-Source: AGHT+IEB1pnuwjwK7RZJpRLFmexc//dFJLg5my5LjMjTYPwcUQabd/4riY4FJopA/XdaZlrjvIH1Lg== X-Received: by 2002:a05:620a:240c:b0:7b1:4327:7b63 with SMTP id af79cd13be357-7b9ba7a573bmr7927319085a.32.1735836334680; Thu, 02 Jan 2025 08:45:34 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:34 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 03/44] selinux: support multiple selinuxfs instances Date: Thu, 2 Jan 2025 11:44:28 -0500 Message-Id: <20250102164509.25606-4-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Support multiple selinuxfs instances, one per selinux namespace. The expected usage would be to unshare the SELinux namespace and the mount namespace, and then mount a new selinuxfs instance. The new instance would then provide an interface for viewing and manipulating the state of the new SELinux namespace and would not affect the parent namespace in any manner. This change by itself should have no effect on SELinux behavior or APIs (userspace or LSM). Signed-off-by: Stephen Smalley --- security/selinux/selinuxfs.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 5de86b2b3378..a72fc91f10ec 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -2152,9 +2152,33 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc) return ret; } +static int selinuxfs_compare(struct super_block *sb, struct fs_context *fc) +{ + struct selinux_fs_info *fsi = sb->s_fs_info; + + return (current_selinux_state == fsi->state); +} + static int sel_get_tree(struct fs_context *fc) { - return get_tree_single(fc, sel_fill_super); + struct super_block *sb; + int err; + + sb = sget_fc(fc, selinuxfs_compare, set_anon_super_fc); + if (IS_ERR(sb)) + return PTR_ERR(sb); + + if (!sb->s_root) { + err = sel_fill_super(sb, fc); + if (err) { + deactivate_locked_super(sb); + return err; + } + sb->s_flags |= SB_ACTIVE; + } + + fc->root = dget(sb->s_root); + return 0; } static const struct fs_context_operations sel_context_ops = { From patchwork Thu Jan 2 16:44:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924614 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com [209.85.160.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DEC0D1494D9 for ; Thu, 2 Jan 2025 16:45:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836341; cv=none; b=AnYCkoVBUizQRmU9qGEYcT4Eeq5DXor6sOyeRjPcrfZU1Bo8DwjazpU6TnmlyX9d0OoKZxuWyqy+c4fDDbl90S2bAl/VllHPJMIsAX11r0d5Dbn1RKUlFTIKaAdxWiBqiO3hvQ02vNTO8OTOfcJI3KgN7enM+w9W4PRlod5P4z4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836341; c=relaxed/simple; bh=RcMbi9nddwmJHMorQUzNSo89Dk3dqrzYCUyVlcFTUEk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jP/7yzhW23ODMBh/Wrey01PkoHI6epPvQHT6JDG2UNhl3EDC9Vqe7o1TxDOUALt64ffm4ZxaVoD6o3DkGhKOeg8cheiuGndzq87IoeVqRy5gCrkMh5i75rF5Rt20Y2q8KMVHfgSVCcXg/ux+FT3+DUdbZ7NIVRwzkm6OlMA6h04= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=AKxZthYE; arc=none smtp.client-ip=209.85.160.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AKxZthYE" Received: by mail-qt1-f173.google.com with SMTP id d75a77b69052e-4678afeb133so104917181cf.0 for ; Thu, 02 Jan 2025 08:45:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836335; x=1736441135; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=uT04y3a33bZnWQ3lpMmcbghAidNRHEASFWX7vpcA7YA=; b=AKxZthYE3Gokd+213V3dw6hOF6WOGSN4sR19a7wCMaM65S0+GqkkLu8UeNM+Ew/PEs kuASfyxkr00sb+zDKvPNKYEoFfhGR089JvBF0cupjQbMx4V+L65MHX1g9nQiWqmVyXS3 3Gw0zcWBKTvXj7EznnJfKnSzAaEzcPdO3wK4+4JNhyua6jSrRruFKrDjohBJO9/qQw8D 7Zp4KZSBecUAmuUkQ+RLfhrgYKkYFU/fDfNxAkZsFZWVRSELj+kJnS5Vdar0Y45rBKkf uYw0fumKyTLLdXJQwewgHNFdP2ECuf+dxDCPGQ6sanms+gLiVwU03Lnkj5p+iKmMPIKg kiJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836335; x=1736441135; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uT04y3a33bZnWQ3lpMmcbghAidNRHEASFWX7vpcA7YA=; b=bzlTDDUe3Jj6TB3utav2er/fP0ciJVfbAAn9c7MQEqomygsOfm5ZgyybOQVMikpzR5 l03fZYAGSoV7oGiUIoB/DuUTxWrOdmH9gRGzUzmuSDbno+tUkW+sSpHpT5l1f68w3TNa HgJvrEwHkmsO6qIaIkHE8PevEZUMfrcE7/0cLv5wUcAJL/jj82YUtu+eHnXgyVL2iUTL Sjg9HmZUVWq2ecHLhC0kM1K/AIUdVeI3Xl0laKCFcY1vwuwruTJmeSXE4DxGVQe884ox w4naYgTJejbH28yHk14UZwBFd4dJV3JVJgb+b3H0qvfOMN00UrX9ssFVwyBMq4rJzBdK DkEw== X-Gm-Message-State: AOJu0YyFSwcyrSO5U3ASKg2aXd/z543hY1t9LQwGt04BOZswHRxnkluX 2KgI4Q59mDCn+Xtv6kTF+YN+XU9nvqoxSHSnpazhtA2p31MPBVoxesMEDQ== X-Gm-Gg: ASbGncuUj+WPFFyhFCbGLPCc+UVyfZAoLUiJdxbHgUAxCMhdcD8bsOGeq0dWvTu7z7R FPgI0xRSgvi12Vj1MFvYEV5vm+WJxKFkY2eI30AJlRSCkDwGgcJ9bqk0DcEHoN91CRaln2Llkvj TEYmOQ6AeACN0rDQb+AMX9nTiazqxbs94ZqdHr5+bSFy+8hRqb3nNvBhAH/9GrbtkrX8/fC59J4 tsTNxuETLVybr9tWYa5U1phE1xsgtWZXZdYEKAYoAcPWJVGXIn7jhJNuhH9cMY00gOJP88IKCPL Nr6DTLPdnNzPhHd6HoDZzOw5mu1b8/tyhfy3JQ5eDg1KY+wH6FH/Rdraset9U/+4iuKmMg== X-Google-Smtp-Source: AGHT+IGLWUKA04FiJmlHz3C/h0SB92Hz2g1oWrO29Im/9+lUSZO3vAPT1sA9x3syeWiWbF/+gJQudw== X-Received: by 2002:ac8:590e:0:b0:467:7076:37c7 with SMTP id d75a77b69052e-46a3b0964c4mr815200781cf.22.1735836335273; Thu, 02 Jan 2025 08:45:35 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:34 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 04/44] selinux: dynamically allocate selinux namespace Date: Thu, 2 Jan 2025 11:44:29 -0500 Message-Id: <20250102164509.25606-5-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Move from static allocation of a single selinux namespace to dynamic allocation. Include necessary support for lifecycle management of the selinux namespace, modeled after the user namespace support. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 32 ++++++++++---- security/selinux/hooks.c | 65 +++++++++++++++++++++++++---- security/selinux/include/security.h | 26 +++++++++++- security/selinux/selinuxfs.c | 3 +- security/selinux/ss/services.c | 2 +- 5 files changed, 109 insertions(+), 19 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index effa0accefc5..cc20c5d8b63a 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -91,20 +91,34 @@ struct selinux_avc { struct avc_cache avc_cache; }; -static struct selinux_avc selinux_avc; - -void selinux_avc_init(struct selinux_avc **avc) +int selinux_avc_create(struct selinux_avc **avc) { + struct selinux_avc *newavc; int i; - selinux_avc.avc_cache_threshold = AVC_DEF_CACHE_THRESHOLD; + newavc = kzalloc(sizeof(*newavc), GFP_KERNEL); + if (!newavc) + return -ENOMEM; + + newavc->avc_cache_threshold = AVC_DEF_CACHE_THRESHOLD; + for (i = 0; i < AVC_CACHE_SLOTS; i++) { - INIT_HLIST_HEAD(&selinux_avc.avc_cache.slots[i]); - spin_lock_init(&selinux_avc.avc_cache.slots_lock[i]); + INIT_HLIST_HEAD(&newavc->avc_cache.slots[i]); + spin_lock_init(&newavc->avc_cache.slots_lock[i]); } - atomic_set(&selinux_avc.avc_cache.active_nodes, 0); - atomic_set(&selinux_avc.avc_cache.lru_hint, 0); - *avc = &selinux_avc; + atomic_set(&newavc->avc_cache.active_nodes, 0); + atomic_set(&newavc->avc_cache.lru_hint, 0); + + *avc = newavc; + return 0; +} + +static void avc_flush(struct selinux_avc *avc); + +void selinux_avc_free(struct selinux_avc *avc) +{ + avc_flush(avc); + kfree(avc); } unsigned int avc_get_cache_threshold(struct selinux_avc *avc) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 400e4dec90a5..ad8172ae7fda 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -108,7 +108,7 @@ #define SELINUX_INODE_INIT_XATTRS 1 -static struct selinux_state init_selinux_state; +static struct selinux_state *init_selinux_state; struct selinux_state *current_selinux_state; /* SECMARK reference count */ @@ -7562,16 +7562,67 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { #endif }; +static void selinux_state_free(struct work_struct *work); + +int selinux_state_create(struct selinux_state *parent, + struct selinux_state **state) +{ + struct selinux_state *newstate; + int rc; + + newstate = kzalloc(sizeof(*newstate), GFP_KERNEL); + if (!newstate) + return -ENOMEM; + + refcount_set(&newstate->count, 1); + INIT_WORK(&newstate->work, selinux_state_free); + + mutex_init(&newstate->status_lock); + mutex_init(&newstate->policy_mutex); + + rc = selinux_avc_create(&newstate->avc); + if (rc) + goto err; + + if (parent) + newstate->parent = get_selinux_state(parent); + + *state = newstate; + return 0; +err: + kfree(newstate); + return rc; +} + +static void selinux_state_free(struct work_struct *work) +{ + struct selinux_state *parent, *state = + container_of(work, struct selinux_state, work); + + do { + parent = state->parent; + if (state->status_page) + __free_page(state->status_page); + selinux_policy_free(state->policy); + selinux_avc_free(state->avc); + kfree(state); + state = parent; + } while (state && refcount_dec_and_test(&state->count)); +} + +void __put_selinux_state(struct selinux_state *state) +{ + schedule_work(&state->work); +} + static __init int selinux_init(void) { pr_info("SELinux: Initializing.\n"); - memset(&init_selinux_state, 0, sizeof(init_selinux_state)); - enforcing_set(&init_selinux_state, selinux_enforcing_boot); - selinux_avc_init(&init_selinux_state.avc); - mutex_init(&init_selinux_state.status_lock); - mutex_init(&init_selinux_state.policy_mutex); - current_selinux_state = &init_selinux_state; + if (selinux_state_create(NULL, &init_selinux_state)) + panic("SELinux: Could not create initial namespace\n"); + enforcing_set(init_selinux_state, selinux_enforcing_boot); + current_selinux_state = init_selinux_state; /* Set the security state for the initial task. */ cred_init_security(); diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 14aa2cbb391a..6df38c714d1f 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -104,9 +104,33 @@ struct selinux_state { struct selinux_avc *avc; struct selinux_policy __rcu *policy; struct mutex policy_mutex; + struct selinux_state *parent; + + refcount_t count; + struct work_struct work; } __randomize_layout; -void selinux_avc_init(struct selinux_avc **avc); +int selinux_state_create(struct selinux_state *parent, + struct selinux_state **state); +void __put_selinux_state(struct selinux_state *state); + +void selinux_policy_free(struct selinux_policy __rcu *policy); + +int selinux_avc_create(struct selinux_avc **avc); +void selinux_avc_free(struct selinux_avc *avc); + +static inline void put_selinux_state(struct selinux_state *state) +{ + if (state && refcount_dec_and_test(&state->count)) + __put_selinux_state(state); +} + +static inline struct selinux_state * +get_selinux_state(struct selinux_state *state) +{ + refcount_inc(&state->count); + return state; +} extern struct selinux_state *current_selinux_state; diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index a72fc91f10ec..a59153c322cc 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -90,7 +90,7 @@ static int selinux_fs_info_create(struct super_block *sb) return -ENOMEM; fsi->last_ino = SEL_INO_NEXT - 1; - fsi->state = current_selinux_state; + fsi->state = get_selinux_state(current_selinux_state); fsi->sb = sb; sb->s_fs_info = fsi; return 0; @@ -102,6 +102,7 @@ static void selinux_fs_info_free(struct super_block *sb) unsigned int i; if (fsi) { + put_selinux_state(fsi->state); for (i = 0; i < fsi->bool_num; i++) kfree(fsi->bool_pending_names[i]); kfree(fsi->bool_pending_names); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index db6c17bb274d..bbac5f3f2fd3 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2183,7 +2183,7 @@ static void security_load_policycaps(struct selinux_state *state, static int security_preserve_bools(struct selinux_policy *oldpolicy, struct selinux_policy *newpolicy); -static void selinux_policy_free(struct selinux_policy *policy) +void selinux_policy_free(struct selinux_policy __rcu *policy) { if (!policy) return; From patchwork Thu Jan 2 16:44:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924613 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com [209.85.160.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E112D14D2BB for ; Thu, 2 Jan 2025 16:45:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836341; cv=none; b=Hjk1qnjnOKSHGbzj8XaPA4AB1yTuxmLP15aLpOc8UrS9vJrZe2KPJOqjFK0aEVzGZ3a0a+pG7oDv6ywlvM7wE4AO+pCq0ZRnZhU7M6OV6UHtrtOY4x44Dy5c0hOPPRkEJS+64nf3l7tGQcNQFyF2/FJXrqK7DM/Ftft90+iQ16o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836341; c=relaxed/simple; bh=ztXafw18nKBJhPnq0WpT34WGf3+j9jnaMQ0ItyuaR1w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TcMA5rzynJhxhJXDwM6wJa1P4ybw29iG/3TSYVafFt8+ZL3Pvs6TCg7LYOh3LfdePAUeSHw3Y60erXkKlL9qXx8TVSKFWVrL9WoTr9OkAZnDsSOIzafI+DDNnxJbIhuk5xftnRZJriojoYPluDD3EFcbwUztEoI0Rt40VL0osM0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=JLf7ckY2; arc=none smtp.client-ip=209.85.160.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JLf7ckY2" Received: by mail-qt1-f173.google.com with SMTP id d75a77b69052e-4678664e22fso101979981cf.2 for ; Thu, 02 Jan 2025 08:45:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836337; x=1736441137; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=U3Um5zRV/W7T37Tpj3IijsXpxgyL0XfNem9+py8wIME=; b=JLf7ckY2J60hK2fb/1lSB7qALvj35PCZjSMcEmRKWhwNVsVWcZ1Cg+Mok26Ll1qWkk 7rEMtEQuaXoaF92mDRxetAiMGvMSXqz7Tru2AyeO27HwVHr7RK3lpVyBdjkxcW588Pe4 +1DHo+lG3QG9g3fY1g2bYYXabqqeS7MOAErXXRqwO4GJqEUbmp1KqXoy/7T0uSfMlSf4 mLXNWUw4GwhF+B2zlLAUxE1eHJ+8hIJg6mX5ZJfltHVv60MUX5jGNP6/P4jGulGUxiF6 sDx7juWztEbKfHgpNC8HyuJIqnNaHYcVxkoHjfE8wYnSnXGXHGgOnm92IIIVpqIxOIlr 8xNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836337; x=1736441137; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=U3Um5zRV/W7T37Tpj3IijsXpxgyL0XfNem9+py8wIME=; b=IBUCRWF0cty/uv4q8DSr8TR7chY6dD377b1DeKfzF69wipfV3Wa4FPWsW7zVYEuq/A +4M6nM9kMSlWWB0RsxVwRSezFL/JGo2MRwCLw9ygU7rt7k5rKfQowoD3R7cDLVzL9YVa 15PC+rEDv0b1IbPaEOVKKiUzzuMlEBKlem9ojyqc6jjWgmBtovdeOP6qQPCc5Ww36JXU QfjeZ286aDotRjTjKBB4jL8SmSzg6PTznsUuq9Rn5qyvP23iYOSx8t0s2WW868qoNPf1 ONC+J90hr1k5Ze37VsCZ3Vsxs8Gx6cuOrR2x5V1VVVrWtgJpLpj6D1lHTBFovsZF0qYK RXpQ== X-Gm-Message-State: AOJu0Yw9UKRbPI12D7MjjHJNM6n9wOKLjokn3In6SoD/c4ZGjEaDFQk8 X+bhbVbYiqSIqpKRvxHYHZrDiBO1tLPj72wNqjHMvDFfOlrvM1L/HV4PNA== X-Gm-Gg: ASbGnctjIvC41VpDBqi3m7Odo01n1Pc9U69dRNM/GGfD+U/hBwsBXqOBmsm7BlAY4MJ tYR90uNHBu4agAFLVFJuh5SVRQSx39H7PeqeJi6gFTJB1nQyNSB+aIvsFE2LMmSRopz7+t7RKxV Swc+N+/+6G8wDxuCAhvb4yCvx3kxKjJnnhlB0HYj3DIdERv0WKb5lBaxv9LX/SnTzIEesoyg1lt OfkbxkpUKVNB5J+pz+Omgrjw84XDDrf3Jl/EaeLklcHjhZAU0PldRZTTxFCCzOkR2EiSaBSVikM Gqua9ymENJu31IL1AbNC495CTyfIgrx2ioo/QhxsM5ZJ0nZuMF+BbJ6o6oswFWiF2K7PlA== X-Google-Smtp-Source: AGHT+IElheFvfvqVqxQ/CC3Qi86lpqBJQhpaiyFvzQ9/FquK3hj68UKvbV2kzYl1Yq0gqEze+hRCUg== X-Received: by 2002:ac8:5d90:0:b0:46a:3176:f78b with SMTP id d75a77b69052e-46a4a976ef3mr861452851cf.38.1735836336566; Thu, 02 Jan 2025 08:45:36 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.35 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:35 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 05/44] netstate,selinux: create the selinux netlink socket per network namespace Date: Thu, 2 Jan 2025 11:44:30 -0500 Message-Id: <20250102164509.25606-6-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The selinux netlink socket is used to notify userspace of changes to the enforcing mode and policy reloads. At present, these notifications are always sent to the initial network namespace. In order to support multiple selinux namespaces, each with its own enforcing mode and policy, we need to create and use a separate selinux netlink socket for each network namespace. Without this change, a policy reload in a child selinux namespace causes a notification to be sent to processes in the init namespace with a sequence number that may be higher than the policy sequence number for that namespace. As a result, userspace AVC instances in the init namespace will then end up rejecting any further access vector results from its own security server instance due to the policy sequence number appearing to regress, which in turn causes all subsequent uncached access checks to fail. Similarly, without this change, changing enforcing mode in the child selinux namespace triggers a notification to all userspace AVC instances in the init namespace that will switch their enforcing modes. This change does alter SELinux behavior, since previously reloading policy or changing enforcing mode in a non-init network namespace would trigger a notification to processes in the init network namespace. However, this behavior is not being relied upon by existing userspace AFAICT and is arguably wrong regardless. This change presumes that one will always unshare the network namespace when unsharing a new selinux namespace (the reverse is not required). Otherwise, the same inconsistencies could arise between the notifications and the relevant policy. At present, nothing enforces this guarantee at the kernel level; it is left up to userspace (e.g. container runtimes). It is an open question as to whether this is a good idea or whether unsharing of the selinux namespace should automatically unshare the network namespace. However, keeping them separate is consistent with the handling of the mount namespace currently, which also should be unshared so that a private selinuxfs mount can be created. Signed-off-by: Stephen Smalley --- include/net/net_namespace.h | 3 +++ security/selinux/netlink.c | 31 +++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 873c0f9fdac6..f7d23eca086e 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -192,6 +192,9 @@ struct net { /* Move to a better place when the config guard is removed. */ struct mutex rtnl_mutex; #endif +#if IS_ENABLED(CONFIG_SECURITY_SELINUX) + struct sock *selnl; +#endif } __randomize_layout; #include diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 1760aee712fd..03678a76f4bb 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c @@ -19,8 +19,6 @@ #include "security.h" -static struct sock *selnl __ro_after_init; - static int selnl_msglen(int msgtype) { int ret = 0; @@ -66,6 +64,7 @@ static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void * static void selnl_notify(int msgtype, void *data) { + struct sock *selnl = current->nsproxy->net_ns->selnl; int len; sk_buff_data_t tmp; struct sk_buff *skb; @@ -105,16 +104,36 @@ void selnl_notify_policyload(u32 seqno) selnl_notify(SELNL_MSG_POLICYLOAD, &seqno); } -static int __init selnl_init(void) +static int __net_init selnl_net_init(struct net *net) { + struct sock *sk; struct netlink_kernel_cfg cfg = { .groups = SELNLGRP_MAX, .flags = NL_CFG_F_NONROOT_RECV, }; - selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX, &cfg); - if (selnl == NULL) - panic("SELinux: Cannot create netlink socket."); + sk = netlink_kernel_create(net, NETLINK_SELINUX, &cfg); + if (!sk) + return -ENOMEM; + net->selnl = sk; + return 0; +} + +static void __net_exit selnl_net_exit(struct net *net) +{ + netlink_kernel_release(net->selnl); + net->selnl = NULL; +} + +static struct pernet_operations selnl_net_ops = { + .init = selnl_net_init, + .exit = selnl_net_exit, +}; + +static int __init selnl_init(void) +{ + if (register_pernet_subsys(&selnl_net_ops)) + panic("Could not register selinux netlink operations\n"); return 0; } From patchwork Thu Jan 2 16:44:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924615 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f174.google.com (mail-qk1-f174.google.com [209.85.222.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9AF4A14F9D9 for ; Thu, 2 Jan 2025 16:45:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836342; cv=none; b=IPfmFTZsSPqz1x11WqBt/A9W7jgd7q/RW7+21qcJloZ+uBf+QQgv/BQA3s0h1jp6TW/ODrs9Cf+AdX/s0nUtqU8gPocOHYvdwPM5ihxeZkrxqllFMlQpmlTDNJb/FxBm6rYA0PYzl52+f2uvZDU37uYOLvErEtXBEF9YOe37Ebs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836342; c=relaxed/simple; bh=o8N/64DJtoinQsAVTN05TZEMPh3+U0EiSzZ2huUQjeY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KHi+Qy+x58QsdjDCWi4qhSQtm7i+Bq6VzHMc8URMg5BnJ6VbVZqBHyXLcGjPvRalbvQw+m06/ETlWE0J69Th1UkchVlXXs1uaERkq5ZzdvKWDnpQ4bdeDdGL/FFrUsxRdcPDPQ3Q1OV4foKpDykJIBwC/ViNJvTXRRKCaPPsvlY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=coQTNWbd; arc=none smtp.client-ip=209.85.222.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="coQTNWbd" Received: by mail-qk1-f174.google.com with SMTP id af79cd13be357-7b9bc648736so916186385a.1 for ; Thu, 02 Jan 2025 08:45:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836337; x=1736441137; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=A+jc/YEptHV5+pTbMpMTKlAxeLc9Kx4SucnHji5wT4Y=; b=coQTNWbdrYH9I7Fw4S3550IK8uOGxqGiddZUkLV0A4dGmajHArNcPsz+c3EsYJ3CQr wS42wIdWBfYzZtgIm1YKRI2v5Nt7z22O3HbrWhI2I4xwGZuEZJAIsGmkPURrELjEbre5 YC8tzuFcDqvTi8skYXurintOFgWKoW9z+oplUOVa6yf4sv4vin4hzzaoKcobvk9b7z43 JNYKgLm8XnaG0nrA9iBmKL8L8aycvXp7wSLWLkU3+BaaM173+xjwopwqfdBjYnOmmvwg ORpojA0H+ln65djOUjLd4Eb61VWLHNiQ/6ZrlOzD/spn7X7hQv3+wUJ4XfPoW1rni6lO FBvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836337; x=1736441137; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=A+jc/YEptHV5+pTbMpMTKlAxeLc9Kx4SucnHji5wT4Y=; b=Z7FJsxMr/BiYS/KuSQuuciEhNTRNzh1CWdNQAPtoa0y7Yqlpjg7TEgxkt/POcM6aSg EaXdFvfL57/RdXUki6+bhlYjo7dH+J4lcCKSiS11fNGtNfJmeL8FmSe9HkVPwAVmsScF +H9jvphFaA4MFvlMQBiyOasdWBikcPQAXm7zb87Q3xrl0o9Qlzo0iCXDYg53A0B2/l1G VwyXUQqDFUVnMOFNBhz65zIYxRA66JfhszqqvN4Sma/ccBbo/2txUUoCkYw0K1U4mJ+E rr6Phs40dcuW842WUmIIFyK/3rFHuqPFTNwTpsACkeWjJwdYNIpiZXpXFJdz3sgi1IME Nqqg== X-Gm-Message-State: AOJu0YwUHYpeqsE4Wp/SBu3O3uFQZLiC9zuoYfGNcCYh6bote4eKe9Bx vMp10uvhGAkiw7QCObJQlaW4qB13tlHZuHUZC25VvZ6Jws5ZnvVduy2zUw== X-Gm-Gg: ASbGncuHO0tIBetLocKm97WW+FXN7KLeEEGlYQWRVfwRglI4fANKqPqCC9ETXL3czXF /5HC0yflzFRaTOYcG/LI6WjnxVmXX6bHaapo9aD3pTsn/ZjAdbcz+67E3vXXmW4m8Eyhv8EFwS2 qaLIsbARvcuAZDoPpzI4NMIK640DvEM9To/zpiZP7MgPNmNlcZU0IuhXa4zytdBWUzAh+siLmlC X4NkZ8xqNJauYyTKQnKHhwTqAjNnX/Mwj+BYmV2SBPvmGq4wLABv6DPBQyvrpL/XAdJ0i9Zub5J 2t1Llyx/BZLzW/SmLJDE+xAcpDBC0ai744S+2C9nZ0roRtpm/XZ/5qIYQh5YTrymLeuSKQ== X-Google-Smtp-Source: AGHT+IFy88yNlBpePC5RbZ+qy5kjncym1+MKAk3mwLFVFkCM1VtVm828yyqzJ2CEyKj+J3bzttA0Hg== X-Received: by 2002:a05:620a:44c4:b0:7b6:d2bb:25c4 with SMTP id af79cd13be357-7b9ba83e797mr7991196485a.62.1735836337189; Thu, 02 Jan 2025 08:45:37 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.36 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:36 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 06/44] selinux: support per-task/cred selinux namespace Date: Thu, 2 Jan 2025 11:44:31 -0500 Message-Id: <20250102164509.25606-7-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Extend the task security structure to include a reference to the associated selinux namespace, and to also contain a pointer to the cred in the parent namespace. The current selinux namespace is changed to the per-task/cred selinux namespace for the current task/cred. This change makes it possible to support per-cred selinux namespaces, but does not yet introduce a mechanism for unsharing of the selinux namespace. Thus, by itself, this change does not alter the existing situation with respect to all processes still using a single init selinux namespace. An alternative would be to hang the selinux namespace off of the user namespace, which itself is associated with the cred. This seems undesirable however since DAC and MAC are orthogonal, and there appear to be real use cases where one will want to use selinux namespaces without user namespaces and vice versa. However, one advantage of hanging off the user namespace would be that it is already associated with other namespaces, such as the network namespace, thus potentially facilitating looking up the relevant selinux namespace from the network input/forward hooks. In most cases however, it appears that we could instead copy a reference to the creating task selinux namespace to sock security structures and use that in those hooks. Introduce a task_security() helper to obtain the correct task/cred security structure from the hooks, and update the hooks to use it. This returns a pointer to the security structure for the task in the same selinux namespace as the caller, or if there is none, a fake security structure with the well-defined unlabeled SIDs. This ensures that we return a valid result that can be used for permission checks and for returning contexts from e.g. reading /proc/pid/attr files. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 50 +++++++++++++++++++++++++---- security/selinux/include/objsec.h | 23 ------------- security/selinux/include/security.h | 32 +++++++++++++++++- 3 files changed, 75 insertions(+), 30 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ad8172ae7fda..ddaf1f527fe3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -108,9 +108,6 @@ #define SELINUX_INODE_INIT_XATTRS 1 -static struct selinux_state *init_selinux_state; -struct selinux_state *current_selinux_state; - /* SECMARK reference count */ static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); @@ -207,6 +204,8 @@ static int selinux_lsm_notifier_avc_callback(u32 event) return 0; } +static struct selinux_state *init_selinux_state; + /* * initialise the security for the init task */ @@ -216,6 +215,7 @@ static void cred_init_security(void) tsec = selinux_cred(unrcu_pointer(current->real_cred)); tsec->osid = tsec->sid = SECINITSID_KERNEL; + tsec->state = get_selinux_state(init_selinux_state); } /* @@ -229,6 +229,24 @@ static inline u32 cred_sid(const struct cred *cred) return tsec->sid; } +static struct task_security_struct unlabeled_task_security = { + .osid = SECINITSID_UNLABELED, + .sid = SECINITSID_UNLABELED, +}; + +static const struct task_security_struct *task_security( + const struct task_struct *p) +{ + const struct task_security_struct *tsec; + + tsec = selinux_cred(__task_cred(p)); + while (tsec->state != current_selinux_state && tsec->parent_cred) + tsec = selinux_cred(tsec->parent_cred); + if (tsec->state != current_selinux_state) + return &unlabeled_task_security; + return tsec; +} + static void __ad_net_init(struct common_audit_data *ad, struct lsm_network_audit *net, int ifindex, struct sock *sk, u16 family) @@ -259,10 +277,12 @@ static void ad_net_init_from_iif(struct common_audit_data *ad, */ static inline u32 task_sid_obj(const struct task_struct *task) { + const struct task_security_struct *tsec; u32 sid; rcu_read_lock(); - sid = cred_sid(__task_cred(task)); + tsec = task_security(task); + sid = tsec->sid; rcu_read_unlock(); return sid; } @@ -4067,6 +4087,18 @@ static int selinux_task_alloc(struct task_struct *task, sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); } +/* + * free/release any cred memory other than the blob itself + */ +static void selinux_cred_free(struct cred *cred) +{ + struct task_security_struct *tsec = selinux_cred(cred); + + put_selinux_state(tsec->state); + if (tsec->parent_cred) + put_cred(tsec->parent_cred); +} + /* * prepare a new set of credentials for modification */ @@ -4077,6 +4109,9 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, struct task_security_struct *tsec = selinux_cred(new); *tsec = *old_tsec; + tsec->state = get_selinux_state(old_tsec->state); + if (old_tsec->parent_cred) + tsec->parent_cred = get_cred(old_tsec->parent_cred); return 0; } @@ -4089,6 +4124,9 @@ static void selinux_cred_transfer(struct cred *new, const struct cred *old) struct task_security_struct *tsec = selinux_cred(new); *tsec = *old_tsec; + tsec->state = get_selinux_state(old_tsec->state); + if (old_tsec->parent_cred) + tsec->parent_cred = get_cred(old_tsec->parent_cred); } static void selinux_cred_getsecid(const struct cred *c, u32 *secid) @@ -6499,7 +6537,7 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, u32 len; rcu_read_lock(); - tsec = selinux_cred(__task_cred(p)); + tsec = task_security(p); if (p != current) { error = avc_has_perm(current_selinux_state, current_sid(), tsec->sid, @@ -7363,6 +7401,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(file_open, selinux_file_open), LSM_HOOK_INIT(task_alloc, selinux_task_alloc), + LSM_HOOK_INIT(cred_free, selinux_cred_free), LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare), LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer), LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid), @@ -7622,7 +7661,6 @@ static __init int selinux_init(void) if (selinux_state_create(NULL, &init_selinux_state)) panic("SELinux: Could not create initial namespace\n"); enforcing_set(init_selinux_state, selinux_enforcing_boot); - current_selinux_state = init_selinux_state; /* Set the security state for the initial task. */ cred_init_security(); diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index c88cae81ee4c..d522caa7f93a 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -29,15 +29,6 @@ #include "flask.h" #include "avc.h" -struct task_security_struct { - u32 osid; /* SID prior to last execve */ - u32 sid; /* current SID */ - u32 exec_sid; /* exec SID */ - u32 create_sid; /* fscreate SID */ - u32 keycreate_sid; /* keycreate SID */ - u32 sockcreate_sid; /* fscreate SID */ -} __randomize_layout; - enum label_initialized { LABEL_INVALID, /* invalid or not initialized */ LABEL_INITIALIZED, /* initialized */ @@ -149,10 +140,6 @@ struct perf_event_security_struct { }; extern struct lsm_blob_sizes selinux_blob_sizes; -static inline struct task_security_struct *selinux_cred(const struct cred *cred) -{ - return cred->security + selinux_blob_sizes.lbs_cred; -} static inline struct file_security_struct *selinux_file(const struct file *file) { @@ -179,16 +166,6 @@ selinux_ipc(const struct kern_ipc_perm *ipc) return ipc->security + selinux_blob_sizes.lbs_ipc; } -/* - * get the subjective security ID of the current task - */ -static inline u32 current_sid(void) -{ - const struct task_security_struct *tsec = selinux_cred(current_cred()); - - return tsec->sid; -} - static inline struct superblock_security_struct * selinux_superblock(const struct super_block *superblock) { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 6df38c714d1f..a66f061c7784 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include "flask.h" @@ -132,7 +134,35 @@ get_selinux_state(struct selinux_state *state) return state; } -extern struct selinux_state *current_selinux_state; +struct task_security_struct { + u32 osid; /* SID prior to last execve */ + u32 sid; /* current SID */ + u32 exec_sid; /* SID upon next execve */ + u32 create_sid; /* SID for new files */ + u32 keycreate_sid; /* SID for new keys */ + u32 sockcreate_sid; /* SID for new sockets */ + struct selinux_state *state; /* selinux namespace */ + const struct cred *parent_cred; /* cred in parent ns */ +} __randomize_layout; + +extern struct lsm_blob_sizes selinux_blob_sizes; + +static inline struct task_security_struct *selinux_cred(const struct cred *cred) +{ + return cred->security + selinux_blob_sizes.lbs_cred; +} + +/* + * get the subjective security ID of the current task + */ +static inline u32 current_sid(void) +{ + const struct task_security_struct *tsec = selinux_cred(current_cred()); + + return tsec->sid; +} + +#define current_selinux_state (selinux_cred(current_cred())->state) static inline bool selinux_initialized(const struct selinux_state *state) { From patchwork Thu Jan 2 16:44:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924617 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f178.google.com (mail-qt1-f178.google.com [209.85.160.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46AEE12EBE7 for ; Thu, 2 Jan 2025 16:45:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836342; cv=none; b=P99RXHkcKqAPLtTVoKppu5gkErwQ8wslVL/owLhA0Is0GMwH/ovVvKBOhDZMTP89Cd2kK8ogVk+413XJmIyrJ8Kx7AiS/Zs4mhnEpf6xH0uIienHNQEEJOvVTYCKPsbOJ95gl4fQYMNS/Zkwgg3a4pw4lN+2ucA9p+OjcBz+Cw4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836342; c=relaxed/simple; bh=SIRjXLX/AiPGgT0i/bxGUipBbo3ELVEhnxSBNSeTOzo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=urowfAxfzz/NxCKCy0fBB6+iknR8Mw2p+RSZFVcFQTIUD243zQzFtlfORC623Kw6ZiRXCj5NbW0r9Eq548zeLeoiLDpSCheFjae0rJBaPdT1BmCChbIWgWb91aubi+ZRLitoV0jWa41Cg0EfMSfevkOtzSbxei2GCnO9DFjgq+c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=msWhZ8S3; arc=none smtp.client-ip=209.85.160.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="msWhZ8S3" Received: by mail-qt1-f178.google.com with SMTP id d75a77b69052e-46769b34cbfso171273611cf.0 for ; Thu, 02 Jan 2025 08:45:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836338; x=1736441138; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8MLJGuOZ6VMPcpfBG7y3RY8a4Gr/qjOpRbiH1q9Ej+I=; b=msWhZ8S371ScHsThRohPCk3860+u1bTGTPdi8gDIjmvYA5dToLTZTCM2pm7z8oEI3k wUvKA81F75+r+qzx4f3p13oucK3NYkS+aykMgKu9OSsLk+2IYJ+a0FCgPnlPqghXHWJE ZUzH02EUcda1TaepSIwN3nEHs5kGDoS+LtfACI6veawvvIqeToDvb4gzlGlIBDT1xP/K mpWW1M44BC6MXUWR9NSDQpm+Ta6cPoO+ELuUvsSbeq7wXFEHY//MPGxGyBK7aV5FJx1A 6baRUeT3f6yXtw+1nr/HRjn4XosVIG3NkXYcGrJeS8ahTZ+HvRToDGItNplvRqqjhgoB ipiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836338; x=1736441138; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8MLJGuOZ6VMPcpfBG7y3RY8a4Gr/qjOpRbiH1q9Ej+I=; b=hF4cAqUPPvxXTDArJI2QYCA/ceXS07SeMtOLH2ESGa0R/2/R3Zs+qpPK6McMugrpvC DzMHQGOdB8j9a2JSh+Nh0F6xc3Ca6SI8LMNkhulTJH9kt9aUzSV56Hvgx9oGoLxMGM8J PCLUylL8dOBptHfUXhDpcyGslr5AqjBcS6WgqVSAoPWZWt8F6IxMVImvMKHBhVzBSn9D f9MSMYqjpyYN0FUd8dmII0L/ZWlFce+v1eJAh0Q2R5fDNxatiSU/gapRRG1gkj2KwAdn 9p8C4y0DTjZai5f5HIP6cXYSqrlQaD34lGJ1p2RQvMAUU21+wK7PT4eS3bfr4ZTMGtgO BzQQ== X-Gm-Message-State: AOJu0YyIH+YBfxFuce2iqCBc5CkKmF6T0DmMf7zmQhgNZL3JJON5Hrvm cd4yL6ixC5mmy+LmwnIVDp1Xdhoc5lj7RQsJq1RP3bhApadXJJ+A7dxJSQ== X-Gm-Gg: ASbGnctaGgUqGUOgvT7rzs05y5TNUrX8WRlvQmP1KPi6kRA6RqppDPeJk/ff2J3dQKL aziDxQc5GZGACnagWSsM438Hfb9Yv7x+SD7/gEQKHaY3hx/g41Ipy7Nb6BMo9NIdmMieIfIIZYK 7g2qbEg/2daqTftELZ4cAaqkWtiOVcCymLvovzNk1YJQmgXslUOqSu0vh5fybwKJxg+fiD2c6zf Iq89uJu8IZZl0ZYc/e6n3A9FinlqBnAOYzIsv5puLS2v6CFURwZw9i2sVoFji2VwygdWhbqqCZD ff9GszHBFN21uXHJuj+CT1XtnXYxuoV5tPaohWIX/mAJWvE9v307LVQzQR8EqrBunQDhHw== X-Google-Smtp-Source: AGHT+IECIFxOPaJNFBqz+azW2rITeXiFwpSXys0Uh7+GLARosBQYz4egDHV61b+yKnsYYO/V5pTDOA== X-Received: by 2002:a05:622a:1a28:b0:46a:3709:6780 with SMTP id d75a77b69052e-46a4a8dcbe6mr789930311cf.19.1735836337764; Thu, 02 Jan 2025 08:45:37 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.37 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:37 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 07/44] selinux: introduce cred_selinux_state() and use it Date: Thu, 2 Jan 2025 11:44:32 -0500 Message-Id: <20250102164509.25606-8-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When using the SID from a cred, we should pass the selinux namespace associated with the cred on security server calls rather than the current selinux namespace, since they could differ. In some of these cases, the cred is always obtained from the current task so there is no real change, but this is cleaner and hopefully less fragile. In other cases, the cred could in fact differ. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 44 ++++++++++++++--------------- security/selinux/include/security.h | 2 ++ 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ddaf1f527fe3..1aa0bb1a83ce 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -454,13 +454,13 @@ static int may_context_mount_sb_relabel(u32 sid, const struct task_security_struct *tsec = selinux_cred(cred); int rc; - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(cred), tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(cred), tsec->sid, sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, NULL); return rc; @@ -472,13 +472,13 @@ static int may_context_mount_inode_relabel(u32 sid, { const struct task_security_struct *tsec = selinux_cred(cred); int rc; - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(cred), tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(cred), sid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, NULL); return rc; @@ -1675,10 +1675,10 @@ static int cred_has_capability(const struct cred *cred, return -EINVAL; } - rc = avc_has_perm_noaudit(current_selinux_state, + rc = avc_has_perm_noaudit(cred_selinux_state(cred), sid, sid, sclass, av, 0, &avd); if (!(opts & CAP_OPT_NOAUDIT)) { - int rc2 = avc_audit(current_selinux_state, + int rc2 = avc_audit(cred_selinux_state(cred), sid, sid, sclass, av, &avd, rc, &ad); if (rc2) return rc2; @@ -1703,7 +1703,7 @@ static int inode_has_perm(const struct cred *cred, sid = cred_sid(cred); isec = selinux_inode(inode); - return avc_has_perm(current_selinux_state, + return avc_has_perm(cred_selinux_state(cred), sid, isec->sid, isec->sclass, perms, adp); } @@ -1777,7 +1777,7 @@ static int file_has_perm(const struct cred *cred, ad.u.file = file; if (sid != fsec->sid) { - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(cred), sid, fsec->sid, SECCLASS_FD, FD__USE, @@ -1992,7 +1992,7 @@ static int superblock_has_perm(const struct cred *cred, u32 sid = cred_sid(cred); sbsec = selinux_superblock(sb); - return avc_has_perm(current_selinux_state, + return avc_has_perm(cred_selinux_state(cred), sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); } @@ -2174,7 +2174,7 @@ static int selinux_capset(struct cred *new, const struct cred *old, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) { - return avc_has_perm(current_selinux_state, + return avc_has_perm(cred_selinux_state(old), cred_sid(old), cred_sid(new), SECCLASS_PROCESS, PROCESS__SETCAP, NULL); } @@ -3749,7 +3749,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, ad.u.op->path = file->f_path; if (ssid != fsec->sid) { - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(cred), ssid, fsec->sid, SECCLASS_FD, FD__USE, @@ -3859,7 +3859,7 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared * private file mapping that will also be writable. * This has an additional check. */ - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(cred), sid, sid, SECCLASS_PROCESS, PROCESS__EXECMEM, NULL); if (rc) @@ -3939,14 +3939,14 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, */ if (vma->vm_start >= vma->vm_mm->start_brk && vma->vm_end <= vma->vm_mm->brk) { - rc = avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_PROCESS, - PROCESS__EXECHEAP, NULL); + rc = avc_has_perm(cred_selinux_state(cred), sid, sid, + SECCLASS_PROCESS, PROCESS__EXECHEAP, + NULL); } else if (!vma->vm_file && (vma_is_initial_stack(vma) || vma_is_stack_for_current(vma))) { - rc = avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_PROCESS, - PROCESS__EXECSTACK, NULL); + rc = avc_has_perm(cred_selinux_state(cred), sid, sid, + SECCLASS_PROCESS, PROCESS__EXECSTACK, + NULL); } else if (vma->vm_file && vma->anon_vma) { /* * We are making executable a file mapping that has @@ -4149,7 +4149,7 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid) u32 sid = current_sid(); int ret; - ret = avc_has_perm(current_selinux_state, + ret = avc_has_perm(tsec->state, sid, secid, SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__USE_AS_OVERRIDE, @@ -4174,7 +4174,7 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) u32 sid = current_sid(); int ret; - ret = avc_has_perm(current_selinux_state, + ret = avc_has_perm(tsec->state, sid, isec->sid, SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__CREATE_FILES_AS, @@ -4326,7 +4326,7 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre av |= PROCESS__SETRLIMIT; if (flags & LSM_PRLIMIT_READ) av |= PROCESS__GETRLIMIT; - return avc_has_perm(current_selinux_state, + return avc_has_perm(cred_selinux_state(cred), cred_sid(cred), cred_sid(tcred), SECCLASS_PROCESS, av, NULL); } @@ -6927,7 +6927,7 @@ static int selinux_key_permission(key_ref_t key_ref, key = key_ref_to_ptr(key_ref); ksec = selinux_key(key); - return avc_has_perm(current_selinux_state, + return avc_has_perm(cred_selinux_state(cred), sid, ksec->sid, SECCLASS_KEY, perm, NULL); } diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index a66f061c7784..8f8531b80bfd 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -164,6 +164,8 @@ static inline u32 current_sid(void) #define current_selinux_state (selinux_cred(current_cred())->state) +#define cred_selinux_state(cred) (selinux_cred(cred)->state) + static inline bool selinux_initialized(const struct selinux_state *state) { /* do a synchronized load to avoid race conditions */ From patchwork Thu Jan 2 16:44:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924616 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f176.google.com (mail-qt1-f176.google.com [209.85.160.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46A7B47A73 for ; Thu, 2 Jan 2025 16:45:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836342; cv=none; b=O5srxTdPNNAH6+8gOukqRVBYB3a6QLFj2QlkLPrPXRfSdl11rH7SjPL/A2qqVZ+5M6BVL8vtIgY/3Z3LxgJaPa5rbO6vbkls9ajSp+g7wIYLErzG2zeh672MkyTo1MCxpNwcM+EWiNxclthJ+CxVtDlwaC7wHkxRrYL1iOkevb0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836342; c=relaxed/simple; bh=HMoh+CVAagzEUUs7NbFsEdUMiBQqgYYbI58FoRU0m2E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ptdsJtdYOcYOmZs1bhWOB6lx7AAMVsZiYwD+ZxzfW2u3WgvmGaR6ouqQ85O/r0CA53YNkhrdqBiEHIG/LmoXGTxoD8tPTlqQwJaFiat86f5a9tRbdZWLBCH7hJenwDuFuInoCr7Fz6jfqPjlnzbXSmR0ANynfWAShAFh5IfniAo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ERH3Rmrv; arc=none smtp.client-ip=209.85.160.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ERH3Rmrv" Received: by mail-qt1-f176.google.com with SMTP id d75a77b69052e-46769b34cbfso171273761cf.0 for ; Thu, 02 Jan 2025 08:45:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836338; x=1736441138; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=AnTaYUE0YNGHxKzd9uyIbsHleaxCw57uQdQFo4wr8To=; b=ERH3RmrvqO66SPqVmksNdK0AncvbukiI5Pf016fiXnzII8zZZhqyP/RiWgMo6DEU08 oNRdxm32WW2OwDQNeBTI0Hhc3ApsVCybvIH7PRcpg5kCzBq7yIYZlxhRFkPPiXC+UNLU NI42NBa5PkjaUx7HsG6KKc8/NN8X09kf6Hx3yhD+woAvrZc60wFrb3SeUROdGeB0m3k6 bIQTgz8W7y9RqJDi4Aw5tRN0L2q4vaCk6KB6wynkl8hMsqKFuBmGrVbWsly7ceDApoH0 l/e0TpZn8RZnIojcj94ggQtX2cVMUCVG4nSlNvjP9XkJC8Qi49oyZPcOOblb2elC+NfZ 9LOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836338; x=1736441138; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AnTaYUE0YNGHxKzd9uyIbsHleaxCw57uQdQFo4wr8To=; b=XkEEZ6i9sOF9HceK0ToItdlNqnuC6nKm9rGcu652VBfrddg+yw98R5deNSnjbPREiw wXg5dZ34k8GMLXVZIIzt11adt+O0ouMVMw+y8cLF4+zFsHMkZW8jMIcKWvEMQVi+yLc3 TNw26Ihex8U1tStzpHJEJRdwJPTW0rzfgQTYCBkNOpW8tT52/AdOpRJnVqQXvp6mzFPc um2eMXJKS7AF893h5IfI+gjLqvZnCY+ZVMwpduvqsvno8tPRZimYUL1DtF66ys9hJWbA WXvUa6isCEnnS/Pzbh2Kk4CdAn/VAAO3Dt37beIFk1UazGDSp0PwjJ9Ksy6H8RNu5R5C YAXw== X-Gm-Message-State: AOJu0YwED+lALFXsAjqWvnixrMS1Zh5SOl1hUB2eFJOOR37iGKGpIIQI rMdlzC/2ZYQLCvQrEVloD9L+UaW0MX19w+AC3+k6TI218QNCBO5Cv8OPWg== X-Gm-Gg: ASbGnctTv2GC3llcEXD0BbUCqG2s3Lak7lj2ogNNbMDnLrBJ65Ar/xIOL4Yaup9zx5I DgaO8xWmHWuDzj+90t13yFxzGUNuWdMzMz8+YQ4ZrwgOzvXpYhh6T7leBgGhde2vpJrvMAPt3Yo 8AFnhYyz6vFhtX2N4G1nbpjxodnrpgfIe36SS3Mrv9oEIuYzrI4jXlsvjBn90kxeKkL3qhUfq3M wcFWYTOUkPz4ENh1uNG/cBi6YTEwcWaASt60OHgh93esIkgFpDiNGpPcbWwrGrkdyA6lmD6BQef QjHFKsiutZYrXK0JPozkt0y3WNQD07zp4QgqBnjNTOyFgnzVMbnO7qcpIgqzyEFzmQdDxg== X-Google-Smtp-Source: AGHT+IHXOpxSt3OKD9vxkC3dCEVUuhap6BiHFQu9sANqzIU4SpAtMYwsGUhtsyO/Td5cs7UqcnyZ2w== X-Received: by 2002:ac8:5952:0:b0:467:b7de:da93 with SMTP id d75a77b69052e-46a4a8baed3mr645614251cf.6.1735836338356; Thu, 02 Jan 2025 08:45:38 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.37 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:38 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 08/44] selinux: add a selinuxfs interface to unshare selinux namespace Date: Thu, 2 Jan 2025 11:44:33 -0500 Message-Id: <20250102164509.25606-9-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Provide a userspace API to unshare the selinux namespace. Currently implemented via a selinuxfs node. This could be coupled with unsharing of other namespaces (e.g. mount namespace, network namespace) that will always be needed or left independent. Don't get hung up on the interface itself, it is just to allow experimentation and testing. Sample usage: sudo bash echo 1 > /sys/fs/selinux/unshare # unshare SELinux namespace unshare -m -n # unshare mount and network namespaces umount /sys/fs/selinux # unmount parent selinuxns mount -t selinuxfs none /sys/fs/selinux # mount child selinuxns id # view initial SID in child namespace, now kernel/init load_policy # load a policy into child namespace id # view context in child namespace after policy load getenforce # check enforcing status of child namespace The above will show that the process now views itself as running in the kernel/init domain in permissive mode, as would be the case at boot. From a different shell on the host system, running ps -eZ or cat /proc//attr/current will show that the process that unshared its selinux namespace is still running in its original context in the initial namespace, and getenforce will show the the initial namespace remains enforcing. Enforcing mode or policy changes in the child will not affect the parent. Signed-off-by: Stephen Smalley --- security/selinux/include/classmap.h | 2 +- security/selinux/selinuxfs.c | 66 +++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 2bc20135324a..84285fba2c06 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -50,7 +50,7 @@ const struct security_class_mapping secclass_map[] = { { "compute_av", "compute_create", "compute_member", "check_context", "load_policy", "compute_relabel", "compute_user", "setenforce", "setbool", "setsecparam", "setcheckreqprot", "read_policy", - "validate_trans", NULL } }, + "validate_trans", "unshare", NULL } }, { "process", { "fork", "transition", "sigchld", "sigkill", "sigstop", "signull", "signal", "ptrace", diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index a59153c322cc..120cfff35029 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -64,6 +64,7 @@ enum sel_inos { SEL_STATUS, /* export current status using mmap() */ SEL_POLICY, /* allow userspace to read the in kernel policy */ SEL_VALIDATE_TRANS, /* compute validatetrans decision */ + SEL_UNSHARE, /* unshare selinux namespace */ SEL_INO_NEXT, /* The next inode number to use */ }; @@ -318,6 +319,70 @@ static const struct file_operations sel_disable_ops = { .llseek = generic_file_llseek, }; +static ssize_t sel_write_unshare(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) + +{ + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; + char *page; + ssize_t length; + bool set; + int rc; + + if (count >= PAGE_SIZE) + return -ENOMEM; + + /* No partial writes. */ + if (*ppos != 0) + return -EINVAL; + + rc = avc_has_perm(current_selinux_state, current_sid(), + SECINITSID_SECURITY, SECCLASS_SECURITY, + SECURITY__UNSHARE, NULL); + if (rc) + return rc; + + page = memdup_user_nul(buf, count); + if (IS_ERR(page)) + return PTR_ERR(page); + + length = -EINVAL; + if (kstrtobool(page, &set)) + goto out; + + if (set) { + struct cred *cred = prepare_creds(); + struct task_security_struct *tsec; + + if (!cred) { + length = -ENOMEM; + goto out; + } + tsec = selinux_cred(cred); + if (selinux_state_create(state, &tsec->state)) { + abort_creds(cred); + length = -ENOMEM; + goto out; + } + tsec->osid = tsec->sid = SECINITSID_KERNEL; + tsec->exec_sid = tsec->create_sid = tsec->keycreate_sid = + tsec->sockcreate_sid = SECSID_NULL; + tsec->parent_cred = get_current_cred(); + commit_creds(cred); + } + + length = count; +out: + kfree(page); + return length; +} + +static const struct file_operations sel_unshare_ops = { + .write = sel_write_unshare, + .llseek = generic_file_llseek, +}; + static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { @@ -2052,6 +2117,7 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc) [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO}, [SEL_VALIDATE_TRANS] = {"validatetrans", &sel_transition_ops, S_IWUGO}, + [SEL_UNSHARE] = {"unshare", &sel_unshare_ops, 0200}, /* last one */ {""} }; From patchwork Thu Jan 2 16:44:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924618 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f176.google.com (mail-qt1-f176.google.com [209.85.160.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C93F148304 for ; Thu, 2 Jan 2025 16:45:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836342; cv=none; b=mbkcmcqS3uQnlzE+toW8Q6s1iQWWdVa3D9ZXJ5UYSNtsmD9+N2HWqVYvHRevoYqVWHAv09DQ2vBDD6bKEHJmo01PLj+Mj+HG+L/S+mfpNky9Buyfr7G9B7fC0+LReq4yGPc07TXebUNOl6HRB07nI6ECZh9adQ1GVF9FIwy8aEY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836342; c=relaxed/simple; bh=i2P4oCa9hkqpT71p39TKSS/5YL3pQ6uw60fPVg3SdQM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=k7stasVSi2VcPf6Z3G1Y+6+iYZeFG4Ww0c1sKUK5C6+OhROxwpOL0+mFQLVgmvVWR4xmKSJCCw4bsPVU7987UDd8OqvPJJgkzbtH/zI98D88xGfM4J4i57x65MIHNCQX9/mhMZCKHoN1M1O5lDEWGAOGlmwjsWG2vNBb2gDUUcQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=PYwxOwY1; arc=none smtp.client-ip=209.85.160.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PYwxOwY1" Received: by mail-qt1-f176.google.com with SMTP id d75a77b69052e-467a63f5d1cso101663521cf.0 for ; Thu, 02 Jan 2025 08:45:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836339; x=1736441139; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=csT6Vl2cSdQwwE//FlLeaEOzUL91iYA1bbItlkvqKF8=; b=PYwxOwY1Q+M4O/FkSxeuxbh5BBQN4BMvVwPRQrKplwUvfiLKZqwso19qwZtt9k1l7G H1Iju57+M9sI+aCg1vlJ7mw2EjRuDLrYXYsgaUYL6OQb1tzzQASDlv6m6rfGm47xR/ws o22dSPN3/u7qBN9SdTTgbvUl1uA4wtARZBgfi98QLHwlqBWg8iGWJhzQB5v6wE8FEpOr P/8M1QKPDGTqnARZyAO8bYu3cUEoX9EoAYkFkwx1IEGzcw5MRZP+brnWhgtt4B/4zAlC 5CiWd683G/PmSCjZ0ROLcOUP3AuBfaozrjXNQfdi8qfNUhYHhtk6BiUtaw0GGXI4Ocey OeZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836339; x=1736441139; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=csT6Vl2cSdQwwE//FlLeaEOzUL91iYA1bbItlkvqKF8=; b=O2xIk99dJuR6KacmXAaKntKyLgikJyvB5xJPJJTbA+rb/R0UCiVFBYaXJFpfQwNwzQ xAf1XpTFItKXqZ9UiRdhViCMVnBiAeWddV4568eIT7oqAp+pDkt319IrC6KI8GaNjZtq UZZQF7dZYXhLXHHPxO80NNFrZUP7DrjrPB7u3Iksvg0IPpUjkIGPX8tS88E8F44fgQsT cgOzOoy33A/3SzhYS5S28Qd7Sc1n7FaJq16EbR0m3NaQAFFfyRBMmsyQLdmGATXnERBB tfm4ze5Ig2hvP7SMf+uG7M/6Umw6lmpqjLEZA4icHH20ASl+8cHIVZ0udLlCbT001oOU lE3w== X-Gm-Message-State: AOJu0YzjJuBtpOuL8Btj9CfO9qJ1JdFymeIrj1QpBM7Hqz936K3x07Pk w9iShP9Si1+/wgQsxaOPbNdN7PyTbIMhcg36+RSvxzcVid0Fb76ySbELPg== X-Gm-Gg: ASbGncs1JOxGLEqW7XIO18JzNYctS3JUZPG0mnIuGvEyq9f5vzwaTDwlpSOE9znP8h8 EVS0qt9fM393yU0o0GhkWRyccajJIrzxQxUjGZN+VJPyoFBeUIghgnjbQEXRrRik5OHcjYtfmjg KAaUdUessgv0apXkebm12lPL0xxDKq1gdduRc44Ypnrjt38bjIzLHFNHv0hE6pxdIoAk1awx+Fu VadlS64HsEzvY7d4r4nq3L9pJ61WWJZMWAZVJW2GPkPwLtEmRErrK6YHeRtjxttjpzQlgxHkDLz eYV+05KYr3Xvnk2rH9Z+8pqCBRtisRzKGnXB/r0wqUUUT0m0gWOsXp9JHhxT+yhn7uDAjg== X-Google-Smtp-Source: AGHT+IGVVBmHqwgQAlshdVSMnIK+XqcFDZLcHaXM8gy4loW28fKtqJgpqwzRzoTiAi/8lsSrN4xX2g== X-Received: by 2002:a05:622a:654:b0:467:5a0b:de08 with SMTP id d75a77b69052e-46a4a8ae1eamr689891571cf.8.1735836338894; Thu, 02 Jan 2025 08:45:38 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.38 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:38 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 09/44] selinuxfs: restrict write operations to the same selinux namespace Date: Thu, 2 Jan 2025 11:44:34 -0500 Message-Id: <20250102164509.25606-10-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This ensures that once a process unshares its selinux namespace, it can no longer act on the parent namespace's selinuxfs instance, irrespective of policy. This is a safety measure so that even if an otherwise unconfined process unshares its selinux namespace, it won't be able to subsequently affect the enforcing mode or policy of the parent. This also helps avoid common mistakes like failing to create a mount namespace and mount a new selinuxfs instance in order to act on one's own selinux namespace after unsharing. Signed-off-by: Stephen Smalley --- security/selinux/selinuxfs.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 120cfff35029..0702aeb0c5b8 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -148,6 +148,9 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, int scan_value; bool old_value, new_value; + if (state != current_selinux_state) + return -EPERM; + if (count >= PAGE_SIZE) return -ENOMEM; @@ -330,6 +333,9 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf, bool set; int rc; + if (state != current_selinux_state) + return -EPERM; + if (count >= PAGE_SIZE) return -ENOMEM; @@ -662,6 +668,9 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, if (!count) return -EINVAL; + if (fsi->state != current_selinux_state) + return -EPERM; + mutex_lock(&fsi->state->policy_mutex); length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, @@ -766,6 +775,9 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, ssize_t length; unsigned int new_value; + if (fsi->state != current_selinux_state) + return -EPERM; + length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, @@ -822,6 +834,9 @@ static ssize_t sel_write_validatetrans(struct file *file, u16 tclass; int rc; + if (state != current_selinux_state) + return -EPERM; + rc = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL); @@ -909,10 +924,14 @@ static ssize_t (*const write_op[])(struct file *, char *, size_t) = { static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) { + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; ino_t ino = file_inode(file)->i_ino; char *data; ssize_t rv; + if (fsi->state != current_selinux_state) + return -EPERM; + if (ino >= ARRAY_SIZE(write_op) || !write_op[ino]) return -EINVAL; @@ -1352,6 +1371,9 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; const char *name = filep->f_path.dentry->d_name.name; + if (fsi->state != current_selinux_state) + return -EPERM; + if (count >= PAGE_SIZE) return -ENOMEM; @@ -1408,6 +1430,9 @@ static ssize_t sel_commit_bools_write(struct file *filep, ssize_t length; int new_value; + if (fsi->state != current_selinux_state) + return -EPERM; + if (count >= PAGE_SIZE) return -ENOMEM; @@ -1539,6 +1564,9 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, ssize_t ret; unsigned int new_value; + if (state != current_selinux_state) + return -EPERM; + ret = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETSECPARAM, From patchwork Thu Jan 2 16:44:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924620 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f178.google.com (mail-qt1-f178.google.com [209.85.160.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6AEB81547FB for ; Thu, 2 Jan 2025 16:45:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836344; cv=none; b=PypUbhSFxh6kbFjiGAaqA/DUOQk1JqkpU2eBi0+YWoHGz1XWmPPc5W43Z6qlL5VTxyaKMLUJxVVju5rmVDjXHdkk6Sb6ovQOgH7Uww/IqmXWPASeK0KFRY7LOFkNqhZYNSGRm0O2g2g5X0udoMcrzMtMBbBaTUFxnTxR/9yh9/w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836344; c=relaxed/simple; bh=+wgSUrfBNcSxnhjdhXGTQqX8dDLfMwhcw/rztHHLK6g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=c9OivI4jVv1ACmHdPmxaRTFhlgYuHVbXrwtu0uMr3l/OSfj7TyHlX6goronwvvqH4JqP8OJokZcVqBJg+3anL3Q6OL/ZzsA9zwLS3Wp3hVdSvnHqY3NGzKNimSU9m/VKI7mgxZkREXm7SH18jm5VfaHq2N0vhRKHCVDjo9bP+1I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=K9MnNJ0X; arc=none smtp.client-ip=209.85.160.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="K9MnNJ0X" Received: by mail-qt1-f178.google.com with SMTP id d75a77b69052e-467a1ee7ff2so94757461cf.0 for ; Thu, 02 Jan 2025 08:45:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836340; x=1736441140; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ss3+Xgf2qnfOq82Ts7mEUS75c6/pwDte5IzPghKPzB8=; b=K9MnNJ0XzCL2GMws+Fpn7v/imK4rFAT82y6/dA/Iqg4U7vs6mgTEzzpQETaXE+sILw w2Ef8kpUIb0gPlf0PVvq7pkFRt0w4iOn/5SWPd4f65zQngSm+PGoznFrP+EfYqIh5cDT vfPhwkFQJslVyczoAt4i+FGHzPnQ3i2mc4cr61LzKwB0HbM56V04xcsSrNEQWC0Wdo2Y FWiU1VWtQRF8wF/3vaqEI1pyQ0CxefVNXavS78B0R7YsX9N3Bu+bSd7CXDc+iBugsoeu 5mvD0l3Ai7M2yZjQJQQuH0/PQV00vUFHD5t3/MWJSfAzT9jr+5J/x8jXtcPMqTVedX65 SdaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836340; x=1736441140; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ss3+Xgf2qnfOq82Ts7mEUS75c6/pwDte5IzPghKPzB8=; b=Cek0rV0GONc54T3dkGOJGT2ag1P89aZEC4tvILLICqoGY2+rBj8qfwCAU5Ab5xtTDs KZWJdgKTQivCCKzpl1Rs5JS8tQhC4Q3f/KCt9pU1Nw2BAf39IU24l1RkyduITa7EYatM zFisFDQxAIg8lqOGJ9yT+TArbBTUSVVI+WMUvSOgKjdDUewgwikfbJGHR70Uy5NQl5H0 ZlEIfGhNA05VHBtxn5HaVEF8iackfitOprT6qEkVf3/xz7q4rw2kQNEX49YNe6WT0Hxe u7AV5FZR8/Znedut8fyARF4FNNFvi7vMo+hTDrM/5MXTRtv3hN1D3Bo4JHPe8T/GFlBF DwFQ== X-Gm-Message-State: AOJu0Yz7U7pxVqpu2nHGrRE1CK1NERVT4o076qLxl4XbhHs2KA8omQod rngzs3aflviBNKvUlZCnJd5pARKhJMLUcmWxxKCh9Q1rfj/HXDqQbqR39A== X-Gm-Gg: ASbGnctpKXfijsam9heapt7LMAoGuBFNpeLKMz9dkDgfkLN5mJbGfHwVeTEnphFavur g+CuDrI7op9Jk3hU16feqjFp2W0JQBKMymr5qOdilnjBIQnOH6P9fVeiX3nxnKd0WYIRYBfrgxg kEefgF1ayr/vd/OncBpWXK/wO0O6wjuA0UqzmjbWFxTSOqviy0hk1VF2ZRjb2SdiFr6mzNQ7UWf BoJKfgENfEA60P+zzqbKiHFqKr5S/oiVqyLS2yThcpx/jCXL9PcJ42HQhXFuK9pczZiw2w7toNz dZBDjDQVRgLUEh35lqKzYxMYr1Xa0i3f6BOAHgh6YsFuWuDfOAJn5lXERa8XTroxNz+91A== X-Google-Smtp-Source: AGHT+IFYVzcT0DttA1ea16/WZKDKLgmk/tNsTUSN3YacHSNRLdhbXKYfcP6XBgEKQA/orVhfXqQ9nw== X-Received: by 2002:a05:622a:28b:b0:467:63a5:fb9c with SMTP id d75a77b69052e-46a4a98a203mr862126761cf.44.1735836339962; Thu, 02 Jan 2025 08:45:39 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.38 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:39 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 10/44] selinux: introduce a global SID table Date: Thu, 2 Jan 2025 11:44:35 -0500 Message-Id: <20250102164509.25606-11-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce a global SID table to provide stable global SID values independent of any particular policy or namespace. This table will only map between global SIDs and security context strings since it must remain policy-independent. Internally each of these global SIDs can then be mapped on a per-policy/namespace basis to per-namespace SIDs and context structures. The LSM interfaces and blob structures will only use the global SID values and thus remain namespace-neutral. Note that this required moving the SID table header and its dependencies out of the security server subdirectory. While we could re-factor it to to reduce the scope of this change, doing so does not seem worthwhile. The security server abstraction is largely obsoleted by LSM, no one has contributed any other security server implementation for SELinux, and over time there has been an increasing blurring of the boundary between the security server and the rest of the SELinux module. Eventually, I anticipate fully moving the security server files out of the ss subdirectory but that is left for a future change. Signed-off-by: Stephen Smalley --- security/selinux/Makefile | 2 +- security/selinux/global_sidtab.c | 100 ++++++++++++++++++ security/selinux/hooks.c | 4 + security/selinux/{ss => include}/avtab.h | 0 security/selinux/{ss => include}/constraint.h | 0 security/selinux/{ss => include}/context.h | 0 security/selinux/{ss => include}/ebitmap.h | 0 security/selinux/include/global_sidtab.h | 19 ++++ security/selinux/{ss => include}/hashtab.h | 0 security/selinux/{ss => include}/mls.h | 0 security/selinux/{ss => include}/mls_types.h | 0 security/selinux/{ss => include}/policydb.h | 0 security/selinux/{ss => include}/sidtab.h | 0 security/selinux/{ss => include}/symtab.h | 0 14 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 security/selinux/global_sidtab.c rename security/selinux/{ss => include}/avtab.h (100%) rename security/selinux/{ss => include}/constraint.h (100%) rename security/selinux/{ss => include}/context.h (100%) rename security/selinux/{ss => include}/ebitmap.h (100%) create mode 100644 security/selinux/include/global_sidtab.h rename security/selinux/{ss => include}/hashtab.h (100%) rename security/selinux/{ss => include}/mls.h (100%) rename security/selinux/{ss => include}/mls_types.h (100%) rename security/selinux/{ss => include}/policydb.h (100%) rename security/selinux/{ss => include}/sidtab.h (100%) rename security/selinux/{ss => include}/symtab.h (100%) diff --git a/security/selinux/Makefile b/security/selinux/Makefile index 66e56e9011df..fe5f6f4bb0ea 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -15,7 +15,7 @@ ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include ccflags-$(CONFIG_SECURITY_SELINUX_DEBUG) += -DDEBUG selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \ - netnode.o netport.o status.o \ + netnode.o netport.o status.o global_sidtab.o \ ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \ ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/context.o diff --git a/security/selinux/global_sidtab.c b/security/selinux/global_sidtab.c new file mode 100644 index 000000000000..161cf31f1ba4 --- /dev/null +++ b/security/selinux/global_sidtab.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "global_sidtab.h" +#include "sidtab.h" + +static struct sidtab global_sidtab; + +int global_sidtab_init(void) +{ + struct context ctx; + int rc, sid; + + rc = sidtab_init(&global_sidtab); + if (rc) + return rc; + + memset(&ctx, 0, sizeof(ctx)); + for (sid = 1; sid <= SECINITSID_NUM; sid++) { + const char *str = security_get_initial_sid_context(sid); + + if (!str) + continue; + ctx.str = (char *)str; + ctx.len = strlen(str)+1; + rc = sidtab_set_initial(&global_sidtab, sid, &ctx); + if (rc) + return rc; + } + + return 0; +} + +int global_sid_to_context(u32 sid, char **scontext, u32 *scontext_len) +{ + struct context *ctx; + + rcu_read_lock(); + ctx = sidtab_search_force(&global_sidtab, sid); + if (!ctx) { + rcu_read_unlock(); + *scontext = NULL; + *scontext_len = 0; + return -EINVAL; + } + *scontext_len = ctx->len; + /* + * Could eliminate allocation + copy if callers do not free + * since the global sidtab entries are never freed. + * This however would not match the current expectation + * of callers of security_sid_to_context(). + * TODO: Update all callers and get rid of this copy. + */ + *scontext = kstrdup(ctx->str, GFP_ATOMIC); + if (!(*scontext)) { + rcu_read_unlock(); + *scontext_len = 0; + return -ENOMEM; + } + + rcu_read_unlock(); + return 0; +} + +int global_context_to_sid(const char *scontext, u32 scontext_len, u32 *out_sid, + gfp_t gfp) +{ + char *str; + struct context ctx; + int rc; + + if (!scontext_len) + return -EINVAL; + + /* + * Could eliminate allocation + copy if callers were required to + * pass in a NUL-terminated string or if the context_cmp/cpy() + * functions did not assume that ctx.str is NUL-terminated. + * This however would not match the current expectation of + * callers of security_context_to_sid, particularly contexts + * fetched from xattr values or provided by the xattr APIs. + * TODO: Change context_cmp/cpy() or update all callers and + * get rid of this copy. + */ + str = kmemdup_nul(scontext, scontext_len, gfp); + if (!str) + return -ENOMEM; + + ctx.str = str; + ctx.len = strlen(str)+1; + +retry: + rcu_read_lock(); + rc = sidtab_context_to_sid(&global_sidtab, &ctx, out_sid); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } + rcu_read_unlock(); + kfree(str); + return rc; +} diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1aa0bb1a83ce..3f6c49c62e96 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -105,6 +105,7 @@ #include "netlabel.h" #include "audit.h" #include "avc_ss.h" +#include "global_sidtab.h" #define SELINUX_INODE_INIT_XATTRS 1 @@ -7662,6 +7663,9 @@ static __init int selinux_init(void) panic("SELinux: Could not create initial namespace\n"); enforcing_set(init_selinux_state, selinux_enforcing_boot); + if (global_sidtab_init()) + panic("SELinux: Could not create global SID table\n"); + /* Set the security state for the initial task. */ cred_init_security(); diff --git a/security/selinux/ss/avtab.h b/security/selinux/include/avtab.h similarity index 100% rename from security/selinux/ss/avtab.h rename to security/selinux/include/avtab.h diff --git a/security/selinux/ss/constraint.h b/security/selinux/include/constraint.h similarity index 100% rename from security/selinux/ss/constraint.h rename to security/selinux/include/constraint.h diff --git a/security/selinux/ss/context.h b/security/selinux/include/context.h similarity index 100% rename from security/selinux/ss/context.h rename to security/selinux/include/context.h diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/include/ebitmap.h similarity index 100% rename from security/selinux/ss/ebitmap.h rename to security/selinux/include/ebitmap.h diff --git a/security/selinux/include/global_sidtab.h b/security/selinux/include/global_sidtab.h new file mode 100644 index 000000000000..f62a9165d26a --- /dev/null +++ b/security/selinux/include/global_sidtab.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * A global security identifier table (sidtab) is a lookup table + * of security context strings indexed by SID value. + */ + +#ifndef _GLOBAL_SIDTAB_H_ +#define _GLOBAL_SIDTAB_H_ + +#include + +extern int global_sidtab_init(void); + +extern int global_sid_to_context(u32 sid, char **scontext, u32 *scontext_len); + +extern int global_context_to_sid(const char *scontext, u32 scontext_len, + u32 *out_sid, gfp_t gfp); + +#endif /* _GLOBAL_SIDTAB_H_ */ diff --git a/security/selinux/ss/hashtab.h b/security/selinux/include/hashtab.h similarity index 100% rename from security/selinux/ss/hashtab.h rename to security/selinux/include/hashtab.h diff --git a/security/selinux/ss/mls.h b/security/selinux/include/mls.h similarity index 100% rename from security/selinux/ss/mls.h rename to security/selinux/include/mls.h diff --git a/security/selinux/ss/mls_types.h b/security/selinux/include/mls_types.h similarity index 100% rename from security/selinux/ss/mls_types.h rename to security/selinux/include/mls_types.h diff --git a/security/selinux/ss/policydb.h b/security/selinux/include/policydb.h similarity index 100% rename from security/selinux/ss/policydb.h rename to security/selinux/include/policydb.h diff --git a/security/selinux/ss/sidtab.h b/security/selinux/include/sidtab.h similarity index 100% rename from security/selinux/ss/sidtab.h rename to security/selinux/include/sidtab.h diff --git a/security/selinux/ss/symtab.h b/security/selinux/include/symtab.h similarity index 100% rename from security/selinux/ss/symtab.h rename to security/selinux/include/symtab.h From patchwork Thu Jan 2 16:44:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924628 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f172.google.com (mail-qk1-f172.google.com [209.85.222.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B8E944C6C for ; Thu, 2 Jan 2025 16:45:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836350; cv=none; b=FNJHEa8SRCI4xqCaNhJDu8wmV/RZ7V3mXnoztHwMusWoN7P8zDbDpI3fCOZMC3lTIJqjtxDidE+4qd2KrNfN4VuKIpiCCpxRiuLg8A2BXNVF841QQ0vYFjbFlPull7ntAqpBm4HfFH3YlUUGtRyhgaxqIBdnALnPChUmOCdb1k4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836350; c=relaxed/simple; bh=WmRHY7jFFSY5toZgnSqnZ+IqgpzyIIQlWBF/jvsnU7M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KfS0QRAZBpqENplASqAY16mrX0cVPHbXYnYM2tAjqXFogA0h9POtxiU/OXOfwdPeiuri5JhTPjNFCH50o38jWkYFmt0TAeJF800AHa9WYG9GnvPIi3b+XxJRYPsL/nbfvbeicRiN7n2CrmzG8OD2EtH60WNapRS5JGtYP2iyqhA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=L+YdG7Ut; arc=none smtp.client-ip=209.85.222.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="L+YdG7Ut" Received: by mail-qk1-f172.google.com with SMTP id af79cd13be357-7b6eb531e13so587363685a.0 for ; Thu, 02 Jan 2025 08:45:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836342; x=1736441142; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=d311B6F+n0IIKipAnq6gkdyHULVnDGILUp/0+O4Ulw0=; b=L+YdG7UtHIk91UhzmqryabEPzwIupIgHHn/36DzQWoaG0vzA0QStbUpb6AJoKit/Wp L1+3wDCdNd575KbQp0J0Uhcqw2j3Su08EW9tnTQKaKISiJ1+oOd/q2Rvw9bG6VhDBxcP k8qFGsvUfII8vK3YCJrQzLnziVlg4sb8dI7CyZZoO1Om83gY7IEXmimKSdubVXSnGpvc 9u05GeB02yOfEHjVQ0wq0uXsvwR6f8xE/5+VVtDVxoTv17BvQIF0j2Nd2bqrNXci/FoP mm6LXu9zYu8NAmEzO3AVjWnQm0aiKat4elQGJ8VUqcu7iZgUH8PQXwPy057l54iDWWM3 a36Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836342; x=1736441142; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=d311B6F+n0IIKipAnq6gkdyHULVnDGILUp/0+O4Ulw0=; b=Ufjl95eOWWQcfTetilMlNKx+dS9RCFPcsdGF868hnvvEvYPfnj3parV3onpe9e0TW9 uc/lGyFre9Inpf9Hcv5ehUmJbI/DjG4WynkxKEWL+zo6h+ZUT47NdpeLpSV8noOwWbWs DEsidboXw9h7WUsl1NTcuzqzFggmJncDJ8ZuHwQpFFTzvDUltuNdRMBEqy9xfeK7J6+B /ZTqFzBAobh6PKmos+6Kc3JVVDJISuovl7wMPSh5wJ/6u2cizvyWynJ9rVA8eViu2e2B FeuJ+jWoeUUVPlKBdBwLt+7yzM+CSqNQUAvzmK2mHr9k6E+4q1njN9WRSrUQQ2MyX5Tg LBHw== X-Gm-Message-State: AOJu0YwRnc1N114VgYf93uy8ekLlmaS/tuU4Qp9g7Bqmc8lD3O+sQDpS aCKTupnIAGR7VGPGDJzD1yfi4Jye/M8oeqSgIgORxXceEYH3fj/QfFkbvQ== X-Gm-Gg: ASbGnctlA0IwXSSH//93doBxNSra9iP3Jm8ZuKXaez8Ljd4ZceL6qu1sbN/eYLIlIam UbylPeefmCOpczegRDo4vgwTWOIxyZswbhXm4327iVYmGyhBxXvtvinAhHjjOz3x95mlp53LcsE 4VKNaL3+qqMsLhtcS0iaPuqr90UnMb7N8xXiSWMxFQMttuE4mAgZgqmTkBVXFDHTvaKTBjAuB/h SWBr4kyaejATGoqUP+xCugKJalCrUk1nkKccDsed5uOeoknh7GMF/IQ/WUUguIJPLClNhuOJm9T BFMX15cKaLd0SYoEd/hqW2R2x0nOJXM4E9jW5o44qYh0BGUPQam4nEU/Fh+GLJJxI9C/UA== X-Google-Smtp-Source: AGHT+IF1kUjAFxaAiFbyfI5meVXlB3MFdsj2k/BlH7JSHITMeWarOZnknEBllfDybpGy2PnqkAbC6A== X-Received: by 2002:a05:620a:240c:b0:7b1:4327:7b63 with SMTP id af79cd13be357-7b9ba7a573bmr7927401685a.32.1735836340939; Thu, 02 Jan 2025 08:45:40 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.40 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:40 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 11/44] selinux: wrap security server interfaces to use the global SID table Date: Thu, 2 Jan 2025 11:44:36 -0500 Message-Id: <20250102164509.25606-12-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Wrap the security server interfaces to use the global SID table, transparently mapping between global SIDs and per-policy SIDs. Rename the existing security server functions with a selinux_ss prefix. The selinuxfs implementation directly uses the underlying selinux_ss interfaces since its functions are always acting relative to a particular SELinux namespace. In contrast, the hook function implementations always use the new wrapper functions to support the use of global SIDs. Since the global SID table always stores security context strings unmapped, this change removes the informational printk about unmapped contexts to avoid filling the logs with noise. If/when we split the global SID table and per-policy SID table implementations, this could be restored to the per-policy SID tables if desired. The implementation leaves a lot to be desired in efficiency, but optimizing the global SID mapping, splitting the global SID and per-policy SID table data structures to avoid wasting unused space in the sidtab entries of each, and/or eliminating the use of per-policy SIDs entirely is left to future changes. It would be good if we could further optimize for the case where there is only a single SELinux namespace and avoid imposing extra overhead on it. Signed-off-by: Stephen Smalley --- security/selinux/global_sidtab.c | 655 ++++++++++++++++++++++- security/selinux/hooks.c | 2 +- security/selinux/include/global_sidtab.h | 5 +- security/selinux/include/security.h | 23 +- security/selinux/include/selinux_ss.h | 115 ++++ security/selinux/include/sidtab.h | 5 + security/selinux/selinuxfs.c | 51 +- security/selinux/ss/services.c | 138 +++-- security/selinux/ss/sidtab.c | 14 +- 9 files changed, 884 insertions(+), 124 deletions(-) create mode 100644 security/selinux/include/selinux_ss.h diff --git a/security/selinux/global_sidtab.c b/security/selinux/global_sidtab.c index 161cf31f1ba4..983b406389cb 100644 --- a/security/selinux/global_sidtab.c +++ b/security/selinux/global_sidtab.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 #include "global_sidtab.h" #include "sidtab.h" +#include "selinux_ss.h" +#include "audit.h" static struct sidtab global_sidtab; @@ -60,8 +62,9 @@ int global_sid_to_context(u32 sid, char **scontext, u32 *scontext_len) return 0; } -int global_context_to_sid(const char *scontext, u32 scontext_len, u32 *out_sid, - gfp_t gfp) +int global_context_to_sid(struct selinux_state *state, u32 ss_sid, + const char *scontext, u32 scontext_len, + u32 *out_sid, gfp_t gfp) { char *str; struct context ctx; @@ -89,7 +92,8 @@ int global_context_to_sid(const char *scontext, u32 scontext_len, u32 *out_sid, retry: rcu_read_lock(); - rc = sidtab_context_to_sid(&global_sidtab, &ctx, out_sid); + rc = sidtab_context_ss_to_sid(&global_sidtab, &ctx, state, ss_sid, + out_sid); if (rc == -ESTALE) { rcu_read_unlock(); goto retry; @@ -98,3 +102,648 @@ int global_context_to_sid(const char *scontext, u32 scontext_len, u32 *out_sid, kfree(str); return rc; } + +static int map_global_sid_to_ss(struct selinux_state *state, u32 sid, + u32 *ss_sid, gfp_t gfp) +{ + struct sidtab_entry *entry; + int rc; + char *scontext; + u32 scontext_len; + + if (sid <= SECINITSID_NUM) { + *ss_sid = sid; + return 0; + } + + rcu_read_lock(); + entry = sidtab_search_entry_force(&global_sidtab, sid); + if (!entry) { + rcu_read_unlock(); + return -EINVAL; + } + if (entry->state == state && entry->ss_sid) { + *ss_sid = entry->ss_sid; + rcu_read_unlock(); + return 0; + } + rcu_read_unlock(); + + rc = global_sid_to_context(sid, &scontext, &scontext_len); + if (rc) + return rc; + + rc = selinux_ss_context_to_sid_force(state, scontext, + scontext_len, ss_sid, gfp); + kfree(scontext); + return rc; +} + +static int map_ss_sid_to_global(struct selinux_state *state, u32 ss_sid, + u32 *out_sid, gfp_t gfp) +{ + char *scontext; + u32 scontext_len; + int rc; + + if (ss_sid <= SECINITSID_NUM) { + *out_sid = ss_sid; + return 0; + } + + rc = selinux_ss_sid_to_context_force(state, ss_sid, &scontext, + &scontext_len); + if (rc) + return rc; + + rc = global_context_to_sid(state, ss_sid, scontext, scontext_len, + out_sid, GFP_ATOMIC); + kfree(scontext); + return rc; +} + +int security_sid_to_context(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len) +{ + // initial SID contexts have to be obtained from the policy, if initialized + if (sid <= SECINITSID_NUM && selinux_initialized(state)) + return selinux_ss_sid_to_context(state, sid, scontext, scontext_len); + + return global_sid_to_context(sid, scontext, scontext_len); +} + +int security_sid_to_context_valid(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len) +{ + int rc; + u32 ss_sid; + + // Valid SID contexts have to be obtained from the policy, if initialized + if (selinux_initialized(state)) { + rc = map_global_sid_to_ss(state, sid, &ss_sid, GFP_ATOMIC); + if (rc) + return rc; + return selinux_ss_sid_to_context(state, ss_sid, scontext, + scontext_len); + } + + return global_sid_to_context(sid, scontext, scontext_len); +} + +int security_sid_to_context_force(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len) +{ + // initial SID contexts have to be obtained from the policy, if initialized + if (sid <= SECINITSID_NUM && selinux_initialized(state)) + return selinux_ss_sid_to_context_force(state, sid, scontext, scontext_len); + + return global_sid_to_context(sid, scontext, scontext_len); +} + +int security_sid_to_context_inval(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len) +{ + int rc; + u32 ss_sid; + + // TODO Cache invalid bit in global SID table so we do not need + // to lookup in the per-policy one each time. + if (selinux_initialized(state)) { + rc = map_global_sid_to_ss(state, sid, &ss_sid, GFP_ATOMIC); + if (rc) + return rc; + return selinux_ss_sid_to_context_inval(state, ss_sid, scontext, + scontext_len); + } + return global_sid_to_context(sid, scontext, scontext_len); +} + +int security_context_to_sid(struct selinux_state *state, const char *scontext, + u32 scontext_len, u32 *out_sid, gfp_t gfp) +{ + int rc; + u32 sid, ss_sid = 0; + char *ctx = NULL; + + /* + * If initialized, validate and canonicalize the context against + * the policy. + */ + if (selinux_initialized(state)) { + rc = selinux_ss_context_to_sid(state, scontext, scontext_len, + &ss_sid, gfp); + if (rc) + return rc; + + rc = selinux_ss_sid_to_context(state, ss_sid, &ctx, + &scontext_len); + if (rc) + return rc; + scontext = ctx; + } + + // allocate or lookup a SID in the global SID table + rc = global_context_to_sid(state, ss_sid, scontext, scontext_len, + &sid, gfp); + if (rc) + goto out; + + *out_sid = sid; + +out: + kfree(ctx); + return rc; +} + +int security_context_str_to_sid(struct selinux_state *state, + const char *scontext, u32 *out_sid, gfp_t gfp) +{ + size_t scontext_len = strlen(scontext) + 1; + + return security_context_to_sid(state, scontext, scontext_len, out_sid, + gfp); +} + +int security_context_to_sid_default(struct selinux_state *state, + const char *scontext, u32 scontext_len, + u32 *out_sid, u32 def_sid, gfp_t gfp) +{ + int rc; + u32 sid, ss_sid = 0; + char *ctx = NULL; + + /* + * If initialized, validate and canonicalize the context against + * the policy. + */ + if (selinux_initialized(state)) { + rc = selinux_ss_context_to_sid_default(state, scontext, + scontext_len, &ss_sid, + def_sid, gfp); + if (rc) + return rc; + + rc = selinux_ss_sid_to_context(state, ss_sid, &ctx, + &scontext_len); + if (rc) + return rc; + scontext = ctx; + } + + // allocate or lookup a SID in the global SID table + rc = global_context_to_sid(state, ss_sid, scontext, scontext_len, + &sid, gfp); + if (rc) + goto out; + + *out_sid = sid; + +out: + kfree(ctx); + return rc; +} + +int security_context_to_sid_force(struct selinux_state *state, + const char *scontext, u32 scontext_len, + u32 *out_sid) +{ + int rc; + u32 sid, ss_sid = 0; + char *ctx = NULL; + + /* + * If initialized, validate and canonicalize the context against + * the policy. + */ + if (selinux_initialized(state)) { + rc = selinux_ss_context_to_sid_force(state, scontext, + scontext_len, &ss_sid, + GFP_KERNEL); + if (rc) + return rc; + + rc = selinux_ss_sid_to_context_force(state, ss_sid, &ctx, + &scontext_len); + if (rc) + return rc; + scontext = ctx; + } + + // allocate or lookup a SID in the global SID table + rc = global_context_to_sid(state, ss_sid, scontext, scontext_len, + &sid, GFP_KERNEL); + if (rc) + goto out; + + *out_sid = sid; + +out: + kfree(ctx); + return rc; +} + +void security_compute_av(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, struct av_decision *avd, + struct extended_perms *xperms) +{ + u32 ss_ssid, ss_tsid; + int rc; + + if (!selinux_initialized(state)) + goto allow; + + rc = map_global_sid_to_ss(state, ssid, &ss_ssid, GFP_ATOMIC); + if (rc) + goto deny; + rc = map_global_sid_to_ss(state, tsid, &ss_tsid, GFP_ATOMIC); + if (rc) + goto deny; + selinux_ss_compute_av(state, ss_ssid, ss_tsid, tclass, avd, xperms); + return; +allow: + avd->allowed = ~0U; + goto out; +deny: + avd->allowed = 0; +out: + avd->auditallow = 0; + avd->auditdeny = ~0U; + avd->seqno = 0; + avd->flags = 0; + xperms->len = 0; +} + +void security_compute_xperms_decision(struct selinux_state *state, u32 ssid, + u32 tsid, u16 tclass, u8 driver, + struct extended_perms_decision *xpermd) +{ + u32 ss_ssid, ss_tsid; + int rc; + + if (!selinux_initialized(state)) + goto allow; + + rc = map_global_sid_to_ss(state, ssid, &ss_ssid, GFP_ATOMIC); + if (rc) + goto deny; + rc = map_global_sid_to_ss(state, tsid, &ss_tsid, GFP_ATOMIC); + if (rc) + goto deny; + selinux_ss_compute_xperms_decision(state, ss_ssid, ss_tsid, tclass, driver, xpermd); + return; +allow: + memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p)); + goto out; +deny: + memset(xpermd->allowed->p, 0, sizeof(xpermd->allowed->p)); +out: + xpermd->driver = driver; + xpermd->used = 0; + memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p)); + memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p)); +} + +int security_transition_sid(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, const struct qstr *qstr, u32 *out_sid) +{ + u32 ss_ssid, ss_tsid, ss_outsid; + int rc; + + if (!selinux_initialized(state)) { + switch (tclass) { + case SECCLASS_PROCESS: + *out_sid = ssid; + break; + default: + *out_sid = tsid; + break; + } + return 0; + } + + rc = map_global_sid_to_ss(state, ssid, &ss_ssid, GFP_ATOMIC); + if (rc) + return rc; + rc = map_global_sid_to_ss(state, tsid, &ss_tsid, GFP_ATOMIC); + if (rc) + return rc; + rc = selinux_ss_transition_sid(state, ss_ssid, ss_tsid, tclass, qstr, + &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int security_port_sid(struct selinux_state *state, u8 protocol, u16 port, + u32 *out_sid) +{ + u32 ss_outsid; + int rc; + + if (!selinux_initialized(state)) { + *out_sid = SECINITSID_PORT; + return 0; + } + + rc = selinux_ss_port_sid(state, protocol, port, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int security_ib_pkey_sid(struct selinux_state *state, u64 subnet_prefix, + u16 pkey_num, u32 *out_sid) +{ + u32 ss_outsid; + int rc; + + if (!selinux_initialized(state)) { + *out_sid = SECINITSID_UNLABELED; + return 0; + } + + rc = selinux_ss_ib_pkey_sid(state, subnet_prefix, pkey_num, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int security_ib_endport_sid(struct selinux_state *state, const char *dev_name, + u8 port_num, u32 *out_sid) +{ + u32 ss_outsid; + int rc; + + if (!selinux_initialized(state)) { + *out_sid = SECINITSID_UNLABELED; + return 0; + } + + rc = selinux_ss_ib_endport_sid(state, dev_name, port_num, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int security_netif_sid(struct selinux_state *state, char *name, u32 *out_sid) +{ + u32 ss_outsid; + int rc; + + if (!selinux_initialized(state)) { + *out_sid = SECINITSID_NETIF; + return 0; + } + + rc = selinux_ss_netif_sid(state, name, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int security_node_sid(struct selinux_state *state, u16 domain, void *addr, + u32 addrlen, u32 *out_sid) +{ + u32 ss_outsid; + int rc; + + if (!selinux_initialized(state)) { + *out_sid = SECINITSID_NODE; + return 0; + } + + rc = selinux_ss_node_sid(state, domain, addr, addrlen, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int security_validate_transition(struct selinux_state *state, u32 oldsid, + u32 newsid, u32 tasksid, u16 tclass) +{ + u32 ss_oldsid, ss_newsid, ss_tasksid; + int rc; + + if (!selinux_initialized(state)) + return 0; + + rc = map_global_sid_to_ss(state, oldsid, &ss_oldsid, GFP_ATOMIC); + if (rc) + return -EINVAL; + rc = map_global_sid_to_ss(state, newsid, &ss_newsid, GFP_ATOMIC); + if (rc) + return -EINVAL; + rc = map_global_sid_to_ss(state, tasksid, &ss_tasksid, GFP_ATOMIC); + if (rc) + return -EINVAL; + return selinux_ss_validate_transition(state, ss_oldsid, ss_newsid, + ss_tasksid, tclass); +} + +int security_bounded_transition(struct selinux_state *state, u32 oldsid, + u32 newsid) +{ + u32 ss_oldsid, ss_newsid; + int rc; + + if (!selinux_initialized(state)) + return 0; + + rc = map_global_sid_to_ss(state, oldsid, &ss_oldsid, GFP_ATOMIC); + if (rc) + return -EINVAL; + rc = map_global_sid_to_ss(state, newsid, &ss_newsid, GFP_ATOMIC); + if (rc) + return -EINVAL; + return selinux_ss_bounded_transition(state, ss_oldsid, ss_newsid); +} + +int security_sid_mls_copy(struct selinux_state *state, u32 sid, u32 mls_sid, + u32 *out_sid) +{ + u32 ss_sid, ss_mlssid, ss_outsid; + int rc; + + if (!selinux_initialized(state)) { + *out_sid = sid; + return 0; + } + + rc = map_global_sid_to_ss(state, sid, &ss_sid, GFP_ATOMIC); + if (rc) + return rc; + rc = map_global_sid_to_ss(state, mls_sid, &ss_mlssid, GFP_ATOMIC); + if (rc) + return rc; + + rc = selinux_ss_sid_mls_copy(state, ss_sid, ss_mlssid, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int security_net_peersid_resolve(struct selinux_state *state, u32 nlbl_sid, + u32 nlbl_type, u32 xfrm_sid, u32 *out_sid) +{ + u32 ss_nlblsid, ss_xfrmsid, ss_outsid; + int rc; + + if (!selinux_initialized(state)) { + if (xfrm_sid == SECSID_NULL) { + *out_sid = nlbl_sid; + return 0; + } + if (nlbl_sid == SECSID_NULL || nlbl_type == NETLBL_NLTYPE_UNLABELED) { + *out_sid = xfrm_sid; + return 0; + } + *out_sid = SECSID_NULL; + return 0; + } + + rc = map_global_sid_to_ss(state, nlbl_sid, &ss_nlblsid, GFP_ATOMIC); + if (rc) + return rc; + rc = map_global_sid_to_ss(state, xfrm_sid, &ss_xfrmsid, GFP_ATOMIC); + if (rc) + return rc; + + rc = selinux_ss_net_peersid_resolve(state, ss_nlblsid, nlbl_type, ss_xfrmsid, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +// only required for (mis)use of superblock_security_struct + selinux_superblock() below. +// TODO Remove when security_fs_use() interface is repaired +#include "objsec.h" + +int security_fs_use(struct selinux_state *state, struct super_block *sb) +{ + int rc; + struct superblock_security_struct *sbsec = selinux_superblock(sb); + + if (!selinux_initialized(state)) { + sbsec->behavior = SECURITY_FS_USE_NONE; + sbsec->sid = SECINITSID_UNLABELED; + return 0; + } + + // TODO - it was a mistake to have pushed direct access to + // sbsec into a security server function. Fix both that + // interface and here to explicitly return the behavior and + // SID via parameters to be set in the sbsec by the caller. + rc = selinux_ss_fs_use(state, sb); + if (rc) + return rc; + + if (sbsec->sid <= SECINITSID_NUM) + return 0; + + return map_ss_sid_to_global(state, sbsec->sid, &sbsec->sid, GFP_ATOMIC); +} + +int security_genfs_sid(struct selinux_state *state, const char *fstype, + const char *path, u16 sclass, u32 *out_sid) +{ + int rc; + u32 ss_outsid; + + if (!selinux_initialized(state)) { + *out_sid = SECINITSID_UNLABELED; + return 0; + } + + rc = selinux_ss_genfs_sid(state, fstype, path, sclass, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int selinux_policy_genfs_sid(struct selinux_policy *policy, const char *fstype, + const char *path, u16 sclass, u32 *out_sid) +{ + int rc; + u32 ss_outsid; + + rc = selinux_ss_policy_genfs_sid(policy, fstype, path, sclass, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(current_selinux_state, ss_outsid, out_sid, + GFP_ATOMIC); +} + +int selinux_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *vrule) +{ + int rc; + struct lsm_prop local_prop; + struct selinux_state *state = current_selinux_state; + + if (!selinux_initialized(state)) + return 0; + + rc = map_global_sid_to_ss(state, prop->selinux.secid, + &local_prop.selinux.secid, GFP_ATOMIC); + if (rc) + return -ENOENT; + return selinux_ss_audit_rule_match(&local_prop, field, op, vrule); +} + +#ifdef CONFIG_NETLABEL +int security_netlbl_secattr_to_sid(struct selinux_state *state, + struct netlbl_lsm_secattr *secattr, + u32 *out_sid) +{ + int rc; + u32 ss_outsid; + + if (!selinux_initialized(state)) { + *out_sid = SECSID_NULL; + return 0; + } + + // The secattr secid is a global SID + if (secattr->flags & NETLBL_SECATTR_SECID) { + *out_sid = secattr->attr.secid; + return 0; + } + + rc = selinux_ss_netlbl_secattr_to_sid(state, secattr, &ss_outsid); + if (rc) + return rc; + + return map_ss_sid_to_global(state, ss_outsid, out_sid, GFP_ATOMIC); +} + +int security_netlbl_sid_to_secattr(struct selinux_state *state, u32 sid, + struct netlbl_lsm_secattr *secattr) +{ + int rc; + u32 ss_sid; + + if (!selinux_initialized(state)) + return 0; + + rc = map_global_sid_to_ss(state, sid, &ss_sid, GFP_ATOMIC); + if (rc) + return rc; + rc = selinux_ss_netlbl_sid_to_secattr(state, ss_sid, secattr); + if (rc) + return rc; + + // The secattr secid is a global SID. + secattr->attr.secid = sid; + secattr->flags |= NETLBL_SECATTR_SECID; + return 0; +} +#endif diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3f6c49c62e96..23b5648be433 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3518,7 +3518,7 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap, isec->sid, &context, &size); else - error = security_sid_to_context(current_selinux_state, isec->sid, + error = security_sid_to_context_valid(current_selinux_state, isec->sid, &context, &size); if (error) return error; diff --git a/security/selinux/include/global_sidtab.h b/security/selinux/include/global_sidtab.h index f62a9165d26a..3a7332bdff2e 100644 --- a/security/selinux/include/global_sidtab.h +++ b/security/selinux/include/global_sidtab.h @@ -9,11 +9,14 @@ #include +struct selinux_state; + extern int global_sidtab_init(void); extern int global_sid_to_context(u32 sid, char **scontext, u32 *scontext_len); -extern int global_context_to_sid(const char *scontext, u32 scontext_len, +extern int global_context_to_sid(struct selinux_state *state, u32 ss_sid, + const char *scontext, u32 scontext_len, u32 *out_sid, gfp_t gfp); #endif /* _GLOBAL_SIDTAB_H_ */ diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 8f8531b80bfd..fe16bc86627d 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -331,25 +331,15 @@ void security_compute_xperms_decision(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, u8 driver, struct extended_perms_decision *xpermd); -void security_compute_av_user(struct selinux_state *state, u32 ssid, u32 tsid, - u16 tclass, struct av_decision *avd); - int security_transition_sid(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, const struct qstr *qstr, u32 *out_sid); -int security_transition_sid_user(struct selinux_state *state, u32 ssid, - u32 tsid, u16 tclass, const char *objname, - u32 *out_sid); - -int security_member_sid(struct selinux_state *state, u32 ssid, u32 tsid, - u16 tclass, u32 *out_sid); - -int security_change_sid(struct selinux_state *state, u32 ssid, u32 tsid, - u16 tclass, u32 *out_sid); - int security_sid_to_context(struct selinux_state *state, u32 sid, char **scontext, u32 *scontext_len); +int security_sid_to_context_valid(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len); + int security_sid_to_context_force(struct selinux_state *state, u32 sid, char **scontext, u32 *scontext_len); @@ -370,9 +360,6 @@ int security_context_to_sid_force(struct selinux_state *state, const char *scontext, u32 scontext_len, u32 *sid); -int security_get_user_sids(struct selinux_state *state, u32 callsid, - char *username, u32 **sids, u32 *nel); - int security_port_sid(struct selinux_state *state, u8 protocol, u16 port, u32 *out_sid); @@ -390,9 +377,6 @@ int security_node_sid(struct selinux_state *state, u16 domain, void *addr, int security_validate_transition(struct selinux_state *state, u32 oldsid, u32 newsid, u32 tasksid, u16 tclass); -int security_validate_transition_user(struct selinux_state *state, u32 oldsid, - u32 newsid, u32 tasksid, u16 tclass); - int security_bounded_transition(struct selinux_state *state, u32 oldsid, u32 newsid); @@ -433,6 +417,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state, int security_netlbl_sid_to_secattr(struct selinux_state *state, u32 sid, struct netlbl_lsm_secattr *secattr); + #else static inline int security_netlbl_secattr_to_sid(struct selinux_state *state, diff --git a/security/selinux/include/selinux_ss.h b/security/selinux/include/selinux_ss.h new file mode 100644 index 000000000000..1b497f984158 --- /dev/null +++ b/security/selinux/include/selinux_ss.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _SELINUX_SS_H_ +#define _SELINUX_SS_H_ + +/* + * SELinux security server policy-dependent interfaces. + * Most callers should use the corresponding security_*() interfaces + * from security.h instead in order to transparently map to/from + * global SIDs. + */ + +void selinux_ss_compute_av(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, struct av_decision *avd, + struct extended_perms *xperms); + +void selinux_ss_compute_xperms_decision(struct selinux_state *state, u32 ssid, + u32 tsid, u16 tclass, u8 driver, + struct extended_perms_decision *xpermd); + +void selinux_ss_compute_av_user(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, struct av_decision *avd); + +int selinux_ss_transition_sid(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, const struct qstr *qstr, + u32 *out_sid); + +int selinux_ss_transition_sid_user(struct selinux_state *state, u32 ssid, + u32 tsid, u16 tclass, const char *objname, + u32 *out_sid); + +int selinux_ss_member_sid(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 *out_sid); + +int selinux_ss_change_sid(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 *out_sid); + +int selinux_ss_sid_to_context(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len); + +int selinux_ss_sid_to_context_force(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len); + +int selinux_ss_sid_to_context_inval(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len); + +int selinux_ss_context_to_sid(struct selinux_state *state, const char *scontext, + u32 scontext_len, u32 *out_sid, gfp_t gfp); + +int selinux_ss_context_str_to_sid(struct selinux_state *state, + const char *scontext, u32 *out_sid, + gfp_t gfp); + +int selinux_ss_context_to_sid_default(struct selinux_state *state, + const char *scontext, u32 scontext_len, + u32 *out_sid, u32 def_sid, + gfp_t gfp_flags); + +int selinux_ss_context_to_sid_force(struct selinux_state *state, + const char *scontext, u32 scontext_len, + u32 *sid, gfp_t gfp); + +int selinux_ss_get_user_sids(struct selinux_state *state, u32 callsid, + char *username, u32 **sids, u32 *nel); + +int selinux_ss_port_sid(struct selinux_state *state, u8 protocol, u16 port, + u32 *out_sid); + +int selinux_ss_ib_pkey_sid(struct selinux_state *state, u64 subnet_prefix, + u16 pkey_num, u32 *out_sid); + +int selinux_ss_ib_endport_sid(struct selinux_state *state, const char *dev_name, + u8 port_num, u32 *out_sid); + +int selinux_ss_netif_sid(struct selinux_state *state, char *name, u32 *if_sid); + +int selinux_ss_node_sid(struct selinux_state *state, u16 domain, void *addr, + u32 addrlen, u32 *out_sid); + +int selinux_ss_validate_transition(struct selinux_state *state, u32 oldsid, + u32 newsid, u32 tasksid, u16 tclass); + +int selinux_ss_validate_transition_user(struct selinux_state *state, u32 oldsid, + u32 newsid, u32 tasksid, u16 tclass); + +int selinux_ss_bounded_transition(struct selinux_state *state, u32 oldsid, + u32 newsid); + +int selinux_ss_sid_mls_copy(struct selinux_state *state, u32 sid, u32 mls_sid, + u32 *new_sid); + +int selinux_ss_net_peersid_resolve(struct selinux_state *state, u32 nlbl_sid, + u32 nlbl_type, u32 xfrm_sid, u32 *peer_sid); + +int selinux_ss_fs_use(struct selinux_state *state, struct super_block *sb); + +int selinux_ss_genfs_sid(struct selinux_state *state, const char *fstype, + const char *path, u16 sclass, u32 *sid); + +int selinux_ss_policy_genfs_sid(struct selinux_policy *policy, + const char *fstype, const char *path, + u16 sclass, u32 *sid); + +int selinux_ss_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *rule); + +#ifdef CONFIG_NETLABEL +int selinux_ss_netlbl_secattr_to_sid(struct selinux_state *state, + struct netlbl_lsm_secattr *secattr, + u32 *sid); + +int selinux_ss_netlbl_sid_to_secattr(struct selinux_state *state, u32 sid, + struct netlbl_lsm_secattr *secattr); +#endif + +#endif /* _SELINUX_SS_H_ */ diff --git a/security/selinux/include/sidtab.h b/security/selinux/include/sidtab.h index 832c85c70d83..1d40e1a7fa42 100644 --- a/security/selinux/include/sidtab.h +++ b/security/selinux/include/sidtab.h @@ -26,6 +26,8 @@ struct sidtab_entry { struct sidtab_str_cache __rcu *cache; #endif struct hlist_node list; + u32 ss_sid; // global SID table only + struct selinux_state *state; // global SID table only }; union sidtab_entry_inner { @@ -134,6 +136,9 @@ void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid); +int sidtab_context_ss_to_sid(struct sidtab *s, struct context *context, + struct selinux_state *state, u32 ss_sid, u32 *sid); + void sidtab_destroy(struct sidtab *s); int sidtab_hash_stats(struct sidtab *sidtab, char *page); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 0702aeb0c5b8..c3308a5c168d 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -39,6 +39,7 @@ #include "avc.h" #include "avc_ss.h" #include "security.h" +#include "selinux_ss.h" #include "objsec.h" #include "conditional.h" #include "ima.h" @@ -733,11 +734,11 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) if (length) goto out; - length = security_context_to_sid(state, buf, size, &sid, GFP_KERNEL); + length = selinux_ss_context_to_sid(state, buf, size, &sid, GFP_KERNEL); if (length) goto out; - length = security_sid_to_context(state, sid, &canon, &len); + length = selinux_ss_sid_to_context(state, sid, &canon, &len); if (length) goto out; @@ -876,19 +877,19 @@ static ssize_t sel_write_validatetrans(struct file *file, if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4) goto out; - rc = security_context_str_to_sid(state, oldcon, &osid, GFP_KERNEL); + rc = selinux_ss_context_str_to_sid(state, oldcon, &osid, GFP_KERNEL); if (rc) goto out; - rc = security_context_str_to_sid(state, newcon, &nsid, GFP_KERNEL); + rc = selinux_ss_context_str_to_sid(state, newcon, &nsid, GFP_KERNEL); if (rc) goto out; - rc = security_context_str_to_sid(state, taskcon, &tsid, GFP_KERNEL); + rc = selinux_ss_context_str_to_sid(state, taskcon, &tsid, GFP_KERNEL); if (rc) goto out; - rc = security_validate_transition_user(state, osid, nsid, tsid, tclass); + rc = selinux_ss_validate_transition_user(state, osid, nsid, tsid, tclass); if (!rc) rc = count; out: @@ -990,15 +991,15 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); if (length) goto out; - length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); if (length) goto out; - security_compute_av_user(state, ssid, tsid, tclass, &avd); + selinux_ss_compute_av_user(state, ssid, tsid, tclass, &avd); length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%x %x %x %x %u %x", @@ -1081,20 +1082,20 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) objname = namebuf; } - length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); if (length) goto out; - length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); if (length) goto out; - length = security_transition_sid_user(state, ssid, tsid, tclass, + length = selinux_ss_transition_sid_user(state, ssid, tsid, tclass, objname, &newsid); if (length) goto out; - length = security_sid_to_context(state, newsid, &newcon, &len); + length = selinux_ss_sid_to_context(state, newsid, &newcon, &len); if (length) goto out; @@ -1147,19 +1148,19 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); if (length) goto out; - length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); if (length) goto out; - length = security_change_sid(state, ssid, tsid, tclass, &newsid); + length = selinux_ss_change_sid(state, ssid, tsid, tclass, &newsid); if (length) goto out; - length = security_sid_to_context(state, newsid, &newcon, &len); + length = selinux_ss_sid_to_context(state, newsid, &newcon, &len); if (length) goto out; @@ -1212,18 +1213,18 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s", con, user) != 2) goto out; - length = security_context_str_to_sid(state, con, &sid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, con, &sid, GFP_KERNEL); if (length) goto out; - length = security_get_user_sids(state, sid, user, &sids, &nsids); + length = selinux_ss_get_user_sids(state, sid, user, &sids, &nsids); if (length) goto out; length = sprintf(buf, "%u", nsids) + 1; ptr = buf + length; for (i = 0; i < nsids; i++) { - rc = security_sid_to_context(state, sids[i], &newcon, &len); + rc = selinux_ss_sid_to_context(state, sids[i], &newcon, &len); if (rc) { length = rc; goto out; @@ -1277,19 +1278,19 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); if (length) goto out; - length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); + length = selinux_ss_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); if (length) goto out; - length = security_member_sid(state, ssid, tsid, tclass, &newsid); + length = selinux_ss_member_sid(state, ssid, tsid, tclass, &newsid); if (length) goto out; - length = security_sid_to_context(state, newsid, &newcon, &len); + length = selinux_ss_sid_to_context(state, newsid, &newcon, &len); if (length) goto out; @@ -1801,7 +1802,7 @@ static ssize_t sel_read_initcon(struct file *file, char __user *buf, ssize_t ret; sid = file_inode(file)->i_ino&SEL_INO_MASK; - ret = security_sid_to_context(fsi->state, sid, &con, &len); + ret = selinux_ss_sid_to_context(fsi->state, sid, &con, &len); if (ret) return ret; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index bbac5f3f2fd3..b5fa7165e0d2 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -54,6 +54,7 @@ #include "avc.h" #include "avc_ss.h" #include "security.h" +#include "selinux_ss.h" #include "context.h" #include "policydb.h" #include "sidtab.h" @@ -831,7 +832,7 @@ static int security_compute_validatetrans(struct selinux_state *state, return rc; } -int security_validate_transition_user(struct selinux_state *state, +int selinux_ss_validate_transition_user(struct selinux_state *state, u32 oldsid, u32 newsid, u32 tasksid, u16 tclass) { @@ -839,7 +840,7 @@ int security_validate_transition_user(struct selinux_state *state, tclass, true); } -int security_validate_transition(struct selinux_state *state, +int selinux_ss_validate_transition(struct selinux_state *state, u32 oldsid, u32 newsid, u32 tasksid, u16 orig_tclass) { @@ -848,7 +849,7 @@ int security_validate_transition(struct selinux_state *state, } /* - * security_bounded_transition - check whether the given + * selinux_ss_bounded_transition - check whether the given * transition is directed to bounded, or not. * It returns 0, if @newsid is bounded by @oldsid. * Otherwise, it returns error code. @@ -857,7 +858,7 @@ int security_validate_transition(struct selinux_state *state, * @oldsid : current security identifier * @newsid : destinated security identifier */ -int security_bounded_transition(struct selinux_state *state, +int selinux_ss_bounded_transition(struct selinux_state *state, u32 old_sid, u32 new_sid) { struct selinux_policy *policy; @@ -1013,7 +1014,7 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd, } } -void security_compute_xperms_decision(struct selinux_state *state, +void selinux_ss_compute_xperms_decision(struct selinux_state *state, u32 ssid, u32 tsid, u16 orig_tclass, @@ -1099,7 +1100,7 @@ void security_compute_xperms_decision(struct selinux_state *state, } /** - * security_compute_av - Compute access vector decisions. + * selinux_ss_compute_av - Compute access vector decisions. * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier @@ -1110,7 +1111,7 @@ void security_compute_xperms_decision(struct selinux_state *state, * Compute a set of access vector decisions based on the * SID pair (@ssid, @tsid) for the permissions in @tclass. */ -void security_compute_av(struct selinux_state *state, +void selinux_ss_compute_av(struct selinux_state *state, u32 ssid, u32 tsid, u16 orig_tclass, @@ -1169,7 +1170,7 @@ void security_compute_av(struct selinux_state *state, goto out; } -void security_compute_av_user(struct selinux_state *state, +void selinux_ss_compute_av_user(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, @@ -1399,7 +1400,7 @@ static int security_sid_to_context_core(struct selinux_state *state, } /** - * security_sid_to_context - Obtain a context for a given SID. + * selinux_ss_sid_to_context - Obtain a context for a given SID. * @state: SELinux state * @sid: security identifier, SID * @scontext: security context @@ -1409,23 +1410,23 @@ static int security_sid_to_context_core(struct selinux_state *state, * into a dynamically allocated string of the correct size. Set @scontext * to point to this string and set @scontext_len to the length of the string. */ -int security_sid_to_context(struct selinux_state *state, - u32 sid, char **scontext, u32 *scontext_len) +int selinux_ss_sid_to_context(struct selinux_state *state, + u32 sid, char **scontext, u32 *scontext_len) { return security_sid_to_context_core(state, sid, scontext, scontext_len, 0, 0); } -int security_sid_to_context_force(struct selinux_state *state, u32 sid, - char **scontext, u32 *scontext_len) +int selinux_ss_sid_to_context_force(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len) { return security_sid_to_context_core(state, sid, scontext, scontext_len, 1, 0); } /** - * security_sid_to_context_inval - Obtain a context for a given SID if it - * is invalid. + * selinux_ss_sid_to_context_inval - Obtain a context for a given SID if it + * is invalid. * @state: SELinux state * @sid: security identifier, SID * @scontext: security context @@ -1437,8 +1438,8 @@ int security_sid_to_context_force(struct selinux_state *state, u32 sid, * this string (or NULL if the context is valid) and set @scontext_len to * the length of the string (or 0 if the context is valid). */ -int security_sid_to_context_inval(struct selinux_state *state, u32 sid, - char **scontext, u32 *scontext_len) +int selinux_ss_sid_to_context_inval(struct selinux_state *state, u32 sid, + char **scontext, u32 *scontext_len) { return security_sid_to_context_core(state, sid, scontext, scontext_len, 1, 1); @@ -1601,7 +1602,7 @@ static int security_context_to_sid_core(struct selinux_state *state, } /** - * security_context_to_sid - Obtain a SID for a given security context. + * selinux_ss_context_to_sid - Obtain a SID for a given security context. * @state: SELinux state * @scontext: security context * @scontext_len: length in bytes @@ -1613,23 +1614,23 @@ static int security_context_to_sid_core(struct selinux_state *state, * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient * memory is available, or 0 on success. */ -int security_context_to_sid(struct selinux_state *state, - const char *scontext, u32 scontext_len, u32 *sid, - gfp_t gfp) +int selinux_ss_context_to_sid(struct selinux_state *state, + const char *scontext, u32 scontext_len, u32 *sid, + gfp_t gfp) { return security_context_to_sid_core(state, scontext, scontext_len, sid, SECSID_NULL, gfp, 0); } -int security_context_str_to_sid(struct selinux_state *state, - const char *scontext, u32 *sid, gfp_t gfp) +int selinux_ss_context_str_to_sid(struct selinux_state *state, + const char *scontext, u32 *sid, gfp_t gfp) { - return security_context_to_sid(state, scontext, strlen(scontext), - sid, gfp); + return security_context_to_sid_core(state, scontext, strlen(scontext), + sid, SECSID_NULL, gfp, 0); } /** - * security_context_to_sid_default - Obtain a SID for a given security context, + * selinux_ss_context_to_sid_default - Obtain a SID for a given security context, * falling back to specified default if needed. * * @state: SELinux state @@ -1648,20 +1649,20 @@ int security_context_str_to_sid(struct selinux_state *state, * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient * memory is available, or 0 on success. */ -int security_context_to_sid_default(struct selinux_state *state, - const char *scontext, u32 scontext_len, - u32 *sid, u32 def_sid, gfp_t gfp_flags) +int selinux_ss_context_to_sid_default(struct selinux_state *state, + const char *scontext, u32 scontext_len, + u32 *sid, u32 def_sid, gfp_t gfp_flags) { return security_context_to_sid_core(state, scontext, scontext_len, sid, def_sid, gfp_flags, 1); } -int security_context_to_sid_force(struct selinux_state *state, - const char *scontext, u32 scontext_len, - u32 *sid) +int selinux_ss_context_to_sid_force(struct selinux_state *state, + const char *scontext, u32 scontext_len, + u32 *sid, gfp_t gfp) { return security_context_to_sid_core(state, scontext, scontext_len, - sid, SECSID_NULL, GFP_KERNEL, 1); + sid, SECSID_NULL, gfp, 1); } static int compute_sid_handle_invalid_context( @@ -1927,7 +1928,7 @@ static int security_compute_sid(struct selinux_state *state, } /** - * security_transition_sid - Compute the SID for a new subject/object. + * selinux_ss_transition_sid - Compute the SID for a new subject/object. * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier @@ -1941,7 +1942,7 @@ static int security_compute_sid(struct selinux_state *state, * if insufficient memory is available, or %0 if the new SID was * computed successfully. */ -int security_transition_sid(struct selinux_state *state, +int selinux_ss_transition_sid(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, const struct qstr *qstr, u32 *out_sid) { @@ -1950,7 +1951,7 @@ int security_transition_sid(struct selinux_state *state, qstr ? qstr->name : NULL, out_sid, true); } -int security_transition_sid_user(struct selinux_state *state, +int selinux_ss_transition_sid_user(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, const char *objname, u32 *out_sid) { @@ -1960,7 +1961,7 @@ int security_transition_sid_user(struct selinux_state *state, } /** - * security_member_sid - Compute the SID for member selection. + * selinux_ss_member_sid - Compute the SID for member selection. * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier @@ -1973,7 +1974,7 @@ int security_transition_sid_user(struct selinux_state *state, * if insufficient memory is available, or %0 if the SID was * computed successfully. */ -int security_member_sid(struct selinux_state *state, +int selinux_ss_member_sid(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, @@ -1985,7 +1986,7 @@ int security_member_sid(struct selinux_state *state, } /** - * security_change_sid - Compute the SID for object relabeling. + * selinux_ss_change_sid - Compute the SID for object relabeling. * @state: SELinux state * @ssid: source security identifier * @tsid: target security identifier @@ -1998,7 +1999,7 @@ int security_member_sid(struct selinux_state *state, * if insufficient memory is available, or %0 if the SID was * computed successfully. */ -int security_change_sid(struct selinux_state *state, +int selinux_ss_change_sid(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, @@ -2429,13 +2430,13 @@ static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c, } /** - * security_port_sid - Obtain the SID for a port. + * selinux_ss_port_sid - Obtain the SID for a port. * @state: SELinux state * @protocol: protocol number * @port: port number * @out_sid: security identifier */ -int security_port_sid(struct selinux_state *state, +int selinux_ss_port_sid(struct selinux_state *state, u8 protocol, u16 port, u32 *out_sid) { struct selinux_policy *policy; @@ -2483,13 +2484,13 @@ int security_port_sid(struct selinux_state *state, } /** - * security_ib_pkey_sid - Obtain the SID for a pkey. + * selinux_ss_ib_pkey_sid - Obtain the SID for a pkey. * @state: SELinux state * @subnet_prefix: Subnet Prefix * @pkey_num: pkey number * @out_sid: security identifier */ -int security_ib_pkey_sid(struct selinux_state *state, +int selinux_ss_ib_pkey_sid(struct selinux_state *state, u64 subnet_prefix, u16 pkey_num, u32 *out_sid) { struct selinux_policy *policy; @@ -2537,13 +2538,13 @@ int security_ib_pkey_sid(struct selinux_state *state, } /** - * security_ib_endport_sid - Obtain the SID for a subnet management interface. + * selinux_ss_ib_endport_sid - Obtain the SID for a subnet management interface. * @state: SELinux state * @dev_name: device name * @port_num: port number * @out_sid: security identifier */ -int security_ib_endport_sid(struct selinux_state *state, +int selinux_ss_ib_endport_sid(struct selinux_state *state, const char *dev_name, u8 port_num, u32 *out_sid) { struct selinux_policy *policy; @@ -2592,12 +2593,12 @@ int security_ib_endport_sid(struct selinux_state *state, } /** - * security_netif_sid - Obtain the SID for a network interface. + * selinux_ss_netif_sid - Obtain the SID for a network interface. * @state: SELinux state * @name: interface name * @if_sid: interface SID */ -int security_netif_sid(struct selinux_state *state, +int selinux_ss_netif_sid(struct selinux_state *state, char *name, u32 *if_sid) { struct selinux_policy *policy; @@ -2655,14 +2656,14 @@ static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask) } /** - * security_node_sid - Obtain the SID for a node (host). + * selinux_ss_node_sid - Obtain the SID for a node (host). * @state: SELinux state * @domain: communication domain aka address family * @addrp: address * @addrlen: address length in bytes * @out_sid: security identifier */ -int security_node_sid(struct selinux_state *state, +int selinux_ss_node_sid(struct selinux_state *state, u16 domain, void *addrp, u32 addrlen, @@ -2744,7 +2745,7 @@ int security_node_sid(struct selinux_state *state, #define SIDS_NEL 25 /** - * security_get_user_sids - Obtain reachable SIDs for a user. + * selinux_ss_get_user_sids - Obtain reachable SIDs for a user. * @state: SELinux state * @fromsid: starting SID * @username: username @@ -2758,7 +2759,7 @@ int security_node_sid(struct selinux_state *state, * number of elements in the array. */ -int security_get_user_sids(struct selinux_state *state, +int selinux_ss_get_user_sids(struct selinux_state *state, u32 fromsid, char *username, u32 **sids, @@ -2926,7 +2927,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, } /** - * security_genfs_sid - Obtain a SID for a file in a filesystem + * selinux_ss_genfs_sid - Obtain a SID for a file in a filesystem * @state: SELinux state * @fstype: filesystem type * @path: path from root of mount @@ -2936,7 +2937,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, * Acquire policy_rwlock before calling __security_genfs_sid() and release * it afterward. */ -int security_genfs_sid(struct selinux_state *state, +int selinux_ss_genfs_sid(struct selinux_state *state, const char *fstype, const char *path, u16 orig_sclass, @@ -2960,7 +2961,7 @@ int security_genfs_sid(struct selinux_state *state, return retval; } -int selinux_policy_genfs_sid(struct selinux_policy *policy, +int selinux_ss_policy_genfs_sid(struct selinux_policy *policy, const char *fstype, const char *path, u16 orig_sclass, @@ -2971,11 +2972,11 @@ int selinux_policy_genfs_sid(struct selinux_policy *policy, } /** - * security_fs_use - Determine how to handle labeling for a filesystem. + * selinux_ss_fs_use - Determine how to handle labeling for a filesystem. * @state: SELinux state * @sb: superblock in question */ -int security_fs_use(struct selinux_state *state, struct super_block *sb) +int selinux_ss_fs_use(struct selinux_state *state, struct super_block *sb) { struct selinux_policy *policy; struct policydb *policydb; @@ -3213,10 +3214,10 @@ static int security_preserve_bools(struct selinux_policy *oldpolicy, } /* - * security_sid_mls_copy() - computes a new sid based on the given + * selinux_ss_sid_mls_copy() - computes a new sid based on the given * sid and the mls portion of mls_sid. */ -int security_sid_mls_copy(struct selinux_state *state, +int selinux_ss_sid_mls_copy(struct selinux_state *state, u32 sid, u32 mls_sid, u32 *new_sid) { struct selinux_policy *policy; @@ -3327,7 +3328,7 @@ int security_sid_mls_copy(struct selinux_state *state, * multiple, inconsistent labels | - | SECSID_NULL * */ -int security_net_peersid_resolve(struct selinux_state *state, +int selinux_ss_net_peersid_resolve(struct selinux_state *state, u32 nlbl_sid, u32 nlbl_type, u32 xfrm_sid, u32 *peer_sid) @@ -3577,7 +3578,7 @@ void selinux_audit_rule_free(void *vrule) } int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, - gfp_t gfp) + gfp_t gfp) { struct selinux_state *state = current_selinux_state; struct selinux_policy *policy; @@ -3702,7 +3703,7 @@ int selinux_audit_rule_known(struct audit_krule *rule) return 0; } -int selinux_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *vrule) +int selinux_ss_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *vrule) { struct selinux_state *state = current_selinux_state; struct selinux_policy *policy; @@ -3868,7 +3869,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, } /** - * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID + * selinux_ss_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID * @state: SELinux state * @secattr: the NetLabel packet security attributes * @sid: the SELinux SID @@ -3883,7 +3884,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, * failure. * */ -int security_netlbl_secattr_to_sid(struct selinux_state *state, +int selinux_ss_netlbl_secattr_to_sid(struct selinux_state *state, struct netlbl_lsm_secattr *secattr, u32 *sid) { @@ -3908,8 +3909,6 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state, if (secattr->flags & NETLBL_SECATTR_CACHE) *sid = *(u32 *)secattr->cache->data; - else if (secattr->flags & NETLBL_SECATTR_SECID) - *sid = secattr->attr.secid; else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { rc = -EIDRM; ctx = sidtab_search(sidtab, SECINITSID_NETMSG); @@ -3951,7 +3950,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state, } /** - * security_netlbl_sid_to_secattr - Convert a SELinux SID to a NetLabel secattr + * selinux_ss_netlbl_sid_to_secattr - Convert a SELinux SID to a NetLabel secattr * @state: SELinux state * @sid: the SELinux SID * @secattr: the NetLabel packet security attributes @@ -3961,7 +3960,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state, * Returns zero on success, negative values on failure. * */ -int security_netlbl_sid_to_secattr(struct selinux_state *state, +int selinux_ss_netlbl_sid_to_secattr(struct selinux_state *state, u32 sid, struct netlbl_lsm_secattr *secattr) { struct selinux_policy *policy; @@ -3987,8 +3986,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state, if (secattr->domain == NULL) goto out; - secattr->attr.secid = sid; - secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID; + secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY; mls_export_netlbl_lvl(policydb, ctx, secattr); rc = mls_export_netlbl_cat(policydb, ctx, secattr); out: diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index cb7125cc7f8e..0ea4a3745adb 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -265,7 +265,8 @@ struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid) return sidtab_search_core(s, sid, 1); } -int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid) +int sidtab_context_ss_to_sid(struct sidtab *s, struct context *context, + struct selinux_state *state, u32 ss_sid, u32 *sid) { unsigned long flags; u32 count, hash = context_compute_hash(context); @@ -308,6 +309,8 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid) goto out_unlock; dst->sid = index_to_sid(count); + dst->state = state; + dst->ss_sid = ss_sid; dst->hash = hash; rc = context_cpy(&dst->context, context); @@ -344,10 +347,6 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid) dst_convert->hash); } - if (context->len) - pr_info("SELinux: Context %s is not valid (left unmapped).\n", - context->str); - *sid = index_to_sid(count); /* write entries before updating count */ @@ -360,6 +359,11 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid) return rc; } +int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid) +{ + return sidtab_context_ss_to_sid(s, context, NULL, 0, sid); +} + static void sidtab_convert_hashtable(struct sidtab *s, u32 count) { struct sidtab_entry *entry; From patchwork Thu Jan 2 16:44:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924625 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f176.google.com (mail-qt1-f176.google.com [209.85.160.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0FC9148304 for ; Thu, 2 Jan 2025 16:45:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836349; cv=none; b=mKSq8Z+8cuTw3JWgPas/y9hKnMIpejxTJC3SUmFOHsiCNV9X6BaqJs+RFie3mKJMA0ggl+/l//h6D2TrEHB7qR2OJ9tDNzJQUv+xqRbB4G52qFkE/Mf7wf024afFoY3oZ1LDmE0ZBJEwTTPJgCdYTUr+JCh7vXbL9iDW3mJQWlQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836349; c=relaxed/simple; bh=HT1WApRkHFGVY3qDlOMfPteLCbpmPT+17nCeAk7FNJU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=S2ZPDlKGtrMeFD6xwU0AEosQFQg4gs8ILguLEn7FBp+cKaMbgwVRY70K97W5J4QJPgEPBWEfczDl/lssPDhVoDOkDWNQk9SFhlrGvUCnJrYyKtVp+Hz076LmK8jhVD8MG9PWysFE5fvfgcfBs3m7WbwnUwzE8ECqH9uE4MYRMEg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=j4eT8Tbu; arc=none smtp.client-ip=209.85.160.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="j4eT8Tbu" Received: by mail-qt1-f176.google.com with SMTP id d75a77b69052e-467b086e0easo59349731cf.1 for ; Thu, 02 Jan 2025 08:45:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836343; x=1736441143; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UICPZ7EHmKzvi2nn4Ds5q8ZzaaCRzjJWzj138UGDkJU=; b=j4eT8TbuP7v35YZp+urog4ZygM61wXciTBJ37pMdDq0xLl2JzcRLWQH8gGdnDpSb4J ulLjDjfpO5/Enwh7YxEJpxU7uDiSkrSC2SFMuH7d6g+0Kr8LDuscGkuzycL+2LQ8OqzZ hjAPWk1JnA1mN/Yfm8C4ovJCipXVcWET2Qs39RpLNXVTFQb+WFSKQ+lbLjF+NuEOyKpn 0lrH+8KNU6OujI9jzFGiW/iYAOjX7A7dEB9Uj6MQuDw4BIvIw7cdVeHli4Xtq64DjcR4 5OyZ4eDKfKndDu/Xd2MHct+WG3OIRwdoP4nD44GOUpMSbajmbV4F8JoUEqBAKItDTXRY iQSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836343; x=1736441143; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UICPZ7EHmKzvi2nn4Ds5q8ZzaaCRzjJWzj138UGDkJU=; b=mf4cHzJSrGDKWan9BjS4PpMXuzIo44kLGDZdKxqPcYf6VPp/gp+0JUlbabcnreYfMW amwPEZM1Xrk6KOsMuho3fX9HFV0K5D08iSCHX1IlN2Wxo0sEA2EOHUIK7NllUC15zVO4 25whP+1y/+zrjsE7PPOczeDO0JHh9dMzjP38HWVSL55C35H8FURpfcix9SnQfRq2DX5e 1efZICFi6SHBgJT1SqlMn/Irl2I2ZnlA6l35vr3Lt8AIh/mZxTdSqQGx37n48/q8/8+T 3l60eqM77f1T12SIwLZJPvS1DUMR8NiMqOMpdk2AT6Wra5MfjmanDrkbSnAvdQ5KxV7H qH2A== X-Gm-Message-State: AOJu0YyFyaSbbZpGyB2FHINMPlXYorMTyx8NaM1XNFdHn0fLCBFu+yIu QREI+Okg/b4Zbs4k39w6nxycy3ianOTX5b7jQfFd3fzDvZ80vV4lc9BJ9w== X-Gm-Gg: ASbGncs7eJOmsKMZfuN+rzQ1p0ItyHtU+rlBa/n1OzIjky/bsWXn6ex9lJvehpgASbY J2Zp4pyg2IeD3+va15Lgpg+4L7pslTx4/8WWBGwpI69QM+FydpO0n5TbRGTkMIQpolETtSin3HB hD+tmEeZpF0c1kcbAEWwJj7KOLQhGb0JnIdF/3o0JZzlJE52B3CM2GCl+H6xKIoCWMDfcOu/S5b F0TmYWDQIS5r7S3XdVEaBaPsrF94ETCGZdP0z8XiOBpq8Upf7LqmKztXv2Kj4E1xufbuqn6OHk/ V0rLOwblDA4i7IuLLKQBFGPTHQ1RWrU/n9sX2KtqAL7KdE8mkDAwN8tnnA4Z1TuY3LsxjA== X-Google-Smtp-Source: AGHT+IEy8xzExXYuhc5E67R03uupM1wVIOdtpjxyHaxSpuIvQXUOhrEkixRJ8FRK+DltOoT0qiNbhA== X-Received: by 2002:a05:622a:1883:b0:466:a763:257a with SMTP id d75a77b69052e-46a4a9b759fmr683358651cf.54.1735836342328; Thu, 02 Jan 2025 08:45:42 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.41 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:41 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 12/44] selinux: update hook functions to use correct selinux namespace Date: Thu, 2 Jan 2025 11:44:37 -0500 Message-Id: <20250102164509.25606-13-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Update the SELinux hook functions to use the correct SELinux namespace rather than always using the current SELinux namespace. This is necessary for hook functions that can be called outside of process context. In order to have a SELinux namespace available for use in all such hook functions, this change saves a reference to the current SELinux namespace in open file security blobs for use by send_sigiotask and in sock security blobs for use in network input or forward hooks. It also fixes a few remaining uses of current_selinux_state that should be using cred_selinux_state() on an appropriate cred structure. In order to correctly label nodes and network interfaces, the SELinux namespace is passed from the hook functions to the sel_netnode and sel_netif interfaces and cached along with the other information. Similarly, where needed, the SELinux namespace is passed from the hook functions to the selinux_netlbl and selinux_xfrm interfaces for use in invoking various security server or AVC interfaces. There are a few residual xfrm functions where we do not have a SELinux namespace available currently. For now these functions always use the init SELinux namespace. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 162 +++++++++++++++++----------- security/selinux/include/netif.h | 4 +- security/selinux/include/netlabel.h | 14 ++- security/selinux/include/netnode.h | 4 +- security/selinux/include/objsec.h | 5 + security/selinux/include/security.h | 2 + security/selinux/include/xfrm.h | 4 +- security/selinux/netif.c | 31 ++++-- security/selinux/netlabel.c | 35 +++--- security/selinux/netnode.c | 25 +++-- security/selinux/xfrm.c | 26 +++-- 11 files changed, 196 insertions(+), 116 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 23b5648be433..6fffd0aa088c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -205,7 +205,7 @@ static int selinux_lsm_notifier_avc_callback(u32 event) return 0; } -static struct selinux_state *init_selinux_state; +struct selinux_state *init_selinux_state; /* * initialise the security for the init task @@ -2082,14 +2082,14 @@ static int selinux_binder_transaction(const struct cred *from, int rc; if (mysid != fromsid) { - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(from), mysid, fromsid, SECCLASS_BINDER, BINDER__IMPERSONATE, NULL); if (rc) return rc; } - return avc_has_perm(current_selinux_state, fromsid, tosid, + return avc_has_perm(cred_selinux_state(from), fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, NULL); } @@ -2117,7 +2117,7 @@ static int selinux_binder_transfer_file(const struct cred *from, ad.u.path = file->f_path; if (sid != fsec->sid) { - rc = avc_has_perm(current_selinux_state, + rc = avc_has_perm(cred_selinux_state(to), sid, fsec->sid, SECCLASS_FD, FD__USE, @@ -2136,7 +2136,7 @@ static int selinux_binder_transfer_file(const struct cred *from, return 0; isec = backing_inode_security(dentry); - return avc_has_perm(current_selinux_state, + return avc_has_perm(cred_selinux_state(to), sid, isec->sid, isec->sclass, file_to_av(file), &ad); } @@ -3723,10 +3723,19 @@ static int selinux_file_alloc_security(struct file *file) fsec->sid = sid; fsec->fown_sid = sid; + fsec->state = get_selinux_state(current_selinux_state); return 0; } +static void selinux_file_free_security(struct file *file) +{ + struct file_security_struct *fsec = selinux_file(file); + + put_selinux_state(fsec->state); + fsec->state = NULL; +} + /* * Check whether a task has the ioctl permission and cmd * operation to an inode. @@ -3763,7 +3772,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, return 0; isec = inode_security(inode); - rc = avc_has_extended_perms(current_selinux_state, + rc = avc_has_extended_perms(cred_selinux_state(cred), ssid, isec->sid, isec->sclass, requested, driver, xperm, &ad); out: @@ -4038,7 +4047,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, else perm = signal_to_av(signum); - return avc_has_perm(current_selinux_state, + return avc_has_perm(fsec->state, fsec->fown_sid, sid, SECCLASS_PROCESS, perm, NULL); } @@ -4373,9 +4382,15 @@ static int selinux_task_movememory(struct task_struct *p) static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { + struct selinux_state *state; u32 secid; u32 perm; + if (cred) + state = cred_selinux_state(cred); + else + state = current_selinux_state; + if (!sig) perm = PROCESS__SIGNULL; /* null signal; existence test */ else @@ -4384,8 +4399,8 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info, secid = current_sid(); else secid = cred_sid(cred); - return avc_has_perm(current_selinux_state, - secid, task_sid_obj(p), SECCLASS_PROCESS, perm, NULL); + return avc_has_perm(state, secid, task_sid_obj(p), + SECCLASS_PROCESS, perm, NULL); } static void selinux_task_to_inode(struct task_struct *p, @@ -4639,6 +4654,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, * selinux_skb_peerlbl_sid - Determine the peer label of a packet * @skb: the packet * @family: protocol family + * @state: the SELinux state * @sid: the packet's peer label SID * * Description: @@ -4650,7 +4666,8 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, * peer labels. * */ -static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) +static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, + struct selinux_state *state, u32 *sid) { int err; u32 xfrm_sid; @@ -4660,12 +4677,13 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) err = selinux_xfrm_skb_sid(skb, &xfrm_sid); if (unlikely(err)) return -EACCES; - err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); + err = selinux_netlbl_skbuff_getsid(skb, family, state, &nlbl_type, + &nlbl_sid); if (unlikely(err)) return -EACCES; - err = security_net_peersid_resolve(current_selinux_state, nlbl_sid, - nlbl_type, xfrm_sid, sid); + err = security_net_peersid_resolve(state, nlbl_sid, nlbl_type, + xfrm_sid, sid); if (unlikely(err)) { pr_warn( "SELinux: failure in selinux_skb_peerlbl_sid()," @@ -4680,6 +4698,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) * selinux_conn_sid - Determine the child socket label for a connection * @sk_sid: the parent socket's SID * @skb_sid: the packet's SID + * @state: the SELinux state * @conn_sid: the resulting connection SID * * If @skb_sid is valid then the user:role:type information from @sk_sid is @@ -4688,13 +4707,13 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) * of @sk_sid. Returns zero on success, negative values on failure. * */ -static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid) +static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, + struct selinux_state *state, u32 *conn_sid) { int err = 0; if (skb_sid != SECSID_NULL) - err = security_sid_mls_copy(current_selinux_state, sk_sid, skb_sid, - conn_sid); + err = security_sid_mls_copy(state, sk_sid, skb_sid, conn_sid); else *conn_sid = sk_sid; @@ -4938,7 +4957,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in break; } - err = sel_netnode_sid(addrp, family_sa, &sid); + err = sel_netnode_sid(current_selinux_state, addrp, family_sa, + &sid); if (err) goto out; @@ -5192,7 +5212,8 @@ static int selinux_socket_unix_may_send(struct socket *sock, &ad); } -static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, +static int selinux_inet_sys_rcv_skb(struct selinux_state *state, + struct net *ns, int ifindex, char *addrp, u16 family, u32 peer_sid, struct common_audit_data *ad) { @@ -5200,21 +5221,19 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, u32 if_sid; u32 node_sid; - err = sel_netif_sid(ns, ifindex, &if_sid); + err = sel_netif_sid(state, ns, ifindex, &if_sid); if (err) return err; - err = avc_has_perm(current_selinux_state, - peer_sid, if_sid, + err = avc_has_perm(state, peer_sid, if_sid, SECCLASS_NETIF, NETIF__INGRESS, ad); if (err) return err; - err = sel_netnode_sid(addrp, family, &node_sid); + err = sel_netnode_sid(state, addrp, family, &node_sid); if (err) return err; - return avc_has_perm(current_selinux_state, - peer_sid, node_sid, - SECCLASS_NODE, NODE__RECVFROM, ad); + return avc_has_perm(state, peer_sid, node_sid, SECCLASS_NODE, + NODE__RECVFROM, ad); } static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, @@ -5223,6 +5242,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, int err = 0; struct sk_security_struct *sksec = selinux_sock(sk); u32 sk_sid = sksec->sid; + struct selinux_state *state = sksec->state; struct common_audit_data ad; struct lsm_network_audit net; char *addrp; @@ -5233,8 +5253,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, return err; if (selinux_secmark_enabled()) { - err = avc_has_perm(current_selinux_state, - sk_sid, skb->secmark, SECCLASS_PACKET, + err = avc_has_perm(state, sk_sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) return err; @@ -5243,7 +5262,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); if (err) return err; - err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); + err = selinux_xfrm_sock_rcv_skb(sksec, skb, &ad); return err; } @@ -5254,6 +5273,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) struct sk_security_struct *sksec = selinux_sock(sk); u16 family = sk->sk_family; u32 sk_sid = sksec->sid; + struct selinux_state *state = sksec->state; struct common_audit_data ad; struct lsm_network_audit net; char *addrp; @@ -5285,17 +5305,16 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (peerlbl_active) { u32 peer_sid; - err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); + err = selinux_skb_peerlbl_sid(skb, family, state, &peer_sid); if (err) return err; - err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif, + err = selinux_inet_sys_rcv_skb(state, sock_net(sk), skb->skb_iif, addrp, family, peer_sid, &ad); if (err) { selinux_netlbl_err(skb, family, err, 0); return err; } - err = avc_has_perm(current_selinux_state, - sk_sid, peer_sid, SECCLASS_PEER, + err = avc_has_perm(state, sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); if (err) { selinux_netlbl_err(skb, family, err, 0); @@ -5304,8 +5323,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) } if (secmark_active) { - err = avc_has_perm(current_selinux_state, - sk_sid, skb->secmark, SECCLASS_PACKET, + err = avc_has_perm(state, sk_sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) return err; @@ -5371,7 +5389,8 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, isec = inode_security_novalidate(SOCK_INODE(sock)); peer_secid = isec->sid; } else if (skb) - selinux_skb_peerlbl_sid(skb, family, &peer_secid); + selinux_skb_peerlbl_sid(skb, family, current_selinux_state, + &peer_secid); *secid = peer_secid; if (peer_secid == SECSID_NULL) @@ -5386,6 +5405,7 @@ static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority sksec->peer_sid = SECINITSID_UNLABELED; sksec->sid = SECINITSID_UNLABELED; sksec->sclass = SECCLASS_SOCKET; + sksec->state = get_selinux_state(current_selinux_state); selinux_netlbl_sk_security_reset(sksec); return 0; @@ -5396,6 +5416,7 @@ static void selinux_sk_free_security(struct sock *sk) struct sk_security_struct *sksec = selinux_sock(sk); selinux_netlbl_sk_security_free(sksec); + put_selinux_state(sksec->state); } static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) @@ -5406,6 +5427,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) newsksec->sid = sksec->sid; newsksec->peer_sid = sksec->peer_sid; newsksec->sclass = sksec->sclass; + newsksec->state = get_selinux_state(sksec->state); selinux_netlbl_sk_security_reset(newsksec); } @@ -5443,6 +5465,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, struct sock *sk = asoc->base.sk; u16 family = sk->sk_family; struct sk_security_struct *sksec = selinux_sock(sk); + struct selinux_state *state = sksec->state; struct common_audit_data ad; struct lsm_network_audit net; int err; @@ -5457,7 +5480,8 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, /* This will return peer_sid = SECSID_NULL if there are * no peer labels, see security_net_peersid_resolve(). */ - err = selinux_skb_peerlbl_sid(skb, family, &asoc->peer_secid); + err = selinux_skb_peerlbl_sid(skb, family, state, + &asoc->peer_secid); if (err) return err; @@ -5481,8 +5505,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, * consistency among the peer SIDs. */ ad_net_init_from_sk(&ad, &net, asoc->base.sk); - err = avc_has_perm(current_selinux_state, - sksec->peer_sid, asoc->peer_secid, + err = avc_has_perm(state, sksec->peer_sid, asoc->peer_secid, sksec->sclass, SCTP_SOCKET__ASSOCIATION, &ad); if (err) @@ -5499,6 +5522,7 @@ static int selinux_sctp_assoc_request(struct sctp_association *asoc, struct sk_buff *skb) { struct sk_security_struct *sksec = selinux_sock(asoc->base.sk); + struct selinux_state *state = sksec->state; u32 conn_sid; int err; @@ -5515,7 +5539,7 @@ static int selinux_sctp_assoc_request(struct sctp_association *asoc, * socket to be generated. selinux_sctp_sk_clone() will then * plug this into the new socket. */ - err = selinux_conn_sid(sksec->sid, asoc->peer_secid, &conn_sid); + err = selinux_conn_sid(sksec->sid, asoc->peer_secid, state, &conn_sid); if (err) return err; @@ -5642,6 +5666,7 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk newsksec->sid = asoc->secid; newsksec->peer_sid = asoc->peer_secid; newsksec->sclass = sksec->sclass; + newsksec->state = sksec->state; selinux_netlbl_sctp_sk_clone(sk, newsk); } @@ -5652,6 +5677,7 @@ static int selinux_mptcp_add_subflow(struct sock *sk, struct sock *ssk) ssksec->sclass = sksec->sclass; ssksec->sid = sksec->sid; + ssksec->state = sksec->state; /* replace the existing subflow label deleting the existing one * and re-recreating a new label using the updated context @@ -5664,21 +5690,22 @@ static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { struct sk_security_struct *sksec = selinux_sock(sk); + struct selinux_state *state = sksec->state; int err; u16 family = req->rsk_ops->family; u32 connsid; u32 peersid; - err = selinux_skb_peerlbl_sid(skb, family, &peersid); + err = selinux_skb_peerlbl_sid(skb, family, state, &peersid); if (err) return err; - err = selinux_conn_sid(sksec->sid, peersid, &connsid); + err = selinux_conn_sid(sksec->sid, peersid, state, &connsid); if (err) return err; req->secid = connsid; req->peer_secid = peersid; - return selinux_netlbl_inet_conn_request(req, family); + return selinux_netlbl_inet_conn_request(req, family, state); } static void selinux_inet_csk_clone(struct sock *newsk, @@ -5707,7 +5734,7 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) family = PF_INET; - selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); + selinux_skb_peerlbl_sid(skb, family, sksec->state, &sksec->peer_sid); } static int selinux_secmark_relabel_packet(u32 sid) @@ -5816,6 +5843,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, u32 peer_sid; struct common_audit_data ad; struct lsm_network_audit net; + struct selinux_state *se_state = init_selinux_state; int secmark_active, peerlbl_active; if (!selinux_policycap_netpeer()) @@ -5827,7 +5855,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, return NF_ACCEPT; family = state->pf; - if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) + if (selinux_skb_peerlbl_sid(skb, family, se_state, &peer_sid) != 0) return NF_DROP; ifindex = state->in->ifindex; @@ -5838,7 +5866,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, if (peerlbl_active) { int err; - err = selinux_inet_sys_rcv_skb(state->net, ifindex, + err = selinux_inet_sys_rcv_skb(se_state, state->net, ifindex, addrp, family, peer_sid, &ad); if (err) { selinux_netlbl_err(skb, family, err, 1); @@ -5847,8 +5875,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, } if (secmark_active) - if (avc_has_perm(current_selinux_state, - peer_sid, skb->secmark, + if (avc_has_perm(se_state, peer_sid, skb->secmark, SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) return NF_DROP; @@ -5857,7 +5884,8 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, * path because we want to make sure we apply the necessary * labeling before IPsec is applied so we can leverage AH * protection */ - if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0) + if (selinux_netlbl_skbuff_setsid(skb, family, se_state, peer_sid) + != 0) return NF_DROP; return NF_ACCEPT; @@ -5866,6 +5894,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { + struct selinux_state *se_state; struct sock *sk; u32 sid; @@ -5897,9 +5926,12 @@ static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb, /* standard practice, label using the parent socket */ sksec = selinux_sock(sk); sid = sksec->sid; - } else + se_state = sksec->state; + } else { sid = SECINITSID_KERNEL; - if (selinux_netlbl_skbuff_setsid(skb, state->pf, sid) != 0) + se_state = init_selinux_state; + } + if (selinux_netlbl_skbuff_setsid(skb, state->pf, se_state, sid) != 0) return NF_DROP; return NF_ACCEPT; @@ -5925,12 +5957,12 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, return NF_DROP; if (selinux_secmark_enabled()) - if (avc_has_perm(current_selinux_state, - sksec->sid, skb->secmark, + if (avc_has_perm(sksec->state, sksec->sid, skb->secmark, SECCLASS_PACKET, PACKET__SEND, &ad)) return NF_DROP_ERR(-ECONNREFUSED); - if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) + if (selinux_xfrm_postroute_last(sksec->sid, skb, sksec->state, &ad, + proto)) return NF_DROP_ERR(-ECONNREFUSED); return NF_ACCEPT; @@ -5948,6 +5980,7 @@ static unsigned int selinux_ip_postroute(void *priv, struct common_audit_data ad; struct lsm_network_audit net; char *addrp; + struct selinux_state *se_state = init_selinux_state; int secmark_active, peerlbl_active; /* If any sort of compatibility mode is enabled then handoff processing @@ -5989,7 +6022,8 @@ static unsigned int selinux_ip_postroute(void *priv, * query the packet directly to determine the security label. */ if (skb->skb_iif) { secmark_perm = PACKET__FORWARD_OUT; - if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) + if (selinux_skb_peerlbl_sid(skb, family, se_state, + &peer_sid)) return NF_DROP; } else { secmark_perm = PACKET__SEND; @@ -6009,7 +6043,8 @@ static unsigned int selinux_ip_postroute(void *priv, struct sk_security_struct *sksec; sksec = selinux_sock(sk); - if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) + se_state = sksec->state; + if (selinux_skb_peerlbl_sid(skb, family, se_state, &skb_sid)) return NF_DROP; /* At this point, if the returned skb peerlbl is SECSID_NULL * and the packet has been through at least one XFRM @@ -6031,7 +6066,7 @@ static unsigned int selinux_ip_postroute(void *priv, return NF_DROP_ERR(-ECONNREFUSED); } } - if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) + if (selinux_conn_sid(sksec->sid, skb_sid, se_state, &peer_sid)) return NF_DROP; secmark_perm = PACKET__SEND; } else { @@ -6040,6 +6075,7 @@ static unsigned int selinux_ip_postroute(void *priv, struct sk_security_struct *sksec = selinux_sock(sk); peer_sid = sksec->sid; secmark_perm = PACKET__SEND; + se_state = sksec->state; } ifindex = state->out->ifindex; @@ -6048,8 +6084,7 @@ static unsigned int selinux_ip_postroute(void *priv, return NF_DROP; if (secmark_active) - if (avc_has_perm(current_selinux_state, - peer_sid, skb->secmark, + if (avc_has_perm(se_state, peer_sid, skb->secmark, SECCLASS_PACKET, secmark_perm, &ad)) return NF_DROP_ERR(-ECONNREFUSED); @@ -6057,17 +6092,15 @@ static unsigned int selinux_ip_postroute(void *priv, u32 if_sid; u32 node_sid; - if (sel_netif_sid(state->net, ifindex, &if_sid)) + if (sel_netif_sid(se_state, state->net, ifindex, &if_sid)) return NF_DROP; - if (avc_has_perm(current_selinux_state, - peer_sid, if_sid, + if (avc_has_perm(se_state, peer_sid, if_sid, SECCLASS_NETIF, NETIF__EGRESS, &ad)) return NF_DROP_ERR(-ECONNREFUSED); - if (sel_netnode_sid(addrp, family, &node_sid)) + if (sel_netnode_sid(se_state, addrp, family, &node_sid)) return NF_DROP; - if (avc_has_perm(current_selinux_state, - peer_sid, node_sid, + if (avc_has_perm(se_state, peer_sid, node_sid, SECCLASS_NODE, NODE__SENDTO, &ad)) return NF_DROP_ERR(-ECONNREFUSED); } @@ -7388,6 +7421,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(file_permission, selinux_file_permission), LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), + LSM_HOOK_INIT(file_free_security, selinux_file_free_security), LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl), LSM_HOOK_INIT(file_ioctl_compat, selinux_file_ioctl_compat), LSM_HOOK_INIT(mmap_file, selinux_mmap_file), diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h index 2838bdc170dd..32de496bb948 100644 --- a/security/selinux/include/netif.h +++ b/security/selinux/include/netif.h @@ -19,6 +19,8 @@ void sel_netif_flush(void); -int sel_netif_sid(struct net *ns, int ifindex, u32 *sid); +struct selinux_state; +int sel_netif_sid(struct selinux_state *state, struct net *ns, int ifindex, + u32 *sid); #endif /* _SELINUX_NETIF_H_ */ diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 5731c0dcd3e8..b8ee75e9d155 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -32,12 +32,15 @@ void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec); void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec); -int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, u32 *type, +int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, + struct selinux_state *state, u32 *type, u32 *sid); -int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, u16 family, u32 sid); +int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, u16 family, + struct selinux_state *state, u32 sid); int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, struct sk_buff *skb); -int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family); +int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family, + struct selinux_state *state); void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family); void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk); int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); @@ -75,6 +78,7 @@ selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) } static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, + struct selinux_state *state, u32 *type, u32 *sid) { *type = NETLBL_NLTYPE_NONE; @@ -82,6 +86,7 @@ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, return 0; } static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, u16 family, + struct selinux_state *state, u32 sid) { return 0; @@ -94,7 +99,8 @@ selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, return 0; } static inline int selinux_netlbl_inet_conn_request(struct request_sock *req, - u16 family) + u16 family, + struct selinux_state *state) { return 0; } diff --git a/security/selinux/include/netnode.h b/security/selinux/include/netnode.h index 9b8b655a8cd3..755bca257e44 100644 --- a/security/selinux/include/netnode.h +++ b/security/selinux/include/netnode.h @@ -21,6 +21,8 @@ void sel_netnode_flush(void); -int sel_netnode_sid(void *addr, u16 family, u32 *sid); +struct selinux_state; +int sel_netnode_sid(struct selinux_state *state, void *addr, u16 family, + u32 *sid); #endif diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index d522caa7f93a..6560cb13fc34 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -28,6 +28,7 @@ #include #include "flask.h" #include "avc.h" +#include "security.h" enum label_initialized { LABEL_INVALID, /* invalid or not initialized */ @@ -50,6 +51,7 @@ struct file_security_struct { u32 fown_sid; /* SID of file owner (for SIGIO) */ u32 isid; /* SID of inode at the time of file open */ u32 pseqno; /* Policy seqno at the time of file open */ + struct selinux_state *state; /* SELinux state */ }; struct superblock_security_struct { @@ -76,6 +78,7 @@ struct netif_security_struct { struct net *ns; /* network namespace */ int ifindex; /* device index */ u32 sid; /* SID for this interface */ + struct selinux_state *state; /* SELinux state */ }; struct netnode_security_struct { @@ -85,6 +88,7 @@ struct netnode_security_struct { } addr; u32 sid; /* SID for this node */ u16 family; /* address family */ + struct selinux_state *state; /* SELinux state */ }; struct netport_security_struct { @@ -111,6 +115,7 @@ struct sk_security_struct { SCTP_ASSOC_UNSET = 0, SCTP_ASSOC_SET, } sctp_assoc_state; + struct selinux_state *state; /* SELinux state */ }; struct tun_security_struct { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index fe16bc86627d..261a6971f262 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -112,6 +112,8 @@ struct selinux_state { struct work_struct work; } __randomize_layout; +extern struct selinux_state *init_selinux_state; + int selinux_state_create(struct selinux_state *parent, struct selinux_state **state); void __put_selinux_state(struct selinux_state *state); diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index de485556ae29..6f7236efc758 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h @@ -38,9 +38,11 @@ static inline int selinux_xfrm_enabled(void) return (atomic_read(&selinux_xfrm_refcount) > 0); } -int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, +int selinux_xfrm_sock_rcv_skb(struct sk_security_struct *sksec, + struct sk_buff *skb, struct common_audit_data *ad); int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, + struct selinux_state *state, struct common_audit_data *ad, u8 proto); int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid); diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 5f0d20031784..81a96886ea57 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -56,6 +56,7 @@ static inline u32 sel_netif_hashfn(const struct net *ns, int ifindex) /** * sel_netif_find - Search for an interface record + * @state: the SELinux state * @ns: the network namespace * @ifindex: the network interface * @@ -64,7 +65,8 @@ static inline u32 sel_netif_hashfn(const struct net *ns, int ifindex) * If an entry can not be found in the table return NULL. * */ -static inline struct sel_netif *sel_netif_find(const struct net *ns, +static inline struct sel_netif *sel_netif_find(struct selinux_state *state, + const struct net *ns, int ifindex) { u32 idx = sel_netif_hashfn(ns, ifindex); @@ -72,7 +74,8 @@ static inline struct sel_netif *sel_netif_find(const struct net *ns, list_for_each_entry_rcu(netif, &sel_netif_hash[idx], list) if (net_eq(netif->nsec.ns, ns) && - netif->nsec.ifindex == ifindex) + netif->nsec.ifindex == ifindex && + (!state || netif->nsec.state == state)) return netif; return NULL; @@ -113,11 +116,13 @@ static void sel_netif_destroy(struct sel_netif *netif) { list_del_rcu(&netif->list); sel_netif_total--; + put_selinux_state(netif->nsec.state); kfree_rcu(netif, rcu_head); } /** * sel_netif_sid_slow - Lookup the SID of a network interface using the policy + * @state: the SELinux state * @ns: the network namespace * @ifindex: the network interface * @sid: interface SID @@ -129,7 +134,8 @@ static void sel_netif_destroy(struct sel_netif *netif) * failure. * */ -static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) +static int sel_netif_sid_slow(struct selinux_state *state, struct net *ns, + int ifindex, u32 *sid) { int ret = 0; struct sel_netif *netif; @@ -147,13 +153,13 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) } spin_lock_bh(&sel_netif_lock); - netif = sel_netif_find(ns, ifindex); + netif = sel_netif_find(state, ns, ifindex); if (netif != NULL) { *sid = netif->nsec.sid; goto out; } - ret = security_netif_sid(current_selinux_state, dev->name, sid); + ret = security_netif_sid(state, dev->name, sid); if (ret != 0) goto out; new = kzalloc(sizeof(*new), GFP_ATOMIC); @@ -161,8 +167,11 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) new->nsec.ns = ns; new->nsec.ifindex = ifindex; new->nsec.sid = *sid; - if (sel_netif_insert(new)) + new->nsec.state = get_selinux_state(state); + if (sel_netif_insert(new)) { + put_selinux_state(state); kfree(new); + } } out: @@ -176,6 +185,7 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) /** * sel_netif_sid - Lookup the SID of a network interface + * @state: the SELinux state * @ns: the network namespace * @ifindex: the network interface * @sid: interface SID @@ -188,12 +198,13 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) * on failure. * */ -int sel_netif_sid(struct net *ns, int ifindex, u32 *sid) +int sel_netif_sid(struct selinux_state *state, struct net *ns, int ifindex, + u32 *sid) { struct sel_netif *netif; rcu_read_lock(); - netif = sel_netif_find(ns, ifindex); + netif = sel_netif_find(state, ns, ifindex); if (likely(netif != NULL)) { *sid = netif->nsec.sid; rcu_read_unlock(); @@ -201,7 +212,7 @@ int sel_netif_sid(struct net *ns, int ifindex, u32 *sid) } rcu_read_unlock(); - return sel_netif_sid_slow(ns, ifindex, sid); + return sel_netif_sid_slow(state, ns, ifindex, sid); } /** @@ -220,7 +231,7 @@ static void sel_netif_kill(const struct net *ns, int ifindex) rcu_read_lock(); spin_lock_bh(&sel_netif_lock); - netif = sel_netif_find(ns, ifindex); + netif = sel_netif_find(NULL, ns, ifindex); if (netif) sel_netif_destroy(netif); spin_unlock_bh(&sel_netif_lock); diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index e35c224145a4..9c360f2ee7fc 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -32,6 +32,7 @@ * @skb: the packet * @family: the packet's address family * @secattr: the NetLabel security attributes + * @state: the SELinux state * @sid: the SID * * Description: @@ -43,11 +44,12 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, u16 family, struct netlbl_lsm_secattr *secattr, + struct selinux_state *state, u32 *sid) { int rc; - rc = security_netlbl_secattr_to_sid(current_selinux_state, secattr, sid); + rc = security_netlbl_secattr_to_sid(state, secattr, sid); if (rc == 0 && (secattr->flags & NETLBL_SECATTR_CACHEABLE) && (secattr->flags & NETLBL_SECATTR_CACHE)) @@ -79,8 +81,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) if (secattr == NULL) return ERR_PTR(-ENOMEM); - rc = security_netlbl_sid_to_secattr(current_selinux_state, sksec->sid, - secattr); + rc = security_netlbl_sid_to_secattr(sksec->state, sksec->sid, secattr); if (rc != 0) { netlbl_secattr_free(secattr); return ERR_PTR(rc); @@ -183,6 +184,7 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet * @family: protocol family + * @state: the SELinux state * @type: NetLabel labeling protocol type * @sid: the SID * @@ -194,6 +196,7 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) */ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, + struct selinux_state *state, u32 *type, u32 *sid) { @@ -210,7 +213,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) rc = selinux_netlbl_sidlookup_cached(skb, family, - &secattr, sid); + &secattr, state, sid); else *sid = SECSID_NULL; *type = secattr.type; @@ -223,6 +226,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid * @skb: the packet * @family: protocol family + * @state: the SELinux state * @sid: the SID * * Description @@ -232,6 +236,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, */ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, u16 family, + struct selinux_state *state, u32 sid) { int rc; @@ -252,8 +257,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, if (secattr == NULL) { secattr = &secattr_storage; netlbl_secattr_init(secattr); - rc = security_netlbl_sid_to_secattr(current_selinux_state, sid, - secattr); + rc = security_netlbl_sid_to_secattr(state, sid, secattr); if (rc != 0) goto skbuff_setsid_return; } @@ -290,8 +294,8 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, return 0; netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(current_selinux_state, - asoc->secid, &secattr); + rc = security_netlbl_sid_to_secattr(sksec->state, asoc->secid, + &secattr); if (rc != 0) goto assoc_request_return; @@ -322,6 +326,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, * selinux_netlbl_inet_conn_request - Label an incoming stream connection * @req: incoming connection request socket * @family: the request socket's address family + * @state: the SELinux state * * Description: * A new incoming connection request is represented by @req, we need to label @@ -330,7 +335,8 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, * is complete. Returns zero on success, negative values on failure. * */ -int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) +int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family, + struct selinux_state *state) { int rc; struct netlbl_lsm_secattr secattr; @@ -339,8 +345,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) return 0; netlbl_secattr_init(&secattr); - rc = security_netlbl_sid_to_secattr(current_selinux_state, req->secid, - &secattr); + rc = security_netlbl_sid_to_secattr(state, req->secid, &secattr); if (rc != 0) goto inet_conn_request_return; rc = netlbl_req_setattr(req, &secattr); @@ -454,8 +459,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) - rc = selinux_netlbl_sidlookup_cached(skb, family, - &secattr, &nlbl_sid); + rc = selinux_netlbl_sidlookup_cached(skb, family, &secattr, + sksec->state, &nlbl_sid); else nlbl_sid = SECINITSID_UNLABELED; netlbl_secattr_destroy(&secattr); @@ -473,8 +478,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, perm = RAWIP_SOCKET__RECVFROM; } - rc = avc_has_perm(current_selinux_state, - sksec->sid, nlbl_sid, sksec->sclass, perm, ad); + rc = avc_has_perm(sksec->state, sksec->sid, nlbl_sid, sksec->sclass, + perm, ad); if (rc == 0) return 0; diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 7683c7f28421..9a56fdf76f81 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -100,7 +100,8 @@ static unsigned int sel_netnode_hashfn_ipv6(const struct in6_addr *addr) * entry can not be found in the table return NULL. * */ -static struct sel_netnode *sel_netnode_find(const void *addr, u16 family) +static struct sel_netnode *sel_netnode_find(struct selinux_state *state, + const void *addr, u16 family) { unsigned int idx; struct sel_netnode *node; @@ -118,7 +119,7 @@ static struct sel_netnode *sel_netnode_find(const void *addr, u16 family) } list_for_each_entry_rcu(node, &sel_netnode_hash[idx].list, list) - if (node->nsec.family == family) + if (node->nsec.family == family && node->nsec.state == state) switch (family) { case PF_INET: if (node->nsec.addr.ipv4 == *(const __be32 *)addr) @@ -176,6 +177,7 @@ static void sel_netnode_insert(struct sel_netnode *node) /** * sel_netnode_sid_slow - Lookup the SID of a network address using the policy + * @state: the SELinux state * @addr: the IP address * @family: the address family * @sid: node SID @@ -187,14 +189,15 @@ static void sel_netnode_insert(struct sel_netnode *node) * failure. * */ -static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) +static int sel_netnode_sid_slow(struct selinux_state *state, void *addr, + u16 family, u32 *sid) { int ret; struct sel_netnode *node; struct sel_netnode *new; spin_lock_bh(&sel_netnode_lock); - node = sel_netnode_find(addr, family); + node = sel_netnode_find(state, addr, family); if (node != NULL) { *sid = node->nsec.sid; spin_unlock_bh(&sel_netnode_lock); @@ -204,13 +207,13 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) new = kzalloc(sizeof(*new), GFP_ATOMIC); switch (family) { case PF_INET: - ret = security_node_sid(current_selinux_state, PF_INET, + ret = security_node_sid(state, PF_INET, addr, sizeof(struct in_addr), sid); if (new) new->nsec.addr.ipv4 = *(__be32 *)addr; break; case PF_INET6: - ret = security_node_sid(current_selinux_state, PF_INET6, + ret = security_node_sid(state, PF_INET6, addr, sizeof(struct in6_addr), sid); if (new) new->nsec.addr.ipv6 = *(struct in6_addr *)addr; @@ -222,6 +225,7 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) if (ret == 0 && new) { new->nsec.family = family; new->nsec.sid = *sid; + new->nsec.state = get_selinux_state(state); sel_netnode_insert(new); } else kfree(new); @@ -235,6 +239,7 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) /** * sel_netnode_sid - Lookup the SID of a network address + * @state: the SELinux state * @addr: the IP address * @family: the address family * @sid: node SID @@ -247,12 +252,13 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) * on failure. * */ -int sel_netnode_sid(void *addr, u16 family, u32 *sid) +int sel_netnode_sid(struct selinux_state *state, void *addr, u16 family, + u32 *sid) { struct sel_netnode *node; rcu_read_lock(); - node = sel_netnode_find(addr, family); + node = sel_netnode_find(state, addr, family); if (node != NULL) { *sid = node->nsec.sid; rcu_read_unlock(); @@ -260,7 +266,7 @@ int sel_netnode_sid(void *addr, u16 family, u32 *sid) } rcu_read_unlock(); - return sel_netnode_sid_slow(addr, family, sid); + return sel_netnode_sid_slow(state, addr, family, sid); } /** @@ -280,6 +286,7 @@ void sel_netnode_flush(void) list_for_each_entry_safe(node, node_tmp, &sel_netnode_hash[idx].list, list) { list_del_rcu(&node->list); + put_selinux_state(node->nsec.state); kfree_rcu(node, rcu); } sel_netnode_hash[idx].size = 0; diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 4d1647ba8e5f..855f77630bdb 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -149,6 +149,8 @@ static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx) */ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) { + /* TODO: obtain SELinux state from related sock */ + struct selinux_state *state = init_selinux_state; int rc; /* All flows should be treated as polmatch'ing an otherwise applicable @@ -160,8 +162,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) if (!selinux_authorizable_ctx(ctx)) return -EINVAL; - rc = avc_has_perm(current_selinux_state, - fl_secid, ctx->ctx_sid, + rc = avc_has_perm(state, fl_secid, ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL); return (rc == -EACCES ? -ESRCH : rc); } @@ -174,6 +175,8 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, const struct flowi_common *flic) { + /* TODO: obtain SELinux state from related sock */ + struct selinux_state *state = init_selinux_state; u32 state_sid; u32 flic_sid; @@ -202,9 +205,8 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, /* We don't need a separate SA Vs. policy polmatch check since the SA * is now of the same label as the flow and a flow Vs. policy polmatch * check had already happened in selinux_xfrm_policy_lookup() above. */ - return (avc_has_perm(current_selinux_state, flic_sid, state_sid, - SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, - NULL) ? 0 : 1); + return (avc_has_perm(state, flic_sid, state_sid, SECCLASS_ASSOCIATION, + ASSOCIATION__SENDTO, NULL) ? 0 : 1); } static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) @@ -341,6 +343,8 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid) { + /* TODO: Obtain SELinux state from related sock */ + struct selinux_state *state = init_selinux_state; int rc; struct xfrm_sec_ctx *ctx; char *ctx_str = NULL; @@ -352,8 +356,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, if (secid == 0) return -EINVAL; - rc = security_sid_to_context(current_selinux_state, secid, &ctx_str, - &str_len); + rc = security_sid_to_context(state, secid, &ctx_str, &str_len); if (rc) return rc; @@ -399,10 +402,11 @@ int selinux_xfrm_state_delete(struct xfrm_state *x) * we need to check for unlabelled access since this may not have * gone thru the IPSec process. */ -int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, +int selinux_xfrm_sock_rcv_skb(struct sk_security_struct *sksec, struct sk_buff *skb, struct common_audit_data *ad) { int i; + u32 sk_sid = sksec->sid; struct sec_path *sp = skb_sec_path(skb); u32 peer_sid = SECINITSID_UNLABELED; @@ -421,8 +425,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, /* This check even when there's no association involved is intended, * according to Trent Jaeger, to make sure a process can't engage in * non-IPsec communication unless explicitly allowed by policy. */ - return avc_has_perm(current_selinux_state, - sk_sid, peer_sid, + return avc_has_perm(sksec->state, sk_sid, peer_sid, SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad); } @@ -434,6 +437,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, * checked in the selinux_xfrm_state_pol_flow_match hook above. */ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, + struct selinux_state *state, struct common_audit_data *ad, u8 proto) { struct dst_entry *dst; @@ -465,6 +469,6 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, /* This check even when there's no association involved is intended, * according to Trent Jaeger, to make sure a process can't engage in * non-IPsec communication unless explicitly allowed by policy. */ - return avc_has_perm(current_selinux_state, sk_sid, SECINITSID_UNLABELED, + return avc_has_perm(state, sk_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad); } From patchwork Thu Jan 2 16:44:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924621 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f177.google.com (mail-qt1-f177.google.com [209.85.160.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB3A57B3E1 for ; Thu, 2 Jan 2025 16:45:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836347; cv=none; b=OgrUluj5R1XA6o0bbtaDveGCpLqk9QW5W+kSdPFPl/86QzYimAMwzrwcWAklC6z2Ddg0t8L5g2G3w44bQxJE1GFY3ZEagJeD7D4iQarfuosQBWqVxRyKW9v+MOaTT0JjRUbS39YdAM6cTrXb0wNdSXHwwJh/wKfS1bxtxbzDS88= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836347; c=relaxed/simple; bh=KwpRHOUviaH4AiGAOCn1t9ffHK9VouigNcBVqx2O2HM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Uoqrirb9dNmTEtQOO5gghm5DW6N7qy+qWM8ICWnTAifx0Bmgyzoqb1nydMajLZe/AoMQ5FpmFmRVc+hPjvAVoF4IlYnGGVY1SnPXPSFJM6+m26mz4aLUiz6sXgWPowWUq9FaepUe411XKLz9b+JZ+oHAUkr7kZmmAAHh+7UYetI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Jbtua4Zr; arc=none smtp.client-ip=209.85.160.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Jbtua4Zr" Received: by mail-qt1-f177.google.com with SMTP id d75a77b69052e-467b086e0easo59349741cf.1 for ; Thu, 02 Jan 2025 08:45:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836343; x=1736441143; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2UhssZCc2QQmkomt4jnH3pklSAzAm4l66a8xNIU+ZcI=; b=Jbtua4ZrEo1Xyofugd/a/oaYwqjck4JKzoyth2oivZ4Wk56S9jrQ/hg3R2QCQ4+JFZ Pxqkvvqz0SPljMtp271i/nrMSbgP3Z79cRrm7nA0HwoIBauS0MnpFXApYAUvYR7JW7OT sId5Q+x7hUCwgLrPlqZLqWeZ1yh+3FSPC01dRzocuy2ZDUh9oBhAgkPxFhWgXcFauYUl c+JBrZ+/rmxMex1kUzTzyvesIF+CPe9xY7IB6Od771CDD5wfvX9MdCv5QEDxLVyn6J7G uEN8ZDByYMe67i96Q/wfAiuqb4QpPfrCsHfCRI9ax6JXHjmuVHhIdXQmhCOYwu75pw54 1WsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836343; x=1736441143; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2UhssZCc2QQmkomt4jnH3pklSAzAm4l66a8xNIU+ZcI=; b=QGjStvi9EZx2Tx8z73PB+EeUQ4iFmat3A+nB34orXpaPegeqe43lbPWpqCP408E5MA Xv1oxL4N/Ms4gwEoL3us1opgGeYChA/gxFe65123suOUaoc3urUHN7PID88RTYoMed7W 59sGGol1B80K8Gq57Tf3pkVk/UAahaE78wRcmI/iYH5OMkue5pBzC6kM7vxpWY2u5vTt zoI5gHx7nBRwdjOG7/z1r6p02QunS9Z/VhU44+YnrQCekhq1wQy6gRFJCd+fNo+hPC+m mGaqz8bK1IvN30pzhRqDvFdqeSIyilYHNnSEizkrXjzjA31WdfIZSdRnlqfE93wZ+EMN QQqQ== X-Gm-Message-State: AOJu0Yz5Q+R38ZQdVyh0ncAuda/UxoLa3AInHlYf7mtl5lSlWuGAkMWH L9w/XX8Q/9Ex1nIsJGt6VdjlYFvOMZl1K0eWIY/f8b6x3gwLEW10C2IkTw== X-Gm-Gg: ASbGnctWF/69qBHywZF/kjqlqfCnA+2KD/2QzmWKAoAo4dEdjfizAJuS9B7IhGeUutm jgriyasnYb6HfKw4iAisqD4YwMX+H6IOnc9k7q/KVVziFEtZuVYqOIpfYP7aCrk/lgi2B2D1AP0 FILaWioNhjJTvvg9mrQD/tP2qInZ+6CeIV0AsE8STeuwgd82/ryB7e0xU6cJ7z2x7+oVw+hkI+d 7tkOmwo6PVKPXhC5F60pq/472KWLSvKphChIQ7K7KWaHX4N5hSYKaLKSi7QlCHRHRK5tWn9H7Bs KwYyhns7rhrU+rf3Pv3orSl3mp/Ue/XK8Ns/kKrv152DNpYdvdgnYmbFiTotyKKZ7FLCUw== X-Google-Smtp-Source: AGHT+IGvio6JXwApI62myZ793TlORPuuofLf8R/19inAHK1X2jz/gip8MhyNwBwWxxv17drFNjRldQ== X-Received: by 2002:a05:622a:594:b0:467:7f7e:57fa with SMTP id d75a77b69052e-46a4a8ee54amr661943591cf.33.1735836342916; Thu, 02 Jan 2025 08:45:42 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.42 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:42 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 13/44] selinux: introduce cred_task_has_perm() Date: Thu, 2 Jan 2025 11:44:38 -0500 Message-Id: <20250102164509.25606-14-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce cred_task_has_perm() for checking permissions between a cred and a target task against not only the current SELinux namespace but all ancestor namespaces too. Convert existing cred-task permission checks in the SELinux hook functions to use cred_task_has_perm() instead of calling avc_has_perm(). Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 44 ++++++++++++++++++ security/selinux/hooks.c | 81 ++++++++++++---------------------- security/selinux/include/avc.h | 4 ++ 3 files changed, 77 insertions(+), 52 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index cc20c5d8b63a..bdd97f8bb571 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1233,6 +1233,50 @@ int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, return rc; } +static u32 task_sid_obj_for_state(const struct task_struct *p, + const struct selinux_state *state) +{ + const struct task_security_struct *tsec; + u32 sid; + + rcu_read_lock(); + tsec = selinux_cred(__task_cred(p)); + while (tsec->state != state && tsec->parent_cred) + tsec = selinux_cred(tsec->parent_cred); + if (tsec->state == state) + sid = tsec->sid; + else + sid = SECINITSID_UNLABELED; + rcu_read_unlock(); + return sid; +} + +int cred_task_has_perm(const struct cred *cred, const struct task_struct *p, + u16 tclass, u32 requested, + struct common_audit_data *ad) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + u32 tsid; + int rc; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + tsid = task_sid_obj_for_state(p, state); + + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + u32 avc_policy_seqno(struct selinux_state *state) { return state->avc->avc_cache.latest_notif; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6fffd0aa088c..c7aca5610402 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2144,15 +2144,12 @@ static int selinux_binder_transfer_file(const struct cred *from, static int selinux_ptrace_access_check(struct task_struct *child, unsigned int mode) { - u32 sid = current_sid(); - u32 csid = task_sid_obj(child); - if (mode & PTRACE_MODE_READ) - return avc_has_perm(current_selinux_state, - sid, csid, SECCLASS_FILE, FILE__READ, NULL); + return cred_task_has_perm(current_cred(), child, + SECCLASS_FILE, FILE__READ, NULL); - return avc_has_perm(current_selinux_state, - sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); + return cred_task_has_perm(current_cred(), child, SECCLASS_PROCESS, + PROCESS__PTRACE, NULL); } static int selinux_ptrace_traceme(struct task_struct *parent) @@ -2165,9 +2162,8 @@ static int selinux_ptrace_traceme(struct task_struct *parent) static int selinux_capget(const struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(target), SECCLASS_PROCESS, - PROCESS__GETCAP, NULL); + return cred_task_has_perm(current_cred(), target, SECCLASS_PROCESS, + PROCESS__GETCAP, NULL); } static int selinux_capset(struct cred *new, const struct cred *old, @@ -4274,23 +4270,20 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents) static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETPGID, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETPGID, NULL); } static int selinux_task_getpgid(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__GETPGID, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__GETPGID, NULL); } static int selinux_task_getsid(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__GETSESSION, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__GETSESSION, NULL); } static void selinux_current_getlsmprop_subj(struct lsm_prop *prop) @@ -4306,23 +4299,20 @@ static void selinux_task_getlsmprop_obj(struct task_struct *p, static int selinux_task_setnice(struct task_struct *p, int nice) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETSCHED, NULL); } static int selinux_task_setioprio(struct task_struct *p, int ioprio) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETSCHED, NULL); } static int selinux_task_getioprio(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__GETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__GETSCHED, NULL); } static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred, @@ -4351,56 +4341,43 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, later be used as a safe reset point for the soft limit upon context transitions. See selinux_bprm_committing_creds. */ if (old_rlim->rlim_max != new_rlim->rlim_max) - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), - SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETRLIMIT, NULL); return 0; } static int selinux_task_setscheduler(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETSCHED, NULL); } static int selinux_task_getscheduler(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__GETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__GETSCHED, NULL); } static int selinux_task_movememory(struct task_struct *p) { - return avc_has_perm(current_selinux_state, - current_sid(), task_sid_obj(p), SECCLASS_PROCESS, - PROCESS__SETSCHED, NULL); + return cred_task_has_perm(current_cred(), p, SECCLASS_PROCESS, + PROCESS__SETSCHED, NULL); } static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { - struct selinux_state *state; - u32 secid; u32 perm; - if (cred) - state = cred_selinux_state(cred); - else - state = current_selinux_state; + if (!cred) + cred = current_cred(); if (!sig) perm = PROCESS__SIGNULL; /* null signal; existence test */ else perm = signal_to_av(sig); - if (!cred) - secid = current_sid(); - else - secid = cred_sid(cred); - return avc_has_perm(state, secid, task_sid_obj(p), - SECCLASS_PROCESS, perm, NULL); + return cred_task_has_perm(cred, p, SECCLASS_PROCESS, perm, NULL); } static void selinux_task_to_inode(struct task_struct *p, diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 9c6d9c5e727e..0a12ebe43632 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -144,6 +144,10 @@ int avc_has_extended_perms(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, u32 requested, u8 driver, u8 perm, struct common_audit_data *ad); +int cred_task_has_perm(const struct cred *cred, const struct task_struct *p, + u16 tclass, u32 requested, + struct common_audit_data *auditdata); + u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 From patchwork Thu Jan 2 16:44:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924623 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f181.google.com (mail-qt1-f181.google.com [209.85.160.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20112153803 for ; Thu, 2 Jan 2025 16:45:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836349; cv=none; b=bQRxS9tqiT+yLO0H7DVaPvrxjGtNBTWzPWIp8NIzMTSjsw7Z3wcVLDqJtFz9YMNtgp8IjBkHJ1rU/zRq7oh6bCOGyVkNuXM2/UtaPXU0N1tFgbdnA5ykSbnqkQQqelffGk5IKKbhgjUJCKwJ+fIU4ddX1TF+KlfJ3NtnklvoBbU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836349; c=relaxed/simple; bh=1O5sylxr8M8hFOuWv2BC10pwyG/sr4+MdROL6mbF80Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=T1CEQzymxZ5dS2+GT3hrQBfaLPGnG2SZB5fhNO5qW7wIALNpg/iD7V/kKoR2KgGiaazVqYRQoX1NJT3GTAzww2jA984Y5nqvhe+XgNuwQBa7A3fERWGJu0pex0Ak43010QTWJJ5a2q3QmB/5gdkH9wHeudmGqEU8NfI8NZeYKg4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=UDBwQjns; arc=none smtp.client-ip=209.85.160.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UDBwQjns" Received: by mail-qt1-f181.google.com with SMTP id d75a77b69052e-46769b34cbfso171275831cf.0 for ; Thu, 02 Jan 2025 08:45:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836344; x=1736441144; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8NhDILDRD0nqc3fBBu1FK6YnCMmG0lhNRfdYsK64T4I=; b=UDBwQjnsRMHxdZZlnYeDH83KouYdZByheS1sm6hoDz8k3h2Mz0aWmTZwHfolmbN6nq 9X/V5TmI6ccFftkCKOEVM8oi40ZPTuijQmEEae0R6ZkC5XfvM6BWCEWRkl0D6szi2sdG gSQeUSAIVT9u0TnQX62zgR+ypwCcj7Y/wiYqTQY2KAxB9HOylm/3APVD6U/szi5VxIs6 CzGF8hWlGfaTX/dspDANiGY6eMNalHao2Ab47AXqZF8q0EbPHJjbf+Uh5fmWg75R8Ffc PRgaxO2wSVtF2AspJf9ap5tnsDWENr7T9XG2RmAH4hYtP+nJx0AvnLDwjINyrpK3OAVZ y1Hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836344; x=1736441144; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8NhDILDRD0nqc3fBBu1FK6YnCMmG0lhNRfdYsK64T4I=; b=FqxWtSg9fi7gYYjXEH0w67c1NI+8bbYPCyFsmSoyITgg9+E9cv2hkd8sMA0vrfJN3f fK1zZ0VFRa9aAEPVK+bsaLakOaIR4qP4YAh7YEnwZJmk2AwX74fJYMIvVP+fhuQCVGB9 LoWHUwuFpzJwFsdoHjjEBlP1CeacWTmVHbC5no3UOIAmoDta1pjtxSMv/Rp+AgyP1aIw XKkjc27Ux7H4UHYOlr2DV+YWtMTdkLYW7191X4M2BKpZFo3YHoH8PgmUQWsGlIvSwDRl j9C2+Vp9ZRBpuHn3zZO5MLS2XDC1WbkC7ycF30uFtjgqJ2HQkk3yuWCsS0qpWVpOuDLm uGIQ== X-Gm-Message-State: AOJu0YwYZd4UpcJN6kGjOMNMOERQmoVrr50Ux+c0nJNPGMLESrFSH+j8 RoOGyGc5lxyhBcGDxH6v+0EIvD6kqiizY6CS5wVQbmMrpEgRQx5cK5tJNQ== X-Gm-Gg: ASbGnctc1c+DnuLRAnoTuyO0OeW0VJTqz7i1BgXtkEuHUZ+i2RNqIw6YrlDoZI8t1Ts ZQ2GnCPp2RDImRYL89czwSObxJE+tDfHQKxj5PX/3y1JPb2QNgOOONmwhy5MUYHpu+rj/gXvFe+ SSH2nK53E3yI6HV2eEiMfFh+uh4J+OCHKGKFko99jlGFxvFWJevCwMtzB1+KqZ9fAWeFoOTY7Yz jGvPwTpfSpu8WM3xM/hQLFwjHQxXZ7oBLXFXJ8le6r/yB+Mec/jYv2xknVkx2ZsqF07iXJv6HfE B9GpYb1w4ixIhAWB5lSPhpdOLijVtCU6lfblkZPks5PEi8sEeZZ+8ckrHDQVr+W3W/s1nQ== X-Google-Smtp-Source: AGHT+IE/DW16TfP1JcF5JFgKtRVFNKsz5jrBi49uZHPx18F3PcPZ/h+SohChpH6M8P9I/POI95d3XA== X-Received: by 2002:a05:622a:118c:b0:467:6226:bfc1 with SMTP id d75a77b69052e-46a4a8f4d78mr766140441cf.29.1735836343900; Thu, 02 Jan 2025 08:45:43 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.43 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:43 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 14/44] selinux: introduce cred_has_extended_perms() Date: Thu, 2 Jan 2025 11:44:39 -0500 Message-Id: <20250102164509.25606-15-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce cred_has_extended_perms() to check extended permissions against the current SELinux namespace and all ancestor namespaces. Update the caller of avc_has_extended_perms() to use this function instead. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 25 +++++++++++++++++++++++++ security/selinux/hooks.c | 5 ++--- security/selinux/include/avc.h | 4 ++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index bdd97f8bb571..93a7eaa42cdd 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1277,6 +1277,31 @@ int cred_task_has_perm(const struct cred *cred, const struct task_struct *p, return 0; } +int cred_has_extended_perms(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, u8 driver, u8 xperm, + struct common_audit_data *ad) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + int rc; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + + rc = avc_has_extended_perms(state, ssid, tsid, tclass, + requested, driver, xperm, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + u32 avc_policy_seqno(struct selinux_state *state) { return state->avc->avc_cache.latest_notif; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c7aca5610402..7608774ac283 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3768,9 +3768,8 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, return 0; isec = inode_security(inode); - rc = avc_has_extended_perms(cred_selinux_state(cred), - ssid, isec->sid, isec->sclass, - requested, driver, xperm, &ad); + rc = cred_has_extended_perms(cred, isec->sid, isec->sclass, + requested, driver, xperm, &ad); out: return rc; } diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 0a12ebe43632..199d83d354fb 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -148,6 +148,10 @@ int cred_task_has_perm(const struct cred *cred, const struct task_struct *p, u16 tclass, u32 requested, struct common_audit_data *auditdata); +int cred_has_extended_perms(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, u8 driver, u8 xperm, + struct common_audit_data *ad); + u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 From patchwork Thu Jan 2 16:44:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924624 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f180.google.com (mail-qt1-f180.google.com [209.85.160.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A89C915381A for ; Thu, 2 Jan 2025 16:45:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836349; cv=none; b=rXqSSvNlm7DzaG1zLXXgpaoKEQ0k3/hNKOj2kH2oRQnYJLp/92/tHWc2SAUVWWM0Ty/eTJ4BLm1DdHg5z/fV4DbbrxDMT6rjU+H4lVsWGh/YGc6EfRfThrxIfZGNHaYN2Sthjnw3GtV8DLnBsHfeVc7iDYfrlMLFmUBH5h5iibM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836349; c=relaxed/simple; bh=RIebBJ3L69k0MVF9/NuKfiY3De+d/RjwSlQCWHMkv9A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Q91C43MQK+BNC6hyNUfu+6NGS9MHKYq8kG3Rf72Lp3yhkf6EfUrZMfVjWyZd1Jr7UqA1/vaCDdrjrW5c04BZdn9X5gKsm6Ud9HMqrntvaoNlxDfnDnqA6Ww7tBaqTpMd5dYbr4n/vIAPEgi4a+59ClzqIqBg2kFr9eikhd17zs8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Bud/F1F3; arc=none smtp.client-ip=209.85.160.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Bud/F1F3" Received: by mail-qt1-f180.google.com with SMTP id d75a77b69052e-467918c360aso133676481cf.0 for ; Thu, 02 Jan 2025 08:45:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836344; x=1736441144; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=w2NHjynO+/XFHmOt+lWq5CCom9u6lL1TgIztn1inUPM=; b=Bud/F1F3Yw8VnkRTLH18NhRpmEEmmee2Xe3l7p+cnFI+vlXUhP2epoHqJeyptz6TNj 1Fx9MGq/R8a9lXwfHokhWld+ikuewrCLDunK1TRV1biViiiRKsc8B1cdslbZHNuWZ1e0 +6x6F1wKLXOgqZ3IJYES/piLZrglTHVXQccFD824oqmUpYwQu7skZtKg0yBiyd0jlD41 LXMZ8h8pKbycFe/t898Z7CIyQKVaJCfGqorqhyNZdfm4xpHjjWKsRABcLfDSI/jHqgJq AtyZyRyc8CK1qjhWbroSVokc3wgrxmn05wngnFSdg02CG/vMOGYmpIRdGSwkk2gEquzX y6tA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836344; x=1736441144; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=w2NHjynO+/XFHmOt+lWq5CCom9u6lL1TgIztn1inUPM=; b=rdWfWGQqABu3dy8eHb70eL7NAMLNqmvb8DkLUcKPNurOEAjjLNiYgnZlzUfkrd+b6K wu+lrtd+XhmZRS53H5+QFE/0C/gEd+GYREnuiBwuC697D3Qkb4YFf9pcUqPHz+UT04BC FUvS9TckwdnB9G2VmtzSacYl+TSbYSMi7jFxEyXNzswIX4X7qsvIQpXJkLjFmb/BxHWk q/mW2Ng0nx/kW8MyPQ1GjvR8DzrlQ1uFL/eRlToxvGCv8FWlFGIp3lu94el5jlyXmxY/ m7rBQGYNvoZM7mPzK6F71nz7cv3bpfxp+E6nxVZ6xnX56fE2yaO0yydtlzm91wJHU6E7 fiFg== X-Gm-Message-State: AOJu0Yy0clWL6FFEErlMPj1iBkX1tbwNV1Bi2teBJHNGOlPxkzWdZzvS mT1tka99usEOTIGmAjsVcRw13bTzT9jwELa0p6dSQECkxEKFyUfsZbL9xg== X-Gm-Gg: ASbGncs/ZXz1iyWF1OSUWtWsPLw0K3FcI7CGeZC7ErrfZARju24iEfJ6cdMm/F6/8v8 x8tbJ2LICTJV5CN7g0YTuQvqxrcoiuP7boikXyi9pVSOb8LqAqkpobiT7PunvEqTbQgEFF/eswU WetYiDQFRAM5AoYM1ibuoTvXzmdJ5Sw63FJrD4KnWY1cIgaPcF8V/he45O3kQF62UmyUS+n5M1L yC7P7eyVGqdMvjzBvJ+7enuGAaUXe5YuGOALx9rexJB/qzIbqqoTvlXJq90l8tbbiihi62niEQE y92oCpNDPj26Wk1q52pzXh0hy4ebof8WkqwxQr4LDo+/ZHZeA7OU3ejLwsvGpTF29sypiw== X-Google-Smtp-Source: AGHT+IEide/e11nkG8mgLyVa6kd+e9OoRRh18yZUZzjQe7QdS8YSR4Ix6rjrI2xYfuF93TYShha4zQ== X-Received: by 2002:ac8:7e87:0:b0:467:6bd8:accd with SMTP id d75a77b69052e-46a4a8ce467mr652738881cf.15.1735836344461; Thu, 02 Jan 2025 08:45:44 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.44 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:44 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 15/44] selinux: introduce cred_self_has_perm() Date: Thu, 2 Jan 2025 11:44:40 -0500 Message-Id: <20250102164509.25606-16-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce a cred_self_has_perm() function for checking permissions between a cred and itself against the current SELinux namespace and all ancestors. Also provide a cred_self_has_perm_noaudit() variant for use where auditing is not desired. Update existing permission checks in the hook functions to use this new helper. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 47 +++++++++++++++++++ security/selinux/hooks.c | 86 ++++++++++++---------------------- security/selinux/include/avc.h | 6 +++ 3 files changed, 84 insertions(+), 55 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 93a7eaa42cdd..8f6a8992170a 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1302,6 +1302,53 @@ int cred_has_extended_perms(const struct cred *cred, u32 tsid, u16 tclass, return 0; } +int cred_self_has_perm(const struct cred *cred, u16 tclass, u32 requested, + struct common_audit_data *ad) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + int rc; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + rc = avc_has_perm(state, ssid, ssid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + +int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, + u32 requested) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + struct av_decision avd; + int rc; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + + rc = avc_has_perm_noaudit(state, ssid, ssid, tclass, + requested, 0, &avd); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + u32 avc_policy_seqno(struct selinux_state *state) { return state->avc->avc_cache.latest_notif; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7608774ac283..f0fb515ca56e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1654,9 +1654,7 @@ static int cred_has_capability(const struct cred *cred, int cap, unsigned int opts, bool initns) { struct common_audit_data ad; - struct av_decision avd; u16 sclass; - u32 sid = cred_sid(cred); u32 av = CAP_TO_MASK(cap); int rc; @@ -1676,14 +1674,11 @@ static int cred_has_capability(const struct cred *cred, return -EINVAL; } - rc = avc_has_perm_noaudit(cred_selinux_state(cred), - sid, sid, sclass, av, 0, &avd); - if (!(opts & CAP_OPT_NOAUDIT)) { - int rc2 = avc_audit(cred_selinux_state(cred), - sid, sid, sclass, av, &avd, rc, &ad); - if (rc2) - return rc2; - } + if (opts & CAP_OPT_NOAUDIT) + rc = cred_self_has_perm_noaudit(cred, sclass, av); + else + rc = cred_self_has_perm(cred, sclass, av, &ad); + return rc; } @@ -3853,7 +3848,6 @@ static int default_noexec __ro_after_init; static int file_map_prot_check(struct file *file, unsigned long prot, int shared) { const struct cred *cred = current_cred(); - u32 sid = cred_sid(cred); int rc = 0; if (default_noexec && @@ -3864,9 +3858,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared * private file mapping that will also be writable. * This has an additional check. */ - rc = avc_has_perm(cred_selinux_state(cred), - sid, sid, SECCLASS_PROCESS, - PROCESS__EXECMEM, NULL); + rc = cred_self_has_perm(cred, SECCLASS_PROCESS, + PROCESS__EXECMEM, NULL); if (rc) goto error; } @@ -3894,10 +3887,8 @@ static int selinux_mmap_addr(unsigned long addr) int rc = 0; if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { - u32 sid = current_sid(); - rc = avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_MEMPROTECT, - MEMPROTECT__MMAP_ZERO, NULL); + rc = cred_self_has_perm(current_cred(), SECCLASS_MEMPROTECT, + MEMPROTECT__MMAP_ZERO, NULL); } return rc; @@ -3928,7 +3919,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, unsigned long prot) { const struct cred *cred = current_cred(); - u32 sid = cred_sid(cred); if (default_noexec && (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { @@ -3944,14 +3934,12 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, */ if (vma->vm_start >= vma->vm_mm->start_brk && vma->vm_end <= vma->vm_mm->brk) { - rc = avc_has_perm(cred_selinux_state(cred), sid, sid, - SECCLASS_PROCESS, PROCESS__EXECHEAP, - NULL); + rc = cred_self_has_perm(cred, SECCLASS_PROCESS, + PROCESS__EXECHEAP, NULL); } else if (!vma->vm_file && (vma_is_initial_stack(vma) || vma_is_stack_for_current(vma))) { - rc = avc_has_perm(cred_selinux_state(cred), sid, sid, - SECCLASS_PROCESS, PROCESS__EXECSTACK, - NULL); + rc = cred_self_has_perm(cred, SECCLASS_PROCESS, + PROCESS__EXECSTACK, NULL); } else if (vma->vm_file && vma->anon_vma) { /* * We are making executable a file mapping that has @@ -4086,10 +4074,8 @@ static int selinux_file_open(struct file *file) static int selinux_task_alloc(struct task_struct *task, unsigned long clone_flags) { - u32 sid = current_sid(); - - return avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL); + return cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + PROCESS__FORK, NULL); } /* @@ -4212,9 +4198,8 @@ static int selinux_kernel_module_from_file(struct file *file) /* init_module */ if (file == NULL) - return avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_SYSTEM, - SYSTEM__MODULE_LOAD, NULL); + return cred_self_has_perm(current_cred(), SECCLASS_SYSTEM, + SYSTEM__MODULE_LOAD, NULL); /* finit_module */ @@ -4394,10 +4379,8 @@ static void selinux_task_to_inode(struct task_struct *p, static int selinux_userns_create(const struct cred *cred) { - u32 sid = current_sid(); - - return avc_has_perm(current_selinux_state, sid, sid, SECCLASS_USER_NAMESPACE, - USER_NAMESPACE__CREATE, NULL); + return cred_self_has_perm(current_cred(), SECCLASS_USER_NAMESPACE, + USER_NAMESPACE__CREATE, NULL); } /* Returns error only if unable to parse addresses */ @@ -6608,29 +6591,24 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) */ switch (attr) { case LSM_ATTR_EXEC: - error = avc_has_perm(current_selinux_state, - mysid, mysid, SECCLASS_PROCESS, - PROCESS__SETEXEC, NULL); + error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + PROCESS__SETEXEC, NULL); break; case LSM_ATTR_FSCREATE: - error = avc_has_perm(current_selinux_state, - mysid, mysid, SECCLASS_PROCESS, - PROCESS__SETFSCREATE, NULL); + error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + PROCESS__SETFSCREATE, NULL); break; case LSM_ATTR_KEYCREATE: - error = avc_has_perm(current_selinux_state, - mysid, mysid, SECCLASS_PROCESS, - PROCESS__SETKEYCREATE, NULL); + error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + PROCESS__SETKEYCREATE, NULL); break; case LSM_ATTR_SOCKCREATE: - error = avc_has_perm(current_selinux_state, - mysid, mysid, SECCLASS_PROCESS, - PROCESS__SETSOCKCREATE, NULL); + error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + PROCESS__SETSOCKCREATE, NULL); break; case LSM_ATTR_CURRENT: - error = avc_has_perm(current_selinux_state, - mysid, mysid, SECCLASS_PROCESS, - PROCESS__SETCURRENT, NULL); + error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + PROCESS__SETCURRENT, NULL); break; default: error = -EOPNOTSUPP; @@ -7277,10 +7255,8 @@ static int selinux_uring_override_creds(const struct cred *new) */ static int selinux_uring_sqpoll(void) { - u32 sid = current_sid(); - - return avc_has_perm(current_selinux_state, sid, sid, - SECCLASS_IO_URING, IO_URING__SQPOLL, NULL); + return cred_self_has_perm(current_cred(), SECCLASS_IO_URING, + IO_URING__SQPOLL, NULL); } /** diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 199d83d354fb..dd2db5d7f433 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -152,6 +152,12 @@ int cred_has_extended_perms(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, u8 driver, u8 xperm, struct common_audit_data *ad); +int cred_self_has_perm(const struct cred *cred, u16 tclass, u32 requested, + struct common_audit_data *ad); + +int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, + u32 requested); + u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 From patchwork Thu Jan 2 16:44:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924630 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f180.google.com (mail-qt1-f180.google.com [209.85.160.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFD0813C9D9 for ; Thu, 2 Jan 2025 16:45:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836351; cv=none; b=t4SWXY2lDVCo2qOJ7YTucItwurWQ6jIe44pVN4Y3MhibF0JfvFNw4T3IhwZ/bRAf1ZjjvC2aBAVH8nslb6d+jhbRmwGtTXxl5jcFflTyWgZzg9C4CesH073q6tJLsnAScZQx9u5Q9gjPJFfZ1ukSUMEjAPc6RWbumSWL5aT7VAA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836351; c=relaxed/simple; bh=+fWs2pi2NkSWNjnzp2aNtEJ/bmbbaWnuZKuPfmD2GrQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UbEe2NtU0dsiTwq23xKP9T7gXWL6suXIg2CWDDFlKlWeIEDH+TW8XPYJSqFMLi8UdZzHj77xXGDAiFhXtDdcOoeop2xOQNEa6ZBzea+ZX86BMIpcWdlZOkpbAgg6JtW59jfm44xly/IfhFLJxlvN3g9iio4+ZIqP318HKSKeQbU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=b/Gp6Off; arc=none smtp.client-ip=209.85.160.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="b/Gp6Off" Received: by mail-qt1-f180.google.com with SMTP id d75a77b69052e-467a3c85e11so72362911cf.2 for ; Thu, 02 Jan 2025 08:45:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836346; x=1736441146; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qvo/0keHFQtiXK0D5wuY3vZQdM+RsA+s2twIrUDc5iM=; b=b/Gp6OffQ87UuIvbIySB4KXq/1a+KGMEWOeX/U6bKpa3cBG5oiceqvnwtaOSt7mE4D Rp25lcJOCq9K44cr7MoIwc+SX+2FBHZ2gO2AVehSdWi2jVvg4GPtiWx96aG+mmfmDqKC 8XsgTpts0NK5172XbomsappAqZ3OcM++fclZhvSVlr14P85LvYl5LktYO7M4U/tdqkml hE0VdHKqBHeRdmeYV9YBFkcFxRMfpPGZ5/kfMUiGv23gC5fQODOmGuIo5FSRkgZ6Ab0q l9MLqZ2wVMrembo6tYyVoIHWkeDhz52M9lbaiQQ+btIwjUS80RH+GWsC/Qwi+Yrrw902 a6kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836346; x=1736441146; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qvo/0keHFQtiXK0D5wuY3vZQdM+RsA+s2twIrUDc5iM=; b=wb/efeArAIlZkHx2nKBfoZNHvsLt2SCXzNBpVKku8VITPiq4DWFJiiYjp2VUezu172 fEOMi2pKeuhp8beWI/y6Q2JpcLlN+Dd/SV7tGw9TN9aGqJMAk3hcycXrg8MOluoUIv3y JkBE2WonxNf7lgLpcfmolCzn2A22ct3YKwx9EG+Nn1KcYHyDOgsbhaEihL7YWq/lMe+1 hpLFyWIgNZK1AUtoKFxx1p62myuXw4hzpVjfpzmi6dJJoB4jK328kYGpoEY9nvKDrf1H L+u8AtvJKd0sG1f9Y2IaJSO+K5yJzqx0L1PifTTjCulcKJzt3lqhtT0+YvATd7GJpla4 lH9w== X-Gm-Message-State: AOJu0YzbcUPsmguK4VT+dehLqR6vrTf20J5Tlk7c3S2wyMswUUzV/Q20 PfEAMJx0wq7oPddHa/leXwX11hqyfFJjLdBbQfIeJe92H+lyIGC27dbO7A== X-Gm-Gg: ASbGnctu0zxVlJZvsdl75WqBKRxPY9P3fXPZxpDeRZcZnOro1EmOYsGmspO2Qfkidg2 ex0ZDE/2j7eJaZkHrG1E9LjLNXZ9MLj5FphEhP7RBK9Ys/sBN6ouc/W6L8uj4r6+pb2xfFauyLy 23fx60xCetyy7vD8uLNt2PY13KoROPTZH/hXJtntiwNHmBb8RQ3XbDOKeaLdraj807f787/5GTW +4pMjwGnnoCXIwRlrzj+T92WdoK3d32UKjFeHswcvNhjbpB51i88mfp7YJJzzhv9EgUtY/dodi+ oJiGb2z6HukmXKHEycd8wOMLAof5API5L0KRQfm+Gs6olRJ5hxmCb2wwR+B5uGWIsTobIg== X-Google-Smtp-Source: AGHT+IHbzTGtAEEs8+GXB+tDQwhEH9JEJZpCe1jdi79dCcgEVOQh3Wzk/8SFhIWdo/UZt9rkpKOpkw== X-Received: by 2002:a05:622a:14a:b0:467:81ef:1953 with SMTP id d75a77b69052e-46a4a8b6f0cmr730634631cf.7.1735836345331; Thu, 02 Jan 2025 08:45:45 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.44 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:44 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 16/44] selinux: introduce cred_has_perm() Date: Thu, 2 Jan 2025 11:44:41 -0500 Message-Id: <20250102164509.25606-17-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce cred_has_perm() to check permissions between a cred and a specified target SID against the current SELinux namespace and all ancestors. Also provide a cred_has_perm_noaudit() variant for use by checks where auditing is not desired or requires further specialization (e.g. selinux_inode_permission). These helpers should NOT be used when checking permissions between two creds (or tasks) since they will not use the target SID from the same namespace as the source cred. They are only suitable when checking permissions to non-cred/task objects like superblocks, inodes, etc. Convert permission checks in the hook functions to use these new helpers when appropriate. Also convert some further checks to using the cred_self_has_perm() helper previously introduced. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 53 +++++ security/selinux/hooks.c | 384 +++++++++++++-------------------- security/selinux/include/avc.h | 6 + 3 files changed, 211 insertions(+), 232 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 8f6a8992170a..19641d5daba8 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1349,6 +1349,59 @@ int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, return 0; } +int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *ad) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + int rc; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + +int cred_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, struct av_decision *avd) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + int rc; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + + /* + * TODO Do we need to use a tmp avd for each + * avc_has_perm_noaudit() call and intersect/union + * the sets as appropriate as we go? Or can we + * simply use the last result since we generally + * only care when there is a denial? + */ + rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, + requested, 0, avd); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + u32 avc_policy_seqno(struct selinux_state *state) { return state->avc->avc_cache.latest_notif; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f0fb515ca56e..b38d0f78f33d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -452,17 +452,14 @@ static int may_context_mount_sb_relabel(u32 sid, struct superblock_security_struct *sbsec, const struct cred *cred) { - const struct task_security_struct *tsec = selinux_cred(cred); int rc; - rc = avc_has_perm(cred_selinux_state(cred), - tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, - FILESYSTEM__RELABELFROM, NULL); + rc = cred_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, + FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = avc_has_perm(cred_selinux_state(cred), - tsec->sid, sid, SECCLASS_FILESYSTEM, + rc = cred_has_perm(cred, sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, NULL); return rc; } @@ -471,18 +468,16 @@ static int may_context_mount_inode_relabel(u32 sid, struct superblock_security_struct *sbsec, const struct cred *cred) { - const struct task_security_struct *tsec = selinux_cred(cred); int rc; - rc = avc_has_perm(cred_selinux_state(cred), - tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, + + rc = cred_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = avc_has_perm(cred_selinux_state(cred), - sid, sbsec->sid, SECCLASS_FILESYSTEM, - FILESYSTEM__ASSOCIATE, NULL); - return rc; + return avc_has_perm(cred_selinux_state(cred), + sid, sbsec->sid, SECCLASS_FILESYSTEM, + FILESYSTEM__ASSOCIATE, NULL); } static int selinux_is_genfs_special_handling(struct super_block *sb) @@ -1691,16 +1686,13 @@ static int inode_has_perm(const struct cred *cred, struct common_audit_data *adp) { struct inode_security_struct *isec; - u32 sid; if (unlikely(IS_PRIVATE(inode))) return 0; - sid = cred_sid(cred); isec = selinux_inode(inode); - return avc_has_perm(cred_selinux_state(cred), - sid, isec->sid, isec->sclass, perms, adp); + return cred_has_perm(cred, isec->sid, isec->sclass, perms, adp); } /* Same as inode_has_perm, but pass explicit audit data containing @@ -1748,7 +1740,7 @@ static inline int file_path_has_perm(const struct cred *cred, } #ifdef CONFIG_BPF_SYSCALL -static int bpf_fd_pass(const struct file *file, u32 sid); +static int bpf_fd_pass(const struct file *file, const struct cred *cred); #endif /* Check whether a task can use an open file descriptor to @@ -1773,17 +1765,14 @@ static int file_has_perm(const struct cred *cred, ad.u.file = file; if (sid != fsec->sid) { - rc = avc_has_perm(cred_selinux_state(cred), - sid, fsec->sid, - SECCLASS_FD, - FD__USE, - &ad); + rc = cred_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, + &ad); if (rc) goto out; } #ifdef CONFIG_BPF_SYSCALL - rc = bpf_fd_pass(file, cred_sid(cred)); + rc = bpf_fd_pass(file, cred); if (rc) return rc; #endif @@ -1830,23 +1819,21 @@ static int may_create(struct inode *dir, struct dentry *dentry, u16 tclass) { - const struct task_security_struct *tsec = selinux_cred(current_cred()); + const struct cred *cred = current_cred(); + const struct task_security_struct *tsec = selinux_cred(cred); struct inode_security_struct *dsec; struct superblock_security_struct *sbsec; - u32 sid, newsid; + u32 newsid; struct common_audit_data ad; int rc; dsec = inode_security(dir); sbsec = selinux_superblock(dir->i_sb); - sid = tsec->sid; - ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = dentry; - rc = avc_has_perm(current_selinux_state, - sid, dsec->sid, SECCLASS_DIR, + rc = cred_has_perm(cred, dsec->sid, SECCLASS_DIR, DIR__ADD_NAME | DIR__SEARCH, &ad); if (rc) @@ -1857,8 +1844,7 @@ static int may_create(struct inode *dir, if (rc) return rc; - rc = avc_has_perm(current_selinux_state, - sid, newsid, tclass, FILE__CREATE, &ad); + rc = cred_has_perm(cred, newsid, tclass, FILE__CREATE, &ad); if (rc) return rc; @@ -1878,9 +1864,9 @@ static int may_link(struct inode *dir, int kind) { + const struct cred *cred = current_cred(); struct inode_security_struct *dsec, *isec; struct common_audit_data ad; - u32 sid = current_sid(); u32 av; int rc; @@ -1892,8 +1878,7 @@ static int may_link(struct inode *dir, av = DIR__SEARCH; av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); - rc = avc_has_perm(current_selinux_state, - sid, dsec->sid, SECCLASS_DIR, av, &ad); + rc = cred_has_perm(cred, dsec->sid, SECCLASS_DIR, av, &ad); if (rc) return rc; @@ -1913,9 +1898,7 @@ static int may_link(struct inode *dir, return 0; } - rc = avc_has_perm(current_selinux_state, - sid, isec->sid, isec->sclass, av, &ad); - return rc; + return cred_has_perm(cred, isec->sid, isec->sclass, av, &ad); } static inline int may_rename(struct inode *old_dir, @@ -1923,9 +1906,9 @@ static inline int may_rename(struct inode *old_dir, struct inode *new_dir, struct dentry *new_dentry) { + const struct cred *cred = current_cred(); struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; struct common_audit_data ad; - u32 sid = current_sid(); u32 av; int old_is_dir, new_is_dir; int rc; @@ -1938,20 +1921,17 @@ static inline int may_rename(struct inode *old_dir, ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = old_dentry; - rc = avc_has_perm(current_selinux_state, - sid, old_dsec->sid, SECCLASS_DIR, + rc = cred_has_perm(cred, old_dsec->sid, SECCLASS_DIR, DIR__REMOVE_NAME | DIR__SEARCH, &ad); if (rc) return rc; - rc = avc_has_perm(current_selinux_state, - sid, old_isec->sid, - old_isec->sclass, FILE__RENAME, &ad); + rc = cred_has_perm(cred, old_isec->sid, old_isec->sclass, + FILE__RENAME, &ad); if (rc) return rc; if (old_is_dir && new_dir != old_dir) { - rc = avc_has_perm(current_selinux_state, - sid, old_isec->sid, - old_isec->sclass, DIR__REPARENT, &ad); + rc = cred_has_perm(cred, old_isec->sid, old_isec->sclass, + DIR__REPARENT, &ad); if (rc) return rc; } @@ -1960,17 +1940,15 @@ static inline int may_rename(struct inode *old_dir, av = DIR__ADD_NAME | DIR__SEARCH; if (d_is_positive(new_dentry)) av |= DIR__REMOVE_NAME; - rc = avc_has_perm(current_selinux_state, - sid, new_dsec->sid, SECCLASS_DIR, av, &ad); + rc = cred_has_perm(cred, new_dsec->sid, SECCLASS_DIR, av, &ad); if (rc) return rc; if (d_is_positive(new_dentry)) { new_isec = backing_inode_security(new_dentry); new_is_dir = d_is_dir(new_dentry); - rc = avc_has_perm(current_selinux_state, - sid, new_isec->sid, - new_isec->sclass, - (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad); + rc = cred_has_perm(cred, new_isec->sid, new_isec->sclass, + (new_is_dir ? DIR__RMDIR : FILE__UNLINK), + &ad); if (rc) return rc; } @@ -1985,11 +1963,10 @@ static int superblock_has_perm(const struct cred *cred, struct common_audit_data *ad) { struct superblock_security_struct *sbsec; - u32 sid = cred_sid(cred); sbsec = selinux_superblock(sb); - return avc_has_perm(cred_selinux_state(cred), - sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); + return cred_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, perms, + ad); } /* Convert a Linux mode and permission mask to an access vector. */ @@ -2112,17 +2089,14 @@ static int selinux_binder_transfer_file(const struct cred *from, ad.u.path = file->f_path; if (sid != fsec->sid) { - rc = avc_has_perm(cred_selinux_state(to), - sid, fsec->sid, - SECCLASS_FD, - FD__USE, - &ad); + rc = cred_has_perm(to, fsec->sid, SECCLASS_FD, FD__USE, + &ad); if (rc) return rc; } #ifdef CONFIG_BPF_SYSCALL - rc = bpf_fd_pass(file, sid); + rc = bpf_fd_pass(file, to); if (rc) return rc; #endif @@ -2131,9 +2105,8 @@ static int selinux_binder_transfer_file(const struct cred *from, return 0; isec = backing_inode_security(dentry); - return avc_has_perm(cred_selinux_state(to), - sid, isec->sid, isec->sclass, file_to_av(file), - &ad); + return cred_has_perm(to, isec->sid, isec->sclass, file_to_av(file), + &ad); } static int selinux_ptrace_access_check(struct task_struct *child, @@ -2231,25 +2204,25 @@ static int selinux_quota_on(struct dentry *dentry) static int selinux_syslog(int type) { + const struct cred *cred = current_cred(); + switch (type) { case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ - return avc_has_perm(current_selinux_state, - current_sid(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL); + return cred_has_perm(cred, SECINITSID_KERNEL, + SECCLASS_SYSTEM, + SYSTEM__SYSLOG_READ, NULL); case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ /* Set level of messages printed to console */ case SYSLOG_ACTION_CONSOLE_LEVEL: - return avc_has_perm(current_selinux_state, - current_sid(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, - NULL); + return cred_has_perm(cred, SECINITSID_KERNEL, + SECCLASS_SYSTEM, + SYSTEM__SYSLOG_CONSOLE, NULL); } /* All other syslog types */ - return avc_has_perm(current_selinux_state, - current_sid(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL); + return cred_has_perm(cred, SECINITSID_KERNEL, SECCLASS_SYSTEM, + SYSTEM__SYSLOG_MOD, NULL); } /* @@ -3058,12 +3031,8 @@ static int selinux_inode_init_security_anon(struct inode *inode, ad.type = LSM_AUDIT_DATA_ANONINODE; ad.u.anonclass = name ? (const char *)name->name : "?"; - return avc_has_perm(current_selinux_state, - sid, - isec->sid, - isec->sclass, - FILE__CREATE, - &ad); + return cred_has_perm(current_cred(), isec->sid, isec->sclass, + FILE__CREATE, &ad); } static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) @@ -3119,7 +3088,6 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode, { struct common_audit_data ad; struct inode_security_struct *isec; - u32 sid = current_sid(); ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = dentry; @@ -3127,8 +3095,8 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode, if (IS_ERR(isec)) return PTR_ERR(isec); - return avc_has_perm(current_selinux_state, - sid, isec->sid, isec->sclass, FILE__READ, &ad); + return cred_has_perm(current_cred(), isec->sid, isec->sclass, + FILE__READ, &ad); } static noinline int audit_inode_permission(struct inode *inode, @@ -3152,7 +3120,6 @@ static int selinux_inode_permission(struct inode *inode, int mask) bool from_access; bool no_block = mask & MAY_NOT_BLOCK; struct inode_security_struct *isec; - u32 sid = current_sid(); struct av_decision avd; int rc, rc2; u32 audited, denied; @@ -3173,9 +3140,8 @@ static int selinux_inode_permission(struct inode *inode, int mask) if (IS_ERR(isec)) return PTR_ERR(isec); - rc = avc_has_perm_noaudit(current_selinux_state, - sid, isec->sid, isec->sclass, perms, 0, - &avd); + rc = cred_has_perm_noaudit(current_cred(), isec->sid, isec->sclass, + perms, &avd); audited = avc_audit_required(perms, &avd, rc, from_access ? FILE__AUDIT_ACCESS : 0, &denied); @@ -3255,11 +3221,12 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { + const struct cred *cred = current_cred(); struct inode *inode = d_backing_inode(dentry); struct inode_security_struct *isec; struct superblock_security_struct *sbsec; struct common_audit_data ad; - u32 newsid, sid = current_sid(); + u32 newsid; int rc = 0; /* if not a selinux xattr, only check the ordinary setattr perm */ @@ -3280,9 +3247,8 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, ad.u.dentry = dentry; isec = backing_inode_security(dentry); - rc = avc_has_perm(current_selinux_state, - sid, isec->sid, isec->sclass, - FILE__RELABELFROM, &ad); + rc = cred_has_perm(cred, isec->sid, isec->sclass, FILE__RELABELFROM, + &ad); if (rc) return rc; @@ -3321,14 +3287,13 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, if (rc) return rc; - rc = avc_has_perm(current_selinux_state, - sid, newsid, isec->sclass, - FILE__RELABELTO, &ad); + rc = cred_has_perm(cred, newsid, isec->sclass, FILE__RELABELTO, + &ad); if (rc) return rc; rc = security_validate_transition(current_selinux_state, isec->sid, newsid, - sid, isec->sclass); + current_sid(), isec->sclass); if (rc) return rc; @@ -3750,11 +3715,8 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, ad.u.op->path = file->f_path; if (ssid != fsec->sid) { - rc = avc_has_perm(cred_selinux_state(cred), - ssid, fsec->sid, - SECCLASS_FD, - FD__USE, - &ad); + rc = cred_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, + &ad); if (rc) goto out; } @@ -4137,14 +4099,10 @@ static void selinux_cred_getlsmprop(const struct cred *c, struct lsm_prop *prop) static int selinux_kernel_act_as(struct cred *new, u32 secid) { struct task_security_struct *tsec = selinux_cred(new); - u32 sid = current_sid(); int ret; - ret = avc_has_perm(tsec->state, - sid, secid, - SECCLASS_KERNEL_SERVICE, - KERNEL_SERVICE__USE_AS_OVERRIDE, - NULL); + ret = cred_has_perm(current_cred(), secid, SECCLASS_KERNEL_SERVICE, + KERNEL_SERVICE__USE_AS_OVERRIDE, NULL); if (ret == 0) { tsec->sid = secid; tsec->create_sid = 0; @@ -4162,14 +4120,12 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) { struct inode_security_struct *isec = inode_security(inode); struct task_security_struct *tsec = selinux_cred(new); - u32 sid = current_sid(); int ret; - ret = avc_has_perm(tsec->state, - sid, isec->sid, - SECCLASS_KERNEL_SERVICE, - KERNEL_SERVICE__CREATE_FILES_AS, - NULL); + ret = cred_has_perm(current_cred(), isec->sid, + SECCLASS_KERNEL_SERVICE, + KERNEL_SERVICE__CREATE_FILES_AS, + NULL); if (ret == 0) tsec->create_sid = isec->sid; @@ -4183,9 +4139,8 @@ static int selinux_kernel_module_request(char *kmod_name) ad.type = LSM_AUDIT_DATA_KMOD; ad.u.kmod_name = kmod_name; - return avc_has_perm(current_selinux_state, - current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM, - SYSTEM__MODULE_REQUEST, &ad); + return cred_has_perm(current_cred(), SECINITSID_KERNEL, + SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, &ad); } static int selinux_kernel_module_from_file(struct file *file) @@ -4193,12 +4148,13 @@ static int selinux_kernel_module_from_file(struct file *file) struct common_audit_data ad; struct inode_security_struct *isec; struct file_security_struct *fsec; + const struct cred *cred = current_cred(); u32 sid = current_sid(); int rc; /* init_module */ if (file == NULL) - return cred_self_has_perm(current_cred(), SECCLASS_SYSTEM, + return cred_self_has_perm(cred, SECCLASS_SYSTEM, SYSTEM__MODULE_LOAD, NULL); /* finit_module */ @@ -4208,16 +4164,15 @@ static int selinux_kernel_module_from_file(struct file *file) fsec = selinux_file(file); if (sid != fsec->sid) { - rc = avc_has_perm(current_selinux_state, - sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); + rc = cred_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, + &ad); if (rc) return rc; } isec = inode_security(file_inode(file)); - return avc_has_perm(current_selinux_state, - sid, isec->sid, SECCLASS_SYSTEM, - SYSTEM__MODULE_LOAD, &ad); + return cred_has_perm(cred, isec->sid, SECCLASS_SYSTEM, + SYSTEM__MODULE_LOAD, &ad); } static int selinux_kernel_read_file(struct file *file, @@ -4727,9 +4682,8 @@ static int sock_has_perm(struct sock *sk, u32 perms) ad_net_init_from_sk(&ad, &net, sk); - return avc_has_perm(current_selinux_state, - current_sid(), sksec->sid, sksec->sclass, perms, - &ad); + return cred_has_perm(current_cred(), sksec->sid, sksec->sclass, + perms, &ad); } static int selinux_socket_create(int family, int type, @@ -4748,8 +4702,8 @@ static int selinux_socket_create(int family, int type, if (rc) return rc; - return avc_has_perm(current_selinux_state, - tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); + return cred_has_perm(current_cred(), newsid, secclass, + SOCKET__CREATE, NULL); } static int selinux_socket_post_create(struct socket *sock, int family, @@ -5698,8 +5652,7 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) static int selinux_secmark_relabel_packet(u32 sid) { - return avc_has_perm(current_selinux_state, - current_sid(), sid, SECCLASS_PACKET, + return cred_has_perm(current_cred(), sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); } @@ -5729,8 +5682,6 @@ static int selinux_tun_dev_alloc_security(void *security) static int selinux_tun_dev_create(void) { - u32 sid = current_sid(); - /* we aren't taking into account the "sockcreate" SID since the socket * that is being created here is not a socket in the traditional sense, * instead it is a private sock, accessible only to the kernel, and @@ -5738,18 +5689,17 @@ static int selinux_tun_dev_create(void) * connections unlike traditional sockets - check the TUN driver to * get a better understanding of why this socket is special */ - return avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, - NULL); + return cred_self_has_perm(current_cred(), SECCLASS_TUN_SOCKET, + TUN_SOCKET__CREATE, NULL); } static int selinux_tun_dev_attach_queue(void *security) { struct tun_security_struct *tunsec = selinux_tun_dev(security); - return avc_has_perm(current_selinux_state, - current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET, - TUN_SOCKET__ATTACH_QUEUE, NULL); + return cred_has_perm(current_cred(), tunsec->sid, + SECCLASS_TUN_SOCKET, TUN_SOCKET__ATTACH_QUEUE, + NULL); } static int selinux_tun_dev_attach(struct sock *sk, void *security) @@ -5772,21 +5722,19 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security) static int selinux_tun_dev_open(void *security) { + const struct cred *cred = current_cred(); struct tun_security_struct *tunsec = selinux_tun_dev(security); - u32 sid = current_sid(); int err; - err = avc_has_perm(current_selinux_state, - sid, tunsec->sid, SECCLASS_TUN_SOCKET, - TUN_SOCKET__RELABELFROM, NULL); + err = cred_has_perm(cred, tunsec->sid, SECCLASS_TUN_SOCKET, + TUN_SOCKET__RELABELFROM, NULL); if (err) return err; - err = avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_TUN_SOCKET, - TUN_SOCKET__RELABELTO, NULL); + err = cred_self_has_perm(cred, SECCLASS_TUN_SOCKET, + TUN_SOCKET__RELABELTO, NULL); if (err) return err; - tunsec->sid = sid; + tunsec->sid = current_sid(); return 0; } @@ -6163,15 +6111,14 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, { struct ipc_security_struct *isec; struct common_audit_data ad; - u32 sid = current_sid(); isec = selinux_ipc(ipc_perms); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = ipc_perms->key; - return avc_has_perm(current_selinux_state, - sid, isec->sid, isec->sclass, perms, &ad); + return cred_has_perm(current_cred(), isec->sid, isec->sclass, perms, + &ad); } static int selinux_msg_msg_alloc_security(struct msg_msg *msg) @@ -6189,7 +6136,6 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) { struct ipc_security_struct *isec; struct common_audit_data ad; - u32 sid = current_sid(); isec = selinux_ipc(msq); ipc_init_security(isec, SECCLASS_MSGQ); @@ -6197,24 +6143,21 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - return avc_has_perm(current_selinux_state, - sid, isec->sid, SECCLASS_MSGQ, - MSGQ__CREATE, &ad); + return cred_has_perm(current_cred(), isec->sid, SECCLASS_MSGQ, + MSGQ__CREATE, &ad); } static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) { struct ipc_security_struct *isec; struct common_audit_data ad; - u32 sid = current_sid(); isec = selinux_ipc(msq); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - return avc_has_perm(current_selinux_state, - sid, isec->sid, SECCLASS_MSGQ, + return cred_has_perm(current_cred(), isec->sid, SECCLASS_MSGQ, MSGQ__ASSOCIATE, &ad); } @@ -6226,8 +6169,7 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) case IPC_INFO: case MSG_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(current_selinux_state, - current_sid(), SECINITSID_KERNEL, + return cred_has_perm(current_cred(), SECINITSID_KERNEL, SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); case IPC_STAT: case MSG_STAT: @@ -6249,6 +6191,7 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) { + const struct cred *cred = current_cred(); struct ipc_security_struct *isec; struct msg_security_struct *msec; struct common_audit_data ad; @@ -6276,14 +6219,11 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m ad.u.ipc_id = msq->key; /* Can this process write to the queue? */ - rc = avc_has_perm(current_selinux_state, - sid, isec->sid, SECCLASS_MSGQ, - MSGQ__WRITE, &ad); + rc = cred_has_perm(cred, isec->sid, SECCLASS_MSGQ, MSGQ__WRITE, &ad); if (!rc) /* Can this process send the message */ - rc = avc_has_perm(current_selinux_state, - sid, msec->sid, SECCLASS_MSG, - MSG__SEND, &ad); + rc = cred_has_perm(cred, msec->sid, SECCLASS_MSG, MSG__SEND, + &ad); if (!rc) /* Can the message be put in the queue? */ rc = avc_has_perm(current_selinux_state, @@ -6324,7 +6264,6 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) { struct ipc_security_struct *isec; struct common_audit_data ad; - u32 sid = current_sid(); isec = selinux_ipc(shp); ipc_init_security(isec, SECCLASS_SHM); @@ -6332,25 +6271,22 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - return avc_has_perm(current_selinux_state, - sid, isec->sid, SECCLASS_SHM, - SHM__CREATE, &ad); + return cred_has_perm(current_cred(), isec->sid, SECCLASS_SHM, + SHM__CREATE, &ad); } static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) { struct ipc_security_struct *isec; struct common_audit_data ad; - u32 sid = current_sid(); isec = selinux_ipc(shp); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - return avc_has_perm(current_selinux_state, - sid, isec->sid, SECCLASS_SHM, - SHM__ASSOCIATE, &ad); + return cred_has_perm(current_cred(), isec->sid, SECCLASS_SHM, + SHM__ASSOCIATE, &ad); } /* Note, at this point, shp is locked down */ @@ -6362,9 +6298,9 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd) case IPC_INFO: case SHM_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(current_selinux_state, - current_sid(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); + return cred_has_perm(current_cred(), SECINITSID_KERNEL, + SECCLASS_SYSTEM, SYSTEM__IPC_INFO, + NULL); case IPC_STAT: case SHM_STAT: case SHM_STAT_ANY: @@ -6405,7 +6341,6 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) { struct ipc_security_struct *isec; struct common_audit_data ad; - u32 sid = current_sid(); isec = selinux_ipc(sma); ipc_init_security(isec, SECCLASS_SEM); @@ -6413,25 +6348,22 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - return avc_has_perm(current_selinux_state, - sid, isec->sid, SECCLASS_SEM, - SEM__CREATE, &ad); + return cred_has_perm(current_cred(), isec->sid, SECCLASS_SEM, + SEM__CREATE, &ad); } static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) { struct ipc_security_struct *isec; struct common_audit_data ad; - u32 sid = current_sid(); isec = selinux_ipc(sma); ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - return avc_has_perm(current_selinux_state, - sid, isec->sid, SECCLASS_SEM, - SEM__ASSOCIATE, &ad); + return cred_has_perm(current_cred(), isec->sid, SECCLASS_SEM, + SEM__ASSOCIATE, &ad); } /* Note, at this point, sma is locked down */ @@ -6444,9 +6376,9 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd) case IPC_INFO: case SEM_INFO: /* No specific object, just general system-wide information. */ - return avc_has_perm(current_selinux_state, - current_sid(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); + return cred_has_perm(current_cred(), SECINITSID_KERNEL, + SECCLASS_SYSTEM, SYSTEM__IPC_INFO, + NULL); case GETPID: case GETNCNT: case GETZCNT: @@ -6532,9 +6464,9 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, rcu_read_lock(); tsec = task_security(p); if (p != current) { - error = avc_has_perm(current_selinux_state, - current_sid(), tsec->sid, - SECCLASS_PROCESS, PROCESS__GETATTR, NULL); + error = cred_has_perm(current_cred(), tsec->sid, + SECCLASS_PROCESS, PROCESS__GETATTR, + NULL); if (error) goto err_unlock; } @@ -6580,9 +6512,10 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, static int selinux_lsm_setattr(u64 attr, void *value, size_t size) { + const struct cred *cred = current_cred(); struct task_security_struct *tsec; struct cred *new; - u32 mysid = current_sid(), sid = 0, ptsid; + u32 sid = 0, ptsid; int error; char *str = value; @@ -6591,23 +6524,23 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) */ switch (attr) { case LSM_ATTR_EXEC: - error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + error = cred_self_has_perm(cred, SECCLASS_PROCESS, PROCESS__SETEXEC, NULL); break; case LSM_ATTR_FSCREATE: - error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + error = cred_self_has_perm(cred, SECCLASS_PROCESS, PROCESS__SETFSCREATE, NULL); break; case LSM_ATTR_KEYCREATE: - error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + error = cred_self_has_perm(cred, SECCLASS_PROCESS, PROCESS__SETKEYCREATE, NULL); break; case LSM_ATTR_SOCKCREATE: - error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + error = cred_self_has_perm(cred, SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, NULL); break; case LSM_ATTR_CURRENT: - error = cred_self_has_perm(current_cred(), SECCLASS_PROCESS, + error = cred_self_has_perm(cred, SECCLASS_PROCESS, PROCESS__SETCURRENT, NULL); break; default: @@ -6674,8 +6607,8 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) tsec->create_sid = sid; } else if (attr == LSM_ATTR_KEYCREATE) { if (sid) { - error = avc_has_perm(current_selinux_state, mysid, sid, - SECCLASS_KEY, KEY__CREATE, NULL); + error = cred_has_perm(cred, sid, SECCLASS_KEY, + KEY__CREATE, NULL); if (error) goto abort_change; } @@ -6879,7 +6812,7 @@ static int selinux_key_permission(key_ref_t key_ref, { struct key *key; struct key_security_struct *ksec; - u32 perm, sid; + u32 perm; switch (need_perm) { case KEY_NEED_VIEW: @@ -6911,12 +6844,10 @@ static int selinux_key_permission(key_ref_t key_ref, } - sid = cred_sid(cred); key = key_ref_to_ptr(key_ref); ksec = selinux_key(key); - return avc_has_perm(cred_selinux_state(cred), - sid, ksec->sid, SECCLASS_KEY, perm, NULL); + return cred_has_perm(cred, ksec->sid, SECCLASS_KEY, perm, NULL); } static int selinux_key_getsecurity(struct key *key, char **_buffer) @@ -6938,10 +6869,9 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) static int selinux_watch_key(struct key *key) { struct key_security_struct *ksec = selinux_key(key); - u32 sid = current_sid(); - return avc_has_perm(current_selinux_state, - sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL); + return cred_has_perm(current_cred(), ksec->sid, SECCLASS_KEY, + KEY__VIEW, NULL); } #endif #endif @@ -7007,19 +6937,17 @@ static int selinux_ib_alloc_security(void *ib_sec) static int selinux_bpf(int cmd, union bpf_attr *attr, unsigned int size) { - u32 sid = current_sid(); + const struct cred *cred = current_cred(); int ret; switch (cmd) { case BPF_MAP_CREATE: - ret = avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, - NULL); + ret = cred_self_has_perm(cred, SECCLASS_BPF, BPF__MAP_CREATE, + NULL); break; case BPF_PROG_LOAD: - ret = avc_has_perm(current_selinux_state, - sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, - NULL); + ret = cred_self_has_perm(cred, SECCLASS_BPF, BPF__PROG_LOAD, + NULL); break; default: ret = 0; @@ -7048,7 +6976,7 @@ static u32 bpf_map_fmode_to_av(fmode_t fmode) * access the bpf object and that's why we have to add this additional check in * selinux_file_receive and selinux_binder_transfer_files. */ -static int bpf_fd_pass(const struct file *file, u32 sid) +static int bpf_fd_pass(const struct file *file, const struct cred *cred) { struct bpf_security_struct *bpfsec; struct bpf_prog *prog; @@ -7058,16 +6986,14 @@ static int bpf_fd_pass(const struct file *file, u32 sid) if (file->f_op == &bpf_map_fops) { map = file->private_data; bpfsec = map->security; - ret = avc_has_perm(current_selinux_state, - sid, bpfsec->sid, SECCLASS_BPF, + ret = cred_has_perm(cred, bpfsec->sid, SECCLASS_BPF, bpf_map_fmode_to_av(file->f_mode), NULL); if (ret) return ret; } else if (file->f_op == &bpf_prog_fops) { prog = file->private_data; bpfsec = prog->aux->security; - ret = avc_has_perm(current_selinux_state, - sid, bpfsec->sid, SECCLASS_BPF, + ret = cred_has_perm(cred, bpfsec->sid, SECCLASS_BPF, BPF__PROG_RUN, NULL); if (ret) return ret; @@ -7077,23 +7003,19 @@ static int bpf_fd_pass(const struct file *file, u32 sid) static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) { - u32 sid = current_sid(); struct bpf_security_struct *bpfsec; bpfsec = map->security; - return avc_has_perm(current_selinux_state, - sid, bpfsec->sid, SECCLASS_BPF, - bpf_map_fmode_to_av(fmode), NULL); + return cred_has_perm(current_cred(), bpfsec->sid, SECCLASS_BPF, + bpf_map_fmode_to_av(fmode), NULL); } static int selinux_bpf_prog(struct bpf_prog *prog) { - u32 sid = current_sid(); struct bpf_security_struct *bpfsec; bpfsec = prog->aux->security; - return avc_has_perm(current_selinux_state, - sid, bpfsec->sid, SECCLASS_BPF, + return cred_has_perm(current_cred(), bpfsec->sid, SECCLASS_BPF, BPF__PROG_RUN, NULL); } @@ -7187,7 +7109,7 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = { #ifdef CONFIG_PERF_EVENTS static int selinux_perf_event_open(struct perf_event_attr *attr, int type) { - u32 requested, sid = current_sid(); + u32 requested; if (type == PERF_SECURITY_OPEN) requested = PERF_EVENT__OPEN; @@ -7200,8 +7122,8 @@ static int selinux_perf_event_open(struct perf_event_attr *attr, int type) else return -EINVAL; - return avc_has_perm(current_selinux_state, sid, sid, SECCLASS_PERF_EVENT, - requested, NULL); + return cred_self_has_perm(current_cred(), SECCLASS_PERF_EVENT, + requested, NULL); } static int selinux_perf_event_alloc(struct perf_event *event) @@ -7217,19 +7139,17 @@ static int selinux_perf_event_alloc(struct perf_event *event) static int selinux_perf_event_read(struct perf_event *event) { struct perf_event_security_struct *perfsec = event->security; - u32 sid = current_sid(); - return avc_has_perm(current_selinux_state, sid, perfsec->sid, - SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL); + return cred_has_perm(current_cred(), perfsec->sid, + SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL); } static int selinux_perf_event_write(struct perf_event *event) { struct perf_event_security_struct *perfsec = event->security; - u32 sid = current_sid(); - return avc_has_perm(current_selinux_state, sid, perfsec->sid, - SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL); + return cred_has_perm(current_cred(), perfsec->sid, + SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL); } #endif @@ -7277,7 +7197,7 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd) ad.type = LSM_AUDIT_DATA_FILE; ad.u.file = file; - return avc_has_perm(current_selinux_state, current_sid(), isec->sid, + return cred_has_perm(current_cred(), isec->sid, SECCLASS_IO_URING, IO_URING__CMD, &ad); } #endif /* CONFIG_IO_URING */ diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index dd2db5d7f433..31fbf844f9d4 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -158,6 +158,12 @@ int cred_self_has_perm(const struct cred *cred, u16 tclass, u32 requested, int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, u32 requested); +int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, + struct common_audit_data *ad); + +int cred_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, struct av_decision *avd); + u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 From patchwork Thu Jan 2 16:44:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924626 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f178.google.com (mail-qk1-f178.google.com [209.85.222.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0AD1B1547E8 for ; Thu, 2 Jan 2025 16:45:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836350; cv=none; b=avT7ekLoLn9xXpbR/cYxsfggeriUhdcDmgt85i+V+W+zYPXPQFy8D2EJGR5uQuIhbBgqPMxfMlKNAFsgfeVunoXpMzbUJevaKrI8/SnldcOoaH3FICZRSstgVvfpTvzMyMNKx9DqwCkI0MBe8qVEv+rGA0i2CYZ/ZFIpIb99KOM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836350; c=relaxed/simple; bh=9+MPeFTotEObXZYYezhBENmtY3zuLnrf4bV/zxX7umo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=OHzpD5WvZTXq62DIbVMsLPZ37BzlkP4738un5A65fYUX9d4BhkA4mjdwCmpmLqj1L89qY+QEd0csMCdlWtZvMdcgDBGEzrbhj3FX9Tw60iOTzkhvC3v4T/y9oXLwGjURlsV6LVVvA2knY2rBdBiBbua0s9+/MoWhlWvUvCgalEA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=cU32ppMo; arc=none smtp.client-ip=209.85.222.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cU32ppMo" Received: by mail-qk1-f178.google.com with SMTP id af79cd13be357-7b6e9db19c8so853149685a.3 for ; Thu, 02 Jan 2025 08:45:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836346; x=1736441146; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BrtXLv0R25qnhdj/3TGD1NzpKanoO+elzjn/Sd6sYlU=; b=cU32ppMos0ownAyaOWC15ZalL/oBDq+ThXfGsf7g8ZSos/stkmYYvJsDItTxdyigmj pzqp+kq9Ygp/KP/nfuYwMWM/LOeocovv2u2Dvk1ZLunbVw1DWrD7awHFLgnMEL6s5MLD J6x3j9Ekb3SLzLW0i63JgGfA/3u5t1J5X6fxpISvobQ1xFr4uYVypqcNdJeb4bJMiJf/ R1PNOhnSJO/+6nY/1oiioZ7mE12wVrrWj6EIEGdGb5ecGdSS6cxNpBZfqol3z3iBK0RY 0TlbEorcmENmXECCr/X/3oZwLjBw6sG6TGNldnrPXpQkmSU75FNOX32fbD+GkcnfOEX4 77rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836346; x=1736441146; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BrtXLv0R25qnhdj/3TGD1NzpKanoO+elzjn/Sd6sYlU=; b=G0RC26Fu0qRNANXT7mjEbyVwXWJeb0eE9RsbD0+ktOWsJbpnc5fnYvmLgc1J9i6pQD j/J5Ii/nYR6D7RHL0O0IE+8UsqPMft+GKC+Ndfr5VgCziZMofo+5WYdYtdU9ENRfaUfi o0gXze3w1E+PVqpn2SAzeucoPErFEDrayxav0jMzhnY3AynfOVdk7EUuABqBflWbjso+ v2mo1M9gDNiBTFQs2t6RiVi1FUGiOsZdSogQ/VfxGfABeccn9n09OOUgE/sTebpED7yu POLCZwQkz0Fla+qWQb7BL4+o/wP59CdsfOhNwQiq/F4RP0BpgSB4WFXuWInHGVt9VnYC o9xQ== X-Gm-Message-State: AOJu0YwoxUw9OJqtbYEmFvVJ/qo2eROM06FQrJXWkW99RtKdDTStLLQr cwMAwsPwN7deDTcZzhKtQ5azbrXv7VqRfgzbVz2rlSMkmg6az4MLp0YdZw== X-Gm-Gg: ASbGnctMZiEUBqYYfIAeydEtBJtaV4/xJRWJgNd28OpfBEA3DYHG/j7XPAJD3TRjvJ+ /1OyMftMOioyLT5vbFOdRMRJmSr1ep0zoYdZpst9YChJeiozIefOzkNMids9+IRt9mRp2MCo3eo qm2ssf/FdB+gvXt5qIp/8XbM0h7jSSeMrEMbZjMVmQvWWC3t5mw1gLLPr+xrcfge9huWrq8u9Fa 2iBPneTiKKLh+xcSSHjwmPjFEiSKHU0uH5ScfjpkpvqPEGAzCbDpT0eGV+hrepg7HTwh3VjVmY2 6o4pYK4b/Ogi3kbNyMupZDn/DH5T33QdlOpSmA07y9rmEAAbouYbjwhKCpipK+FQYQxErQ== X-Google-Smtp-Source: AGHT+IFVSuOd6/yd/4VnoneZHdxUpDJqciw8kuRxeDLQG1QqrpvB7iz+NwxkjMISspcPr2l36tkkWA== X-Received: by 2002:a05:620a:4623:b0:7b6:daf1:7f13 with SMTP id af79cd13be357-7b9ba716936mr7182484785a.9.1735836345989; Thu, 02 Jan 2025 08:45:45 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.45 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:45 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 17/44] selinux: introduce cred_ssid_has_perm() and cred_other_has_perm() Date: Thu, 2 Jan 2025 11:44:42 -0500 Message-Id: <20250102164509.25606-18-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce cred_ssid_has_perm() for checking permissions between a fixed (source SID, target SID) pair against the current SELinux namespace and all ancestors. This helper is appropriate for checks between two object SIDs, but should NOT be used when dealing with task/cred objects. Introduce cred_other_has_perm() for checking permissions between two creds against the current SELinux namespace and all ancestors. Convert permission checks of these two forms in the hook functions to use these new namespace-aware helpers. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 62 ++++++++++++++++++++++++++++++++++ security/selinux/hooks.c | 61 +++++++++++++-------------------- security/selinux/include/avc.h | 7 ++++ 3 files changed, 93 insertions(+), 37 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 19641d5daba8..acf62dad064f 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1402,6 +1402,68 @@ int cred_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, return 0; } +int cred_ssid_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *ad) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + int rc; + + do { + tsec = selinux_cred(cred); + state = tsec->state; + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + +static u32 cred_sid_for_state(const struct cred *cred, + const struct selinux_state *state) +{ + const struct task_security_struct *tsec; + u32 sid; + + tsec = selinux_cred(cred); + while (tsec->state != state && tsec->parent_cred) + tsec = selinux_cred(tsec->parent_cred); + if (tsec->state == state) + sid = tsec->sid; + else + sid = SECINITSID_UNLABELED; + return sid; +} + +int cred_other_has_perm(const struct cred *cred, const struct cred *other, + u16 tclass, u32 requested, + struct common_audit_data *ad) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + u32 tsid; + int rc; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + tsid = cred_sid_for_state(other, state); + + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + } while (cred); + + return 0; +} + u32 avc_policy_seqno(struct selinux_state *state) { return state->avc->avc_cache.latest_notif; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b38d0f78f33d..028e94c6e396 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -475,9 +475,8 @@ static int may_context_mount_inode_relabel(u32 sid, if (rc) return rc; - return avc_has_perm(cred_selinux_state(cred), - sid, sbsec->sid, SECCLASS_FILESYSTEM, - FILESYSTEM__ASSOCIATE, NULL); + return cred_ssid_has_perm(cred, sid, sbsec->sid, SECCLASS_FILESYSTEM, + FILESYSTEM__ASSOCIATE, NULL); } static int selinux_is_genfs_special_handling(struct super_block *sb) @@ -1848,10 +1847,9 @@ static int may_create(struct inode *dir, if (rc) return rc; - return avc_has_perm(current_selinux_state, - newsid, sbsec->sid, - SECCLASS_FILESYSTEM, - FILESYSTEM__ASSOCIATE, &ad); + return cred_ssid_has_perm(cred, newsid, sbsec->sid, + SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, + &ad); } #define MAY_LINK 0 @@ -2040,9 +2038,8 @@ static inline u32 open_file_to_av(struct file *file) static int selinux_binder_set_context_mgr(const struct cred *mgr) { - return avc_has_perm(current_selinux_state, - current_sid(), cred_sid(mgr), SECCLASS_BINDER, - BINDER__SET_CONTEXT_MGR, NULL); + return cred_other_has_perm(current_cred(), mgr, SECCLASS_BINDER, + BINDER__SET_CONTEXT_MGR, NULL); } static int selinux_binder_transaction(const struct cred *from, @@ -2050,28 +2047,25 @@ static int selinux_binder_transaction(const struct cred *from, { u32 mysid = current_sid(); u32 fromsid = cred_sid(from); - u32 tosid = cred_sid(to); int rc; if (mysid != fromsid) { - rc = avc_has_perm(cred_selinux_state(from), - mysid, fromsid, SECCLASS_BINDER, - BINDER__IMPERSONATE, NULL); + rc = cred_other_has_perm(current_cred(), from, + SECCLASS_BINDER, + BINDER__IMPERSONATE, NULL); if (rc) return rc; } - return avc_has_perm(cred_selinux_state(from), fromsid, tosid, - SECCLASS_BINDER, BINDER__CALL, NULL); + return cred_other_has_perm(from, to, SECCLASS_BINDER, BINDER__CALL, + NULL); } static int selinux_binder_transfer_binder(const struct cred *from, const struct cred *to) { - return avc_has_perm(current_selinux_state, - cred_sid(from), cred_sid(to), - SECCLASS_BINDER, BINDER__TRANSFER, - NULL); + return cred_other_has_perm(from, to, SECCLASS_BINDER, + BINDER__TRANSFER, NULL); } static int selinux_binder_transfer_file(const struct cred *from, @@ -2139,9 +2133,8 @@ static int selinux_capset(struct cred *new, const struct cred *old, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) { - return avc_has_perm(cred_selinux_state(old), - cred_sid(old), cred_sid(new), SECCLASS_PROCESS, - PROCESS__SETCAP, NULL); + return cred_other_has_perm(old, new, SECCLASS_PROCESS, + PROCESS__SETCAP, NULL); } /* @@ -3297,12 +3290,9 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, if (rc) return rc; - return avc_has_perm(current_selinux_state, - newsid, - sbsec->sid, - SECCLASS_FILESYSTEM, - FILESYSTEM__ASSOCIATE, - &ad); + return cred_ssid_has_perm(cred, newsid, sbsec->sid, + SECCLASS_FILESYSTEM, + FILESYSTEM__ASSOCIATE, &ad); } static int selinux_inode_set_acl(struct mnt_idmap *idmap, @@ -4265,9 +4255,7 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre av |= PROCESS__SETRLIMIT; if (flags & LSM_PRLIMIT_READ) av |= PROCESS__GETRLIMIT; - return avc_has_perm(cred_selinux_state(cred), - cred_sid(cred), cred_sid(tcred), - SECCLASS_PROCESS, av, NULL); + return cred_other_has_perm(cred, tcred, SECCLASS_PROCESS, av, NULL); } static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, @@ -6226,9 +6214,8 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m &ad); if (!rc) /* Can the message be put in the queue? */ - rc = avc_has_perm(current_selinux_state, - msec->sid, isec->sid, SECCLASS_MSGQ, - MSGQ__ENQUEUE, &ad); + rc = cred_ssid_has_perm(cred, msec->sid, isec->sid, + SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad); return rc; } @@ -7163,8 +7150,8 @@ static int selinux_perf_event_write(struct perf_event *event) */ static int selinux_uring_override_creds(const struct cred *new) { - return avc_has_perm(current_selinux_state, current_sid(), cred_sid(new), - SECCLASS_IO_URING, IO_URING__OVERRIDE_CREDS, NULL); + return cred_other_has_perm(current_cred(), new, SECCLASS_IO_URING, + IO_URING__OVERRIDE_CREDS, NULL); } /** diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 31fbf844f9d4..ec40b856da91 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -164,6 +164,13 @@ int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, int cred_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, struct av_decision *avd); +int cred_ssid_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *ad); + +int cred_other_has_perm(const struct cred *cred, const struct cred *other, + u16 tclass, u32 requested, + struct common_audit_data *ad); + u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 From patchwork Thu Jan 2 16:44:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924627 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f182.google.com (mail-qt1-f182.google.com [209.85.160.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 820F0154BE4 for ; Thu, 2 Jan 2025 16:45:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836350; cv=none; b=f9m+6uG3hfbjAPVc16h117QIqgwcwa//dw7VLQykyMs6nBhQe1YOa9ikpniXvp7XvHtVu+5rQsx7LENpamTKjM9qV7gMe07qba7zWMi7TdYqtzeqronk6KQ5i5EVKOFW8pSHGCQu7rdffsTRy2CaPV2WEHjzvtwKnj6LdLNo3rE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836350; c=relaxed/simple; bh=OvAnuEzack9VuIOgNEP6p07Pkeh5zPa4zXw/9LKuc/k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=W+poBiFiIlB0dUr+B/l8n8wzzYQYh7/wvOJ0zEIeoPWGApcXWzmBPX+SvYB3RobBS6efu0aqW0Gg3rXR2OPxA1JPzVYdpbpgQtNYuetUHjtPZvHcZhL9qpaLU3XKrReFjChMRDC79X78OJt/sJ4qHdpAsBK8dF0U1Z/ntYYUm/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZSj9NPHs; arc=none smtp.client-ip=209.85.160.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZSj9NPHs" Received: by mail-qt1-f182.google.com with SMTP id d75a77b69052e-467bc28277eso95725391cf.1 for ; Thu, 02 Jan 2025 08:45:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836347; x=1736441147; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ljkPvdOs9go0qhM3C/UzLvjdIhlm6hrSdhwd6AjIkGc=; b=ZSj9NPHsL3vDf66KoGaGkgZJfCGeu/uJIeXoDVJsEaxGtEEpcv5Lw2xJ83qx3RfnsL CQFsAsxYYXVntlfmY4IT+f0pBh9iKaCCpvJCCJ+8yh935eXyfJLPT99lie63gLUMfl7B BqYGBeJQpTrsoiS6iHpc5r2bQyqZ5ung0EXrJzLp5tk/trihOSsZtxeQsrOozNYCJaXT m5bSP1Hv0QyQtgJpc51Xuc9nSL01KVoWYUl/a6Y67X4DsvCG99PgfMBvHADx3CiWrLZw hfza1DwfZjeiNf7VpXHMVw1e9Z7+Mf733EYsHKj0m+BjSOUbCRiv9lRrYMRPp9vngats 0J2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836347; x=1736441147; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ljkPvdOs9go0qhM3C/UzLvjdIhlm6hrSdhwd6AjIkGc=; b=MqG5n5Bf160IAYuuUFfAFXYA1rTq+xIENpfI5xBKVRaI1HYMur/z2/1rsaW86eT5q9 7gQYsXw65YCm+PJDxEWtHje+4s53awunxQ2h0Kfhv6xGfMcE5f9h5XxiYtyDyoUgAMbD DpTS/ugwtUnCdiSVLq4DPN3XVb6U0jdJ4/UBNhKKd40GpvvgWIii5YZbVRPH9cMvuX81 VN8kTdTSsO10aL7dxT6opmx2w93VNMe0nt2ZQqTZwN0jab3VfEv4iab2FCxCype1YShn v9PwDmsO4r9+K8PeEhEgvkF09zs22PBNU8yWk+fL3kr/1/LlumnlU9Al/U6+SAIDqhWJ QknQ== X-Gm-Message-State: AOJu0YyjqB+FE3V57npIJ5nt44EFwUVgrNAxuz+iDRkspmtbRwaAsPJP tDHQp7r/n+zn+GyXVE/fdHLUpmfvO9za/L1WZvElCdoF0HB3bD5aTo8iCw== X-Gm-Gg: ASbGncstjqcw8ep59S/Qe+tZUWe+WGTCEzYxVFyR9OOKtSwSNzzDPIg/P00AnAn4Auy RnWrWDt7lSv7mO2p7Y8Z6mGWeTuEfX06JDto8p36yjKWcXjT9yzmrH795QHYe1cuw9qnVL2j6IH kZ9f9bW0h4hBKtPrTGt75dQsF5trLSR7MuPJqnRSbhFD/7PdNx90n1uiulUH7QfZzEuiL22gTeU ePB671I5LiHZ2USYZfzI2V7Faa0RLkjcvBe/brl4x1AzWBMrGFs64Gv8re/3FmbCn1HxRpuA8Kq 1DYFVkbFALHSUqXv+OrmPPv//Jmj/zQnEo5OPSDQFT3KIahHwegKkWBAQYfD7frsfrhhqQ== X-Google-Smtp-Source: AGHT+IERmRg3HJtOj99qZYJiBGYIuTwB2C/WoN0KADzX7cGSiVrx7NSQkwMDndwBx7AuZ9/DY5QWQA== X-Received: by 2002:a05:622a:1aa8:b0:467:5eb6:5153 with SMTP id d75a77b69052e-46a4a8e4669mr890063211cf.19.1735836346905; Thu, 02 Jan 2025 08:45:46 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.46 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:46 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 18/44] selinux: introduce task_obj_perm() Date: Thu, 2 Jan 2025 11:44:43 -0500 Message-Id: <20250102164509.25606-19-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce task_obj_perm() for namespace-aware permission checking between two tasks using the objective SID for both tasks and without assuming that either task is current. Convert the permission checks of this form in the hook functions to use this new helper. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 56 ++++++++++++++++++++++++++++++++++ security/selinux/hooks.c | 5 ++- security/selinux/include/avc.h | 3 ++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index acf62dad064f..cc64dce0f061 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1277,6 +1277,62 @@ int cred_task_has_perm(const struct cred *cred, const struct task_struct *p, return 0; } +static const struct task_security_struct *task_security( + const struct task_struct *p) +{ + const struct task_security_struct *tsec; + + tsec = selinux_cred(__task_cred(p)); + while (tsec->state != current_selinux_state && tsec->parent_cred) + tsec = selinux_cred(tsec->parent_cred); + if (tsec->state != current_selinux_state) + return NULL; + return tsec; +} + +int task_obj_has_perm(const struct task_struct *s, + const struct task_struct *t, + u16 tclass, u32 requested, + struct common_audit_data *ad) +{ + const struct cred *cred; + const struct task_security_struct *tsec; + struct selinux_state *state; + u32 ssid; + u32 tsid; + int rc; + + state = current_selinux_state; + rcu_read_lock(); + tsec = task_security(s); + if (tsec) + ssid = tsec->sid; + else + ssid = SECINITSID_UNLABELED; + rcu_read_unlock(); + + do { + tsid = task_sid_obj_for_state(t, state); + + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + if (!cred) + break; + + rcu_read_lock(); + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + rcu_read_unlock(); + } while (cred); + + return 0; +} + + int cred_has_extended_perms(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, u8 driver, u8 xperm, struct common_audit_data *ad) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 028e94c6e396..a19cfef5325a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2116,9 +2116,8 @@ static int selinux_ptrace_access_check(struct task_struct *child, static int selinux_ptrace_traceme(struct task_struct *parent) { - return avc_has_perm(current_selinux_state, - task_sid_obj(parent), task_sid_obj(current), - SECCLASS_PROCESS, PROCESS__PTRACE, NULL); + return task_obj_has_perm(parent, current, SECCLASS_PROCESS, + PROCESS__PTRACE, NULL); } static int selinux_capget(const struct task_struct *target, kernel_cap_t *effective, diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index ec40b856da91..e47b75819f4a 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -171,6 +171,9 @@ int cred_other_has_perm(const struct cred *cred, const struct cred *other, u16 tclass, u32 requested, struct common_audit_data *ad); +int task_obj_has_perm(const struct task_struct *s, const struct task_struct *t, + u16 tclass, u32 requested, struct common_audit_data *ad); + u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 From patchwork Thu Jan 2 16:44:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924629 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f176.google.com (mail-qt1-f176.google.com [209.85.160.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97EE8149DF0 for ; Thu, 2 Jan 2025 16:45:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836351; cv=none; b=SgGQuGWunTJs4gpO/iLsq0ChWU8a/wqEo4b0co83ieqjewj47SH4nCexzG0mwVaL1/aYSkja260WtBfU1Q7hYoozwsZQUgGedEf0yVjrbvhQ+XnRqAhy02cYLWcekmnFWs+zlGunM1jXV2Fvz1Mh60/sKYnTT5O0tIyiyfuodcY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836351; c=relaxed/simple; bh=Cy9/HthkIqjdSOIrBIHNwm4iXYkN/R1eEXhd7G85CUI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hCL051/htXSE0nrmvXc1gGtYsswUAreMchNbgEvkakAgeCsQSC5W0XrqAilVPyxDRs3QuBpWkD8R3iFPlBLHC7jmD5rCiJF2yLzxjcpEtJPFH9cMc49azKOn0BvWTdpSiZHW34BbPZ3+51qKv5IQPzaiIsID7/A2RNoOi4KKjsU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TzWfZQQe; arc=none smtp.client-ip=209.85.160.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TzWfZQQe" Received: by mail-qt1-f176.google.com with SMTP id d75a77b69052e-467a3f1e667so66793831cf.0 for ; Thu, 02 Jan 2025 08:45:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836348; x=1736441148; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Bzv3ZX9wa+dFK2R6j7JkfEPqTQlLW0Nl6pQBz700Uq4=; b=TzWfZQQerZD4ehr6UjA2/T6V+GQtZK/XWcE4S+bXHc0J9GA5QgUqtNC+NALSKqyoYA 3p4SR72NP4Ko/m6f5IsAOXKYYBox0OYKmvLr+i2jYyJ4Sc8hCCLfHIo69Hwb8Hlukeqm 8VmYqhahOrjuCd/ouE4TsxYSpgy8aTf8lSxFF6qAXtggCMu//KNf0S9sz+/tkZ287Ds+ n21gJpVat1du1fAKjRFiA+sxQjD1TOYzRLzqISRoaGDOdQjuPtELFYnqVBEyvmP/nh3A aj4beIVdyMlZ5rKUr4VhiVqlQpyv4uiwXxzO549xDYSeu8s4r5Hx2ozVlsj2B0ib6gto hJ+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836348; x=1736441148; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Bzv3ZX9wa+dFK2R6j7JkfEPqTQlLW0Nl6pQBz700Uq4=; b=twsxBoSJ8VABombHP8bgpVSav878SZ8g3Z5lcXVG31geEbaPV+V1cEDvX/TXjLUD3n foXG4cHNK4XKDaYyQWNUIsAqWtrXnDxau9G3QiyvuBmD2epzLDBw35RgsMYzlf8uKOap kbMCljpR9J7w3+nV6XEX4nAj3voDEJ1UTYAVKkpWORXYnu6jzPJ5nPZnr9361c0O0q2+ woa9pWLtWFxdQrqQuc++6zKFc6Il3t2LfrvODBckkWmpLuL0KNAru6699A5hgc8kLTH1 CS6fuRrCwMmBhvTGq6vo11mUcVyKrvudvAMXmsa6sbpALPhI+CJyeJMtZd2wYEgpmUA7 q2fQ== X-Gm-Message-State: AOJu0YwQDDiMMdu2DeO8y2T67EUc7Dn7daw/nJUbNEfBtGC5i3ZIbb84 cO8zbLVdQgTDIVGH2XIruff0p2UxvguhaW5KZGB5ZJWp+sZSgUh7Z2GdVQ== X-Gm-Gg: ASbGncvWPI6dsKJyb6j5O1POCtn6jgVWqVZd1GqekaWbp9XWNoKMRWkGW1jYNm9LTBh BJPgY289RJ9Ga/QZrmQHBFocm5kQD99YbT9eAjZS+IUAVFsr6Yo3JGD7XJwq4m6iu3j/DfoVd0Z 3Ozq4257IFBLUmxXmfYIRk5jmmIiJsIq3iJA3WXVPirBB3ZxROgk74ZJHERJwRmWjTc+57UhJ2i K6ISWUIH8IG8YqBWtbgdq8ZkpTZXjFgc53liUOf82Pu2gRAf7bnwRrEcKvUqjxZjaqld6QFDMgC WkQ5ISkPaSU7v2c4p87Qio/FylboN/ocDd5FRA/pGJ6PPNuFQ33HbE2qyRb0ppctVNlxKQ== X-Google-Smtp-Source: AGHT+IFqFuy9VxUPpU4T0+7zVsCPyrLBr0Hvf2dOZNFrpUcmHj6f/QcJel6hBjMEMQdN5nZRts/Idw== X-Received: by 2002:a05:622a:1827:b0:467:70ce:75e9 with SMTP id d75a77b69052e-46a4a8e83d4mr806783191cf.23.1735836347991; Thu, 02 Jan 2025 08:45:47 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.47 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:47 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 19/44] selinux: fix selinux_lsm_getattr() check Date: Thu, 2 Jan 2025 11:44:44 -0500 Message-Id: <20250102164509.25606-20-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Fix the selinux_lsm_getattr() permission check to use cred_task_has_perm() instead of cred_has_perm() since we need to use the target task's SID in the same namespace as current. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a19cfef5325a..728a59aa52d6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6448,14 +6448,14 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, u32 len; rcu_read_lock(); - tsec = task_security(p); if (p != current) { - error = cred_has_perm(current_cred(), tsec->sid, - SECCLASS_PROCESS, PROCESS__GETATTR, - NULL); + error = cred_task_has_perm(current_cred(), p, + SECCLASS_PROCESS, + PROCESS__GETATTR, NULL); if (error) goto err_unlock; } + tsec = task_security(p); switch (attr) { case LSM_ATTR_CURRENT: sid = tsec->sid; From patchwork Thu Jan 2 16:44:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924631 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f182.google.com (mail-qt1-f182.google.com [209.85.160.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E06715575D for ; Thu, 2 Jan 2025 16:45:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836352; cv=none; b=rqqF6dDONF/2TmV2rs4Xfv4gmHhdXqbFNURg7VAgS/922Kpi+gvoMe6yzOj5zTBT2wWX0sZUDV5sq37nRK1dnQKPl8noBV3Nk5EFPbQXi/K8fZyBhQKROtAcmPFnJcvEeNFbwNsM+EW4zpe8OY8AUnmSPbQsysN6DYzuwuuS5og= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836352; c=relaxed/simple; bh=p6xQr7fyLW6hJXEQ66hoI55mqfFqC7GtSALqtLBahkQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jUT6ZpV7TJoV+NT9lWmagfjZtV5wSllnyMQtloq7jQ3qsQrthp6a8mIvqEoBoBqldLZebIBQOy4zt0p5mEZnaK8ELXHUoWOWjFGEWy21UP/sR+4cJiKHQsqWHCCcx4la24qOPGR5KmT3e7HyywodUMi59V6NwEyPiECuB8VQWSk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TAikLcyy; arc=none smtp.client-ip=209.85.160.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TAikLcyy" Received: by mail-qt1-f182.google.com with SMTP id d75a77b69052e-467a17055e6so128389751cf.3 for ; Thu, 02 Jan 2025 08:45:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836349; x=1736441149; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KbvQFBPG02Kc4aTtsHuZjuF5x6gzUFwDF1PhT+HJtec=; b=TAikLcyyqgTOWvZUDOVbawRx4J8dNmDlQeVnbvPP5iKh+3/55820eeCWrvMBzhGYaA tSGZcjXxqGCQ/So7cjE5XMB2VDmmN1QQXWTTVRfJuot+8MEC9zrSmuvRhfScNG3yoGtn rETYLZVQKEQSzAQcm+FnydvjGtRNZFEk1vJteQBahn/wv+XC+o8i2Zz36gjtu0zdLCfT XCtMn9lQyX0QIBTy7z6Kr1oHsS7GhziiiYyFrICPNf5NRY7MetIe2ZacgjOUOkUf2MjM uiP5FwxJYnhxYl3wR9WWmM3CKbYPPOPk8E6xhcBlcTeby+KNcjr6CxRMnMVSRqU5MSNN fXrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836349; x=1736441149; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KbvQFBPG02Kc4aTtsHuZjuF5x6gzUFwDF1PhT+HJtec=; b=Q9TmhL+8Wsi5vXnIl2KOSGBS471SDYI6yqC1ii4SZTV6PkpTapcc54udeR9wBzcMHJ UE+0gLp4m6rXczwm1sDw1ZJdDqR+4xbZd47kxu+dWs7MI4Ro+RX1ah3qNMFoafP0RnVd 16g2iXXGvfhwhbXltiqyNsIjtZ3AxD93Tl1v/rKYtS4TqaOYFH0HZoXEYl7X1S/ztxvO 8NrnI/8wTeDRehgpzmS1m2nQ1SrU3j4KJRpLfsWUPCo2q9jq65MN6HRWvmTRqIDxnOn6 lxkOqG0K2UNseD8bFuvMADd8HQBdK20Mo9Z1i8K9LK/wW0IOggtpVlK2nHbs3mxr2lmi x7RQ== X-Gm-Message-State: AOJu0Yz6m10BouvH1VSx5xw/a5PFB+0tCbH434CJhYD2s5Nuwm6UHuEE dzxF1rx29458b4Rhfng5bHx0oegCCBpAMHDJQpQ5dwV1JXUFskwmIgPtnw== X-Gm-Gg: ASbGncvVcV4SHMv2J8ycsU5FiAeWAoM1ssA87AQu2HU5CE1tZTe2P1VHAL901OpIbeK /Lzh7nT0K77NidJI/Eg0UgohI/sNxkU3+eC6fDO3we4JYspnu2E75oFqke8gOFlZ2j0GwcB2cyi vmXIMHJDlSpR6UlmiVsPozZ0ATOTZYa/k2KMhGjQ3X9ozJNpmX83TtztZyWAJzGLU7QMZAqhJ/i YNl6l9XJn1kNnOBQDteOdzrAhksJsFWVHbNRA1KFxtzSDWGQD0y/SU5r87Jh/wednzUxpnm9w0E lmee69boYV8bqiFYTpYNort/kaqgSa1adGpgHzzXh0kkf1DuyKReeQXpHHOUxpEg/CRdhg== X-Google-Smtp-Source: AGHT+IE/ay1Q7UeI/AOcpZnhoZ9k3zL6ZUYka226rzx3fyJderKg4EN+mS2K9P4iW82AzY1pBNauIA== X-Received: by 2002:a05:622a:287:b0:45d:82a0:5028 with SMTP id d75a77b69052e-46a4a8b879cmr682051911cf.1.1735836348752; Thu, 02 Jan 2025 08:45:48 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.48 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:48 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 20/44] selinux: update bprm hooks for selinux namespaces Date: Thu, 2 Jan 2025 11:44:45 -0500 Message-Id: <20250102164509.25606-21-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Update the bprm hook functions for SELinux namespaces. Unlike most of the hook functions, this does not require converting all of the permission checks to use the new helpers that check permissions against the current and all ancestor namespaces. Instead, we only need to check the transition-related permissions against the current namespace since only the SID in that current namespace is changed by a transition. However, we do want to check execute_no_trans against the ancestor namespaces since they are not transitioning; hence, a check is added to the end of selinux_bprm_creds_for_exec() for that purpose. Otherwise, we just document the fact that we are intentionally only checking against the current SELinux namespace for the other checks. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 728a59aa52d6..e34ba9a9f2a0 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2273,6 +2273,11 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm, av |= PROCESS2__NNP_TRANSITION; if (nosuid) av |= PROCESS2__NOSUID_TRANSITION; + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. + */ rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS2, av, NULL); @@ -2302,6 +2307,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm, static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) { + const struct cred *cred = current_cred(); const struct task_security_struct *old_tsec; struct task_security_struct *new_tsec; struct inode_security_struct *isec; @@ -2312,7 +2318,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) /* SELinux context only depends on initial program or script and not * the script interpreter */ - old_tsec = selinux_cred(current_cred()); + old_tsec = selinux_cred(cred); new_tsec = selinux_cred(bprm->cred); isec = inode_security(inode); @@ -2368,12 +2374,23 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) ad.u.file = bprm->file; if (new_tsec->sid == old_tsec->sid) { + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. + */ rc = avc_has_perm(current_selinux_state, old_tsec->sid, isec->sid, SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); if (rc) return rc; } else { + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. + */ + /* Check permissions for the transition. */ rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, @@ -2424,6 +2441,19 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) bprm->secureexec |= !!rc; } + /* + * If in a non-init namespace, also check the ability of the + * ancestors to execute without transitioning since the SID + * in ancestor namespaces is NOT modified. + */ + cred = old_tsec->parent_cred; + if (cred) { + rc = cred_has_perm(cred, isec->sid, + SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); + if (rc) + return rc; + } + return 0; } @@ -2510,6 +2540,9 @@ static void selinux_bprm_committing_creds(const struct linux_binprm *bprm) * higher than the default soft limit for cases where the default is * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. */ + /* Only check against the current namespace because the SID + * does not change in the parent. + */ rc = avc_has_perm(current_selinux_state, new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__RLIMITINH, NULL); @@ -2550,6 +2583,9 @@ static void selinux_bprm_committed_creds(const struct linux_binprm *bprm) * This must occur _after_ the task SID has been updated so that any * kill done after the flush will be checked against the new SID. */ + /* Only check against the current namespace because the SID + * does not change in the parent. + */ rc = avc_has_perm(current_selinux_state, osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); if (rc) { From patchwork Thu Jan 2 16:44:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924632 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 366FF129A78 for ; Thu, 2 Jan 2025 16:45:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836353; cv=none; b=rKzRyERsYht0g+HDWLe3ds55H+T3KP21+AWC6pP5oUJhNi4gmXDv7uxEPmflXvW5IMjguZOfMFD7LsjtHqatWM1kITxVs3Pna3lEGetRdVjyO8k4GDVXFFoX356cO82IfSdLqqqg8C3ZDoqGwENsp5fMdQ8ykptudryrMeYJdgw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836353; c=relaxed/simple; bh=QEMapwMDcDE+gYEdzwvVlWiyApaNAbQUE0dVPoDUuis=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=VhfrWqx98fnHRlHWbOLX/DPE7SSmBXz3MwI4pPN9HdbaT8L4MeGcnVFvry90EQjLkDyumoQcWf7dKzDP2IjLKjA0YT00h6B+JgWuSiRoHwvJgoxxAJI0FagLjcfr8yFd9Sx8Ua+wfj+WBtIl4g1aCuvKNgZja+ROEVHXyItiFAE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mtzFquW5; arc=none smtp.client-ip=209.85.160.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mtzFquW5" Received: by mail-qt1-f172.google.com with SMTP id d75a77b69052e-46783d44db0so108077311cf.1 for ; Thu, 02 Jan 2025 08:45:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836350; x=1736441150; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Y7gt27Cr3eBW9daTYnTwObgzvnUB9vupxIyBMIES5I0=; b=mtzFquW58nWatJcpOsqAvhPoK8tj/mZe9GhVtN1xe4jtMGoG04Mlv1UWutPczhntke vng7TVNM9eEwztyl0bol2wTKhyabz0/91e6/ITIK01/5bXNicScZvv7CAiyXO3GOev1+ qgKfM9iu0JqUAeX1/1DPdEfZ302JK9JPxDwEnacMyO7Xt7xPY6bTNYsPvYVqUPEWZ/V5 OCEokaZUOWjoQWu7fQNNOj2Bq1EQ5wa1WiudChf2K1sarSTFhIuLplEZeFIFcSyq7XjD wQEFaeFEqAeiWXmg6FP3Nbc0oNqd3ZBuvb0kRsVa2hMeqf+E7WzR/cJAMKprEXQXVeZY tOZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836350; x=1736441150; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y7gt27Cr3eBW9daTYnTwObgzvnUB9vupxIyBMIES5I0=; b=NoctIVdNexmp1OHZpAPeJPixEvTh3MqySHYziYw1zGL9DHT4QXXrz4PfboyqLnohuP ZFrcEMM7Yeihy1qL4RmwX6BjHD68s6KrBEu/0jR0cI1EMxVYuEbliNLKtwCNcdiVKWgs adJNsyjVbgHuEaVnHi/Ji/Jtyomhk+jmPgi1w/TEdAmoBKsuQ2AwOLKtj0P0GH+qXpUa H8Y4FCUkKqUcw5jUAZzoh2ter0VMCZXB6+tF7c+Sj3rEGsgoO4XQO8bIsmugDXrMfnym hqqNm2J4AxTsx1BhFd/13+Rez90d2ymnyIgNMZkpzjSBWFS2GGFoYbesORLmDFEgAziD E2yw== X-Gm-Message-State: AOJu0Yyk6utdaGL8PGq/Ge0ujWqxYUhYoiYRHBCZix2B6btGn4IY1GA8 H1ft01eSa/jPwjiD2AtpIDgRoXwZt3hIGVub9hxNoIIJEbwK/JtfNaX4LQ== X-Gm-Gg: ASbGncu3N9HAOiKFTHm1z9ZMD5m9aNZYFiwtlbyi9ITChHm51Eyeu6D0ceMOwAsJoD0 qZyy1FPgkW731MTtgwdKizQT/rDNG53UYTLGYuhqnoB5OKiuscatDVwN8UxxvF+WnjBIz4+jx0s 6vpiaRhSmruYQbuznBoNj+ORFDpF9zHHt4k+RBBOre4TdHLNztyLnWdNFkJB3xNgoUEroIYteV1 hc0LDg73ooV28V5tujAaCIc1U2k4moMlJ6MENg0u2v2Rro7+l3U7S5m3XCND/JJ+N/Xn+q+wkvO 2L0vFZKWOiN+rbanMW70SyTJO33V+vVDZxupX1rBLQPuGSMbn1NtwZfvgV8FC6+rd+N8aA== X-Google-Smtp-Source: AGHT+IEcMUSosKyv9vVlv7zInz/2erfN5GYNHSxrIvPVhBoGm9M8L58OS8jbwxX9T6ieMWg00vGOgw== X-Received: by 2002:a05:622a:189f:b0:467:5414:9cf9 with SMTP id d75a77b69052e-46a4a8cc587mr781961651cf.18.1735836349758; Thu, 02 Jan 2025 08:45:49 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.48 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:49 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 21/44] selinux: add kerneldoc to new permission checking functions Date: Thu, 2 Jan 2025 11:44:46 -0500 Message-Id: <20250102164509.25606-22-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add kerneldoc to new namespace-aware permission checking functions. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 144 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 143 insertions(+), 1 deletion(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index cc64dce0f061..480ffac13c19 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1251,6 +1251,21 @@ static u32 task_sid_obj_for_state(const struct task_struct *p, return sid; } +/** + * cred_task_has_perm - Check and audit permissions on a (cred, task) pair + * @cred: subject credentials + * @p: target task + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check permissions between a cred @cred and a task @p for @cred's namespace + * and all ancestors to determine whether the @requested permissions are + * granted. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + */ int cred_task_has_perm(const struct cred *cred, const struct task_struct *p, u16 tclass, u32 requested, struct common_audit_data *ad) @@ -1290,6 +1305,22 @@ static const struct task_security_struct *task_security( return tsec; } +/** + * task_obj_has_perm - Check and audit permissions on a (task, other-task) pair + * @s: source task + * @t: target task + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check permissions between a task @s and a task @t for the current namespace + * and all ancestors to determine whether the @requested permissions are + * granted. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + * DO NOT USE when @s is current; use cred_task_has_perm() instead. + */ int task_obj_has_perm(const struct task_struct *s, const struct task_struct *t, u16 tclass, u32 requested, @@ -1332,7 +1363,24 @@ int task_obj_has_perm(const struct task_struct *s, return 0; } - +/** + * cred_has_extended_perms - Check and audit extended permissions on a (cred, tsid) pair + * @cred: subject credentials + * @tsid: target security identifier + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @driver: driver value + * @xperm: extended permission value + * @auditdata: auxiliary audit data + * + * Check extended permissions between a cred @cred and a target + * security identifier @tsid for @cred's namespace and all ancestors + * to determine whether the @requested permissions are granted for the + * specified (@driver, @xperm) pair. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if the @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + */ int cred_has_extended_perms(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, u8 driver, u8 xperm, struct common_audit_data *ad) @@ -1358,6 +1406,20 @@ int cred_has_extended_perms(const struct cred *cred, u32 tsid, u16 tclass, return 0; } +/** + * cred_self_has_perm - Check and audit permissions on a (cred, self) pair + * @cred: subject credentials + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check permissions between a cred @cred and itself for @cred's namespace + * and all ancestors to determine whether the @requested permissions are + * granted. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + */ int cred_self_has_perm(const struct cred *cred, u16 tclass, u32 requested, struct common_audit_data *ad) { @@ -1380,6 +1442,18 @@ int cred_self_has_perm(const struct cred *cred, u16 tclass, u32 requested, return 0; } +/** + * cred_self_has_perm_noaudit - Check permissions on a (cred, self) pair, no audit + * @cred: subject credentials + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * + * Check permissions between a cred @cred and itself for @cred's namespace + * and all ancestors to determine whether the @requested permissions are + * granted. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + */ int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, u32 requested) { @@ -1405,6 +1479,25 @@ int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, return 0; } + +/** + * cred_has_perm - Check and audit permissions on a (cred, tsid) pair + * @cred: subject credentials + * @tsid: target security identifier + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check permissions between a cred @cred and a target SID @tsid for + * @cred's namespace and all ancestors to determine whether the + * @requested permissions are granted, interpreting the permissions based + * on @tclass. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + * DO NOT USE when checking permissions between two creds (or tasks); + * use cred_other_has_perm() or cred_task_has_perm() instead. + */ int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, struct common_audit_data *ad) { @@ -1427,6 +1520,22 @@ int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, return 0; } +/** + * cred_has_perm_noaudit - Check permissions on a (cred, tsid) pair, no audit + * @cred: subject credentials + * @tsid: target security identifier + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @avd: access vector decisions + * + * Check permissions between a cred @cred and a target SID @tsid for + * @cred's namespace and all ancestors to determine whether the + * @requested permissions are granted. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + * DO NOT USE when checking permissions between two creds (or tasks); + * use cred_other_has_perm() or cred_task_has_perm() instead. + */ int cred_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, struct av_decision *avd) { @@ -1458,6 +1567,24 @@ int cred_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, return 0; } +/** + * cred_ssid_has_perm - Check and audit permissions on a (ssid, tsid) pair + * @cred: subject credentials + * @ssid: source security identifier + * @tsid: target security identifier + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check permissions between a source SID @ssid and a target SID @tsid for + * @cred's namespace and all ancestors to determine whether the + * @requested permissions are granted. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + * DO NOT USE when checking permissions involving cred/task SIDs; this + * helper is only for object-to-object checks. + */ int cred_ssid_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, u32 requested, struct common_audit_data *ad) { @@ -1494,6 +1621,21 @@ static u32 cred_sid_for_state(const struct cred *cred, return sid; } +/** + * cred_other_has_perm - Check and audit permissions on a (cred, other-cred) pair + * @cred: subject credentials + * @other: other credentials + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check permissions between a cred @cred and a task @p for @cred's namespace + * and all ancestors to determine whether the @requested permissions are + * granted. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + */ int cred_other_has_perm(const struct cred *cred, const struct cred *other, u16 tclass, u32 requested, struct common_audit_data *ad) From patchwork Thu Jan 2 16:44:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924633 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f178.google.com (mail-qk1-f178.google.com [209.85.222.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B697415575C for ; Thu, 2 Jan 2025 16:45:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836354; cv=none; b=hcEiKTrnAFGGO35SAjBdEaT0beHzgT4Q+j7PSQ0pi3t2l8lPD3BaLp62XwxDWjK+KKImwzDjEFoQkPYIllEniDQOoLR/zoot01xdvUKEN3/+zXv6RXyXiBqvw0FeQbOLtWofIlO0fhWzgJSZEntMe98QbDp8KJDvtfllRtqK5NE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836354; c=relaxed/simple; bh=9aEI82yj5MBuwzxIhcriT0S0m7aRBS/Vtz4jCdIc5CQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=H8TSTaVGVNwnJSdJgV+xMJx+fPHLAxc7D01zTyYtiTyi+58hlYzQB7LDvQFQVWekKxbmAUJ9qlobmfAUEpB06kAqKzuqUNadWVDvbBjwy0YgGf7+q0LFPv8/ZyIzJIs9NA3TWpaVoqIkRSIBOIz0uUDri3sNZ2z7Vb0xdppgGgc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hR7F1Dly; arc=none smtp.client-ip=209.85.222.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hR7F1Dly" Received: by mail-qk1-f178.google.com with SMTP id af79cd13be357-7b6eb531e13so587369585a.0 for ; Thu, 02 Jan 2025 08:45:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836350; x=1736441150; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=PpHt0QuX96SLxrx0ZqRsq4Zuvzso+9JWoIe7UP1DSD8=; b=hR7F1DlyebHMRo+emOcH3TpGqvE9jcaOJkUjeVh4gXu68p/fMTjVNjsnTlElYsz1+T Ml5Zija1Yjh+UM9CA6nJ6C1uQTGFZue5S9pHa7du8GZEdVR5SWH9HeG7tCVj5W1Wom9e ql8OqFrwjLUZIAWJMq43dObBtg6AQuVEkrShGsV+K6bv3Y136f9jdFYmMQDfCSx8hVkj 2+41RfFBhg1mMu5B901/FHz6lTEb9JGHYVa7mzH1cOq/aKn+F2/B0Zeulen4c9b24d0w 198CylsMHj8pcdW1YiNFoZHKYyzO9juli7c9l1u1lIvrd3jA7r0MNHakqhQu3Dw2p8FN iXNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836350; x=1736441150; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=PpHt0QuX96SLxrx0ZqRsq4Zuvzso+9JWoIe7UP1DSD8=; b=bshJw0jge7//wV8q4TeRQ8qRTu34KIJfGvCQeqQcsx0dz662Y8KtHVlAgTqqsx6j57 4jraBQ5qQQSuc5jTyvd4jt38tecJgvcKNjh7ETj5bdeIqYGycsUz2/yrFrra4D3tHyw2 qsTTDsaJTqTIa8ZYyVtB4P6Qo6KaojXBfC+UPgNg2QK1zc5NvLpt3C1JWltcmHEkLW5A izj48tWpTVKR+6jm6cPTIcMB68tQ5v0H5nOFmD1CFwz+NnfGjHVFkbsRjpn5SMePnsxV IhWsuqU54hSlHigx0rabXjZ3mN3lTZfd7BqOKj28T1zIfZ+6W2SLHcHyNgZzRrp77CH1 IHFg== X-Gm-Message-State: AOJu0Yzhb1VvvZewTOZAHtwewGtpXACKNbr6sPp60+uJ5wru+ZNmth3N AYA7PanliypDwW+2xYr1urmcVRQKNjFAig4bvhB/CTcJQp5dKs2IXmsjDQ== X-Gm-Gg: ASbGncsMRryNazOvDTAxDa27pgBu0c3qxfeYCWrOFUxEbydQcpi7nFXMBZf59kVT7wP +05If/Lswi6mneTdJVg/1wwj4t1C6EXcdjqZExdNz/Za7K1tOGpAbG04sD0QowcHaK4RsGdN0CU +d4cVIOHk4RzdSFrObhoupmtX69OtwKomFBR47AiP05m56mL/QGrCWoh6H7dNUbisbgi1SO3Y2R Jm7RA3WJ4NZe97a/iN67Nj7K6KzrcfJff3o+Ah4R0iMXasNp7LH0/zUsrleeubnwqQ4fsmrZaKt 12dTjemxIxKGUjKiQkem2toK98DLnj1isuYuje+1hg50Kx/YJOxgq/EaNkHGe11x5Va7Ig== X-Google-Smtp-Source: AGHT+IFm3N13jcjAcyOmURRhyonD875zrp0E4BrWWeIxxpteA/3aWfnzjss2Qqktl3toYjci5u72bg== X-Received: by 2002:a05:620a:2b8d:b0:7b6:cc37:cbe9 with SMTP id af79cd13be357-7b9ba738a3cmr7116050785a.19.1735836350296; Thu, 02 Jan 2025 08:45:50 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.49 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:50 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 22/44] selinux: convert selinux_file_send_sigiotask() to namespace-aware helper Date: Thu, 2 Jan 2025 11:44:47 -0500 Message-Id: <20250102164509.25606-23-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Convert selinux_file_send_sigiotask() to use the cred_task_has_perm() namespace-aware permission checking helper. This required saving the file owner cred in the file security blob for later use in this hook function. Since the cred already includes the cred/task security blob which has the task SID and the SELinux state/namespace, we can drop those separate fields from the file_security_struct at the same time. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 15 ++++++--------- security/selinux/include/objsec.h | 3 +-- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e34ba9a9f2a0..5a0355229ad3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3703,8 +3703,7 @@ static int selinux_file_alloc_security(struct file *file) u32 sid = current_sid(); fsec->sid = sid; - fsec->fown_sid = sid; - fsec->state = get_selinux_state(current_selinux_state); + fsec->cred = get_cred(current_cred()); return 0; } @@ -3713,8 +3712,7 @@ static void selinux_file_free_security(struct file *file) { struct file_security_struct *fsec = selinux_file(file); - put_selinux_state(fsec->state); - fsec->state = NULL; + put_cred(fsec->cred); } /* @@ -3996,14 +3994,14 @@ static void selinux_file_set_fowner(struct file *file) struct file_security_struct *fsec; fsec = selinux_file(file); - fsec->fown_sid = current_sid(); + put_cred(fsec->cred); + fsec->cred = get_cred(current_cred()); } static int selinux_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int signum) { struct file *file; - u32 sid = task_sid_obj(tsk); u32 perm; struct file_security_struct *fsec; @@ -4017,9 +4015,8 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, else perm = signal_to_av(signum); - return avc_has_perm(fsec->state, - fsec->fown_sid, sid, - SECCLASS_PROCESS, perm, NULL); + return cred_task_has_perm(fsec->cred, tsk, SECCLASS_PROCESS, perm, + NULL); } static int selinux_file_receive(struct file *file) diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 6560cb13fc34..7c452047664c 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -48,10 +48,9 @@ struct inode_security_struct { struct file_security_struct { u32 sid; /* SID of open file description */ - u32 fown_sid; /* SID of file owner (for SIGIO) */ u32 isid; /* SID of inode at the time of file open */ u32 pseqno; /* Policy seqno at the time of file open */ - struct selinux_state *state; /* SELinux state */ + const struct cred *cred; /* cred for file owner (for SIGIO) */ }; struct superblock_security_struct { From patchwork Thu Jan 2 16:44:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924635 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f177.google.com (mail-qt1-f177.google.com [209.85.160.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 016BF156960 for ; Thu, 2 Jan 2025 16:45:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836356; cv=none; b=EzA5n41KAJiO1sVxCmi5oU3hh7O1MurBSEdJ1yu2fXvZXeGOPMgxWR3yQBT+XLEiYffQ3/nTRzAdUfrCx6xv9hDHi6NQSOQ2cFwJE7pd07VFOBV0cLYQEmCNriohOo0bZ8rNJJGnHizJ+ReLS4UsN3+DmFBQ00vdJitqElIdUiY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836356; c=relaxed/simple; bh=J5ir3pXzVWcVZLlOckA90l1C7TFB8uRC8Osq2JnD+yk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hmUllVffOXdiGhb3ERiwoV/M41ZRX7K+uxOcyzwZaj62p7zNgZlYxqmKt4R12vo0ZMIyPi32xX8hPx6xKtPO/r5pKb6Gl8T3WgCaPvTM9E9c95Sz+WpB6ZYAvX+jtcWadlq4dmZpvvO5vitoyKYbO/9gGTnLB88o+Al88ROmPLg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=UEc9ST4b; arc=none smtp.client-ip=209.85.160.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UEc9ST4b" Received: by mail-qt1-f177.google.com with SMTP id d75a77b69052e-467918c360aso133677751cf.0 for ; Thu, 02 Jan 2025 08:45:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836351; x=1736441151; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2S401lEPZsDKsA1n3s9T88OCDi2dN+S969GJxv7UcS8=; b=UEc9ST4by4WG/1AU1dJn9uTqZQhbiFUfJZC6oEpCPLKsQt/EHZ1d9L56Umx+1SffFs 6ZnyVMWaPBTRJSjhkYZUA8CFY84Li5NfYiNMCYPSxCJ7Jo3dQuUjt2i9n2ULnuCja6Hh cP4KS75g1SME+aMRBgEjfc+2JFPmrZlwEMi4cpWw3IhvVZIk1n22yoHXoL8t6kPQs1np cNh7wvo/owQINOEpGHXkHC25xq3EvyUxsRM9O6rYi/tm2ZlW2sacmxY37t1MgwKVG4U+ 0FSov37NYfxxNwoB+849HOjhRvUoVUQVxLhoRe1SzUQGfT6PUk7KoP6yon4fDA6xZ0Vb jrdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836351; x=1736441151; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2S401lEPZsDKsA1n3s9T88OCDi2dN+S969GJxv7UcS8=; b=bfBUia1bhuja7GXOVcb8+3wd7L15cdkJaGr1kdUVd1GHD6lrwZ5BSkByObgik7XW25 yhedkaZdikIxzh74toi6uDzQ+fKuIPSP1JcbNuw3YGmdfAxaxF6uK70gVepYxqTNTpeZ +YAHr4AmgAOS3njrA7Xy+4bU87n5LxhbLmswpZZaoa5GGvK/IXgsvCvvuVvZft8KZ6YZ I0Kjdb11EyQlVCmhj0aWJYuQVZMCyipPKhC4x4vFnkeVdkg4+z+R/DtdIqLuUIX+NCIC G1IBxgDqmEvIiQRx9rblT8tWkfb/ml97vT/dO0Pfwq7qkKJOVcrM1LA8h/0SSRbs0NCE Va1Q== X-Gm-Message-State: AOJu0YwBvD8ODIOz5MSVGxHr9cMny8hBZ9Teq/buiL/dgQNhJNi2KrO9 F9vGIFaD9fwsSBeKDPgoIVAoNhDc7ZNN6+OUq7evyj4z5Vr1/cGznMc6yg== X-Gm-Gg: ASbGncuhP0tsH3v5o7XgvW71K/W2kZ9Tv9jEOXifKB0T3R7yH+Qelh5nbktZWvog1JW sBltfpD9XtcBJbZzHOGNw7odWua91JE3MEm4ZgR08vGNWwL6LIUXgHIuqD3KXxmBadQw0cte/0q zF+gCalGU2QQhYkFql6UBZPen9ro9UjJUyQsvhqQRsTbvL0nzU/u/feu1LqGNIALUGG9kcR2e0W rYZqVMbdmQ6GEnbjcFXG4AilJ2UNoNfaFszAbnwDaWOLosgUAVOgf3o6pn937nfPhWRpEiSGJsJ TCqULrawc5hLFu3kMIRZPBFI6DvO+uU1kAzQsyhsugyYPwehpxtANxXUJx9I60ZTSAXx8g== X-Google-Smtp-Source: AGHT+IHWC34Ru4w2jFqRfyZaxevHnabZsS6UIkuWEop9fo+dW8eOSHZbYSeIPnGgnRlNKMIPpcSpeQ== X-Received: by 2002:ac8:7f41:0:b0:466:b394:92bc with SMTP id d75a77b69052e-46a4a8b81famr689964751cf.6.1735836350948; Thu, 02 Jan 2025 08:45:50 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.50 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:50 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 23/44] selinux: rename cred_has_perm*() to cred_tsid_has_perm*() Date: Thu, 2 Jan 2025 11:44:48 -0500 Message-Id: <20250102164509.25606-24-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Rename cred_has_perm*() to cred_tsid_has_perm*() for greater clarity and parallelism with the other helper functions. These functions check permissions between a cred and a fixed target SID for the current namespace and its ancestors. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 12 +- security/selinux/hooks.c | 240 ++++++++++++++++----------------- security/selinux/include/avc.h | 8 +- 3 files changed, 130 insertions(+), 130 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 480ffac13c19..250d56dae487 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1481,7 +1481,7 @@ int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, /** - * cred_has_perm - Check and audit permissions on a (cred, tsid) pair + * cred_tsid_has_perm - Check and audit permissions on a (cred, tsid) pair * @cred: subject credentials * @tsid: target security identifier * @tclass: target security class @@ -1498,8 +1498,8 @@ int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, * DO NOT USE when checking permissions between two creds (or tasks); * use cred_other_has_perm() or cred_task_has_perm() instead. */ -int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, - u32 requested, struct common_audit_data *ad) +int cred_tsid_has_perm(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *ad) { struct task_security_struct *tsec; struct selinux_state *state; @@ -1521,7 +1521,7 @@ int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, } /** - * cred_has_perm_noaudit - Check permissions on a (cred, tsid) pair, no audit + * cred_tsid_has_perm_noaudit - Check permissions on a (cred, tsid) pair, no audit * @cred: subject credentials * @tsid: target security identifier * @tclass: target security class @@ -1536,8 +1536,8 @@ int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, * DO NOT USE when checking permissions between two creds (or tasks); * use cred_other_has_perm() or cred_task_has_perm() instead. */ -int cred_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, - u32 requested, struct av_decision *avd) +int cred_tsid_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, struct av_decision *avd) { struct task_security_struct *tsec; struct selinux_state *state; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5a0355229ad3..1619d5c2c187 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -454,13 +454,13 @@ static int may_context_mount_sb_relabel(u32 sid, { int rc; - rc = cred_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, - FILESYSTEM__RELABELFROM, NULL); + rc = cred_tsid_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, + FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; - rc = cred_has_perm(cred, sid, SECCLASS_FILESYSTEM, - FILESYSTEM__RELABELTO, NULL); + rc = cred_tsid_has_perm(cred, sid, SECCLASS_FILESYSTEM, + FILESYSTEM__RELABELTO, NULL); return rc; } @@ -470,8 +470,8 @@ static int may_context_mount_inode_relabel(u32 sid, { int rc; - rc = cred_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, - FILESYSTEM__RELABELFROM, NULL); + rc = cred_tsid_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, + FILESYSTEM__RELABELFROM, NULL); if (rc) return rc; @@ -1691,7 +1691,7 @@ static int inode_has_perm(const struct cred *cred, isec = selinux_inode(inode); - return cred_has_perm(cred, isec->sid, isec->sclass, perms, adp); + return cred_tsid_has_perm(cred, isec->sid, isec->sclass, perms, adp); } /* Same as inode_has_perm, but pass explicit audit data containing @@ -1764,8 +1764,8 @@ static int file_has_perm(const struct cred *cred, ad.u.file = file; if (sid != fsec->sid) { - rc = cred_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, - &ad); + rc = cred_tsid_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, + &ad); if (rc) goto out; } @@ -1832,9 +1832,9 @@ static int may_create(struct inode *dir, ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = dentry; - rc = cred_has_perm(cred, dsec->sid, SECCLASS_DIR, - DIR__ADD_NAME | DIR__SEARCH, - &ad); + rc = cred_tsid_has_perm(cred, dsec->sid, SECCLASS_DIR, + DIR__ADD_NAME | DIR__SEARCH, + &ad); if (rc) return rc; @@ -1843,7 +1843,7 @@ static int may_create(struct inode *dir, if (rc) return rc; - rc = cred_has_perm(cred, newsid, tclass, FILE__CREATE, &ad); + rc = cred_tsid_has_perm(cred, newsid, tclass, FILE__CREATE, &ad); if (rc) return rc; @@ -1876,7 +1876,7 @@ static int may_link(struct inode *dir, av = DIR__SEARCH; av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); - rc = cred_has_perm(cred, dsec->sid, SECCLASS_DIR, av, &ad); + rc = cred_tsid_has_perm(cred, dsec->sid, SECCLASS_DIR, av, &ad); if (rc) return rc; @@ -1896,7 +1896,7 @@ static int may_link(struct inode *dir, return 0; } - return cred_has_perm(cred, isec->sid, isec->sclass, av, &ad); + return cred_tsid_has_perm(cred, isec->sid, isec->sclass, av, &ad); } static inline int may_rename(struct inode *old_dir, @@ -1919,17 +1919,17 @@ static inline int may_rename(struct inode *old_dir, ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = old_dentry; - rc = cred_has_perm(cred, old_dsec->sid, SECCLASS_DIR, - DIR__REMOVE_NAME | DIR__SEARCH, &ad); + rc = cred_tsid_has_perm(cred, old_dsec->sid, SECCLASS_DIR, + DIR__REMOVE_NAME | DIR__SEARCH, &ad); if (rc) return rc; - rc = cred_has_perm(cred, old_isec->sid, old_isec->sclass, - FILE__RENAME, &ad); + rc = cred_tsid_has_perm(cred, old_isec->sid, old_isec->sclass, + FILE__RENAME, &ad); if (rc) return rc; if (old_is_dir && new_dir != old_dir) { - rc = cred_has_perm(cred, old_isec->sid, old_isec->sclass, - DIR__REPARENT, &ad); + rc = cred_tsid_has_perm(cred, old_isec->sid, old_isec->sclass, + DIR__REPARENT, &ad); if (rc) return rc; } @@ -1938,15 +1938,15 @@ static inline int may_rename(struct inode *old_dir, av = DIR__ADD_NAME | DIR__SEARCH; if (d_is_positive(new_dentry)) av |= DIR__REMOVE_NAME; - rc = cred_has_perm(cred, new_dsec->sid, SECCLASS_DIR, av, &ad); + rc = cred_tsid_has_perm(cred, new_dsec->sid, SECCLASS_DIR, av, &ad); if (rc) return rc; if (d_is_positive(new_dentry)) { new_isec = backing_inode_security(new_dentry); new_is_dir = d_is_dir(new_dentry); - rc = cred_has_perm(cred, new_isec->sid, new_isec->sclass, - (new_is_dir ? DIR__RMDIR : FILE__UNLINK), - &ad); + rc = cred_tsid_has_perm(cred, new_isec->sid, new_isec->sclass, + (new_is_dir ? DIR__RMDIR : FILE__UNLINK), + &ad); if (rc) return rc; } @@ -1963,8 +1963,8 @@ static int superblock_has_perm(const struct cred *cred, struct superblock_security_struct *sbsec; sbsec = selinux_superblock(sb); - return cred_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, perms, - ad); + return cred_tsid_has_perm(cred, sbsec->sid, SECCLASS_FILESYSTEM, perms, + ad); } /* Convert a Linux mode and permission mask to an access vector. */ @@ -2083,8 +2083,8 @@ static int selinux_binder_transfer_file(const struct cred *from, ad.u.path = file->f_path; if (sid != fsec->sid) { - rc = cred_has_perm(to, fsec->sid, SECCLASS_FD, FD__USE, - &ad); + rc = cred_tsid_has_perm(to, fsec->sid, SECCLASS_FD, FD__USE, + &ad); if (rc) return rc; } @@ -2099,8 +2099,8 @@ static int selinux_binder_transfer_file(const struct cred *from, return 0; isec = backing_inode_security(dentry); - return cred_has_perm(to, isec->sid, isec->sclass, file_to_av(file), - &ad); + return cred_tsid_has_perm(to, isec->sid, isec->sclass, file_to_av(file), + &ad); } static int selinux_ptrace_access_check(struct task_struct *child, @@ -2201,20 +2201,20 @@ static int selinux_syslog(int type) switch (type) { case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ - return cred_has_perm(cred, SECINITSID_KERNEL, - SECCLASS_SYSTEM, - SYSTEM__SYSLOG_READ, NULL); + return cred_tsid_has_perm(cred, SECINITSID_KERNEL, + SECCLASS_SYSTEM, + SYSTEM__SYSLOG_READ, NULL); case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ /* Set level of messages printed to console */ case SYSLOG_ACTION_CONSOLE_LEVEL: - return cred_has_perm(cred, SECINITSID_KERNEL, - SECCLASS_SYSTEM, - SYSTEM__SYSLOG_CONSOLE, NULL); + return cred_tsid_has_perm(cred, SECINITSID_KERNEL, + SECCLASS_SYSTEM, + SYSTEM__SYSLOG_CONSOLE, NULL); } /* All other syslog types */ - return cred_has_perm(cred, SECINITSID_KERNEL, SECCLASS_SYSTEM, - SYSTEM__SYSLOG_MOD, NULL); + return cred_tsid_has_perm(cred, SECINITSID_KERNEL, SECCLASS_SYSTEM, + SYSTEM__SYSLOG_MOD, NULL); } /* @@ -2448,8 +2448,8 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) */ cred = old_tsec->parent_cred; if (cred) { - rc = cred_has_perm(cred, isec->sid, - SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); + rc = cred_tsid_has_perm(cred, isec->sid, + SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); if (rc) return rc; } @@ -3059,8 +3059,8 @@ static int selinux_inode_init_security_anon(struct inode *inode, ad.type = LSM_AUDIT_DATA_ANONINODE; ad.u.anonclass = name ? (const char *)name->name : "?"; - return cred_has_perm(current_cred(), isec->sid, isec->sclass, - FILE__CREATE, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, isec->sclass, + FILE__CREATE, &ad); } static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) @@ -3123,8 +3123,8 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode, if (IS_ERR(isec)) return PTR_ERR(isec); - return cred_has_perm(current_cred(), isec->sid, isec->sclass, - FILE__READ, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, isec->sclass, + FILE__READ, &ad); } static noinline int audit_inode_permission(struct inode *inode, @@ -3168,8 +3168,8 @@ static int selinux_inode_permission(struct inode *inode, int mask) if (IS_ERR(isec)) return PTR_ERR(isec); - rc = cred_has_perm_noaudit(current_cred(), isec->sid, isec->sclass, - perms, &avd); + rc = cred_tsid_has_perm_noaudit(current_cred(), isec->sid, isec->sclass, + perms, &avd); audited = avc_audit_required(perms, &avd, rc, from_access ? FILE__AUDIT_ACCESS : 0, &denied); @@ -3275,8 +3275,8 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, ad.u.dentry = dentry; isec = backing_inode_security(dentry); - rc = cred_has_perm(cred, isec->sid, isec->sclass, FILE__RELABELFROM, - &ad); + rc = cred_tsid_has_perm(cred, isec->sid, isec->sclass, FILE__RELABELFROM, + &ad); if (rc) return rc; @@ -3315,8 +3315,8 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, if (rc) return rc; - rc = cred_has_perm(cred, newsid, isec->sclass, FILE__RELABELTO, - &ad); + rc = cred_tsid_has_perm(cred, newsid, isec->sclass, FILE__RELABELTO, + &ad); if (rc) return rc; @@ -3738,8 +3738,8 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, ad.u.op->path = file->f_path; if (ssid != fsec->sid) { - rc = cred_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, - &ad); + rc = cred_tsid_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, + &ad); if (rc) goto out; } @@ -4123,8 +4123,8 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid) struct task_security_struct *tsec = selinux_cred(new); int ret; - ret = cred_has_perm(current_cred(), secid, SECCLASS_KERNEL_SERVICE, - KERNEL_SERVICE__USE_AS_OVERRIDE, NULL); + ret = cred_tsid_has_perm(current_cred(), secid, SECCLASS_KERNEL_SERVICE, + KERNEL_SERVICE__USE_AS_OVERRIDE, NULL); if (ret == 0) { tsec->sid = secid; tsec->create_sid = 0; @@ -4144,10 +4144,10 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) struct task_security_struct *tsec = selinux_cred(new); int ret; - ret = cred_has_perm(current_cred(), isec->sid, - SECCLASS_KERNEL_SERVICE, - KERNEL_SERVICE__CREATE_FILES_AS, - NULL); + ret = cred_tsid_has_perm(current_cred(), isec->sid, + SECCLASS_KERNEL_SERVICE, + KERNEL_SERVICE__CREATE_FILES_AS, + NULL); if (ret == 0) tsec->create_sid = isec->sid; @@ -4161,8 +4161,8 @@ static int selinux_kernel_module_request(char *kmod_name) ad.type = LSM_AUDIT_DATA_KMOD; ad.u.kmod_name = kmod_name; - return cred_has_perm(current_cred(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, &ad); + return cred_tsid_has_perm(current_cred(), SECINITSID_KERNEL, + SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, &ad); } static int selinux_kernel_module_from_file(struct file *file) @@ -4186,15 +4186,15 @@ static int selinux_kernel_module_from_file(struct file *file) fsec = selinux_file(file); if (sid != fsec->sid) { - rc = cred_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, - &ad); + rc = cred_tsid_has_perm(cred, fsec->sid, SECCLASS_FD, FD__USE, + &ad); if (rc) return rc; } isec = inode_security(file_inode(file)); - return cred_has_perm(cred, isec->sid, SECCLASS_SYSTEM, - SYSTEM__MODULE_LOAD, &ad); + return cred_tsid_has_perm(cred, isec->sid, SECCLASS_SYSTEM, + SYSTEM__MODULE_LOAD, &ad); } static int selinux_kernel_read_file(struct file *file, @@ -4702,8 +4702,8 @@ static int sock_has_perm(struct sock *sk, u32 perms) ad_net_init_from_sk(&ad, &net, sk); - return cred_has_perm(current_cred(), sksec->sid, sksec->sclass, - perms, &ad); + return cred_tsid_has_perm(current_cred(), sksec->sid, sksec->sclass, + perms, &ad); } static int selinux_socket_create(int family, int type, @@ -4722,8 +4722,8 @@ static int selinux_socket_create(int family, int type, if (rc) return rc; - return cred_has_perm(current_cred(), newsid, secclass, - SOCKET__CREATE, NULL); + return cred_tsid_has_perm(current_cred(), newsid, secclass, + SOCKET__CREATE, NULL); } static int selinux_socket_post_create(struct socket *sock, int family, @@ -5672,8 +5672,8 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) static int selinux_secmark_relabel_packet(u32 sid) { - return cred_has_perm(current_cred(), sid, SECCLASS_PACKET, - PACKET__RELABELTO, NULL); + return cred_tsid_has_perm(current_cred(), sid, SECCLASS_PACKET, + PACKET__RELABELTO, NULL); } static void selinux_secmark_refcount_inc(void) @@ -5717,9 +5717,9 @@ static int selinux_tun_dev_attach_queue(void *security) { struct tun_security_struct *tunsec = selinux_tun_dev(security); - return cred_has_perm(current_cred(), tunsec->sid, - SECCLASS_TUN_SOCKET, TUN_SOCKET__ATTACH_QUEUE, - NULL); + return cred_tsid_has_perm(current_cred(), tunsec->sid, + SECCLASS_TUN_SOCKET, TUN_SOCKET__ATTACH_QUEUE, + NULL); } static int selinux_tun_dev_attach(struct sock *sk, void *security) @@ -5746,8 +5746,8 @@ static int selinux_tun_dev_open(void *security) struct tun_security_struct *tunsec = selinux_tun_dev(security); int err; - err = cred_has_perm(cred, tunsec->sid, SECCLASS_TUN_SOCKET, - TUN_SOCKET__RELABELFROM, NULL); + err = cred_tsid_has_perm(cred, tunsec->sid, SECCLASS_TUN_SOCKET, + TUN_SOCKET__RELABELFROM, NULL); if (err) return err; err = cred_self_has_perm(cred, SECCLASS_TUN_SOCKET, @@ -6137,8 +6137,8 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = ipc_perms->key; - return cred_has_perm(current_cred(), isec->sid, isec->sclass, perms, - &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, isec->sclass, perms, + &ad); } static int selinux_msg_msg_alloc_security(struct msg_msg *msg) @@ -6163,8 +6163,8 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - return cred_has_perm(current_cred(), isec->sid, SECCLASS_MSGQ, - MSGQ__CREATE, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, SECCLASS_MSGQ, + MSGQ__CREATE, &ad); } static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) @@ -6177,8 +6177,8 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - return cred_has_perm(current_cred(), isec->sid, SECCLASS_MSGQ, - MSGQ__ASSOCIATE, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, SECCLASS_MSGQ, + MSGQ__ASSOCIATE, &ad); } static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) @@ -6189,8 +6189,8 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) case IPC_INFO: case MSG_INFO: /* No specific object, just general system-wide information. */ - return cred_has_perm(current_cred(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); + return cred_tsid_has_perm(current_cred(), SECINITSID_KERNEL, + SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL); case IPC_STAT: case MSG_STAT: case MSG_STAT_ANY: @@ -6239,11 +6239,11 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m ad.u.ipc_id = msq->key; /* Can this process write to the queue? */ - rc = cred_has_perm(cred, isec->sid, SECCLASS_MSGQ, MSGQ__WRITE, &ad); + rc = cred_tsid_has_perm(cred, isec->sid, SECCLASS_MSGQ, MSGQ__WRITE, &ad); if (!rc) /* Can this process send the message */ - rc = cred_has_perm(cred, msec->sid, SECCLASS_MSG, MSG__SEND, - &ad); + rc = cred_tsid_has_perm(cred, msec->sid, SECCLASS_MSG, MSG__SEND, + &ad); if (!rc) /* Can the message be put in the queue? */ rc = cred_ssid_has_perm(cred, msec->sid, isec->sid, @@ -6290,8 +6290,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - return cred_has_perm(current_cred(), isec->sid, SECCLASS_SHM, - SHM__CREATE, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, SECCLASS_SHM, + SHM__CREATE, &ad); } static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) @@ -6304,8 +6304,8 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = shp->key; - return cred_has_perm(current_cred(), isec->sid, SECCLASS_SHM, - SHM__ASSOCIATE, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, SECCLASS_SHM, + SHM__ASSOCIATE, &ad); } /* Note, at this point, shp is locked down */ @@ -6317,9 +6317,9 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd) case IPC_INFO: case SHM_INFO: /* No specific object, just general system-wide information. */ - return cred_has_perm(current_cred(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__IPC_INFO, - NULL); + return cred_tsid_has_perm(current_cred(), SECINITSID_KERNEL, + SECCLASS_SYSTEM, SYSTEM__IPC_INFO, + NULL); case IPC_STAT: case SHM_STAT: case SHM_STAT_ANY: @@ -6367,8 +6367,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - return cred_has_perm(current_cred(), isec->sid, SECCLASS_SEM, - SEM__CREATE, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, SECCLASS_SEM, + SEM__CREATE, &ad); } static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) @@ -6381,8 +6381,8 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = sma->key; - return cred_has_perm(current_cred(), isec->sid, SECCLASS_SEM, - SEM__ASSOCIATE, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, SECCLASS_SEM, + SEM__ASSOCIATE, &ad); } /* Note, at this point, sma is locked down */ @@ -6395,9 +6395,9 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd) case IPC_INFO: case SEM_INFO: /* No specific object, just general system-wide information. */ - return cred_has_perm(current_cred(), SECINITSID_KERNEL, - SECCLASS_SYSTEM, SYSTEM__IPC_INFO, - NULL); + return cred_tsid_has_perm(current_cred(), SECINITSID_KERNEL, + SECCLASS_SYSTEM, SYSTEM__IPC_INFO, + NULL); case GETPID: case GETNCNT: case GETZCNT: @@ -6626,8 +6626,8 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) tsec->create_sid = sid; } else if (attr == LSM_ATTR_KEYCREATE) { if (sid) { - error = cred_has_perm(cred, sid, SECCLASS_KEY, - KEY__CREATE, NULL); + error = cred_tsid_has_perm(cred, sid, SECCLASS_KEY, + KEY__CREATE, NULL); if (error) goto abort_change; } @@ -6866,7 +6866,7 @@ static int selinux_key_permission(key_ref_t key_ref, key = key_ref_to_ptr(key_ref); ksec = selinux_key(key); - return cred_has_perm(cred, ksec->sid, SECCLASS_KEY, perm, NULL); + return cred_tsid_has_perm(cred, ksec->sid, SECCLASS_KEY, perm, NULL); } static int selinux_key_getsecurity(struct key *key, char **_buffer) @@ -6889,8 +6889,8 @@ static int selinux_watch_key(struct key *key) { struct key_security_struct *ksec = selinux_key(key); - return cred_has_perm(current_cred(), ksec->sid, SECCLASS_KEY, - KEY__VIEW, NULL); + return cred_tsid_has_perm(current_cred(), ksec->sid, SECCLASS_KEY, + KEY__VIEW, NULL); } #endif #endif @@ -7005,15 +7005,15 @@ static int bpf_fd_pass(const struct file *file, const struct cred *cred) if (file->f_op == &bpf_map_fops) { map = file->private_data; bpfsec = map->security; - ret = cred_has_perm(cred, bpfsec->sid, SECCLASS_BPF, - bpf_map_fmode_to_av(file->f_mode), NULL); + ret = cred_tsid_has_perm(cred, bpfsec->sid, SECCLASS_BPF, + bpf_map_fmode_to_av(file->f_mode), NULL); if (ret) return ret; } else if (file->f_op == &bpf_prog_fops) { prog = file->private_data; bpfsec = prog->aux->security; - ret = cred_has_perm(cred, bpfsec->sid, SECCLASS_BPF, - BPF__PROG_RUN, NULL); + ret = cred_tsid_has_perm(cred, bpfsec->sid, SECCLASS_BPF, + BPF__PROG_RUN, NULL); if (ret) return ret; } @@ -7025,8 +7025,8 @@ static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) struct bpf_security_struct *bpfsec; bpfsec = map->security; - return cred_has_perm(current_cred(), bpfsec->sid, SECCLASS_BPF, - bpf_map_fmode_to_av(fmode), NULL); + return cred_tsid_has_perm(current_cred(), bpfsec->sid, SECCLASS_BPF, + bpf_map_fmode_to_av(fmode), NULL); } static int selinux_bpf_prog(struct bpf_prog *prog) @@ -7034,8 +7034,8 @@ static int selinux_bpf_prog(struct bpf_prog *prog) struct bpf_security_struct *bpfsec; bpfsec = prog->aux->security; - return cred_has_perm(current_cred(), bpfsec->sid, SECCLASS_BPF, - BPF__PROG_RUN, NULL); + return cred_tsid_has_perm(current_cred(), bpfsec->sid, SECCLASS_BPF, + BPF__PROG_RUN, NULL); } static int selinux_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, @@ -7159,16 +7159,16 @@ static int selinux_perf_event_read(struct perf_event *event) { struct perf_event_security_struct *perfsec = event->security; - return cred_has_perm(current_cred(), perfsec->sid, - SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL); + return cred_tsid_has_perm(current_cred(), perfsec->sid, + SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL); } static int selinux_perf_event_write(struct perf_event *event) { struct perf_event_security_struct *perfsec = event->security; - return cred_has_perm(current_cred(), perfsec->sid, - SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL); + return cred_tsid_has_perm(current_cred(), perfsec->sid, + SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL); } #endif @@ -7216,8 +7216,8 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd) ad.type = LSM_AUDIT_DATA_FILE; ad.u.file = file; - return cred_has_perm(current_cred(), isec->sid, - SECCLASS_IO_URING, IO_URING__CMD, &ad); + return cred_tsid_has_perm(current_cred(), isec->sid, + SECCLASS_IO_URING, IO_URING__CMD, &ad); } #endif /* CONFIG_IO_URING */ diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index e47b75819f4a..967848594270 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -158,11 +158,11 @@ int cred_self_has_perm(const struct cred *cred, u16 tclass, u32 requested, int cred_self_has_perm_noaudit(const struct cred *cred, u16 tclass, u32 requested); -int cred_has_perm(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, - struct common_audit_data *ad); +int cred_tsid_has_perm(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *ad); -int cred_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, - u32 requested, struct av_decision *avd); +int cred_tsid_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, + u32 requested, struct av_decision *avd); int cred_ssid_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, u32 requested, struct common_audit_data *ad); From patchwork Thu Jan 2 16:44:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924634 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f179.google.com (mail-qt1-f179.google.com [209.85.160.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1A980155398 for ; Thu, 2 Jan 2025 16:45:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836355; cv=none; b=FfwJds1WIqabixFej1o+iA8BNUfcTLkFdpMMPID5X5AH/l39sbYQJRCk5vgb0sqNck583AIX83HPnwmCH48tRIi3VQHu0mYYKA1Y2oD0gSGGn1gJXaA3XCaE0I8bg+an5YXXcl/7+u4h6L3pK0/SpG0A2NHp4mQnBtjqNDrAfZ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836355; c=relaxed/simple; bh=Gr6+LLWTf0EU+XQO2/lQPI8CJYWw1H5moDSgjj++l0Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NaUln0eTul7vnVx+4k71Trqldmy/+QOJWKKRvg3t38BsTWQkhqLQxgdY5gnZ8EKVx2s7WTBkQPBIgPKsVVIo+gnB4ZYR+Orxtd4kspRKD7VOLmC4TESGuPYyGbRCcJL3y08rj6f1ZNreo6MOrImkAAfvZ7z8Fm/GX32HnMJPq78= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OKmssddP; arc=none smtp.client-ip=209.85.160.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OKmssddP" Received: by mail-qt1-f179.google.com with SMTP id d75a77b69052e-468f6b3a439so99973961cf.1 for ; Thu, 02 Jan 2025 08:45:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836351; x=1736441151; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lbFXOwGTguM08dszQds876fBrzafoT6GF/aDBJs00es=; b=OKmssddP2/c7/88GF1FlQ9lPj9gNgFl9zAZJ8CvGwzAnBaVY1brCsNVBbVPC8QheGz izO8wNdaWEm41dxjL0UvQ7D7t/fOlGVy7lppQMBCNvZ4sDWCAsQjYQtp5/zkhCRyVMJJ JYkbwvDpKgtsMiMw18P3oBNkUcQvGeIxeqLoKAjAA9OBmcjjfixyuJwoN+Ry2FxyeH4z OxJlkai7rHp58pJJnvoH+aRutJyiIhyz+vdcupU4uNruobtbAGuHKPdpc7z/RpRqrLvN ZNEy90ZIY/oVgbxd4x7grygDYoQcnkDG9HASJA+S9A9orU1kWtHVYeJ8B3wLWevHe6Su wmQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836351; x=1736441151; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lbFXOwGTguM08dszQds876fBrzafoT6GF/aDBJs00es=; b=jAxlZpbOvFtApkoxvngxP3ffgEDwV3ksmXx35ftlw3MOw7SSyumiIv9vgDH0QTSZb9 1mK+AWf1lqFXRJGYb7S97YiJBR7ToehimKzMTQFagmO5RUD/teB/m66oTz0Bmu2H+2xg E2FcRQWnI81AbzP6icQEJunzzeG624x5viJWyURwiVbc5Ny3B7b8Ry39PAOBvyEMbA37 BUCjvbVrfg/EjY4k0xh6bNmLJ9RQk62Pi+CY9inee5bt+jl2jjEFqy9VaFOV2/qjBiKb RN9waUoKSQPGhfLC3QpJrNOhY137IeUJoDle9ZT0G4RamN3t9rgz8nVTe0hRBU2PM+YV 628g== X-Gm-Message-State: AOJu0YxgLdjab51Ep2R5OPWx+IT77BGHNm9qNws7gcQBVuwb5LILwmKH Q82nNKpN+Nk8hoqrdhixnktThAqdd/WNmkNPDEsj2Xc0+6NfFUUENKv0Tw== X-Gm-Gg: ASbGncsTnK+JqC1gu4Gq9tJeXTCkFm0PHb6csrPih1rJoHZv8187v/B5Jp1Y2psWwog tGkX8Hqi01sC7mjWYydYB87+05eJ9KzVsuAYcy7ll3nAWuk43w5tV7MJXwz02BEm4efgnrEfNoG Zre6zcvMvH1h0qK4eMo5INtl3dImADLzYJy2RUl+yvqi+Gue3WdbefLVzdsmytv0vubCKZ2WkOp nlm9GSNCqof3Pl9mV4R5lhvHm9VO53peaoSymsyGCVFJAtws3T7xSJN6Y3amm1IuiA0E0RW0lzY yu3lDvDqlEQoARrly3VkcoDcJ/dlGho9mMqzrJMBJ9cciXkd/hKXD9/W9T8iDxkqEijS5w== X-Google-Smtp-Source: AGHT+IEfgvg1E+AskkvPQ8T0qgoGTyrjQWgqP9DUqmEaGGAm0Mddua0X7tJjOL7D2vI8XJgw9F3svQ== X-Received: by 2002:ac8:5a48:0:b0:467:6692:c189 with SMTP id d75a77b69052e-46a4a8cdda7mr788919351cf.13.1735836351473; Thu, 02 Jan 2025 08:45:51 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.51 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:51 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 24/44] selinux: convert additional checks to cred_ssid_has_perm() Date: Thu, 2 Jan 2025 11:44:49 -0500 Message-Id: <20250102164509.25606-25-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Convert additional permission checks in the hook functions to use the namespace-aware cred_ssid_has_perm() helper function. In particular, the following hook functions are updated: selinux_socket_bind() selinux_socket_connect_helper() selinux_socket_unix_stream_connect() selinux_socket_unix_may_send() selinux_msg_queue_msgrcv() In each of these cases, the check is between two object SIDs and does not use the current cred SID. selinux_msg_queue_msgrcv() may bear revisiting since the source SID is the SID of the receiving task (not current). An alternative would be to use the receiving task's cred and the cred_tsid_has_perm() helper for these checks. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1619d5c2c187..9e09bfff8392 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4778,6 +4778,7 @@ static int selinux_socket_socketpair(struct socket *socka, static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) { + const struct cred *cred = current_cred(); struct sock *sk = sock->sk; struct sk_security_struct *sksec = selinux_sock(sk); u16 family; @@ -4859,10 +4860,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in snum, &sid); if (err) goto out; - err = avc_has_perm(current_selinux_state, - sksec->sid, sid, - sksec->sclass, - SOCKET__NAME_BIND, &ad); + err = cred_ssid_has_perm(cred, sksec->sid, + sid, sksec->sclass, + SOCKET__NAME_BIND, + &ad); if (err) goto out; } @@ -4900,9 +4901,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in else ad.u.net->v6info.saddr = addr6->sin6_addr; - err = avc_has_perm(current_selinux_state, - sksec->sid, sid, - sksec->sclass, node_perm, &ad); + err = cred_ssid_has_perm(cred, sksec->sid, sid, + sksec->sclass, node_perm, &ad); if (err) goto out; } @@ -4921,6 +4921,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in static int selinux_socket_connect_helper(struct socket *sock, struct sockaddr *address, int addrlen) { + const struct cred *cred = current_cred(); struct sock *sk = sock->sk; struct sk_security_struct *sksec = selinux_sock(sk); int err; @@ -4999,8 +5000,8 @@ static int selinux_socket_connect_helper(struct socket *sock, ad.u.net = &net; ad.u.net->dport = htons(snum); ad.u.net->family = address->sa_family; - err = avc_has_perm(current_selinux_state, - sksec->sid, sid, sksec->sclass, perm, &ad); + err = cred_ssid_has_perm(cred, sksec->sid, sid, + sksec->sclass, perm, &ad); if (err) return err; } @@ -5101,6 +5102,7 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { + const struct cred *cred = current_cred(); struct sk_security_struct *sksec_sock = selinux_sock(sock); struct sk_security_struct *sksec_other = selinux_sock(other); struct sk_security_struct *sksec_new = selinux_sock(newsk); @@ -5110,10 +5112,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, ad_net_init_from_sk(&ad, &net, other); - err = avc_has_perm(current_selinux_state, - sksec_sock->sid, sksec_other->sid, - sksec_other->sclass, - UNIX_STREAM_SOCKET__CONNECTTO, &ad); + err = cred_ssid_has_perm(cred, sksec_sock->sid, sksec_other->sid, + sksec_other->sclass, + UNIX_STREAM_SOCKET__CONNECTTO, &ad); if (err) return err; @@ -5133,6 +5134,7 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, static int selinux_socket_unix_may_send(struct socket *sock, struct socket *other) { + const struct cred *cred = current_cred(); struct sk_security_struct *ssec = selinux_sock(sock->sk); struct sk_security_struct *osec = selinux_sock(other->sk); struct common_audit_data ad; @@ -5140,9 +5142,8 @@ static int selinux_socket_unix_may_send(struct socket *sock, ad_net_init_from_sk(&ad, &net, other->sk); - return avc_has_perm(current_selinux_state, - ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, - &ad); + return cred_ssid_has_perm(cred, ssec->sid, osec->sid, osec->sclass, + SOCKET__SENDTO, &ad); } static int selinux_inet_sys_rcv_skb(struct selinux_state *state, @@ -6256,6 +6257,7 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m struct task_struct *target, long type, int mode) { + const struct cred *cred = current_cred(); struct ipc_security_struct *isec; struct msg_security_struct *msec; struct common_audit_data ad; @@ -6268,13 +6270,11 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m ad.type = LSM_AUDIT_DATA_IPC; ad.u.ipc_id = msq->key; - rc = avc_has_perm(current_selinux_state, - sid, isec->sid, - SECCLASS_MSGQ, MSGQ__READ, &ad); + rc = cred_ssid_has_perm(cred, sid, isec->sid, SECCLASS_MSGQ, + MSGQ__READ, &ad); if (!rc) - rc = avc_has_perm(current_selinux_state, - sid, msec->sid, - SECCLASS_MSG, MSG__RECEIVE, &ad); + rc = cred_ssid_has_perm(cred, sid, msec->sid, + SECCLASS_MSG, MSG__RECEIVE, &ad); return rc; } From patchwork Thu Jan 2 16:44:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924638 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f175.google.com (mail-qt1-f175.google.com [209.85.160.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E5C7715C14B for ; Thu, 2 Jan 2025 16:45:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836359; cv=none; b=OvICP3voWXi8ciWRi8DyleHrPYpjH6rbqWcIxGP8gp608iBkHJlufGkyreAvcJnFHKwH1S77xdmU4QnCxJbCoPQe+917MzmI3D0Arax4TSYfrpoABqYwy7zDksnGJk1idZp4D2/siZqRBtYgx3g2CKxIZ7S78jfmQ1iW0UpCEf0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836359; c=relaxed/simple; bh=6yABFnon6lWmAIEfDwjauDvWxlakaJ5VCIiBBNtxl/Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=WMo78kYr6UKtPFn842tz1C65+yahpYUwCH8f095TKqeN9upGxgpFT/H5bvc6CpY7f29jm+21LnWbKwmfSpPxqBJjUz7lHC7X/++2Qd2FRMF63b+c2VBBo479y5kKKuXLTBTPe9+y0YGwx3vhfTT5PhzGU8oeCPCsZaP236qsl1s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KBmm9c/M; arc=none smtp.client-ip=209.85.160.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KBmm9c/M" Received: by mail-qt1-f175.google.com with SMTP id d75a77b69052e-467b086e0easo59350691cf.1 for ; Thu, 02 Jan 2025 08:45:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836354; x=1736441154; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ueWae7UAsncssRcZaGi8g3eHnW0Xddpnc0FDay9WJEI=; b=KBmm9c/M5g3BwjSXqJVMYno4UfZ6AofD76wHMKYDRfz21D/UkX/Su8vUZUCUTSD5mv 8NzBHQ8pjOe/mMyABN/BiNYGPuFG674tN+uK9cc8ZToN2PVsM3KdDZaQ+2k2+EpP3WBb k1AfKLjRiTTktG5SVy1WbRtdV+xxjWvMUZ3LMjkOQLoCDemsuABjOoBZuQwkZ44u0jQT 9u5YQfIeawrnXMDyFnrt8uXWms3Z00Y4Q4GvZcVXwnwOiH6f7jaUEpC5bkzcjXJDoz4E YTk1NwtR5AwoI5j3cgBCeUNdTDUI766wdqeamjzpSTZj35C5F9bkggyXrAAC8+AnPx7w nY9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836354; x=1736441154; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ueWae7UAsncssRcZaGi8g3eHnW0Xddpnc0FDay9WJEI=; b=NFZq4vJVj2KKYHGHx8yggRiA9J5xoke3eoSLv/F75vzzWHUPyurRibekAETb+Ay5aT RMMG7fLSIBkIPpxRbCa7yn5855ZAbU/2TMTHF9GAvisFkRxbkKfU/ndbCqnW/13Dwqzy Tjw35H/lBR3eNn9kzyRCBdZJW0rQ8RXLAdap++MbrMK1uisGN4xDR+A+FLmprkAlVm1d Sv83dxvZQdk+B52oVpdH77Hz0gIsDEiCH8Fr8gwbyF2JGMZdmZBNfaIGSGCSrxUgu6R1 c75+Nj9lCC6FwnuV7Nd0qGDMNKRAZtuhEnQ7iA9FEHJLSlqReKv1xE3o/GxW8ly79UFc BCcQ== X-Gm-Message-State: AOJu0Yz1PBTcbCVgaCZxDFURMNtW2B5ZusYWwhrzmzI790AITBuXb510 o/9v++niCNidZlOQKcDOaQWGur5bxHlF8TQOsPCZ8NnV8PkZTy1Pu67tHQ== X-Gm-Gg: ASbGncvPgBzVx5AbLaRayscxBkq5NpGyiBL7OKGOsnwB65z/s7eS6/5ZROLWhlDL0bV 1AdDfxcPLnHxGBsmWwadIPEbdvakntks/60OBqkgAYa59YpoDKuWSESca9EP7Ix4tFC4AhgpCs2 5DbRYALKNmAdg06jFjQMTp3Pu2HPsXdS/JkeiPjVBZaLMly0GQnJLh5Q6P/1MLTL0TY9ecc9SDQ eXyDQA6vkv0R2/p1nrsXR+cXMtoWf6iL4k30+a2opBsZyGrLHSMB55q+F5HLWr0LWlAM9jtON2p NnV+KbEzhkzvQuXU/yH0KdrwLJWaGShAs5Ppe9IxkxSb5nQ7pWL08qEe9jzTy19HtLhREA== X-Google-Smtp-Source: AGHT+IGRsxlFvpWwuAs6Jsf8u4ukU0RQWawkmzwygq3OKeJPCK52xVI55nm6ot0OgOVUWv0WX97yWg== X-Received: by 2002:ac8:5754:0:b0:466:9738:22de with SMTP id d75a77b69052e-46a4a988996mr770073281cf.41.1735836352271; Thu, 02 Jan 2025 08:45:52 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.51 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:51 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 25/44] selinux: introduce selinux_state_has_perm() Date: Thu, 2 Jan 2025 11:44:50 -0500 Message-Id: <20250102164509.25606-26-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce selinux_state_has_perm() for checking permissions on a (ssid, tsid) pair for a namespace and its ancestors when there is no cred available, e.g. for the networking checks. To support selinux_state_has_perm(), introduce a creator SID field in the selinux_state structure to save the SID of the process that created the namespace, or SECINITSID_KERNEL for the initial namespace. This SID is used as the subject SID for checks in the parent namespace. Some of the checks previously converted to using cred_ssid_has_perm() may be candidates for switching to this new helper even though a cred was available in those hooks. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 37 +++++++++++++++ security/selinux/hooks.c | 72 ++++++++++++++++------------- security/selinux/include/avc.h | 4 ++ security/selinux/include/security.h | 3 +- security/selinux/selinuxfs.c | 3 +- 5 files changed, 85 insertions(+), 34 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 250d56dae487..a533385d0149 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1662,6 +1662,43 @@ int cred_other_has_perm(const struct cred *cred, const struct cred *other, return 0; } +/** + * selinux_state_has_perm - Check and audit permissions on a (ssid, tsid) pair + * @state: SELinux state + * @ssid: source security identifier + * @tsid: target security identifier + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check permissions between a source SID @ssid and a target SID @tsid for + * @state and all ancestors to determine whether the @requested permissions + * are granted, interpreting the permissions based on @tclass. + * For the ancestor checks, use the SID of the creator of the namespace + * as the source SID of the check. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + * DO NOT USE when a cred is available; use cred_*_has_perm() instead. + */ +int selinux_state_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 requested, + struct common_audit_data *ad) +{ + int rc; + + do { + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + ssid = state->creator_sid; + state = state->parent; + } while (state); + + return 0; +} + u32 avc_policy_seqno(struct selinux_state *state) { return state->avc->avc_cache.latest_notif; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9e09bfff8392..3fd787bf5cc6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5158,16 +5158,16 @@ static int selinux_inet_sys_rcv_skb(struct selinux_state *state, err = sel_netif_sid(state, ns, ifindex, &if_sid); if (err) return err; - err = avc_has_perm(state, peer_sid, if_sid, - SECCLASS_NETIF, NETIF__INGRESS, ad); + err = selinux_state_has_perm(state, peer_sid, if_sid, + SECCLASS_NETIF, NETIF__INGRESS, ad); if (err) return err; err = sel_netnode_sid(state, addrp, family, &node_sid); if (err) return err; - return avc_has_perm(state, peer_sid, node_sid, SECCLASS_NODE, - NODE__RECVFROM, ad); + return selinux_state_has_perm(state, peer_sid, node_sid, SECCLASS_NODE, + NODE__RECVFROM, ad); } static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, @@ -5187,8 +5187,9 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, return err; if (selinux_secmark_enabled()) { - err = avc_has_perm(state, sk_sid, skb->secmark, SECCLASS_PACKET, - PACKET__RECV, &ad); + err = selinux_state_has_perm(state, sk_sid, skb->secmark, + SECCLASS_PACKET, PACKET__RECV, + &ad); if (err) return err; } @@ -5248,8 +5249,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) selinux_netlbl_err(skb, family, err, 0); return err; } - err = avc_has_perm(state, sk_sid, peer_sid, SECCLASS_PEER, - PEER__RECV, &ad); + err = selinux_state_has_perm(state, sk_sid, peer_sid, + SECCLASS_PEER, PEER__RECV, &ad); if (err) { selinux_netlbl_err(skb, family, err, 0); return err; @@ -5257,8 +5258,9 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) } if (secmark_active) { - err = avc_has_perm(state, sk_sid, skb->secmark, SECCLASS_PACKET, - PACKET__RECV, &ad); + err = selinux_state_has_perm(state, sk_sid, skb->secmark, + SECCLASS_PACKET, PACKET__RECV, + &ad); if (err) return err; } @@ -5439,9 +5441,9 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, * consistency among the peer SIDs. */ ad_net_init_from_sk(&ad, &net, asoc->base.sk); - err = avc_has_perm(state, sksec->peer_sid, asoc->peer_secid, - sksec->sclass, SCTP_SOCKET__ASSOCIATION, - &ad); + err = selinux_state_has_perm(state, sksec->peer_sid, + asoc->peer_secid, sksec->sclass, + SCTP_SOCKET__ASSOCIATION, &ad); if (err) return err; } @@ -5803,8 +5805,9 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, } if (secmark_active) - if (avc_has_perm(se_state, peer_sid, skb->secmark, - SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) + if (selinux_state_has_perm(se_state, peer_sid, skb->secmark, + SECCLASS_PACKET, + PACKET__FORWARD_IN, &ad)) return NF_DROP; if (netlbl_enabled()) @@ -5885,8 +5888,9 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, return NF_DROP; if (selinux_secmark_enabled()) - if (avc_has_perm(sksec->state, sksec->sid, skb->secmark, - SECCLASS_PACKET, PACKET__SEND, &ad)) + if (selinux_state_has_perm(sksec->state, sksec->sid, + skb->secmark, SECCLASS_PACKET, + PACKET__SEND, &ad)) return NF_DROP_ERR(-ECONNREFUSED); if (selinux_xfrm_postroute_last(sksec->sid, skb, sksec->state, &ad, @@ -6012,8 +6016,8 @@ static unsigned int selinux_ip_postroute(void *priv, return NF_DROP; if (secmark_active) - if (avc_has_perm(se_state, peer_sid, skb->secmark, - SECCLASS_PACKET, secmark_perm, &ad)) + if (selinux_state_has_perm(se_state, peer_sid, skb->secmark, + SECCLASS_PACKET, secmark_perm, &ad)) return NF_DROP_ERR(-ECONNREFUSED); if (peerlbl_active) { @@ -6022,14 +6026,14 @@ static unsigned int selinux_ip_postroute(void *priv, if (sel_netif_sid(se_state, state->net, ifindex, &if_sid)) return NF_DROP; - if (avc_has_perm(se_state, peer_sid, if_sid, - SECCLASS_NETIF, NETIF__EGRESS, &ad)) + if (selinux_state_has_perm(se_state, peer_sid, if_sid, + SECCLASS_NETIF, NETIF__EGRESS, &ad)) return NF_DROP_ERR(-ECONNREFUSED); if (sel_netnode_sid(se_state, addrp, family, &node_sid)) return NF_DROP; - if (avc_has_perm(se_state, peer_sid, node_sid, - SECCLASS_NODE, NODE__SENDTO, &ad)) + if (selinux_state_has_perm(se_state, peer_sid, node_sid, + SECCLASS_NODE, NODE__SENDTO, &ad)) return NF_DROP_ERR(-ECONNREFUSED); } @@ -6912,10 +6916,10 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val) ibpkey.subnet_prefix = subnet_prefix; ibpkey.pkey = pkey_val; ad.u.ibpkey = &ibpkey; - return avc_has_perm(current_selinux_state, - sec->sid, sid, - SECCLASS_INFINIBAND_PKEY, - INFINIBAND_PKEY__ACCESS, &ad); + return selinux_state_has_perm(current_selinux_state, + sec->sid, sid, + SECCLASS_INFINIBAND_PKEY, + INFINIBAND_PKEY__ACCESS, &ad); } static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, @@ -6937,10 +6941,10 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name, ibendport.dev_name = dev_name; ibendport.port = port_num; ad.u.ibendport = &ibendport; - return avc_has_perm(current_selinux_state, - sec->sid, sid, - SECCLASS_INFINIBAND_ENDPORT, - INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad); + return selinux_state_has_perm(current_selinux_state, + sec->sid, sid, + SECCLASS_INFINIBAND_ENDPORT, + INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad); } static int selinux_ib_alloc_security(void *ib_sec) @@ -7530,6 +7534,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { static void selinux_state_free(struct work_struct *work); int selinux_state_create(struct selinux_state *parent, + u32 creator_sid, struct selinux_state **state) { struct selinux_state *newstate; @@ -7539,6 +7544,8 @@ int selinux_state_create(struct selinux_state *parent, if (!newstate) return -ENOMEM; + newstate->creator_sid = creator_sid; + refcount_set(&newstate->count, 1); INIT_WORK(&newstate->work, selinux_state_free); @@ -7584,7 +7591,8 @@ static __init int selinux_init(void) { pr_info("SELinux: Initializing.\n"); - if (selinux_state_create(NULL, &init_selinux_state)) + if (selinux_state_create(NULL, SECINITSID_KERNEL, + &init_selinux_state)) panic("SELinux: Could not create initial namespace\n"); enforcing_set(init_selinux_state, selinux_enforcing_boot); diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 967848594270..95fed265071d 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -174,6 +174,10 @@ int cred_other_has_perm(const struct cred *cred, const struct cred *other, int task_obj_has_perm(const struct task_struct *s, const struct task_struct *t, u16 tclass, u32 requested, struct common_audit_data *ad); +int selinux_state_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, + u16 tclass, u32 requested, + struct common_audit_data *ad); + u32 avc_policy_seqno(struct selinux_state *state); #define AVC_CALLBACK_GRANT 1 diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 261a6971f262..bf2d13227113 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -110,11 +110,12 @@ struct selinux_state { refcount_t count; struct work_struct work; + u32 creator_sid; /* SID of namespace creator */ } __randomize_layout; extern struct selinux_state *init_selinux_state; -int selinux_state_create(struct selinux_state *parent, +int selinux_state_create(struct selinux_state *parent, u32 creator_sid, struct selinux_state **state); void __put_selinux_state(struct selinux_state *state); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index c3308a5c168d..8c159b88615f 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -367,7 +367,8 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf, goto out; } tsec = selinux_cred(cred); - if (selinux_state_create(state, &tsec->state)) { + if (selinux_state_create(state, current_sid(), + &tsec->state)) { abort_creds(cred); length = -ENOMEM; goto out; From patchwork Thu Jan 2 16:44:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924636 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f180.google.com (mail-qt1-f180.google.com [209.85.160.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 748DB155A2F for ; Thu, 2 Jan 2025 16:45:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836356; cv=none; b=J4q7nitfTTsRW7/reJgoE1TN0kRulGG6MHRy4wBYoTJxeTHPTCwLsssUYDzwAHEe+a45JpwFh72kPPHHY8lYmzX2csCiQsvM50pBAHjdD+ETQIrXAuGJiEoygnjQgMdYE6mS5+RaXOulJX+1aQC58lEEf7GONLG2pbXNZuJJfpw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836356; c=relaxed/simple; bh=ZbS2+VccBHLtiDuM0S7nHtGMeAMZDaDEXxkyVy1DaYg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=K74TbntkH20+kLGN3GJZM5laqEtMRmN0Bl78cZ3FeiOfsgx43+RASiIqtM7T4RgvwwpWxi5iaIn0CVoZwx0Dt6w3NkCYeQZPtUxSRaPBbcMOa91psLWBGS73H0WtueoT3PkHuHNQsICgE+JvsOa5n/V9oqdjMQkh/YCw7E4No/Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nNApbCJn; arc=none smtp.client-ip=209.85.160.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nNApbCJn" Received: by mail-qt1-f180.google.com with SMTP id d75a77b69052e-46769b34cbfso171277511cf.0 for ; Thu, 02 Jan 2025 08:45:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836353; x=1736441153; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tw0Gl432QvBZ/79LUAgPlxfNl05mtmHs8WJ6hVvUgLE=; b=nNApbCJnPCw9OiO38O3gwfpCoMKJhCYTRncZl09Am6h4T3NwblDObvCAxnEcVnFlMM JT2NFr6F4oSPgP9ItpUbM+Fclt7VH66ItEZrDHG2ow61vT/hfKzeLMQjKh+6ATBHIz+3 s52oRorvI6yA4WKHxz1p6BSSx3rvT8rKBVrkldNW7eLpKF8GAuJDroOLwfWm7fMe7rrY mIn7zyW+IwbwpG6RMghRQMj5Y5P1MH9H5GXj1UdxWqD3AxLcFlP54NoIoQ/NQ0T9gEyP l3PR7rk/UB9AhrBpPsv6TgqlqSC0xrRyOBMuBidSH73UDqNYH+XCjkZFykjq+Uqcldld B/Xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836353; x=1736441153; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tw0Gl432QvBZ/79LUAgPlxfNl05mtmHs8WJ6hVvUgLE=; b=tGFXWRVxUndOYA2f3UoJaZSzQPm1CvtiuHMNfnL9eitR4qiN+Vdl5yM5+4574G280G wOZUaqgO1mFH4eliIpJ4ZbSlyLNh+DquHlII0NT72XZUFW+tWH1KhD/Gt5p+lPXN/vZ7 HHGbHgbHXHOds85e69GnfSYNZpETULiBnvtyzx8jiQq4nTZ41cHxknAM0ugN1RXRrt3L UnOrZn4wguVstZFDczk2T0qYklHgIG9qpk4n+H5f2dQGZv1S1v10OJt2RmIe8uPjh/lV xzzhuN2SYaT7Kv6/ruDBW/71od+GxZeeOxbunbhYs23aVSon+hwuym6z4a96XtaGGAK5 U3bg== X-Gm-Message-State: AOJu0YySaqRSKaZa0s/n+0GT6+7JBak2yvBhdfWnA93DUZazVQFHTpzi zALbwoMghNOVsVQDhppAZq8GiLTyB90U6hUdOz/DvTGz/XoiagEcUKmOmA== X-Gm-Gg: ASbGnctKl3PErmso4icxzUYPOM3ZnEZcQ+4rxa+Xv7scD0tftw0goUSsHhoef2Qhhkc NZKFRe+cDj5quygouvwKVPd2DYFDheqfIZS+n0IE2qbwRNPpvFOhC+Vqc1TwlIBuxeWnJrJiB/U mKEq9UqZdgZfM64GhMwmG+ZTHt/O3VFShaDCC5AJ5uRfKgMo7bEYBDRyiZx0NK54uYI1Wie2mK8 wI+vbyp+EeKJhZxABTa91SWHZOVb+wU/9LCg12j0bR1MRY5hjQMQiNpgxKuJ4dzHKETzrijxCM0 Mp3tXxe8/RGSefrfYbyzbtpOi8x8B+jetIjuGWv5cQG4KpSErIdgrG/QDebrjOwgK2jQdA== X-Google-Smtp-Source: AGHT+IHcfxxI/IAT0eB2MBjrltKe2yDP1mWx1v0j6zaZ6wzr0gIFbWCNQVITt2S3AG5j4p688TpE4g== X-Received: by 2002:ac8:7d84:0:b0:467:8630:585b with SMTP id d75a77b69052e-46a4a8dae88mr697448331cf.14.1735836352895; Thu, 02 Jan 2025 08:45:52 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.52 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:52 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 26/44] selinux: annotate selinuxfs permission checks Date: Thu, 2 Jan 2025 11:44:51 -0500 Message-Id: <20250102164509.25606-27-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Annotate the selinuxfs permission checks with comments explaining why we only check permissions against the current SELinux namespace (because these operations only read or modify the state of the current SELinux namespace). If we were instead to check permissions against ancestor namespaces, we would need to be allowed by the ancestor policies to perform the same operation in those namespaces, which would be undesirable. Signed-off-by: Stephen Smalley --- security/selinux/selinuxfs.c | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 8c159b88615f..590c883ae86d 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -171,6 +171,10 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, old_value = enforcing_enabled(state); if (new_value != old_value) { + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETENFORCE, @@ -344,6 +348,10 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf, if (*ppos != 0) return -EINVAL; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ rc = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__UNSHARE, NULL); @@ -455,6 +463,10 @@ static int sel_open_policy(struct inode *inode, struct file *filp) mutex_lock(&fsi->state->policy_mutex); + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ rc = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); @@ -517,6 +529,10 @@ static ssize_t sel_read_policy(struct file *filp, char __user *buf, struct policy_load_memory *plm = filp->private_data; int ret; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ ret = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); @@ -674,6 +690,11 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, return -EPERM; mutex_lock(&fsi->state->policy_mutex); + + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); @@ -729,6 +750,10 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) u32 sid, len; ssize_t length; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL); @@ -780,6 +805,10 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, if (fsi->state != current_selinux_state) return -EPERM; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, @@ -839,6 +868,10 @@ static ssize_t sel_write_validatetrans(struct file *file, if (state != current_selinux_state) return -EPERM; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ rc = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL); @@ -972,6 +1005,10 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) struct av_decision avd; ssize_t length; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL); @@ -1026,6 +1063,10 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) u32 len; int nargs; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, @@ -1128,6 +1169,10 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) char *newcon = NULL; u32 len; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, @@ -1193,6 +1238,10 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) " This will not be supported in the future; please update your" " userspace.\n", current->comm, current->pid); + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_USER, @@ -1258,6 +1307,10 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) char *newcon = NULL; u32 len; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, @@ -1389,6 +1442,10 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, mutex_lock(&fsi->state->policy_mutex); + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETBOOL, @@ -1448,6 +1505,10 @@ static ssize_t sel_commit_bools_write(struct file *filep, mutex_lock(&fsi->state->policy_mutex); + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ length = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETBOOL, @@ -1569,6 +1630,10 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, if (state != current_selinux_state) return -EPERM; + /* + * Only check against the current namespace because + * this operation only affects it and no others. + */ ret = avc_has_perm(current_selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETSECPARAM, From patchwork Thu Jan 2 16:44:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924637 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD4B37B3E1 for ; Thu, 2 Jan 2025 16:45:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836358; cv=none; b=gUqp+V0Iif76dlSVnWtPTV0ebWtTbNaV6gM0teblZbgAsXDAMsOApQAGMesCpJPUSpwD8El6KTruid4aFnDXsbGpQVBuYwW8SR8j+O9ZVvIWIxAL5WYFo6zRgAUeCCEWkEeiOF9S60MHqPk6tT5la2cLA3wF+vA3j4LzV6yN4lI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836358; c=relaxed/simple; bh=pLYKtOLkVEeztobOa9R9waUcezrEI3PVPPvPHuXaEII=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=SFApzNZW7OBKJsy/95OV+RpdYOIoZz4NynuzCITTFoxWBRDFqn6bLE1XwWqUKnQlMYOosZDTK4tX5qZFOOjezlA4bzSR8YxpHY4gnbl2cJCBe9fCr1CGBT0mYsYd+rcUi2MhbRkrVaYSJa7puOJupAvm2O5u99idOAP8s5XgBM4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VIJot9q2; arc=none smtp.client-ip=209.85.160.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VIJot9q2" Received: by mail-qt1-f172.google.com with SMTP id d75a77b69052e-467a17055e6so128390341cf.3 for ; Thu, 02 Jan 2025 08:45:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836354; x=1736441154; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=RuKGORPO0S6GHRdMIITTSQiI/DOvb7oakAlW6iIk5Eo=; b=VIJot9q2LHWskY8TqBXRvUsgUAERmdGUQYTRpsRiqF1aIHInvdwrki52gLDeI//Nl/ puxniMS1qiPEN0sxRD/KGF7ZOFVV6WjEKFhVH3E7dXQvessCyvykreObbSxVOVNRSPrE 6OeLrEATmAtRW+6Q99WuOO4j6zQ7dQJGdP1j/ILV7FKZtl4+h/mEGvMBJ1LbARoaib+A CsYfv3ohJ//7g7DoJwgGZHWcxfHIHF1leojMshmD0Vaq13RvCjBOpBYybuOm0rt+fn2x uqgQYeRIcbbT+1lS8IRkwsOz/Qbf6ZgiJTFglky4RSvDFsmTSG2SIwfYv9A3cyYNAS59 TTYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836354; x=1736441154; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RuKGORPO0S6GHRdMIITTSQiI/DOvb7oakAlW6iIk5Eo=; b=uthZcMeagfA2I4hvccDaIfavUM0TFZ9OBs81hX1ctfIOUm4vFiqIwho6reESQdeUH5 HuUlX9RDcW20AY1F+n00tBciOJ82xVg7V27EatRal0+/N6dvGgJQ3bF7ffsPAqqbSIGA NfHVJBKQcdHQB1RtgyDkpaRgzL7BRzJp/yv0194KGMOuXtK5fFKq2QhZujJeUGn+3w6n 2NZzYFc1i+3tqTMq8sumE29PirgIvVS9f0Y8R0YJ6D8QV6dEqx8xGZIFhqAKnrFqSUuq pFKNErsdGa791O29Q+Mvqwez4iu+Sfcv84j/hnpqCkdaCLbHIFBzyCT/okTrE4Hf+FHF /5Nw== X-Gm-Message-State: AOJu0YxDxy/o6TjdQ0uHzqMrbQj2cTwDu2wRejA/7Sj5LqCGOUTNAb0k ckzvlrdTswSw+zf0ej93+LX4D4A8flFaSTwrNodx0aZ4F0lcdTKTjNDcMg== X-Gm-Gg: ASbGncvC6SZ5uQmxx03nX+bmh9dNUbXdVJ1Fx1JOXzaKMi2rXke6GVPPslDFlve0dCI rlnlMFjLXpNiv3d4Kk0OMdYXpRMr/QoPuFrV1doQJz9ZSAht1vc0Tpqs7ySXKIlGHU5nHFAMUa+ Br8ucII6GuPnxlbeJG906x+7JztXyk0JA5+b7gjPTAFl7mvZUuAv4Q0MsBJqbmomMa+4wOiOVBH w4VBL6fwiyI4gNEl/h7pfNz3QLTdYXOBGq36F0YpRgN7NwjNnhukPQJqd6LwZXHXmxInOzpzABG o3yXJa0fvQyOGfLn1A6q6DHmJrFjNOUUq+RZYQt0Utz+N1LQesL5zy37HCmqXAu0SjIrDA== X-Google-Smtp-Source: AGHT+IE4z/CXulTefc5KPufPzDoLmQ1aNmh25HkKlBLaEKaoR8lNrxyartjkqW2lzb5GJ4QODROSUA== X-Received: by 2002:ac8:5a0a:0:b0:467:5711:bdb8 with SMTP id d75a77b69052e-46a4a9a34a6mr871558631cf.46.1735836353686; Thu, 02 Jan 2025 08:45:53 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.53 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:53 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 27/44] selinux: annotate process transition permission checks Date: Thu, 2 Jan 2025 11:44:52 -0500 Message-Id: <20250102164509.25606-28-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Annotate all process transition-related permission checks that are only performed against the current SELinux namespace and not ancestors with comments. These checks are only applied against the current namespace because the process SID only changes in the current namespace; the SID in ancestor namespaces remains unchanged. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 46 ++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3fd787bf5cc6..5730138d4eb8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2385,19 +2385,23 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) if (rc) return rc; } else { + /* Check permissions for the transition. */ /* * Only check against the current SELinux namespace * because only the SID in the current namespace * is changed by a transition. */ - - /* Check permissions for the transition. */ rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); if (rc) return rc; + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. + */ rc = avc_has_perm(current_selinux_state, new_tsec->sid, isec->sid, SECCLASS_FILE, FILE__ENTRYPOINT, &ad); @@ -2406,6 +2410,11 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) /* Check for shared state */ if (bprm->unsafe & LSM_UNSAFE_SHARE) { + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. + */ rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__SHARE, @@ -2419,6 +2428,12 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) if (bprm->unsafe & LSM_UNSAFE_PTRACE) { u32 ptsid = ptrace_parent_sid(); if (ptsid != 0) { + /* + * Only check against the current SELinux + * namespace because only the SID in the + * current namespace is changed by a + * transition. + */ rc = avc_has_perm(current_selinux_state, ptsid, new_tsec->sid, SECCLASS_PROCESS, @@ -2434,6 +2449,11 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm) /* Enable secure mode for SIDs transitions unless the noatsecure permission is granted between the two SIDs, i.e. ahp returns 0. */ + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. + */ rc = avc_has_perm(current_selinux_state, old_tsec->sid, new_tsec->sid, SECCLASS_PROCESS, PROCESS__NOATSECURE, @@ -2540,8 +2560,10 @@ static void selinux_bprm_committing_creds(const struct linux_binprm *bprm) * higher than the default soft limit for cases where the default is * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. */ - /* Only check against the current namespace because the SID - * does not change in the parent. + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. */ rc = avc_has_perm(current_selinux_state, new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, @@ -2583,8 +2605,10 @@ static void selinux_bprm_committed_creds(const struct linux_binprm *bprm) * This must occur _after_ the task SID has been updated so that any * kill done after the flush will be checked against the new SID. */ - /* Only check against the current namespace because the SID - * does not change in the parent. + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. */ rc = avc_has_perm(current_selinux_state, osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); @@ -6651,6 +6675,11 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) } /* Check permissions for the transition. */ + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. + */ error = avc_has_perm(current_selinux_state, tsec->sid, sid, SECCLASS_PROCESS, PROCESS__DYNTRANSITION, NULL); @@ -6661,6 +6690,11 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) Otherwise, leave SID unchanged and fail. */ ptsid = ptrace_parent_sid(); if (ptsid != 0) { + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by a transition. + */ error = avc_has_perm(current_selinux_state, ptsid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL); From patchwork Thu Jan 2 16:44:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924640 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qv1-f51.google.com (mail-qv1-f51.google.com [209.85.219.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B551C1547C0 for ; Thu, 2 Jan 2025 16:45:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836359; cv=none; b=MMvaDc83Cb0iEax9TfdbyExFwUbB6ko2BSHn6aOD/VksE9hW2kmtCa4g220NJwYe8w8RxGWA6DskN/Aqe9C2f3Cg+zNKiq3ylTUCXLSrqDkj31RKmbLREm1NCAI+JsfUJW49iZSW+HD0ruGaZmDFcF2arsOJET5IfLiTV0TZMLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836359; c=relaxed/simple; bh=VIgkTQn0xV7x2gTfMKwPNCh4kXpuTR0cCqL0zdcMSgI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DYtRZu/cmMf3VfgydEyFshal+5uNJnCMozkKfX4sPE6XKSCdCnlOFjrm0F8/xVPPXz8/rTeStkMxf6ZGL40dYfHrk0k5kJPMn6cav6D0WIyIA3nzkZd9Jj5AIPA5PhqtwqyqnC9om1qGXxp2QOk75gG3e57R4Hel0/h+h3y7Z/w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Aft3odXo; arc=none smtp.client-ip=209.85.219.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Aft3odXo" Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-6dd43b08674so73839536d6.3 for ; Thu, 02 Jan 2025 08:45:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836354; x=1736441154; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MSH6OXioNwnoY/0Lz5QCJEkuvXAEGypy3/AMiwEK00M=; b=Aft3odXorlNvgIXOVFv4Ip3lX66yD7RumWXylN3nuFQSUhBDWv5+BaqTZGMIGiFXlq toqAVEDNgl+d+rByiy24CV3GdgQn8or+nJf6dNATYGVdfv75ic9dGJs1stNsaHOiwkrE /BqanYvTN3bzmsQWfCZmoIk+BjD8i0yw2v3F/SNHnk9VTr3AJpGtCgr2j56bfc4Dremj 2nRRBHKljBkxOTFixdAbVNAZYsMJ0kYx4OF3MTzCAG7BUUhmpUs9WK/fpK4BIXoxqWCZ Bl6mS4/Vp6a3bjbn4u3aPPA1ZMyMbMOScJSdayp471aFIL5PEB3+1cBVHsPjAVfwaANB sK8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836354; x=1736441154; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MSH6OXioNwnoY/0Lz5QCJEkuvXAEGypy3/AMiwEK00M=; b=mv2FNJQHam1CR9i1xs0g5QDqwDYT6uaMrMw2Vpd3CJgLTscmBTOyBJ4SzpebXpzGP6 2w1iavq7c7qU5hoSxjXpegq3+dCIIEYe7VVGB8S1k2zuabb4m0Z7ffVrJPKc4Bwz5uWY bGd0q8V+3QnYO6XnaqoamYc4oNpL3uQ+OBgk4uxO7Jx/B4FS5UtytnjQKGMzXxEZQn2x nSJEIi8jaQmeRh1mpJwiGQE3jcjirFYwuJUZD7nQ8RjQnC3hrbd44PMDyUNw8gQRt3NE NG+sgdBwFTi0ZgvI0AilPmlDL7Cw5441b+7cBxatBfhh3kMKjtIKdm4OowCcGzEa4Ltk P0YA== X-Gm-Message-State: AOJu0Yz7bt870rg9nVp+g2XTpHv0uZkQqDABg03oNCPINIYJ8u7mTzks s3ESgFmxEZRyvzFvJ+J2tTEIr6bewkwPoe4qYUCewFdEa9QxwGRsY616pg== X-Gm-Gg: ASbGnculQS1NchbMlWzPOQCCyhdwoSpdKZH8JM1qvV7yy67IwlDH0yFi4fki0G+vkRN /YofDyRyYZg/hJD7qufxoSJtm7LTSI1Fc/+AEPQteiG7hE72KLotCF8oarmA9GUocUkps0VuERp U2oPlsc9CEKq8wwkguD8AEXfbkCOm1gYQP41B+a0Hy04S61k3jfbA0n9jpRLCq0vpra6wCCePW+ KU4TOu1lm5mJX97QG0ZXtSbI7qcyjGaRUJ05MoKJDBigh7MIuN3rx/td62cZideYxQpctyYxKa7 zpsS0xJ2ZQignynA4l/eUoi5DxuSRHehzhmCwWi2cxrkOYfwgL1WtnYlGMBkySDj1aApHA== X-Google-Smtp-Source: AGHT+IGIl5nI2ch3XyG0iNf0jQzb9/9Y/dsYbnBCqQO8q+0by1yFo+hzPmc/u/9wVx0vyRpdF6RB/Q== X-Received: by 2002:a05:6214:76f:b0:6d8:af37:ae5b with SMTP id 6a1803df08f44-6dd233acca7mr739055116d6.43.1735836354279; Thu, 02 Jan 2025 08:45:54 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.53 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:53 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 28/44] selinux: convert xfrm and netlabel permission checks Date: Thu, 2 Jan 2025 11:44:53 -0500 Message-Id: <20250102164509.25606-29-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Convert the xfrm and netlabel permission checks to use the appropriate namespace-aware helper for each check. When in process context, use cred_tsid_has_perm() to check permission; when not in process context, use selinux_state_has_perm(). Signed-off-by: Stephen Smalley --- security/selinux/netlabel.c | 6 +++--- security/selinux/xfrm.c | 33 ++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 9c360f2ee7fc..06ce45f628f8 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -137,7 +137,7 @@ void selinux_netlbl_cache_invalidate(void) * @gateway: true if host is acting as a gateway, false otherwise * * Description: - * When a packet is dropped due to a call to avc_has_perm() pass the error + * When a packet is dropped due to a permission denial, pass the error * code to the NetLabel subsystem so any protocol specific processing can be * done. This is safe to call even if you are unsure if NetLabel labeling is * present on the packet, NetLabel is smart enough to only act when it should. @@ -478,8 +478,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, perm = RAWIP_SOCKET__RECVFROM; } - rc = avc_has_perm(sksec->state, sksec->sid, nlbl_sid, sksec->sclass, - perm, ad); + rc = selinux_state_has_perm(sksec->state, sksec->sid, nlbl_sid, + sksec->sclass, perm, ad); if (rc == 0) return 0; diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 855f77630bdb..be91a28ab47b 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -102,9 +102,9 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, if (rc) goto err; - rc = avc_has_perm(current_selinux_state, - current_sid(), ctx->ctx_sid, - SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); + rc = cred_tsid_has_perm(current_cred(), ctx->ctx_sid, + SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, + NULL); if (rc) goto err; @@ -137,10 +137,9 @@ static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx) if (!ctx) return 0; - return avc_has_perm(current_selinux_state, - current_sid(), ctx->ctx_sid, - SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, - NULL); + return cred_tsid_has_perm(current_cred(), ctx->ctx_sid, + SECCLASS_ASSOCIATION, + ASSOCIATION__SETCONTEXT, NULL); } /* @@ -162,8 +161,9 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) if (!selinux_authorizable_ctx(ctx)) return -EINVAL; - rc = avc_has_perm(state, fl_secid, ctx->ctx_sid, - SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL); + rc = selinux_state_has_perm(state, fl_secid, ctx->ctx_sid, + SECCLASS_ASSOCIATION, + ASSOCIATION__POLMATCH, NULL); return (rc == -EACCES ? -ESRCH : rc); } @@ -205,8 +205,9 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, /* We don't need a separate SA Vs. policy polmatch check since the SA * is now of the same label as the flow and a flow Vs. policy polmatch * check had already happened in selinux_xfrm_policy_lookup() above. */ - return (avc_has_perm(state, flic_sid, state_sid, SECCLASS_ASSOCIATION, - ASSOCIATION__SENDTO, NULL) ? 0 : 1); + return (selinux_state_has_perm(state, flic_sid, state_sid, + SECCLASS_ASSOCIATION, + ASSOCIATION__SENDTO, NULL) ? 0 : 1); } static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) @@ -425,8 +426,9 @@ int selinux_xfrm_sock_rcv_skb(struct sk_security_struct *sksec, struct sk_buff * /* This check even when there's no association involved is intended, * according to Trent Jaeger, to make sure a process can't engage in * non-IPsec communication unless explicitly allowed by policy. */ - return avc_has_perm(sksec->state, sk_sid, peer_sid, - SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad); + return selinux_state_has_perm(sksec->state, sk_sid, peer_sid, + SECCLASS_ASSOCIATION, + ASSOCIATION__RECVFROM, ad); } /* @@ -469,6 +471,7 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, /* This check even when there's no association involved is intended, * according to Trent Jaeger, to make sure a process can't engage in * non-IPsec communication unless explicitly allowed by policy. */ - return avc_has_perm(state, sk_sid, SECINITSID_UNLABELED, - SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad); + return selinux_state_has_perm(state, sk_sid, SECINITSID_UNLABELED, + SECCLASS_ASSOCIATION, + ASSOCIATION__SENDTO, ad); } From patchwork Thu Jan 2 16:44:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924639 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f181.google.com (mail-qk1-f181.google.com [209.85.222.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 69DA714F9F7 for ; Thu, 2 Jan 2025 16:45:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836360; cv=none; b=shf+ASuee0q8JibfOOG/Q/g1ResoMFJBr1wAf8wJHkansq2j2oPLS/AVSBgLa7b3WHQzJ1Xtz7z7ycTRGdN+qrH5JgFUVVikn8cTWFQsRy09XR279n3wyuu10WwBlCsOGavUUIJCaNwfQ1r06Wu/8CzkJ8qseGD4C3gBnDpdeRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836360; c=relaxed/simple; bh=ciA55Er2WCBV42DsQ/CCKkGVWYkwO0k0AVId9Y14xAw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jv5DDx2gKCJgl72Es20vvnd4QNK9dCFe7L9s2ka9bv2yiob092h97v7wheOyzLuT93JS3Z5yNRFWAOf5pINNq4nU4X4k7GWwLn2UvhsE/5e5xCA3pQGQk19ZhuOKk7G+vItBFl/kERIhfi77GrWAdSQMfT4VHQuTz1Qo9ZFqb9k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=lUe+XzNX; arc=none smtp.client-ip=209.85.222.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lUe+XzNX" Received: by mail-qk1-f181.google.com with SMTP id af79cd13be357-7b6ff72ba5aso946803985a.1 for ; Thu, 02 Jan 2025 08:45:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836355; x=1736441155; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7iS2JKJ/kLXdoj5LJgkhhamyl48FBR8NUfIx1FZgTPE=; b=lUe+XzNX+SmNi3XCmwLPmweqQ6OmjlomHpmEFVcfkD8JBiezCjL8BNovAd77X7Mn+Q RsubqmqSaEItVTzd8z6uGrA6w030YXqPmi4T58onJJcFuFFZW1Xh4To+rr1AOPSGCkf5 iSClu85OHTLgH/X5GkKahdgB/rmYiWmIjuRmbsP5zrArM0JEmdvJ8LxC5W91Z1CS9vvb LJr5NPLGSaj2ctUk317RNaRup5sx09XOZNSjYFZUcdpCvN+7L4FtnPYzgHdbavqfgJU4 qUCKF6UY9m5mpZhAlXrgkGKnSSQdXJVr3HNwAzlG1VxWET1OGiCKS51mjwppil9reg5Z wmMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836355; x=1736441155; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7iS2JKJ/kLXdoj5LJgkhhamyl48FBR8NUfIx1FZgTPE=; b=UERLYyAP/nk01xnUVYLJC2WCs/BHCtr7Yl3weKCpwCwquU7ZBSimKctAwItwYpxgsG uqOKnVtN4Vpboo6aO6NnAK2vvQSZ2KujUHNleHUyMWwDkDRmhzIsHSi+yZX46PXFu7yo 8tHfiwm45c8LT2+NHJm5jbrtKvlqR8cawPlt69I5Lui7bIiMgbY7trhiDo2g/THonvXi Fh1pKvreq1PdkNNpNztH5Kw2byOQpF9psG2CO/HtW4BWPo9NqVrVhpXTlHB9PIGD4XRR XcKTvBkwmEoIJgYeCRvMT0cmwWNw/qvkfVAGljWBcouyZbpCnbVyEJYG8y7zR89XMO1W BFuA== X-Gm-Message-State: AOJu0YyMAQGl/1KjNetwJfFwoKMUbU7nv1xDjtdRtCKF2rCeAz7rH1Fl Y09vw7Op8+M6TLh+LCB1FlEYMz6hHXDszBj/Z53zkabNVnrZ+0mSm2V9Fg== X-Gm-Gg: ASbGncswbCxP8vgywDG37m2StG1uXC/T8djroQ0TJ1OiPjWnv/jf6yuLs8W7wmZ+wRB 9jfsiL28iSj4De9X/JMe63Pye3v1I5LteMfUZYbGSHkPj+Gs4K6SwJzYXwyRXIWRcqTZg6QIpe6 6mLfpLs2oZ2I40FHSGRNAELyiiJktTgMr6lyju+VYDASOFl1v25syxXf5dJD5/JTQI4q5J08iKL N0GFDYDswIobqSAY3eajE2jNbiSBDVKckOL7p5r6H+AFT5AGVTYpInXxYFx+Jv6I/jq8RDOTym7 hMOduCkTBGJvyE2h78fxDvZGsV+eiZaCuSoH31d6htrDcLoqLJMhOjrXvo37ntw7+I5TOw== X-Google-Smtp-Source: AGHT+IFz5usn++utfgGPhO9gq1mk/9/5QjFeW4ctKLdRoF13OqOyrbZp+OybEjHa+btTtZmlLJsUew== X-Received: by 2002:a05:620a:4452:b0:7b6:785e:ce1a with SMTP id af79cd13be357-7b9ba7168afmr6610831285a.4.1735836355333; Thu, 02 Jan 2025 08:45:55 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.54 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:54 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 29/44] selinux: switch selinux_lsm_setattr() checks to current namespace Date: Thu, 2 Jan 2025 11:44:54 -0500 Message-Id: <20250102164509.25606-30-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Switch the selinux_lsm_setattr() checks to only check against the current SELinux namespace because this operation only changes the SID in the current namespace. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 44 ++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5730138d4eb8..d9a1d2e075a8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6560,35 +6560,41 @@ static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, static int selinux_lsm_setattr(u64 attr, void *value, size_t size) { const struct cred *cred = current_cred(); + struct selinux_state *state = current_selinux_state; struct task_security_struct *tsec; struct cred *new; - u32 sid = 0, ptsid; + u32 mysid = current_sid(), sid = 0, ptsid; int error; char *str = value; /* * Basic control over ability to set these attributes at all. */ + /* + * Only check against the current SELinux namespace + * because only the SID in the current namespace + * is changed by this operation. + */ switch (attr) { case LSM_ATTR_EXEC: - error = cred_self_has_perm(cred, SECCLASS_PROCESS, - PROCESS__SETEXEC, NULL); + error = avc_has_perm(state, mysid, mysid, SECCLASS_PROCESS, + PROCESS__SETEXEC, NULL); break; case LSM_ATTR_FSCREATE: - error = cred_self_has_perm(cred, SECCLASS_PROCESS, - PROCESS__SETFSCREATE, NULL); + error = avc_has_perm(state, mysid, mysid, SECCLASS_PROCESS, + PROCESS__SETFSCREATE, NULL); break; case LSM_ATTR_KEYCREATE: - error = cred_self_has_perm(cred, SECCLASS_PROCESS, - PROCESS__SETKEYCREATE, NULL); + error = avc_has_perm(state, mysid, mysid, SECCLASS_PROCESS, + PROCESS__SETKEYCREATE, NULL); break; case LSM_ATTR_SOCKCREATE: - error = cred_self_has_perm(cred, SECCLASS_PROCESS, - PROCESS__SETSOCKCREATE, NULL); + error = avc_has_perm(state, mysid, mysid, SECCLASS_PROCESS, + PROCESS__SETSOCKCREATE, NULL); break; case LSM_ATTR_CURRENT: - error = cred_self_has_perm(cred, SECCLASS_PROCESS, - PROCESS__SETCURRENT, NULL); + error = avc_has_perm(state, mysid, mysid, SECCLASS_PROCESS, + PROCESS__SETCURRENT, NULL); break; default: error = -EOPNOTSUPP; @@ -6603,7 +6609,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) str[size-1] = 0; size--; } - error = security_context_to_sid(current_selinux_state, value, size, + error = security_context_to_sid(state, value, size, &sid, GFP_KERNEL); if (error == -EINVAL && attr == LSM_ATTR_FSCREATE) { if (!has_cap_mac_admin(true)) { @@ -6629,9 +6635,8 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) return error; } - error = security_context_to_sid_force( - current_selinux_state, - value, size, &sid); + error = security_context_to_sid_force(state, value, + size, &sid); } if (error) return error; @@ -6668,7 +6673,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) goto abort_change; if (!current_is_single_threaded()) { - error = security_bounded_transition(current_selinux_state, + error = security_bounded_transition(state, tsec->sid, sid); if (error) goto abort_change; @@ -6680,8 +6685,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) * because only the SID in the current namespace * is changed by a transition. */ - error = avc_has_perm(current_selinux_state, - tsec->sid, sid, SECCLASS_PROCESS, + error = avc_has_perm(state, tsec->sid, sid, SECCLASS_PROCESS, PROCESS__DYNTRANSITION, NULL); if (error) goto abort_change; @@ -6695,8 +6699,8 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) * because only the SID in the current namespace * is changed by a transition. */ - error = avc_has_perm(current_selinux_state, - ptsid, sid, SECCLASS_PROCESS, + error = avc_has_perm(state, ptsid, sid, + SECCLASS_PROCESS, PROCESS__PTRACE, NULL); if (error) goto abort_change; From patchwork Thu Jan 2 16:44:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924642 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7EA5515666D for ; Thu, 2 Jan 2025 16:45:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836360; cv=none; b=lTHfzTIzgCMP1MmIMies4WNa3hhHD4oEHBINGFxlUs5ZyAl/cl1QxVpBgYFsj28iTLA87m6njhECcs4rRtWkX6/Xh/aQ03bNl7R8zrC5OoiZwZNzaoJPA2U20GZcx0P1iw2VCWnsYKKV8djp4kd6Ma6i+EKGpS8iv/7dgwMLqDM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836360; c=relaxed/simple; bh=tnt+dYF9+EbojKI/nhUuYqtuYU/Q2ehcJ32yJ/WCgZc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UjOVGsysSXl4Isg6gVWb1kZFYFulwC/LQm9nXyvKodfP+7Jgeg1FxLDECt1/3DZkhMwlQnpzsdZ4a2dwW8Tc9KKPg/4BHo1yeAEQ3xqFMMvNVVhIG4q7VvIiT9Pw7aaJ9AO8ENoiDPsazOnuNblZQV5Em9tiLXFVBw9PZbfyURk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Z8/74Tqy; arc=none smtp.client-ip=209.85.160.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Z8/74Tqy" Received: by mail-qt1-f172.google.com with SMTP id d75a77b69052e-468f6b3a439so99974571cf.1 for ; Thu, 02 Jan 2025 08:45:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836356; x=1736441156; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Tgwr+4gxBk66JtaER6US6NxWymV//BwWwTpMKaSgKoU=; b=Z8/74TqyFGCR1DXzrwFw5DdMwbHzAQXm1znUrpT6GI+RREb8Ux4YdP72BpWTKPIOc9 gEWiVewH5Ugb1Zq3y84peXJ80EXAA3srvdy5hQTVo7JQbdHOUBULUJhg9fG2y43yvMBK li9jeMyjF+YHEhcXUTR3hPLFUS/y1i6K77e7gmHlG/KOH8IIma2B4iqLEENxuE8GFs8R jqx/C1431cC5OHQq7gpSEXJC9Hg3Fhk4aUfUjfcYWd2Rh00Jz+BpRgf0Sb1A9mAhoO/3 k1YLMEsFM4GRpHg7CPhZ6i39c0VgmeIipumKVUqscuyLIkF5FVAQtw2V2q/6/S0KXzbq Yj6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836356; x=1736441156; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Tgwr+4gxBk66JtaER6US6NxWymV//BwWwTpMKaSgKoU=; b=YTAwThIbKDF0/KaMLT3svAsuc8k4XqSTBTPyFzU0Sly5eqK75C5fYsuAD0QKTITScQ L19+Updy8bVnvezcjnldVFs4UJPwQ/xtr6j/JQHIwJ1Zf3H+GijrpDYQBbJ35nEF4TgE Ei36HyKxAVps0ry6vQ7m3my3MYZIzdPPgkLBOFB0ovvK8FpLdmAyHZItQ9Glil47v9Cr HcZBDVlMxTFRgWDW00S/SFJCF3k/QePKK5DLlZHo+I0nhLYfMf3TP7zFOa5XU508xch9 nbW45l2MOUjS4UFWq+IFtfAyT9nE3exUlkzdv3KWxZK3923vbL1WM+pjeSDTvfAqvU8a L+9Q== X-Gm-Message-State: AOJu0YzOMz5taqTQH5dNTpm5dkavoq5WZh3ci0m9mvTlDI8TglU+ljq0 mB/w0nzhxDCa1LGwDwOCi07zlQ3gW8OFLSWpMLNh/K0f5SRi2J5lQsGUNA== X-Gm-Gg: ASbGncvK7lhvzT3iH34XWVDOvFmKb/xK3sUfkRi8fxT+s3hB4HVNv8ZSwC23SMcBHHu CsPpAn0dIJ8+t4fZt0CHjIGsRc/ZUuXS3KQwIh6Q9Jiozfig+5TvpOfoFLpzFLCb7QHKraLELel EQtS0Eb6LHrpDVhF2UckB7uYpnnLlY1KoPiYkFU6TtanQQM3S1H5i89FVo4JVqlJVwxyl4HcLQX u5E5lN/PTP3YStYqAlaKlszj9zqDqejfWDqVJdiGDkaR3ypx3e5kN9N64jj+lyfNDzIzdjIFIU5 KJnCsIiWgm2xBOeswJIql4lLNgOl7gM2bnDCJ8xNLDbP0JXSfmErChTm0H0Pm0j1wONkTA== X-Google-Smtp-Source: AGHT+IFZGBKouJkfNLlLDgyaYBzB/5LNDNR6bNZWc9x5TL2Cm5Ui+b6+X5kTJmLyWM55enY35gm1sw== X-Received: by 2002:ac8:5a95:0:b0:467:51d7:e15 with SMTP id d75a77b69052e-46a4a8b8697mr762823341cf.7.1735836356077; Thu, 02 Jan 2025 08:45:56 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.55 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:55 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 30/44] selinux: add limits for SELinux namespaces Date: Thu, 2 Jan 2025 11:44:55 -0500 Message-Id: <20250102164509.25606-31-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add maxns and maxnsdepth limits for SELinux namespaces to enable control over the max number of SELinux namespaces and the max depth to which one can nest SELinux namespaces. Provide Kconfig options to control the default values for both limits, and allow them to be overridden via selinuxfs in the init SELinux namespace only. Signed-off-by: Stephen Smalley --- security/selinux/Kconfig | 18 ++++ security/selinux/hooks.c | 18 +++- security/selinux/include/classmap.h | 2 +- security/selinux/include/security.h | 2 + security/selinux/selinuxfs.c | 129 ++++++++++++++++++++++++++++ 5 files changed, 167 insertions(+), 2 deletions(-) diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 61abc1e094a8..82db54462253 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -87,3 +87,21 @@ config SECURITY_SELINUX_DEBUG echo -n 'file "security/selinux/*" +p' > \ /proc/dynamic_debug/control + +config SECURITY_SELINUX_MAXNS + int "SELinux default maximum number of namespaces" + depends on SECURITY_SELINUX + range 0 65535 + default 65535 + help + This option sets the default maximum number of SELinux namespaces. + The value may be viewed or modified via /sys/fs/selinux/maxns. + +config SECURITY_SELINUX_MAXNSDEPTH + int "SELinux default maximum depth of namespaces" + depends on SECURITY_SELINUX + range 0 32 + default 32 + help + This option sets the default maximum depth of SELinux namespaces. + The value may be viewed or modified via /sys/fs/selinux/maxnsdepth. diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d9a1d2e075a8..3bf4428ccfca 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7571,6 +7571,11 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { static void selinux_state_free(struct work_struct *work); +unsigned int selinux_maxns = CONFIG_SECURITY_SELINUX_MAXNS; +unsigned int selinux_maxnsdepth = CONFIG_SECURITY_SELINUX_MAXNSDEPTH; + +static atomic_t selinux_nsnum = ATOMIC_INIT(0); + int selinux_state_create(struct selinux_state *parent, u32 creator_sid, struct selinux_state **state) @@ -7578,6 +7583,12 @@ int selinux_state_create(struct selinux_state *parent, struct selinux_state *newstate; int rc; + if (atomic_read(&selinux_nsnum) >= selinux_maxns) + return -ENOSPC; + + if (parent && parent->depth >= selinux_maxnsdepth) + return -ENOSPC; + newstate = kzalloc(sizeof(*newstate), GFP_KERNEL); if (!newstate) return -ENOMEM; @@ -7594,8 +7605,12 @@ int selinux_state_create(struct selinux_state *parent, if (rc) goto err; - if (parent) + if (parent) { newstate->parent = get_selinux_state(parent); + newstate->depth = parent->depth + 1; + } + + atomic_inc(&selinux_nsnum); *state = newstate; return 0; @@ -7615,6 +7630,7 @@ static void selinux_state_free(struct work_struct *work) __free_page(state->status_page); selinux_policy_free(state->policy); selinux_avc_free(state->avc); + atomic_dec(&selinux_nsnum); kfree(state); state = parent; } while (state && refcount_dec_and_test(&state->count)); diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 84285fba2c06..425cd18a1fa8 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -50,7 +50,7 @@ const struct security_class_mapping secclass_map[] = { { "compute_av", "compute_create", "compute_member", "check_context", "load_policy", "compute_relabel", "compute_user", "setenforce", "setbool", "setsecparam", "setcheckreqprot", "read_policy", - "validate_trans", "unshare", NULL } }, + "validate_trans", "unshare", "setmaxns", "setmaxnsdepth", NULL } }, { "process", { "fork", "transition", "sigchld", "sigkill", "sigstop", "signull", "signal", "ptrace", diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index bf2d13227113..830f890b4cb9 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -111,10 +111,12 @@ struct selinux_state { refcount_t count; struct work_struct work; u32 creator_sid; /* SID of namespace creator */ + unsigned short depth; } __randomize_layout; extern struct selinux_state *init_selinux_state; +extern unsigned int selinux_maxns, selinux_maxnsdepth; int selinux_state_create(struct selinux_state *parent, u32 creator_sid, struct selinux_state **state); void __put_selinux_state(struct selinux_state *state); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 590c883ae86d..7a0947dece69 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -66,6 +66,8 @@ enum sel_inos { SEL_POLICY, /* allow userspace to read the in kernel policy */ SEL_VALIDATE_TRANS, /* compute validatetrans decision */ SEL_UNSHARE, /* unshare selinux namespace */ + SEL_MAXNS, /* maximum number of SELinux namespaces */ + SEL_MAXNSDEPTH, /* maximum depth of SELinux namespaces */ SEL_INO_NEXT, /* The next inode number to use */ }; @@ -399,6 +401,131 @@ static const struct file_operations sel_unshare_ops = { .llseek = generic_file_llseek, }; +static ssize_t sel_read_maxns(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + char tmpbuf[TMPBUFLEN]; + ssize_t length; + + length = scnprintf(tmpbuf, TMPBUFLEN, "%u", selinux_maxns); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); +} + + +static ssize_t sel_write_maxns(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) + +{ + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; + char *page = NULL; + ssize_t length; + + /* + * Only permit setting from the init SELinux namespace, and only + * on the init SELinux namespace. + */ + if (current_selinux_state != init_selinux_state || + state != init_selinux_state) + return -EPERM; + + length = avc_has_perm(current_selinux_state, + current_sid(), SECINITSID_SECURITY, + SECCLASS_SECURITY, SECURITY__SETMAXNS, + NULL); + if (length) + return length; + + if (count >= PAGE_SIZE) + return -ENOMEM; + + /* No partial writes. */ + if (*ppos != 0) + return -EINVAL; + + page = memdup_user_nul(buf, count); + if (IS_ERR(page)) + return PTR_ERR(page); + + length = kstrtouint(page, 0, &selinux_maxns); + if (length) + goto out; + + length = count; +out: + kfree(page); + return length; +} + +static const struct file_operations sel_maxns_ops = { + .read = sel_read_maxns, + .write = sel_write_maxns, + .llseek = generic_file_llseek, +}; + +static ssize_t sel_read_maxnsdepth(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + char tmpbuf[TMPBUFLEN]; + ssize_t length; + + length = scnprintf(tmpbuf, TMPBUFLEN, "%u", selinux_maxnsdepth); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); +} + + +static ssize_t sel_write_maxnsdepth(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) + +{ + struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_state *state = fsi->state; + char *page = NULL; + ssize_t length; + + /* + * Only permit setting from the init SELinux namespace, and only + * on the init SELinux namespace. + */ + if (current_selinux_state != init_selinux_state || + state != init_selinux_state) + return -EPERM; + + length = avc_has_perm(current_selinux_state, + current_sid(), SECINITSID_SECURITY, + SECCLASS_SECURITY, SECURITY__SETMAXNSDEPTH, + NULL); + if (length) + return length; + + if (count >= PAGE_SIZE) + return -ENOMEM; + + /* No partial writes. */ + if (*ppos != 0) + return -EINVAL; + + page = memdup_user_nul(buf, count); + if (IS_ERR(page)) + return PTR_ERR(page); + + length = kstrtouint(page, 0, &selinux_maxnsdepth); + if (length) + goto out; + + length = count; +out: + kfree(page); + return length; +} + +static const struct file_operations sel_maxnsdepth_ops = { + .read = sel_read_maxnsdepth, + .write = sel_write_maxnsdepth, + .llseek = generic_file_llseek, +}; + + static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { @@ -2213,6 +2340,8 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc) [SEL_VALIDATE_TRANS] = {"validatetrans", &sel_transition_ops, S_IWUGO}, [SEL_UNSHARE] = {"unshare", &sel_unshare_ops, 0200}, + [SEL_MAXNS] = {"maxns", &sel_maxns_ops, 0600}, + [SEL_MAXNSDEPTH] = {"maxnsdepth", &sel_maxnsdepth_ops, 0600}, /* last one */ {""} }; From patchwork Thu Jan 2 16:44:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924641 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f182.google.com (mail-qt1-f182.google.com [209.85.160.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49847155A2F for ; Thu, 2 Jan 2025 16:45:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836360; cv=none; b=SdCuvs/hq+mOTFkOpo0l9uPT6yoOKr7sMgiNbSDvShCNBFGjwXOEiVijObPKuLKVh+tHTbGSZ22BMVhrVvPQXcaKEKBbmjbyjuQkys/KVOhtETJ2zLvdmcKjPq21O6CKHQWMqe5OmjtAZDWvli3NBEhndd7VFRfPxmGEYKrpDqU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836360; c=relaxed/simple; bh=B6+7Qlc+O4cbq//MdkQnEY1Z4rS49iki39lm94+XHtM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ivu9vfdtm2I7RWibvjdkuEUhTEDtAHrPWUo3QI0BgRVvB3uIPPABr1PUdApYOEogt5aQp31bJm3WJXQfla/KU6pKfWA4bQcIBscWtyqUGDsvrAk/hz59bgDyT+nkmvQSaLTAArY4q6LPOXRkFrsKap8JCOuCjGCkU+JZU1HdW6U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=m9yomZeD; arc=none smtp.client-ip=209.85.160.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="m9yomZeD" Received: by mail-qt1-f182.google.com with SMTP id d75a77b69052e-467a3c85e11so72363961cf.2 for ; Thu, 02 Jan 2025 08:45:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836356; x=1736441156; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fc67pef3KugB2832iY3lGROTmy7a72TTDa40iH9SJBk=; b=m9yomZeDlJJBD7j31qg+r4eKkSPgyxhbtSQoawGu55IBtyb1ojfqqme7kBloc62hF3 x1DSm7OaGEp+W72U6OQFbklokdrqKMkuKi2BRShbWaTSc5YA9zrl3pUeBHMd3ZCMmxyd 3cZmd7qKI+e/CdV8rlqNZ3Yc5txBIfZa3jropfqiGb6lHb805pUBut8PYiOcXHcUuRng MIOHpepPDfEY7hRjS3Hwb9NbxU6Cjijh1ITHKY+uSLhrCmG8/dNYTCZHr5IMniYP5J5m hwNWBwtDSYRh0ZpVNQ4vCoZ+lmgyWrEi52SMUc5sJJLyBwBEXJr2Qvbb+VYhjVeoiRYq HuCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836356; x=1736441156; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fc67pef3KugB2832iY3lGROTmy7a72TTDa40iH9SJBk=; b=F+VJBIZFgdjJivZEhT8von9MMJeKaFxeNKKS8Tds21L4DK6EUlmgavef+bLGhwDoGd LLCMp4hZpqMgSFeEhOQg/puAZKHhtuQELDvigmpGoCMuhvfbIWgRJKVGJA+lhNlc6EUW AINZFN/z8s19/GkFzNx9K4pJaHruMYNblYxD9kRE1K2EMwYmZY4wAFp1dIqXlXu3uuyO NFiA6FPVNAUgd8YhQeoK2J21fVkmV+9iZS63VFiW/hj1hGgfSnRbrjXPnBLNj9gNv3LC fSzoeFfLomCXuFr6jlesZ/96w8Fns4d2Ig+bPvrteFmrtJcW7ok+uL4ttvUY/kg0Vytd zjEg== X-Gm-Message-State: AOJu0YyH+E5UX4Q4jMU00w63eRRa2BGQZeZF9Zwo1fXaHINdPxZab08p F0bRsj8EE5R9lvljjhQda6pEzzmniRTvd/Ui9y0gYgkoVZjXhPkecHqoEw== X-Gm-Gg: ASbGnctg4y+/1Lc7MUxSqREPseKVnkHuotjR/ksMqscvDFVEZqUllzWqUIDUsM8PVA2 DqHvD08FrsguBNtQ9b4QmwsFkSywOxbBW0Avqkt3la0L+T/wYvAY110Wt8cTAJK4t5hM6C3dGAY cSBp0ghNnvgKelcH4I+dajqOC800fK8ou+DZBFwKd9zMLaKZKtzK+Z/dHesT/2dU6/a9Lfi6PKF LOTL9INy1GHlLDwb/4nYlvs21kZjFRhX5gP5dxiiZ88WAA44xWTasYGQ5l+cddSWnNLQ4yj9nHS QtCuPwtcUfeIZsF7cR3fGOyxQo0736yMzUxaIK6JaosWb5Zavi4K585xmKP/tDaFzFGGJA== X-Google-Smtp-Source: AGHT+IETJogixn+uDooQ3dtjxMKfRw/KYRWEUBnz4EcKkm4DKDq7zAHZsf/Xt50fm7NYWC2u4FFGnw== X-Received: by 2002:ac8:574a:0:b0:458:5716:fbd8 with SMTP id d75a77b69052e-46a4a8ebeb9mr795565461cf.32.1735836356631; Thu, 02 Jan 2025 08:45:56 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.56 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:56 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 31/44] selinux: fix namespace creation Date: Thu, 2 Jan 2025 11:44:56 -0500 Message-Id: <20250102164509.25606-32-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Fix selinux_state_create() to consume the provided parent state reference rather than incrementing its refcount. Fix sel_write_unshare() to put any previously set parent_cred prior to setting the new one. With these two fixes, nested SELinux namespaces are properly freed when all references are dropped. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 3 ++- security/selinux/selinuxfs.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3bf4428ccfca..3c4ea7ed3750 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7606,7 +7606,8 @@ int selinux_state_create(struct selinux_state *parent, goto err; if (parent) { - newstate->parent = get_selinux_state(parent); + /* Consumes parent reference */ + newstate->parent = parent; newstate->depth = parent->depth + 1; } diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 7a0947dece69..0395ab187fd9 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -386,6 +386,8 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf, tsec->osid = tsec->sid = SECINITSID_KERNEL; tsec->exec_sid = tsec->create_sid = tsec->keycreate_sid = tsec->sockcreate_sid = SECSID_NULL; + if (tsec->parent_cred) + put_cred(tsec->parent_cred); tsec->parent_cred = get_current_cred(); commit_creds(cred); } From patchwork Thu Jan 2 16:44:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924643 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f170.google.com (mail-qt1-f170.google.com [209.85.160.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF4F21553A7 for ; Thu, 2 Jan 2025 16:45:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836362; cv=none; b=CSJ64GNYjrg8fGkmzuiTkqaISHVKS+EWZWG/jg2e9WUVArBAkEg4iBTO/NSBfVolqADUBHocfB33Ue0NHwVp8jGO+K44KqS677WGyTtt1UWziXgUEDrwRK5QN0TyZrkM02hAydv+8k5W6bgiITov3wtMbXZJ7tbckoMDFiFLawc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836362; c=relaxed/simple; bh=IswauXKqcYJPhhfGN1VUx2JAArghAv97CaUJ+GbPNwA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=R41y6M2uOr9M2JUXi8lJOopqzcWZCthSBWJK+39v/Rnlvnpi3OO6jUw4KcgW2WOU+lLrHeuLOIQq9oPHpIJF3a1kWj5yzJfYw0Q/A7j5fG1MUmzkvUwsk/ELLjtpQxL+8WS79kG0toNRYyzmd6F1QzuzRpfKL24vK6OtAvyZ7LY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OYGyWfMD; arc=none smtp.client-ip=209.85.160.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OYGyWfMD" Received: by mail-qt1-f170.google.com with SMTP id d75a77b69052e-46769b34cbfso171278361cf.0 for ; Thu, 02 Jan 2025 08:45:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836357; x=1736441157; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yIKct/+Tt8KlsMRbFmx3VYVi1FpFrekyJRfYqe3w3ZQ=; b=OYGyWfMDTKRfPICN4x/EWaL9P4eqtmj2VGa37zf2K62z7GwV1HYDS1gSQpcBsXNCQz T1wmH+9DSXeiz6ARyTlZTn5FLpqcmweTn0n3lPNSOiFQTCElbpUQYmBnR59ufsU5M6h9 5QLvKQTsVa1xbeTGIFkRtk6ATSwtsAQ3F6PqjorFmQNQgoeoOV92jnP4QYxIQY3u5Xrv RAc/QWF6dRTeLOo41EfD7x4Twn13SHHoqqp+TltJ4px6MH5ZEzkJ1TN5rACoLc8yMVT4 SO3D2vM9qwOHlIMjfyOaXXbuN3mMFarBXwpSU+9DSjCXL5hm048eMY6X2aY0zThlcCFh H4vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836357; x=1736441157; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yIKct/+Tt8KlsMRbFmx3VYVi1FpFrekyJRfYqe3w3ZQ=; b=WpW0iLaIZ2Fhu7VV+VI0bH5R24kd6CfU5iPP0sDBTEBnc5E0hWyGw9UGCa4BUBeEHw /8Rtjr61yGYDysu+y1dfX/qwz4tVPFDYGlSvWgbnSKF3I9tqujIIJ+WFF+LEaCyRQRPq 02ypHni4xHkyYjOjmyMU7QfWiWVhSR56/COl3oXPVGZshsHtj4E9+zNhNwS2zWZTgl2s 5yPozl26aoiVquS0il9GE6iW5i+Dswc+07bN8JxDP6cfrdFGeVmxaFoX42N+rUDDGF7Z fd1fb1f9zdhf2M1m36dgljDl6GRMbtL5HQFkglPHuf1JAyZ0uUEXQbFt753ZiWYZCi5c 4eXw== X-Gm-Message-State: AOJu0Yxm3DFhrdXVUmR3xilxEbXJGpYxhDLibFNrHKdEKwkXBnJZZnp+ o6GOesphMWKTTAB2uQD8EV6IIyssJ5SBROSSuE0nUCuvo7FVUljiySK4Yg== X-Gm-Gg: ASbGncs0PAfk2zmQzfIsaNDpOVh2uLxnFiXrxhMZB2SuOI/PkpY08SkmwutIGBg+q24 n15utnnv4x/LflNDnQcVarCYjRvH4CskpY5Uq5zSQvDE/3nE572+uZRWxXj4iZvCzJwE/lXJ2eS e7kBmhasdKHGmO53lslZwzu7462yXAC5K4RlSsVD/2gFMRvFqwKh7Tvqi3DfWbcgMXjfWtlftjn 6Fl1OrOY21VaAYaf8R2PE55PXw8kG7Y2n772DjV3bN+1idMoNRo2XtfPhVlNceErIU5yFgsjCZP eaID0lRcuqUYslOGwby2bFBpr6PHOcUMNaWf1LZ8UB1C2/5samgWIwZTxL9zFOnlLcYfVg== X-Google-Smtp-Source: AGHT+IGvTLHNYPaxGV3nGsla9kyu3dU6Zy+eJzxc1EDXEZh0j+m9+GQ/3DiY6BEo1Uk0We+dNeBEQg== X-Received: by 2002:a05:622a:14cd:b0:467:4802:e6a1 with SMTP id d75a77b69052e-46a4a9a3e94mr752693251cf.48.1735836357168; Thu, 02 Jan 2025 08:45:57 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.56 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:56 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 32/44] selinux: limit selinux netlink notifications to init namespace Date: Thu, 2 Jan 2025 11:44:57 -0500 Message-Id: <20250102164509.25606-33-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To prevent modifying the enforcing status or resetting the AVC in the userspace policy enforcers, do not deliver SELinux netlink notifications to the init network namespace unless they were generated by the init SELinux namespace. If you want to receive SELinux netlink notifications in a non-init SELinux namespace, then unshare your network namespace too. Otherwise, just map the SELinux status page (/sys/fs/selinux/status) to check the enforcing status and to detect policy reloads which is now the default behavior in libselinux on any kernels that support it. Signed-off-by: Stephen Smalley --- security/selinux/netlink.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 03678a76f4bb..fb55d3ba25f5 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c @@ -70,6 +70,17 @@ static void selnl_notify(int msgtype, void *data) struct sk_buff *skb; struct nlmsghdr *nlh; + /* + * Do not deliver SELinux netlink notifications to the + * init network namespace if they were not generated + * by the init selinux namespace. Unshare network + * namespace if you want to receive them; otherwise, + * just get updates via the SELinux status page. + */ + if (current_selinux_state != init_selinux_state && + net_eq(current->nsproxy->net_ns, &init_net)) + return; + len = selnl_msglen(msgtype); skb = nlmsg_new(len, GFP_USER); From patchwork Thu Jan 2 16:44:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924645 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f171.google.com (mail-qt1-f171.google.com [209.85.160.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 316A715C14B for ; Thu, 2 Jan 2025 16:45:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836363; cv=none; b=hMm2pGcClGquZFc7v7mqJDForIhq/C7mQC5AQKimp7tYOEIEq4QdRUn2kPBhZr77Kb89llpJSCHZV2HMmAHtrtIKlFmQK5djPMj4xPBlK9OZHrS7rZAKs1asApZI7Lb2WRTe7uoWubt+wdZHP4/yJGhOn3BMScWau6lAq9e9rtk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836363; c=relaxed/simple; bh=0TYmBzOQvZ2/t+8nEIImwpR7zTT1lLA1rvqY32RGv5I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=baksAdZ6AhI+Mw7KH9nLCEpYwPrw9IHzSxoXcxcV4ERTnNYoTvGtMW8wY/1hVsjGIwOfPcmUazUAuLcyOf2CkErx8pFUvG6BTyC4QwnClSmsSd5c/4F1BcPYs7eE9NGFRZkbizgmqID4MJVKWXx6xFQTKLa9DaXp7wZdHaRrs6U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WaLEeWB8; arc=none smtp.client-ip=209.85.160.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WaLEeWB8" Received: by mail-qt1-f171.google.com with SMTP id d75a77b69052e-46741855f9bso103439581cf.2 for ; Thu, 02 Jan 2025 08:45:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836358; x=1736441158; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=duohzdXzUV6DuywaJMPPM2Kl9XCO2YYHl8tJ1P/9ohQ=; b=WaLEeWB8ypnIkPeuOgU6DPcUj+h0ukU8qkIPd5JQJilTugxMQMICNnuWKv7i0ZAQC0 c2Y5s1cZFaG0WwbcD9NLUHdKTmvlAfmbzvQ7ZZjoE6ADMOSMBhBRK5pwLPKI6SJ4JXZQ CdpX9Oc7dYez0nwe9q7TLLKfej3CDSJEHPMDu2lnP8C+NPgy3VQor61t1z3BtG8G/slM hdoU40r5iylsYWgip13Yz10qe8GCdqUietHXJKHLoQucnudJofH2RAvRXSLxnSJJRxAw oTsI4PsPDAOnWvQ4AZAQtkL1wldbiw2yyjyY8IR3mzCw23QE0cBA2xKUZbmoXKcmFGMD +oLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836358; x=1736441158; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=duohzdXzUV6DuywaJMPPM2Kl9XCO2YYHl8tJ1P/9ohQ=; b=PNPkd1Jdt4XR//oJnOM/ml5/Xzj9MPdkZTN46skUitmy87a1cmoDWPCnvzOhFlPsAl AkA5MFQdQ9gOTYEijN2Z1ln07302XIjEqiFRd7ATgMPz6q3kUnfJkogRjVmd5uufcHi0 lkWZaKoY+yuhQygYjnMVut7YOsFlp/kNJslRruqfuOb8u89tVo5/ZO02LlBLJtqvtS5a L2H3/uspehImyXLp7/dTS1JGd3bTAMT0SZ1myOIfyx1Wbyyr1brq7d8NjgBvCG/ikYI7 zOJV/jChtCQbgMSdFdFknQpiroDxx22Ttpw+65s3vw6mNMSzY+1oh0LWBgapKF9ikoYv UILA== X-Gm-Message-State: AOJu0YxwllFzChfEC2U3iPb963qln14NDLdImfPwZRIFS1OyxHCfJTe7 O7jCUXappSiQUGLuvTexG0kktRFDp55JX2ZBzq/3hu9vmDY2xVzhOxM5iA== X-Gm-Gg: ASbGncuE5zSp77zjKgPtj510eGnSO0hLfRda0LTzWXPOts7gZ3BB38bxLoSqRBo/Esr pmZ5TndJvKi1dBKiu6s6JMmcmKNuGzogOjswb2/R2AVMpwdCjgQQ/A+c8Z4m3YOnZFJSw9rMP69 y/XbMhMlwKW+FT6TseNTOUCoIX4d0K8O6wmkiKmoAfwwsMcg8nmdI2OvUncEydh6D0hxCmvbTYU uuxAFlL1BJP5YuLQh37AeMDxD4ARe1O7z1RtjDA32QcoSoxjjcP7LZpfsfRFJ0uNaHPoUO1mZaY wxQTTiDmCi2BvAvQt1V0VmZGvNvwOUtmvBZbDyNibIUC72H8WbSoMr+f1zHS1yAFkRX5nw== X-Google-Smtp-Source: AGHT+IFbE0cyW9FBPGCJbmO2DSTOq/8bDObK2fNzdfavGYT53l9Znr5jZ8paJv+E5iNnxlvzAM5MJw== X-Received: by 2002:a05:622a:64c:b0:467:61a5:1a85 with SMTP id d75a77b69052e-46a4a8e87b4mr725846651cf.30.1735836357900; Thu, 02 Jan 2025 08:45:57 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.57 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:57 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 33/44] selinux: refactor selinux_state_create() Date: Thu, 2 Jan 2025 11:44:58 -0500 Message-Id: <20250102164509.25606-34-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Refactor selinux_state_create() to be more like create_user_ns() after which it was originally modeled. In particular, pass in a single cred argument and update the cred SELinux blob with the new state. This makes the reference counting situation clearer with regard to the old state / parent reference and simplifies the callers. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 78 ++++++++++++++++++++--------- security/selinux/include/security.h | 3 +- security/selinux/selinuxfs.c | 11 +--- 3 files changed, 56 insertions(+), 36 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3c4ea7ed3750..5ede1bf55f9a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -205,20 +205,6 @@ static int selinux_lsm_notifier_avc_callback(u32 event) return 0; } -struct selinux_state *init_selinux_state; - -/* - * initialise the security for the init task - */ -static void cred_init_security(void) -{ - struct task_security_struct *tsec; - - tsec = selinux_cred(unrcu_pointer(current->real_cred)); - tsec->osid = tsec->sid = SECINITSID_KERNEL; - tsec->state = get_selinux_state(init_selinux_state); -} - /* * get the security ID of a set of credentials */ @@ -7576,10 +7562,11 @@ unsigned int selinux_maxnsdepth = CONFIG_SECURITY_SELINUX_MAXNSDEPTH; static atomic_t selinux_nsnum = ATOMIC_INIT(0); -int selinux_state_create(struct selinux_state *parent, - u32 creator_sid, - struct selinux_state **state) +int selinux_state_create(const struct cred *cred) { + struct task_security_struct *tsec = selinux_cred(cred); + struct selinux_state *parent = tsec->state; + u32 creator_sid = tsec->sid; struct selinux_state *newstate; int rc; @@ -7606,14 +7593,39 @@ int selinux_state_create(struct selinux_state *parent, goto err; if (parent) { - /* Consumes parent reference */ + /* + * The reference to the new state replaces the reference + * to the old state (parent) in the cred security blob; + * hence, we do not need to use get_selinux_state() below + * to increment the parent reference count. + */ newstate->parent = parent; newstate->depth = parent->depth + 1; } atomic_inc(&selinux_nsnum); - *state = newstate; + /* + * Set the new namespace. + * The reference count was initialized to 1 and + * this is that reference. + */ + tsec->state = newstate; + + /* Reset the SIDs for the new namespace. */ + tsec->osid = tsec->sid = SECINITSID_KERNEL; + tsec->exec_sid = tsec->create_sid = tsec->keycreate_sid = + tsec->sockcreate_sid = SECSID_NULL; + + /* + * Save the credential in the parent namespace + * for later use in checks in that namespace. + */ + if (parent) { + put_cred(tsec->parent_cred); + tsec->parent_cred = get_current_cred(); + } + return 0; err: kfree(newstate); @@ -7642,21 +7654,39 @@ void __put_selinux_state(struct selinux_state *state) schedule_work(&state->work); } +struct selinux_state *init_selinux_state; + static __init int selinux_init(void) { + const struct cred *cred = unrcu_pointer(current->real_cred); + struct task_security_struct *tsec = selinux_cred(cred); + pr_info("SELinux: Initializing.\n"); - if (selinux_state_create(NULL, SECINITSID_KERNEL, - &init_selinux_state)) + /* + * Initialize the first cred with the kernel SID and + * NULL state since selinux_state_create() expects + * these two fields to be set. The rest is handled by + * selinux_state_create(), which will update the state + * field to refer to the new state and set the parent + * pointer to the old state value (NULL). + */ + tsec->sid = SECINITSID_KERNEL; + tsec->state = NULL; + if (selinux_state_create(cred)) panic("SELinux: Could not create initial namespace\n"); + + /* + * Save a reference to the initial SELinux namespace + * for use in various other functions. + */ + init_selinux_state = get_selinux_state(tsec->state); + enforcing_set(init_selinux_state, selinux_enforcing_boot); if (global_sidtab_init()) panic("SELinux: Could not create global SID table\n"); - /* Set the security state for the initial task. */ - cred_init_security(); - default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); if (!default_noexec) pr_notice("SELinux: virtual memory is executable by default\n"); diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 830f890b4cb9..adba67b074e4 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -117,8 +117,7 @@ struct selinux_state { extern struct selinux_state *init_selinux_state; extern unsigned int selinux_maxns, selinux_maxnsdepth; -int selinux_state_create(struct selinux_state *parent, u32 creator_sid, - struct selinux_state **state); +int selinux_state_create(const struct cred *cred); void __put_selinux_state(struct selinux_state *state); void selinux_policy_free(struct selinux_policy __rcu *policy); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 0395ab187fd9..c91bf329692c 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -370,25 +370,16 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf, if (set) { struct cred *cred = prepare_creds(); - struct task_security_struct *tsec; if (!cred) { length = -ENOMEM; goto out; } - tsec = selinux_cred(cred); - if (selinux_state_create(state, current_sid(), - &tsec->state)) { + if (selinux_state_create(cred)) { abort_creds(cred); length = -ENOMEM; goto out; } - tsec->osid = tsec->sid = SECINITSID_KERNEL; - tsec->exec_sid = tsec->create_sid = tsec->keycreate_sid = - tsec->sockcreate_sid = SECSID_NULL; - if (tsec->parent_cred) - put_cred(tsec->parent_cred); - tsec->parent_cred = get_current_cred(); commit_creds(cred); } From patchwork Thu Jan 2 16:44:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924644 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f175.google.com (mail-qt1-f175.google.com [209.85.160.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 45ED315575D for ; Thu, 2 Jan 2025 16:46:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836363; cv=none; b=iOxNvJl+yM+wVogsjCR0LmuVoaGfjQGrlkyIpcDmr/3nXQeRYXTqMf+92lWWO5uczHg7irnNb7V/lF4YuoOj2dgClonFEJBpk9YhlPVhHfZEb7WT2AWiv1/cafkHOhNaC5fj0VwT/ehHrhLfg/4zxiAwoLQX6h6pSMnBxhrM72A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836363; c=relaxed/simple; bh=06KcZWQYrh91+bR0JzH5PuxSxa1e7uqw2+5FixvLwe8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uamVnMu/PnW70O/dgpUkNTBI4xaguygW9U+gpzIsK5MeUM1lF0rslOja6Y+19TOTfDxvjk1ZrFLTnWJ7+fIix9jZB11iOAlNTZRQpZjSbhPDHqktiOLYSdqJAAkTszNA1ld19c3f7lBwwRP+SdsYHuDMdJZ1zjuhjos40SXxDfQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Yrh7aVuv; arc=none smtp.client-ip=209.85.160.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Yrh7aVuv" Received: by mail-qt1-f175.google.com with SMTP id d75a77b69052e-46792996074so112827221cf.0 for ; Thu, 02 Jan 2025 08:46:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836358; x=1736441158; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LdawipmAM+1BxbnzS0FSenj1HYBbHP7fiM226zN9Mh0=; b=Yrh7aVuvbcqLBjixWrZCjvr/apfqq8G7m7X6aqFE9jm5pz3peaKp2zDwC7gq5xfO/7 ThqJ4JDr9Et8//hZf/XuIykek+AQATaVgeikRmh9rfSizJ8F/8A6E3+AgU81/qIuJATd er2RlSXPkzdyn1hSzl93RAIP0B2xAJ1dd5zS3nkLuV3kUm7mhUuqpeLMI0ATNlguOcWq b5ifvMFu9/Xzp2d976llCfnwmf4oJLNNK0Hk9x0ahtuo4P90zTv7tCarktorcohHoEsX ofBBpzu8twTl7faezkNKjFuh2kBOhjHOpmqpNjyxAWhoTw2rEsKh4vJ+LGDWg4nCYCvJ U8AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836358; x=1736441158; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LdawipmAM+1BxbnzS0FSenj1HYBbHP7fiM226zN9Mh0=; b=X/9kxf7vTr0jedLuTgmB75hg8vvOH2zgAbg33I10UPAV426y5Wi1jl/b24cdpMfu+P XTDVPnXyowuMVdGxe5mcqEcgSa/l4Hky9YxzvLUr8mwUljCYQxjcugAb5SfC3qzNYtcP kQwChdVrj9SJ9yxTS4R4ZwGHnzYrjIO+1nZyExQW06t2CjFRy36GJezuiiSopLpy0bc9 DkSwp1ISOgDLVtjhT9G1gf5pUvVd/CXmhJrAs1FjwDGOKEijuv9cdnr6eUaX3fYOTYa2 +hkN0NlSmBbR5Rw8FQuGlg5FKe7BjQzXh4EopzLMxY7sJVkRp1Aomkj/Gx+pNDo8QXCt 7tsw== X-Gm-Message-State: AOJu0Yzszk01ea89/D/9dnENLclAdUJxJQFlJypYI5rXMaIq826JdCFd sAk4C/lztQqNHYK4h/ZEZ2tu1kf87rsFZ5ikwrJ8HJfo0fDnzg5tlIw9Cw== X-Gm-Gg: ASbGncvNNxIn4naINhbyNnI59Rx0SGqCQBoj1oZkoEdcJIlN65VUZkGUK5MGI4CIbrV 9TTCVreeLc5bzhYWWGpbYNOjLS57YjLIQaGnAt3gqPifJ8KqU64GSF8BCf2WAHrYbH3EH7/vfO+ wafAIcvsIdhjWYtU+77Lo7U/L6xBr/P4bKjo4mt+9bDSA1Epq/NMlqD+naM814rN+2Sl+cMH2Fw +o84pN56HFJIBVJJl+Iyf2sO7XwKNMerE3M9TfAuIPNwuaH7Zq7AEQHDmSrMMo6Pve7ZJOpcfaa 4eK+vEQY8fHjTBNbCrtf7d5dN4lqI96eAexQhvN+eYBJvF5xW7wMwZykUa83CgHWReqZFg== X-Google-Smtp-Source: AGHT+IGhglLdz2oxtb8aKOFBU6YiVr18tZwdrKfn14jHkEl7Oq8Ye2etPQEm9Kl5SnxTTAFLKob/fQ== X-Received: by 2002:a05:622a:1a29:b0:467:5da6:8096 with SMTP id d75a77b69052e-46a4a977800mr833245641cf.44.1735836358458; Thu, 02 Jan 2025 08:45:58 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.58 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:58 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 34/44] selinux: make open_perms namespace-aware Date: Thu, 2 Jan 2025 11:44:59 -0500 Message-Id: <20250102164509.25606-35-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Adjust the handling of the open_perms policy capability to be namespace-aware. This ensures that file open permission is checked against each namespace in accordance with the namespace policy. Otherwise, a child SELinux namespace could escape checking of file open permission in the parent namespace by disabling it in its own policy. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 111 +++++++++++++++++++++------- security/selinux/include/security.h | 5 +- 2 files changed, 85 insertions(+), 31 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5ede1bf55f9a..80590b99399a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2004,22 +2004,6 @@ static inline u32 file_to_av(const struct file *file) return av; } -/* - * Convert a file to an access vector and include the correct - * open permission. - */ -static inline u32 open_file_to_av(struct file *file) -{ - u32 av = file_to_av(file); - struct inode *inode = file_inode(file); - - if (selinux_policycap_openperm() && - inode->i_sb->s_magic != SOCKFS_MAGIC) - av |= FILE__OPEN; - - return av; -} - /* Hook functions begin here. */ static int selinux_binder_set_context_mgr(const struct cred *mgr) @@ -3198,7 +3182,13 @@ static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, const struct cred *cred = current_cred(); struct inode *inode = d_backing_inode(dentry); unsigned int ia_valid = iattr->ia_valid; - __u32 av = FILE__WRITE; + struct inode_security_struct *isec; + struct task_security_struct *tsec; + struct selinux_state *state; + struct common_audit_data ad; + u32 ssid, tsid, av, requested; + u16 sclass; + int rc; /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ if (ia_valid & ATTR_FORCE) { @@ -3212,13 +3202,41 @@ static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) return dentry_has_perm(cred, dentry, FILE__SETATTR); - if (selinux_policycap_openperm() && - inode->i_sb->s_magic != SOCKFS_MAGIC && - (ia_valid & ATTR_SIZE) && - !(ia_valid & ATTR_FILE)) - av |= FILE__OPEN; + /* + * The following is an inlined version of dentry_has_perm()-> + * inode_has_perm()->cred_tsid_has_perm() in order to specialize + * the requested permissions based on the open_perms policycap + * value in each namespace. + */ + ad.type = LSM_AUDIT_DATA_DENTRY; + ad.u.dentry = dentry; + __inode_security_revalidate(inode, dentry, true); + if (unlikely(IS_PRIVATE(inode))) + return 0; + isec = selinux_inode(inode); + tsid = isec->sid; + sclass = isec->sclass; + av = FILE__WRITE; + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + requested = av; + + if (selinux_policycap_openperm(state) && + inode->i_sb->s_magic != SOCKFS_MAGIC && + (ia_valid & ATTR_SIZE) && + !(ia_valid & ATTR_FILE)) + requested |= FILE__OPEN; + + rc = avc_has_perm(state, ssid, tsid, sclass, requested, &ad); + if (rc) + return rc; + cred = tsec->parent_cred; + } while (cred); - return dentry_has_perm(cred, dentry, av); + return 0; } static int selinux_inode_getattr(const struct path *path) @@ -4038,11 +4056,17 @@ static int selinux_file_receive(struct file *file) static int selinux_file_open(struct file *file) { - struct file_security_struct *fsec; - struct inode_security_struct *isec; + struct file_security_struct *fsec = selinux_file(file); + struct inode *inode = file_inode(file); + struct inode_security_struct *isec = inode_security(inode); + const struct cred *cred = file->f_cred; + struct task_security_struct *tsec; + struct selinux_state *state; + struct common_audit_data ad; + u32 ssid, tsid, av, requested; + u16 sclass; + int rc; - fsec = selinux_file(file); - isec = inode_security(file_inode(file)); /* * Save inode label and policy sequence number * at open-time so that selinux_file_permission @@ -4060,7 +4084,38 @@ static int selinux_file_open(struct file *file) * new inode label or new policy. * This check is not redundant - do not remove. */ - return file_path_has_perm(file->f_cred, file, open_file_to_av(file)); + /* + * The following is an inlined version of file_path_has_perm()-> + * inode_has_perm()->cred_tsid_has_perm() in order to specialize + * the requested permissions based on the open_perms policycap + * value in each namespace. + */ + ad.type = LSM_AUDIT_DATA_FILE; + ad.u.file = file; + cred = file->f_cred; + if (unlikely(IS_PRIVATE(inode))) + return 0; + tsid = isec->sid; + sclass = isec->sclass; + av = file_to_av(file); + + do { + tsec = selinux_cred(cred); + ssid = tsec->sid; + state = tsec->state; + requested = av; + + if (selinux_policycap_openperm(state) && + inode->i_sb->s_magic != SOCKFS_MAGIC) + requested |= FILE__OPEN; + + rc = avc_has_perm(state, ssid, tsid, sclass, requested, &ad); + if (rc) + return rc; + cred = tsec->parent_cred; + } while (cred); + + return 0; } /* task security operations */ diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index adba67b074e4..4b2ebe31467b 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -215,10 +215,9 @@ static inline bool selinux_policycap_netpeer(void) current_selinux_state->policycap[POLICYDB_CAP_NETPEER]); } -static inline bool selinux_policycap_openperm(void) +static inline bool selinux_policycap_openperm(struct selinux_state *state) { - return READ_ONCE( - current_selinux_state->policycap[POLICYDB_CAP_OPENPERM]); + return READ_ONCE(state->policycap[POLICYDB_CAP_OPENPERM]); } static inline bool selinux_policycap_extsockclass(void) From patchwork Thu Jan 2 16:45:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924649 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f170.google.com (mail-qt1-f170.google.com [209.85.160.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 843921487D1 for ; Thu, 2 Jan 2025 16:46:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836364; cv=none; b=Qdt3ohv3VeM7PuUbSgshUd9FLKFbL4Zub+5JY17OzoA2RcEcGE5gNa06aiFKS3JzPtVuA+Eg2iTAqCbiAkRPJPvSydxmrT7UObJN+GbVcxXFPAwwPgfWsYcO8k21eKhaFIMTRU83SHU1JOcBOlxfhsxOGPocsmyEpId8LVT9qmw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836364; c=relaxed/simple; bh=jJYRPJO8GkRCzfd5ETPVYCTf3CrT+rBA4AiojXX8088=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GexXG7DBrSyj/aaQvTakcTsBPtXGOLzyAu5Tb7GM6pt0fDiOutTq0rnOKYXg1zL3bu2abcF8GPxWeiZYh07J3oOZTnUIhqxnPSgG4ZPciS7TspTigiAT15FHyXbhaWjDhDC3DmeyBmmzjHgdhvTDwe6Y8X1zdfsN3nCX0jwWjoM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=lZ9S6Uvp; arc=none smtp.client-ip=209.85.160.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lZ9S6Uvp" Received: by mail-qt1-f170.google.com with SMTP id d75a77b69052e-467a37a2a53so137998841cf.2 for ; Thu, 02 Jan 2025 08:46:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836359; x=1736441159; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wEmcYjCd/swmAgsX5yvNjuuYpxBOvM3SqdH7e4dnSC8=; b=lZ9S6UvpSp9t3rqJN2dZuq4yT7HvHiWyuYYYM7psoRqwVi4eEYG6v/0JVr/7ZMK2zb +pamZbPmEjHCres2JARwrrE7AUzqTA9Y0VtiNQPrt3jxp2I/bRzYIj3OBQL5nb4NPYTA VKs+32BgiZvTGpg1QZ7Cy5rGVzaoealwv0YuFJD+5f0phbIo0Q/1ZJsrnN5Gu9iovL1b j0rOv494ybb2hPIn7HrpFskjkLexy4EF9nPnMnFwADtGG6RfwgaxYyzaaE+1TepGIR0w ok32FE0jc2HGQjz3/eSIju1fhMzP8mU/5uIjzYbzyQZUb/2lH+YFDxXNCXzRB/3CEiY7 mjKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836359; x=1736441159; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wEmcYjCd/swmAgsX5yvNjuuYpxBOvM3SqdH7e4dnSC8=; b=UWlzjmW1j0CX9ZKEM2N059IlbFZgqcSJZ6hsiiDm6linUxGUIEheI0ErJ/ZVDpm7Y7 LrgDZgR3AJGbg0WkATGy56K/Woyzu5udB4Afcm5g41pK23EnlkCayHvoORjl3C+Yp2la IDrKu9RhAd8dkkq+vJK5SShZpfYUTPUqhMw1BXl52C589bbD7Kk46KXI9m24ktaCdx4z JJD4LnN4pRGQmD9TfqRSM9thT2+bjF+4ehjrC2o85M43fiMROGEI9CHSo/dsh6kHySfq FtAV9gxVhW5mFxmUuZVi93JWknCFJiR6s4caLlMGM8G4PoW2622w4BtH4V6VbpZcZ/FR IvhQ== X-Gm-Message-State: AOJu0YzJQQCMPfOOTTLdz1PQQDX1XhJZ5JqWZ/aBjzClb0nJ8QRWqAXj IaOVJdexKnGPPvmlmY4Vewt0hyP1fQJgW9J1ziNGlr21T8CIZkLtR/OkKA== X-Gm-Gg: ASbGncuTWjkNv/7yxUpIW8tRMus2aPU/Qs0uJc7ou8zBskVssjLfeodhxJLh2t20ESg g7eP35ydDXcIMo47pTCyyUX0/fww0ttNGtp+LyNe9erLn4oJbG+iG3aAebaM7B/jO75bREDF+Zu 45zw7fPUFBECZzQPGIfztgrVre1eQ6xDKMMTLroeWcCnXTSJ7s0BDKJ8UAYiTX3HbdLicqwAF/T 4wotWYOpj9pLKhnZb5WzHehvLIDdx0CJNtsmlXuTnQXilaWcXmeUn7QPvXg6/rZ4rUz9/FFCuWf Tpo/QhWXkcdJyHZz+XOmdXK0rybTiv/M/E5ZpzJEQUPAy19X4FnoKd1zF49sy/GuGPdTug== X-Google-Smtp-Source: AGHT+IEUekRhIGNniJq2Ylfs+3fS8sY1n6ubgAxeeNOKAHFDZyJaqvrkotFcUysQngmDu/R5phvBqg== X-Received: by 2002:a05:622a:20b:b0:467:7513:3d8 with SMTP id d75a77b69052e-46a4a8d0261mr702318461cf.21.1735836358999; Thu, 02 Jan 2025 08:45:58 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.58 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:58 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 35/44] selinux: split cred_ssid_has_perm() into two cases Date: Thu, 2 Jan 2025 11:45:00 -0500 Message-Id: <20250102164509.25606-36-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Split cred_ssid_has_perm() into two separate functions, cred_obj_has_perm() to perform the namespace-aware checks for inter-object checks like associate, and cred_ssid_has_perm() to perform namespace-aware checks for socket and SysV IPC checks where the SSID is in fact derived from the creating task SID. Modify cred_ssid_has_perm() to only use the provided ssid for the initial check in the current namespace, and to instead use the task SID from the parent cred for each check against the ancestor namespaces. This ensures that socket and SysV IPC is correctly controlled in each namespace based on the task's SID/context in that namespace. We still need to determine whether peer labeling is correctly handled across different namespaces, and if not, to adapt appropriately. Signed-off-by: Stephen Smalley --- security/selinux/avc.c | 59 ++++++++++++++++++++++++++++++++-- security/selinux/hooks.c | 16 ++++----- security/selinux/include/avc.h | 3 ++ 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index a533385d0149..57935359b3d7 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -1568,7 +1568,7 @@ int cred_tsid_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, } /** - * cred_ssid_has_perm - Check and audit permissions on a (ssid, tsid) pair + * cred_obj_has_perm - Check and audit permissions on a (ssid, tsid) pair * @cred: subject credentials * @ssid: source security identifier * @tsid: target security identifier @@ -1585,8 +1585,9 @@ int cred_tsid_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, * DO NOT USE when checking permissions involving cred/task SIDs; this * helper is only for object-to-object checks. */ -int cred_ssid_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, - u32 requested, struct common_audit_data *ad) +int cred_obj_has_perm(const struct cred *cred, u32 ssid, u32 tsid, + u16 tclass, u32 requested, + struct common_audit_data *ad) { struct task_security_struct *tsec; struct selinux_state *state; @@ -1605,6 +1606,58 @@ int cred_ssid_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, return 0; } +/** + * cred_ssid_has_perm - Check and audit permissions on a (ssid, tsid) pair + * @cred: subject credentials + * @ssid: source security identifier + * @tsid: target security identifier + * @tclass: target security class + * @requested: requested permissions, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check permissions between a source SID @ssid and a target SID @tsid for + * @cred's namespace and check between the parent cred's SID and %tsid + * for all ancestors to determine whether the @requested permissions are + * granted. + * Audit the granting or denial of permissions in accordance with the policy. + * Return %0 if all @requested permissions are granted, -%EACCES if any + * permissions are denied, or another -errno upon other errors. + * DO NOT USE when checking permissions involving cred/task SIDs; this + * helper is only for socket and IPC checks. + */ +int cred_ssid_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *ad) +{ + struct task_security_struct *tsec; + struct selinux_state *state; + int rc; + + /* Check using the provided ssid in the current namespace. */ + tsec = selinux_cred(cred); + state = tsec->state; + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + while (cred) { + /* + * In all ancestor namespaces, use the task SID from + * the corresponding credential as the subject SID. + */ + tsec = selinux_cred(cred); + state = tsec->state; + ssid = tsec->sid; + rc = avc_has_perm(state, ssid, tsid, tclass, requested, ad); + if (rc) + return rc; + + cred = tsec->parent_cred; + } + + return 0; +} + static u32 cred_sid_for_state(const struct cred *cred, const struct selinux_state *state) { diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 80590b99399a..68538c74dc99 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -461,8 +461,8 @@ static int may_context_mount_inode_relabel(u32 sid, if (rc) return rc; - return cred_ssid_has_perm(cred, sid, sbsec->sid, SECCLASS_FILESYSTEM, - FILESYSTEM__ASSOCIATE, NULL); + return cred_obj_has_perm(cred, sid, sbsec->sid, SECCLASS_FILESYSTEM, + FILESYSTEM__ASSOCIATE, NULL); } static int selinux_is_genfs_special_handling(struct super_block *sb) @@ -1833,9 +1833,9 @@ static int may_create(struct inode *dir, if (rc) return rc; - return cred_ssid_has_perm(cred, newsid, sbsec->sid, - SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, - &ad); + return cred_obj_has_perm(cred, newsid, sbsec->sid, + SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, + &ad); } #define MAY_LINK 0 @@ -3353,9 +3353,9 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap, if (rc) return rc; - return cred_ssid_has_perm(cred, newsid, sbsec->sid, - SECCLASS_FILESYSTEM, - FILESYSTEM__ASSOCIATE, &ad); + return cred_obj_has_perm(cred, newsid, sbsec->sid, + SECCLASS_FILESYSTEM, + FILESYSTEM__ASSOCIATE, &ad); } static int selinux_inode_set_acl(struct mnt_idmap *idmap, diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 95fed265071d..5e02c1323848 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -164,6 +164,9 @@ int cred_tsid_has_perm(const struct cred *cred, u32 tsid, u16 tclass, int cred_tsid_has_perm_noaudit(const struct cred *cred, u32 tsid, u16 tclass, u32 requested, struct av_decision *avd); +int cred_obj_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, + u32 requested, struct common_audit_data *ad); + int cred_ssid_has_perm(const struct cred *cred, u32 ssid, u32 tsid, u16 tclass, u32 requested, struct common_audit_data *ad); From patchwork Thu Jan 2 16:45:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924646 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f179.google.com (mail-qt1-f179.google.com [209.85.160.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83D1C47A73 for ; Thu, 2 Jan 2025 16:46:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836364; cv=none; b=Ll8u2MNMRZFxcOdJ9XWmsPczCzrj1cZYpH4n5B+jXMi66ds2BnQKZpHrL1p8PsBJTi6wGeV25S/tgh9XbnPvgkc2P37VUYiqZij0D2ZD8AB0VHBcUqlbRWR7Yjx03TJlfu059xluAWfV5ASpIMmOA9mgI04icSxPoq8HcldjQzc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836364; c=relaxed/simple; bh=EpnnaoVModCzAaWDiGLOVWI2IPG6d6UBsE47xuT++TQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dC2SMledUgAdjw6gxTjtAL5Xn7fGXC+mjTeyRPhKbrgMxwbDEiu66tT6BNR3NDflwpOGxcfRBpvD5vGESPFJ9ONKc+1gwb55fIHR3xoNP3D7GdVx+INNwGGLswcEOkGyyXNYrNAdp4EQS/wawoX82kVNCwzNOLUWMnslkA0Qgxc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=O0jEoC5z; arc=none smtp.client-ip=209.85.160.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="O0jEoC5z" Received: by mail-qt1-f179.google.com with SMTP id d75a77b69052e-4679d366adeso98454241cf.1 for ; Thu, 02 Jan 2025 08:46:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836359; x=1736441159; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YQih05fUzP5zUKira43vzXXqq2ld3PdlBX2mcXzV8mU=; b=O0jEoC5zcljZgfzH2MXwsRepzjQt5KANyLLA2I+SJ9JMs9h3pxCKGTfbxZYqp+SNR3 mGBvAfQnSU0vv2LU9CYrxLMAmaqcD+aU3su7YmCDm24xWZAtY6syGgCN8BRl6CLqkJla CHyfF8u1Cb7YGqOzJ778/NMizrLHK5vj+otwCJ1MZNmzw5n+TrKGmsvBzTOiLqexOxZv FfVOUBPaOhCNDk4q6LmDbmupopMVV3cuqgFgEtVO88Y24dQbq0pLx/Lk9TOM1Gdfluwr EWO+2u2zziEW6utCnNJ2rEfvaTN9rhiq9qpnEuWPpdLZDy/HijodKLSQcNvu5H3mAC1v h+mg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836359; x=1736441159; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YQih05fUzP5zUKira43vzXXqq2ld3PdlBX2mcXzV8mU=; b=YINCrbenYM0FaneSceR7c1w2SNgSwdXxaDqPzRnwXpuHMpBCBkTULVjNr7EBY2a6E7 c97T2BCbnzGZy2w1i3rXvMPcD7XoUSngngb+Z71Mt8LXoz5Y/wxGKg/KKcysTaLATtkX ejuWtA2z7SorGoFnoh9qwWBvSsCl22s9KlqNGaf1scVPl7oGlAzKOwNJhDjRqpsoNNON Z5QcJCPe7f2YVOD41+VqRGlN1vXn0FQARPgtAhmwgK/UwOWNaDByAJ9Y9cNy15qUi+4V CP3PeIYZH/YRqRdaB/6e+SBYC7Xj5Lq4T1xOGDR9VoRmdA2TRMGYK3oaEVjPItdHcEm6 WQCw== X-Gm-Message-State: AOJu0Yw4ooA/lfoiWGqHGe8j4lgyZywgb5OTzPfDlTQ4pYCyRYaWw4CL oFozWiRZT8CJ0KoMil5f9BLNK9Yg42McKioVAqws9kouqlPykyldxOFGBA== X-Gm-Gg: ASbGnctOHwAjxR4BfDWOiymq1Tcj3H9EY56HV2Ldzhkl/9iHZ0LjSvrCUlwgVzsYuqU 7K1Leo6PHm09YNkTZ+dIBz8tTE8KmbGvt4qynIR33BbIHqE/IvYDN7e+m5lV9CRs0uGBqN7koqj DOszWpFguDbZ+aWB0Dp0wCy0awL/vP9YvhkB90nWrf8QUKnb+knwo5QQL22LDVQColhKQVmG6qb dJn0x2b1YrigXDtK4UGzQsj/BL8AwUcjZufWA5+EHDvYK3cZGkTvwSk8z01Vii+jislBTrzsnWs 1e9OX0NMDC6tdwXTrb4EObkKXRmqUNF3v8VjaJGuE5IhZv5SIBOIITMHr9pdQYXdn1LHFA== X-Google-Smtp-Source: AGHT+IG5YC2DnkGPzayjpAS7OPfh3tzRO5VgteA09MG4gyXdaFXV47yMRGNaiKhRbDwo0Hi5y8nrVA== X-Received: by 2002:ac8:5755:0:b0:467:6b6b:fc1 with SMTP id d75a77b69052e-46a4b143bf5mr768723991cf.16.1735836359522; Thu, 02 Jan 2025 08:45:59 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.59 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:59 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 36/44] selinux: set initial SID context for init to "kernel" in global SID table Date: Thu, 2 Jan 2025 11:45:01 -0500 Message-Id: <20250102164509.25606-37-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Userspace treats any non-null value other than "kernel" as an indicator that SELinux policy has already been loaded, so the global SID table needs to transparently remap the init initial SID to "kernel" just like the security server does. Signed-off-by: Stephen Smalley --- security/selinux/global_sidtab.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/security/selinux/global_sidtab.c b/security/selinux/global_sidtab.c index 983b406389cb..50c3d58a11ed 100644 --- a/security/selinux/global_sidtab.c +++ b/security/selinux/global_sidtab.c @@ -21,6 +21,15 @@ int global_sidtab_init(void) if (!str) continue; + /* + * Before the policy is loaded, translate + * SECINITSID_INIT to "kernel", because systemd and + * libselinux < 2.6 take a getcon_raw() result that is + * both non-null and not "kernel" to mean that a policy + * is already loaded. + */ + if (sid == SECINITSID_INIT) + str = "kernel"; ctx.str = (char *)str; ctx.len = strlen(str)+1; rc = sidtab_set_initial(&global_sidtab, sid, &ctx); From patchwork Thu Jan 2 16:45:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924647 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f177.google.com (mail-qt1-f177.google.com [209.85.160.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA5AA13BC0C for ; Thu, 2 Jan 2025 16:46:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836365; cv=none; b=LjggFaN3NC5tF2pU+YyMmbEeXbGcODGh9qgZSlFh7ReWa93iZs7Ymy2vS4OlTTMSjSCFSE3SPUoqP92bYwmS4sJLnXUP4sYWq8BZmWFAjY4mhnAoj4iRUkohUeYisnK+vS/xeGA6Zwhqv0gGmdQ7CuQPJWd9UBGYw5RVyirf70g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836365; c=relaxed/simple; bh=JmXtFZxpD/PAWZ6O1X3aNBClCaVuZmb60sV8E2bBIUQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=r/yypCghrrxFor564KFZ2DnjbCRkZ2DDqKD6ICz4r7h6gyzPMOKJOMtZJfs7/48fyjJBh8dw+nCjxtOX8W6pIp/A+mSTAtbis5pdOCyzufqq8LUDI7b1zhhkT7+So6q46pTZuME0twTdceo0mBuOqZUfBJONOb5BVmTrp91Uwnk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BUUSxyON; arc=none smtp.client-ip=209.85.160.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BUUSxyON" Received: by mail-qt1-f177.google.com with SMTP id d75a77b69052e-467a1d43821so110002211cf.1 for ; Thu, 02 Jan 2025 08:46:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836360; x=1736441160; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QMG6ObMctKHXcORkMwPGBPDSOmStMVuUAEpzMpjAx6Q=; b=BUUSxyONbNvMkdr4q60gjLdpqMKteD2ZPRWHXVnL9VY8CUry8kXtPcMpfqAFNo2qbf OCwjmTpTGxhHSOYLqvLQ28kLTIsWWUOxmVnR2/KA5TSi5zIFByZB1vKMrPe3vDA3MZ/L TxxERn7s/tW40rF/KLAAUUiu/xCctRVzkvRRWrIHxmM2sC+qVqgnKaNof9F+niR7wt7m /UKarx0qzhb9yCaUWbnIRINO+QCyd6Ud+M+EL1MRw/X1UOyfuctMLWG9xrCHe9wrszs/ QIVfP+JvyzP+nMs7XnTL2WwOlR3IkrMhOnWsGwPuPGBNeIVfNGDCve9oTS3iQ9w+TAEt dARg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836360; x=1736441160; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QMG6ObMctKHXcORkMwPGBPDSOmStMVuUAEpzMpjAx6Q=; b=oZgXcixc17iPXKZlJotrxDQ/bJ0a8KRnO7MxTIBplY3Fuha1CK8EUsfjR8SNjptqD7 Ushpv7zlZDgDI0GfSrCJOhidoJQi++2xS/qLIRFEPgs++kpaYfAXP2HTKP4xF5jTMaM3 Y9rbRkXlzTuMaMt8y/aj1mf9DMlrcYC52jnWS/t5W4cJuuKn1IKxDcXV82AydluNHbQJ FlIPu/pkiRlMbSJ2GEB71TVhHXWtEICnDtCWckWEWSsNFxqgkiZi+9DuEL4C6v2cwcdF V4VHtknf97HqJQQK3qt/ay3qLhy92yCoE8AHtiw8nSEHAQ/sSFFtiYKJhItbtuiOuO9U Ok/Q== X-Gm-Message-State: AOJu0Yy549BnJ76LK3K5LAIGURjRwvTXpn1rBDZlVT5NLvNUTL03x7jS ryCgYnh3+aTbELZ/ep5y0sVX1SyoNNbxo6fVzOs1RPFKPfA4kxVimmiC1Q== X-Gm-Gg: ASbGnctPoG0gT8KLLN4Cej9QhbXJQZLZFLjxR65Hu6QSSbIaMKfuzDOrcAanditVVcr ZfqnkdglZLrKzzho9SLw7TjrT3X2vKDW66ctLPv7TEjVedf6io2La8QOXSEkTW6CJFxqnTBKQD7 Re+yrptgLqIJyconTSAfnxLJA/zmWkytrZMqVQYJEkD6MOY85sNWtH24LlrcdE9yTjJjuD9YFXJ 07W9fK1Zb9LTyPfcOhzL5tPPcqfo//lgCNfeTgtEEbwoQOcUAo6NBkIuf2M5OtY+0sODZuO18xA glEhf5mQLsz99OIQICyKHjvCkyxoo7R8kyo7m0rfik5Rqoi8IJvMkuqz4tuGTRXYPtkKSA== X-Google-Smtp-Source: AGHT+IETsG24V03dvnD+pKjPxQMc+fQWRcPtB4usXgocCQmrwYAT1yo5VlCr9fE995/kfmKQUZoRaA== X-Received: by 2002:a05:622a:1a23:b0:467:61c1:df38 with SMTP id d75a77b69052e-46a4b1135fcmr858014101cf.12.1735836360324; Thu, 02 Jan 2025 08:46:00 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.45.59 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:45:59 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 37/44] selinux: disallow writes to /sys/fs/selinux/user in non-init namespaces Date: Thu, 2 Jan 2025 11:45:02 -0500 Message-Id: <20250102164509.25606-38-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Disallow writes to /sys/fs/selinux/user in non-init SELinux namespaces. Signed-off-by: Stephen Smalley --- security/selinux/selinuxfs.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index c91bf329692c..de4d7eda415f 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1354,9 +1354,16 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) int rc; u32 i, len, nsids; - pr_warn_ratelimited("SELinux: %s (%d) wrote to /sys/fs/selinux/user!" - " This will not be supported in the future; please update your" - " userspace.\n", current->comm, current->pid); + if (state == init_selinux_state) { + pr_warn_ratelimited("SELinux: %s (%d) wrote to /sys/fs/selinux/user!" + " This will not be supported in the future; please update your" + " userspace.\n", current->comm, current->pid); + } else { + pr_warn_ratelimited("SELinux: %s (%d) tried to write to /sys/fs/selinux/user!" + " This is not supported in non-init SELinux namespaces; please update your" + " userspace.\n", current->comm, current->pid); + return -EPERM; + } /* * Only check against the current namespace because From patchwork Thu Jan 2 16:45:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924648 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D84F413C9D9 for ; Thu, 2 Jan 2025 16:46:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836365; cv=none; b=SLJtESyqgOlcHMRPiA00xuwQgS+AHU7pcDX8zVYqK2D2O9Rgger0YS/g91N+bDSzLj4494PkkOPc69/9jy37DMAXWqtTukcCWIVQc/GzsZpeoshtZ2gx+6sstdDVgNhEaUeAjRTkppjFqcDOdh3afvr/6Fa3sWTeQJx056CdhdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836365; c=relaxed/simple; bh=cKYt3gLji1Fc+2zfzPlwotrmC+VvsXLzznlnz/PcGIE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=apMB3wHGj1dA4+EQ9YOydK0T2iCg9i/OTXw44RU0gVQjkhxGLIompvvharnoqFEN5FmMD4dGahLY+5D4wParB9NflIzeuTWes01TMKlaOj3s0+OdOXe1aOE7RzwNx7ZG64uTK++o1RqQ2yEZwlAkrDbEp3gqGWVtIptwsXakhUg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ARlFYmmJ; arc=none smtp.client-ip=209.85.160.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ARlFYmmJ" Received: by mail-qt1-f172.google.com with SMTP id d75a77b69052e-46677ef6920so99878091cf.0 for ; Thu, 02 Jan 2025 08:46:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836361; x=1736441161; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BC9UDm2mtl2zeQO28MY5z349mz+5z+hSD9ZmfQLetnc=; b=ARlFYmmJQsBh/VpB9UexlPrRdSKI4DBp9/MtoQObSGFd0v5KGqb7g3BV7PhD7l58Nf lxZRxN/HnR1wz1iIcEt7BON3zQERXTbxCyXW6S8qQXjeEwGRX0iEkgVfucEYhxqY6GbW 60A+0hE+iH93LxdxaxqPoO1qx/CXv1SobxasheH2XSVpNDIpJLwj7MdjRwW1o0IBScf0 tAQPnKwNNHAdXtZxWgMF2bLjpL/xXgv6cdA1s0VeXAnfHZcQvX4lkswgMGDuRLfIkPIx gdP/mvu3mP3pqU8O1Ffp6nUeZ4QAKdkjK1VooRnTw984SDpid40Bu/HfzCuy4RB6DYJZ J4Qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836361; x=1736441161; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BC9UDm2mtl2zeQO28MY5z349mz+5z+hSD9ZmfQLetnc=; b=bkGofjDhThKOZWxPuO6hnra8ZqZpQQ98aEmya3E+dmnCnip81YWOJ450/ayZGQ5eRM oztwc+UNskfuCh8BKHUL9LIg4PVpjEN7bF8rK5WiZN4sqvw5Uijr5Lja8Cva9IWt5XeV u2UrGcRKXwvjpXIsQcFAWPQS8/VnSY/BROkQJQh7wKgR7kVVBsaOFX9goDHatHcde7jx 9vwBOEe+TL0pywlvvWKf4aHpzXoR7dIBJFvk/v+1rWB+rYjIntM8aYag3Sobp7TGiWGN 8S9i0d92DK7Hg6lxzOwtfc18TJgV46522sks779NV/n3JXcBkrS8vK2mJwittAHCeKGW Pnng== X-Gm-Message-State: AOJu0YzZLzfQdoRpH1GqbWpgH8LKW1rF+agCAd/PRwaH2HgFHIjrIRFb s5hgxLe4nGmDFFjsQ29r+YSZCJUXQH/7fHFjZ91BLwmqBAMso1CZh5wVWQ== X-Gm-Gg: ASbGncuChyiAptTn/CyvBL0gnk33jiSMgiJbGY7UCa3MalSLzJvgTuKGibNG1cNyc+1 GIo9Gl+4rp9+EWX27QDpzD0Gh24xgNq4Pu21pADCAbKJ2cXeHMueLsave9OfB4sT7jCEF3HDA8Q HEeWHR+EJTcnDCpgVO/f5LgD9kh+YJNINAO8RQHrJBTyhfxIV3rfpQ9nh8kCEXVZ/m9UWFDMQtu J5mslS38EMVdGPOx/OaIOxmCqMVEKOQRcXQ4vLRsxxK7zkHe0krlYVAtmoOisCfXgewhies+Wa1 QfQrKxfEm92ovwpAXNkCdgtUY3yKIUWY1L7ucDi/b2r9lt3xWvF/biczcUiNmUKLKRUfqQ== X-Google-Smtp-Source: AGHT+IFKbjWtrDG6XZf9TmgjgLGQU/v6rmJ7pwjuEH4bRtZBUk93Bx+/PX7BjHOTC9dcFYsiVbfWvA== X-Received: by 2002:a05:622a:1984:b0:467:6654:3dda with SMTP id d75a77b69052e-46a3af9ffdfmr923459591cf.12.1735836360848; Thu, 02 Jan 2025 08:46:00 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.46.00 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:46:00 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 38/44] selinux: convert nlmsg_sock_has_extended_perms() to namespace-aware Date: Thu, 2 Jan 2025 11:45:03 -0500 Message-Id: <20250102164509.25606-39-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Convert nlmsg_sock_has_extended_perms() to use the cred_has_extended_perms() helper for namespace-aware checking. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 68538c74dc99..11d940fb79bd 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6122,9 +6122,9 @@ static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_t driver = nlmsg_type >> 8; xperm = nlmsg_type & 0xff; - return avc_has_extended_perms(current_selinux_state, current_sid(), - sksec->sid, sksec->sclass, perms, - driver, xperm, &ad); + return cred_has_extended_perms(current_cred(), sksec->sid, + sksec->sclass, perms, driver, xperm, + &ad); } static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) From patchwork Thu Jan 2 16:45:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924650 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f172.google.com (mail-qk1-f172.google.com [209.85.222.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E5291547C0 for ; Thu, 2 Jan 2025 16:46:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836366; cv=none; b=aF9nMQa1Qz4zTjX2Hbn5bgziGs6gNvQ/XPMD3QPxBSP6tHVze6TkxsgAvgIU8+DvVT95KkyuaNMawEQIkXolUDHU7i+/J6IkGzl8ISsearTXijpjN4ha6iH/IUXPjMe7hQseuwlkP5Z5r8XTppCXeN0QrUqL3nM/HNp0bgbtwOE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836366; c=relaxed/simple; bh=iACk5BLwzEKGgFfMZYpmiwvvKZfyk58jc84cB19KqKg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FjQOXneNktT2d4RXuT/UbESwJ2GW+AgNMXE7OkF88+94tsriSE025U/xsPHZN32MGsc3F47RVK0qFM3AAkk3arO2cGu5fW9qie+8MSrhGRZoqgSo34jvPL7RWVjVxssa5GlAkvxBckX9Yp+Z28Jip3wKGym8XBTxed7cw/Jxv5w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kJR67xMw; arc=none smtp.client-ip=209.85.222.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kJR67xMw" Received: by mail-qk1-f172.google.com with SMTP id af79cd13be357-7b6f95d2eafso1135341685a.3 for ; Thu, 02 Jan 2025 08:46:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836362; x=1736441162; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/rFcz7YsS3yXQhalooHUjmrFUA0y1Gw78zxjoWAYYX8=; b=kJR67xMwmBbyHLTC5nORh0Ou9jhyT3ECwXotpVrGKlQzElyTuLtdc7QziIKF8pflI2 MaGBe5KpfgMCgla+gJdr9l/3iiCk9t5Y0BGsHU38/xFzO5ZHpbKOXNXJ/NtI+EZMgmZR 00AsA5EsijP04ZQyX3gR2DmGbxRJ7ClaibQ8jPb+BKC6ezFZcAc4WsDp+3GgUS2R8cj6 K/yqRJJIb5WrPm5dTkxK+86rYsa/XI0TzLOnJOtsc2fWBfgJOfTfYlm8Om0F5X6swQzg d9DRDIFUSC4ONCVzliZfB4v30CupPPiUPM7Y16SCZMjk2VtPgCYJB/5TaeL/LobkdZPR DnvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836362; x=1736441162; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/rFcz7YsS3yXQhalooHUjmrFUA0y1Gw78zxjoWAYYX8=; b=ZgdtajNKfBYo/K1/3ufFYTdnVxe31ga2Ic1YaZPwn/E40p8DpxVFEUXnFOj0itRRY7 gShSu3V4aDmFpl3KC3IdIZ3AQuibjJtAh4I/Le1Akmbr0XI54ksUKmGynz4oB6cvHS2j 1yxZ1AlnedOPzFmdWwQ0pJi7n2qLuUM4UzivVkBdPZOBNSsy4bIop0R5v+HN4tKeryH9 7JQmmDd8SCptpcSqpb/zmyD4Iu24gBXaneF2oju2qjpyM455il+wksQB1r8PVS4O+r1w 5gwS1DuWcQ/KHObIhpSIih8VQ2RTpWyy+WXyyfYWlxC/XwSbaVKc8cBy6qPri0ngxDjR ZrEg== X-Gm-Message-State: AOJu0YzF0SwnpVLrjfULZrMjnbtlqVgMm3CxqWzySBsbBQqIjmtavw9N XmqschGyEJ14sO/QDbX9eHIeWqTZ6yYNz7QmwZqNdU0HDFTbdIFCF6XAGg== X-Gm-Gg: ASbGncumEBsXRM+X1Gx5rXmjIsxFZbGAf6leNutdP20AOmhL1HwjfoU5h0Sgg0ArXfU ZNfdYtot/MEqBDo3Alve+/1PJJSltJRU4LTIsfX962e+fnTQZBMUCA2dFZ8Q63iUhCOz9Rbpou6 WRHnRiPiguROBsiRruyJShi8Z3h/OFaloghBENEo2P9EO4ihYyKdEQktH+NUjkn6mu2m80p/cFM Cx8yr4DKibMVxy/rRUylFdTnJMLsCIS2l3PqxdTTcH8FhwD4j6tShzrdp2nIwomEByFlb6or498 SvwIlynjttA7fSgubndyc+syWfCRmKOiDUhkGlaXxUovVACXovx0ykDNUCszDbEu3KYczQ== X-Google-Smtp-Source: AGHT+IEQ4OjPb0yPMoAGB5HHBCC4kkrM05pRZj+DbxrW71kpN5lERZzpD4yJDuFiF9AI5v51PRwsdQ== X-Received: by 2002:a05:622a:20f:b0:462:c473:94ee with SMTP id d75a77b69052e-46a4a9c71dbmr643015001cf.49.1735836361577; Thu, 02 Jan 2025 08:46:01 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.46.00 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:46:01 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 39/44] selinux: defer inode init on current selinux state Date: Thu, 2 Jan 2025 11:45:04 -0500 Message-Id: <20250102164509.25606-40-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Previously inode_doinit_with_dentry() was only checking sbsec->flags to see if it should defer the inode security blob initialization, which was fine when there was only a single SELinux state/namespace since that could only be set if the state was initialized. However, with the introduction of SELinux namespaces, the superblock could be initialized in the parent (or other ancestor) namespace but the current namespace may not yet be initialized (i.e. the namespace was unshared but no policy has yet been loaded into it). Add an explicit test of selinux_initialized(current_selinux_state) to defer initialization of the inode in this situation so that we do not end up setting it to initialized with an unlabeled SID prior to policy load. An alternative would be to proceed with initialization but do it against the parent namespace. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 11d940fb79bd..dfc422d9c042 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1440,7 +1440,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent isec->sclass = inode_mode_to_security_class(inode->i_mode); sbsec = selinux_superblock(inode->i_sb); - if (!(sbsec->flags & SE_SBINITIALIZED)) { + if (!(sbsec->flags & SE_SBINITIALIZED) || + !selinux_initialized(current_selinux_state)) { /* Defer initialization until selinux_complete_init, after the initial policy is loaded and the security server is ready to handle calls. */ From patchwork Thu Jan 2 16:45:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924652 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f181.google.com (mail-qt1-f181.google.com [209.85.160.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 11C8A15CD49 for ; Thu, 2 Jan 2025 16:46:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836368; cv=none; b=LPLTYZ5TG2i0o2dAbGDzveSCnkI4/i8QiWks6n6bFkFnuQAxg9OMbIpAIuXm4A9lBCaGOziPU0VsYTUCeXzxITZUqvHOkVazC1OOm9b6RY+1MR/GyPldhYpjTG1BlsM/Bb4gVOcDHDjwD6bnp4P1+rPf+j4ga38muGU3QmKneoE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836368; c=relaxed/simple; bh=kxf0ZUjIlKNZIGKFfrsPx3WNH881gPEEzAVzaVWCZBM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=l/0NJRDlATAdufH/CFrp+UbtNLIVLeeDy/10mvF0DBxJKb7TtMvCokI08KnKxoKly9zEP720A5qLb1cwzSs58vef/Kn0Pabh1OzPO4MovcXRF8Z0ejcaAgRMGJUOKE5t2bNl9H3xAeLmINzzXZkupgll/GLnVbttjRrwfkVa174= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=gvJPLUhU; arc=none smtp.client-ip=209.85.160.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gvJPLUhU" Received: by mail-qt1-f181.google.com with SMTP id d75a77b69052e-467a1d43821so110002461cf.1 for ; Thu, 02 Jan 2025 08:46:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836362; x=1736441162; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8xRpCT6ZKl0oN4rqvkFExrCml7OdEuAPiV6bFp9DXyc=; b=gvJPLUhU0SPevumrqH/HXK+p1Y7Z0UdVp+84aNYMqRiO5/tkKz/7iHbeX90pMAPsxL NbjLvkU/obY5jXG7Q5vPEyUHyKNUBy+pa3DejqFDzDRbnBK8FVUGoV7CZvlqtczoCpjb Tz5DFMuOYNiLNNEB6mVYrEECyZrw7ahyRfPsj0bb2Yirh7oAsnB0AudCeltVUSnnlQPt 69sspf61Hka9/XaWWdjohN362eU9CzuIxvEtElQkHsrbOGt3lBSk8rwOsRCXynT910g1 x72HpoNLmqFHxbB6sXFXYbc9+PJv2e3uHQTXB37uSJGl/TyrU0TAAG+OXuOg+4ToNrZd 8FTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836362; x=1736441162; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8xRpCT6ZKl0oN4rqvkFExrCml7OdEuAPiV6bFp9DXyc=; b=ZwTQoLXRx95CfEK1ao+a1jvrT/lv8YbjwmZtTZeR6En5AgiCi9uU7rAUNXZpckbNpP ha1C8Hcrk24y6wvxoAX9dlmZJZnb00HLeuZWFMVZ1b3ukHapDROdN49KD69iPMCJ1bn6 feTkISUhM4cUj4natlmQIXs8qyHjewb0L+R3aU8brppSLafxbphVkcNiSbQ7Ih8vJqqk nkwETYsOLyUgx6EksHAdBVfa0dqaNAAeXnFMSvbKs9XUYBZ+o9usksF9mqhDiM4VgV44 gt0qlo6wqf2SdqJvEkizUmQXJf/VEBmk9/mGt0WpLh5RpXRR5HYN67aOplPT98xPPPel Osww== X-Gm-Message-State: AOJu0YzlENzJu/MuB7LPXIctfHIHtFdwEULfOh14+jPajHI+A0MAhtg9 jF/yPH+8dCZU+1GuPxHMdBrWxvmjQE5sS3AUdqUJB89sgIsEUSkHCFByZg== X-Gm-Gg: ASbGnctDCD3id4epKePd5Q+UhX8SlGc8ZRGYyTX4G0sAckovWpT6ItYN9Yjz/hTmy5F 1xP9DokbTne49BQhrjHmCktCr39UO6rpQ2qlErp1n3LHcSUGyfil5SD2XlkXB/lS3cVoXfOY8eW qmVzAHRxbtyFT89ACeIwE6JxWqV0YatkY2D0ufdDHbOJUGgNARc5LTUOXXe7LZ4j/tlFA+d04Cx 9pMB7JktlE8pzD6Ya7+sCUMHXTdfYm1k/xcP6XNN0wyP4B2Q/Vz3c6xbopHpOvvJytHLV+ImjAU 0D/ugzilRnSaNIf82OHgiLJkG0aB8iYbkwonynQ1B94pZhnXsfF6GOsGzINaxQoYwViXog== X-Google-Smtp-Source: AGHT+IFrxWkcHUtssrANtNVYo2si1X1f9E1rklRIBWXl4+nbn5v4AgL4dbq8D+THvm/tHykYUkIcXA== X-Received: by 2002:ac8:5910:0:b0:467:5cfb:bd40 with SMTP id d75a77b69052e-46a4b1890b0mr750650521cf.19.1735836362465; Thu, 02 Jan 2025 08:46:02 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.46.01 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:46:01 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 40/44] selinux: init inode from nearest initialized namespace Date: Thu, 2 Jan 2025 11:45:05 -0500 Message-Id: <20250102164509.25606-41-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The previous commit deferred inode initialization until the current SELinux state/namespace has been initialized, which fixes some cases but can still leave some inodes unlabeled. Instead of deferring initialization, proceed with initialization using the nearest ancestor namespace that is initialized. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 47 +++++++++++++++++------------ security/selinux/include/security.h | 6 ++-- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index dfc422d9c042..5ce0e2afd84f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1320,10 +1320,9 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_SOCKET; } -static int selinux_genfs_get_sid(struct dentry *dentry, - u16 tclass, - u16 flags, - u32 *sid) +static int selinux_genfs_get_sid(struct selinux_state *state, + struct dentry *dentry, u16 tclass, + u16 flags, u32 *sid) { int rc; struct super_block *sb = dentry->d_sb; @@ -1346,8 +1345,8 @@ static int selinux_genfs_get_sid(struct dentry *dentry, path++; } } - rc = security_genfs_sid(current_selinux_state, sb->s_type->name, - path, tclass, sid); + rc = security_genfs_sid(state, sb->s_type->name, path, + tclass, sid); if (rc == -ENOENT) { /* No match in policy, mark as unlabeled. */ *sid = SECINITSID_UNLABELED; @@ -1358,7 +1357,9 @@ static int selinux_genfs_get_sid(struct dentry *dentry, return rc; } -static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry, +static int inode_doinit_use_xattr(struct selinux_state *state, + struct inode *inode, + struct dentry *dentry, u32 def_sid, u32 *sid) { #define INITCONTEXTLEN 255 @@ -1401,8 +1402,8 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry, return 0; } - rc = security_context_to_sid_default(current_selinux_state, context, rc, - sid, def_sid, GFP_NOFS); + rc = security_context_to_sid_default(state, context, rc, sid, + def_sid, GFP_NOFS); if (rc) { char *dev = inode->i_sb->s_id; unsigned long ino = inode->i_ino; @@ -1422,6 +1423,7 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry, /* The inode's security attributes must be initialized before first use. */ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) { + struct selinux_state *state = current_selinux_state; struct superblock_security_struct *sbsec = NULL; struct inode_security_struct *isec = selinux_inode(inode); u32 task_sid, sid = 0; @@ -1440,8 +1442,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent isec->sclass = inode_mode_to_security_class(inode->i_mode); sbsec = selinux_superblock(inode->i_sb); - if (!(sbsec->flags & SE_SBINITIALIZED) || - !selinux_initialized(current_selinux_state)) { + if (!(sbsec->flags & SE_SBINITIALIZED)) { /* Defer initialization until selinux_complete_init, after the initial policy is loaded and the security server is ready to handle calls. */ @@ -1452,6 +1453,13 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out_unlock; } + /* + * Find an initialized state to use; there must be at least + * one or else the sbsec won't have been initialized. + */ + while (!selinux_initialized(state)) + state = state->parent; + sclass = isec->sclass; task_sid = isec->task_sid; sid = isec->sid; @@ -1498,8 +1506,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out_invalid; } - rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid, - &sid); + rc = inode_doinit_use_xattr(state, inode, dentry, + sbsec->def_sid, &sid); dput(dentry); if (rc) goto out; @@ -1512,8 +1520,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent sid = sbsec->sid; /* Try to obtain a transition SID. */ - rc = security_transition_sid(current_selinux_state, task_sid, sid, - sclass, NULL, &sid); + rc = security_transition_sid(state, task_sid, sid, sclass, + NULL, &sid); if (rc) goto out; break; @@ -1526,7 +1534,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if ((sbsec->flags & SE_SBGENFS) && (!S_ISLNK(inode->i_mode) || - selinux_policycap_genfs_seclabel_symlinks())) { + selinux_policycap_genfs_seclabel_symlinks(state))) { /* We must have a dentry to determine the label on * procfs inodes */ if (opt_dentry) { @@ -1553,7 +1561,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent */ if (!dentry) goto out_invalid; - rc = selinux_genfs_get_sid(dentry, sclass, + rc = selinux_genfs_get_sid(state, dentry, sclass, sbsec->flags, &sid); if (rc) { dput(dentry); @@ -1562,8 +1570,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if ((sbsec->flags & SE_SBGENFS_XATTR) && (inode->i_opflags & IOP_XATTR)) { - rc = inode_doinit_use_xattr(inode, dentry, - sid, &sid); + rc = inode_doinit_use_xattr(state, inode, + dentry, sid, + &sid); if (rc) { dput(dentry); goto out; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 4b2ebe31467b..1426302c353d 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -245,11 +245,11 @@ static inline bool selinux_policycap_nnp_nosuid_transition(void) ->policycap[POLICYDB_CAP_NNP_NOSUID_TRANSITION]); } -static inline bool selinux_policycap_genfs_seclabel_symlinks(void) +static inline bool +selinux_policycap_genfs_seclabel_symlinks(struct selinux_state *state) { return READ_ONCE( - current_selinux_state - ->policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]); + state->policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]); } static inline bool selinux_policycap_ioctl_skip_cloexec(void) From patchwork Thu Jan 2 16:45:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924651 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 100D2282E1 for ; Thu, 2 Jan 2025 16:46:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836367; cv=none; b=pLyPSici5ySd3Rgd3jZWnils9IlHaQUG7O15eU/Vup6/pJAF5XeeFztigJHplfAAyO99fyZlQDKUvvD+lBU8pkhr+pddBx4P257Dj0Mcn6DC30WkqVZ+pCXSRkrLwCR3vfkTQCiYbUMZuCvsT5cm6six504V3RUPEYE/ofC1fYc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836367; c=relaxed/simple; bh=bPthf95/IjQcMu347ZTGwI7GRHK03+FW41G19lwYsM4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=eFY7bA09T7Nx2mNWrXHSWLTUuM+C+XT3XxRuzmjjBHjRgtJR8NLH+hcFKCds4BJU+Ym2lbEqYlyI4IrtrCl1ODkiUWyZpdVSDGoM0FJ3leu+rrlfhu2zKfH2j4Wfl33gSvHKze/OhXZiM3hUFzbABTgMb3oP1ys9ibs4Bf2Vs7I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=UR+KGH51; arc=none smtp.client-ip=209.85.160.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UR+KGH51" Received: by mail-qt1-f172.google.com with SMTP id d75a77b69052e-467918c35easo154602411cf.2 for ; Thu, 02 Jan 2025 08:46:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836363; x=1736441163; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KS0seltETOGWAVSrtmFxVuTXqLLPmq7wCJ7ziVzozOo=; b=UR+KGH516ilytbylX/lkftAceTbckUR3EQmu11ttZ93hJu7sAF4DKwAEL/KNWVeAVX bHQNOBIB7e9VgsC8VLSkeG4RSz4mSL1Bn16M8WwPqw32Q4aOXmDssWHa4dS1+QuGX6pJ kERYqJziPWd+peliSx0GsMbMFAZzl53dbMSJzXFeZsfFA0UEuHVQP328sZl1gzkgDDFS /0FhbB6ivngCVyEVa2CYCM8Xl5gfaoZEzs1x2UcgG9KGkg/Z7fTuM331tpxpkduEoixU witn2IKeJKCvYOh4xOSsEBkrO4tsbw2aJGpRY5ZqSYfcYNHo6NU/z+g9DrHOrK7vRKBX Gb/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836363; x=1736441163; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KS0seltETOGWAVSrtmFxVuTXqLLPmq7wCJ7ziVzozOo=; b=eydRX2NhGph0pO7ajbMotv8D55MRDBtYwzZq9K0ajLAmbhcg3whPmvGO628BGjJnnc ik3R6DCEmGkiZBFDwlUmsrxQzewovGJjxcUMBugUjoqoLuStOaVnPspir8k/GIR20qA1 GDZfATkLVNlY9rAnK3yRjF8nHkr0TC3yOoA3Wzm4GN+zRkTAeeWcDrn5V37khV20pWUq wnTCO7Su0j94W0rPUkq0t6YaJ4REo5c/7I/BnQWwnLEIj2wgIEqImaKjkSV5Ep8giVTw hyTgMHg0EtTNTZuZv9JFFW65tUZSQ15uajJ6UUzoSP0v5Eq3f6cQiu4i0QrEYiG+J2KB VFPA== X-Gm-Message-State: AOJu0YyEW3I4kPn7q3Gv6l6ZXKDIIxqySo8cRK3V7xe/lTlw3iBbSgWP 4HDY9/jMBttFg7/ez0EXwrOQrI9T8iLv14F9aHCwIKNN3F+gR3AYhhO47A== X-Gm-Gg: ASbGnctN0+OSRD8Xyrmds8zN13OjjLUr5qoit3gy1ANgxS2Ldaxyod9V79UjCHrFvhe rkwuHTp3ruO2rf40BJ6fjbWy/58o6Bh7FAn20XyiGSUWjl75d8qzCSOjRs9fsOnqKOIHSgI37x0 4EL+07katS2huc3JejAlyX/RVbfrWmoJ87f3DsM+93sbEbu51N+EpCwnrgzLSDXhVhAIU5qDvdl MbIoDsW/c4pxacz0gzlVH1x9GZzwXz6u1lMKnEG1F/UNARAlNDWRhXwxBIiIkR4dF9KX9vU6GB+ wshuo5YrSrfAINnQXTUZrkcZDiuDWpMCIr/07ifodvKt7k1e/mHcrdRsPWxF5552pxaP7A== X-Google-Smtp-Source: AGHT+IFUlMSVfeqOnWCBQ4i+pvjq/jahZyI8sF90lHLiV8Xnaa2TtVhN2ygNuslsb0K9caIhJq2Cng== X-Received: by 2002:ac8:5dcd:0:b0:460:9b2b:e8b5 with SMTP id d75a77b69052e-46a4a8baef4mr891358491cf.4.1735836363002; Thu, 02 Jan 2025 08:46:03 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.46.02 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:46:02 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 41/44] selinux: allow userspace to detect non-init SELinux namespace Date: Thu, 2 Jan 2025 11:45:06 -0500 Message-Id: <20250102164509.25606-42-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Enable reading of /sys/fs/selinux/unshare as a way to detect whether a process is in a non-init SELinux namespace. This is to allow the selinux-testsuite to adapt based on whether it is run within a child SELinux namespace. Whether or not we want to retain this as a userspace API is an open question. Signed-off-by: Stephen Smalley --- security/selinux/selinuxfs.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index de4d7eda415f..efceb3ac9157 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -329,6 +329,19 @@ static const struct file_operations sel_disable_ops = { .llseek = generic_file_llseek, }; +static ssize_t sel_read_unshare(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; + char tmpbuf[1]; + + if (fsi->state == init_selinux_state) + tmpbuf[0] = '0'; + else + tmpbuf[0] = '1'; + return simple_read_from_buffer(buf, count, ppos, tmpbuf, 1); +} + static ssize_t sel_write_unshare(struct file *file, const char __user *buf, size_t count, loff_t *ppos) @@ -390,6 +403,7 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf, } static const struct file_operations sel_unshare_ops = { + .read = sel_read_unshare, .write = sel_write_unshare, .llseek = generic_file_llseek, }; @@ -2339,7 +2353,7 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc) [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO}, [SEL_VALIDATE_TRANS] = {"validatetrans", &sel_transition_ops, S_IWUGO}, - [SEL_UNSHARE] = {"unshare", &sel_unshare_ops, 0200}, + [SEL_UNSHARE] = {"unshare", &sel_unshare_ops, 0600}, [SEL_MAXNS] = {"maxns", &sel_maxns_ops, 0600}, [SEL_MAXNSDEPTH] = {"maxnsdepth", &sel_maxnsdepth_ops, 0600}, /* last one */ {""} From patchwork Thu Jan 2 16:45:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924653 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f174.google.com (mail-qk1-f174.google.com [209.85.222.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B147C155321 for ; Thu, 2 Jan 2025 16:46:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836368; cv=none; b=XGnzrsQBc/GUj3zGuJhcDt5J8JKx6zY9FTugmLr6wtKFj3ZEpN4i/PItg24tNc2V+lETPG/T1FF+1ZlM3kvs/+RkmjFOXF4uBea47ri6ETCy7+1aLAfYmvp/AZCoNS+/ZxogZYJ6BPaWQpkHqciXd2Rz4u8EzqXsior3jPaXI/g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836368; c=relaxed/simple; bh=3lstVvoIKDrbY/Kw/AyHr2jehr16SC+3tBnjjeuD+3U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=WE2shuiS6aWfwBwOHlmJX6qvZmMHgqiVbwZMyNp7kbXByelR+rZxakc9Ae6rPRDsQfNN+sZwhT3NKwS8USn05TaTGJroJu1otSiMBpSVy24h0lpLA8dtS/wmmr8QkHyTeY7CLDdt+++v077ekyMj3m5eYpljXdnl/Op+KZuSnus= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ffTFN/wJ; arc=none smtp.client-ip=209.85.222.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ffTFN/wJ" Received: by mail-qk1-f174.google.com with SMTP id af79cd13be357-7b7041273ddso819124385a.3 for ; Thu, 02 Jan 2025 08:46:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836363; x=1736441163; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=o/kBecojtJbJEwGGJ7ydPliof2m9e4Ne+qfAhthVE5E=; b=ffTFN/wJe/4F5TJ+11eS1Gw0sGzx0b7aq/qYialwdWsBiECSYoIjfqmOm4gf1Y2zEn xFxKUNNRmERvjlF++tn60FyqM6O92SYTbhu4bTp0v6XL3QjbgMNLR7/X5YwYDr45Y75Y RRqtBir0mJ4mUS3nJ/FcwgNWtyrvvgXbRGQOteNuHPFSYBorv+vRCt+8vb1brpsYJVju 7ItfsoqEJqMDuTPvEPuaAIPKAF+qaXbL3rkJw8XMUj33ol/ezQpUBoGjRE7ATskZxQ7L PAWX4yzaRcWgfxiqOZeo+UvDS3x8Y31p6k3/noBptbXRbqFwbQDQFOZuti6Uw6e8TVzO EZ3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836363; x=1736441163; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=o/kBecojtJbJEwGGJ7ydPliof2m9e4Ne+qfAhthVE5E=; b=w/ftaAzhJWGLP2t7L4ueEXGZ8qeakPbCOmTg2y1/TvuheVeWPyeWMg1CfIQGUad8Wg KV7V/70jhfIP+1daCHHR6qpGKX3fhSrLpxjylpH+QlDv7P12S/G9kYHjfH5N1svn9tOx zfoEBGnP6SAYgn0rmPPd23yFzJrfWrfEBTiGCfUUEZuRwhavT+g36eZ8Hcf4QcRLRKQR +lHhkwoIAGT9jWlBPJy6r8EVHXONdnTpWM0DL5pZ6o8hUCmMct/+LOUPNWWa3yWoHrkq 4QeznOcIYcVsXyzNww1fVmjZrTxy/2wtGfNgWsNQ4S9mPRB9RzsKEN2lFN22Br4jrFZF ub+g== X-Gm-Message-State: AOJu0YwY5OFPa4vLEqu1S8LFZnRbLvP7I26Yx0uZPs2kJQ4PhuGFVIGK q33+4nBJVTugHc/gYK5FWlQtXfY3XgcB5RRjNIY5jJL5ukHbVh+qJpV/DQ== X-Gm-Gg: ASbGnctMbOt+LS6CNVoKz8QkX8dhcT7887RjsCUP7ufNUbySIFDcp+gLOzyOibXTkl3 mdgCS8IJSnSo6IlDdiesMWt79bnqKeahVfxHYAZ8ogxZVV+iM8v4NgaSEVCZM8SchfeQ83RP+zb czQOyThuRWiFs0K1a+eXV7LRWoSEYnanD6bX/+HvuVA55/C0+oEksidR6XEU5Eb3QndhsgM+6zH CrNjsQ01G/tuEF2QW6++/6NZIBJG7fCfVoczIQhKjBrbHqNP/vyiL3maKnUW3l9l8SPRy2upVeL kp4f799psdhw9t4WhfuQNdWJQMxbJuS9zt3FktXUxHPpBMfOWdFTooTIC/yTHaqCd8F6MA== X-Google-Smtp-Source: AGHT+IEEQhXk+IRxWdEAO7MNHWAm1OVZkCKAjk8iWB8qLsU57IhEC2zwksDpscC+nFU3QTybCw8ORw== X-Received: by 2002:a05:620a:45a1:b0:7b6:f15c:3b1d with SMTP id af79cd13be357-7b9ba7c1d81mr5993000985a.32.1735836363526; Thu, 02 Jan 2025 08:46:03 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.46.03 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:46:03 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 42/44] selinux: exempt creation of init SELinux namespace from limits Date: Thu, 2 Jan 2025 11:45:07 -0500 Message-Id: <20250102164509.25606-43-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Exempt the creation of the init SELinux namespace from the maxns limit. It was already exempted from the maxnsdepth limit by virtue of only applying that check when there is a parent namespace. Otherwise, if one were to set CONFIG_SECURITY_SELINUX_MAXNS to 0, the creation of the init SELinux namespace would fail. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5ce0e2afd84f..8c0e44effdbc 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7635,7 +7635,7 @@ int selinux_state_create(const struct cred *cred) struct selinux_state *newstate; int rc; - if (atomic_read(&selinux_nsnum) >= selinux_maxns) + if (parent && atomic_read(&selinux_nsnum) >= selinux_maxns) return -ENOSPC; if (parent && parent->depth >= selinux_maxnsdepth) From patchwork Thu Jan 2 16:45:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924654 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qt1-f177.google.com (mail-qt1-f177.google.com [209.85.160.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D9D615B554 for ; Thu, 2 Jan 2025 16:46:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836368; cv=none; b=tUntjFenJKbfVR+PsOm3boNdAP+2nMeIMttdNB5l8dqqduBi+8GWL9jQM/c9GaXoXUqRsUHFMGsVEqIQ2VzjFZU4V5nYdwc+5wcXwBf3agSejfOs9gi+4o1PcEVmwU7RB+t39WIvAucAz/2Hp4vewBQUnPN9eLFCXHPMx4HsXWw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836368; c=relaxed/simple; bh=K8R8kC3jcmlf0rDFUv28CZDFUfJ0vqtVQSVDSGRDxvg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=m8y+KhTURb8bFHDRXQsKhDQxpbi1zE6M7G4hhjfvf9sXHpwO6JRQArKLDgkk5T2CEkXCkiF1YdZ/d2rPrPSKNsZWitBiY7W+3HXzyhvNQ/gleO8KjItyCVXkcCLZlCyCA08+Zan0ZAHE6eVJEM2+eJPR6Gmdu/J46osTMBw318I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MDU3xeh9; arc=none smtp.client-ip=209.85.160.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MDU3xeh9" Received: by mail-qt1-f177.google.com with SMTP id d75a77b69052e-467a3f1e667so66794931cf.0 for ; Thu, 02 Jan 2025 08:46:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836364; x=1736441164; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZRpte4Yj3L0lxneuJsucmfxqmY0Gdyz1zaBITUyNYP8=; b=MDU3xeh9hPwyY2cBQ18hKSzgEGVEWvL7lH3pRc2FoOpkjSVjGAfvR/ZNod6fV7O9dt WM62RDex/Qms6zbTJvVVisY7jj6MNR8+mDkOKL93m5uZTYoi3iwamT26MESFGMXHWS6U Ki1c64D/SY22bNJs8r6pWXbE69WL4nUTPuE49UX3lMoaX6J3PQhSfhSwB8NgbjiRvgZ+ qqsbMgA5VFe0PCltR09E7vlNnHXf5BvOZRsG5XFZ2me3CKG+2tl3GM+eVOYl0/94qkJd XOjEkW9EgTHza5LxTB8rKdKjMs6ZO/t78Ub9bBblWU0QHE0OKyUtebO8ldouf5fV8Ebf Sbdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836364; x=1736441164; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZRpte4Yj3L0lxneuJsucmfxqmY0Gdyz1zaBITUyNYP8=; b=SY8jSvpmUtkNWQ6AsCiAVicl2ykLRwNuMzcoyYOmw3vB2WKSnQVi/+dnSEXAp8JvKM Jk4Qyzr+KWmwXVkgnFQlF7j4AOvC5y1eqVowNem11IeD14OY1t362cp0sAh3F/CUFXLB T4hMEfB4zoJ0RVBk9Ms9kgXw7ygAyIKhAZXafXvJW6stQjnaQ1rFPYvZlsl4CFtLBxSZ ANagLIT8/m53LOBZfgI+++jLVP087UBtsp+QUEij+B5hO7A9lQ1u6Q/KoOMZAEBAF3QG jWfstaimTYyjgZze8/aLSeFBtEYC9qfmzTE5qNP2eu/ziBY9IWpBc6Iff9FrWkxQkJLB GsCA== X-Gm-Message-State: AOJu0Yx+r1fRRbldWOH+U1mH6l/Xj45zhJteGhu5Jt6YB0dZT4kE1O6A d0khYNE6wKBgcm4Rhe4LaNLYKTPQi/IP3/GrPNL+nAud1olUPimKXAgTWQ== X-Gm-Gg: ASbGncs/9b9aCrfUs8W4moEY2zziSkjwl2TrHw/9ola4VyUjo4m+Duf3YUACeErZAii GCnEFD12DQfZIE365HPCNd6HhTaCCrPkSkpXijIqr8zjHfcV01Icf1NTTTfYP5MmcU67U/jY0LY rLdL//eJQ+be8tnemBeuNgCDKjhiO+cr9dRqgebkFXEdKAUqJL+LdA/sovZwdlJFSH0GvmqgW6n 83+p5P4NCVwbnznulYtTLNhWt276nKHweFlJMT81Vb2UlbfQjP4NzN2FUiRUBmHEy+4rLcPTOUa p6EKf/XHYQ0D6l9ObRV5xyZVXdrOhc71KUCQ8KtOtlGH8gN5gUxheThB/7HYiY7Xh1bTlQ== X-Google-Smtp-Source: AGHT+IHj+jiISNkqg/TKfNxAlmeSW9VyqQL4jLiVFvRCCXPBOvMkevROIcQZWtX7DNqktmBINUnJbw== X-Received: by 2002:ac8:5d51:0:b0:467:5144:8374 with SMTP id d75a77b69052e-46a4a8eb034mr685568111cf.25.1735836364079; Thu, 02 Jan 2025 08:46:04 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.46.03 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:46:03 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 43/44] selinux: introduce a Kconfig option for SELinux namespaces Date: Thu, 2 Jan 2025 11:45:08 -0500 Message-Id: <20250102164509.25606-44-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce a separate SECURITY_SELINUX_NS Kconfig option for enabling SELinux namespaces and have it default to n since it is experimental. Make the SECURITY_SELINUX_MAXNS and SECURITY_SELINUX_MAXNSDEPTH Kconfig options depend on this new option. This option only controls whether the SELinux namespace support is exposed to userspace, not the underlying infrastructure support. When set to n, the kernel APIs for unsharing the SELinux namespace (/sys/fs/selinux/unshare) and for setting limits on SELinux namespaces (/sys/fs/selinux/{maxns,maxnsdepth}) are not created and only a single initial SELinux namespace is created during startup and associated with all tasks. When set to y, the kernel APIs are created and userspace can use them (if permitted by policy and constrained by the limits) to unshare the SELinux namespace. Signed-off-by: Stephen Smalley --- security/selinux/Kconfig | 42 +++++++++++++++++++++++++++++++++--- security/selinux/hooks.c | 4 ++++ security/selinux/selinuxfs.c | 7 +++++- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 82db54462253..aa25da389c46 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -88,10 +88,46 @@ config SECURITY_SELINUX_DEBUG echo -n 'file "security/selinux/*" +p' > \ /proc/dynamic_debug/control +config SECURITY_SELINUX_NS + bool "SELinux namespace support (experimental)" + depends on SECURITY_SELINUX + default n + help + This enables (experimental) support for SELinux namespaces, + i.e the ability to create multiple SELinux namespaces where + each namespace has its own independent enforcing mode, + AVC, and policy, accessible through its own independent + selinuxfs instance. When a task unshares its SELinux namespace, + it is associated with a new child namespace whose initial + state is permissive with no policy loaded, and the task is assigned + a separate SID in the new namespace, initially the kernel SID, + which is likewise independent of its SID in ancestor namespaces. + Subsequent actions by the task and its descendants are checked + against the new namespace and all ancestor namespaces, using the + SID it has in each namespace for that namespace's checks. Objects + like inodes only have a single SID irrespective of the namespace + in which they are created or accessed. If the context associated + with a SID is not defined in a namespace, then it is treated as + the unlabeled SID for access checking purposes in that namespace. + The current kernel API for unsharing the SELinux namespace is to + write a "1" to /sys/fs/selinux/unshare; this is likely to change + before upstreaming. Experimental patches for libselinux and + systemd to use this support can be found in the selinuxns + branches of https://github.com/stephensmalley/selinux, which + provides a selinux_unshare() API that wraps the kernel interface, + and https://github.com/stephensmalley/systemd, which has + a modified systemd-nspawn that uses this API when called + with --selinux-namespace and a modified systemd to perform + SELinux initialization when started within a container that + has its own SELinux namespace. Userspace can also detect + whether it is running in a non-init SELinux namespace by + reading /sys/fs/selinux/unshare ("1" means it has been unshared, + "0" means it has not) but an API for this might not be retained. + config SECURITY_SELINUX_MAXNS int "SELinux default maximum number of namespaces" - depends on SECURITY_SELINUX - range 0 65535 + depends on SECURITY_SELINUX_NS + range 1 65535 default 65535 help This option sets the default maximum number of SELinux namespaces. @@ -99,7 +135,7 @@ config SECURITY_SELINUX_MAXNS config SECURITY_SELINUX_MAXNSDEPTH int "SELinux default maximum depth of namespaces" - depends on SECURITY_SELINUX + depends on SECURITY_SELINUX_NS range 0 32 default 32 help diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8c0e44effdbc..a6c980f9117b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7622,8 +7622,10 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { static void selinux_state_free(struct work_struct *work); +#ifdef CONFIG_SECURITY_SELINUX_NS unsigned int selinux_maxns = CONFIG_SECURITY_SELINUX_MAXNS; unsigned int selinux_maxnsdepth = CONFIG_SECURITY_SELINUX_MAXNSDEPTH; +#endif static atomic_t selinux_nsnum = ATOMIC_INIT(0); @@ -7635,11 +7637,13 @@ int selinux_state_create(const struct cred *cred) struct selinux_state *newstate; int rc; +#ifdef CONFIG_SECURITY_SELINUX_NS if (parent && atomic_read(&selinux_nsnum) >= selinux_maxns) return -ENOSPC; if (parent && parent->depth >= selinux_maxnsdepth) return -ENOSPC; +#endif newstate = kzalloc(sizeof(*newstate), GFP_KERNEL); if (!newstate) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index efceb3ac9157..785991d77166 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -65,9 +65,11 @@ enum sel_inos { SEL_STATUS, /* export current status using mmap() */ SEL_POLICY, /* allow userspace to read the in kernel policy */ SEL_VALIDATE_TRANS, /* compute validatetrans decision */ +#ifdef CONFIG_SECURITY_SELINUX_NS SEL_UNSHARE, /* unshare selinux namespace */ SEL_MAXNS, /* maximum number of SELinux namespaces */ SEL_MAXNSDEPTH, /* maximum depth of SELinux namespaces */ +#endif SEL_INO_NEXT, /* The next inode number to use */ }; @@ -329,6 +331,7 @@ static const struct file_operations sel_disable_ops = { .llseek = generic_file_llseek, }; +#ifdef CONFIG_SECURITY_SELINUX_NS static ssize_t sel_read_unshare(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { @@ -531,7 +534,7 @@ static const struct file_operations sel_maxnsdepth_ops = { .write = sel_write_maxnsdepth, .llseek = generic_file_llseek, }; - +#endif static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, size_t count, loff_t *ppos) @@ -2353,9 +2356,11 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc) [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO}, [SEL_VALIDATE_TRANS] = {"validatetrans", &sel_transition_ops, S_IWUGO}, +#ifdef CONFIG_SECURITY_SELINUX_NS [SEL_UNSHARE] = {"unshare", &sel_unshare_ops, 0600}, [SEL_MAXNS] = {"maxns", &sel_maxns_ops, 0600}, [SEL_MAXNSDEPTH] = {"maxnsdepth", &sel_maxnsdepth_ops, 0600}, +#endif /* last one */ {""} }; From patchwork Thu Jan 2 16:45:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Smalley X-Patchwork-Id: 13924655 X-Patchwork-Delegate: paul@paul-moore.com Received: from mail-qk1-f173.google.com (mail-qk1-f173.google.com [209.85.222.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F384E1547C0 for ; Thu, 2 Jan 2025 16:46:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836370; cv=none; b=ssY69Iorl8ZdYl+4KCSxP2BcY5iYQXysz0YEs4phmfC/B4LLqLadP2DIggJzuyJN+vmlo+/wujjnt1WS7pBaMV0zSiCG3Br9GcEbqfteyjniTRDTCEu4Vhk5OWYMah/A6ARksqdcPHHvtMazq/kDFuJ1Imfn3KdUjJ1IBCRLZUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735836370; c=relaxed/simple; bh=+iZpS2Rr1b/5SWTrq6fU9FOEkkYcEP/Ggj4ViT0wFNI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=V481wETQoupFDcHoRrQoVW8vOkboDeCnt9hwd3oJlx9iVmbUzAmu8kJr+Ock/Uo4y+zL2n+b79fcczpypITrrrZ7nnCILdllD6JFRD9xLi4ghlbEA0B+GfCIsTcCiHZPUSziP9TwZbxYBE9kPONAwFtB+UhfQdSYe0J/bro13eY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WRqNitaJ; arc=none smtp.client-ip=209.85.222.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WRqNitaJ" Received: by mail-qk1-f173.google.com with SMTP id af79cd13be357-7b6e8814842so991322685a.0 for ; Thu, 02 Jan 2025 08:46:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735836365; x=1736441165; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YeDvGkxIoG2pQKa7PHtBx1HxqggtqDBJK5ahsNF77fc=; b=WRqNitaJRwi9dV9ieqEQWSR6sNmvQzJyyiA349BRe9WiXuLJYm6nrmAxxt/bYK8I3G HKdNRrLS7yWeUzwW5KTKsNR6EVhNZJseoEJeloalyJnj7HjXtBb+YIodHjYbkQp0NSl8 wUZlhI8lSn9mdSuV/qi1HuLrlkc5ej24Ll0kKCAzFE8Se+I8RKtIFWHpLrmVCNe2/+Qi S8CrZydHGJXmynXOtc5z1meK9pO6f88ugr2hv0e182xTwDURUG/XKhjoUmYfX/B8aEOZ XdfHkVd988vIiezwFnprtAiUxZKZLeb6hMLeNH8kibbFwGfdsImfCG3JHPzX5ZYnl3z5 W6/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735836365; x=1736441165; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YeDvGkxIoG2pQKa7PHtBx1HxqggtqDBJK5ahsNF77fc=; b=Ju3cOEhSLV7baxzO8IJGgvo0tRTs09tmuvcxkfH1uKYIIGp5Yslh8ofLAVnGCigaln J3iVlIrxAUcTxt7RV8qkJ8gWvZTP1SMSwgCPem9dVM5lL9+dUkpGI3bYvWa0imTZ8VRj sosN967LgbxFdaxwW0t6iHKOFW+i9Mutxk7sN9zzrXLZCaUlxNvpOVgMaOIqHypKCVek q7eOZNt16WjPWnqdKrKuqvSRjEaqJTOevIQNHk3fBsjByU+Gkn1ASNuoLlhD6TLrxcgh n6WGvnD4S7aXSrAgfAz5xzQMIlKxGWsGE8du+hSkPGKigf6zq2rJpdJ/7Ucu1cMfs3Dh 0xTQ== X-Gm-Message-State: AOJu0YyXy0BsQ5KDX4FJs3QTfykqyXNAKBaNldOo036wV2jphwqZDs0y jPkBQ8PC01GFf4pq6ghC+6NhpfQ3lPE72hk5aOruVsns4Q3WpiNjZB+X7g== X-Gm-Gg: ASbGncvEkeNbGKy9LAbm/QBY3LrPG0yAaG8bFfda+EVkwyXFu0Nws5t66xEnDJwSJCE zNAlRbaDF3knQGCilJ0ZD8QbjtXTwHqdlWwz5DBcEg5ooU6h1Cy2kQUFuWXTDWgqmqei3uso8PC xawbiN7Ca5o93XbNxYwJ7M5nbugXJVtt+rvw3dfy7ELeY7WQ3xFHYdSMt4lfyRAsDGOyQjrF2EF /s5i1vr/pEPl+io6/rkq0LB0TNKzFZ/paHtP1RgIMHi56/Mp65N9WcANGmq9j2e5LgxKqOas3qn +0T0xfKHVyTODDo7oJiKlskxLcxLjNCPyMH7Abmpo8fEVoZ53bRnKORJ9UeTb6QvUJ/FMA== X-Google-Smtp-Source: AGHT+IEi9WSUdQocLTMkARF2ziQEnyawHYcEjRuV0AjP8twKBNDZD3/BgzOeTCdp4dbvhfER9I2BYA== X-Received: by 2002:a05:620a:650a:b0:7b6:6634:5a42 with SMTP id af79cd13be357-7b9ba79b290mr6575707985a.23.1735836365253; Thu, 02 Jan 2025 08:46:05 -0800 (PST) Received: from a-gady2p56i3do.evoforge.org (ec2-52-70-167-183.compute-1.amazonaws.com. [52.70.167.183]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-46a3eb19684sm136795101cf.58.2025.01.02.08.46.04 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jan 2025 08:46:04 -0800 (PST) From: Stephen Smalley To: selinux@vger.kernel.org Cc: paul@paul-moore.com, omosnace@redhat.com, Stephen Smalley Subject: [RFC PATCH 44/44] selinux: fix inode initialization when no namespace is initialized Date: Thu, 2 Jan 2025 11:45:09 -0500 Message-Id: <20250102164509.25606-45-stephen.smalley.work@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20250102164509.25606-1-stephen.smalley.work@gmail.com> References: <20250102164509.25606-1-stephen.smalley.work@gmail.com> Precedence: bulk X-Mailing-List: selinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 commit e8087cb36d3d2c6eab77 ("selinux: init inode from nearest initialized namespace") wrongly assumed that there must be at least one ancestor namespace that is initialized. In the case where the init SELinux namespace was never initialized (i.e. no policy loaded on the host), then this assumption can be false. Fix the logic to defer initialization of the inode in that situation. Signed-off-by: Stephen Smalley --- security/selinux/hooks.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a6c980f9117b..da8f76707c8c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1441,8 +1441,14 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if (isec->sclass == SECCLASS_FILE) isec->sclass = inode_mode_to_security_class(inode->i_mode); + /* + * Find an initialized state to use. + */ + while (state && !selinux_initialized(state)) + state = state->parent; + sbsec = selinux_superblock(inode->i_sb); - if (!(sbsec->flags & SE_SBINITIALIZED)) { + if (!state || !(sbsec->flags & SE_SBINITIALIZED)) { /* Defer initialization until selinux_complete_init, after the initial policy is loaded and the security server is ready to handle calls. */ @@ -1453,13 +1459,6 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out_unlock; } - /* - * Find an initialized state to use; there must be at least - * one or else the sbsec won't have been initialized. - */ - while (!selinux_initialized(state)) - state = state->parent; - sclass = isec->sclass; task_sid = isec->task_sid; sid = isec->sid;