/* SPDX-License-Identifier: GPL-2.0-only */1/*2* Landlock - Credential hooks3*4* Copyright © 2019-2020 Mickaël Salaün <[email protected]>5* Copyright © 2019-2020 ANSSI6* Copyright © 2021-2025 Microsoft Corporation7*/89#ifndef _SECURITY_LANDLOCK_CRED_H10#define _SECURITY_LANDLOCK_CRED_H1112#include <linux/container_of.h>13#include <linux/cred.h>14#include <linux/init.h>15#include <linux/rcupdate.h>1617#include "access.h"18#include "limits.h"19#include "ruleset.h"20#include "setup.h"2122/**23* struct landlock_cred_security - Credential security blob24*25* This structure is packed to minimize the size of struct26* landlock_file_security. However, it is always aligned in the LSM cred blob,27* see lsm_set_blob_size().28*/29struct landlock_cred_security {30/**31* @domain: Immutable ruleset enforced on a task.32*/33struct landlock_ruleset *domain;3435#ifdef CONFIG_AUDIT36/**37* @domain_exec: Bitmask identifying the domain layers that were enforced by38* the current task's executed file (i.e. no new execve(2) since39* landlock_restrict_self(2)).40*/41u16 domain_exec;42/**43* @log_subdomains_off: Set if the domain descendants's log_status should be44* set to %LANDLOCK_LOG_DISABLED. This is not a landlock_hierarchy45* configuration because it applies to future descendant domains and it does46* not require a current domain.47*/48u8 log_subdomains_off : 1;49#endif /* CONFIG_AUDIT */50} __packed;5152#ifdef CONFIG_AUDIT5354/* Makes sure all layer executions can be stored. */55static_assert(BITS_PER_TYPE(typeof_member(struct landlock_cred_security,56domain_exec)) >=57LANDLOCK_MAX_NUM_LAYERS);5859#endif /* CONFIG_AUDIT */6061static inline struct landlock_cred_security *62landlock_cred(const struct cred *cred)63{64return cred->security + landlock_blob_sizes.lbs_cred;65}6667static inline struct landlock_ruleset *landlock_get_current_domain(void)68{69return landlock_cred(current_cred())->domain;70}7172/*73* The call needs to come from an RCU read-side critical section.74*/75static inline const struct landlock_ruleset *76landlock_get_task_domain(const struct task_struct *const task)77{78return landlock_cred(__task_cred(task))->domain;79}8081static inline bool landlocked(const struct task_struct *const task)82{83bool has_dom;8485if (task == current)86return !!landlock_get_current_domain();8788rcu_read_lock();89has_dom = !!landlock_get_task_domain(task);90rcu_read_unlock();91return has_dom;92}9394/**95* landlock_get_applicable_subject - Return the subject's Landlock credential96* if its enforced domain applies to (i.e.97* handles) at least one of the access rights98* specified in @masks99*100* @cred: credential101* @masks: access masks102* @handle_layer: returned youngest layer handling a subset of @masks. Not set103* if the function returns NULL.104*105* Returns: landlock_cred(@cred) if any access rights specified in @masks is106* handled, or NULL otherwise.107*/108static inline const struct landlock_cred_security *109landlock_get_applicable_subject(const struct cred *const cred,110const struct access_masks masks,111size_t *const handle_layer)112{113const union access_masks_all masks_all = {114.masks = masks,115};116const struct landlock_ruleset *domain;117ssize_t layer_level;118119if (!cred)120return NULL;121122domain = landlock_cred(cred)->domain;123if (!domain)124return NULL;125126for (layer_level = domain->num_layers - 1; layer_level >= 0;127layer_level--) {128union access_masks_all layer = {129.masks = domain->access_masks[layer_level],130};131132if (layer.all & masks_all.all) {133if (handle_layer)134*handle_layer = layer_level;135136return landlock_cred(cred);137}138}139140return NULL;141}142143__init void landlock_add_cred_hooks(void);144145#endif /* _SECURITY_LANDLOCK_CRED_H */146147148