landlock: Use bit-fields for storing handled layer access masks
When defined using bit-fields, the compiler takes care of packing the bits in a memory-efficient way and frees us from defining LANDLOCK_SHIFT_ACCESS_* by hand. The exact memory layout does not matter in our use case. The manual definition of LANDLOCK_SHIFT_ACCESS_* has resulted in bugs in at least two recent patch sets [1] [2] where new kinds of handled access rights were introduced. Cc: Mikhail Ivanov <ivanov.mikhail1@huawei-partners.com> Cc: Tahera Fahimi <fahimitahera@gmail.com> Link: https://lore.kernel.org/r/ebd680cc-25d6-ee14-4856-310f5e5e28e4@huawei-partners.com [1] Link: https://lore.kernel.org/r/ZmLEoBfHyUR3nKAV@google.com [2] Signed-off-by: Günther Noack <gnoack@google.com> Link: https://lore.kernel.org/r/20240610082115.1693267-1-gnoack@google.com Signed-off-by: Mickaël Salaün <mic@digikod.net>
This commit is contained in:
parent
256abd8e55
commit
395a02d04e
@ -21,12 +21,10 @@
|
|||||||
#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_IOCTL_DEV
|
#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_IOCTL_DEV
|
||||||
#define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1)
|
#define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1)
|
||||||
#define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS)
|
#define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS)
|
||||||
#define LANDLOCK_SHIFT_ACCESS_FS 0
|
|
||||||
|
|
||||||
#define LANDLOCK_LAST_ACCESS_NET LANDLOCK_ACCESS_NET_CONNECT_TCP
|
#define LANDLOCK_LAST_ACCESS_NET LANDLOCK_ACCESS_NET_CONNECT_TCP
|
||||||
#define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1)
|
#define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1)
|
||||||
#define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET)
|
#define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET)
|
||||||
#define LANDLOCK_SHIFT_ACCESS_NET LANDLOCK_NUM_ACCESS_FS
|
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
|
@ -169,13 +169,9 @@ static void build_check_ruleset(void)
|
|||||||
.num_rules = ~0,
|
.num_rules = ~0,
|
||||||
.num_layers = ~0,
|
.num_layers = ~0,
|
||||||
};
|
};
|
||||||
typeof(ruleset.access_masks[0]) access_masks = ~0;
|
|
||||||
|
|
||||||
BUILD_BUG_ON(ruleset.num_rules < LANDLOCK_MAX_NUM_RULES);
|
BUILD_BUG_ON(ruleset.num_rules < LANDLOCK_MAX_NUM_RULES);
|
||||||
BUILD_BUG_ON(ruleset.num_layers < LANDLOCK_MAX_NUM_LAYERS);
|
BUILD_BUG_ON(ruleset.num_layers < LANDLOCK_MAX_NUM_LAYERS);
|
||||||
BUILD_BUG_ON(access_masks <
|
|
||||||
((LANDLOCK_MASK_ACCESS_FS << LANDLOCK_SHIFT_ACCESS_FS) |
|
|
||||||
(LANDLOCK_MASK_ACCESS_NET << LANDLOCK_SHIFT_ACCESS_NET)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,10 +39,10 @@ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_NET);
|
|||||||
static_assert(sizeof(unsigned long) >= sizeof(access_mask_t));
|
static_assert(sizeof(unsigned long) >= sizeof(access_mask_t));
|
||||||
|
|
||||||
/* Ruleset access masks. */
|
/* Ruleset access masks. */
|
||||||
typedef u32 access_masks_t;
|
struct access_masks {
|
||||||
/* Makes sure all ruleset access rights can be stored. */
|
access_mask_t fs : LANDLOCK_NUM_ACCESS_FS;
|
||||||
static_assert(BITS_PER_TYPE(access_masks_t) >=
|
access_mask_t net : LANDLOCK_NUM_ACCESS_NET;
|
||||||
LANDLOCK_NUM_ACCESS_FS + LANDLOCK_NUM_ACCESS_NET);
|
};
|
||||||
|
|
||||||
typedef u16 layer_mask_t;
|
typedef u16 layer_mask_t;
|
||||||
/* Makes sure all layers can be checked. */
|
/* Makes sure all layers can be checked. */
|
||||||
@ -226,7 +226,7 @@ struct landlock_ruleset {
|
|||||||
* layers are set once and never changed for the
|
* layers are set once and never changed for the
|
||||||
* lifetime of the ruleset.
|
* lifetime of the ruleset.
|
||||||
*/
|
*/
|
||||||
access_masks_t access_masks[];
|
struct access_masks access_masks[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -265,8 +265,7 @@ landlock_add_fs_access_mask(struct landlock_ruleset *const ruleset,
|
|||||||
|
|
||||||
/* Should already be checked in sys_landlock_create_ruleset(). */
|
/* Should already be checked in sys_landlock_create_ruleset(). */
|
||||||
WARN_ON_ONCE(fs_access_mask != fs_mask);
|
WARN_ON_ONCE(fs_access_mask != fs_mask);
|
||||||
ruleset->access_masks[layer_level] |=
|
ruleset->access_masks[layer_level].fs |= fs_mask;
|
||||||
(fs_mask << LANDLOCK_SHIFT_ACCESS_FS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -278,17 +277,14 @@ landlock_add_net_access_mask(struct landlock_ruleset *const ruleset,
|
|||||||
|
|
||||||
/* Should already be checked in sys_landlock_create_ruleset(). */
|
/* Should already be checked in sys_landlock_create_ruleset(). */
|
||||||
WARN_ON_ONCE(net_access_mask != net_mask);
|
WARN_ON_ONCE(net_access_mask != net_mask);
|
||||||
ruleset->access_masks[layer_level] |=
|
ruleset->access_masks[layer_level].net |= net_mask;
|
||||||
(net_mask << LANDLOCK_SHIFT_ACCESS_NET);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline access_mask_t
|
static inline access_mask_t
|
||||||
landlock_get_raw_fs_access_mask(const struct landlock_ruleset *const ruleset,
|
landlock_get_raw_fs_access_mask(const struct landlock_ruleset *const ruleset,
|
||||||
const u16 layer_level)
|
const u16 layer_level)
|
||||||
{
|
{
|
||||||
return (ruleset->access_masks[layer_level] >>
|
return ruleset->access_masks[layer_level].fs;
|
||||||
LANDLOCK_SHIFT_ACCESS_FS) &
|
|
||||||
LANDLOCK_MASK_ACCESS_FS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline access_mask_t
|
static inline access_mask_t
|
||||||
@ -304,9 +300,7 @@ static inline access_mask_t
|
|||||||
landlock_get_net_access_mask(const struct landlock_ruleset *const ruleset,
|
landlock_get_net_access_mask(const struct landlock_ruleset *const ruleset,
|
||||||
const u16 layer_level)
|
const u16 layer_level)
|
||||||
{
|
{
|
||||||
return (ruleset->access_masks[layer_level] >>
|
return ruleset->access_masks[layer_level].net;
|
||||||
LANDLOCK_SHIFT_ACCESS_NET) &
|
|
||||||
LANDLOCK_MASK_ACCESS_NET;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool landlock_unmask_layers(const struct landlock_rule *const rule,
|
bool landlock_unmask_layers(const struct landlock_rule *const rule,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user