Skip to content

Commit 5dfcb15

Browse files
pcmooregregkh
authored andcommitted
lsm: add backing_file LSM hooks
[ Upstream commit 6af36ae ] 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> [Mainline declares lsm_backing_file_cache in security/lsm.h. Linux 6.18.y does not have security/lsm_init.c or security/lsm.h; the cache variable is defined locally as static struct kmem_cache *lsm_backing_file_cache in security/security.c.] Signed-off-by: Cai Xinchen <caixinchen1@huawei.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 5e47099 commit 5dfcb15

13 files changed

Lines changed: 194 additions & 15 deletions

File tree

fs/backing-file.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/backing-file.h>
1313
#include <linux/splice.h>
1414
#include <linux/mm.h>
15+
#include <linux/security.h>
1516

1617
#include "internal.h"
1718

@@ -29,14 +30,15 @@
2930
* returned file into a container structure that also stores the stacked
3031
* file's path, which can be retrieved using backing_file_user_path().
3132
*/
32-
struct file *backing_file_open(const struct path *user_path, int flags,
33+
struct file *backing_file_open(const struct file *user_file, int flags,
3334
const struct path *real_path,
3435
const struct cred *cred)
3536
{
37+
const struct path *user_path = &user_file->f_path;
3638
struct file *f;
3739
int error;
3840

39-
f = alloc_empty_backing_file(flags, cred);
41+
f = alloc_empty_backing_file(flags, cred, user_file);
4042
if (IS_ERR(f))
4143
return f;
4244

@@ -52,15 +54,16 @@ struct file *backing_file_open(const struct path *user_path, int flags,
5254
}
5355
EXPORT_SYMBOL_GPL(backing_file_open);
5456

55-
struct file *backing_tmpfile_open(const struct path *user_path, int flags,
57+
struct file *backing_tmpfile_open(const struct file *user_file, int flags,
5658
const struct path *real_parentpath,
5759
umode_t mode, const struct cred *cred)
5860
{
5961
struct mnt_idmap *real_idmap = mnt_idmap(real_parentpath->mnt);
62+
const struct path *user_path = &user_file->f_path;
6063
struct file *f;
6164
int error;
6265

63-
f = alloc_empty_backing_file(flags, cred);
66+
f = alloc_empty_backing_file(flags, cred, user_file);
6467
if (IS_ERR(f))
6568
return f;
6669

@@ -339,6 +342,12 @@ int backing_file_mmap(struct file *file, struct vm_area_struct *vma,
339342
vma_set_file(vma, file);
340343

341344
old_cred = override_creds(ctx->cred);
345+
ret = security_mmap_backing_file(vma, file, user_file);
346+
if (ret) {
347+
revert_creds(old_cred);
348+
return ret;
349+
}
350+
342351
ret = vfs_mmap(vma->vm_file, vma);
343352
revert_creds(old_cred);
344353

fs/file_table.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ struct backing_file {
5050
struct path user_path;
5151
freeptr_t bf_freeptr;
5252
};
53+
#ifdef CONFIG_SECURITY
54+
void *security;
55+
#endif
5356
};
5457

5558
#define backing_file(f) container_of(f, struct backing_file, file)
@@ -66,8 +69,21 @@ void backing_file_set_user_path(struct file *f, const struct path *path)
6669
}
6770
EXPORT_SYMBOL_GPL(backing_file_set_user_path);
6871

72+
#ifdef CONFIG_SECURITY
73+
void *backing_file_security(const struct file *f)
74+
{
75+
return backing_file(f)->security;
76+
}
77+
78+
void backing_file_set_security(struct file *f, void *security)
79+
{
80+
backing_file(f)->security = security;
81+
}
82+
#endif /* CONFIG_SECURITY */
83+
6984
static inline void backing_file_free(struct backing_file *ff)
7085
{
86+
security_backing_file_free(&ff->file);
7187
path_put(&ff->user_path);
7288
kmem_cache_free(bfilp_cachep, ff);
7389
}
@@ -288,10 +304,12 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
288304
return f;
289305
}
290306

291-
static int init_backing_file(struct backing_file *ff)
307+
static int init_backing_file(struct backing_file *ff,
308+
const struct file *user_file)
292309
{
293310
memset(&ff->user_path, 0, sizeof(ff->user_path));
294-
return 0;
311+
backing_file_set_security(&ff->file, NULL);
312+
return security_backing_file_alloc(&ff->file, user_file);
295313
}
296314

297315
/*
@@ -301,7 +319,8 @@ static int init_backing_file(struct backing_file *ff)
301319
* This is only for kernel internal use, and the allocate file must not be
302320
* installed into file tables or such.
303321
*/
304-
struct file *alloc_empty_backing_file(int flags, const struct cred *cred)
322+
struct file *alloc_empty_backing_file(int flags, const struct cred *cred,
323+
const struct file *user_file)
305324
{
306325
struct backing_file *ff;
307326
int error;
@@ -318,7 +337,7 @@ struct file *alloc_empty_backing_file(int flags, const struct cred *cred)
318337

319338
/* The f_mode flags must be set before fput(). */
320339
ff->file.f_mode |= FMODE_BACKING | FMODE_NOACCOUNT;
321-
error = init_backing_file(ff);
340+
error = init_backing_file(ff, user_file);
322341
if (unlikely(error)) {
323342
fput(&ff->file);
324343
return ERR_PTR(error);

fs/fuse/passthrough.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ struct fuse_backing *fuse_passthrough_open(struct file *file, int backing_id)
167167
goto out;
168168

169169
/* 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,
171171
&fb->file->f_path, fb->cred);
172172
err = PTR_ERR(backing_file);
173173
if (IS_ERR(backing_file)) {

fs/internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
100100
*/
101101
struct file *alloc_empty_file(int flags, const struct cred *cred);
102102
struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred);
103-
struct file *alloc_empty_backing_file(int flags, const struct cred *cred);
103+
struct file *alloc_empty_backing_file(int flags, const struct cred *cred,
104+
const struct file *user_file);
104105
void backing_file_set_user_path(struct file *f, const struct path *path);
105106

106107
static inline void file_put_write_access(struct file *file)

fs/overlayfs/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1355,7 +1355,7 @@ static int ovl_create_tmpfile(struct file *file, struct dentry *dentry,
13551355
}
13561356

13571357
ovl_path_upper(dentry->d_parent, &realparentpath);
1358-
realfile = backing_tmpfile_open(&file->f_path, flags, &realparentpath,
1358+
realfile = backing_tmpfile_open(file, flags, &realparentpath,
13591359
mode, current_cred());
13601360
err = PTR_ERR_OR_ZERO(realfile);
13611361
pr_debug("tmpfile/open(%pd2, 0%o) = %i\n", realparentpath.dentry, mode, err);

fs/overlayfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static struct file *ovl_open_realfile(const struct file *file,
4848
if (!inode_owner_or_capable(real_idmap, realinode))
4949
flags &= ~O_NOATIME;
5050

51-
realfile = backing_file_open(file_user_path(file),
51+
realfile = backing_file_open(file,
5252
flags, realpath, current_cred());
5353
}
5454
ovl_revert_creds(old_cred);

include/linux/backing-file.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ struct backing_file_ctx {
1818
void (*end_write)(struct kiocb *iocb, ssize_t);
1919
};
2020

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,
2222
const struct path *real_path,
2323
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,
2525
const struct path *real_parentpath,
2626
umode_t mode, const struct cred *cred);
2727
ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,

include/linux/fs.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2890,6 +2890,19 @@ struct file *dentry_create(const struct path *path, int flags, umode_t mode,
28902890
const struct cred *cred);
28912891
const struct path *backing_file_user_path(const struct file *f);
28922892

2893+
#ifdef CONFIG_SECURITY
2894+
void *backing_file_security(const struct file *f);
2895+
void backing_file_set_security(struct file *f, void *security);
2896+
#else
2897+
static inline void *backing_file_security(const struct file *f)
2898+
{
2899+
return NULL;
2900+
}
2901+
static inline void backing_file_set_security(struct file *f, void *security)
2902+
{
2903+
}
2904+
#endif /* CONFIG_SECURITY */
2905+
28932906
/*
28942907
* When mmapping a file on a stackable filesystem (e.g., overlayfs), the file
28952908
* stored in ->vm_file is a backing file whose f_inode is on the underlying

include/linux/lsm_audit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ struct common_audit_data {
9494
#endif
9595
char *kmod_name;
9696
struct lsm_ioctlop_audit *op;
97-
struct file *file;
97+
const struct file *file;
9898
struct lsm_ibpkey_audit *ibpkey;
9999
struct lsm_ibendport_audit *ibendport;
100100
int reason;

include/linux/lsm_hook_defs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,18 @@ LSM_HOOK(int, 0, file_permission, struct file *file, int mask)
191191
LSM_HOOK(int, 0, file_alloc_security, struct file *file)
192192
LSM_HOOK(void, LSM_RET_VOID, file_release, struct file *file)
193193
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)
194197
LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd,
195198
unsigned long arg)
196199
LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd,
197200
unsigned long arg)
198201
LSM_HOOK(int, 0, mmap_addr, unsigned long addr)
199202
LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot,
200203
unsigned long prot, unsigned long flags)
204+
LSM_HOOK(int, 0, mmap_backing_file, struct vm_area_struct *vma,
205+
struct file *backing_file, struct file *user_file)
201206
LSM_HOOK(int, 0, file_mprotect, struct vm_area_struct *vma,
202207
unsigned long reqprot, unsigned long prot)
203208
LSM_HOOK(int, 0, file_lock, struct file *file, unsigned int cmd)

0 commit comments

Comments
 (0)