Message ID | 20221019193431.2923462-2-jane.chu@oracle.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | vsprintf: check non-canonical pointer by kern_addr_valid() | expand |
Hi Jane, Thank you for the patch! Yet something to improve: [auto build test ERROR on linus/master] [also build test ERROR on v6.1-rc1] [cannot apply to next-20221020] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Jane-Chu/vsprintf-check-non-canonical-pointer-by-kern_addr_valid/20221020-103535 patch link: https://lore.kernel.org/r/20221019193431.2923462-2-jane.chu%40oracle.com patch subject: [PATCH v3 1/1] vsprintf: protect kernel from panic due to non-canonical pointer dereference config: x86_64-rhel-8.3-func compiler: gcc-11 (Debian 11.3.0-8) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/7da79322bb256f65be136ef3ca3d557e42da8ffe git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Jane-Chu/vsprintf-check-non-canonical-pointer-by-kern_addr_valid/20221020-103535 git checkout 7da79322bb256f65be136ef3ca3d557e42da8ffe # save the config file mkdir build_dir && cp config build_dir/.config make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): lib/vsprintf.c: In function 'check_pointer_msg': >> lib/vsprintf.c:701:14: error: implicit declaration of function 'kern_addr_valid'; did you mean 'virt_addr_valid'? [-Werror=implicit-function-declaration] 701 | if (!kern_addr_valid((unsigned long)ptr)) | ^~~~~~~~~~~~~~~ | virt_addr_valid lib/vsprintf.c: In function 'va_format': lib/vsprintf.c:1688:9: warning: function 'va_format' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format] 1688 | buf += vsnprintf(buf, end > buf ? end - buf : 0, va_fmt->fmt, va); | ^~~ cc1: some warnings being treated as errors vim +701 lib/vsprintf.c 687 688 /* 689 * Do not call any complex external code here. Nested printk()/vsprintf() 690 * might cause infinite loops. Failures might break printk() and would 691 * be hard to debug. 692 */ 693 static const char *check_pointer_msg(const void *ptr) 694 { 695 if (!ptr) 696 return "(null)"; 697 698 if ((unsigned long)ptr < PAGE_SIZE || IS_ERR_VALUE(ptr)) 699 return "(efault)"; 700 > 701 if (!kern_addr_valid((unsigned long)ptr)) 702 return "(efault)"; 703 704 return NULL; 705 } 706
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c414a8d9f1ea..b38c12ef1e45 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -698,6 +698,9 @@ static const char *check_pointer_msg(const void *ptr) if ((unsigned long)ptr < PAGE_SIZE || IS_ERR_VALUE(ptr)) return "(efault)"; + if (!kern_addr_valid((unsigned long)ptr)) + return "(efault)"; + return NULL; }
Having stepped on a local kernel bug where reading sysfs has led to out-of-bound pointer dereference by vsprintf() which led to GPF panic. And the reason for GPF is that the OOB pointer was turned to a non-canonical address such as 0x7665645f63616465. vsprintf() already has this line of defense if ((unsigned long)ptr < PAGE_SIZE || IS_ERR_VALUE(ptr)) return "(efault)"; Since a non-canonical pointer can be detected by kern_addr_valid() on architectures that present VM holes as well as meaningful implementation of kern_addr_valid() that detects the non-canonical addresses, this patch addes a check on non-canonical string pointer by kern_addr_valid() and display "(efault)" to alert user that something is wrong instead of unecessarily panic the server. On the other hand, if the non-canonical string pointer is dereferenced else where in the kernel, by virtue of being non-canonical, a crash is expected to be immediate. Signed-off-by: Jane Chu <jane.chu@oracle.com> --- lib/vsprintf.c | 3 +++ 1 file changed, 3 insertions(+)