Skip to content

Commit

Permalink
tracefs: Restrict tracefs when the kernel is locked down
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
Matthew Garrett authored and James Morris committed Aug 20, 2019
1 parent 5496197 commit ccbd54f
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 1 deletion.
42 changes: 41 additions & 1 deletion fs/tracefs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,33 @@
#include <linux/parser.h>
#include <linux/magic.h>
#include <linux/slab.h>
#include <linux/security.h>

#define TRACEFS_DEFAULT_MODE 0700

static struct vfsmount *tracefs_mount;
static int tracefs_mount_count;
static bool tracefs_registered;

static int default_open_file(struct inode *inode, struct file *filp)
{
struct dentry *dentry = filp->f_path.dentry;
struct file_operations *real_fops;
int ret;

if (!dentry)
return -EINVAL;

ret = security_locked_down(LOCKDOWN_TRACEFS);
if (ret)
return ret;

real_fops = dentry->d_fsdata;
if (!real_fops->open)
return 0;
return real_fops->open(inode, filp);
}

static ssize_t default_read_file(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
Expand Down Expand Up @@ -221,6 +241,12 @@ static int tracefs_apply_options(struct super_block *sb)
return 0;
}

static void tracefs_destroy_inode(struct inode *inode)
{
if (S_ISREG(inode->i_mode))
kfree(inode->i_fop);
}

static int tracefs_remount(struct super_block *sb, int *flags, char *data)
{
int err;
Expand Down Expand Up @@ -257,6 +283,7 @@ static int tracefs_show_options(struct seq_file *m, struct dentry *root)
static const struct super_operations tracefs_super_operations = {
.statfs = simple_statfs,
.remount_fs = tracefs_remount,
.destroy_inode = tracefs_destroy_inode,
.show_options = tracefs_show_options,
};

Expand Down Expand Up @@ -387,6 +414,7 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops)
{
struct file_operations *proxy_fops;
struct dentry *dentry;
struct inode *inode;

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

proxy_fops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
if (unlikely(!proxy_fops)) {
iput(inode);
return failed_creating(dentry);
}

if (!fops)
fops = &tracefs_file_operations;

dentry->d_fsdata = (void *)fops;
memcpy(proxy_fops, fops, sizeof(*proxy_fops));
proxy_fops->open = default_open_file;
inode->i_mode = mode;
inode->i_fop = fops ? fops : &tracefs_file_operations;
inode->i_fop = proxy_fops;
inode->i_private = data;
d_instantiate(dentry, inode);
fsnotify_create(dentry->d_parent->d_inode, dentry);
Expand Down
1 change: 1 addition & 0 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ enum lockdown_reason {
LOCKDOWN_KPROBES,
LOCKDOWN_BPF_READ,
LOCKDOWN_PERF,
LOCKDOWN_TRACEFS,
LOCKDOWN_CONFIDENTIALITY_MAX,
};

Expand Down
1 change: 1 addition & 0 deletions security/lockdown/lockdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
[LOCKDOWN_KPROBES] = "use of kprobes",
[LOCKDOWN_BPF_READ] = "use of bpf to read kernel RAM",
[LOCKDOWN_PERF] = "unsafe use of perf",
[LOCKDOWN_TRACEFS] = "use of tracefs",
[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
};

Expand Down

0 comments on commit ccbd54f

Please sign in to comment.