Date: Sun, 10 Jul 2016 08:15:51 +0000 (UTC) From: Dmitry Chagin <dchagin@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r302515 - in head/sys: amd64/linux amd64/linux32 compat/linux i386/linux Message-ID: <201607100815.u6A8FpmA049808@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dchagin Date: Sun Jul 10 08:15:50 2016 New Revision: 302515 URL: https://svnweb.freebsd.org/changeset/base/302515 Log: 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. Added: head/sys/compat/linux/linux_persona.h (contents, props changed) Modified: head/sys/amd64/linux/syscalls.master head/sys/amd64/linux32/syscalls.master head/sys/compat/linux/linux_emul.c head/sys/compat/linux/linux_emul.h head/sys/compat/linux/linux_misc.c head/sys/i386/linux/syscalls.master Modified: head/sys/amd64/linux/syscalls.master ============================================================================== --- head/sys/amd64/linux/syscalls.master Sun Jul 10 08:04:02 2016 (r302514) +++ head/sys/amd64/linux/syscalls.master Sun Jul 10 08:15:50 2016 (r302515) @@ -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: head/sys/amd64/linux32/syscalls.master ============================================================================== --- head/sys/amd64/linux32/syscalls.master Sun Jul 10 08:04:02 2016 (r302514) +++ head/sys/amd64/linux32/syscalls.master Sun Jul 10 08:15:50 2016 (r302515) @@ -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: head/sys/compat/linux/linux_emul.c ============================================================================== --- head/sys/compat/linux/linux_emul.c Sun Jul 10 08:04:02 2016 (r302514) +++ head/sys/compat/linux/linux_emul.c Sun Jul 10 08:15:50 2016 (r302515) @@ -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: head/sys/compat/linux/linux_emul.h ============================================================================== --- head/sys/compat/linux/linux_emul.h Sun Jul 10 08:04:02 2016 (r302514) +++ head/sys/compat/linux/linux_emul.h Sun Jul 10 08:15:50 2016 (r302515) @@ -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: head/sys/compat/linux/linux_misc.c ============================================================================== --- head/sys/compat/linux/linux_misc.c Sun Jul 10 08:04:02 2016 (r302514) +++ head/sys/compat/linux/linux_misc.c Sun Jul 10 08:15:50 2016 (r302515) @@ -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); } Added: head/sys/compat/linux/linux_persona.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/compat/linux/linux_persona.h Sun Jul 10 08:15:50 2016 (r302515) @@ -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: head/sys/i386/linux/syscalls.master ============================================================================== --- head/sys/i386/linux/syscalls.master Sun Jul 10 08:04:02 2016 (r302514) +++ head/sys/i386/linux/syscalls.master Sun Jul 10 08:15:50 2016 (r302515) @@ -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?201607100815.u6A8FpmA049808>