1c33fa9f5SIngo Molnar /* 2c33fa9f5SIngo Molnar * Access kernel memory without faulting. 3c33fa9f5SIngo Molnar */ 4c33fa9f5SIngo Molnar #include <linux/uaccess.h> 5c33fa9f5SIngo Molnar #include <linux/module.h> 6c33fa9f5SIngo Molnar #include <linux/mm.h> 7c33fa9f5SIngo Molnar 8c33fa9f5SIngo Molnar /** 9c33fa9f5SIngo Molnar * probe_kernel_read(): safely attempt to read from a location 10c33fa9f5SIngo Molnar * @dst: pointer to the buffer that shall take the data 11c33fa9f5SIngo Molnar * @src: address to read from 12c33fa9f5SIngo Molnar * @size: size of the data chunk 13c33fa9f5SIngo Molnar * 14c33fa9f5SIngo Molnar * Safely read from address @src to the buffer at @dst. If a kernel fault 15c33fa9f5SIngo Molnar * happens, handle that and return -EFAULT. 16c33fa9f5SIngo Molnar */ 17c33fa9f5SIngo Molnar long probe_kernel_read(void *dst, void *src, size_t size) 18c33fa9f5SIngo Molnar { 19c33fa9f5SIngo Molnar long ret; 20b4b8ac52SJason Wessel mm_segment_t old_fs = get_fs(); 21c33fa9f5SIngo Molnar 22b4b8ac52SJason Wessel set_fs(KERNEL_DS); 23c33fa9f5SIngo Molnar pagefault_disable(); 24c33fa9f5SIngo Molnar ret = __copy_from_user_inatomic(dst, 25c33fa9f5SIngo Molnar (__force const void __user *)src, size); 26c33fa9f5SIngo Molnar pagefault_enable(); 27b4b8ac52SJason Wessel set_fs(old_fs); 28c33fa9f5SIngo Molnar 29c33fa9f5SIngo Molnar return ret ? -EFAULT : 0; 30c33fa9f5SIngo Molnar } 31c33fa9f5SIngo Molnar EXPORT_SYMBOL_GPL(probe_kernel_read); 32c33fa9f5SIngo Molnar 33c33fa9f5SIngo Molnar /** 34c33fa9f5SIngo Molnar * probe_kernel_write(): safely attempt to write to a location 35c33fa9f5SIngo Molnar * @dst: address to write to 36c33fa9f5SIngo Molnar * @src: pointer to the data that shall be written 37c33fa9f5SIngo Molnar * @size: size of the data chunk 38c33fa9f5SIngo Molnar * 39c33fa9f5SIngo Molnar * Safely write to address @dst from the buffer at @src. If a kernel fault 40c33fa9f5SIngo Molnar * happens, handle that and return -EFAULT. 41c33fa9f5SIngo Molnar */ 42c33fa9f5SIngo Molnar long probe_kernel_write(void *dst, void *src, size_t size) 43c33fa9f5SIngo Molnar { 44c33fa9f5SIngo Molnar long ret; 45b4b8ac52SJason Wessel mm_segment_t old_fs = get_fs(); 46c33fa9f5SIngo Molnar 47b4b8ac52SJason Wessel set_fs(KERNEL_DS); 48c33fa9f5SIngo Molnar pagefault_disable(); 49c33fa9f5SIngo Molnar ret = __copy_to_user_inatomic((__force void __user *)dst, src, size); 50c33fa9f5SIngo Molnar pagefault_enable(); 51b4b8ac52SJason Wessel set_fs(old_fs); 52c33fa9f5SIngo Molnar 53c33fa9f5SIngo Molnar return ret ? -EFAULT : 0; 54c33fa9f5SIngo Molnar } 55c33fa9f5SIngo Molnar EXPORT_SYMBOL_GPL(probe_kernel_write); 56