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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'lsm-pr-20260410' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm

Pull LSM updates from Paul Moore:
"We only have five patches in the LSM tree, but three of the five are
for an important bugfix relating to overlayfs and the mmap() and
mprotect() access controls for LSMs. Highlights below:

- Fix problems with the mmap() and mprotect() LSM hooks on overlayfs

As we are dealing with problems both in mmap() and mprotect() there
are essentially two components to this fix, spread across three
patches with all marked for stable.

The simplest portion of the fix is the creation of a new LSM hook,
security_mmap_backing_file(), that is used to enforce LSM mmap()
access controls on backing files in the stacked/overlayfs case. The
existing security_mmap_file() does not have visibility past the
user file. You can see from the associated SELinux hook callback
the code is fairly straightforward.

The mprotect() fix is a bit more complicated as there is no way in
the mprotect() code path to inspect both the user and backing
files, and bolting on a second file reference to vm_area_struct
wasn't really an option.

The solution taken here adds a LSM security blob and associated
hooks to the backing_file struct that LSMs can use to capture and
store relevant information from the user file. While the necessary
SELinux information is relatively small, a single u32, I expect
other LSMs to require more than that, and a dedicated backing_file
LSM blob provides a storage mechanism without negatively impacting
other filesystems.

I want to note that other LSMs beyond SELinux have been involved in
the discussion of the fixes presented here and they are working on
their own related changes using these new hooks, but due to other
issues those patches will be coming at a later date.

- Use kstrdup_const()/kfree_const() for securityfs symlink targets

- Resolve a handful of kernel-doc warnings in cred.h"

* tag 'lsm-pr-20260410' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm:
selinux: fix overlayfs mmap() and mprotect() access checks
lsm: add backing_file LSM hooks
fs: prepare for adding LSM blob to backing_file
securityfs: use kstrdup_const() to manage symlink targets
cred: fix kernel-doc warnings in cred.h

