Author: dchagin
Date: Mon Jul 18 16:34:11 2016
New Revision: 303005
URL: https://svnweb.freebsd.org/changeset/base/303005

Log:
  MFC r302515:
  
  Implement Linux personality() system call mainly due to READ_IMPLIES_EXEC 
flag.
  In Linux if this flag is set, PROT_READ implies PROT_EXEC for mmap().
  Linux/i386 set this flag automatically if the binary requires executable 
stack.
  
  READ_IMPLIES_EXEC flag will be used in the next Linux mmap() commit.
  
  Approved by:  re (gjb)

Added:
  stable/11/sys/compat/linux/linux_persona.h
     - copied unchanged from r302515, head/sys/compat/linux/linux_persona.h
Modified:
  stable/11/sys/amd64/linux/syscalls.master
  stable/11/sys/amd64/linux32/syscalls.master
  stable/11/sys/compat/linux/linux_emul.c
  stable/11/sys/compat/linux/linux_emul.h
  stable/11/sys/compat/linux/linux_misc.c
  stable/11/sys/i386/linux/syscalls.master
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/amd64/linux/syscalls.master
==============================================================================
--- stable/11/sys/amd64/linux/syscalls.master   Mon Jul 18 16:06:21 2016        
(r303004)
+++ stable/11/sys/amd64/linux/syscalls.master   Mon Jul 18 16:34:11 2016        
(r303005)
@@ -270,7 +270,7 @@
 133    AUE_MKNOD       STD     { int linux_mknod(char *path, l_int mode, \
                                    l_dev_t dev); }
 134    AUE_USELIB      UNIMPL  uselib
