View | Details | Raw Unified | Return to bug 208580 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/amd64/amd64/elf_machdep.c (-1 / +2 lines)
Lines 72-78 struct sysentvec elf64_freebsd_sysvec = { Link Here
72
	.sv_setregs	= exec_setregs,
72
	.sv_setregs	= exec_setregs,
73
	.sv_fixlimit	= NULL,
73
	.sv_fixlimit	= NULL,
74
	.sv_maxssiz	= NULL,
74
	.sv_maxssiz	= NULL,
75
	.sv_flags	= SV_ABI_FREEBSD | SV_LP64 | SV_SHP | SV_TIMEKEEP,
75
	.sv_flags	= SV_ABI_FREEBSD | SV_LP64 | SV_SHP | SV_TIMEKEEP |
76
			    SV_ASLR,
76
	.sv_set_syscall_retval = cpu_set_syscall_retval,
77
	.sv_set_syscall_retval = cpu_set_syscall_retval,
77
	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
78
	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
78
	.sv_syscallnames = syscallnames,
79
	.sv_syscallnames = syscallnames,
(-)b/sys/arm/arm/elf_machdep.c (-1 / +1 lines)
Lines 76-82 struct sysentvec elf32_freebsd_sysvec = { Link Here
76
	.sv_maxssiz	= NULL,
76
	.sv_maxssiz	= NULL,
77
	.sv_flags	=
77
	.sv_flags	=
78
#if __ARM_ARCH >= 6
78
#if __ARM_ARCH >= 6
79
			  SV_SHP | SV_TIMEKEEP |
79
			  SV_SHP | SV_TIMEKEEP | SV_ASLR |
80
#endif
80
#endif
81
			  SV_ABI_FREEBSD | SV_ILP32,
81
			  SV_ABI_FREEBSD | SV_ILP32,
82
	.sv_set_syscall_retval = cpu_set_syscall_retval,
82
	.sv_set_syscall_retval = cpu_set_syscall_retval,
(-)b/sys/compat/freebsd32/freebsd32_misc.c (+3 lines)
Lines 3039-3044 freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap) Link Here
3039
	switch (uap->com) {
3039
	switch (uap->com) {
3040
	case PROC_SPROTECT:
3040
	case PROC_SPROTECT:
3041
	case PROC_TRACE_CTL:
3041
	case PROC_TRACE_CTL:
3042
	case PROC_ASLR_CTL:
3042
		error = copyin(PTRIN(uap->data), &flags, sizeof(flags));
3043
		error = copyin(PTRIN(uap->data), &flags, sizeof(flags));
3043
		if (error != 0)
3044
		if (error != 0)
3044
			return (error);
3045
			return (error);
Lines 3068-3073 freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap) Link Here
3068
		data = &x.rk;
3069
		data = &x.rk;
3069
		break;
3070
		break;
3070
	case PROC_TRACE_STATUS:
3071
	case PROC_TRACE_STATUS:
3072
	case PROC_ASLR_STATUS:
3071
		data = &flags;
3073
		data = &flags;
3072
		break;
3074
		break;
3073
	default:
3075
	default:
Lines 3086-3091 freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap) Link Here
3086
			error = error1;
3088
			error = error1;
3087
		break;
3089
		break;
3088
	case PROC_TRACE_STATUS:
3090
	case PROC_TRACE_STATUS:
3091
	case PROC_ASLR_STATUS:
3089
		if (error == 0)
3092
		if (error == 0)
3090
			error = copyout(&flags, uap->data, sizeof(flags));
3093
			error = copyout(&flags, uap->data, sizeof(flags));
3091
		break;
3094
		break;
(-)b/sys/compat/ia32/ia32_sysvec.c (-4 / +2 lines)
Lines 120-130 struct sysentvec ia32_freebsd_sysvec = { Link Here
120
	.sv_setregs	= ia32_setregs,
120
	.sv_setregs	= ia32_setregs,
121
	.sv_fixlimit	= ia32_fixlimit,
121
	.sv_fixlimit	= ia32_fixlimit,
122
	.sv_maxssiz	= &ia32_maxssiz,
122
	.sv_maxssiz	= &ia32_maxssiz,
123
	.sv_flags	= SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 |
123
	.sv_flags	= SV_ABI_FREEBSD | SV_IA32 | SV_ILP32
124
#ifdef __amd64__
124
#ifdef __amd64__
125
		SV_SHP | SV_TIMEKEEP
125
		| SV_SHP | SV_TIMEKEEP | SV_ASLR
126
#else
127
		0
128
#endif
126
#endif
129
	,
127
	,
130
	.sv_set_syscall_retval = ia32_set_syscall_retval,
128
	.sv_set_syscall_retval = ia32_set_syscall_retval,
(-)b/sys/i386/i386/elf_machdep.c (-1 / +1 lines)
Lines 79-85 struct sysentvec elf32_freebsd_sysvec = { Link Here
79
	.sv_fixlimit	= NULL,
79
	.sv_fixlimit	= NULL,
80
	.sv_maxssiz	= NULL,
80
	.sv_maxssiz	= NULL,
81
	.sv_flags	= SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP |
81
	.sv_flags	= SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP |
82
			    SV_TIMEKEEP,
82
			    SV_TIMEKEEP | SV_ASLR,
83
	.sv_set_syscall_retval = cpu_set_syscall_retval,
83
	.sv_set_syscall_retval = cpu_set_syscall_retval,
84
	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
84
	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
85
	.sv_syscallnames = syscallnames,
85
	.sv_syscallnames = syscallnames,
(-)b/sys/kern/imgact_elf.c (-14 / +88 lines)
Lines 137-142 SYSCTL_INT(_kern_elf32, OID_AUTO, read_exec, CTLFLAG_RW, &i386_read_exec, 0, Link Here
137
#endif
137
#endif
138
#endif
138
#endif
139
139
140
static int __elfN(aslr_enabled) = 1;
141
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
142
    aslr_enabled, CTLFLAG_RWTUN, &__elfN(aslr_enabled), 0,
143
    __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": enable aslr");
144
145
static int __elfN(pie_aslr_enabled) = 1;
146
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
147
    pie_aslr_enabled, CTLFLAG_RWTUN, &__elfN(pie_aslr_enabled), 0,
148
    __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": enable aslr for PIE binaries");
149
150
static int __elfN(aslr_care_sbrk) = 0;
151
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
152
    aslr_care_sbrk, CTLFLAG_RW, &__elfN(aslr_care_sbrk), 0,
153
    __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": assume sbrk is used");
154
140
static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
155
static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
141
156
142
#define	trunc_page_ps(va, ps)	((va) & ~(ps - 1))
157
#define	trunc_page_ps(va, ps)	((va) & ~(ps - 1))
Lines 453-462 __elfN(map_insert)(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
453
			 * The mapping is not page aligned. This means we have
468
			 * The mapping is not page aligned. This means we have
454
			 * to copy the data. Sigh.
469
			 * to copy the data. Sigh.
455
			 */
470
			 */
456
			rv = vm_map_find(map, NULL, 0, &start, end - start, 0,
471
			vm_map_lock(map);
457
			    VMFS_NO_SPACE, prot | VM_PROT_WRITE, VM_PROT_ALL,
472
			rv = vm_map_insert(map, NULL, 0, start, end,
458
			    0);
473
			    prot | VM_PROT_WRITE, VM_PROT_ALL, 0);
459
			if (rv)
474
			vm_map_unlock(map);
475
			if (rv != KERN_SUCCESS)
460
				return (rv);
476
				return (rv);
461
			if (object == NULL)
477
			if (object == NULL)
462
				return (KERN_SUCCESS);
478
				return (KERN_SUCCESS);
Lines 471-479 __elfN(map_insert)(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
471
				error = copyout((caddr_t)sf_buf_kva(sf) + off,
487
				error = copyout((caddr_t)sf_buf_kva(sf) + off,
472
				    (caddr_t)start, sz);
488
				    (caddr_t)start, sz);
473
				vm_imgact_unmap_page(sf);
489
				vm_imgact_unmap_page(sf);
474
				if (error) {
490
				if (error != 0)
475
					return (KERN_FAILURE);
491
					return (KERN_FAILURE);
476
				}
477
				offset += sz;
492
				offset += sz;
478
			}
493
			}
479
			rv = KERN_SUCCESS;
494
			rv = KERN_SUCCESS;
Lines 747-752 fail: Link Here
747
	return (error);
762
	return (error);
748
}
763
}
749
764
765
static u_long
766
__CONCAT(rnd_, __elfN(base))(u_long base, u_long minv, u_long maxv,
767
    u_int align)
