Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 18 Jul 2016 16:34:11 +0000 (UTC)
From:      Dmitry Chagin <dchagin@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r303005 - in stable/11/sys: amd64/linux amd64/linux32 compat/linux i386/linux
Message-ID:  <201607181634.u6IGYBUq023109@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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); }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201607181634.u6IGYBUq023109>