+431 -95
+13 -5
fs/backing-file.c
··· 12 12 #include <linux/backing-file.h> 13 13 #include <linux/splice.h> 14 14 #include <linux/mm.h> 15 + #include <linux/security.h> 15 16 16 17 #include "internal.h" 17 18 ··· 30 29 * returned file into a container structure that also stores the stacked 31 30 * file's path, which can be retrieved using backing_file_user_path(). 32 31 */ 33 - struct file *backing_file_open(const struct path *user_path, int flags, 32 + struct file *backing_file_open(const struct file *user_file, int flags, 34 33 const struct path *real_path, 35 34 const struct cred *cred) 36 35 { 36 + const struct path *user_path = &user_file->f_path; 37 37 struct file *f; 38 38 int error; 39 39 40 - f = alloc_empty_backing_file(flags, cred); 40 + f = alloc_empty_backing_file(flags, cred, user_file); 41 41 if (IS_ERR(f)) 42 42 return f; 43 43 ··· 54 52 } 55 53 EXPORT_SYMBOL_GPL(backing_file_open); 56 54 57 - struct file *backing_tmpfile_open(const struct path *user_path, int flags, 55 + struct file *backing_tmpfile_open(const struct file *user_file, int flags, 58 56 const struct path *real_parentpath, 59 57 umode_t mode, const struct cred *cred) 60 58 { 61 59 struct mnt_idmap *real_idmap = mnt_idmap(real_parentpath->mnt); 60 + const struct path *user_path = &user_file->f_path; 62 61 struct file *f; 63 62 int error; 64 63 65 - f = alloc_empty_backing_file(flags, cred); 64 + f = alloc_empty_backing_file(flags, cred, user_file); 66 65 if (IS_ERR(f)) 67 66 return f; 68 67 ··· 339 336 340 337 vma_set_file(vma, file); 341 338 342 - scoped_with_creds(ctx->cred) 339 + scoped_with_creds(ctx->cred) { 340 + ret = security_mmap_backing_file(vma, file, user_file); 341 + if (ret) 342 + return ret; 343 + 343 344 ret = vfs_mmap(vma->vm_file, vma); 345 + } 344 346 345 347 if (ctx->accessed) 346 348 ctx->accessed(user_file);
+9 -1
fs/erofs/ishare.c
··· 4 4 */ 5 5 #include <linux/xxhash.h> 6 6 #include <linux/mount.h> 7 + #include <linux/security.h> 7 8 #include "internal.h" 8 9 #include "xattr.h" 9 10 ··· 107 106 108 107 if (file->f_flags & O_DIRECT) 109 108 return -EINVAL; 110 - realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred()); 109 + realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred(), 110 + file); 111 111 if (IS_ERR(realfile)) 112 112 return PTR_ERR(realfile); 113 113 ihold(sharedinode); ··· 152 150 static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma) 153 151 { 154 152 struct file *realfile = file->private_data; 153 + int err; 155 154 156 155 vma_set_file(vma, realfile); 156 + 157 + err = security_mmap_backing_file(vma, realfile, file); 158 + if (err) 159 + return err; 160 + 157 161 return generic_file_readonly_mmap(file, vma); 158 162 } 159 163
+40 -3
fs/file_table.c
··· 54 54 struct path user_path; 55 55 freeptr_t bf_freeptr; 56 56 }; 57 + #ifdef CONFIG_SECURITY 58 + void *security; 59 + #endif 57 60 }; 58 61 59 62 #define backing_file(f) container_of(f, struct backing_file, file) ··· 73 70 } 74 71 EXPORT_SYMBOL_GPL(backing_file_set_user_path); 75 72 73 + #ifdef CONFIG_SECURITY 74 + void *backing_file_security(const struct file *f) 75 + { 76 + return backing_file(f)->security; 77 + } 78 + 79 + void backing_file_set_security(struct file *f, void *security) 80 + { 81 + backing_file(f)->security = security; 82 + } 83 + #endif /* CONFIG_SECURITY */ 84 + 85 + static inline void backing_file_free(struct backing_file *ff) 86 + { 87 + security_backing_file_free(&ff->file); 88 + path_put(&ff->user_path); 89 + kmem_cache_free(bfilp_cache, ff); 90 + } 91 + 76 92 static inline void file_free(struct file *f) 77 93 { 78 94 security_file_free(f); ··· 99 77 percpu_counter_dec(&nr_files); 100 78 put_cred(f->f_cred); 101 79 if (unlikely(f->f_mode & FMODE_BACKING)) { 102 - path_put(backing_file_user_path(f)); 103 - kmem_cache_free(bfilp_cache, backing_file(f)); 80 + backing_file_free(backing_file(f)); 104 81 } else { 105 82 kmem_cache_free(filp_cache, f); 106 83 } ··· 308 287 return f; 309 288 } 310 289 290 + static int init_backing_file(struct backing_file *ff, 291 + const struct file *user_file) 292 + { 293 + memset(&ff->user_path, 0, sizeof(ff->user_path)); 294 + backing_file_set_security(&ff->file, NULL); 295 + return security_backing_file_alloc(&ff->file, user_file); 296 + } 297 + 311 298 /* 312 299 * Variant of alloc_empty_file() that allocates a backing_file container 313 300 * and doesn't check and modify nr_files. ··· 323 294 * This is only for kernel internal use, and the allocate file must not be 324 295 * installed into file tables or such. 325 296 */ 326 - struct file *alloc_empty_backing_file(int flags, const struct cred *cred) 297 + struct file *alloc_empty_backing_file(int flags, const struct cred *cred, 298 + const struct file *user_file) 327 299 { 328 300 struct backing_file *ff; 329 301 int error; ··· 339 309 return ERR_PTR(error); 340 310 } 341 311 312 + /* The f_mode flags must be set before fput(). */ 342 313 ff->file.f_mode |= FMODE_BACKING | FMODE_NOACCOUNT; 314 + error = init_backing_file(ff, user_file); 315 + if (unlikely(error)) { 316 + fput(&ff->file); 317 + return ERR_PTR(error); 318 + } 319 + 343 320 return &ff->file; 344 321 } 345 322 EXPORT_SYMBOL_GPL(alloc_empty_backing_file);
+1 -1
fs/fuse/passthrough.c
··· 167 167 goto out; 168 168 169 169 /* Allocate backing file per fuse file to store fuse path */ 170 - backing_file = backing_file_open(&file->f_path, file->f_flags, 170 + backing_file = backing_file_open(file, file->f_flags, 171 171 &fb->file->f_path, fb->cred); 172 172 err = PTR_ERR(backing_file); 173 173 if (IS_ERR(backing_file)) {
+2 -1
fs/internal.h
··· 106 106 */ 107 107 struct file *alloc_empty_file(int flags, const struct cred *cred); 108 108 struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred); 109 - struct file *alloc_empty_backing_file(int flags, const struct cred *cred); 109 + struct file *alloc_empty_backing_file(int flags, const struct cred *cred, 110 + const struct file *user_file); 110 111 void backing_file_set_user_path(struct file *f, const struct path *path); 111 112 112 113 static inline void file_put_write_access(struct file *file)
+1 -1
fs/overlayfs/dir.c
··· 1389 1389 return PTR_ERR(cred); 1390 1390 1391 1391 ovl_path_upper(dentry->d_parent, &realparentpath); 1392 - realfile = backing_tmpfile_open(&file->f_path, flags, &realparentpath, 1392 + realfile = backing_tmpfile_open(file, flags, &realparentpath, 1393 1393 mode, current_cred()); 1394 1394 err = PTR_ERR_OR_ZERO(realfile); 1395 1395 pr_debug("tmpfile/open(%pd2, 0%o) = %i\n", realparentpath.dentry, mode, err);
+1 -1
fs/overlayfs/file.c
··· 48 48 if (!inode_owner_or_capable(real_idmap, realinode)) 49 49 flags &= ~O_NOATIME; 50 50 51 - realfile = backing_file_open(file_user_path(file), 51 + realfile = backing_file_open(file, 52 52 flags, realpath, current_cred()); 53 53 } 54 54 }
+2 -2
include/linux/backing-file.h
··· 18 18 void (*end_write)(struct kiocb *iocb, ssize_t); 19 19 }; 20 20 21 - struct file *backing_file_open(const struct path *user_path, int flags, 21 + struct file *backing_file_open(const struct file *user_file, int flags, 22 22 const struct path *real_path, 23 23 const struct cred *cred); 24 - struct file *backing_tmpfile_open(const struct path *user_path, int flags, 24 + struct file *backing_tmpfile_open(const struct file *user_file, int flags, 25 25 const struct path *real_parentpath, 26 26 umode_t mode, const struct cred *cred); 27 27 ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
+7 -3
include/linux/cred.h
··· 33 33 34 34 /** 35 35 * get_group_info - Get a reference to a group info structure 36 - * @group_info: The group info to reference 36 + * @gi: The group info to reference 37 37 * 38 38 * This gets a reference to a set of supplementary groups. 39 39 * 40 40 * If the caller is accessing a task's credentials, they must hold the RCU read 41 41 * lock when reading. 42 + * 43 + * Returns: @gi 42 44 */ 43 45 static inline struct group_info *get_group_info(struct group_info *gi) 44 46 { ··· 211 209 * usage count. The purpose of this is to attempt to catch at compile time the 212 210 * accidental alteration of a set of credentials that should be considered 213 211 * immutable. 212 + * 213 + * Returns: @cred when the references are acquired, NULL otherwise. 214 214 */ 215 215 static inline const struct cred *get_cred_many(const struct cred *cred, int nr) 216 216 { ··· 250 246 } 251 247 252 248 /** 253 - * put_cred - Release a reference to a set of credentials 254 - * @cred: The credentials to release 249 + * put_cred_many - Release a reference to a set of credentials 250 + * @_cred: The credentials to release 255 251 * @nr: Number of references to release 256 252 * 257 253 * Release a reference to a set of credentials, deleting them when the last ref
+13
include/linux/fs.h
··· 2475 2475 const struct cred *cred); 2476 2476 const struct path *backing_file_user_path(const struct file *f); 2477 2477 2478 + #ifdef CONFIG_SECURITY 2479 + void *backing_file_security(const struct file *f); 2480 + void backing_file_set_security(struct file *f, void *security); 2481 + #else 2482 + static inline void *backing_file_security(const struct file *f) 2483 + { 2484 + return NULL; 2485 + } 2486 + static inline void backing_file_set_security(struct file *f, void *security) 2487 + { 2488 + } 2489 + #endif /* CONFIG_SECURITY */ 2490 + 2478 2491 /* 2479 2492 * When mmapping a file on a stackable filesystem (e.g., overlayfs), the file 2480 2493 * stored in ->vm_file is a backing file whose f_inode is on the underlying
+1 -1
include/linux/lsm_audit.h
··· 94 94 #endif 95 95 char *kmod_name; 96 96 struct lsm_ioctlop_audit *op; 97 - struct file *file; 97 + const struct file *file; 98 98 struct lsm_ibpkey_audit *ibpkey; 99 99 struct lsm_ibendport_audit *ibendport; 100 100 int reason;
+5
include/linux/lsm_hook_defs.h
··· 191 191 LSM_HOOK(int, 0, file_alloc_security, struct file *file) 192 192 LSM_HOOK(void, LSM_RET_VOID, file_release, struct file *file) 193 193 LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file) 194 + LSM_HOOK(int, 0, backing_file_alloc, struct file *backing_file, 195 + const struct file *user_file) 196 + LSM_HOOK(void, LSM_RET_VOID, backing_file_free, struct file *backing_file) 194 197 LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd, 195 198 unsigned long arg) 196 199 LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd, ··· 201 198 LSM_HOOK(int, 0, mmap_addr, unsigned long addr) 202 199 LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot, 203 200 unsigned long prot, unsigned long flags) 201 + LSM_HOOK(int, 0, mmap_backing_file, struct vm_area_struct *vma, 202 + struct file *backing_file, struct file *user_file) 204 203 LSM_HOOK(int, 0, file_mprotect, struct vm_area_struct *vma, 205 204 unsigned long reqprot, unsigned long prot) 206 205 LSM_HOOK(int, 0, file_lock, struct file *file, unsigned int cmd)
+1
include/linux/lsm_hooks.h
··· 104 104 struct lsm_blob_sizes { 105 105 unsigned int lbs_cred; 106 106 unsigned int lbs_file; 107 + unsigned int lbs_backing_file; 107 108 unsigned int lbs_ib; 108 109 unsigned int lbs_inode; 109 110 unsigned int lbs_sock;
+22
include/linux/security.h
··· 472 472 int security_file_alloc(struct file *file); 473 473 void security_file_release(struct file *file); 474 474 void security_file_free(struct file *file); 475 + int security_backing_file_alloc(struct file *backing_file, 476 + const struct file *user_file); 477 + void security_backing_file_free(struct file *backing_file); 475 478 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 476 479 int security_file_ioctl_compat(struct file *file, unsigned int cmd, 477 480 unsigned long arg); 478 481 int security_mmap_file(struct file *file, unsigned long prot, 479 482 unsigned long flags); 483 + int security_mmap_backing_file(struct vm_area_struct *vma, 484 + struct file *backing_file, 485 + struct file *user_file); 480 486 int security_mmap_addr(unsigned long addr); 481 487 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, 482 488 unsigned long prot); ··· 1147 1141 static inline void security_file_free(struct file *file) 1148 1142 { } 1149 1143 1144 + static inline int security_backing_file_alloc(struct file *backing_file, 1145 + const struct file *user_file) 1146 + { 1147 + return 0; 1148 + } 1149 + 1150 + static inline void security_backing_file_free(struct file *backing_file) 1151 + { } 1152 + 1150 1153 static inline int security_file_ioctl(struct file *file, unsigned int cmd, 1151 1154 unsigned long arg) 1152 1155 { ··· 1171 1156 1172 1157 static inline int security_mmap_file(struct file *file, unsigned long prot, 1173 1158 unsigned long flags) 1159 + { 1160 + return 0; 1161 + } 1162 + 1163 + static inline int security_mmap_backing_file(struct vm_area_struct *vma, 1164 + struct file *backing_file, 1165 + struct file *user_file) 1174 1166 { 1175 1167 return 0; 1176 1168 }
+5 -5
security/inode.c
··· 30 30 static void securityfs_free_inode(struct inode *inode) 31 31 { 32 32 if (S_ISLNK(inode->i_mode)) 33 - kfree(inode->i_link); 33 + kfree_const(inode->i_link); 34 34 free_inode_nonrcu(inode); 35 35 } 36 36 ··· 258 258 const struct inode_operations *iops) 259 259 { 260 260 struct dentry *dent; 261 - char *link = NULL; 261 + const char *link = NULL; 262 262 263 263 if (target) { 264 - link = kstrdup(target, GFP_KERNEL); 264 + link = kstrdup_const(target, GFP_KERNEL); 265 265 if (!link) 266 266 return ERR_PTR(-ENOMEM); 267 267 } 268 268 dent = securityfs_create_dentry(name, S_IFLNK | 0444, parent, 269 - link, NULL, iops); 269 + (void *)link, NULL, iops); 270 270 if (IS_ERR(dent)) 271 - kfree(link); 271 + kfree_const(link); 272 272 273 273 return dent; 274 274 }
+1
security/lsm.h
··· 29 29 30 30 /* LSM blob caches */ 31 31 extern struct kmem_cache *lsm_file_cache; 32 + extern struct kmem_cache *lsm_backing_file_cache; 32 33 extern struct kmem_cache *lsm_inode_cache; 33 34 34 35 /* LSM blob allocators */
+9
security/lsm_init.c
··· 293 293 blobs = lsm->blobs; 294 294 lsm_blob_size_update(&blobs->lbs_cred, &blob_sizes.lbs_cred); 295 295 lsm_blob_size_update(&blobs->lbs_file, &blob_sizes.lbs_file); 296 + lsm_blob_size_update(&blobs->lbs_backing_file, 297 + &blob_sizes.lbs_backing_file); 296 298 lsm_blob_size_update(&blobs->lbs_ib, &blob_sizes.lbs_ib); 297 299 /* inode blob gets an rcu_head in addition to LSM blobs. */ 298 300 if (blobs->lbs_inode && blob_sizes.lbs_inode == 0) ··· 443 441 if (lsm_debug) { 444 442 lsm_pr("blob(cred) size %d\n", blob_sizes.lbs_cred); 445 443 lsm_pr("blob(file) size %d\n", blob_sizes.lbs_file); 444 + lsm_pr("blob(backing_file) size %d\n", 445 + blob_sizes.lbs_backing_file); 446 446 lsm_pr("blob(ib) size %d\n", blob_sizes.lbs_ib); 447 447 lsm_pr("blob(inode) size %d\n", blob_sizes.lbs_inode); 448 448 lsm_pr("blob(ipc) size %d\n", blob_sizes.lbs_ipc); ··· 466 462 lsm_file_cache = kmem_cache_create("lsm_file_cache", 467 463 blob_sizes.lbs_file, 0, 468 464 SLAB_PANIC, NULL); 465 + if (blob_sizes.lbs_backing_file) 466 + lsm_backing_file_cache = kmem_cache_create( 467 + "lsm_backing_file_cache", 468 + blob_sizes.lbs_backing_file, 469 + 0, SLAB_PANIC, NULL); 469 470 if (blob_sizes.lbs_inode) 470 471 lsm_inode_cache = kmem_cache_create("lsm_inode_cache", 471 472 blob_sizes.lbs_inode, 0,
+102
security/security.c
··· 82 82 struct lsm_blob_sizes blob_sizes; 83 83 84 84 struct kmem_cache *lsm_file_cache; 85 + struct kmem_cache *lsm_backing_file_cache; 85 86 struct kmem_cache *lsm_inode_cache; 86 87 87 88 #define SECURITY_HOOK_ACTIVE_KEY(HOOK, IDX) security_hook_active_##HOOK##_##IDX ··· 170 169 171 170 file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL); 172 171 if (file->f_security == NULL) 172 + return -ENOMEM; 173 + return 0; 174 + } 175 + 176 + /** 177 + * lsm_backing_file_alloc - allocate a composite backing file blob 178 + * @backing_file: the backing file 179 + * 180 + * Allocate the backing file blob for all the modules. 181 + * 182 + * Returns 0, or -ENOMEM if memory can't be allocated. 183 + */ 184 + static int lsm_backing_file_alloc(struct file *backing_file) 185 + { 186 + void *blob; 187 + 188 + if (!lsm_backing_file_cache) { 189 + backing_file_set_security(backing_file, NULL); 190 + return 0; 191 + } 192 + 193 + blob = kmem_cache_zalloc(lsm_backing_file_cache, GFP_KERNEL); 194 + backing_file_set_security(backing_file, blob); 195 + if (!blob) 173 196 return -ENOMEM; 174 197 return 0; 175 198 } ··· 2444 2419 } 2445 2420 2446 2421 /** 2422 + * security_backing_file_alloc() - Allocate and setup a backing file blob 2423 + * @backing_file: the backing file 2424 + * @user_file: the associated user visible file 2425 + * 2426 + * Allocate a backing file LSM blob and perform any necessary initialization of 2427 + * the LSM blob. There will be some operations where the LSM will not have 2428 + * access to @user_file after this point, so any important state associated 2429 + * with @user_file that is important to the LSM should be captured in the 2430 + * backing file's LSM blob. 2431 + * 2432 + * LSM's should avoid taking a reference to @user_file in this hook as it will 2433 + * result in problems later when the system attempts to drop/put the file 2434 + * references due to a circular dependency. 2435 + * 2436 + * Return: Return 0 if the hook is successful, negative values otherwise. 2437 + */ 2438 + int security_backing_file_alloc(struct file *backing_file, 2439 + const struct file *user_file) 2440 + { 2441 + int rc; 2442 + 2443 + rc = lsm_backing_file_alloc(backing_file); 2444 + if (rc) 2445 + return rc; 2446 + rc = call_int_hook(backing_file_alloc, backing_file, user_file); 2447 + if (unlikely(rc)) 2448 + security_backing_file_free(backing_file); 2449 + 2450 + return rc; 2451 + } 2452 + 2453 + /** 2454 + * security_backing_file_free() - Free a backing file blob 2455 + * @backing_file: the backing file 2456 + * 2457 + * Free any LSM state associate with a backing file's LSM blob, including the 2458 + * blob itself. 2459 + */ 2460 + void security_backing_file_free(struct file *backing_file) 2461 + { 2462 + void *blob = backing_file_security(backing_file); 2463 + 2464 + call_void_hook(backing_file_free, backing_file); 2465 + 2466 + if (blob) { 2467 + backing_file_set_security(backing_file, NULL); 2468 + kmem_cache_free(lsm_backing_file_cache, blob); 2469 + } 2470 + } 2471 + 2472 + /** 2447 2473 * security_file_ioctl() - Check if an ioctl is allowed 2448 2474 * @file: associated file 2449 2475 * @cmd: ioctl cmd ··· 2581 2505 return call_int_hook(mmap_file, file, prot, mmap_prot(file, prot), 2582 2506 flags); 2583 2507 } 2508 + 2509 + /** 2510 + * security_mmap_backing_file - Check if mmap'ing a backing file is allowed 2511 + * @vma: the vm_area_struct for the mmap'd region 2512 + * @backing_file: the backing file being mmap'd 2513 + * @user_file: the user file being mmap'd 2514 + * 2515 + * Check permissions for a mmap operation on a stacked filesystem. This hook 2516 + * is called after the security_mmap_file() and is responsible for authorizing 2517 + * the mmap on @backing_file. It is important to note that the mmap operation 2518 + * on @user_file has already been authorized and the @vma->vm_file has been 2519 + * set to @backing_file. 2520 + * 2521 + * Return: Returns 0 if permission is granted. 2522 + */ 2523 + int security_mmap_backing_file(struct vm_area_struct *vma, 2524 + struct file *backing_file, 2525 + struct file *user_file) 2526 + { 2527 + /* recommended by the stackable filesystem devs */ 2528 + if (WARN_ON_ONCE(!(backing_file->f_mode & FMODE_BACKING))) 2529 + return -EIO; 2530 + 2531 + return call_int_hook(mmap_backing_file, vma, backing_file, user_file); 2532 + } 2533 + EXPORT_SYMBOL_GPL(security_mmap_backing_file); 2584 2534 2585 2535 /** 2586 2536 * security_mmap_addr() - Check if mmap'ing an address is allowed
+185 -71
security/selinux/hooks.c
··· 1745 1745 static int bpf_fd_pass(const struct file *file, u32 sid); 1746 1746 #endif 1747 1747 1748 + static int __file_has_perm(const struct cred *cred, const struct file *file, 1749 + u32 av, bool bf_user_file) 1750 + 1751 + { 1752 + struct common_audit_data ad; 1753 + struct inode *inode; 1754 + u32 ssid = cred_sid(cred); 1755 + u32 tsid_fd; 1756 + int rc; 1757 + 1758 + if (bf_user_file) { 1759 + struct backing_file_security_struct *bfsec; 1760 + const struct path *path; 1761 + 1762 + if (WARN_ON(!(file->f_mode & FMODE_BACKING))) 1763 + return -EIO; 1764 + 1765 + bfsec = selinux_backing_file(file); 1766 + path = backing_file_user_path(file); 1767 + tsid_fd = bfsec->uf_sid; 1768 + inode = d_inode(path->dentry); 1769 + 1770 + ad.type = LSM_AUDIT_DATA_PATH; 1771 + ad.u.path = *path; 1772 + } else { 1773 + struct file_security_struct *fsec = selinux_file(file); 1774 + 1775 + tsid_fd = fsec->sid; 1776 + inode = file_inode(file); 1777 + 1778 + ad.type = LSM_AUDIT_DATA_FILE; 1779 + ad.u.file = file; 1780 + } 1781 + 1782 + if (ssid != tsid_fd) { 1783 + rc = avc_has_perm(ssid, tsid_fd, SECCLASS_FD, FD__USE, &ad); 1784 + if (rc) 1785 + return rc; 1786 + } 1787 + 1788 + #ifdef CONFIG_BPF_SYSCALL 1789 + /* regardless of backing vs user file, use the underlying file here */ 1790 + rc = bpf_fd_pass(file, ssid); 1791 + if (rc) 1792 + return rc; 1793 + #endif 1794 + 1795 + /* av is zero if only checking access to the descriptor. */ 1796 + if (av) 1797 + return inode_has_perm(cred, inode, av, &ad); 1798 + 1799 + return 0; 1800 + } 1801 + 1748 1802 /* Check whether a task can use an open file descriptor to 1749 1803 access an inode in a given way. Check access to the 1750 1804 descriptor itself, and then use dentry_has_perm to ··· 1807 1753 has the same SID as the process. If av is zero, then 1808 1754 access to the file is not checked, e.g. for cases 1809 1755 where only the descriptor is affected like seek. */ 1810 - static int file_has_perm(const struct cred *cred, 1811 - struct file *file, 1812 - u32 av) 1756 + static inline int file_has_perm(const struct cred *cred, 1757 + const struct file *file, u32 av) 1813 1758 { 1814 - struct file_security_struct *fsec = selinux_file(file); 1815 - struct inode *inode = file_inode(file); 1816 - struct common_audit_data ad; 1817 - u32 sid = cred_sid(cred); 1818 - int rc; 1819 - 1820 - ad.type = LSM_AUDIT_DATA_FILE; 1821 - ad.u.file = file; 1822 - 1823 - if (sid != fsec->sid) { 1824 - rc = avc_has_perm(sid, fsec->sid, 1825 - SECCLASS_FD, 1826 - FD__USE, 1827 - &ad); 1828 - if (rc) 1829 - goto out; 1830 - } 1831 - 1832 - #ifdef CONFIG_BPF_SYSCALL 1833 - rc = bpf_fd_pass(file, cred_sid(cred)); 1834 - if (rc) 1835 - return rc; 1836 - #endif 1837 - 1838 - /* av is zero if only checking access to the descriptor. */ 1839 - rc = 0; 1840 - if (av) 1841 - rc = inode_has_perm(cred, inode, av, &ad); 1842 - 1843 - out: 1844 - return rc; 1759 + return __file_has_perm(cred, file, av, false); 1845 1760 } 1846 1761 1847 1762 /* ··· 3848 3825 return 0; 3849 3826 } 3850 3827 3828 + static int selinux_backing_file_alloc(struct file *backing_file, 3829 + const struct file *user_file) 3830 + { 3831 + struct backing_file_security_struct *bfsec; 3832 + 3833 + bfsec = selinux_backing_file(backing_file); 3834 + bfsec->uf_sid = selinux_file(user_file)->sid; 3835 + 3836 + return 0; 3837 + } 3838 + 3851 3839 /* 3852 3840 * Check whether a task has the ioctl permission and cmd 3853 3841 * operation to an inode. ··· 3976 3942 3977 3943 static int default_noexec __ro_after_init; 3978 3944 3979 - static int file_map_prot_check(struct file *file, unsigned long prot, int shared) 3945 + static int __file_map_prot_check(const struct cred *cred, 3946 + const struct file *file, unsigned long prot, 3947 + bool shared, bool bf_user_file) 3980 3948 { 3981 - const struct cred *cred = current_cred(); 3982 - u32 sid = cred_sid(cred); 3983 - int rc = 0; 3949 + struct inode *inode = NULL; 3950 + bool prot_exec = prot & PROT_EXEC; 3951 + bool prot_write = prot & PROT_WRITE; 3984 3952 3985 - if (default_noexec && 3986 - (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) || 3987 - (!shared && (prot & PROT_WRITE)))) { 3953 + if (file) { 3954 + if (bf_user_file) 3955 + inode = d_inode(backing_file_user_path(file)->dentry); 3956 + else 3957 + inode = file_inode(file); 3958 + } 3959 + 3960 + if (default_noexec && prot_exec && 3961 + (!file || IS_PRIVATE(inode) || (!shared && prot_write))) { 3962 + int rc; 3963 + u32 sid = cred_sid(cred); 3964 + 3988 3965 /* 3989 - * We are making executable an anonymous mapping or a 3990 - * private file mapping that will also be writable. 3991 - * This has an additional check. 3966 + * We are making executable an anonymous mapping or a private 3967 + * file mapping that will also be writable. 3992 3968 */ 3993 - rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, 3994 - PROCESS__EXECMEM, NULL); 3969 + rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__EXECMEM, 3970 + NULL); 3995 3971 if (rc) 3996 - goto error; 3972 + return rc; 3997 3973 } 3998 3974 3999 3975 if (file) { 4000 - /* read access is always possible with a mapping */ 3976 + /* "read" always possible, "write" only if shared */ 4001 3977 u32 av = FILE__READ; 4002 - 4003 - /* write access only matters if the mapping is shared */ 4004 - if (shared && (prot & PROT_WRITE)) 3978 + if (shared && prot_write) 4005 3979 av |= FILE__WRITE; 4006 - 4007 - if (prot & PROT_EXEC) 3980 + if (prot_exec) 4008 3981 av |= FILE__EXECUTE; 4009 3982 4010 - return file_has_perm(cred, file, av); 3983 + return __file_has_perm(cred, file, av, bf_user_file); 4011 3984 } 4012 3985 4013 - error: 4014 - return rc; 3986 + return 0; 3987 + } 3988 + 3989 + static inline int file_map_prot_check(const struct cred *cred, 3990 + const struct file *file, 3991 + unsigned long prot, bool shared) 3992 + { 3993 + return __file_map_prot_check(cred, file, prot, shared, false); 4015 3994 } 4016 3995 4017 3996 static int selinux_mmap_addr(unsigned long addr) ··· 4040 3993 return rc; 4041 3994 } 4042 3995 4043 - static int selinux_mmap_file(struct file *file, 4044 - unsigned long reqprot __always_unused, 4045 - unsigned long prot, unsigned long flags) 3996 + static int selinux_mmap_file_common(const struct cred *cred, struct file *file, 3997 + unsigned long prot, bool shared) 4046 3998 { 4047 - struct common_audit_data ad; 4048 - int rc; 4049 - 4050 3999 if (file) { 4000 + int rc; 4001 + struct common_audit_data ad; 4002 + 4051 4003 ad.type = LSM_AUDIT_DATA_FILE; 4052 4004 ad.u.file = file; 4053 - rc = inode_has_perm(current_cred(), file_inode(file), 4054 - FILE__MAP, &ad); 4005 + rc = inode_has_perm(cred, file_inode(file), FILE__MAP, &ad); 4055 4006 if (rc) 4056 4007 return rc; 4057 4008 } 4058 4009 4059 - return file_map_prot_check(file, prot, 4060 - (flags & MAP_TYPE) == MAP_SHARED); 4010 + return file_map_prot_check(cred, file, prot, shared); 4011 + } 4012 + 4013 + static int selinux_mmap_file(struct file *file, 4014 + unsigned long reqprot __always_unused, 4015 + unsigned long prot, unsigned long flags) 4016 + { 4017 + return selinux_mmap_file_common(current_cred(), file, prot, 4018 + (flags & MAP_TYPE) == MAP_SHARED); 4019 + } 4020 + 4021 + /** 4022 + * selinux_mmap_backing_file - Check mmap permissions on a backing file 4023 + * @vma: memory region 4024 + * @backing_file: stacked filesystem backing file 4025 + * @user_file: user visible file 4026 + * 4027 + * This is called after selinux_mmap_file() on stacked filesystems, and it 4028 + * is this function's responsibility to verify access to @backing_file and 4029 + * setup the SELinux state for possible later use in the mprotect() code path. 4030 + * 4031 + * By the time this function is called, mmap() access to @user_file has already 4032 + * been authorized and @vma->vm_file has been set to point to @backing_file. 4033 + * 4034 + * Return zero on success, negative values otherwise. 4035 + */ 4036 + static int selinux_mmap_backing_file(struct vm_area_struct *vma, 4037 + struct file *backing_file, 4038 + struct file *user_file __always_unused) 4039 + { 4040 + unsigned long prot = 0; 4041 + 4042 + /* translate vma->vm_flags perms into PROT perms */ 4043 + if (vma->vm_flags & VM_READ) 4044 + prot |= PROT_READ; 4045 + if (vma->vm_flags & VM_WRITE) 4046 + prot |= PROT_WRITE; 4047 + if (vma->vm_flags & VM_EXEC) 4048 + prot |= PROT_EXEC; 4049 + 4050 + return selinux_mmap_file_common(backing_file->f_cred, backing_file, 4051 + prot, vma->vm_flags & VM_SHARED); 4061 4052 } 4062 4053 4063 4054 static int selinux_file_mprotect(struct vm_area_struct *vma, 4064 4055 unsigned long reqprot __always_unused, 4065 4056 unsigned long prot) 4066 4057 { 4058 + int rc; 4067 4059 const struct cred *cred = current_cred(); 4068 4060 u32 sid = cred_sid(cred); 4061 + const struct file *file = vma->vm_file; 4062 + bool backing_file; 4063 + bool shared = vma->vm_flags & VM_SHARED; 4064 + 4065 + /* check if we need to trigger the "backing files are awful" mode */ 4066 + backing_file = file && (file->f_mode & FMODE_BACKING); 4069 4067 4070 4068 if (default_noexec && 4071 4069 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { 4072 - int rc = 0; 4073 4070 /* 4074 4071 * We don't use the vma_is_initial_heap() helper as it has 4075 4072 * a history of problems and is currently broken on systems ··· 4127 4036 vma->vm_end <= vma->vm_mm->brk) { 4128 4037 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, 4129 4038 PROCESS__EXECHEAP, NULL); 4130 - } else if (!vma->vm_file && (vma_is_initial_stack(vma) || 4039 + if (rc) 4040 + return rc; 4041 + } else if (!file && (vma_is_initial_stack(vma) || 4131 4042 vma_is_stack_for_current(vma))) { 4132 4043 rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, 4133 4044 PROCESS__EXECSTACK, NULL); 4134 - } else if (vma->vm_file && vma->anon_vma) { 4045 + if (rc) 4046 + return rc; 4047 + } else if (file && vma->anon_vma) { 4135 4048 /* 4136 4049 * We are making executable a file mapping that has 4137 4050 * had some COW done. Since pages might have been ··· 4143 4048 * modified content. This typically should only 4144 4049 * occur for text relocations. 4145 4050 */ 4146 - rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD); 4051 + rc = __file_has_perm(cred, file, FILE__EXECMOD, 4052 + backing_file); 4053 + if (rc) 4054 + return rc; 4055 + if (backing_file) { 4056 + rc = file_has_perm(file->f_cred, file, 4057 + FILE__EXECMOD); 4058 + if (rc) 4059 + return rc; 4060 + } 4147 4061 } 4062 + } 4063 + 4064 + rc = __file_map_prot_check(cred, file, prot, shared, backing_file); 4065 + if (rc) 4066 + return rc; 4067 + if (backing_file) { 4068 + rc = file_map_prot_check(file->f_cred, file, prot, shared); 4148 4069 if (rc) 4149 4070 return rc; 4150 4071 } 4151 4072 4152 - return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); 4073 + return 0; 4153 4074 } 4154 4075 4155 4076 static int selinux_file_lock(struct file *file, unsigned int cmd) ··· 7504 7393 .lbs_cred = sizeof(struct cred_security_struct), 7505 7394 .lbs_task = sizeof(struct task_security_struct), 7506 7395 .lbs_file = sizeof(struct file_security_struct), 7396 + .lbs_backing_file = sizeof(struct backing_file_security_struct), 7507 7397 .lbs_inode = sizeof(struct inode_security_struct), 7508 7398 .lbs_ipc = sizeof(struct ipc_security_struct), 7509 7399 .lbs_key = sizeof(struct key_security_struct), ··· 7610 7498 7611 7499 LSM_HOOK_INIT(file_permission, selinux_file_permission), 7612 7500 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), 7501 + LSM_HOOK_INIT(backing_file_alloc, selinux_backing_file_alloc), 7613 7502 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl), 7614 7503 LSM_HOOK_INIT(file_ioctl_compat, selinux_file_ioctl_compat), 7615 7504 LSM_HOOK_INIT(mmap_file, selinux_mmap_file), 7505 + LSM_HOOK_INIT(mmap_backing_file, selinux_mmap_backing_file), 7616 7506 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr), 7617 7507 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect), 7618 7508 LSM_HOOK_INIT(file_lock, selinux_file_lock),
+11
security/selinux/include/objsec.h
··· 88 88 u32 pseqno; /* Policy seqno at the time of file open */ 89 89 }; 90 90 91 + struct backing_file_security_struct { 92 + u32 uf_sid; /* associated user file fsec->sid */ 93 + }; 94 + 91 95 struct superblock_security_struct { 92 96 u32 sid; /* SID of file system superblock */ 93 97 u32 def_sid; /* default SID for labeling */ ··· 197 193 static inline struct file_security_struct *selinux_file(const struct file *file) 198 194 { 199 195 return file->f_security + selinux_blob_sizes.lbs_file; 196 + } 197 + 198 + static inline struct backing_file_security_struct * 199 + selinux_backing_file(const struct file *backing_file) 200 + { 201 + void *blob = backing_file_security(backing_file); 202 + return blob + selinux_blob_sizes.lbs_backing_file; 200 203 } 201 204 202 205 static inline struct inode_security_struct *