Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

landlock: Define access_mask_t to enforce a consistent access mask size

Create and use the access_mask_t typedef to enforce a consistent access
mask size and uniformly use a 16-bits type. This will helps transition
to a 32-bits value one day.

Add a build check to make sure all (filesystem) access rights fit in.
This will be extended with a following commit.

Reviewed-by: Paul Moore <paul@paul-moore.com>
Link: https://lore.kernel.org/r/20220506161102.525323-2-mic@digikod.net
Cc: stable@vger.kernel.org
Signed-off-by: Mickaël Salaün <mic@digikod.net>

+30 -15
+11 -8
security/landlock/fs.c
··· 152 152 * @path: Should have been checked by get_path_from_fd(). 153 153 */ 154 154 int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, 155 - const struct path *const path, u32 access_rights) 155 + const struct path *const path, 156 + access_mask_t access_rights) 156 157 { 157 158 int err; 158 159 struct landlock_object *object; ··· 185 184 186 185 static inline u64 unmask_layers(const struct landlock_ruleset *const domain, 187 186 const struct path *const path, 188 - const u32 access_request, u64 layer_mask) 187 + const access_mask_t access_request, 188 + u64 layer_mask) 189 189 { 190 190 const struct landlock_rule *rule; 191 191 const struct inode *inode; ··· 226 224 } 227 225 228 226 static int check_access_path(const struct landlock_ruleset *const domain, 229 - const struct path *const path, u32 access_request) 227 + const struct path *const path, 228 + const access_mask_t access_request) 230 229 { 231 230 bool allowed = false; 232 231 struct path walker_path; ··· 312 309 } 313 310 314 311 static inline int current_check_access_path(const struct path *const path, 315 - const u32 access_request) 312 + const access_mask_t access_request) 316 313 { 317 314 const struct landlock_ruleset *const dom = 318 315 landlock_get_current_domain(); ··· 515 512 516 513 /* Path hooks */ 517 514 518 - static inline u32 get_mode_access(const umode_t mode) 515 + static inline access_mask_t get_mode_access(const umode_t mode) 519 516 { 520 517 switch (mode & S_IFMT) { 521 518 case S_IFLNK: ··· 568 565 get_mode_access(d_backing_inode(old_dentry)->i_mode)); 569 566 } 570 567 571 - static inline u32 maybe_remove(const struct dentry *const dentry) 568 + static inline access_mask_t maybe_remove(const struct dentry *const dentry) 572 569 { 573 570 if (d_is_negative(dentry)) 574 571 return 0; ··· 638 635 639 636 /* File hooks */ 640 637 641 - static inline u32 get_file_access(const struct file *const file) 638 + static inline access_mask_t get_file_access(const struct file *const file) 642 639 { 643 - u32 access = 0; 640 + access_mask_t access = 0; 644 641 645 642 if (file->f_mode & FMODE_READ) { 646 643 /* A directory can only be opened in read mode. */
+1 -1
security/landlock/fs.h
··· 66 66 67 67 int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, 68 68 const struct path *const path, 69 - u32 access_hierarchy); 69 + access_mask_t access_hierarchy); 70 70 71 71 #endif /* _SECURITY_LANDLOCK_FS_H */
+2
security/landlock/limits.h
··· 9 9 #ifndef _SECURITY_LANDLOCK_LIMITS_H 10 10 #define _SECURITY_LANDLOCK_LIMITS_H 11 11 12 + #include <linux/bitops.h> 12 13 #include <linux/limits.h> 13 14 #include <uapi/linux/landlock.h> 14 15 ··· 20 19 21 20 #define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_MAKE_SYM 22 21 #define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1) 22 + #define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS) 23 23 24 24 /* clang-format on */ 25 25
+4 -2
security/landlock/ruleset.c
··· 45 45 return new_ruleset; 46 46 } 47 47 48 - struct landlock_ruleset *landlock_create_ruleset(const u32 fs_access_mask) 48 + struct landlock_ruleset * 49 + landlock_create_ruleset(const access_mask_t fs_access_mask) 49 50 { 50 51 struct landlock_ruleset *new_ruleset; 51 52 ··· 229 228 230 229 /* @ruleset must be locked by the caller. */ 231 230 int landlock_insert_rule(struct landlock_ruleset *const ruleset, 232 - struct landlock_object *const object, const u32 access) 231 + struct landlock_object *const object, 232 + const access_mask_t access) 233 233 { 234 234 struct landlock_layer layers[] = { { 235 235 .access = access,
+12 -4
security/landlock/ruleset.h
··· 9 9 #ifndef _SECURITY_LANDLOCK_RULESET_H 10 10 #define _SECURITY_LANDLOCK_RULESET_H 11 11 12 + #include <linux/bitops.h> 13 + #include <linux/build_bug.h> 12 14 #include <linux/mutex.h> 13 15 #include <linux/rbtree.h> 14 16 #include <linux/refcount.h> 15 17 #include <linux/workqueue.h> 16 18 19 + #include "limits.h" 17 20 #include "object.h" 21 + 22 + typedef u16 access_mask_t; 23 + /* Makes sure all filesystem access rights can be stored. */ 24 + static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS); 18 25 19 26 /** 20 27 * struct landlock_layer - Access rights for a given layer ··· 35 28 * @access: Bitfield of allowed actions on the kernel object. They are 36 29 * relative to the object type (e.g. %LANDLOCK_ACTION_FS_READ). 37 30 */ 38 - u16 access; 31 + access_mask_t access; 39 32 }; 40 33 41 34 /** ··· 142 135 * layers are set once and never changed for the 143 136 * lifetime of the ruleset. 144 137 */ 145 - u16 fs_access_masks[]; 138 + access_mask_t fs_access_masks[]; 146 139 }; 147 140 }; 148 141 }; 149 142 150 - struct landlock_ruleset *landlock_create_ruleset(const u32 fs_access_mask); 143 + struct landlock_ruleset * 144 + landlock_create_ruleset(const access_mask_t fs_access_mask); 151 145 152 146 void landlock_put_ruleset(struct landlock_ruleset *const ruleset); 153 147 void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset); 154 148 155 149 int landlock_insert_rule(struct landlock_ruleset *const ruleset, 156 150 struct landlock_object *const object, 157 - const u32 access); 151 + const access_mask_t access); 158 152 159 153 struct landlock_ruleset * 160 154 landlock_merge_ruleset(struct landlock_ruleset *const parent,