mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 05:32:00 +00:00
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 <mjg59@google.com> Reviewed-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Cc: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
5496197f9b
commit
ccbd54ff54
@ -20,6 +20,7 @@
|
||||
#include <linux/parser.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#define TRACEFS_DEFAULT_MODE 0700
|
||||
|
||||
@ -27,6 +28,25 @@ 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)
|
||||
{
|
||||
@ -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;
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
@ -121,6 +121,7 @@ enum lockdown_reason {
|
||||
LOCKDOWN_KPROBES,
|
||||
LOCKDOWN_BPF_READ,
|
||||
LOCKDOWN_PERF,
|
||||
LOCKDOWN_TRACEFS,
|
||||
LOCKDOWN_CONFIDENTIALITY_MAX,
|
||||
};
|
||||
|
||||
|
@ -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",
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user