diff options
| author | Patrick Mooney <pmooney@pfmooney.com> | 2016-03-22 22:51:09 +0000 |
|---|---|---|
| committer | Patrick Mooney <pmooney@pfmooney.com> | 2016-03-23 19:38:41 +0000 |
| commit | fcc3d074e6a2ad9529ce014e16d99720f33a053d (patch) | |
| tree | 4a1962c1cccd07dd28ef33a85585b3a0c00f8bfd | |
| parent | c11422a43e3c04c55f76ea9544fd8650f35c3309 (diff) | |
| download | illumos-joyent-fcc3d074e6a2ad9529ce014e16d99720f33a053d.tar.gz | |
OS-5259 lxbrand mmap(2) should heed personality
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Cody Mello <melloc@joyent.com>
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/lx_brand.c | 4 | ||||
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/mem.c | 15 | ||||
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/misc.c | 55 | ||||
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h | 1 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_brand.c | 37 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_syscall.c | 4 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_proc.h | 2 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_prvnops.c | 36 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_brand.h | 23 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_syscalls.h | 1 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_personality.c | 112 | ||||
| -rw-r--r-- | usr/src/uts/intel/Makefile.files | 1 |
12 files changed, 220 insertions, 71 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c index 87d89cf34f..e7d5ddccc3 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c +++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c @@ -1098,7 +1098,7 @@ static lx_syscall_handler_t lx_handlers[] = { lx_utime, /* 132: utime */ lx_mknod, /* 133: mknod */ NULL, /* 134: uselib */ - lx_personality, /* 135: personality */ + NULL, /* 135: personality */ NULL, /* 136: ustat */ lx_statfs, /* 137: statfs */ lx_fstatfs, /* 138: fstatfs */ @@ -1430,7 +1430,7 @@ static lx_syscall_handler_t lx_handlers[] = { lx_fchdir, /* 133: fchdir */ NULL, /* 134: bdflush */ lx_sysfs, /* 135: sysfs */ - lx_personality, /* 136: personality */ + NULL, /* 136: personality */ NULL, /* 137: afs_syscall */ lx_setfsuid16, /* 138: setfsuid16 */ lx_setfsgid16, /* 139: setfsgid16 */ diff --git a/usr/src/lib/brand/lx/lx_brand/common/mem.c b/usr/src/lib/brand/lx/lx_brand/common/mem.c index c84a07d76d..234348753f 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/mem.c +++ b/usr/src/lib/brand/lx/lx_brand/common/mem.c @@ -139,9 +139,20 @@ mmap_common(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, * show that segments mmap'd from userland (such as libraries mapped in * by the dynamic linker) all have exec the permission set, even for * data segments. + * + * This insanity is tempered by the fact that the behavior is disabled + * for ELF binaries bearing a PT_GNU_STACK header which lacks PF_X + * (which most do). Such a header will clear the READ_IMPLIES_EXEC + * flag from the process personality. */ - if (prot & PROT_READ) - prot |= PROT_EXEC; + if (prot & PROT_READ) { + unsigned int personality; + + personality = syscall(SYS_brand, B_GET_PERSONALITY); + if ((personality & LX_PER_READ_IMPLIES_EXEC) != 0) { + prot |= PROT_EXEC; + } + } ret = mmap64(addr, len, prot, ltos_mmap_flags(flags), fd, off); diff --git a/usr/src/lib/brand/lx/lx_brand/common/misc.c b/usr/src/lib/brand/lx/lx_brand/common/misc.c index ed4f812973..5fd637babe 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/misc.c +++ b/usr/src/lib/brand/lx/lx_brand/common/misc.c @@ -304,61 +304,6 @@ lx_setgroups16(uintptr_t p1, uintptr_t p2) } /* - * personality(). We don't really support Linux personalities, but we have to - * emulate enough (or ahem, lie) to show that we support the basic personality. - * We also allow certain (relatively) harmless bits of the personality to be - * "set" -- keeping track of whatever lie we're telling so we don't get caught - * out too easily. - */ -#define LX_PER_LINUX 0x0 -#define LX_PER_MASK 0xff - -/* - * These are for what Linux calls "bug emulation". - */ -#define LX_PER_UNAME26 0x0020000 -#define LX_PER_ADDR_NO_RANDOMIZE 0x0040000 -#define LX_PER_FDPIC_FUNCPTRS 0x0080000 -#define LX_PER_MMAP_PAGE_ZERO 0x0100000 -#define LX_PER_ADDR_COMPAT_LAYOUT 0x0200000 -#define LX_PER_READ_IMPLIES_EXEC 0x0400000 -#define LX_PER_ADDR_LIMIT_32BIT 0x0800000 -#define LX_PER_SHORT_INODE 0x1000000 -#define LX_PER_WHOLE_SECONDS 0x2000000 -#define LX_PER_STICKY_TIMEOUTS 0x4000000 -#define LX_PER_ADDR_LIMIT_3GB 0x8000000 - -long -lx_personality(uintptr_t p1) -{ - static int current = LX_PER_LINUX; - int per = (int)p1; - - switch (per) { - case -1: - /* Request current personality */ - return (current); - case LX_PER_LINUX: - current = per; - return (0); - default: - if (per & LX_PER_MASK) - return (-EINVAL); - - /* - * We allow a subset of the legacy emulation personality - * attributes to be "turned on" -- which we put in quotes - * because we don't actually change our behavior based on - * them. (Note that we silently ignore the others.) - */ - current = per & (LX_PER_ADDR_LIMIT_3GB | - LX_PER_ADDR_NO_RANDOMIZE | LX_PER_ADDR_COMPAT_LAYOUT); - - return (0); - } -} - -/* * mknod() - Since we don't have the SYS_CONFIG privilege within a zone, the * only mode we have to support is S_IFIFO. We also have to distinguish between * an invalid type and insufficient privileges. diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h index 312e040059..5c9c0d9d7f 100644 --- a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h @@ -148,7 +148,6 @@ extern long lx_reboot(uintptr_t, uintptr_t, uintptr_t, uintptr_t); extern long lx_getgroups16(uintptr_t, uintptr_t); extern long lx_setgroups(uintptr_t, uintptr_t); extern long lx_setgroups16(uintptr_t, uintptr_t); -extern long lx_personality(uintptr_t); extern long lx_query_module(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); diff --git a/usr/src/uts/common/brand/lx/os/lx_brand.c b/usr/src/uts/common/brand/lx/os/lx_brand.c index aed3585f55..bd41ad80d5 100644 --- a/usr/src/uts/common/brand/lx/os/lx_brand.c +++ b/usr/src/uts/common/brand/lx/os/lx_brand.c @@ -1834,6 +1834,16 @@ lx_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, return (EINVAL); } + case B_GET_PERSONALITY: { + unsigned int result; + + mutex_enter(&p->p_lock); + pd = ptolxproc(p); + result = pd->l_personality; + mutex_exit(&p->p_lock); + return (result); + } + } return (EINVAL); @@ -1984,26 +1994,26 @@ lx_elfexec(struct vnode *vp, struct execa *uap, struct uarg *args, struct intpdata *idata, int level, long *execsz, int setid, caddr_t exec_file, struct cred *cred, int *brand_action) { - int error; + int error, i; vnode_t *nvp; Ehdr ehdr; Addr uphdr_vaddr; intptr_t voffset; char *interp = NULL; uintptr_t ldaddr = NULL; - int i; proc_t *p = ttoproc(curthread); klwp_t *lwp = ttolwp(curthread); - struct execenv env; - struct execenv origenv; + lx_proc_data_t *lxpd = ptolxproc(p); + struct execenv env, origenv; stack_t orig_sigaltstack; struct user *up = PTOU(ttoproc(curthread)); lx_elf_data_t edp; char *lib_path = LX_LIB_PATH; boolean_t execstk = B_TRUE; + unsigned int personality; - ASSERT(ttoproc(curthread)->p_brand == &lx_brand); - ASSERT(ttoproc(curthread)->p_brand_data != NULL); + ASSERT(p->p_brand == &lx_brand); + ASSERT(lxpd != NULL); /* * Start with a separate struct for ELF data instead of inheriting @@ -2103,12 +2113,19 @@ lx_elfexec(struct vnode *vp, struct execa *uap, struct uarg *args, #endif /* + * Revert the base personality while maintaining any existing flags. + */ + personality = LX_PER_LINUX | (lxpd->l_personality & ~LX_PER_MASK); + + /* * Linux defaults to an executable stack unless the aformentioned - * PT_GNU_STACK entry in the elf header dictates otherwise. + * PT_GNU_STACK entry in the elf header dictates otherwise. Enabling + * the READ_IMPLIES_EXEC personality flag is also implied in this case. */ if (execstk) { args->stk_prot |= PROT_EXEC; args->stk_prot_override = B_TRUE; + personality |= LX_PER_READ_IMPLIES_EXEC; } /* @@ -2420,9 +2437,11 @@ lx_elfexec(struct vnode *vp, struct execa *uap, struct uarg *args, } /* - * Record the brand ELF data now that the exec is a success. + * Record the brand ELF data and new personality now that the exec has + * proceeded successfully. */ - bcopy(&edp, &ttolxproc(curthread)->l_elf_data, sizeof (edp)); + bcopy(&edp, &lxpd->l_elf_data, sizeof (edp)); + lxpd->l_personality = personality; return (0); } diff --git a/usr/src/uts/common/brand/lx/os/lx_syscall.c b/usr/src/uts/common/brand/lx/os/lx_syscall.c index 1423ca15aa..5e0f03cc5c 100644 --- a/usr/src/uts/common/brand/lx/os/lx_syscall.c +++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c @@ -752,7 +752,7 @@ lx_sysent_t lx_sysent32[] = { {"fchdir", NULL, 0, 1}, /* 133 */ {"bdflush", NULL, NOSYS_KERNEL, 0}, /* 134 */ {"sysfs", NULL, 0, 3}, /* 135 */ - {"personality", NULL, 0, 1}, /* 136 */ + {"personality", lx_personality, 0, 1}, /* 136 */ {"afs_syscall", NULL, NOSYS_KERNEL, 0}, /* 137 */ {"setfsuid16", NULL, 0, 1}, /* 138 */ {"setfsgid16", NULL, 0, 1}, /* 139 */ @@ -1122,7 +1122,7 @@ lx_sysent_t lx_sysent64[] = { {"utime", NULL, 0, 2}, /* 132 */ {"mknod", NULL, 0, 3}, /* 133 */ {"uselib", NULL, NOSYS_KERNEL, 0}, /* 134 */ - {"personality", NULL, 0, 1}, /* 135 */ + {"personality", lx_personality, 0, 1}, /* 135 */ {"ustat", NULL, NOSYS_OBSOLETE, 2}, /* 136 */ {"statfs", NULL, 0, 2}, /* 137 */ {"fstatfs", NULL, 0, 2}, /* 138 */ diff --git a/usr/src/uts/common/brand/lx/procfs/lx_proc.h b/usr/src/uts/common/brand/lx/procfs/lx_proc.h index cd4d440450..471d7c0fdd 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_proc.h +++ b/usr/src/uts/common/brand/lx/procfs/lx_proc.h @@ -123,6 +123,7 @@ typedef enum lxpr_nodetype { LXPR_PID_MEM, /* /proc/<pid>/mem */ LXPR_PID_MOUNTINFO, /* /proc/<pid>/mountinfo */ LXPR_PID_OOM_SCR_ADJ, /* /proc/<pid>/oom_score_adj */ + LXPR_PID_PERSONALITY, /* /proc/<pid>/personality */ LXPR_PID_ROOTDIR, /* /proc/<pid>/root */ LXPR_PID_STAT, /* /proc/<pid>/stat */ LXPR_PID_STATM, /* /proc/<pid>/statm */ @@ -144,6 +145,7 @@ typedef enum lxpr_nodetype { LXPR_PID_TID_MEM, /* /proc/<pid>/task/<tid>/mem */ LXPR_PID_TID_MOUNTINFO, /* /proc/<pid>/task/<tid>/mountinfo */ LXPR_PID_TID_OOM_SCR_ADJ, /* /proc/<pid>/task/<tid>/oom_score_adj */ + LXPR_PID_TID_PERSONALITY, /* /proc/<pid>/task/<tid>/personality */ LXPR_PID_TID_ROOTDIR, /* /proc/<pid>/task/<tid>/root */ LXPR_PID_TID_STAT, /* /proc/<pid>/task/<tid>/stat */ LXPR_PID_TID_STATM, /* /proc/<pid>/task/<tid>/statm */ diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c index 106c75e532..2040aadade 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c +++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c @@ -177,6 +177,7 @@ static void lxpr_read_pid_limits(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_pid_maps(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_pid_mountinfo(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_pid_oom_scr_adj(lxpr_node_t *, lxpr_uiobuf_t *); +static void lxpr_read_pid_personality(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_pid_stat(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_pid_statm(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_pid_status(lxpr_node_t *, lxpr_uiobuf_t *); @@ -332,6 +333,7 @@ static lxpr_dirent_t piddir[] = { { LXPR_PID_MEM, "mem" }, { LXPR_PID_MOUNTINFO, "mountinfo" }, { LXPR_PID_OOM_SCR_ADJ, "oom_score_adj" }, + { LXPR_PID_PERSONALITY, "personality" }, { LXPR_PID_ROOTDIR, "root" }, { LXPR_PID_STAT, "stat" }, { LXPR_PID_STATM, "statm" }, @@ -359,6 +361,7 @@ static lxpr_dirent_t tiddir[] = { { LXPR_PID_MEM, "mem" }, { LXPR_PID_MOUNTINFO, "mountinfo" }, { LXPR_PID_TID_OOM_SCR_ADJ, "oom_score_adj" }, + { LXPR_PID_PERSONALITY, "personality" }, { LXPR_PID_ROOTDIR, "root" }, { LXPR_PID_TID_STAT, "stat" }, { LXPR_PID_STATM, "statm" }, @@ -633,6 +636,7 @@ static void (*lxpr_read_function[LXPR_NFILES])() = { lxpr_read_empty, /* /proc/<pid>/mem */ lxpr_read_pid_mountinfo, /* /proc/<pid>/mountinfo */ lxpr_read_pid_oom_scr_adj, /* /proc/<pid>/oom_score_adj */ + lxpr_read_pid_personality, /* /proc/<pid>/personality */ lxpr_read_invalid, /* /proc/<pid>/root */ lxpr_read_pid_stat, /* /proc/<pid>/stat */ lxpr_read_pid_statm, /* /proc/<pid>/statm */ @@ -654,6 +658,7 @@ static void (*lxpr_read_function[LXPR_NFILES])() = { lxpr_read_empty, /* /proc/<pid>/task/<tid>/mem */ lxpr_read_pid_mountinfo, /* /proc/<pid>/task/<tid>/mountinfo */ lxpr_read_pid_oom_scr_adj, /* /proc/<pid>/task/<tid>/oom_scr_adj */ + lxpr_read_pid_personality, /* /proc/<pid>/task/<tid>/personality */ lxpr_read_invalid, /* /proc/<pid>/task/<tid>/root */ lxpr_read_pid_tid_stat, /* /proc/<pid>/task/<tid>/stat */ lxpr_read_pid_statm, /* /proc/<pid>/task/<tid>/statm */ @@ -755,6 +760,7 @@ static vnode_t *(*lxpr_lookup_function[LXPR_NFILES])() = { lxpr_lookup_not_a_dir, /* /proc/<pid>/mem */ lxpr_lookup_not_a_dir, /* /proc/<pid>/mountinfo */ lxpr_lookup_not_a_dir, /* /proc/<pid>/oom_score_adj */ + lxpr_lookup_not_a_dir, /* /proc/<pid>/personality */ lxpr_lookup_not_a_dir, /* /proc/<pid>/root */ lxpr_lookup_not_a_dir, /* /proc/<pid>/stat */ lxpr_lookup_not_a_dir, /* /proc/<pid>/statm */ @@ -776,6 +782,7 @@ static vnode_t *(*lxpr_lookup_function[LXPR_NFILES])() = { lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/mem */ lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/mountinfo */ lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/oom_scr_adj */ + lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/personality */ lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/root */ lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/stat */ lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/statm */ @@ -877,6 +884,7 @@ static int (*lxpr_readdir_function[LXPR_NFILES])() = { lxpr_readdir_not_a_dir, /* /proc/<pid>/mem */ lxpr_readdir_not_a_dir, /* /proc/<pid>/mountinfo */ lxpr_readdir_not_a_dir, /* /proc/<pid>/oom_score_adj */ + lxpr_readdir_not_a_dir, /* /proc/<pid>/personality */ lxpr_readdir_not_a_dir, /* /proc/<pid>/root */ lxpr_readdir_not_a_dir, /* /proc/<pid>/stat */ lxpr_readdir_not_a_dir, /* /proc/<pid>/statm */ @@ -898,6 +906,7 @@ static int (*lxpr_readdir_function[LXPR_NFILES])() = { lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/mem */ lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/mountinfo */ lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid/oom_scr_adj */ + lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid/personality */ lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/root */ lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/stat */ lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/statm */ @@ -1816,6 +1825,33 @@ lxpr_read_pid_oom_scr_adj(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) lxpr_uiobuf_printf(uiobuf, "0\n"); } +/* + * lxpr_read_pid_personality(): read personality for process + */ +static void +lxpr_read_pid_personality(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) +{ + proc_t *p; + lx_proc_data_t *lxpd; + unsigned int personality; + + ASSERT(lxpnp->lxpr_type == LXPR_PID_PERSONALITY); + + p = lxpr_lock(lxpnp->lxpr_pid, ZOMB_OK); + if (p == NULL) { + lxpr_uiobuf_seterr(uiobuf, EINVAL); + return; + } + if ((lxpd = ptolxproc(p)) != NULL) { + personality = lxpd->l_personality; + } else { + /* Report native processes as having the SunOS personality */ + personality = LX_PER_SUNOS; + } + lxpr_unlock(p); + + lxpr_uiobuf_printf(uiobuf, "%08x\n", personality); +} /* * lxpr_read_pid_statm(): memory status file diff --git a/usr/src/uts/common/brand/lx/sys/lx_brand.h b/usr/src/uts/common/brand/lx/sys/lx_brand.h index 01d47458c3..a7d87f70d8 100644 --- a/usr/src/uts/common/brand/lx/sys/lx_brand.h +++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h @@ -104,6 +104,7 @@ extern "C" { #define B_SIGEV_THREAD_ID 148 #define B_OVERRIDE_KERN_VER 149 #define B_NOTIFY_VDSO_LOC 150 +#define B_GET_PERSONALITY 151 #ifndef _ASM /* @@ -310,11 +311,33 @@ typedef struct lx_proc_data { /* Override zone-wide settings for uname release and version */ char l_uname_release[LX_KERN_RELEASE_MAX]; char l_uname_version[LX_KERN_VERSION_MAX]; + + /* Linux process personality */ + unsigned int l_personality; } lx_proc_data_t; #endif /* _KERNEL */ /* + * Linux process personality(2) flags stored in l_personality + */ +#define LX_PER_UNAME26 0x0020000 +#define LX_PER_ADDR_NO_RANDOMIZE 0x0040000 +#define LX_PER_FDPIC_FUNCPTRS 0x0080000 +#define LX_PER_MMAP_PAGE_ZERO 0x0100000 +#define LX_PER_ADDR_COMPAT_LAYOUT 0x0200000 +#define LX_PER_READ_IMPLIES_EXEC 0x0400000 +#define LX_PER_ADDR_LIMIT_32BIT 0x0800000 +#define LX_PER_SHORT_INODE 0x1000000 +#define LX_PER_WHOLE_SECONDS 0x2000000 +#define LX_PER_STICKY_TIMEOUTS 0x4000000 +#define LX_PER_ADDR_LIMIT_3GB 0x8000000 + +#define LX_PER_LINUX 0x00 +#define LX_PER_SUNOS (0x06 | LX_PER_STICKY_TIMEOUTS) +#define LX_PER_MASK 0xff + +/* * A data type big enough to bitmap all Linux possible cpus. * The bitmap size is defined as 1024 cpus in the Linux 2.4 and 2.6 man pages * for sched_getaffinity() and sched_getaffinity(). diff --git a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h index 60ad1e7ef4..f932c70bb9 100644 --- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h +++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h @@ -104,6 +104,7 @@ extern long lx_nanosleep(); extern long lx_oldgetrlimit(); extern long lx_open(); extern long lx_openat(); +extern long lx_personality(); extern long lx_pipe(); extern long lx_pipe2(); extern long lx_poll(); diff --git a/usr/src/uts/common/brand/lx/syscall/lx_personality.c b/usr/src/uts/common/brand/lx/syscall/lx_personality.c new file mode 100644 index 0000000000..e7aa945b50 --- /dev/null +++ b/usr/src/uts/common/brand/lx/syscall/lx_personality.c @@ -0,0 +1,112 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2016 Joyent, Inc. + */ + +#include <sys/systm.h> +#include <sys/mutex.h> +#include <sys/brand.h> + +#include <sys/lx_brand.h> +#include <sys/lx_impl.h> + + +/* + * These flags are for what Linux calls "bug emulation". + * (Descriptions from the personality(2) Linux man page.) + * + * Flags which are currently actionable in LX: + * - READ_IMPLIES_EXEC (since Linux 2.6.8) + * With this flag set, PROT_READ implies PROT_EXEC for mmap(2). + * + * Flags which are current accepted but ignored: + * - UNAME26 (since Linux 3.1) + * Have uname(2) report a 2.6.40+ version number rather than a 3.x version + * number. Added as a stopgap measure to support broken applications that + * could not handle the kernel version- numbering switch from 2.6.x to 3.x. + * + * - ADDR_NO_RANDOMIZE (since Linux 2.6.12) + * With this flag set, disable address-space-layout randomization. + * + * - FDPIC_FUNCPTRS (since Linux 2.6.11) + * User-space function pointers to signal handlers point (on certain + * architectures) to descriptors. + * + * - MMAP_PAGE_ZERO (since Linux 2.4.0) + * Map page 0 as read-only (to support binaries that depend on this SVr4 + * behavior). + * + * - ADDR_COMPAT_LAYOUT (since Linux 2.6.9) + * With this flag set, provide legacy virtual address space layout. + * + * - ADDR_LIMIT_32BIT (since Linux 2.2) + * Limit the address space to 32 bits. + * + * - SHORT_INODE (since Linux 2.4.0) + * No effects(?). + * + * - WHOLE_SECONDS (since Linux 1.2.0) + * No effects(?). + * + * - STICKY_TIMEOUTS (since Linux 1.2.0) + * With this flag set, select(2), pselect(2), and ppoll(2) do not modify the + * returned timeout argument when interrupted by a signal handler. + * + * - ADDR_LIMIT_3GB (since Linux 2.4.0) + * With this flag set, use 0xc0000000 as the offset at which to search a + * virtual memory chunk on mmap(2); otherwise use 0xffffe000. + */ + +#define LX_PER_GET 0xffffffff + +long +lx_personality(unsigned int arg) +{ + lx_proc_data_t *lxpd = ptolxproc(curproc); + unsigned int result = 0; + + mutex_enter(&curproc->p_lock); + result = lxpd->l_personality; + + if (arg == LX_PER_GET) { + mutex_exit(&curproc->p_lock); + return (result); + } + + /* + * Prevent changes to the personality if the process is undergoing an + * exec. This will allow elfexec and friends to manipulate the + * personality without hinderance. + */ + if ((curproc->p_flag & P_PR_EXEC) != 0) { + mutex_exit(&curproc->p_lock); + return (set_errno(EINVAL)); + } + + /* + * Keep tabs when a non-Linux personality is set. This is silently + * allowed to succeed, even though the emulation required is almost + * certainly missing. + */ + if ((arg & LX_PER_MASK) != LX_PER_LINUX) { + char buf[64]; + + (void) snprintf(buf, sizeof (buf), "invalid personality: %02X", + arg & LX_PER_MASK); + lx_unsupported(buf); + } + + lxpd->l_personality = arg; + mutex_exit(&curproc->p_lock); + return (result); +} diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files index b730774ac7..430445e3c5 100644 --- a/usr/src/uts/intel/Makefile.files +++ b/usr/src/uts/intel/Makefile.files @@ -317,6 +317,7 @@ LX_BRAND_OBJS = \ lx_mkdir.o \ lx_modify_ldt.o \ lx_open.o \ + lx_personality.o \ lx_pid.o \ lx_pipe.o \ lx_poll.o \ |
