From owner-svn-src-stable-11@freebsd.org  Mon Jul 18 16:34:13 2016
Return-Path: <owner-svn-src-stable-11@freebsd.org>
Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org
 [IPv6:2001:1900:2254:206a::19:1])
 by mailman.ysv.freebsd.org (Postfix) with ESMTP id 9B654B9C463;
 Mon, 18 Jul 2016 16:34:13 +0000 (UTC)
 (envelope-from dchagin@FreeBSD.org)
Received: from repo.freebsd.org (repo.freebsd.org
 [IPv6:2610:1c1:1:6068::e6a:0])
 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
 (Client did not present a certificate)
 by mx1.freebsd.org (Postfix) with ESMTPS id 568F61C71;
 Mon, 18 Jul 2016 16:34:13 +0000 (UTC)
 (envelope-from dchagin@FreeBSD.org)
Received: from repo.freebsd.org ([127.0.1.37])
 by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u6IGYC1v023116;
 Mon, 18 Jul 2016 16:34:12 GMT (envelope-from dchagin@FreeBSD.org)
Received: (from dchagin@localhost)
 by repo.freebsd.org (8.15.2/8.15.2/Submit) id u6IGYBUq023109;
 Mon, 18 Jul 2016 16:34:11 GMT (envelope-from dchagin@FreeBSD.org)
Message-Id: <201607181634.u6IGYBUq023109@repo.freebsd.org>
X-Authentication-Warning: repo.freebsd.org: dchagin set sender to
 dchagin@FreeBSD.org using -f
From: Dmitry Chagin <dchagin@FreeBSD.org>
Date: Mon, 18 Jul 2016 16:34:11 +0000 (UTC)
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
X-SVN-Group: stable-11
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: svn-src-stable-11@freebsd.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: SVN commit messages for only the 11-stable src tree
 <svn-src-stable-11.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/svn-src-stable-11>, 
 <mailto:svn-src-stable-11-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-stable-11/>
List-Post: <mailto:svn-src-stable-11@freebsd.org>
List-Help: <mailto:svn-src-stable-11-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/svn-src-stable-11>, 
 <mailto:svn-src-stable-11-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Mon, 18 Jul 2016 16:34:13 -0000

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); }