-135    AUE_PERSONALITY STD     { int linux_personality(l_ulong per); }
+135    AUE_PERSONALITY STD     { int linux_personality(l_uint per); }
 136    AUE_NULL        STD     { int linux_ustat(l_dev_t dev, \
                                    struct l_ustat *ubuf); }
 137    AUE_STATFS      STD     { int linux_statfs(char *path, \

Modified: stable/11/sys/amd64/linux32/syscalls.master
==============================================================================
--- stable/11/sys/amd64/linux32/syscalls.master Mon Jul 18 16:06:21 2016        
(r303004)
+++ stable/11/sys/amd64/linux32/syscalls.master Mon Jul 18 16:34:11 2016        
(r303005)
@@ -238,7 +238,7 @@
 134    AUE_BDFLUSH     STD     { int linux_bdflush(void); }
 135    AUE_NULL        STD     { int linux_sysfs(l_int option, \
                                    l_ulong arg1, l_ulong arg2); }
-136    AUE_PERSONALITY STD     { int linux_personality(l_ulong per); }
+136    AUE_PERSONALITY STD     { int linux_personality(l_uint per); }
 137    AUE_NULL        UNIMPL  afs_syscall
 138    AUE_SETFSUID    STD     { int linux_setfsuid16(l_uid16_t uid); }
 139    AUE_SETFSGID    STD     { int linux_setfsgid16(l_gid16_t gid); }

Modified: stable/11/sys/compat/linux/linux_emul.c
==============================================================================
--- stable/11/sys/compat/linux/linux_emul.c     Mon Jul 18 16:06:21 2016        
(r303004)
+++ stable/11/sys/compat/linux/linux_emul.c     Mon Jul 18 16:34:11 2016        
(r303005)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 
 #include <compat/linux/linux_emul.h>
 #include <compat/linux/linux_misc.h>
+#include <compat/linux/linux_persona.h>
 #include <compat/linux/linux_util.h>
 
 
@@ -127,7 +128,7 @@ linux_proc_init(struct thread *td, struc
                 /* epoll should be destroyed in a case of exec. */
                pem = pem_find(p);
                KASSERT(pem != NULL, ("proc_exit: proc emuldata not found.\n"));
-
+               pem->persona = 0;
                if (pem->epoll != NULL) {
                        emd = pem->epoll;
                        pem->epoll = NULL;
@@ -220,6 +221,9 @@ linux_proc_exec(void *arg __unused, stru
 {
        struct thread *td = curthread;
        struct thread *othertd;
+#if defined(__amd64__)
+       struct linux_pemuldata *pem;
+#endif
 
        /*
         * In a case of execing from linux binary properly detach
@@ -243,6 +247,17 @@ linux_proc_exec(void *arg __unused, stru
                        linux_proc_init(td, NULL, 0);
                else
                        linux_proc_init(td, td, 0);
+#if defined(__amd64__)
+               /*
+                * An IA32 executable which has executable stack will have the
+                * READ_IMPLIES_EXEC personality flag set automatically.
+                */
+               if (SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
+                   imgp->stack_prot & VM_PROT_EXECUTE) {
+                       pem = pem_find(p);
+                       pem->persona |= LINUX_READ_IMPLIES_EXEC;
+               }
+#endif
        }
 }
 

Modified: stable/11/sys/compat/linux/linux_emul.h
==============================================================================
--- stable/11/sys/compat/linux/linux_emul.h     Mon Jul 18 16:06:21 2016        
(r303004)
+++ stable/11/sys/compat/linux/linux_emul.h     Mon Jul 18 16:34:11 2016        
(r303005)
@@ -67,6 +67,7 @@ struct linux_pemuldata {
        uint32_t        flags;          /* process emuldata flags */
        struct sx       pem_sx;         /* lock for this struct */
        void            *epoll;         /* epoll data */
+       uint32_t        persona;        /* process execution domain */
 };
 
 #define        LINUX_PEM_XLOCK(p)      sx_xlock(&(p)->pem_sx)

Modified: stable/11/sys/compat/linux/linux_misc.c
==============================================================================
--- stable/11/sys/compat/linux/linux_misc.c     Mon Jul 18 16:06:21 2016        
(r303004)
+++ stable/11/sys/compat/linux/linux_misc.c     Mon Jul 18 16:34:11 2016        
(r303005)
@@ -1200,15 +1200,23 @@ linux_mknodat(struct thread *td, struct 
 int
 linux_personality(struct thread *td, struct linux_personality_args *args)
 {
+       struct linux_pemuldata *pem;
+       struct proc *p = td->td_proc;
+       uint32_t old;
+
 #ifdef DEBUG
        if (ldebug(personality))
-               printf(ARGS(personality, "%lu"), (unsigned long)args->per);
+               printf(ARGS(personality, "%u"), args->per);
 #endif
-       if (args->per != 0)
-               return (EINVAL);
 
-       /* Yes Jim, it's still a Linux... */
-       td->td_retval[0] = 0;
+       PROC_LOCK(p);
+       pem = pem_find(p);
+       old = pem->persona;
+       if (args->per != 0xffffffff)
+               pem->persona = args->per;
+       PROC_UNLOCK(p);
+
+       td->td_retval[0] = old;
        return (0);
 }
 

Copied: stable/11/sys/compat/linux/linux_persona.h (from r302515, 
head/sys/compat/linux/linux_persona.h)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/11/sys/compat/linux/linux_persona.h  Mon Jul 18 16:34:11 2016        
(r303005, copy of r302515, head/sys/compat/linux/linux_persona.h)
@@ -0,0 +1,56 @@
+/*
+ * $FreeBSD$
+ */
+
+#ifndef LINUX_PERSONALITY_H
+#define LINUX_PERSONALITY_H
+
+/*
+ * Flags for bug emulation.
+ *
+ * These occupy the top three bytes.
+ */
+enum {
+       LINUX_UNAME26 =                 0x0020000,
+       LINUX_ADDR_NO_RANDOMIZE =       0x0040000,      /* disable randomization
+                                                        * of VA space
+                                                        */
+       LINUX_FDPIC_FUNCPTRS =          0x0080000,      /* userspace function
+                                                        * ptrs point to 
descriptors
+                                                        * (signal handling)
+                                                        */
+       LINUX_MMAP_PAGE_ZERO =          0x0100000,
+       LINUX_ADDR_COMPAT_LAYOUT =      0x0200000,
+       LINUX_READ_IMPLIES_EXEC =       0x0400000,
+       LINUX_ADDR_LIMIT_32BIT =        0x0800000,
+       LINUX_SHORT_INODE =             0x1000000,
+       LINUX_WHOLE_SECONDS =           0x2000000,
+       LINUX_STICKY_TIMEOUTS =         0x4000000,
+       LINUX_ADDR_LIMIT_3GB =          0x8000000,
+};
+
+/*
+ * Security-relevant compatibility flags that must be
+ * cleared upon setuid or setgid exec:
+ */
+#define LINUX_PER_CLEAR_ON_SETID       (LINUX_READ_IMPLIES_EXEC  | \
+                                       LINUX_ADDR_NO_RANDOMIZE  | \
+                                       LINUX_ADDR_COMPAT_LAYOUT | \
+                                       LINUX_MMAP_PAGE_ZERO)
+
+/*
+ * Personality types.
+ *
+ * These go in the low byte.  Avoid using the top bit, it will
+ * conflict with error returns.
+ */
+enum {
+       LINUX_PER_LINUX =       0x0000,
+       LINUX_PER_LINUX_32BIT = 0x0000 | LINUX_ADDR_LIMIT_32BIT,
+       LINUX_PER_LINUX_FDPIC = 0x0000 | LINUX_FDPIC_FUNCPTRS,
+       LINUX_PER_LINUX32 =     0x0008,
+       LINUX_PER_LINUX32_3GB = 0x0008 | LINUX_ADDR_LIMIT_3GB,
+       LINUX_PER_MASK =        0x00ff,
+};
+
+#endif /* LINUX_PERSONALITY_H */

Modified: stable/11/sys/i386/linux/syscalls.master
==============================================================================
--- stable/11/sys/i386/linux/syscalls.master    Mon Jul 18 16:06:21 2016        
(r303004)
+++ stable/11/sys/i386/linux/syscalls.master    Mon Jul 18 16:34:11 2016        
(r303005)
@@ -240,7 +240,7 @@
 134    AUE_BDFLUSH     STD     { int linux_bdflush(void); }
 135    AUE_NULL        STD     { int linux_sysfs(l_int option, \
                                    l_ulong arg1, l_ulong arg2); }
-136    AUE_PERSONALITY STD     { int linux_personality(l_ulong per); }
+136    AUE_PERSONALITY STD     { int linux_personality(l_uint per); }
 137    AUE_NULL        UNIMPL  afs_syscall
 138    AUE_SETFSUID    STD     { int linux_setfsuid16(l_uid16_t uid); }
 139    AUE_SETFSGID    STD     { int linux_setfsgid16(l_gid16_t gid); }
_______________________________________________
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