From e87e4c8e00b7b22386265fbbb90624468c91d8a7 Mon Sep 17 00:00:00 2001 From: roy Date: Tue, 2 Jan 2024 04:39:17 +0800 Subject: [PATCH] Fix segment fault exe symbolic link then run ls cmd Description ----------- When create a symbolic link and then execute 'ls' command, this will make the segmentation fault in user space Root cause ---------- By checking kernel log, we can see that "usercopy: Kernel memory exposure attempt detected from SLUB object 'simplefs_cache' (offset 0, size 5)!", and by tracing kernel call, we also find call "readlink_copy" fail In readlink_copy, this will copy data to user space, and the message shows kernel memoery exposure. Fix solution ---------- By kernel document https://docs.kernel.org/core-api/memory-allocation.html?highlight=kmem_cache_create "kmem_cache_create() or kmem_cache_create_usercopy() before it can be used. The second function should be used if a part of the cache might be copied to the userspace" and readlink will copy the target name from simplefs inode link(inode->i_link) to the user space, so we replace kmem_cache_create to kmem_cache_create_usercopy How has this been tested: ---------- run make check Testing cmd: ln file hdlink...Success Testing cmd: mkdir dir/dir...Success Testing cmd: ln -s file symlink...Success Testing cmd: ls -lR...Success Testing cmd: mkdir len_of_name_of_this_dir_is_29...Success Testing cmd: touch len_of_name_of_the_file_is_29...Success Testing cmd: ln -s dir len_of_name_of_the_link_is_29...Success Testing cmd: echo abc > file...Success Testing cmd: dd if=/dev/zero of=file bs=1M count=12 status=none...dd: error writing 'file': File too large Check if exist: drwxr-xr-x 3 dir...Success Check if exist: -rw-r--r-- 2 file...Success Check if exist: -rw-r--r-- 2 hdlink...Success Check if exist: drwxr-xr-x 2 dir...Success Check if exist: lrwxrwxrwx 1 symlink...Success Close #30 --- super.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/super.c b/super.c index 5b43c69..a5fea7a 100644 --- a/super.c +++ b/super.c @@ -13,8 +13,11 @@ static struct kmem_cache *simplefs_inode_cache; int simplefs_init_inode_cache(void) { - simplefs_inode_cache = kmem_cache_create( - "simplefs_cache", sizeof(struct simplefs_inode_info), 0, 0, NULL); + simplefs_inode_cache = kmem_cache_create_usercopy( + "simplefs_cache", sizeof(struct simplefs_inode_info), 0, 0, + 0, + sizeof(struct simplefs_inode_info), + NULL); if (!simplefs_inode_cache) return -ENOMEM; return 0;