Skip to content

Commit a24c6f7

Browse files
Peter Enderborggregkh
authored andcommitted
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: Peter Enderborg <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 072e133 commit a24c6f7

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,21 @@
827827
useful to also enable the page_owner functionality.
828828
on: enable the feature
829829

830+
debugfs= [KNL] This parameter enables what is exposed to userspace
831+
and debugfs internal clients.
832+
Format: { on, no-mount, off }
833+
on: All functions are enabled.
834+
no-mount:
835+
Filesystem is not registered but kernel clients can
836+
access APIs and a crashkernel can be used to read
837+
its content. There is nothing to mount.
838+
off: Filesystem is not registered and clients
839+
get a -EPERM as result when trying to register files
840+
or directories within debugfs.
841+
This is equivalent of the runtime functionality if
842+
debugfs was not enabled in the kernel at all.
843+
Default value is set in build-time with a kernel configuration.
844+
830845
debugpat [X86] Enable PAT debugging
831846

832847
decnet.addr= [HW,NET]

fs/debugfs/inode.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
static struct vfsmount *debugfs_mount;
3636
static int debugfs_mount_count;
3737
static bool debugfs_registered;
38+
static unsigned int debugfs_allow = DEFAULT_DEBUGFS_ALLOW_BITS;
3839

3940
/*
4041
* 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,
266267
int flags, const char *dev_name,
267268
void *data)
268269
{
270+
if (!(debugfs_allow & DEBUGFS_ALLOW_API))
271+
return ERR_PTR(-EPERM);
272+
269273
return mount_single(fs_type, flags, data, debug_fill_super);
270274
}
271275

@@ -311,6 +315,9 @@ static struct dentry *start_creating(const char *name, struct dentry *parent)
311315
struct dentry *dentry;
312316
int error;
313317

318+
if (!(debugfs_allow & DEBUGFS_ALLOW_API))
319+
return ERR_PTR(-EPERM);
320+
314321
pr_debug("creating file '%s'\n", name);
315322

316323
if (IS_ERR(parent))
@@ -385,6 +392,11 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
385392
if (IS_ERR(dentry))
386393
return dentry;
387394

395+
if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
396+
failed_creating(dentry);
397+
return ERR_PTR(-EPERM);
398+
}
399+
388400
inode = debugfs_get_inode(dentry->d_sb);
389401
if (unlikely(!inode)) {
390402
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)
541553
if (IS_ERR(dentry))
542554
return dentry;
543555

556+
if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
557+
failed_creating(dentry);
558+
return ERR_PTR(-EPERM);
559+
}
560+
544561
inode = debugfs_get_inode(dentry->d_sb);
545562
if (unlikely(!inode)) {
546563
pr_err("out of free dentries, can not create directory '%s'\n",
@@ -583,6 +600,11 @@ struct dentry *debugfs_create_automount(const char *name,
583600
if (IS_ERR(dentry))
584601
return dentry;
585602

603+
if (!(debugfs_allow & DEBUGFS_ALLOW_API)) {
604+
failed_creating(dentry);
605+
return ERR_PTR(-EPERM);
606+
}
607+
586608
inode = debugfs_get_inode(dentry->d_sb);
587609
if (unlikely(!inode)) {
588610
pr_err("out of free dentries, can not create automount '%s'\n",
@@ -786,10 +808,27 @@ bool debugfs_initialized(void)
786808
}
787809
EXPORT_SYMBOL_GPL(debugfs_initialized);
788810

811+
static int __init debugfs_kernel(char *str)
812+
{
813+
if (str) {
814+
if (!strcmp(str, "on"))
815+
debugfs_allow = DEBUGFS_ALLOW_API | DEBUGFS_ALLOW_MOUNT;
816+
else if (!strcmp(str, "no-mount"))
817+
debugfs_allow = DEBUGFS_ALLOW_API;
818+
else if (!strcmp(str, "off"))
819+
debugfs_allow = 0;
820+
}
821+
822+
return 0;
823+
}
824+
early_param("debugfs", debugfs_kernel);
789825
static int __init debugfs_init(void)
790826
{
791827
int retval;
792828

829+
if (!(debugfs_allow & DEBUGFS_ALLOW_MOUNT))
830+
return -EPERM;
831+
793832
retval = sysfs_create_mount_point(kernel_kobj, "debug");
794833
if (retval)
795834
return retval;

fs/debugfs/internal.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,18 @@ struct debugfs_fsdata {
2929
*/
3030
#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
3131

32+
/* Access BITS */
33+
#define DEBUGFS_ALLOW_API BIT(0)
34+
#define DEBUGFS_ALLOW_MOUNT BIT(1)
35+
36+
#ifdef CONFIG_DEBUG_FS_ALLOW_ALL
37+
#define DEFAULT_DEBUGFS_ALLOW_BITS (DEBUGFS_ALLOW_MOUNT | DEBUGFS_ALLOW_API)
38+
#endif
39+
#ifdef CONFIG_DEBUG_FS_DISALLOW_MOUNT
40+
#define DEFAULT_DEBUGFS_ALLOW_BITS (DEBUGFS_ALLOW_API)
41+
#endif
42+
#ifdef CONFIG_DEBUG_FS_ALLOW_NONE
43+
#define DEFAULT_DEBUGFS_ALLOW_BITS (0)
44+
#endif
45+
3246
#endif /* _DEBUGFS_INTERNAL_H_ */

lib/Kconfig.debug

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,38 @@ config DEBUG_FS
476476

477477
If unsure, say N.
478478

479+
choice
480+
prompt "Debugfs default access"
481+
depends on DEBUG_FS
482+
default DEBUG_FS_ALLOW_ALL
483+
help
484+
This selects the default access restrictions for debugfs.
485+
It can be overridden with kernel command line option
486+
debugfs=[on,no-mount,off]. The restrictions apply for API access
487+
and filesystem registration.
488+
489+
config DEBUG_FS_ALLOW_ALL
490+
bool "Access normal"
491+
help
492+
No restrictions apply. Both API and filesystem registration
493+
is on. This is the normal default operation.
494+
495+
config DEBUG_FS_DISALLOW_MOUNT
496+
bool "Do not register debugfs as filesystem"
497+
help
498+
The API is open but filesystem is not loaded. Clients can still do
499+
their work and read with debug tools that do not need
500+
debugfs filesystem.
501+
502+
config DEBUG_FS_ALLOW_NONE
503+
bool "No access"
504+
help
505+
Access is off. Clients get -PERM when trying to create nodes in
506+
debugfs tree and debugfs is not registered as a filesystem.
507+
Client can then back-off or continue without debugfs access.
508+
509+
endchoice
510+
479511
source "lib/Kconfig.kgdb"
480512

481513
source "lib/Kconfig.ubsan"

0 commit comments

Comments
 (0)