at master 1.7 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* Perform sanity checking for object sizes for uaccess.h and uio.h. */ 3#ifndef __LINUX_UCOPYSIZE_H__ 4#define __LINUX_UCOPYSIZE_H__ 5 6#include <linux/bug.h> 7 8#ifdef CONFIG_HARDENED_USERCOPY 9#include <linux/jump_label.h> 10extern void __check_object_size(const void *ptr, unsigned long n, 11 bool to_user); 12 13DECLARE_STATIC_KEY_MAYBE(CONFIG_HARDENED_USERCOPY_DEFAULT_ON, 14 validate_usercopy_range); 15 16static __always_inline void check_object_size(const void *ptr, unsigned long n, 17 bool to_user) 18{ 19 if (!__builtin_constant_p(n) && 20 static_branch_maybe(CONFIG_HARDENED_USERCOPY_DEFAULT_ON, 21 &validate_usercopy_range)) { 22 __check_object_size(ptr, n, to_user); 23 } 24} 25#else 26static inline void check_object_size(const void *ptr, unsigned long n, 27 bool to_user) 28{ } 29#endif /* CONFIG_HARDENED_USERCOPY */ 30 31extern void __compiletime_error("copy source size is too small") 32__bad_copy_from(void); 33extern void __compiletime_error("copy destination size is too small") 34__bad_copy_to(void); 35 36void __copy_overflow(int size, unsigned long count); 37 38static inline void copy_overflow(int size, unsigned long count) 39{ 40 if (IS_ENABLED(CONFIG_BUG)) 41 __copy_overflow(size, count); 42} 43 44static __always_inline __must_check bool 45check_copy_size(const void *addr, size_t bytes, bool is_source) 46{ 47 int sz = __builtin_object_size(addr, 0); 48 if (unlikely(sz >= 0 && sz < bytes)) { 49 if (!__builtin_constant_p(bytes)) 50 copy_overflow(sz, bytes); 51 else if (is_source) 52 __bad_copy_from(); 53 else 54 __bad_copy_to(); 55 return false; 56 } 57 if (WARN_ON_ONCE(bytes > INT_MAX)) 58 return false; 59 check_object_size(addr, bytes, is_source); 60 return true; 61} 62 63#endif /* __LINUX_UCOPYSIZE_H__ */