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)
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to