Why does permission on "/sys/kernel/debug/tracing" directory is 700 in RHEL8?

Solution Verified - Updated -

Environment

  • Red Hat Enterprise Linux 8

Issue

  • our monitoring detected something weird about /sys/kernel/debug/tracing/, saying that it's not accessible by the monitoring user (nrpe)?
  • Why the permission of directory /sys/kernel/debug/tracing is 700 in RHEL8 while it was 755 in RHEL7?
RHEL7
*****

# ll -d /sys/kernel/debug/tracing/
drwxr-xr-x. 8 root root 0 Mar 17  2021 /sys/kernel/debug/tracing/

RHEL8
*****

# ll -d /sys/kernel/debug/tracing/
drwx------. 8 root root 0 Mar  9 02:35 /sys/kernel/debug/tracing/

Resolution

  • This is because on RHEL8, tracing is handled by different filesystem called tracefs. By default tracefs is mounted on /sys/kernel/tracing
  • However if anyone tries to access /sys/kernel/debug/tracing directory, the same filesystem will get mounted there as well.
# mount|grep tra
none on /sys/kernel/tracing type tracefs (rw,relatime,seclabel)

# ll -d /sys/kernel/tracing
drwx------. 8 root root 0 Mar 17 18:06 /sys/kernel/tracing

# ll -d /sys/kernel/debug/tracing
dr-xr-xr-x. 3 root root 0 Mar 17 18:06 /sys/kernel/debug/tracing

# ll -d /sys/kernel/debug/tracing/
drwx------. 8 root root 0 Mar 17 18:06 /sys/kernel/debug/tracing/  <--- [notice following /]

# ll -d /sys/kernel/debug/tracing
drwx------. 8 root root 0 Mar 17 18:06 /sys/kernel/debug/tracing

# mount|grep tra
none on /sys/kernel/tracing type tracefs (rw,relatime,seclabel)
tracefs on /sys/kernel/debug/tracing type tracefs (rw,relatime,seclabel)    <--- [tracefs mounted again]
  • Before 4.1, all ftrace tracing control files were within the debugfs
    file system, which is typically located at /sys/kernel/debug/tracing.
    For backward compatibility, when mounting the debugfs file system,
    the tracefs file system will be automatically mounted at /sys/kernel/debug/tracing

  • All files located in the tracefs file system will be located in that
    debugfs file system directory as well.

  • Refer Add new file system tracefs

  • Also refer Function Tracer or FTRACE which uses tracefs.

Root Cause

  • In the kernel source code of RHEL8, the permission is defined as 700 in following file.
