Commit a24c6f7b authored by Peter Enderborg's avatar Peter Enderborg Committed by Greg Kroah-Hartman

debugfs: Add access restriction option

Since debugfs include sensitive information it need to be treated
carefully. But it also has many very useful debug functions for userspace.
With this option we can have same configuration for system with
need of debugfs and a way to turn it off. This gives a extra protection
for exposure on systems where user-space services with system
access are attacked.

It is controlled by a configurable default value that can be override
with a kernel command line parameter. (debugfs=)

It can be on or off, but also internally on but not seen from user-space.
This no-mount mode do not register a debugfs as filesystem, but client can
register their parts in the internal structures. This data can be readed
with a debugger or saved with a crashkernel. When it is off clients
get EPERM error when accessing the functions for registering their
components.
Signed-off-by: default avatarPeter Enderborg <peter.enderborg@sony.com>
Link: https://lore.kernel.org/r/20200716071511.26864-3-peter.enderborg@sony.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 072e133d
...@@ -827,6 +827,21 @@ ...@@ -827,6 +827,21 @@
useful to also enable the page_owner functionality. useful to also enable the page_owner functionality.
on: enable the feature on: enable the feature
debugfs= [KNL] This parameter enables what is exposed to userspace
and debugfs internal clients.
Format: { on, no-mount, off }
on: All functions are enabled.
no-mount:
Filesystem is not registered but kernel clients can
access APIs and a crashkernel can be used to read
its content. There is nothing to mount.
off: Filesystem is not registered and clients
get a -EPERM as result when trying to register files
or directories within debugfs.
This is equivalent of the runtime functionality if
debugfs was not enabled in the kernel at all.
Default value is set in build-time with a kernel configuration.
debugpat [X86] Enable PAT debugging debugpat [X86] Enable PAT debugging
decnet.addr= [HW,NET] decnet.addr= [HW,NET]
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
static struct vfsmount *debugfs_mount; static struct vfsmount *debugfs_mount;
static int debugfs_mount_count; static int debugfs_mount_count;
static bool debugfs_registered; static bool debugfs_registered;
static unsigned int debugfs_allow = DEFAULT_DEBUGFS_ALLOW_BITS;
/* /*
* Don't allow access attributes to be changed whilst the kernel is locked down * Don't allow access attributes to be changed whilst the kernel is locked down
...@@ -266,6 +267,9 @@ static struct dentry *debug_mount(struct file_system_type *fs_type, ...@@ -266,6 +267,9 @@ static struct dentry *debug_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, int flags, const char *dev_name,
void *data) void *data)
{ {
if (!(debugfs_allow & DEBUGFS_ALLOW_API))
return ERR_PTR(-EPERM);
return mount_single(fs_type, flags, data, debug_fill_super); return mount_single(fs_type, flags, data, debug_fill_super);
} }
...@@ -311,6 +315,9 @@ static struct dentry *start_creating(const char *name, struct dentry *parent) ...@@ -311,6 +315,9 @@ static struct dentry *start_creating(const char *name, struct dentry *parent)
struct dentry *dentry; struct dentry *dentry;
int error; int error;
if (!(debugfs_allow & DEBUGFS_ALLOW_API))
return ERR_PTR(-EPERM);
pr_debug("creating file '%s'\n", name); pr_debug("creating file '%s'\n", name);
if (IS_ERR(parent)) if (IS_ERR(parent))
...@@ -385,6 +392,11 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode, ...@@ -385,6 +392,11 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return dentry; return dentry;
if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
failed_creating(dentry);
return ERR_PTR(-EPERM);
}
inode = debugfs_get_inode(dentry->d_sb); inode = debugfs_get_inode(dentry->d_sb);
if (unlikely(!inode)) { if (unlikely(!inode)) {
pr_err("out of free dentries, can not create file '%s'\n", pr_err("out of free dentries, can not create file '%s'\n",
...@@ -541,6 +553,11 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) ...@@ -541,6 +553,11 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return dentry; return dentry;
if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
failed_creating(dentry);
return ERR_PTR(-EPERM);
}
inode = debugfs_get_inode(dentry->d_sb); inode = debugfs_get_inode(dentry->d_sb);
if (unlikely(!inode)) { if (unlikely(!inode)) {
pr_err("out of free dentries, can not create directory '%s'\n", pr_err("out of free dentries, can not create directory '%s'\n",
...@@ -583,6 +600,11 @@ struct dentry *debugfs_create_automount(const char *name, ...@@ -583,6 +600,11 @@ struct dentry *debugfs_create_automount(const char *name,
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return dentry; return dentry;
if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
failed_creating(dentry);
return ERR_PTR(-EPERM);
}
inode = debugfs_get_inode(dentry->d_sb); inode = debugfs_get_inode(dentry->d_sb);
if (unlikely(!inode)) { if (unlikely(!inode)) {
pr_err("out of free dentries, can not create automount '%s'\n", pr_err("out of free dentries, can not create automount '%s'\n",
...@@ -786,10 +808,27 @@ bool debugfs_initialized(void) ...@@ -786,10 +808,27 @@ bool debugfs_initialized(void)
} }
EXPORT_SYMBOL_GPL(debugfs_initialized); EXPORT_SYMBOL_GPL(debugfs_initialized);
static int __init debugfs_kernel(char *str)
{
if (str) {
if (!strcmp(str, "on"))
debugfs_allow = DEBUGFS_ALLOW_API | DEBUGFS_ALLOW_MOUNT;
else if (!strcmp(str, "no-mount"))
debugfs_allow = DEBUGFS_ALLOW_API;
else if (!strcmp(str, "off"))
debugfs_allow = 0;
}
return 0;
}
early_param("debugfs", debugfs_kernel);
static int __init debugfs_init(void) static int __init debugfs_init(void)
{ {
int retval; int retval;
if (!(debugfs_allow & DEBUGFS_ALLOW_MOUNT))
return -EPERM;
retval = sysfs_create_mount_point(kernel_kobj, "debug"); retval = sysfs_create_mount_point(kernel_kobj, "debug");
if (retval) if (retval)
return retval; return retval;
......
...@@ -29,4 +29,18 @@ struct debugfs_fsdata { ...@@ -29,4 +29,18 @@ struct debugfs_fsdata {
*/ */
#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0) #define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
/* Access BITS */
#define DEBUGFS_ALLOW_API BIT(0)
#define DEBUGFS_ALLOW_MOUNT BIT(1)
#ifdef CONFIG_DEBUG_FS_ALLOW_ALL
#define DEFAULT_DEBUGFS_ALLOW_BITS (DEBUGFS_ALLOW_MOUNT | DEBUGFS_ALLOW_API)
#endif
#ifdef CONFIG_DEBUG_FS_DISALLOW_MOUNT
#define DEFAULT_DEBUGFS_ALLOW_BITS (DEBUGFS_ALLOW_API)
#endif
#ifdef CONFIG_DEBUG_FS_ALLOW_NONE
#define DEFAULT_DEBUGFS_ALLOW_BITS (0)
#endif
#endif /* _DEBUGFS_INTERNAL_H_ */ #endif /* _DEBUGFS_INTERNAL_H_ */
...@@ -476,6 +476,38 @@ config DEBUG_FS ...@@ -476,6 +476,38 @@ config DEBUG_FS
If unsure, say N. If unsure, say N.
choice
prompt "Debugfs default access"
depends on DEBUG_FS
default DEBUG_FS_ALLOW_ALL
help
This selects the default access restrictions for debugfs.
It can be overridden with kernel command line option
debugfs=[on,no-mount,off]. The restrictions apply for API access
and filesystem registration.
config DEBUG_FS_ALLOW_ALL
bool "Access normal"
help
No restrictions apply. Both API and filesystem registration
is on. This is the normal default operation.
config DEBUG_FS_DISALLOW_MOUNT
bool "Do not register debugfs as filesystem"
help
The API is open but filesystem is not loaded. Clients can still do
their work and read with debug tools that do not need
debugfs filesystem.
config DEBUG_FS_ALLOW_NONE
bool "No access"
help
Access is off. Clients get -PERM when trying to create nodes in
debugfs tree and debugfs is not registered as a filesystem.
Client can then back-off or continue without debugfs access.
endchoice
source "lib/Kconfig.kgdb" source "lib/Kconfig.kgdb"
source "lib/Kconfig.ubsan" source "lib/Kconfig.ubsan"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment