/* SPDX-License-Identifier: GPL-2.0-only */ /* * Landlock - Access types and helpers * * Copyright © 2016-2020 Mickaël Salaün * Copyright © 2018-2020 ANSSI * Copyright © 2024-2025 Microsoft Corporation */ #ifndef _SECURITY_LANDLOCK_ACCESS_H #define _SECURITY_LANDLOCK_ACCESS_H #include #include #include #include #include "limits.h" /* * All access rights that are denied by default whether they are handled or not * by a ruleset/layer. This must be ORed with all ruleset->access_masks[] * entries when we need to get the absolute handled access masks, see * landlock_upgrade_handled_access_masks(). */ /* clang-format off */ #define _LANDLOCK_ACCESS_FS_INITIALLY_DENIED ( \ LANDLOCK_ACCESS_FS_REFER) /* clang-format on */ /* clang-format off */ #define _LANDLOCK_ACCESS_FS_OPTIONAL ( \ LANDLOCK_ACCESS_FS_TRUNCATE | \ LANDLOCK_ACCESS_FS_IOCTL_DEV) /* clang-format on */ typedef u16 access_mask_t; /* Makes sure all filesystem access rights can be stored. */ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS); /* Makes sure all network access rights can be stored. */ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_NET); /* Makes sure all scoped rights can be stored. */ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_SCOPE); /* Makes sure for_each_set_bit() and for_each_clear_bit() calls are OK. */ static_assert(sizeof(unsigned long) >= sizeof(access_mask_t)); /* Ruleset access masks. */ struct access_masks { access_mask_t fs : LANDLOCK_NUM_ACCESS_FS; access_mask_t net : LANDLOCK_NUM_ACCESS_NET; access_mask_t scope : LANDLOCK_NUM_SCOPE; }; union access_masks_all { struct access_masks masks; u32 all; }; /* Makes sure all fields are covered. */ static_assert(sizeof(typeof_member(union access_masks_all, masks)) == sizeof(typeof_member(union access_masks_all, all))); /** * struct layer_access_masks - A boolean matrix of layers and access rights * * This has a bit for each combination of layer numbers and access rights. * During access checks, it is used to represent the access rights for each * layer which still need to be fulfilled. When all bits are 0, the access * request is considered to be fulfilled. */ struct layer_access_masks { /** * @access: The unfulfilled access rights for each layer. */ access_mask_t access[LANDLOCK_MAX_NUM_LAYERS]; }; /* * Tracks domains responsible of a denied access. This avoids storing in each * object the full matrix of per-layer unfulfilled access rights, which is * required by update_request(). * * Each nibble represents the layer index of the newest layer which denied a * certain access right. For file system access rights, the upper four bits are * the index of the layer which denies LANDLOCK_ACCESS_FS_IOCTL_DEV and the * lower nibble represents LANDLOCK_ACCESS_FS_TRUNCATE. */ typedef u8 deny_masks_t; /* * Makes sure all optional access rights can be tied to a layer index (cf. * get_deny_mask). */ static_assert(BITS_PER_TYPE(deny_masks_t) >= (HWEIGHT(LANDLOCK_MAX_NUM_LAYERS - 1) * HWEIGHT(_LANDLOCK_ACCESS_FS_OPTIONAL))); /* LANDLOCK_MAX_NUM_LAYERS must be a power of two (cf. deny_masks_t assert). */ static_assert(HWEIGHT(LANDLOCK_MAX_NUM_LAYERS) == 1); /* Upgrades with all initially denied by default access rights. */ static inline struct access_masks landlock_upgrade_handled_access_masks(struct access_masks access_masks) { /* * All access rights that are denied by default whether they are * explicitly handled or not. */ if (access_masks.fs) access_masks.fs |= _LANDLOCK_ACCESS_FS_INITIALLY_DENIED; return access_masks; } /* Checks the subset relation between access masks. */ static inline bool access_mask_subset(access_mask_t subset, access_mask_t superset) { return (subset | superset) == superset; } #endif /* _SECURITY_LANDLOCK_ACCESS_H */