# head -5 fs/tracefs/inode.c
/*
 *  inode.c - part of tracefs, a pseudo file system for activating tracing
 *
 * Based on debugfs by: Greg Kroah-Hartman <greg@kroah.com>
 *

# grep TRACEFS_DEFAULT_MODE fs/tracefs/inode.c -n
28:#define TRACEFS_DEFAULT_MODE 0700
  • If you check the permission of other directories inside /sys/kernel/debug [except tracing] on RHEL8 all have 755 permission.
drwxr-xr-x.  2 root root 0 Mar 13 17:32 acpi
drwxr-xr-x. 11 root root 0 Mar 13 17:32 bdi
drwxr-xr-x.  8 root root 0 Mar 13 17:32 block
drwxr-xr-x.  2 root root 0 Mar 13 17:32 cleancache
drwxr-xr-x.  2 root root 0 Mar 13 17:32 clk
drwxr-xr-x.  2 root root 0 Mar 13 17:32 device_component
drwxr-xr-x.  2 root root 0 Mar 13 17:32 dma_buf
drwxr-xr-x.  3 root root 0 Mar 13 17:32 dri
drwxr-xr-x.  2 root root 0 Mar 13 17:32 dynamic_debug
drwxr-xr-x.  2 root root 0 Mar 13 17:32 error_injection
drwxr-xr-x.  2 root root 0 Mar 13 17:32 extfrag
drwxr-xr-x.  2 root root 0 Mar 13 17:32 frontswap
drwxr-xr-x.  3 root root 0 Mar 13 17:32 hid
drwxr-xr-x.  2 root root 0 Mar 13 22:32 intel_powerclamp
drwxr-xr-x.  4 root root 0 Mar 13 17:32 ixgbe
drwxr-xr-x.  2 root root 0 Mar 13 17:32 kprobes
drwxr-xr-x.  2 root root 0 Mar 13 22:32 kvm
drwxr-xr-x.  2 root root 0 Mar 13 17:32 mce
drwxr-xr-x.  3 root root 0 Mar 13 17:32 megaraid_sas
drwxr-xr-x.  2 root root 0 Mar 13 17:32 pinctrl
drwxr-xr-x.  2 root root 0 Mar 13 22:32 pkg_temp_thermal
drwxr-xr-x.  2 root root 0 Mar 13 17:32 pm_genpd
drwxr-xr-x.  2 root root 0 Mar 13 17:32 ras
drwxr-xr-x.  2 root root 0 Mar 13 17:32 regmap
drwxr-xr-x.  2 root root 0 Mar 13 17:32 resctrl
drwxr-xr-x.  5 root root 0 Mar 13 22:32 sunrpc
drwxr-xr-x.  2 root root 0 Mar 13 17:32 swiotlb
drwx------.  8 root root 0 Mar 13 17:32 tracing
drwxr-xr-x.  7 root root 0 Mar 13 17:32 usb
drwxr-xr-x.  3 root root 0 Mar 13 17:32 x86
drwxr-xr-x.  2 root root 0 Mar 13 17:32 zsmalloc
drwxr-xr-x.  2 root root 0 Mar 13 17:32 zswap
  • The piece of code which gives 755 permission is as follows. Refer complete source file here
/**
 * debugfs_create_dir - create a directory in the debugfs filesystem
 * @name: a pointer to a string containing the name of the directory to
 *        create.
 * @parent: a pointer to the parent dentry for this file.  This should be a
 *          directory dentry if set.  If this parameter is NULL, then the
 *          directory will be created in the root of the debugfs filesystem.
 *
 * This function creates a directory in debugfs with the given name.
 *
 * This function will return a pointer to a dentry if it succeeds.  This
 * pointer must be passed to the debugfs_remove() function when the file is
 * to be removed (no automatic cleanup happens if your module is unloaded,
 * you are responsible here.)  If an error occurs, %NULL will be returned.
 *
 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
 * returned.
 */
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
{
    struct dentry *dentry = start_creating(name, parent);
    struct inode *inode;

    if (IS_ERR(dentry))
        return NULL;

    inode = debugfs_get_inode(dentry->d_sb);
    if (unlikely(!inode))
        return failed_creating(dentry);

    inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;    <=----- [ Decoding this will come as 755]
    inode->i_op = &debugfs_dir_inode_operations;
    inode->i_fop = &simple_dir_operations;

    /* directory inodes start off with i_nlink == 2 (for "." entry) */
    inc_nlink(inode);
    d_instantiate(dentry, inode);
    inc_nlink(d_inode(dentry->d_parent));
    fsnotify_mkdir(d_inode(dentry->d_parent), dentry);
    return end_creating(dentry);
}
  • In RHEL7, the same function debugfs_create_dir will look like follows. Refer Refer complete source file here
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
{
    return __create_file(name, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,   <=---- [ this also gives 755]
                   parent, NULL, NULL);
}
  • Decoding permission. Refer man chmod(2).
#define S_IFDIR         0040000 
#define S_IRWXU         00700

#define S_IRUGO         (S_IRUSR|S_IRGRP|S_IROTH)
                        #define S_IRUSR 00400  
                        #define S_IRGRP 00040  
                        #define S_IROTH 00004

#define S_IRUGO        (00400 | 00040 | 00004)

#define S_IXUGO         (S_IXUSR|S_IXGRP|S_IXOTH)
                        #define S_IXUSR 00100
                        #define S_IXGRP 00010
                        #define S_IXOTH 00001

#define S_IXUGO        (00100 | 00010 | 00001)


S_IFDIR -> for directory
S_IRWXU -> rwx for user (700)
S_IRUGO -> read for user,group,other (444)
S_IXUGO -> execute for user,group,other (111)

If we OR them, it comes 755.

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.