implicit declaration of function ‘copy_struct_from_user’
vysocky opened this issue · comments
The latest version (commit 4276242) of the HSMP is not possible to compile because of the following error:
$ make
make -C /lib/modules/`uname -r`/build M=$PWD modules
make[1]: Entering directory `/usr/src/kernels/3.10.0-1160.53.1.el7.x86_64'
CC [M] /apps/all/AMD_hsmp/42762428221d7304dd12ebc9c724952fa5a5d253/amd_hsmp.o
/apps/all/AMD_hsmp/42762428221d7304dd12ebc9c724952fa5a5d253/amd_hsmp.c: In function ‘hsmp_ioctl’:
/apps/all/AMD_hsmp/42762428221d7304dd12ebc9c724952fa5a5d253/amd_hsmp.c:280:2: error: implicit declaration of function ‘copy_struct_from_user’ [-Werror=implicit-function-declaration]
if (copy_struct_from_user(&msg, sizeof(msg), arguser, sizeof(struct hsmp_message)))
^
cc1: some warnings being treated as errors
make[2]: *** [/apps/all/AMD_hsmp/42762428221d7304dd12ebc9c724952fa5a5d253/amd_hsmp.o] Error 1
make[1]: *** [_module_/apps/all/AMD_hsmp/42762428221d7304dd12ebc9c724952fa5a5d253] Error 2
make[1]: Leaving directory `/usr/src/kernels/3.10.0-1160.53.1.el7.x86_64'
$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Hi Vysocky
API 'copy_struct_from_user' was introduced to include/linux/uaccess.h header in v5.4 kernel
linux$ git describe f5a1a536fa14895ccff4e94e6a5af90901ce86aa
v5.4-rc1-1-gf5a1a536fa14
It looks like you are trying to build this module in 3.10 kernel. Could you use 'copy_from_user' locally. While, will modify code to use the appropriate API based on kernel version.
I had to add the following block of code extracted from several header files, but it is working
static inline bool should_fail_usercopy(void) { return false; }
static inline bool kasan_check_write(const volatile void *p, unsigned int size)
{
return true;
}
#define KCSAN_ACCESS_WRITE (1 << 0) /* Access is a write. */
#define kcsan_check_write(ptr, size) \
kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE)
static inline void kcsan_check_access(const volatile void *ptr, size_t size,
int type) { }
static __always_inline void
instrument_copy_from_user(const void *to, const void __user *from, unsigned long n)
{
kasan_check_write(to, n);
kcsan_check_write(to, n);
}
static __always_inline __must_check unsigned long
raw_copy_from_user(void *dst, const void __user *src, unsigned long size)
{
return copy_user_generic(dst, (__force void *)src, size);
}
#ifdef __LITTLE_ENDIAN
# define aligned_byte_mask(n) ((1ul << 8*(n))-1)
#else
# define aligned_byte_mask(n) (~0xfful << (BITS_PER_LONG - 8 - 8*(n)))
#endif
#ifndef user_read_access_begin
#define user_read_access_begin user_access_begin
#define user_read_access_end user_access_end
#endif
#ifndef user_access_begin
#define user_access_begin(ptr,len) access_ok(ptr, len)
#define user_access_end() do { } while (0)
#define unsafe_op_wrap(op, err) do { if (unlikely(op)) goto err; } while (0)
#define unsafe_get_user(x,p,e) unsafe_op_wrap(__get_user(x,p),e)
#define unsafe_put_user(x,p,e) unsafe_op_wrap(__put_user(x,p),e)
#define unsafe_copy_to_user(d,s,l,e) unsafe_op_wrap(__copy_to_user(d,s,l),e)
#define unsafe_copy_from_user(d,s,l,e) unsafe_op_wrap(__copy_from_user(d,s,l),e)
static inline unsigned long user_access_save(void) { return 0UL; }
static inline void user_access_restore(unsigned long flags) { }
#endif
#define access_ok(addr, size) \
({ \
WARN_ON_IN_IRQ(); \
likely(!__range_not_ok(addr, size, TASK_SIZE_MAX)); \
})
int check_zeroed_user(const void __user *from, size_t size)
{
unsigned long val;
uintptr_t align = (uintptr_t) from % sizeof(unsigned long);
if (unlikely(size == 0))
return 1;
from -= align;
size += align;
if (!user_read_access_begin(from, size))
return -EFAULT;
unsafe_get_user(val, (unsigned long __user *) from, err_fault);
if (align)
val &= ~aligned_byte_mask(align);
while (size > sizeof(unsigned long)) {
if (unlikely(val))
goto done;
from += sizeof(unsigned long);
size -= sizeof(unsigned long);
unsafe_get_user(val, (unsigned long __user *) from, err_fault);
}
if (size < sizeof(unsigned long))
val &= aligned_byte_mask(size);
done:
user_read_access_end();
return (val == 0);
err_fault:
user_read_access_end();
return -EFAULT;
}
static __always_inline __must_check int
copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
size_t usize)
{
size_t size = min(ksize, usize);
size_t rest = max(ksize, usize) - size;
/* Deal with trailing bytes. */
if (usize < ksize) {
memset(dst + size, 0, rest);
} else if (usize > ksize) {
int ret = check_zeroed_user(src + size, rest);
if (ret <= 0)
return ret ?: -E2BIG;
}
/* Copy the interoperable parts of the struct. */
if (copy_from_user(dst, src, size))
return -EFAULT;
return 0;
}
Dear @nchatrad ,
what is the status of this issue? Do you have any expectation when it will be solved?
@vysocky
as mentioned earlier, for older kernel versions prior to v5.4 (where copy_struct_from_user() is not defined). You may use the following change in the driver.
- if (copy_struct_from_user(&msg, sizeof(msg), arguser, sizeof(struct hsmp_message)))
+ if (copy_from_user(&msg, arguser, sizeof(struct hsmp_message)))
Note: this driver is accepted https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=for-next&id=91f410aa679a035e7abdff47daca4418c384c770