svn commit: r315419 - in head/sys/compat/linuxkpi/common: include/linux src
Hans Petter Selasky
hselasky at FreeBSD.org
Thu Mar 16 16:49:29 UTC 2017
Author: hselasky
Date: Thu Mar 16 16:49:27 2017
New Revision: 315419
URL: https://svnweb.freebsd.org/changeset/base/315419
Log:
Implement more userspace memory access functions in the LinuxKPI.
Obtained from: kmacy @
MFC after: 1 week
Sponsored by: Mellanox Technologies
Modified:
head/sys/compat/linuxkpi/common/include/linux/uaccess.h
head/sys/compat/linuxkpi/common/src/linux_compat.c
Modified: head/sys/compat/linuxkpi/common/include/linux/uaccess.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/uaccess.h Thu Mar 16 16:40:54 2017 (r315418)
+++ head/sys/compat/linuxkpi/common/include/linux/uaccess.h Thu Mar 16 16:49:27 2017 (r315419)
@@ -29,11 +29,22 @@
*
* $FreeBSD$
*/
+
#ifndef _LINUX_UACCESS_H_
#define _LINUX_UACCESS_H_
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+
#include <linux/compiler.h>
+#define VERIFY_READ VM_PROT_READ
+#define VERIFY_WRITE VM_PROT_WRITE
+
#define __get_user(_x, _p) ({ \
int __err; \
__typeof(*(_p)) __x; \
@@ -48,9 +59,13 @@
})
#define get_user(_x, _p) linux_copyin((_p), &(_x), sizeof(*(_p)))
#define put_user(_x, _p) linux_copyout(&(_x), (_p), sizeof(*(_p)))
+#define clear_user(...) linux_clear_user(__VA_ARGS__)
+#define access_ok(...) linux_access_ok(__VA_ARGS__)
extern int linux_copyin(const void *uaddr, void *kaddr, size_t len);
extern int linux_copyout(const void *kaddr, void *uaddr, size_t len);
+extern size_t linux_clear_user(void *uaddr, size_t len);
+extern int linux_access_ok(int rw, const void *uaddr, size_t len);
/*
* NOTE: The returned value from pagefault_disable() must be stored
@@ -69,4 +84,10 @@ pagefault_enable(int save)
vm_fault_enable_pagefaults(save);
}
-#endif /* _LINUX_UACCESS_H_ */
+static inline bool
+pagefault_disabled(void)
+{
+ return ((curthread->td_pflags & TDP_NOFAULTING) != 0);
+}
+
+#endif /* _LINUX_UACCESS_H_ */
Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c Thu Mar 16 16:40:54 2017 (r315418)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c Thu Mar 16 16:49:27 2017 (r315419)
@@ -508,6 +508,53 @@ linux_copyout(const void *kaddr, void *u
return (-copyout(kaddr, uaddr, len));
}
+size_t
+linux_clear_user(void *_uaddr, size_t _len)
+{
+ uint8_t *uaddr = _uaddr;
+ size_t len = _len;
+
+ /* make sure uaddr is aligned before going into the fast loop */
+ while (((uintptr_t)uaddr & 7) != 0 && len > 7) {
+ if (subyte(uaddr, 0))
+ return (_len);
+ uaddr++;
+ len--;
+ }
+
+ /* zero 8 bytes at a time */
+ while (len > 7) {
+ if (suword64(uaddr, 0))
+ return (_len);
+ uaddr += 8;
+ len -= 8;
+ }
+
+ /* zero fill end, if any */
+ while (len > 0) {
+ if (subyte(uaddr, 0))
+ return (_len);
+ uaddr++;
+ len--;
+ }
+ return (0);
+}
+
+int
+linux_access_ok(int rw, const void *uaddr, size_t len)
+{
+ uintptr_t saddr;
+ uintptr_t eaddr;
+
+ /* get start and end address */
+ saddr = (uintptr_t)uaddr;
+ eaddr = (uintptr_t)uaddr + len;
+
+ /* verify addresses are valid for userspace */
+ return ((saddr == eaddr) ||
+ (eaddr > saddr && eaddr <= VM_MAXUSER_ADDRESS));
+}
+
static int
linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
More information about the svn-src-all
mailing list