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.

lsm: add backing_file LSM hooks

Stacked filesystems such as overlayfs do not currently provide the
necessary mechanisms for LSMs to properly enforce access controls on the
mmap() and mprotect() operations. In order to resolve this gap, a LSM
security blob is being added to the backing_file struct and the following
new LSM hooks are being created:

security_backing_file_alloc()
security_backing_file_free()
security_mmap_backing_file()

The first two hooks are to manage the lifecycle of the LSM security blob
in the backing_file struct, while the third provides a new mmap() access
control point for the underlying backing file. It is also expected that
LSMs will likely want to update their security_file_mprotect() callback
to address issues with their mprotect() controls, but that does not
require a change to the security_file_mprotect() LSM hook.

There are a three other small changes to support these new LSM hooks:
* Pass the user file associated with a backing file down to
alloc_empty_backing_file() so it can be included in the
security_backing_file_alloc() hook.
* Add getter and setter functions for the backing_file struct LSM blob
as the backing_file struct remains private to fs/file_table.c.
* Constify the file struct field in the LSM common_audit_data struct to
better support LSMs that need to pass a const file struct pointer into
the common LSM audit code.

Thanks to Arnd Bergmann for identifying the missing EXPORT_SYMBOL_GPL()
and supplying a fixup.

Cc: stable@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-unionfs@vger.kernel.org
Cc: linux-erofs@lists.ozlabs.org
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Paul Moore <paul@paul-moore.com>

