diff options
Diffstat (limited to 'fs/debugfs/inode.c')
-rw-r--r-- | fs/debugfs/inode.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 042b688ed124..7b975dbb2bb4 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/parser.h> | 26 | #include <linux/parser.h> |
27 | #include <linux/magic.h> | 27 | #include <linux/magic.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/security.h> | ||
29 | 30 | ||
30 | #include "internal.h" | 31 | #include "internal.h" |
31 | 32 | ||
@@ -35,6 +36,32 @@ static struct vfsmount *debugfs_mount; | |||
35 | static int debugfs_mount_count; | 36 | static int debugfs_mount_count; |
36 | static bool debugfs_registered; | 37 | static bool debugfs_registered; |
37 | 38 | ||
39 | /* | ||
40 | * Don't allow access attributes to be changed whilst the kernel is locked down | ||
41 | * so that we can use the file mode as part of a heuristic to determine whether | ||
42 | * to lock down individual files. | ||
43 | */ | ||
44 | static int debugfs_setattr(struct dentry *dentry, struct iattr *ia) | ||
45 | { | ||
46 | int ret = security_locked_down(LOCKDOWN_DEBUGFS); | ||
47 | |||
48 | if (ret && (ia->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))) | ||
49 | return ret; | ||
50 | return simple_setattr(dentry, ia); | ||
51 | } | ||
52 | |||
53 | static const struct inode_operations debugfs_file_inode_operations = { | ||
54 | .setattr = debugfs_setattr, | ||
55 | }; | ||
56 | static const struct inode_operations debugfs_dir_inode_operations = { | ||
57 | .lookup = simple_lookup, | ||
58 | .setattr = debugfs_setattr, | ||
59 | }; | ||
60 | static const struct inode_operations debugfs_symlink_inode_operations = { | ||
61 | .get_link = simple_get_link, | ||
62 | .setattr = debugfs_setattr, | ||
63 | }; | ||
64 | |||
38 | static struct inode *debugfs_get_inode(struct super_block *sb) | 65 | static struct inode *debugfs_get_inode(struct super_block *sb) |
39 | { | 66 | { |
40 | struct inode *inode = new_inode(sb); | 67 | struct inode *inode = new_inode(sb); |
@@ -369,6 +396,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode, | |||
369 | inode->i_mode = mode; | 396 | inode->i_mode = mode; |
370 | inode->i_private = data; | 397 | inode->i_private = data; |
371 | 398 | ||
399 | inode->i_op = &debugfs_file_inode_operations; | ||
372 | inode->i_fop = proxy_fops; | 400 | inode->i_fop = proxy_fops; |
373 | dentry->d_fsdata = (void *)((unsigned long)real_fops | | 401 | dentry->d_fsdata = (void *)((unsigned long)real_fops | |
374 | DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); | 402 | DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); |
@@ -532,7 +560,7 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) | |||
532 | } | 560 | } |
533 | 561 | ||
534 | inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; | 562 | inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; |
535 | inode->i_op = &simple_dir_inode_operations; | 563 | inode->i_op = &debugfs_dir_inode_operations; |
536 | inode->i_fop = &simple_dir_operations; | 564 | inode->i_fop = &simple_dir_operations; |
537 | 565 | ||
538 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | 566 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
@@ -632,7 +660,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, | |||
632 | return failed_creating(dentry); | 660 | return failed_creating(dentry); |
633 | } | 661 | } |
634 | inode->i_mode = S_IFLNK | S_IRWXUGO; | 662 | inode->i_mode = S_IFLNK | S_IRWXUGO; |
635 | inode->i_op = &simple_symlink_inode_operations; | 663 | inode->i_op = &debugfs_symlink_inode_operations; |
636 | inode->i_link = link; | 664 | inode->i_link = link; |
637 | d_instantiate(dentry, inode); | 665 | d_instantiate(dentry, inode); |
638 | return end_creating(dentry); | 666 | return end_creating(dentry); |