diff options
author | Dillon Amburgey <dillona@dillona.com> | 2017-01-17 21:53:22 -0500 |
---|---|---|
committer | Trent Mick <trentm@gmail.com> | 2017-01-17 21:53:22 -0500 |
commit | aec067a881847c338981aa717b8f42fb35c3b849 (patch) | |
tree | f2dc8823c5dc50b25752c4549fedd395eeb43e24 | |
parent | 5ddda660b6ddd28eef7e27c16d4a6fed11998f03 (diff) | |
download | illumos-joyent-cr1193-OS-5879.tar.gz |
OS-5879 lxbrand should expose ASLR via sysctlcr1193-OS-5879
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_brand.c | 78 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_proc.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_prvnops.c | 88 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_brand.h | 2 |
4 files changed, 169 insertions, 0 deletions
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 839ff9219a..8ff5545c06 100644 --- a/usr/src/uts/common/brand/lx/os/lx_brand.c +++ b/usr/src/uts/common/brand/lx/os/lx_brand.c @@ -176,6 +176,7 @@ #include <sys/zfs_ioctl.h> #include <inet/tcp_impl.h> #include <inet/udp_impl.h> +#include <sys/secflags.h> int lx_debug = 0; @@ -391,6 +392,14 @@ lx_setattr(zone_t *zone, int attr, void *ubuf, size_t ubufsz) (void) strlcpy(lxzd->lxzd_kernel_release, buf, LX_KERN_RELEASE_MAX); mutex_exit(&lxzd->lxzd_lock); + + /* Linux ASLR level 2 has been the default since 2.6.25 */ + if (lx_kern_release_cmp(zone, "2.6.25") < 0) { + lx_set_zone_aslr(zone, B_FALSE); + } else { + lx_set_zone_aslr(zone, B_TRUE); + } + return (0); } case LX_ATTR_KERN_VERSION: { @@ -1801,6 +1810,75 @@ lx_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, return (EINVAL); } +void +lx_set_zone_aslr(zone_t *zone, boolean_t enable) +{ + secflagdelta_t sfd; + proc_t *p; + boolean_t zone_aslr_enabled; + + ASSERT(zone != NULL); + ASSERT(zone->zone_brand == &lx_brand); + + mutex_enter(&zone->zone_lock); + zone_aslr_enabled = secflag_isset(zone->zone_secflags.psf_effective, + PROC_SEC_ASLR); + + bzero(&sfd, sizeof (sfd)); + + if (enable) { + /* Don't do anything if ASLR is already on */ + if (zone_aslr_enabled) { + mutex_exit(&zone->zone_lock); + return; + } + + secflag_set(&sfd.psd_add, PROC_SEC_ASLR); + } else { + /* Don't do anything if ASLR is already off */ + if (!zone_aslr_enabled) { + mutex_exit(&zone->zone_lock); + return; + } + + secflag_set(&sfd.psd_rem, PROC_SEC_ASLR); + } + + /* Walk all active processes in the zone */ + mutex_enter(&pidlock); + for (p = practive; p != NULL; p = p->p_next) { + /* skip kernel processes */ + if (p->p_exec == NULLVP || p->p_as == &kas || + (p->p_flag & SSYS)) + continue; + /* + * Only processes in the given zone + * are taken into account + */ + if (p->p_zone->zone_id == zone->zone_id) { + mutex_enter(&p->p_lock); + secflags_apply_delta( + &p->p_secflags.psf_effective, + &sfd); + secflags_apply_delta(&p->p_secflags.psf_inherit, + &sfd); + mutex_exit(&p->p_lock); + } + } + mutex_exit(&pidlock); + + /* + * There isn't a functional reason to replace these + * because secflags work through strict inheritance. + * When the zone is already running, this has no effect. + * Do it anyway to serve as a clear marker of whether ASLR is + * enabled or disabled. + */ + secflags_apply_delta(&zone->zone_secflags.psf_effective, &sfd); + secflags_apply_delta(&zone->zone_secflags.psf_inherit, &sfd); + mutex_exit(&zone->zone_lock); +} + /* * Compare linux kernel version to the one set for the zone. * Returns greater than 0 if zone version is higher, less than 0 if the zone 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 67988e4aab..ebf5fd4021 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_proc.h +++ b/usr/src/uts/common/brand/lx/procfs/lx_proc.h @@ -214,6 +214,7 @@ typedef enum lxpr_nodetype { LXPR_SYS_KERNEL_PID_MAX, /* /proc/sys/kernel/pid_max */ LXPR_SYS_KERNEL_RANDDIR, /* /proc/sys/kernel/random */ LXPR_SYS_KERNEL_RAND_BOOTID, /* /proc/sys/kernel/random/boot_id */ + LXPR_SYS_KERNEL_RAND_VASPACE, /* /proc/sys/kernel/randomize_va_space */ LXPR_SYS_KERNEL_SEM, /* /proc/sys/kernel/sem */ LXPR_SYS_KERNEL_SHMALL, /* /proc/sys/kernel/shmall */ LXPR_SYS_KERNEL_SHMMAX, /* /proc/sys/kernel/shmmax */ 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 5586ed05ad..b4dbd94d75 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c +++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c @@ -79,6 +79,7 @@ #include <inet/ipclassifier.h> #include <sys/socketvar.h> #include <fs/sockfs/socktpi.h> +#include <sys/secflags.h> /* Dependent on procfs */ extern kthread_t *prchoose(proc_t *); @@ -230,6 +231,7 @@ static void lxpr_read_sys_kernel_ngroups_max(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_osrel(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_pid_max(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_rand_bootid(lxpr_node_t *, lxpr_uiobuf_t *); +static void lxpr_read_sys_kernel_rand_vaspace(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_sem(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_shmall(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_shmmax(lxpr_node_t *, lxpr_uiobuf_t *); @@ -274,6 +276,8 @@ static int lxpr_write_sys_net_ipv4_tcp_winscale(lxpr_node_t *, uio_t *, cred_t *, caller_context_t *); static int lxpr_write_sys_kernel_corepatt(lxpr_node_t *, uio_t *, cred_t *, caller_context_t *); +static int lxpr_write_sys_kernel_rand_vaspace(lxpr_node_t *, uio_t *, cred_t *, + caller_context_t *); /* * Simple conversion @@ -523,6 +527,7 @@ static lxpr_dirent_t sys_kerneldir[] = { { LXPR_SYS_KERNEL_OSREL, "osrelease" }, { LXPR_SYS_KERNEL_PID_MAX, "pid_max" }, { LXPR_SYS_KERNEL_RANDDIR, "random" }, + { LXPR_SYS_KERNEL_RAND_VASPACE, "randomize_va_space" }, { LXPR_SYS_KERNEL_SEM, "sem" }, { LXPR_SYS_KERNEL_SHMALL, "shmall" }, { LXPR_SYS_KERNEL_SHMMAX, "shmmax" }, @@ -615,6 +620,7 @@ static wftab_t wr_tab[] = { {LXPR_PID_TID_OOM_SCR_ADJ, NULL}, {LXPR_SYS_FS_FILEMAX, NULL}, {LXPR_SYS_KERNEL_COREPATT, lxpr_write_sys_kernel_corepatt}, + {LXPR_SYS_KERNEL_RAND_VASPACE, lxpr_write_sys_kernel_rand_vaspace}, {LXPR_SYS_KERNEL_SHMALL, NULL}, {LXPR_SYS_KERNEL_SHMMAX, NULL}, {LXPR_SYS_NET_CORE_SOMAXCON, lxpr_write_sys_net_core_somaxc}, @@ -839,6 +845,7 @@ static void (*lxpr_read_function[LXPR_NFILES])() = { lxpr_read_sys_kernel_pid_max, /* /proc/sys/kernel/pid_max */ lxpr_read_invalid, /* /proc/sys/kernel/random */ lxpr_read_sys_kernel_rand_bootid, /* /proc/sys/kernel/random/boot_id */ + lxpr_read_sys_kernel_rand_vaspace, /* .../kernel/randomize_va_space */ lxpr_read_sys_kernel_sem, /* /proc/sys/kernel/sem */ lxpr_read_sys_kernel_shmall, /* /proc/sys/kernel/shmall */ lxpr_read_sys_kernel_shmmax, /* /proc/sys/kernel/shmmax */ @@ -979,6 +986,7 @@ static vnode_t *(*lxpr_lookup_function[LXPR_NFILES])() = { lxpr_lookup_not_a_dir, /* /proc/sys/kernel/pid_max */ lxpr_lookup_sys_kdir_randdir, /* /proc/sys/kernel/random */ lxpr_lookup_not_a_dir, /* /proc/sys/kernel/random/boot_id */ + lxpr_lookup_not_a_dir, /* .../kernel/randomize_va_space */ lxpr_lookup_not_a_dir, /* /proc/sys/kernel/sem */ lxpr_lookup_not_a_dir, /* /proc/sys/kernel/shmall */ lxpr_lookup_not_a_dir, /* /proc/sys/kernel/shmmax */ @@ -1119,6 +1127,7 @@ static int (*lxpr_readdir_function[LXPR_NFILES])() = { lxpr_readdir_not_a_dir, /* /proc/sys/kernel/pid_max */ lxpr_readdir_sys_kdir_randdir, /* /proc/sys/kernel/random */ lxpr_readdir_not_a_dir, /* /proc/sys/kernel/random/boot_id */ + lxpr_readdir_not_a_dir, /* .../kernel/randomize_va_space */ lxpr_readdir_not_a_dir, /* /proc/sys/kernel/sem */ lxpr_readdir_not_a_dir, /* /proc/sys/kernel/shmall */ lxpr_readdir_not_a_dir, /* /proc/sys/kernel/shmmax */ @@ -4468,6 +4477,28 @@ lxpr_read_sys_kernel_rand_bootid(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) lxpr_uiobuf_printf(uiobuf, "%s\n", bootid); } +static void +lxpr_read_sys_kernel_rand_vaspace(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) +{ + zone_t *zone = LXPTOZ(lxpnp); + boolean_t zone_aslr_enabled; + + ASSERT(lxpnp->lxpr_type == LXPR_SYS_KERNEL_RAND_VASPACE); + ASSERT(zone != NULL); + ASSERT(zone->zone_brand == &lx_brand); + + mutex_enter(&zone->zone_lock); + zone_aslr_enabled = secflag_isset(zone->zone_secflags.psf_effective, + PROC_SEC_ASLR); + mutex_exit(&zone->zone_lock); + + if (zone_aslr_enabled) { + lxpr_uiobuf_printf(uiobuf, "%d\n", 2); + } else { + lxpr_uiobuf_printf(uiobuf, "%d\n", 0); + } +} + /* ARGSUSED */ static void lxpr_read_sys_kernel_sem(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) @@ -7087,6 +7118,63 @@ lxpr_write_sys_kernel_corepatt(lxpr_node_t *lxpnp, struct uio *uio, /* ARGSUSED */ static int +lxpr_write_sys_kernel_rand_vaspace(lxpr_node_t *lxpnp, struct uio *uio, + struct cred *cr, caller_context_t *ct) +{ + zone_t *zone = LXPTOZ(lxpnp); + char val[3]; + size_t olen; + int error; + + ASSERT(lxpnp->lxpr_type == LXPR_SYS_KERNEL_RAND_VASPACE); + + if (uio->uio_loffset != 0) + return (EINVAL); + + if (uio->uio_resid == 0) + return (0); + + olen = uio->uio_resid; + if (olen > sizeof (val) - 1) + return (EINVAL); + + bzero(val, sizeof (val)); + error = uiomove(val, olen, UIO_WRITE, uio); + if (error != 0) + return (error); + + if (val[olen - 1] == '\n') + val[olen - 1] = '\0'; + + switch (val[0]) { + case '0': + lx_set_zone_aslr(zone, B_FALSE); + + break; + case '1': + /* + * Linux distinguishes between (1) "conservative" and + * (2) "full" ASLR. Illumos does not have the same distinction. + */ + /* FALLTHROUGH */ + case '2': + lx_set_zone_aslr(zone, B_TRUE); + + break; + default: + /* + * Linux actually accepts any signed 32-bit value. + * All non-zero values are considered to mean ASLR is enabled. + * However we're just supporting the current documented values. + */ + return (EINVAL); + } + + return (0); +} + +/* ARGSUSED */ +static int lxpr_write_pid_loginuid(lxpr_node_t *lxpnp, struct uio *uio, struct cred *cr, caller_context_t *ct) { 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 147e8961f2..a8bbc5b369 100644 --- a/usr/src/uts/common/brand/lx/sys/lx_brand.h +++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h @@ -661,6 +661,8 @@ typedef struct lx_virt_disk { extern int lx_kern_release_cmp(zone_t *, const char *); +extern void lx_set_zone_aslr(zone_t *, boolean_t); + extern void lx_lwp_set_native_stack_current(lx_lwp_data_t *, uintptr_t); extern void lx_divert(klwp_t *, uintptr_t); extern int lx_runexe(klwp_t *, void *); |