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 (-21 / +107 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 424-436 __elfN(map_partial)(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
424
}
439
}
425
440
426
static int
441
static int
427
__elfN(map_insert)(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
442
__elfN(map_insert)(struct image_params *imgp, vm_map_t map, vm_object_t object,
428
    vm_offset_t start, vm_offset_t end, vm_prot_t prot, int cow)
443
    vm_ooffset_t offset, vm_offset_t start, vm_offset_t end, vm_prot_t prot,
444
    int cow)
429
{
445
{
430
	struct sf_buf *sf;
446
	struct sf_buf *sf;
431
	vm_offset_t off;
447
	vm_offset_t off;
432
	vm_size_t sz;
448
	vm_size_t sz;
433
	int error, rv;
449
	int error, locked, rv;
434
450
435
	if (start != trunc_page(start)) {
451
	if (start != trunc_page(start)) {
436
		rv = __elfN(map_partial)(map, object, offset, start,
452
		rv = __elfN(map_partial)(map, object, offset, start,
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
469
			 * The mapping is not page aligned. This means we have
454
			 * to copy the data. Sigh.
470
			 * to copy the data. Sigh.
455
			 */
471
			 */
456
			rv = vm_map_find(map, NULL, 0, &start, end - start, 0,
472
			vm_map_lock(map);
457
			    VMFS_NO_SPACE, prot | VM_PROT_WRITE, VM_PROT_ALL,
473
			rv = vm_map_insert(map, NULL, 0, start, end,
458
			    0);
474
			    prot | VM_PROT_WRITE, VM_PROT_ALL, 0);
459
			if (rv)
475
			vm_map_unlock(map);
476
			if (rv != KERN_SUCCESS)
460
				return (rv);
477
				return (rv);
461
			if (object == NULL)
478
			if (object == NULL)
462
				return (KERN_SUCCESS);
479
				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,
488
				error = copyout((caddr_t)sf_buf_kva(sf) + off,
472
				    (caddr_t)start, sz);
489
				    (caddr_t)start, sz);
473
				vm_imgact_unmap_page(sf);
490
				vm_imgact_unmap_page(sf);
474
				if (error) {
491
				if (error != 0)
475
					return (KERN_FAILURE);
492
					return (KERN_FAILURE);
476
				}
477
				offset += sz;
493
				offset += sz;
478
			}
494
			}
479
			rv = KERN_SUCCESS;
495
			rv = KERN_SUCCESS;
Lines 483-490 __elfN(map_insert)(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
483
			rv = vm_map_insert(map, object, offset, start, end,
499
			rv = vm_map_insert(map, object, offset, start, end,
484
			    prot, VM_PROT_ALL, cow);
500
			    prot, VM_PROT_ALL, cow);
485
			vm_map_unlock(map);
501
			vm_map_unlock(map);
486
			if (rv != KERN_SUCCESS)
502
			if (rv != KERN_SUCCESS) {
503
				locked = VOP_ISLOCKED(imgp->vp);
504
				VOP_UNLOCK(imgp->vp, 0);
487
				vm_object_deallocate(object);
505
				vm_object_deallocate(object);
506
				vn_lock(imgp->vp, locked | LK_RETRY);
507
			}
488
		}
508
		}
489
		return (rv);
509
		return (rv);
490
	} else {
510
	} else {
Lines 541-547 __elfN(load_section)(struct image_params *imgp, vm_offset_t offset, Link Here
541
		cow = MAP_COPY_ON_WRITE | MAP_PREFAULT |
561
		cow = MAP_COPY_ON_WRITE | MAP_PREFAULT |
542
		    (prot & VM_PROT_WRITE ? 0 : MAP_DISABLE_COREDUMP);
562
		    (prot & VM_PROT_WRITE ? 0 : MAP_DISABLE_COREDUMP);
543
563
544
		rv = __elfN(map_insert)(map,
564
		rv = __elfN(map_insert)(imgp, map,
545
				      object,
565
				      object,
546
				      file_addr,	/* file offset */
566
				      file_addr,	/* file offset */
547
				      map_addr,		/* virtual start */
567
				      map_addr,		/* virtual start */
Lines 571-578 __elfN(load_section)(struct image_params *imgp, vm_offset_t offset, Link Here
571
591
572
	/* This had damn well better be true! */
592
	/* This had damn well better be true! */
573
	if (map_len != 0) {
593
	if (map_len != 0) {
574
		rv = __elfN(map_insert)(map, NULL, 0, map_addr, map_addr +
594
		rv = __elfN(map_insert)(imgp, map, NULL, 0, map_addr,
575
		    map_len, VM_PROT_ALL, 0);
595
		    map_addr + map_len, VM_PROT_ALL, 0);
576
		if (rv != KERN_SUCCESS) {
596
		if (rv != KERN_SUCCESS) {
577
			return (EINVAL);
597
			return (EINVAL);
578
		}
598
		}
Lines 747-752 fail: Link Here
747
	return (error);
767
	return (error);
748
}
768
}
749
769
770
static u_long
771
__CONCAT(rnd_, __elfN(base))(u_long base, u_long minv, u_long maxv,
772
    u_int align)
773
{
774
	u_long rbase, res;
775
776
	arc4rand(&rbase, sizeof(rbase), 0);
777
	res = base + rbase % (maxv - minv);
778
	res &= ~((u_long)align - 1);
779
	KASSERT(res >= base,
780
	    ("res %#lx < base %#lx, minv %#lx maxv %#lx rbase %#lx",
781
	    res, base, minv, maxv, rbase));
782
	KASSERT(res < maxv,
783
	    ("res %#lx > maxv %#lx, minv %#lx base %#lx rbase %#lx",
784
	    res, maxv, minv, base, rbase));
785
	return (res);
786
}
787
750
static int
788
static int
751
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
789
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
752
{
790
{
Lines 755-760 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
755
	const Elf_Phdr *phdr;
793
	const Elf_Phdr *phdr;
756
	Elf_Auxargs *elf_auxargs;
794
	Elf_Auxargs *elf_auxargs;
757
	struct vmspace *vmspace;
795
	struct vmspace *vmspace;
796
	vm_map_t map;
758
	const char *err_str, *newinterp;
797
	const char *err_str, *newinterp;
759
	char *interp, *interp_buf, *path;
798
	char *interp, *interp_buf, *path;
760
	Elf_Brandinfo *brand_info;
799
	Elf_Brandinfo *brand_info;
Lines 762-767 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
762
	vm_prot_t prot;
801
	vm_prot_t prot;
763
	u_long text_size, data_size, total_size, text_addr, data_addr;
802
	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;
803
	u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr;
804
	u_long maxalign, mapsz, maxv;
765
	int32_t osrel;
805
	int32_t osrel;
766
	int error, i, n, interp_name_len, have_interp;
806
	int error, i, n, interp_name_len, have_interp;
767
807
Lines 803-814 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
803
	err_str = newinterp = NULL;
843
	err_str = newinterp = NULL;
804
	interp = interp_buf = NULL;
844
	interp = interp_buf = NULL;
805
	td = curthread;
845
	td = curthread;
846
	maxalign = PAGE_SIZE;
847
	mapsz = 0;
806
848
807
	for (i = 0; i < hdr->e_phnum; i++) {
849
	for (i = 0; i < hdr->e_phnum; i++) {
808
		switch (phdr[i].p_type) {
850
		switch (phdr[i].p_type) {
809
		case PT_LOAD:
851
		case PT_LOAD:
810
			if (n == 0)
852
			if (n == 0)
811
				baddr = phdr[i].p_vaddr;
853
				baddr = phdr[i].p_vaddr;
854
			if (phdr[i].p_align > maxalign)
855
				maxalign = phdr[i].p_align;
856
			mapsz += phdr[i].p_memsz;
812
			n++;
857
			n++;
813
			break;
858
			break;
814
		case PT_INTERP:
859
		case PT_INTERP:
Lines 862-867 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
862
		error = ENOEXEC;
907
		error = ENOEXEC;
863
		goto ret;
908
		goto ret;
864
	}
909
	}
910
	sv = brand_info->sysvec;
911
	et_dyn_addr = 0;
865
	if (hdr->e_type == ET_DYN) {
912
	if (hdr->e_type == ET_DYN) {
866
		if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) {
913
		if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) {
867
			uprintf("Cannot execute shared object\n");
914
			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
919
		 * Honour the base load address from the dso if it is
873
		 * non-zero for some reason.
920
		 * non-zero for some reason.
874
		 */
921
		 */
875
		if (baddr == 0)
922
		if (baddr == 0) {
876
			et_dyn_addr = ET_DYN_LOAD_ADDR;
923
			if ((sv->sv_flags & SV_ASLR) == 0)
877
		else
924
				et_dyn_addr = ET_DYN_LOAD_ADDR;
878
			et_dyn_addr = 0;
925
			else if ((__elfN(pie_aslr_enabled) &&
879
	} else
926
			    (imgp->proc->p_flag2 & P2_ASLR_DISABLE) == 0) ||
880
		et_dyn_addr = 0;
927
			    (imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0)
881
	sv = brand_info->sysvec;
928
				et_dyn_addr = 1;
929
			else
930
				et_dyn_addr = ET_DYN_LOAD_ADDR;
931
		}
932
	}
882
	if (interp != NULL && brand_info->interp_newpath != NULL)
933
	if (interp != NULL && brand_info->interp_newpath != NULL)
883
		newinterp = brand_info->interp_newpath;
934
		newinterp = brand_info->interp_newpath;
884
935
Lines 897-902 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
897
948
898
	error = exec_new_vmspace(imgp, sv);
949
	error = exec_new_vmspace(imgp, sv);
899
	imgp->proc->p_sysent = sv;
950
	imgp->proc->p_sysent = sv;
951
	vmspace = imgp->proc->p_vmspace;
952
	map = &vmspace->vm_map;
953
954
	if ((sv->sv_flags & SV_ASLR) == 0 ||
955
	    (imgp->proc->p_flag2 & P2_ASLR_DISABLE) != 0) {
956
		KASSERT(et_dyn_addr != 1, ("et_dyn_addr == 1 and !ASLR"));
957
	} else if ((imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0 ||
958
	    (__elfN(aslr_enabled) && hdr->e_type != ET_DYN) ||
959
	    et_dyn_addr == 1) {
960
		vm_map_lock(map);
961
		map->flags |= MAP_ASLR;
962
		/*
963
		 * If user does not care about sbrk, utilize the bss
964
		 * grow region for mappings as well.  We can select
965
		 * the base for the image anywere and still not suffer
966
		 * from the fragmentation.
967
		 */
968
		if (!__elfN(aslr_care_sbrk) ||
969
		    (imgp->proc->p_flag2 & P2_ASLR_IGNSTART) != 0)
970
			map->flags |= MAP_ASLR_IGNSTART;
971
		vm_map_unlock(map);
972
	}
973
	maxv = vm_map_max(map) - lim_max(td, RLIMIT_STACK);
974
	if (et_dyn_addr == 1) {
975
		KASSERT((map->flags & MAP_ASLR) != 0,
976
		    ("et_dyn_addr but !MAP_ASLR"));
977
		et_dyn_addr = __CONCAT(rnd_, __elfN(base))(vm_map_min(map),
978
		    vm_map_min(map) + mapsz + lim_max(td, RLIMIT_DATA),
979
		    /* reserve half of the address space to interpreter */
980
		    maxv / 2, 1UL << flsl(maxalign));
981
	}
900
982
901
	vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
983
	vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
902
	if (error != 0)
984
	if (error != 0)
Lines 989-995 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
989
		goto ret;
1071
		goto ret;
990
	}
1072
	}
991
1073
992
	vmspace = imgp->proc->p_vmspace;
993
	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
1074
	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
994
	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
1075
	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
995
	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
1076
	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
Lines 1010-1015 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
1010
	if (interp != NULL) {
1091
	if (interp != NULL) {
1011
		have_interp = FALSE;
1092
		have_interp = FALSE;
1012
		VOP_UNLOCK(imgp->vp, 0);
1093
		VOP_UNLOCK(imgp->vp, 0);
1094
		if ((map->flags & MAP_ASLR) != 0) {
1095
			addr = __CONCAT(rnd_, __elfN(base))(addr, addr,
1096
			    /* Assume that interpeter fits into 1/4 of AS */
1097
			    (maxv + addr) / 2, PAGE_SIZE);
1098
		}
1013
		if (brand_info->emul_path != NULL &&
1099
		if (brand_info->emul_path != NULL &&
1014
		    brand_info->emul_path[0] != '\0') {
1100
		    brand_info->emul_path[0] != '\0') {
1015
			path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1101
			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