diff options
Diffstat (limited to 'fs/debugfs/file.c')
-rw-r--r-- | fs/debugfs/file.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 93e4ca6b2ad7..87846aad594b 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/atomic.h> | 19 | #include <linux/atomic.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/poll.h> | 21 | #include <linux/poll.h> |
22 | #include <linux/security.h> | ||
22 | 23 | ||
23 | #include "internal.h" | 24 | #include "internal.h" |
24 | 25 | ||
@@ -136,6 +137,25 @@ void debugfs_file_put(struct dentry *dentry) | |||
136 | } | 137 | } |
137 | EXPORT_SYMBOL_GPL(debugfs_file_put); | 138 | EXPORT_SYMBOL_GPL(debugfs_file_put); |
138 | 139 | ||
140 | /* | ||
141 | * Only permit access to world-readable files when the kernel is locked down. | ||
142 | * We also need to exclude any file that has ways to write or alter it as root | ||
143 | * can bypass the permissions check. | ||
144 | */ | ||
145 | static bool debugfs_is_locked_down(struct inode *inode, | ||
146 | struct file *filp, | ||
147 | const struct file_operations *real_fops) | ||
148 | { | ||
149 | if ((inode->i_mode & 07777) == 0444 && | ||
150 | !(filp->f_mode & FMODE_WRITE) && | ||
151 | !real_fops->unlocked_ioctl && | ||
152 | !real_fops->compat_ioctl && | ||
153 | !real_fops->mmap) | ||
154 | return false; | ||
155 | |||
156 | return security_locked_down(LOCKDOWN_DEBUGFS); | ||
157 | } | ||
158 | |||
139 | static int open_proxy_open(struct inode *inode, struct file *filp) | 159 | static int open_proxy_open(struct inode *inode, struct file *filp) |
140 | { | 160 | { |
141 | struct dentry *dentry = F_DENTRY(filp); | 161 | struct dentry *dentry = F_DENTRY(filp); |
@@ -147,6 +167,11 @@ static int open_proxy_open(struct inode *inode, struct file *filp) | |||
147 | return r == -EIO ? -ENOENT : r; | 167 | return r == -EIO ? -ENOENT : r; |
148 | 168 | ||
149 | real_fops = debugfs_real_fops(filp); | 169 | real_fops = debugfs_real_fops(filp); |
170 | |||
171 | r = debugfs_is_locked_down(inode, filp, real_fops); | ||
172 | if (r) | ||
173 | goto out; | ||
174 | |||
150 | real_fops = fops_get(real_fops); | 175 | real_fops = fops_get(real_fops); |
151 | if (!real_fops) { | 176 | if (!real_fops) { |
152 | /* Huh? Module did not clean up after itself at exit? */ | 177 | /* Huh? Module did not clean up after itself at exit? */ |
@@ -272,6 +297,11 @@ static int full_proxy_open(struct inode *inode, struct file *filp) | |||
272 | return r == -EIO ? -ENOENT : r; | 297 | return r == -EIO ? -ENOENT : r; |
273 | 298 | ||
274 | real_fops = debugfs_real_fops(filp); | 299 | real_fops = debugfs_real_fops(filp); |
300 | |||
301 | r = debugfs_is_locked_down(inode, filp, real_fops); | ||
302 | if (r) | ||
303 | goto out; | ||
304 | |||
275 | real_fops = fops_get(real_fops); | 305 | real_fops = fops_get(real_fops); |
276 | if (!real_fops) { | 306 | if (!real_fops) { |
277 | /* Huh? Module did not cleanup after itself at exit? */ | 307 | /* Huh? Module did not cleanup after itself at exit? */ |