768
{
769
	u_long rbase, res;
770
771
	arc4rand(&rbase, sizeof(rbase), 0);
772
	res = base + rbase % (maxv - minv);
773
	res &= ~(align - 1);
774
	return (res);
775
}
776
750
static int
777
static int
751
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
778
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
752
{
779
{
Lines 755-760 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
755
	const Elf_Phdr *phdr;
782
	const Elf_Phdr *phdr;
756
	Elf_Auxargs *elf_auxargs;
783
	Elf_Auxargs *elf_auxargs;
757
	struct vmspace *vmspace;
784
	struct vmspace *vmspace;
785
	vm_map_t map;
758
	const char *err_str, *newinterp;
786
	const char *err_str, *newinterp;
759
	char *interp, *interp_buf, *path;
787
	char *interp, *interp_buf, *path;
760
	Elf_Brandinfo *brand_info;
788
	Elf_Brandinfo *brand_info;
Lines 762-767 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
762
	vm_prot_t prot;
790
	vm_prot_t prot;
763
	u_long text_size, data_size, total_size, text_addr, data_addr;
791
	u_long text_size, data_size, total_size, text_addr, data_addr;
764
	u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr;
792
	u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr;
793
	u_long maxalign, mapsz, maxv;
765
	int32_t osrel;
794
	int32_t osrel;
766
	int error, i, n, interp_name_len, have_interp;
795
	int error, i, n, interp_name_len, have_interp;
767
796
Lines 803-814 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
803
	err_str = newinterp = NULL;
832
	err_str = newinterp = NULL;
804
	interp = interp_buf = NULL;
833
	interp = interp_buf = NULL;
805
	td = curthread;
834
	td = curthread;
835
	maxalign = PAGE_SIZE;
836
	mapsz = 0;
806
837
807
	for (i = 0; i < hdr->e_phnum; i++) {
838
	for (i = 0; i < hdr->e_phnum; i++) {
808
		switch (phdr[i].p_type) {
839
		switch (phdr[i].p_type) {
809
		case PT_LOAD:
840
		case PT_LOAD:
810
			if (n == 0)
841
			if (n == 0)
811
				baddr = phdr[i].p_vaddr;
842
				baddr = phdr[i].p_vaddr;
843
			if (phdr[i].p_align > maxalign)
844
				maxalign = phdr[i].p_align;
845
			mapsz += phdr[i].p_memsz;
812
			n++;
846
			n++;
813
			break;
847
			break;
814
		case PT_INTERP:
848
		case PT_INTERP:
Lines 862-867 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
862
		error = ENOEXEC;
896
		error = ENOEXEC;
863
		goto ret;
897
		goto ret;
864
	}
898
	}
899
	sv = brand_info->sysvec;
900
	et_dyn_addr = 0;
865
	if (hdr->e_type == ET_DYN) {
901
	if (hdr->e_type == ET_DYN) {
866
		if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) {
902
		if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) {
867
			uprintf("Cannot execute shared object\n");
903
			uprintf("Cannot execute shared object\n");
Lines 872-884 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
872
		 * Honour the base load address from the dso if it is
908
		 * Honour the base load address from the dso if it is
873
		 * non-zero for some reason.
909
		 * non-zero for some reason.
874
		 */
910
		 */
875
		if (baddr == 0)
911
		if (baddr == 0) {
876
			et_dyn_addr = ET_DYN_LOAD_ADDR;
912
			if ((sv->sv_flags & SV_ASLR) == 0)
877
		else
913
				et_dyn_addr = ET_DYN_LOAD_ADDR;
878
			et_dyn_addr = 0;
914
			else if ((__elfN(pie_aslr_enabled) &&
879
	} else
915
			    (imgp->proc->p_flag2 & P2_ASLR_DISABLE) == 0) ||
880
		et_dyn_addr = 0;
916
			    (imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0)
881
	sv = brand_info->sysvec;
917
				et_dyn_addr = 1;
918
			else
919
				et_dyn_addr = ET_DYN_LOAD_ADDR;
920
		}
921
	}
882
	if (interp != NULL && brand_info->interp_newpath != NULL)
922
	if (interp != NULL && brand_info->interp_newpath != NULL)
883
		newinterp = brand_info->interp_newpath;
923
		newinterp = brand_info->interp_newpath;
884
924
Lines 897-902 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
897
937
898
	error = exec_new_vmspace(imgp, sv);
938
	error = exec_new_vmspace(imgp, sv);
899
	imgp->proc->p_sysent = sv;
939
	imgp->proc->p_sysent = sv;
940
	vmspace = imgp->proc->p_vmspace;
941
	map = &vmspace->vm_map;
942
943
	if ((sv->sv_flags & SV_ASLR) == 0 ||
944
	    (imgp->proc->p_flag2 & P2_ASLR_DISABLE) != 0) {
945
		KASSERT(et_dyn_addr != 1, ("et_dyn_addr == 1 and !ASLR"));
946
	} else if ((imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0 ||
947
	    (__elfN(aslr_enabled) && hdr->e_type != ET_DYN) ||
948
	    et_dyn_addr == 1) {
949
		vm_map_lock(map);
950
		map->flags |= MAP_ASLR;
951
		/*
952
		 * If user does not care about sbrk, utilize the bss
953
		 * grow region for mappings as well.  We can select
954
		 * the base for the image anywere and still not suffer
955
		 * from the fragmentation.
956
		 */
957
		if (!__elfN(aslr_care_sbrk) ||
958
		    (imgp->proc->p_flag2 & P2_ASLR_IGNSTART) != 0)
959
			map->flags |= MAP_ASLR_IGNSTART;
960
		vm_map_unlock(map);
961
	}
962
	maxv = vm_map_max(map) - lim_max(td, RLIMIT_STACK);
963
	if (et_dyn_addr == 1) {
964
		KASSERT((map->flags & MAP_ASLR) != 0,
965
		    ("et_dyn_addr but !MAP_ASLR"));
966
		et_dyn_addr = __CONCAT(rnd_, __elfN(base))(vm_map_min(map),
967
		    vm_map_min(map) + mapsz + lim_max(td, RLIMIT_DATA),
968
		    /* reserve half of the address space to interpreter */
969
		    maxv / 2, 1UL << flsl(maxalign));
970
	}
900
971
901
	vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
972
	vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
902
	if (error != 0)
973
	if (error != 0)
Lines 989-995 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
989
		goto ret;
1060
		goto ret;
990
	}
1061
	}
991
1062
992
	vmspace = imgp->proc->p_vmspace;
993
	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
1063
	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
994
	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
1064
	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
995
	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
1065
	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
Lines 1010-1015 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
1010
	if (interp != NULL) {
1080
	if (interp != NULL) {
1011
		have_interp = FALSE;
1081
		have_interp = FALSE;
1012
		VOP_UNLOCK(imgp->vp, 0);
1082
		VOP_UNLOCK(imgp->vp, 0);
1083
		if ((map->flags & MAP_ASLR) != 0) {
1084
			addr = __CONCAT(rnd_, __elfN(base))(addr, addr,
1085
			    maxv, PAGE_SIZE);
1086
		}
1013
		if (brand_info->emul_path != NULL &&
1087
		if (brand_info->emul_path != NULL &&
1014
		    brand_info->emul_path[0] != '\0') {
1088
		    brand_info->emul_path[0] != '\0') {
1015
			path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1089
			path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
(-)b/sys/kern/kern_fork.c (-1 / +2 lines)
Lines 497-503 do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * Link Here
497
	 * Increase reference counts on shared objects.
497
	 * Increase reference counts on shared objects.
498
	 */
498
	 */
499
	p2->p_flag = P_INMEM;
499
	p2->p_flag = P_INMEM;
500
	p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC);
500
	p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC |
501
	    P2_ASLR_ENABLE | P2_ASLR_DISABLE | P2_ASLR_IGNSTART);
501
	p2->p_swtick = ticks;
502
	p2->p_swtick = ticks;
502
	if (p1->p_flag & P_PROFIL)
503
	if (p1->p_flag & P_PROFIL)
503
		startprofclock(p2);
504
		startprofclock(p2);
(-)b/sys/kern/kern_procctl.c (-1 / +62 lines)
Lines 1-6 Link Here
1
/*-
1
/*-
2
 * Copyright (c) 2014 John Baldwin
2
 * Copyright (c) 2014 John Baldwin
3
 * Copyright (c) 2014 The FreeBSD Foundation
3
 * Copyright (c) 2014-2016 The FreeBSD Foundation
4
 *
4
 *
5
 * Portions of this software were developed by Konstantin Belousov
5
 * Portions of this software were developed by Konstantin Belousov
6
 * under sponsorship from the FreeBSD Foundation.
6
 * under sponsorship from the FreeBSD Foundation.
Lines 43-48 __FBSDID("$FreeBSD$"); Link Here
43
#include <sys/sysproto.h>
43
#include <sys/sysproto.h>
44
#include <sys/wait.h>
44
#include <sys/wait.h>
45
45
46
#include <vm/vm.h>
47
#include <vm/pmap.h>
48
#include <vm/vm_map.h>
49
46
static int
50
static int
47
protect_setchild(struct thread *td, struct proc *p, int flags)
51
protect_setchild(struct thread *td, struct proc *p, int flags)
48
{
52
{
Lines 336-341 trace_status(struct thread *td, struct proc *p, int *data) Link Here
336
	return (0);
340
	return (0);
337
}
341
}
338
342
343
static int
344
aslr_ctl(struct thread *td, struct proc *p, int state)
345
{
346
347
	PROC_LOCK_ASSERT(p, MA_OWNED);
348
349
	switch (state) {
350
	case PROC_ASLR_FORCE_ENABLE:
351
		p->p_flag2 &= ~P2_ASLR_DISABLE;
352
		p->p_flag2 |= P2_ASLR_ENABLE;
353
		break;
354
	case PROC_ASLR_FORCE_DISABLE:
355
		p->p_flag2 |= P2_ASLR_DISABLE;
356
		p->p_flag2 &= ~P2_ASLR_ENABLE;
357
		break;
358
	case PROC_ASLR_NOFORCE:
359
		p->p_flag2 &= ~(P2_ASLR_ENABLE | P2_ASLR_DISABLE);
360
		break;
361
	default:
362
		return (EINVAL);
363
	}
364
	return (0);
365
}
366
367
static int
368
aslr_status(struct thread *td, struct proc *p, int *data)
369
{
370
	int d;
371
372
	switch (p->p_flag2 & (P2_ASLR_ENABLE | P2_ASLR_DISABLE)) {
373
	case 0:
374
		d = PROC_ASLR_NOFORCE;
375
		break;
376
	case P2_ASLR_ENABLE:
377
		d = PROC_ASLR_FORCE_ENABLE;
378
		break;
379
	case P2_ASLR_DISABLE:
380
		d = PROC_ASLR_FORCE_DISABLE;
381
		break;
382
	}
383
	if ((p->p_vmspace->vm_map.flags & MAP_ASLR) != 0)
384
		d |= PROC_ASLR_ACTIVE;
385
	*data = d;
386
	return (0);
387
}
388
339
#ifndef _SYS_SYSPROTO_H_
389
#ifndef _SYS_SYSPROTO_H_
340
struct procctl_args {
390
struct procctl_args {
341
	idtype_t idtype;
391
	idtype_t idtype;
Lines 359-364 sys_procctl(struct thread *td, struct procctl_args *uap) Link Here
359
	switch (uap->com) {
409
	switch (uap->com) {
360
	case PROC_SPROTECT:
410
	case PROC_SPROTECT:
361
	case PROC_TRACE_CTL:
411
	case PROC_TRACE_CTL:
412
	case PROC_ASLR_CTL:
362
		error = copyin(uap->data, &flags, sizeof(flags));
413
		error = copyin(uap->data, &flags, sizeof(flags));
363
		if (error != 0)
414
		if (error != 0)
364
			return (error);
415
			return (error);
Lines 386-391 sys_procctl(struct thread *td, struct procctl_args *uap) Link Here
386
		data = &x.rk;
437
		data = &x.rk;
387
		break;
438
		break;
388
	case PROC_TRACE_STATUS:
439
	case PROC_TRACE_STATUS:
440
	case PROC_ASLR_STATUS:
389
		data = &flags;
441
		data = &flags;
390
		break;
442
		break;
391
	default:
443
	default:
Lines 403-408 sys_procctl(struct thread *td, struct procctl_args *uap) Link Here
403
			error = error1;
455
			error = error1;
404
		break;
456
		break;
405
	case PROC_TRACE_STATUS:
457
	case PROC_TRACE_STATUS:
458
	case PROC_ASLR_STATUS:
406
		if (error == 0)
459
		if (error == 0)
407
			error = copyout(&flags, uap->data, sizeof(flags));
460
			error = copyout(&flags, uap->data, sizeof(flags));
408
		break;
461
		break;
Lines 432-437 kern_procctl_single(struct thread *td, struct proc *p, int com, void *data) Link Here
432
		return (trace_ctl(td, p, *(int *)data));
485
		return (trace_ctl(td, p, *(int *)data));
433
	case PROC_TRACE_STATUS:
486
	case PROC_TRACE_STATUS:
434
		return (trace_status(td, p, data));
487
		return (trace_status(td, p, data));
488
	case PROC_ASLR_CTL:
489
		return (aslr_ctl(td, p, *(int *)data));
490
	case PROC_ASLR_STATUS:
491
		return (aslr_status(td, p, data));
435
	default:
492
	default:
436
		return (EINVAL);
493
		return (EINVAL);
437
	}
494
	}
Lines 452-457 kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) Link Here
452
	case PROC_REAP_GETPIDS:
509
	case PROC_REAP_GETPIDS:
453
	case PROC_REAP_KILL:
510
	case PROC_REAP_KILL:
454
	case PROC_TRACE_STATUS:
511
	case PROC_TRACE_STATUS:
512
	case PROC_ASLR_CTL:
513
	case PROC_ASLR_STATUS:
455
		if (idtype != P_PID)
514
		if (idtype != P_PID)
456
			return (EINVAL);
515
			return (EINVAL);
457
	}
516
	}
Lines 471-476 kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) Link Here
471
		tree_locked = true;
530
		tree_locked = true;
472
		break;
531
		break;
473
	case PROC_TRACE_STATUS:
532
	case PROC_TRACE_STATUS:
533
	case PROC_ASLR_CTL:
534
	case PROC_ASLR_STATUS:
474
		tree_locked = false;
535
		tree_locked = false;
475
		break;
536
		break;
476
	default:
537
	default:
(-)b/sys/sys/proc.h (+3 lines)
Lines 702-707 struct proc { Link Here
702
#define	P2_NOTRACE_EXEC 0x00000004	/* Keep P2_NOPTRACE on exec(2). */
702
#define	P2_NOTRACE_EXEC 0x00000004	/* Keep P2_NOPTRACE on exec(2). */
703
#define	P2_AST_SU	0x00000008	/* Handles SU ast for kthreads. */
703
#define	P2_AST_SU	0x00000008	/* Handles SU ast for kthreads. */
704
#define	P2_LWP_EVENTS	0x00000010	/* Report LWP events via ptrace(2). */
704
#define	P2_LWP_EVENTS	0x00000010	/* Report LWP events via ptrace(2). */
705
#define	P2_ASLR_ENABLE	0x00000020	/* Force enable ASLR. */
706
#define	P2_ASLR_DISABLE	0x00000040	/* Force disable ASLR. */
707
#define	P2_ASLR_IGNSTART 0x00000080	/* Enable ASLR to consume sbrk area. */
705
708
706
/* Flags protected by proctree_lock, kept in p_treeflags. */
709
/* Flags protected by proctree_lock, kept in p_treeflags. */
707
#define	P_TREE_ORPHANED		0x00000001	/* Reparented, on orphan list */
710
#define	P_TREE_ORPHANED		0x00000001	/* Reparented, on orphan list */
(-)b/sys/sys/procctl.h (+7 lines)
Lines 43-48 Link Here
43
#define	PROC_REAP_KILL		6	/* kill descendants */
43
#define	PROC_REAP_KILL		6	/* kill descendants */
44
#define	PROC_TRACE_CTL		7	/* en/dis ptrace and coredumps */
44
#define	PROC_TRACE_CTL		7	/* en/dis ptrace and coredumps */
45
#define	PROC_TRACE_STATUS	8	/* query tracing status */
45
#define	PROC_TRACE_STATUS	8	/* query tracing status */
46
#define	PROC_ASLR_CTL		9	/* en/dis ASLR */
47
#define	PROC_ASLR_STATUS	10	/* query ASLR status */
46
48
47
/* Operations for PROC_SPROTECT (passed in integer arg). */
49
/* Operations for PROC_SPROTECT (passed in integer arg). */
48
#define	PPROT_OP(x)	((x) & 0xf)
50
#define	PPROT_OP(x)	((x) & 0xf)
Lines 102-107 struct procctl_reaper_kill { Link Here
102
#define	PROC_TRACE_CTL_DISABLE		2
104
#define	PROC_TRACE_CTL_DISABLE		2
103
#define	PROC_TRACE_CTL_DISABLE_EXEC	3
105
#define	PROC_TRACE_CTL_DISABLE_EXEC	3
104
106
107
#define	PROC_ASLR_FORCE_ENABLE		1
108
#define	PROC_ASLR_FORCE_DISABLE		2
109
#define	PROC_ASLR_NOFORCE		3
110
#define	PROC_ASLR_ACTIVE		0x80000000
111
105
#ifndef _KERNEL
112
#ifndef _KERNEL
106
__BEGIN_DECLS
113
__BEGIN_DECLS
107
int	procctl(idtype_t, id_t, int, void *);
114
int	procctl(idtype_t, id_t, int, void *);
(-)b/sys/sys/sysent.h (-1 / +2 lines)
Lines 138-144 struct sysentvec { Link Here
138
#define	SV_AOUT		0x008000	/* a.out executable. */
138
#define	SV_AOUT		0x008000	/* a.out executable. */
139
#define	SV_SHP		0x010000	/* Shared page. */
139
#define	SV_SHP		0x010000	/* Shared page. */
140
#define	SV_CAPSICUM	0x020000	/* Force cap_enter() on startup. */
140
#define	SV_CAPSICUM	0x020000	/* Force cap_enter() on startup. */
141
#define	SV_TIMEKEEP	0x040000
141
#define	SV_TIMEKEEP	0x040000	/* Shared page timehands. */
142
#define	SV_ASLR		0x080000	/* ASLR allowed. */
142
143
143
#define	SV_ABI_MASK	0xff
144
#define	SV_ABI_MASK	0xff
144
#define	SV_PROC_FLAG(p, x)	((p)->p_sysent->sv_flags & (x))
145
#define	SV_PROC_FLAG(p, x)	((p)->p_sysent->sv_flags & (x))
(-)b/sys/vm/vm_map.c (-6 / +97 lines)
Lines 1470-1475 vm_map_fixed(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
1470
	return (result);
1470
	return (result);
1471
}
1471
}
1472
1472
1473
static const int aslr_pages_rnd_64[2] = {0x1000, 0x10};
1474
static const int aslr_pages_rnd_32[2] = {0x100, 0x4};
1475
1476
static int aslr_sloppiness = 5;
1477
SYSCTL_INT(_vm, OID_AUTO, aslr_sloppiness, CTLFLAG_RW, &aslr_sloppiness, 0,
1478
    "");
1479
1480
static int aslr_collapse_anon = 1;
1481
SYSCTL_INT(_vm, OID_AUTO, aslr_collapse_anon, CTLFLAG_RW,
1482
    &aslr_collapse_anon, 0,
1483
    "");
1484
1485
#define	MAP_32BIT_MAX_ADDR	((vm_offset_t)1 << 31)
1486
1473
/*
1487
/*
1474
 *	vm_map_find finds an unallocated region in the target address
1488
 *	vm_map_find finds an unallocated region in the target address
1475
 *	map with the given length.  The search is defined to be
1489
 *	map with the given length.  The search is defined to be
Lines 1485-1492 vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
1485
	    vm_size_t length, vm_offset_t max_addr, int find_space,
1499
	    vm_size_t length, vm_offset_t max_addr, int find_space,
1486
	    vm_prot_t prot, vm_prot_t max, int cow)
1500
	    vm_prot_t prot, vm_prot_t max, int cow)
1487
{
1501
{
1488
	vm_offset_t alignment, initial_addr, start;
1502
	vm_map_entry_t prev_entry;
1489
	int result;
1503
	vm_offset_t alignment, addr_save, start, start1, rand_max, re;
1504
	const int *aslr_pages_rnd;
1505
	int result, do_aslr, pidx;
1506
	bool en_aslr, anon;
1490
1507
1491
	KASSERT((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0 ||
1508
	KASSERT((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0 ||
1492
	    object == NULL,
1509
	    object == NULL,
Lines 1499-1519 vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
1499
		alignment = (vm_offset_t)1 << (find_space >> 8);
1516
		alignment = (vm_offset_t)1 << (find_space >> 8);
1500
	} else
1517
	} else
1501
		alignment = 0;
1518
		alignment = 0;
1502
	initial_addr = *addr;
1519
	do_aslr = (map->flags & MAP_ASLR) != 0 ? aslr_sloppiness : 0;
1520
	en_aslr = do_aslr != 0;
1521
	anon = object == NULL && (cow & (MAP_INHERIT_SHARE |
1522
	    MAP_STACK_GROWS_UP | MAP_STACK_GROWS_DOWN)) == 0 &&
1523
	    prot != PROT_NONE && aslr_collapse_anon;
1524
	addr_save = *addr;
1525
	if (en_aslr) {
1526
		if (vm_map_max(map) > MAP_32BIT_MAX_ADDR &&
1527
		    (max_addr == 0 || max_addr > MAP_32BIT_MAX_ADDR))
1528
			aslr_pages_rnd = aslr_pages_rnd_64;
1529
		else
1530
			aslr_pages_rnd = aslr_pages_rnd_32;
1531
		if (find_space != VMFS_NO_SPACE && (map->flags &
1532
		    MAP_ASLR_IGNSTART) != 0) {
1533
			start = anon ? map->anon_loc : vm_map_min(map);
1534
		} else {
1535
			start = anon && *addr == 0 ? map->anon_loc : addr_save;
1536
		}
1537
	} else {
1538
		start = addr_save;
1539
	}
1540
	start1 = start; /* for again_any_space restart */
1503
again:
1541
again:
1504
	start = initial_addr;
1542
	if (en_aslr && (do_aslr == 0 || (anon &&
1543
	    do_aslr == aslr_sloppiness - 1))) {
1544
		/*
1545
		 * We are either at the last aslr iteration, or anon
1546
		 * coalescing failed on the first try.  Retry with
1547
		 * free run.
1548
		 */
1549
		if ((map->flags & MAP_ASLR_IGNSTART) != 0)
1550
			start = vm_map_min(map);
1551
		else
1552
			start = addr_save;
1553
	}
1554
again_any_space:
1505
	vm_map_lock(map);
1555
	vm_map_lock(map);
1506
	do {
1556
	do {
1507
		if (find_space != VMFS_NO_SPACE) {
1557
		if (find_space != VMFS_NO_SPACE) {
1508
			if (vm_map_findspace(map, start, length, addr) ||
1558
			if (vm_map_findspace(map, start, length, addr) ||
1509
			    (max_addr != 0 && *addr + length > max_addr)) {
1559
			    (max_addr != 0 && *addr + length > max_addr)) {
1510
				vm_map_unlock(map);
1560
				vm_map_unlock(map);
1561
				if (do_aslr > 0) {
1562
					do_aslr--;
1563
					goto again;
1564
				}
1511
				if (find_space == VMFS_OPTIMAL_SPACE) {
1565
				if (find_space == VMFS_OPTIMAL_SPACE) {
1512
					find_space = VMFS_ANY_SPACE;
1566
					find_space = VMFS_ANY_SPACE;
1513
					goto again;
1567
					start = start1;
1568
					goto again_any_space;
1514
				}
1569
				}
1515
				return (KERN_NO_SPACE);
1570
				return (KERN_NO_SPACE);
1516
			}
1571
			}
1572
			/*
1573
			 * The R step for ASLR.  But skip it if we are
1574
			 * trying to coalesce anon memory request.
1575
			 */
1576
			if (do_aslr > 0 &&
1577
			    !(anon && do_aslr == aslr_sloppiness)) {
1578
				vm_map_lookup_entry(map, *addr, &prev_entry);
1579
				if (MAXPAGESIZES > 1 && pagesizes[1] != 0 &&
1580
				    (find_space == VMFS_SUPER_SPACE ||
1581
				    find_space == VMFS_OPTIMAL_SPACE))
1582
					pidx = 1;
1583
				else
1584
					pidx = 0;
1585
				re = prev_entry->next == &map->header ?
1586
				    map->max_offset : prev_entry->next->start;
1587
				rand_max = ((max_addr != 0 && re > max_addr) ?
1588
				    max_addr : re) - *addr - length;
1589
				rand_max /= pagesizes[pidx];
1590
				if (rand_max < aslr_pages_rnd[pidx]) {
1591
					vm_map_unlock(map);
1592
					start = re;
1593
					do_aslr--;
1594
					goto again;
1595
				}
1596
				*addr += (arc4random() % rand_max) *
1597
				    pagesizes[pidx];
1598
			}
1517
			switch (find_space) {
1599
			switch (find_space) {
1518
			case VMFS_SUPER_SPACE:
1600
			case VMFS_SUPER_SPACE:
1519
			case VMFS_OPTIMAL_SPACE:
1601
			case VMFS_OPTIMAL_SPACE:
Lines 1529-1535 again: Link Here
1529
				}
1611
				}
1530
				break;
1612
				break;
1531
			}
1613
			}
1532
1533
			start = *addr;
1614
			start = *addr;
1534
		}
1615
		}
1535
		if ((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) != 0) {
1616
		if ((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) != 0) {
Lines 1539-1546 again: Link Here
1539
			result = vm_map_insert(map, object, offset, start,
1620
			result = vm_map_insert(map, object, offset, start,
1540
			    start + length, prot, max, cow);
1621
			    start + length, prot, max, cow);
1541
		}
1622
		}
1623
		if (result != KERN_SUCCESS && do_aslr > 0) {
1624
			vm_map_unlock(map);
1625
			do_aslr--;
1626
			goto again;
1627
		}
1542
	} while (result == KERN_NO_SPACE && find_space != VMFS_NO_SPACE &&
1628
	} while (result == KERN_NO_SPACE && find_space != VMFS_NO_SPACE &&
1543
	    find_space != VMFS_ANY_SPACE);
1629
	    find_space != VMFS_ANY_SPACE);
1630
	if (result == KERN_SUCCESS && anon)
1631
		map->anon_loc = *addr + length;
1544
	vm_map_unlock(map);
1632
	vm_map_unlock(map);
1545
	return (result);
1633
	return (result);
1546
}
1634
}
Lines 3049-3054 vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end) Link Here
3049
3137
3050
		pmap_remove(map->pmap, entry->start, entry->end);
3138
		pmap_remove(map->pmap, entry->start, entry->end);
3051
3139
3140
		if (entry->end == map->anon_loc)
3141
			map->anon_loc = entry->prev->end;
3142
3052
		/*
3143
		/*
3053
		 * Delete the entry only after removing all pmap
3144
		 * Delete the entry only after removing all pmap
3054
		 * entries pointing to its pages.  (Otherwise, its
3145
		 * entries pointing to its pages.  (Otherwise, its
(-)b/sys/vm/vm_map.h (+3 lines)
Lines 190-195 struct vm_map { Link Here
190
	pmap_t pmap;			/* (c) Physical map */
190
	pmap_t pmap;			/* (c) Physical map */
191
#define	min_offset	header.start	/* (c) */
191
#define	min_offset	header.start	/* (c) */
192
#define	max_offset	header.end	/* (c) */
192
#define	max_offset	header.end	/* (c) */
193
	vm_offset_t	anon_loc;
193
	int busy;
194
	int busy;
194
};
195
};
195
196
Lines 198-203 struct vm_map { Link Here
198
 */
199
 */
199
#define MAP_WIREFUTURE		0x01	/* wire all future pages */
200
#define MAP_WIREFUTURE		0x01	/* wire all future pages */
200
#define	MAP_BUSY_WAKEUP		0x02
201
#define	MAP_BUSY_WAKEUP		0x02
202
#define	MAP_ASLR		0x04	/* enabled ASLR */
203
#define	MAP_ASLR_IGNSTART	0x08
201
204
202
#ifdef	_KERNEL
205
#ifdef	_KERNEL
203
static __inline vm_offset_t
206
static __inline vm_offset_t

Return to bug 208580