• Steven Rostedt (Google)'s avatar
    tracefs: Check for dentry->d_inode exists in set_gid() · ad579864
    Steven Rostedt (Google) authored
    If a getdents() is called on the tracefs directory but does not get all
    the files, it can leave a "cursor" dentry in the d_subdirs list of tracefs
    dentry. This cursor dentry does not have a d_inode for it. Before
    referencing tracefs_inode from the dentry, the d_inode must first be
    checked if it has content. If not, then it's not a tracefs_inode and can
    be ignored.
    
    The following caused a crash:
    
     #define getdents64(fd, dirp, count) syscall(SYS_getdents64, fd, dirp, count)
     #define BUF_SIZE 256
     #define TDIR "/tmp/file0"
    
     int main(void)
     {
    	char buf[BUF_SIZE];
    	int fd;
           	int n;
    
           	mkdir(TDIR, 0777);
    	mount(NULL, TDIR, "tracefs", 0, NULL);
           	fd = openat(AT_FDCWD, TDIR, O_RDONLY);
           	n = getdents64(fd, buf, BUF_SIZE);
           	ret = mount(NULL, TDIR, NULL, MS_NOSUID|MS_REMOUNT|MS_RELATIME|MS_LAZYTIME,
    		    "gid=1000");
    	return 0;
     }
    
    That's because the 256 BUF_SIZE was not big enough to read all the
    dentries of the tracefs file system and it left a "cursor" dentry in the
    subdirs of the tracefs root inode. Then on remounting with "gid=1000",
    it would cause an iteration of all dentries which hit:
    
    	ti = get_tracefs(dentry->d_inode);
    	if (ti && (ti->flags & TRACEFS_EVENT_INODE))
    		eventfs_update_gid(dentry, gid);
    
    Which crashed because of the dereference of the cursor dentry which had a NULL
    d_inode.
    
    In the subdir loop of the dentry lookup of set_gid(), if a child has a
    NULL d_inode, simply skip it.
    
    Link: https://lore.kernel.org/all/20240102135637.3a21fb10@gandalf.local.home/
    Link: https://lore.kernel.org/linux-trace-kernel/20240102151249.05da244d@gandalf.local.home
    
    Cc: stable@vger.kernel.org
    Cc: Masami Hiramatsu <mhiramat@kernel.org>
    Cc: Mark Rutland <mark.rutland@arm.com>
    Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
    Fixes: 7e8358ed ("eventfs: Fix file and directory uid and gid ownership")
    Reported-by: default avatar"Ubisectech Sirius" <bugreport@ubisectech.com>
    Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
    ad579864
inode.c 19.9 KB