#ifndef _KERNEL_LIBKERN_UMEM_H #define _KERNEL_LIBKERN_UMEM_H #include #include #define USER_STR_MAXLEN (128) #define USER_PTRARRAY_MAXLEN (128) #define USER_STRARRAY_MAXLEN (128) bool umem_validate_str(const char __user* us, size_t maxlen); bool umem_validate_ptrarray(const void __user** uptrarr, size_t maxlen); static ALWAYS_INLINE bool umem_validate_strarray(const char __user** s, size_t maxlen) { return umem_validate_ptrarray((const void __user**)s, maxlen); } void* umem_bring_to_kernel(const void __user* data, size_t size); char* umem_bring_to_kernel_str(const char __user* data, size_t maxlen); char* umem_bring_to_kernel_str_with_len(const char __user* data, size_t size); char** umem_bring_to_kernel_strarray(const char __user** udata, size_t maxlen); void umem_copy_to_user(void __user* dest, const void* src, size_t length); void umem_copy_from_user(void* dest, const void __user* src, size_t length); static ALWAYS_INLINE void umem_get_user_1(uint8_t* ptr, uint8_t* uptr) { *ptr = *uptr; } static ALWAYS_INLINE void umem_get_user_2(uint16_t* ptr, uint16_t* uptr) { *ptr = *uptr; } static ALWAYS_INLINE void umem_get_user_4(uint32_t* ptr, uint32_t* uptr) { *ptr = *uptr; } static ALWAYS_INLINE void umem_get_user_8(uint64_t* ptr, uint64_t* uptr) { *ptr = *uptr; } static ALWAYS_INLINE void umem_put_user_1(uint8_t* val, uint8_t* uptr) { *uptr = *val; } static ALWAYS_INLINE void umem_put_user_2(uint16_t* val, uint16_t* uptr) { *uptr = *val; } static ALWAYS_INLINE void umem_put_user_4(uint32_t* val, uint32_t* uptr) { *uptr = *val; } static ALWAYS_INLINE void umem_put_user_8(uint64_t* val, uint64_t* uptr) { *uptr = *val; } #define __umem_put_user_impl_size(size, x, ptr) umem_put_user_##size(x, ptr) #define umem_put_user(x, ptr) \ ({ \ __typeof__(*(ptr)) __user_val; \ __user_val = x; \ switch (sizeof(*(ptr))) { \ case 1: \ __umem_put_user_impl_size(1, (uint8_t*)&__user_val, (uint8_t*)ptr); \ break; \ case 2: \ __umem_put_user_impl_size(2, (uint16_t*)&__user_val, (uint16_t*)ptr); \ break; \ case 4: \ __umem_put_user_impl_size(4, (uint32_t*)&__user_val, (uint32_t*)ptr); \ break; \ case 8: \ __umem_put_user_impl_size(8, (uint64_t*)&__user_val, (uint64_t*)ptr); \ break; \ default: \ umem_copy_to_user(ptr, &__user_val, sizeof(*(ptr))); \ break; \ } \ }) #define __umem_get_user_impl_size(size, x, ptr) umem_get_user_##size(x, ptr) #define umem_get_user(ptr, uptr) \ ({ \ switch (sizeof(*(ptr))) { \ case 1: \ __umem_get_user_impl_size(1, (uint8_t*)ptr, (uint8_t*)uptr); \ break; \ case 2: \ __umem_get_user_impl_size(2, (uint16_t*)ptr, (uint16_t*)uptr); \ break; \ case 4: \ __umem_get_user_impl_size(4, (uint32_t*)ptr, (uint32_t*)uptr); \ break; \ case 8: \ __umem_get_user_impl_size(8, (uint64_t*)ptr, (uint64_t*)uptr); \ break; \ default: \ umem_copy_from_user(ptr, uptr, sizeof(*(ptr))); \ break; \ } \ }) #endif // _KERNEL_LIBKERN_UMEM_H