Skip to content

Commit ccbd54f

Browse files
Matthew GarrettJames Morris
Matthew Garrett
authored and
James Morris
committed
tracefs: Restrict tracefs when the kernel is locked down
Tracefs may release more information about the kernel than desirable, so restrict it when the kernel is locked down in confidentiality mode by preventing open(). (Fixed by Ben Hutchings to avoid a null dereference in default_file_open()) Signed-off-by: Matthew Garrett <[email protected]> Reviewed-by: Steven Rostedt (VMware) <[email protected]> Cc: Ben Hutchings <[email protected]> Signed-off-by: James Morris <[email protected]>
1 parent 5496197 commit ccbd54f

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

fs/tracefs/inode.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,33 @@
2020
#include <linux/parser.h>
2121
#include <linux/magic.h>
2222
#include <linux/slab.h>
23+
#include <linux/security.h>
2324

2425
#define TRACEFS_DEFAULT_MODE 0700
2526

2627
static struct vfsmount *tracefs_mount;
2728
static int tracefs_mount_count;
2829
static bool tracefs_registered;
2930

31+
static int default_open_file(struct inode *inode, struct file *filp)
32+
{
33+
struct dentry *dentry = filp->f_path.dentry;
34+
struct file_operations *real_fops;
35+
int ret;
36+
37+
if (!dentry)
38+
return -EINVAL;
39+
40+
ret = security_locked_down(LOCKDOWN_TRACEFS);
41+
if (ret)
42+
return ret;
43+
44+
real_fops = dentry->d_fsdata;
45+
if (!real_fops->open)
46+
return 0;
47+
return real_fops->open(inode, filp);
48+
}
49+
3050
static ssize_t default_read_file(struct file *file, char __user *buf,
3151
size_t count, loff_t *ppos)
3252
{
@@ -221,6 +241,12 @@ static int tracefs_apply_options(struct super_block *sb)
221241
return 0;
222242
}
223243

244+
static void tracefs_destroy_inode(struct inode *inode)
245+
{
246+
if (S_ISREG(inode->i_mode))
247+
kfree(inode->i_fop);
248+
}
249+
224250
static int tracefs_remount(struct super_block *sb, int *flags, char *data)
225251
{
226252
int err;
@@ -257,6 +283,7 @@ static int tracefs_show_options(struct seq_file *m, struct dentry *root)
257283
static const struct super_operations tracefs_super_operations = {
258284
.statfs = simple_statfs,
259285
.remount_fs = tracefs_remount,
286+
.destroy_inode = tracefs_destroy_inode,
260287
.show_options = tracefs_show_options,
261288
};
262289

@@ -387,6 +414,7 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode,
387414
struct dentry *parent, void *data,
388415
const struct file_operations *fops)
389416
{
417+
struct file_operations *proxy_fops;
390418
struct dentry *dentry;
391419
struct inode *inode;
392420

@@ -402,8 +430,20 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode,
402430
if (unlikely(!inode))
403431
return failed_creating(dentry);
404432

433+
proxy_fops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
434+
if (unlikely(!proxy_fops)) {
435+
iput(inode);
436+
return failed_creating(dentry);
437+
}
438+
439+
if (!fops)
440+
fops = &tracefs_file_operations;
441+
442+
dentry->d_fsdata = (void *)fops;
443+
memcpy(proxy_fops, fops, sizeof(*proxy_fops));
444+
proxy_fops->open = default_open_file;
405445
inode->i_mode = mode;
406-
inode->i_fop = fops ? fops : &tracefs_file_operations;
446+
inode->i_fop = proxy_fops;
407447
inode->i_private = data;
408448
d_instantiate(dentry, inode);
409449
fsnotify_create(dentry->d_parent->d_inode, dentry);

include/linux/security.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ enum lockdown_reason {
121121
LOCKDOWN_KPROBES,
122122
LOCKDOWN_BPF_READ,
123123
LOCKDOWN_PERF,
124+
LOCKDOWN_TRACEFS,
124125
LOCKDOWN_CONFIDENTIALITY_MAX,
125126
};
126127

security/lockdown/lockdown.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
3636
[LOCKDOWN_KPROBES] = "use of kprobes",
3737
[LOCKDOWN_BPF_READ] = "use of bpf to read kernel RAM",
3838
[LOCKDOWN_PERF] = "unsafe use of perf",
39+
[LOCKDOWN_TRACEFS] = "use of tracefs",
3940
[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
4041
};
4142

0 commit comments

Comments
 (0)