+206 -17
+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 ··· 103 102 104 103 if (file->f_flags & O_DIRECT) 105 104 return -EINVAL; 106 - realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred()); 105 + realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred(), 106 + file); 107 107 if (IS_ERR(realfile)) 108 108 return PTR_ERR(realfile); 109 109 ihold(sharedinode); ··· 148 146 static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma) 149 147 { 150 148 struct file *realfile = file->private_data; 149 + int err; 151 150 152 151 vma_set_file(vma, realfile); 152 + 153 + err = security_mmap_backing_file(vma, realfile, file); 154 + if (err) 155 + return err; 156 + 153 157 return generic_file_readonly_mmap(file, vma); 154 158 } 155 159
+23 -4
fs/file_table.c
··· 50 50 struct path user_path; 51 51 freeptr_t bf_freeptr; 52 52 }; 53 + #ifdef CONFIG_SECURITY 54 + void *security; 55 + #endif 53 56 }; 54 57 55 58 #define backing_file(f) container_of(f, struct backing_file, file) ··· 69 66 } 70 67 EXPORT_SYMBOL_GPL(backing_file_set_user_path); 71 68 69 + #ifdef CONFIG_SECURITY 70 + void *backing_file_security(const struct file *f) 71 + { 72 + return backing_file(f)->security; 73 + } 74 + 75 + void backing_file_set_security(struct file *f, void *security) 76 + { 77 + backing_file(f)->security = security; 78 + } 79 + #endif /* CONFIG_SECURITY */ 80 + 72 81 static inline void backing_file_free(struct backing_file *ff) 73 82 { 83 + security_backing_file_free(&ff->file); 74 84 path_put(&ff->user_path); 75 85 kmem_cache_free(bfilp_cachep, ff); 76 86 } ··· 304 288 return f; 305 289 } 306 290 307 - static int init_backing_file(struct backing_file *ff) 291 + static int init_backing_file(struct backing_file *ff, 292 + const struct file *user_file) 308 293 { 309 294 memset(&ff->user_path, 0, sizeof(ff->user_path)); 310 - return 0; 295 + backing_file_set_security(&ff->file, NULL); 296 + return security_backing_file_alloc(&ff->file, user_file); 311 297 } 312 298 313 299 /* ··· 319 301 * This is only for kernel internal use, and the allocate file must not be 320 302 * installed into file tables or such. 321 303 */ 322 - struct file *alloc_empty_backing_file(int flags, const struct cred *cred) 304 + struct file *alloc_empty_backing_file(int flags, const struct cred *cred, 305 + const struct file *user_file) 323 306 { 324 307 struct backing_file *ff; 325 308 int error; ··· 337 318 338 319 /* The f_mode flags must be set before fput(). */ 339 320 ff->file.f_mode |= FMODE_BACKING | FMODE_NOACCOUNT; 340 - error = init_backing_file(ff); 321 + error = init_backing_file(ff, user_file); 341 322 if (unlikely(error)) { 342 323 fput(&ff->file); 343 324 return ERR_PTR(error);
+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
··· 1374 1374 return PTR_ERR(cred); 1375 1375 1376 1376 ovl_path_upper(dentry->d_parent, &realparentpath); 1377 - realfile = backing_tmpfile_open(&file->f_path, flags, &realparentpath, 1377 + realfile = backing_tmpfile_open(file, flags, &realparentpath, 1378 1378 mode, current_cred()); 1379 1379 err = PTR_ERR_OR_ZERO(realfile); 1380 1380 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,
+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
··· 471 471 int security_file_alloc(struct file *file); 472 472 void security_file_release(struct file *file); 473 473 void security_file_free(struct file *file); 474 + int security_backing_file_alloc(struct file *backing_file, 475 + const struct file *user_file); 476 + void security_backing_file_free(struct file *backing_file); 474 477 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 475 478 int security_file_ioctl_compat(struct file *file, unsigned int cmd, 476 479 unsigned long arg); 477 480 int security_mmap_file(struct file *file, unsigned long prot, 478 481 unsigned long flags); 482 + int security_mmap_backing_file(struct vm_area_struct *vma, 483 + struct file *backing_file, 484 + struct file *user_file); 479 485 int security_mmap_addr(unsigned long addr); 480 486 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, 481 487 unsigned long prot); ··· 1146 1140 static inline void security_file_free(struct file *file) 1147 1141 { } 1148 1142 1143 + static inline int security_backing_file_alloc(struct file *backing_file, 1144 + const struct file *user_file) 1145 + { 1146 + return 0; 1147 + } 1148 + 1149 + static inline void security_backing_file_free(struct file *backing_file) 1150 + { } 1151 + 1149 1152 static inline int security_file_ioctl(struct file *file, unsigned int cmd, 1150 1153 unsigned long arg) 1151 1154 { ··· 1170 1155 1171 1156 static inline int security_mmap_file(struct file *file, unsigned long prot, 1172 1157 unsigned long flags) 1158 + { 1159 + return 0; 1160 + } 1161 + 1162 + static inline int security_mmap_backing_file(struct vm_area_struct *vma, 1163 + struct file *backing_file, 1164 + struct file *user_file) 1173 1165 { 1174 1166 return 0; 1175 1167 }
+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
··· 81 81 struct lsm_blob_sizes blob_sizes; 82 82 83 83 struct kmem_cache *lsm_file_cache; 84 + struct kmem_cache *lsm_backing_file_cache; 84 85 struct kmem_cache *lsm_inode_cache; 85 86 86 87 #define SECURITY_HOOK_ACTIVE_KEY(HOOK, IDX) security_hook_active_##HOOK##_##IDX ··· 169 168 170 169 file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL); 171 170 if (file->f_security == NULL) 171 + return -ENOMEM; 172 + return 0; 173 + } 174 + 175 + /** 176 + * lsm_backing_file_alloc - allocate a composite backing file blob 177 + * @backing_file: the backing file 178 + * 179 + * Allocate the backing file blob for all the modules. 180 + * 181 + * Returns 0, or -ENOMEM if memory can't be allocated. 182 + */ 183 + static int lsm_backing_file_alloc(struct file *backing_file) 184 + { 185 + void *blob; 186 + 187 + if (!lsm_backing_file_cache) { 188 + backing_file_set_security(backing_file, NULL); 189 + return 0; 190 + } 191 + 192 + blob = kmem_cache_zalloc(lsm_backing_file_cache, GFP_KERNEL); 193 + backing_file_set_security(backing_file, blob); 194 + if (!blob) 172 195 return -ENOMEM; 173 196 return 0; 174 197 } ··· 2443 2418 } 2444 2419 2445 2420 /** 2421 + * security_backing_file_alloc() - Allocate and setup a backing file blob 2422 + * @backing_file: the backing file 2423 + * @user_file: the associated user visible file 2424 + * 2425 + * Allocate a backing file LSM blob and perform any necessary initialization of 2426 + * the LSM blob. There will be some operations where the LSM will not have 2427 + * access to @user_file after this point, so any important state associated 2428 + * with @user_file that is important to the LSM should be captured in the 2429 + * backing file's LSM blob. 2430 + * 2431 + * LSM's should avoid taking a reference to @user_file in this hook as it will 2432 + * result in problems later when the system attempts to drop/put the file 2433 + * references due to a circular dependency. 2434 + * 2435 + * Return: Return 0 if the hook is successful, negative values otherwise. 2436 + */ 2437 + int security_backing_file_alloc(struct file *backing_file, 2438 + const struct file *user_file) 2439 + { 2440 + int rc; 2441 + 2442 + rc = lsm_backing_file_alloc(backing_file); 2443 + if (rc) 2444 + return rc; 2445 + rc = call_int_hook(backing_file_alloc, backing_file, user_file); 2446 + if (unlikely(rc)) 2447 + security_backing_file_free(backing_file); 2448 + 2449 + return rc; 2450 + } 2451 + 2452 + /** 2453 + * security_backing_file_free() - Free a backing file blob 2454 + * @backing_file: the backing file 2455 + * 2456 + * Free any LSM state associate with a backing file's LSM blob, including the 2457 + * blob itself. 2458 + */ 2459 + void security_backing_file_free(struct file *backing_file) 2460 + { 2461 + void *blob = backing_file_security(backing_file); 2462 + 2463 + call_void_hook(backing_file_free, backing_file); 2464 + 2465 + if (blob) { 2466 + backing_file_set_security(backing_file, NULL); 2467 + kmem_cache_free(lsm_backing_file_cache, blob); 2468 + } 2469 + } 2470 + 2471 + /** 2446 2472 * security_file_ioctl() - Check if an ioctl is allowed 2447 2473 * @file: associated file 2448 2474 * @cmd: ioctl cmd ··· 2580 2504 return call_int_hook(mmap_file, file, prot, mmap_prot(file, prot), 2581 2505 flags); 2582 2506 } 2507 + 2508 + /** 2509 + * security_mmap_backing_file - Check if mmap'ing a backing file is allowed 2510 + * @vma: the vm_area_struct for the mmap'd region 2511 + * @backing_file: the backing file being mmap'd 2512 + * @user_file: the user file being mmap'd 2513 + * 2514 + * Check permissions for a mmap operation on a stacked filesystem. This hook 2515 + * is called after the security_mmap_file() and is responsible for authorizing 2516 + * the mmap on @backing_file. It is important to note that the mmap operation 2517 + * on @user_file has already been authorized and the @vma->vm_file has been 2518 + * set to @backing_file. 2519 + * 2520 + * Return: Returns 0 if permission is granted. 2521 + */ 2522 + int security_mmap_backing_file(struct vm_area_struct *vma, 2523 + struct file *backing_file, 2524 + struct file *user_file) 2525 + { 2526 + /* recommended by the stackable filesystem devs */ 2527 + if (WARN_ON_ONCE(!(backing_file->f_mode & FMODE_BACKING))) 2528 + return -EIO; 2529 + 2530 + return call_int_hook(mmap_backing_file, vma, backing_file, user_file); 2531 + } 2532 + EXPORT_SYMBOL_GPL(security_mmap_backing_file); 2583 2533 2584 2534 /** 2585 2535 * security_mmap_addr() - Check if mmap'ing an address is allowed