Skip to content

Commit 3ba310f

Browse files
committed
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
2 parents de63934 + 82544d3 commit 3ba310f

20 files changed

Lines changed: 424 additions & 88 deletions

File tree

fs/backing-file.c

Lines changed: 13 additions & 5 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

@@ -336,8 +339,13 @@ int backing_file_mmap(struct file *file, struct vm_area_struct *vma,
336339

337340
vma_set_file(vma, file);
338341

339-
scoped_with_creds(ctx->cred)
342+
scoped_with_creds(ctx->cred) {
343+
ret = security_mmap_backing_file(vma, file, user_file);
344+
if (ret)
345+
return ret;
346+
340347
ret = vfs_mmap(vma->vm_file, vma);
348+
}
341349

342350
if (ctx->accessed)
343351
ctx->accessed(user_file);

fs/erofs/ishare.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
#include <linux/xxhash.h>
66
#include <linux/mount.h>
7+
#include <linux/security.h>
78
#include "internal.h"
89
#include "xattr.h"
910

@@ -106,7 +107,8 @@ static int erofs_ishare_file_open(struct inode *inode, struct file *file)
106107

107108
if (file->f_flags & O_DIRECT)
108109
return -EINVAL;
109-
realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred());
110+
realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred(),
111+
file);
110112
if (IS_ERR(realfile))
111113
return PTR_ERR(realfile);
112114
ihold(sharedinode);
@@ -150,8 +152,14 @@ static ssize_t erofs_ishare_file_read_iter(struct kiocb *iocb,
150152
static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma)
151153
{
152154
struct file *realfile = file->private_data;
155+
int err;
153156

154157
vma_set_file(vma, realfile);
158+
159+
err = security_mmap_backing_file(vma, realfile, file);
160+
if (err)
161+
return err;
162+
155163
return generic_file_readonly_mmap(file, vma);
156164
}
157165

fs/file_table.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ struct backing_file {
5454
struct path user_path;
5555
freeptr_t bf_freeptr;
5656
};
57+
#ifdef CONFIG_SECURITY
58+
void *security;
59+
#endif
5760
};
5861

5962
#define backing_file(f) container_of(f, struct backing_file, file)
@@ -70,15 +73,33 @@ void backing_file_set_user_path(struct file *f, const struct path *path)
7073
}
7174
EXPORT_SYMBOL_GPL(backing_file_set_user_path);
7275

76+
#ifdef CONFIG_SECURITY
77+
void *backing_file_security(const struct file *f)
78+
{
79+
return backing_file(f)->security;
80+
}
81+
82+
void backing_file_set_security(struct file *f, void *security)
83+
{
84+
backing_file(f)->security = security;
85+
}
86+
#endif /* CONFIG_SECURITY */
87+
88+
static inline void backing_file_free(struct backing_file *ff)
89+
{
90+
security_backing_file_free(&ff->file);
91+
path_put(&ff->user_path);
92+
kmem_cache_free(bfilp_cache, ff);
93+
}
94+
7395
static inline void file_free(struct file *f)
7496
{
7597
security_file_free(f);
7698
if (likely(!(f->f_mode & FMODE_NOACCOUNT)))
7799
percpu_counter_dec(&nr_files);
78100
put_cred(f->f_cred);
79101
if (unlikely(f->f_mode & FMODE_BACKING)) {
80-
path_put(backing_file_user_path(f));
81-
kmem_cache_free(bfilp_cache, backing_file(f));
102+
backing_file_free(backing_file(f));
82103
} else {
83104
kmem_cache_free(filp_cache, f);
84105
}
@@ -287,14 +308,23 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
287308
return f;
288309
}
289310

311+
static int init_backing_file(struct backing_file *ff,
312+
const struct file *user_file)
313+
{
314+
memset(&ff->user_path, 0, sizeof(ff->user_path));
315+
backing_file_set_security(&ff->file, NULL);
316+
return security_backing_file_alloc(&ff->file, user_file);
317+
}
318+
290319
/*
291320
* Variant of alloc_empty_file() that allocates a backing_file container
292321
* and doesn't check and modify nr_files.
293322
*
294323
* This is only for kernel internal use, and the allocate file must not be
295324
* installed into file tables or such.
296325
*/
297-
struct file *alloc_empty_backing_file(int flags, const struct cred *cred)
326+
struct file *alloc_empty_backing_file(int flags, const struct cred *cred,
327+
const struct file *user_file)
298328
{
299329
struct backing_file *ff;
300330
int error;
@@ -309,7 +339,14 @@ struct file *alloc_empty_backing_file(int flags, const struct cred *cred)
309339
return ERR_PTR(error);
310340
}
311341

342+
/* The f_mode flags must be set before fput(). */
312343
ff->file.f_mode |= FMODE_BACKING | FMODE_NOACCOUNT;
344+
error = init_backing_file(ff, user_file);
345+
if (unlikely(error)) {
346+
fput(&ff->file);
347+
return ERR_PTR(error);
348+
}
349+
313350
return &ff->file;
314351
}
315352
EXPORT_SYMBOL_GPL(alloc_empty_backing_file);

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
@@ -106,7 +106,8 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
106106
*/
107107
struct file *alloc_empty_file(int flags, const struct cred *cred);
108108
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);
110111
void backing_file_set_user_path(struct file *f, const struct path *path);
111112

112113
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
@@ -1389,7 +1389,7 @@ static int ovl_create_tmpfile(struct file *file, struct dentry *dentry,
13891389
return PTR_ERR(cred);
13901390

13911391
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,
13931393
mode, current_cred());
13941394
err = PTR_ERR_OR_ZERO(realfile);
13951395
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
}

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/cred.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ struct group_info {
3333

3434
/**
3535
* 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
3737
*
3838
* This gets a reference to a set of supplementary groups.
3939
*
4040
* If the caller is accessing a task's credentials, they must hold the RCU read
4141
* lock when reading.
42+
*
43+
* Returns: @gi
4244
*/
4345
static inline struct group_info *get_group_info(struct group_info *gi)
4446
{
@@ -209,6 +211,8 @@ DEFINE_CLASS(override_creds,
209211
* usage count. The purpose of this is to attempt to catch at compile time the
210212
* accidental alteration of a set of credentials that should be considered
211213
* immutable.
214+
*
215+
* Returns: @cred when the references are acquired, NULL otherwise.
212216
*/
213217
static inline const struct cred *get_cred_many(const struct cred *cred, int nr)
214218
{
@@ -246,8 +250,8 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred)
246250
}
247251

248252
/**
249-
* put_cred - Release a reference to a set of credentials
250-
* @cred: The credentials to release
253+
* put_cred_many - Release a reference to a set of credentials
254+
* @_cred: The credentials to release
251255
* @nr: Number of references to release
252256
*
253257
* Release a reference to a set of credentials, deleting them when the last ref

include/linux/fs.h

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

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+
24782491
/*
24792492
* When mmapping a file on a stackable filesystem (e.g., overlayfs), the file
24802493
* stored in ->vm_file is a backing file whose f_inode is on the underlying

0 commit comments

Comments
 (0)