summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDillon Amburgey <dillona@dillona.com>2017-01-17 21:53:22 -0500
committerTrent Mick <trentm@gmail.com>2017-01-17 21:53:22 -0500
commitaec067a881847c338981aa717b8f42fb35c3b849 (patch)
treef2dc8823c5dc50b25752c4549fedd395eeb43e24
parent5ddda660b6ddd28eef7e27c16d4a6fed11998f03 (diff)
downloadillumos-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.c78
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_proc.h1
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_prvnops.c88
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_brand.h2
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 *);