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 73-79 struct sysentvec elf64_freebsd_sysvec = { Link Here
73
	.sv_setregs	= exec_setregs,
73
	.sv_setregs	= exec_setregs,
74
	.sv_fixlimit	= NULL,
74
	.sv_fixlimit	= NULL,
75
	.sv_maxssiz	= NULL,
75
	.sv_maxssiz	= NULL,
76
	.sv_flags	= SV_ABI_FREEBSD | SV_LP64 | SV_SHP | SV_TIMEKEEP,
76
	.sv_flags	= SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP |
77
			    SV_TIMEKEEP,
77
	.sv_set_syscall_retval = cpu_set_syscall_retval,
78
	.sv_set_syscall_retval = cpu_set_syscall_retval,
78
	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
79
	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
79
	.sv_syscallnames = syscallnames,
80
	.sv_syscallnames = syscallnames,
(-)b/sys/arm/arm/elf_machdep.c (-1 / +1 lines)
Lines 82-88 struct sysentvec elf32_freebsd_sysvec = { Link Here
82
	.sv_maxssiz	= NULL,
82
	.sv_maxssiz	= NULL,
83
	.sv_flags	=
83
	.sv_flags	=
84
#if __ARM_ARCH >= 6
84
#if __ARM_ARCH >= 6
85
			  SV_SHP | SV_TIMEKEEP |
85
			  SV_ASLR | SV_SHP | SV_TIMEKEEP |
86
#endif
86
#endif
87
			  SV_ABI_FREEBSD | SV_ILP32,
87
			  SV_ABI_FREEBSD | SV_ILP32,
88
	.sv_set_syscall_retval = cpu_set_syscall_retval,
88
	.sv_set_syscall_retval = cpu_set_syscall_retval,
(-)b/sys/compat/freebsd32/freebsd32_misc.c (+3 lines)
Lines 3325-3330 freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap) Link Here
3325
	int error, error1, flags, signum;
3325
	int error, error1, flags, signum;
3326
3326
3327
	switch (uap->com) {
3327
	switch (uap->com) {
3328
	case PROC_ASLR_CTL:
3328
	case PROC_SPROTECT:
3329
	case PROC_SPROTECT:
3329
	case PROC_TRACE_CTL:
3330
	case PROC_TRACE_CTL:
3330
	case PROC_TRAPCAP_CTL:
3331
	case PROC_TRAPCAP_CTL:
Lines 3356-3361 freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap) Link Here
3356
			return (error);
3357
			return (error);
3357
		data = &x.rk;
3358
		data = &x.rk;
3358
		break;
3359
		break;
3360
	case PROC_ASLR_STATUS:
3359
	case PROC_TRACE_STATUS:
3361
	case PROC_TRACE_STATUS:
3360
	case PROC_TRAPCAP_STATUS:
3362
	case PROC_TRAPCAP_STATUS:
3361
		data = &flags;
3363
		data = &flags;
Lines 3384-3389 freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap) Link Here
3384
		if (error == 0)
3386
		if (error == 0)
3385
			error = error1;
3387
			error = error1;
3386
		break;
3388
		break;
3389
	case PROC_ASLR_STATUS:
3387
	case PROC_TRACE_STATUS:
3390
	case PROC_TRACE_STATUS:
3388
	case PROC_TRAPCAP_STATUS:
3391
	case PROC_TRAPCAP_STATUS:
3389
		if (error == 0)
3392
		if (error == 0)
(-)b/sys/compat/ia32/ia32_sysvec.c (-1 / +1 lines)
Lines 119-125 struct sysentvec ia32_freebsd_sysvec = { Link Here
119
	.sv_setregs	= ia32_setregs,
119
	.sv_setregs	= ia32_setregs,
120
	.sv_fixlimit	= ia32_fixlimit,
120
	.sv_fixlimit	= ia32_fixlimit,
121
	.sv_maxssiz	= &ia32_maxssiz,
121
	.sv_maxssiz	= &ia32_maxssiz,
122
	.sv_flags	= SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 |
122
	.sv_flags	= SV_ABI_FREEBSD | SV_ASLR | SV_IA32 | SV_ILP32 |
123
			    SV_SHP | SV_TIMEKEEP,
123
			    SV_SHP | SV_TIMEKEEP,
124
	.sv_set_syscall_retval = ia32_set_syscall_retval,
124
	.sv_set_syscall_retval = ia32_set_syscall_retval,
125
	.sv_fetch_syscall_args = ia32_fetch_syscall_args,
125
	.sv_fetch_syscall_args = ia32_fetch_syscall_args,
(-)b/sys/i386/i386/elf_machdep.c (-2 / +2 lines)
Lines 75-82 struct sysentvec elf32_freebsd_sysvec = { Link Here
75
	.sv_setregs	= exec_setregs,
75
	.sv_setregs	= exec_setregs,
76
	.sv_fixlimit	= NULL,
76
	.sv_fixlimit	= NULL,
77
	.sv_maxssiz	= NULL,
77
	.sv_maxssiz	= NULL,
78
	.sv_flags	= SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP |
78
	.sv_flags	= SV_ABI_FREEBSD | SV_ASLR | SV_IA32 | SV_ILP32 |
79
			    SV_TIMEKEEP,
79
			    SV_SHP | SV_TIMEKEEP,
80
	.sv_set_syscall_retval = cpu_set_syscall_retval,
80
	.sv_set_syscall_retval = cpu_set_syscall_retval,
81
	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
81
	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
82
	.sv_syscallnames = syscallnames,
82
	.sv_syscallnames = syscallnames,
(-)b/sys/kern/imgact_elf.c (-4 / +126 lines)
Lines 138-143 SYSCTL_INT(_kern_elf32, OID_AUTO, read_exec, CTLFLAG_RW, &i386_read_exec, 0, Link Here
138
#endif
138
#endif
139
#endif
139
#endif
140
140
141
static int __elfN(aslr_enabled) = 1;
142
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
143
    aslr_enabled, CTLFLAG_RWTUN, &__elfN(aslr_enabled), 0,
144
    __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
145
    ": enable address map randomization");
146
147
static int __elfN(pie_aslr_enabled) = 1;
148
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
149
    pie_aslr_enabled, CTLFLAG_RWTUN, &__elfN(pie_aslr_enabled), 0,
150
    __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
151
    ": enable address map randomization for PIE binaries");
152
153
static int __elfN(aslr_honor_sbrk) = 0;
154
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
155
    aslr_honor_sbrk, CTLFLAG_RW, &__elfN(aslr_honor_sbrk), 0,
156
    __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": assume sbrk is used");
157
141
static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
158
static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
142
159
143
#define	trunc_page_ps(va, ps)	rounddown2(va, ps)
160
#define	trunc_page_ps(va, ps)	rounddown2(va, ps)
Lines 775-780 __elfN(load_file)(struct proc *p, const char *file, u_long *addr, Link Here
775
	return (error);
792
	return (error);
776
}
793
}
777
794
795
static u_long
796
__CONCAT(rnd_, __elfN(base))(vm_map_t map __unused, u_long minv, u_long maxv,
797
    u_int align)
798
{
799
	u_long rbase, res;
800
801
	MPASS(vm_map_min(map) <= minv);
802
	MPASS(maxv <= vm_map_max(map));
803
	MPASS(minv < maxv);
804
	MPASS(minv + align < maxv);
805
	arc4rand(&rbase, sizeof(rbase), 0);
806
	res = roundup(minv, (u_long)align) + rbase % (maxv - minv);
807
	res &= ~((u_long)align - 1);
808
	if (res >= maxv)
809
		res -= align;
810
	KASSERT(res >= minv,
811
	    ("res %#lx < minv %#lx, maxv %#lx rbase %#lx",
812
	    res, minv, maxv, rbase));
813
	KASSERT(res < maxv,
814
	    ("res %#lx > maxv %#lx, minv %#lx rbase %#lx",
815
	    res, maxv, minv, rbase));
816
	return (res);
817
}
818
819
/*
820
 * Impossible et_dyn_addr initial value indicating that the real base
821
 * must be calculated later with some randomization applied.
822
 */
823
#define	ET_DYN_ADDR_RAND	1
824
778
static int
825
static int
779
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
826
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
780
{
827
{
Lines 783-788 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
783
	const Elf_Phdr *phdr;
830
	const Elf_Phdr *phdr;
784
	Elf_Auxargs *elf_auxargs;
831
	Elf_Auxargs *elf_auxargs;
785
	struct vmspace *vmspace;
832
	struct vmspace *vmspace;
833
	vm_map_t map;
786
	const char *err_str, *newinterp;
834
	const char *err_str, *newinterp;
787
	char *interp, *interp_buf, *path;
835
	char *interp, *interp_buf, *path;
788
	Elf_Brandinfo *brand_info;
836
	Elf_Brandinfo *brand_info;
Lines 790-795 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
790
	vm_prot_t prot;
838
	vm_prot_t prot;
791
	u_long text_size, data_size, total_size, text_addr, data_addr;
839
	u_long text_size, data_size, total_size, text_addr, data_addr;
792
	u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr;
840
	u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr;
841
	u_long maxalign, mapsz, maxv, maxv1;
793
	uint32_t fctl0;
842
	uint32_t fctl0;
794
	int32_t osrel;
843
	int32_t osrel;
795
	int error, i, n, interp_name_len, have_interp;
844
	int error, i, n, interp_name_len, have_interp;
Lines 833-844 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
833
	err_str = newinterp = NULL;
882
	err_str = newinterp = NULL;
834
	interp = interp_buf = NULL;
883
	interp = interp_buf = NULL;
835
	td = curthread;
884
	td = curthread;
885
	maxalign = PAGE_SIZE;
886
	mapsz = 0;
836
887
837
	for (i = 0; i < hdr->e_phnum; i++) {
888
	for (i = 0; i < hdr->e_phnum; i++) {
838
		switch (phdr[i].p_type) {
889
		switch (phdr[i].p_type) {
839
		case PT_LOAD:
890
		case PT_LOAD:
840
			if (n == 0)
891
			if (n == 0)
841
				baddr = phdr[i].p_vaddr;
892
				baddr = phdr[i].p_vaddr;
893
			if (phdr[i].p_align > maxalign)
894
				maxalign = phdr[i].p_align;
895
			mapsz += phdr[i].p_memsz;
842
			n++;
896
			n++;
843
			break;
897
			break;
844
		case PT_INTERP:
898
		case PT_INTERP:
Lines 899-904 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
899
		error = ENOEXEC;
953
		error = ENOEXEC;
900
		goto ret;
954
		goto ret;
901
	}
955
	}
956
	sv = brand_info->sysvec;
902
	et_dyn_addr = 0;
957
	et_dyn_addr = 0;
903
	if (hdr->e_type == ET_DYN) {
958
	if (hdr->e_type == ET_DYN) {
904
		if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) {
959
		if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) {
Lines 910-919 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
910
		 * Honour the base load address from the dso if it is
965
		 * Honour the base load address from the dso if it is
911
		 * non-zero for some reason.
966
		 * non-zero for some reason.
912
		 */
967
		 */
913
		if (baddr == 0)
968
		if (baddr == 0) {
914
			et_dyn_addr = ET_DYN_LOAD_ADDR;
969
			if ((sv->sv_flags & SV_ASLR) == 0 ||
970
			    (fctl0 & NT_FREEBSD_FCTL_NO_ASLR) != 0)
971
				et_dyn_addr = ET_DYN_LOAD_ADDR;
972
			else if ((__elfN(pie_aslr_enabled) &&
973
			    (imgp->proc->p_flag2 & P2_ASLR_DISABLE) == 0) ||
974
			    (imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0)
975
				et_dyn_addr = ET_DYN_ADDR_RAND;
976
			else
977
				et_dyn_addr = ET_DYN_LOAD_ADDR;
978
		}
915
	}
979
	}
916
	sv = brand_info->sysvec;
917
	if (interp != NULL && brand_info->interp_newpath != NULL)
980
	if (interp != NULL && brand_info->interp_newpath != NULL)
918
		newinterp = brand_info->interp_newpath;
981
		newinterp = brand_info->interp_newpath;
919
982
Lines 930-938 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
930
	 */
993
	 */
931
	VOP_UNLOCK(imgp->vp, 0);
994
	VOP_UNLOCK(imgp->vp, 0);
932
995
996
	/*
997
	 * Decide whether to enable randomization of user mappings.
998
	 * First, reset user preferences for the setid binaries.
999
	 * Then, account for the support of the randomization by the
1000
	 * ABI, by user preferences, and make special treatment for
1001
	 * PIE binaries.
1002
	 */
1003
	if (imgp->credential_setid) {
1004
		PROC_LOCK(imgp->proc);
1005
		imgp->proc->p_flag2 &= ~(P2_ASLR_ENABLE | P2_ASLR_DISABLE);
1006
		PROC_UNLOCK(imgp->proc);
1007
	}
1008
	if ((sv->sv_flags & SV_ASLR) == 0 ||
1009
	    (imgp->proc->p_flag2 & P2_ASLR_DISABLE) != 0 ||
1010
	    (fctl0 & NT_FREEBSD_FCTL_NO_ASLR) != 0) {
1011
		KASSERT(et_dyn_addr != ET_DYN_ADDR_RAND,
1012
		    ("et_dyn_addr == RAND and !ASLR"));
1013
	} else if ((imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0 ||
1014
	    (__elfN(aslr_enabled) && hdr->e_type == ET_EXEC) ||
1015
	    et_dyn_addr == ET_DYN_ADDR_RAND) {
1016
		imgp->map_flags |= MAP_ASLR;
1017
		/*
1018
		 * If user does not care about sbrk, utilize the bss
1019
		 * grow region for mappings as well.  We can select
1020
		 * the base for the image anywere and still not suffer
1021
		 * from the fragmentation.
1022
		 */
1023
		if (!__elfN(aslr_honor_sbrk) ||
1024
		    (imgp->proc->p_flag2 & P2_ASLR_IGNSTART) != 0)
1025
			imgp->map_flags |= MAP_ASLR_IGNSTART;
1026
	}
1027
933
	error = exec_new_vmspace(imgp, sv);
1028
	error = exec_new_vmspace(imgp, sv);
1029
	vmspace = imgp->proc->p_vmspace;
1030
	map = &vmspace->vm_map;
1031
934
	imgp->proc->p_sysent = sv;
1032
	imgp->proc->p_sysent = sv;
935
1033
1034
	maxv = vm_map_max(map) - lim_max(td, RLIMIT_STACK);
1035
	if (et_dyn_addr == ET_DYN_ADDR_RAND) {
1036
		KASSERT((map->flags & MAP_ASLR) != 0,
1037
		    ("ET_DYN_ADDR_RAND but !MAP_ASLR"));
1038
		et_dyn_addr = __CONCAT(rnd_, __elfN(base))(map,
1039
		    vm_map_min(map) + mapsz + lim_max(td, RLIMIT_DATA),
1040
		    /* reserve half of the address space to interpreter */
1041
		    maxv / 2, 1UL << flsl(maxalign));
1042
	}
1043
936
	vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
1044
	vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
937
	if (error != 0)
1045
	if (error != 0)
938
		goto ret;
1046
		goto ret;
Lines 1024-1030 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
1024
		goto ret;
1132
		goto ret;
1025
	}
1133
	}
1026
1134
1027
	vmspace = imgp->proc->p_vmspace;
1028
	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
1135
	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
1029
	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
1136
	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
1030
	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
1137
	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
Lines 1038-1043 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
1038
	 */
1145
	 */
1039
	addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(td,
1146
	addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(td,
1040
	    RLIMIT_DATA));
1147
	    RLIMIT_DATA));
1148
	if ((map->flags & MAP_ASLR) != 0) {
1149
		maxv1 = maxv / 2 + addr / 2;
1150
		MPASS(maxv1 >= addr);	/* No overflow */
1151
		map->anon_loc = __CONCAT(rnd_, __elfN(base))(map, addr, maxv1,
1152
		    MAXPAGESIZES > 1 ? pagesizes[1] : pagesizes[0]);
1153
	} else {
1154
		map->anon_loc = addr;
1155
	}
1041
	PROC_UNLOCK(imgp->proc);
1156
	PROC_UNLOCK(imgp->proc);
1042
1157
1043
	imgp->entry_addr = entry;
1158
	imgp->entry_addr = entry;
Lines 1045-1050 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) Link Here
1045
	if (interp != NULL) {
1160
	if (interp != NULL) {
1046
		have_interp = FALSE;
1161
		have_interp = FALSE;
1047
		VOP_UNLOCK(imgp->vp, 0);
1162
		VOP_UNLOCK(imgp->vp, 0);
1163
		if ((map->flags & MAP_ASLR) != 0) {
1164
			/* Assume that interpeter fits into 1/4 of AS */
1165
			maxv1 = maxv / 2 + addr / 2;
1166
			MPASS(maxv1 >= addr);	/* No overflow */
1167
			addr = __CONCAT(rnd_, __elfN(base))(map, addr,
1168
			    maxv1, PAGE_SIZE);
1169
		}
1048
		if (brand_info->emul_path != NULL &&
1170
		if (brand_info->emul_path != NULL &&
1049
		    brand_info->emul_path[0] != '\0') {
1171
		    brand_info->emul_path[0] != '\0') {
1050
			path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1172
			path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
(-)b/sys/kern/kern_exec.c (-2 / +7 lines)
Lines 1102-1110 exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv) Link Here
1102
		shmexit(vmspace);
1102
		shmexit(vmspace);
1103
		pmap_remove_pages(vmspace_pmap(vmspace));
1103
		pmap_remove_pages(vmspace_pmap(vmspace));
1104
		vm_map_remove(map, vm_map_min(map), vm_map_max(map));
1104
		vm_map_remove(map, vm_map_min(map), vm_map_max(map));
1105
		/* An exec terminates mlockall(MCL_FUTURE). */
1105
		/*
1106
		 * An exec terminates mlockall(MCL_FUTURE), ASLR state
1107
		 * must be re-evaluated.
1108
		 */
1106
		vm_map_lock(map);
1109
		vm_map_lock(map);
1107
		vm_map_modflags(map, 0, MAP_WIREFUTURE);
1110
		vm_map_modflags(map, 0, MAP_WIREFUTURE | MAP_ASLR |
1111
		    MAP_ASLR_IGNSTART);
1108
		vm_map_unlock(map);
1112
		vm_map_unlock(map);
1109
	} else {
1113
	} else {
1110
		error = vmspace_exec(p, sv_minuser, sv->sv_maxuser);
1114
		error = vmspace_exec(p, sv_minuser, sv->sv_maxuser);
Lines 1113-1118 exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv) Link Here
1113
		vmspace = p->p_vmspace;
1117
		vmspace = p->p_vmspace;
1114
		map = &vmspace->vm_map;
1118
		map = &vmspace->vm_map;
1115
	}
1119
	}
1120
	map->flags |= imgp->map_flags;
1116
1121
1117
	/* Map a shared page */
1122
	/* Map a shared page */
1118
	obj = sv->sv_shared_page_obj;
1123
	obj = sv->sv_shared_page_obj;
(-)b/sys/kern/kern_fork.c (-1 / +2 lines)
Lines 466-472 do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * Link Here
466
	 * Increase reference counts on shared objects.
466
	 * Increase reference counts on shared objects.
467
	 */
467
	 */
468
	p2->p_flag = P_INMEM;
468
	p2->p_flag = P_INMEM;
469
	p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC | P2_TRAPCAP);
469
	p2->p_flag2 = p1->p_flag2 & (P2_ASLR_DISABLE | P2_ASLR_ENABLE |
470
	    P2_ASLR_IGNSTART | P2_NOTRACE | P2_NOTRACE_EXEC | P2_TRAPCAP);
470
	p2->p_swtick = ticks;
471
	p2->p_swtick = ticks;
471
	if (p1->p_flag & P_PROFIL)
472
	if (p1->p_flag & P_PROFIL)
472
		startprofclock(p2);
473
		startprofclock(p2);
(-)b/sys/kern/kern_procctl.c (+72 lines)
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
#include <vm/vm_extern.h>
50
46
static int
51
static int
47
protect_setchild(struct thread *td, struct proc *p, int flags)
52
protect_setchild(struct thread *td, struct proc *p, int flags)
48
{
53
{
Lines 413-418 trapcap_status(struct thread *td, struct proc *p, int *data) Link Here
413
	return (0);
418
	return (0);
414
}
419
}
415
420
421
static int
422
aslr_ctl(struct thread *td, struct proc *p, int state)
423
{
424
425
	PROC_LOCK_ASSERT(p, MA_OWNED);
426
427
	switch (state) {
428
	case PROC_ASLR_FORCE_ENABLE:
429
		p->p_flag2 &= ~P2_ASLR_DISABLE;
430
		p->p_flag2 |= P2_ASLR_ENABLE;
431
		break;
432
	case PROC_ASLR_FORCE_DISABLE:
433
		p->p_flag2 |= P2_ASLR_DISABLE;
434
		p->p_flag2 &= ~P2_ASLR_ENABLE;
435
		break;
436
	case PROC_ASLR_NOFORCE:
437
		p->p_flag2 &= ~(P2_ASLR_ENABLE | P2_ASLR_DISABLE);
438
		break;
439
	default:
440
		return (EINVAL);
441
	}
442
	return (0);
443
}
444
445
static int
446
aslr_status(struct thread *td, struct proc *p, int *data)
447
{
448
	struct vmspace *vm;
449
	int d;
450
451
	switch (p->p_flag2 & (P2_ASLR_ENABLE | P2_ASLR_DISABLE)) {
452
	case 0:
453
		d = PROC_ASLR_NOFORCE;
454
		break;
455
	case P2_ASLR_ENABLE:
456
		d = PROC_ASLR_FORCE_ENABLE;
457
		break;
458
	case P2_ASLR_DISABLE:
459
		d = PROC_ASLR_FORCE_DISABLE;
460
		break;
461
	}
462
	if ((p->p_flag & P_WEXIT) == 0) {
463
		_PHOLD(p);
464
		PROC_UNLOCK(p);
465
		vm = vmspace_acquire_ref(p);
466
		if (vm != NULL && (vm->vm_map.flags & MAP_ASLR) != 0) {
467
			d |= PROC_ASLR_ACTIVE;
468
			vmspace_free(vm);
469
		}
470
		PROC_LOCK(p);
471
		_PRELE(p);
472
	}
473
	*data = d;
474
	return (0);
475
}
476
416
#ifndef _SYS_SYSPROTO_H_
477
#ifndef _SYS_SYSPROTO_H_
417
struct procctl_args {
478
struct procctl_args {
418
	idtype_t idtype;
479
	idtype_t idtype;
Lines 434-439 sys_procctl(struct thread *td, struct procctl_args *uap) Link Here
434
	int error, error1, flags, signum;
495
	int error, error1, flags, signum;
435
496
436
	switch (uap->com) {
497
	switch (uap->com) {
498
	case PROC_ASLR_CTL:
437
	case PROC_SPROTECT:
499
	case PROC_SPROTECT:
438
	case PROC_TRACE_CTL:
500
	case PROC_TRACE_CTL:
439
	case PROC_TRAPCAP_CTL:
501
	case PROC_TRAPCAP_CTL:
Lines 463-468 sys_procctl(struct thread *td, struct procctl_args *uap) Link Here
463
			return (error);
525
			return (error);
464
		data = &x.rk;
526
		data = &x.rk;
465
		break;
527
		break;
528
	case PROC_ASLR_STATUS:
466
	case PROC_TRACE_STATUS:
529
	case PROC_TRACE_STATUS:
467
	case PROC_TRAPCAP_STATUS:
530
	case PROC_TRAPCAP_STATUS:
468
		data = &flags;
531
		data = &flags;
Lines 490-495 sys_procctl(struct thread *td, struct procctl_args *uap) Link Here
490
		if (error == 0)
553
		if (error == 0)
491
			error = error1;
554
			error = error1;
492
		break;
555
		break;
556
	case PROC_ASLR_STATUS:
493
	case PROC_TRACE_STATUS:
557
	case PROC_TRACE_STATUS:
494
	case PROC_TRAPCAP_STATUS:
558
	case PROC_TRAPCAP_STATUS:
495
		if (error == 0)
559
		if (error == 0)
Lines 509-514 kern_procctl_single(struct thread *td, struct proc *p, int com, void *data) Link Here
509
573
510
	PROC_LOCK_ASSERT(p, MA_OWNED);
574
	PROC_LOCK_ASSERT(p, MA_OWNED);
511
	switch (com) {
575
	switch (com) {
576
	case PROC_ASLR_CTL:
577
		return (aslr_ctl(td, p, *(int *)data));
578
	case PROC_ASLR_STATUS:
579
		return (aslr_status(td, p, data));
512
	case PROC_SPROTECT:
580
	case PROC_SPROTECT:
513
		return (protect_set(td, p, *(int *)data));
581
		return (protect_set(td, p, *(int *)data));
514
	case PROC_REAP_ACQUIRE:
582
	case PROC_REAP_ACQUIRE:
Lines 544-549 kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) Link Here
544
	bool tree_locked;
612
	bool tree_locked;
545
613
546
	switch (com) {
614
	switch (com) {
615
	case PROC_ASLR_CTL:
616
	case PROC_ASLR_STATUS:
547
	case PROC_REAP_ACQUIRE:
617
	case PROC_REAP_ACQUIRE:
548
	case PROC_REAP_RELEASE:
618
	case PROC_REAP_RELEASE:
549
	case PROC_REAP_STATUS:
619
	case PROC_REAP_STATUS:
Lines 593-598 kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) Link Here
593
		sx_xlock(&proctree_lock);
663
		sx_xlock(&proctree_lock);
594
		tree_locked = true;
664
		tree_locked = true;
595
		break;
665
		break;
666
	case PROC_ASLR_CTL:
667
	case PROC_ASLR_STATUS:
596
	case PROC_TRACE_STATUS:
668
	case PROC_TRACE_STATUS:
597
	case PROC_TRAPCAP_STATUS:
669
	case PROC_TRAPCAP_STATUS:
598
		tree_locked = false;
670
		tree_locked = false;
(-)b/sys/sys/elf_common.h (+3 lines)
Lines 762-767 typedef struct { Link Here
762
#define	NT_FREEBSD_ARCH_TAG	3
762
#define	NT_FREEBSD_ARCH_TAG	3
763
#define	NT_FREEBSD_FEATURE_CTL	4
763
#define	NT_FREEBSD_FEATURE_CTL	4
764
764
765
/* NT_FREEBSD_FEATURE_CTL desc[0] bits */
766
#define	NT_FREEBSD_FCTL_NO_ASLR	0x00000001
767
765
/* Values for n_type.  Used in core files. */
768
/* Values for n_type.  Used in core files. */
766
#define	NT_PRSTATUS	1	/* Process status. */
769
#define	NT_PRSTATUS	1	/* Process status. */
767
#define	NT_FPREGSET	2	/* Floating point registers. */
770
#define	NT_FPREGSET	2	/* Floating point registers. */
(-)b/sys/sys/imgact.h (+1 lines)
Lines 89-94 struct image_params { Link Here
89
	u_long stack_sz;
89
	u_long stack_sz;
90
	struct ucred *newcred;		/* new credentials if changing */
90
	struct ucred *newcred;		/* new credentials if changing */
91
	bool credential_setid;		/* true if becoming setid */
91
	bool credential_setid;		/* true if becoming setid */
92
	u_int map_flags;
92
};
93
};
93
94
94
#ifdef _KERNEL
95
#ifdef _KERNEL
(-)b/sys/sys/proc.h (+3 lines)
Lines 756-761 struct proc { Link Here
756
#define	P2_AST_SU	0x00000008	/* Handles SU ast for kthreads. */
756
#define	P2_AST_SU	0x00000008	/* Handles SU ast for kthreads. */
757
#define	P2_PTRACE_FSTP	0x00000010 /* SIGSTOP from PT_ATTACH not yet handled. */
757
#define	P2_PTRACE_FSTP	0x00000010 /* SIGSTOP from PT_ATTACH not yet handled. */
758
#define	P2_TRAPCAP	0x00000020	/* SIGTRAP on ENOTCAPABLE */
758
#define	P2_TRAPCAP	0x00000020	/* SIGTRAP on ENOTCAPABLE */
759
#define	P2_ASLR_ENABLE	0x00000040	/* Force enable ASLR. */
760
#define	P2_ASLR_DISABLE	0x00000080	/* Force disable ASLR. */
761
#define	P2_ASLR_IGNSTART 0x00000100	/* Enable ASLR to consume sbrk area. */
759
762
760
/* Flags protected by proctree_lock, kept in p_treeflags. */
763
/* Flags protected by proctree_lock, kept in p_treeflags. */
761
#define	P_TREE_ORPHANED		0x00000001	/* Reparented, on orphan list */
764
#define	P_TREE_ORPHANED		0x00000001	/* Reparented, on orphan list */
(-)b/sys/sys/procctl.h (+7 lines)
Lines 53-58 Link Here
53
#define	PROC_TRAPCAP_STATUS	10	/* query trap capability status */
53
#define	PROC_TRAPCAP_STATUS	10	/* query trap capability status */
54
#define	PROC_PDEATHSIG_CTL	11	/* set parent death signal */
54
#define	PROC_PDEATHSIG_CTL	11	/* set parent death signal */
55
#define	PROC_PDEATHSIG_STATUS	12	/* get parent death signal */
55
#define	PROC_PDEATHSIG_STATUS	12	/* get parent death signal */
56
#define	PROC_ASLR_CTL		13	/* en/dis ASLR */
57
#define	PROC_ASLR_STATUS	14	/* query ASLR status */
56
58
57
/* Operations for PROC_SPROTECT (passed in integer arg). */
59
/* Operations for PROC_SPROTECT (passed in integer arg). */
58
#define	PPROT_OP(x)	((x) & 0xf)
60
#define	PPROT_OP(x)	((x) & 0xf)
Lines 116-121 struct procctl_reaper_kill { Link Here
116
#define	PROC_TRAPCAP_CTL_ENABLE		1
118
#define	PROC_TRAPCAP_CTL_ENABLE		1
117
#define	PROC_TRAPCAP_CTL_DISABLE	2
119
#define	PROC_TRAPCAP_CTL_DISABLE	2
118
120
121
#define	PROC_ASLR_FORCE_ENABLE		1
122
#define	PROC_ASLR_FORCE_DISABLE		2
123
#define	PROC_ASLR_NOFORCE		3
124
#define	PROC_ASLR_ACTIVE		0x80000000
125
119
#ifndef _KERNEL
126
#ifndef _KERNEL
120
__BEGIN_DECLS
127
__BEGIN_DECLS
121
int	procctl(idtype_t, id_t, int, void *);
128
int	procctl(idtype_t, id_t, int, void *);
(-)b/sys/sys/sysent.h (+1 lines)
Lines 144-149 struct sysentvec { Link Here
144
#define	SV_SHP		0x010000	/* Shared page. */
144
#define	SV_SHP		0x010000	/* Shared page. */
145
#define	SV_CAPSICUM	0x020000	/* Force cap_enter() on startup. */
145
#define	SV_CAPSICUM	0x020000	/* Force cap_enter() on startup. */
146
#define	SV_TIMEKEEP	0x040000	/* Shared page timehands. */
146
#define	SV_TIMEKEEP	0x040000	/* Shared page timehands. */
147
#define	SV_ASLR		0x080000	/* ASLR allowed. */
147
148
148
#define	SV_ABI_MASK	0xff
149
#define	SV_ABI_MASK	0xff
149
#define	SV_ABI_ERRNO(p, e)	((p)->p_sysent->sv_errsize <= 0 ? e :	\
150
#define	SV_ABI_ERRNO(p, e)	((p)->p_sysent->sv_errsize <= 0 ? e :	\
(-)b/sys/vm/vm_map.c (-5 / +111 lines)
Lines 801-806 _vm_map_init(vm_map_t map, pmap_t pmap, vm_offset_t min, vm_offset_t max) Link Here
801
	map->root = NULL;
801
	map->root = NULL;
802
	map->timestamp = 0;
802
	map->timestamp = 0;
803
	map->busy = 0;
803
	map->busy = 0;
804
	map->anon_loc = 0;
804
}
805
}
805
806
806
void
807
void
Lines 1480-1485 vm_map_fixed(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
1480
	return (result);
1481
	return (result);
1481
}
1482
}
1482
1483
1484
static const int aslr_pages_rnd_64[2] = {0x1000, 0x10};
1485
static const int aslr_pages_rnd_32[2] = {0x100, 0x4};
1486
1487
static int cluster_anon = 1;
1488
SYSCTL_INT(_vm, OID_AUTO, cluster_anon, CTLFLAG_RW,
1489
    &cluster_anon, 0,
1490
    "Cluster anonymous mappings");
1491
1492
static long aslr_restarts;
1493
SYSCTL_LONG(_vm, OID_AUTO, aslr_restarts, CTLFLAG_RD,
1494
    &aslr_restarts, 0,
1495
    "Number of aslr failures");
1496
1497
#define	MAP_32BIT_MAX_ADDR	((vm_offset_t)1 << 31)
1498
1483
/*
1499
/*
1484
 * Searches for the specified amount of free space in the given map with the
1500
 * Searches for the specified amount of free space in the given map with the
1485
 * specified alignment.  Performs an address-ordered, first-fit search from
1501
 * specified alignment.  Performs an address-ordered, first-fit search from
Lines 1559-1566 vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
1559
	    vm_size_t length, vm_offset_t max_addr, int find_space,
1575
	    vm_size_t length, vm_offset_t max_addr, int find_space,
1560
	    vm_prot_t prot, vm_prot_t max, int cow)
1576
	    vm_prot_t prot, vm_prot_t max, int cow)
1561
{
1577
{
1562
	vm_offset_t alignment, min_addr;
1578
	vm_offset_t alignment, curr_min_addr, min_addr;
1563
	int rv;
1579
	int gap, pidx, rv, try;
1580
	bool cluster, en_aslr, update_anon;
1564
1581
1565
	KASSERT((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0 ||
1582
	KASSERT((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0 ||
1566
	    object == NULL,
1583
	    object == NULL,
Lines 1575-1598 vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
1575
		alignment = (vm_offset_t)1 << (find_space >> 8);
1592
		alignment = (vm_offset_t)1 << (find_space >> 8);
1576
	} else
1593
	} else
1577
		alignment = 0;
1594
		alignment = 0;
1595
	en_aslr = (map->flags & MAP_ASLR) != 0;
1596
	update_anon = cluster = cluster_anon != 0 &&
1597
	    (map->flags & MAP_IS_SUB_MAP) == 0 && max_addr == 0 &&
1598
	    find_space != VMFS_NO_SPACE && object == NULL &&
1599
	    (cow & (MAP_INHERIT_SHARE | MAP_STACK_GROWS_UP |
1600
	    MAP_STACK_GROWS_DOWN)) == 0 && prot != PROT_NONE;
1601
	curr_min_addr = min_addr = *addr;
1602
	if (en_aslr && min_addr == 0 && !cluster &&
1603
	    find_space != VMFS_NO_SPACE &&
1604
	    (map->flags & MAP_ASLR_IGNSTART) != 0)
1605
		curr_min_addr = min_addr = vm_map_min(map);
1606
	try = 0;
1578
	vm_map_lock(map);
1607
	vm_map_lock(map);
1608
	if (cluster) {
1609
		curr_min_addr = map->anon_loc;
1610
		if (curr_min_addr == 0)
1611
			cluster = false;
1612
	}
1579
	if (find_space != VMFS_NO_SPACE) {
1613
	if (find_space != VMFS_NO_SPACE) {
1580
		KASSERT(find_space == VMFS_ANY_SPACE ||
1614
		KASSERT(find_space == VMFS_ANY_SPACE ||
1581
		    find_space == VMFS_OPTIMAL_SPACE ||
1615
		    find_space == VMFS_OPTIMAL_SPACE ||
1582
		    find_space == VMFS_SUPER_SPACE ||
1616
		    find_space == VMFS_SUPER_SPACE ||
1583
		    alignment != 0, ("unexpected VMFS flag"));
1617
		    alignment != 0, ("unexpected VMFS flag"));
1584
		min_addr = *addr;
1585
again:
1618
again:
1586
		if (vm_map_findspace(map, min_addr, length, addr) ||
1619
		/*
1620
		 * When creating an anonymous mapping, try clustering
1621
		 * with an existing anonymous mapping first.
1622
		 *
1623
		 * We make up to two attempts to find address space
1624
		 * for a given find_space value. The first attempt may
1625
		 * apply randomization or may cluster with an existing
1626
		 * anonymous mapping. If this first attempt fails,
1627
		 * perform a first-fit search of the available address
1628
		 * space.
1629
		 *
1630
		 * If all tries failed, and find_space is
1631
		 * VMFS_OPTIMAL_SPACE, fallback to VMFS_ANY_SPACE.
1632
		 * Again enable clustering and randomization.
1633
		 */
1634
		try++;
1635
		MPASS(try <= 2);
1636
1637
		if (try == 2) {
1638
			/*
1639
			 * Second try: we failed either to find a
1640
			 * suitable region for randomizing the
1641
			 * allocation, or to cluster with an existing
1642
			 * mapping.  Retry with free run.
1643
			 */
1644
			curr_min_addr = (map->flags & MAP_ASLR_IGNSTART) != 0 ?
1645
			    vm_map_min(map) : min_addr;
1646
			atomic_add_long(&aslr_restarts, 1);
1647
		}
1648
1649
		if (try == 1 && en_aslr && !cluster) {
1650
			/*
1651
			 * Find space for allocation, including
1652
			 * gap needed for later randomization.
1653
			 */
1654
			pidx = MAXPAGESIZES > 1 && pagesizes[1] != 0 &&
1655
			    (find_space == VMFS_SUPER_SPACE || find_space ==
1656
			    VMFS_OPTIMAL_SPACE) ? 1 : 0;
1657
			gap = vm_map_max(map) > MAP_32BIT_MAX_ADDR &&
1658
			    (max_addr == 0 || max_addr > MAP_32BIT_MAX_ADDR) ?
1659
			    aslr_pages_rnd_64[pidx] : aslr_pages_rnd_32[pidx];
1660
			if (vm_map_findspace(map, curr_min_addr, length +
1661
			    gap * pagesizes[pidx], addr) ||
1662
			    (max_addr != 0 && *addr + length > max_addr))
1663
				goto again;
1664
			/* And randomize the start address. */
1665
			*addr += (arc4random() % gap) * pagesizes[pidx];
1666
		} else if (vm_map_findspace(map, curr_min_addr, length, addr) ||
1587
		    (max_addr != 0 && *addr + length > max_addr)) {
1667
		    (max_addr != 0 && *addr + length > max_addr)) {
1668
			if (cluster) {
1669
				cluster = false;
1670
				MPASS(try == 1);
1671
				goto again;
1672
			}
1588
			rv = KERN_NO_SPACE;
1673
			rv = KERN_NO_SPACE;
1589
			goto done;
1674
			goto done;
1590
		}
1675
		}
1676
1591
		if (find_space != VMFS_ANY_SPACE &&
1677
		if (find_space != VMFS_ANY_SPACE &&
1592
		    (rv = vm_map_alignspace(map, object, offset, addr, length,
1678
		    (rv = vm_map_alignspace(map, object, offset, addr, length,
1593
		    max_addr, alignment)) != KERN_SUCCESS) {
1679
		    max_addr, alignment)) != KERN_SUCCESS) {
1594
			if (find_space == VMFS_OPTIMAL_SPACE) {
1680
			if (find_space == VMFS_OPTIMAL_SPACE) {
1595
				find_space = VMFS_ANY_SPACE;
1681
				find_space = VMFS_ANY_SPACE;
1682
				curr_min_addr = min_addr;
1683
				cluster = update_anon;
1684
				try = 0;
1596
				goto again;
1685
				goto again;
1597
			}
1686
			}
1598
			goto done;
1687
			goto done;
Lines 1613-1618 vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, Link Here
1613
		rv = vm_map_insert(map, object, offset, *addr, *addr + length,
1702
		rv = vm_map_insert(map, object, offset, *addr, *addr + length,
1614
		    prot, max, cow);
1703
		    prot, max, cow);
1615
	}
1704
	}
1705
	if (rv == KERN_SUCCESS && update_anon)
1706
		map->anon_loc = *addr + length;
1616
done:
1707
done:
1617
	vm_map_unlock(map);
1708
	vm_map_unlock(map);
1618
	return (rv);
1709
	return (rv);
Lines 1922-1928 vm_map_submap( Link Here
1922
	vm_map_t submap)
2013
	vm_map_t submap)
1923
{
2014
{
1924
	vm_map_entry_t entry;
2015
	vm_map_entry_t entry;
1925
	int result = KERN_INVALID_ARGUMENT;
2016
	int result;
2017
2018
	result = KERN_INVALID_ARGUMENT;
2019
2020
	vm_map_lock(submap);
2021
	submap->flags |= MAP_IS_SUB_MAP;
2022
	vm_map_unlock(submap);
1926
2023
1927
	vm_map_lock(map);
2024
	vm_map_lock(map);
1928
2025
Lines 1944-1949 vm_map_submap( Link Here
1944
	}
2041
	}
1945
	vm_map_unlock(map);
2042
	vm_map_unlock(map);
1946
2043
2044
	if (result != KERN_SUCCESS) {
2045
		vm_map_lock(submap);
2046
		submap->flags &= ~MAP_IS_SUB_MAP;
2047
		vm_map_unlock(submap);
2048
	}
1947
	return (result);
2049
	return (result);
1948
}
2050
}
1949
2051
Lines 3170-3175 vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end) Link Here
3170
		    entry->object.vm_object != NULL)
3272
		    entry->object.vm_object != NULL)
3171
			pmap_remove(map->pmap, entry->start, entry->end);
3273
			pmap_remove(map->pmap, entry->start, entry->end);
3172
3274
3275
		if (entry->end == map->anon_loc)
3276
			map->anon_loc = entry->start;
3277
3173
		/*
3278
		/*
3174
		 * Delete the entry only after removing all pmap
3279
		 * Delete the entry only after removing all pmap
3175
		 * entries pointing to its pages.  (Otherwise, its
3280
		 * entries pointing to its pages.  (Otherwise, its
Lines 3443-3448 vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge) Link Here
3443
	locked = vm_map_trylock(new_map); /* trylock to silence WITNESS */
3548
	locked = vm_map_trylock(new_map); /* trylock to silence WITNESS */
3444
	KASSERT(locked, ("vmspace_fork: lock failed"));
3549
	KASSERT(locked, ("vmspace_fork: lock failed"));
3445
3550
3551
	new_map->anon_loc = old_map->anon_loc;
3446
	old_entry = old_map->header.next;
3552
	old_entry = old_map->header.next;
3447
3553
3448
	while (old_entry != &old_map->header) {
3554
	while (old_entry != &old_map->header) {
(-)b/sys/vm/vm_map.h (+4 lines)
Lines 202-207 struct vm_map { Link Here
202
	vm_flags_t flags;		/* flags for this vm_map */
202
	vm_flags_t flags;		/* flags for this vm_map */
203
	vm_map_entry_t root;		/* Root of a binary search tree */
203
	vm_map_entry_t root;		/* Root of a binary search tree */
204
	pmap_t pmap;			/* (c) Physical map */
204
	pmap_t pmap;			/* (c) Physical map */
205
	vm_offset_t anon_loc;
205
	int busy;
206
	int busy;
206
};
207
};
207
208
Lines 210-215 struct vm_map { Link Here
210
 */
211
 */
211
#define MAP_WIREFUTURE		0x01	/* wire all future pages */
212
#define MAP_WIREFUTURE		0x01	/* wire all future pages */
212
#define	MAP_BUSY_WAKEUP		0x02
213
#define	MAP_BUSY_WAKEUP		0x02
214
#define	MAP_IS_SUB_MAP		0x04	/* has parent */
215
#define	MAP_ASLR		0x08	/* enabled ASLR */
216
#define	MAP_ASLR_IGNSTART	0x10
213
217
214
#ifdef	_KERNEL
218
#ifdef	_KERNEL
215
#if defined(KLD_MODULE) && !defined(KLD_TIED)
219
#if defined(KLD_MODULE) && !defined(KLD_TIED)
(-)b/usr.bin/proccontrol/proccontrol.c (-2 / +30 lines)
Lines 39-44 __FBSDID("$FreeBSD$"); Link Here
39
#include <unistd.h>
39
#include <unistd.h>
40
40
41
enum {
41
enum {
42
	MODE_ASLR,
42
	MODE_INVALID,
43
	MODE_INVALID,
43
	MODE_TRACE,
44
	MODE_TRACE,
44
	MODE_TRAPCAP,
45
	MODE_TRAPCAP,
Lines 62-68 static void __dead2 Link Here
62
usage(void)
63
usage(void)
63
{
64
{
64
65
65
	fprintf(stderr, "Usage: proccontrol -m (trace|trapcap) [-q] "
66
	fprintf(stderr, "Usage: proccontrol -m (aslr|trace|trapcap) [-q] "
66
	    "[-s (enable|disable)] [-p pid | command]\n");
67
	    "[-s (enable|disable)] [-p pid | command]\n");
67
	exit(1);
68
	exit(1);
68
}
69
}
Lines 81-87 main(int argc, char *argv[]) Link Here
81
	while ((ch = getopt(argc, argv, "m:qs:p:")) != -1) {
82
	while ((ch = getopt(argc, argv, "m:qs:p:")) != -1) {
82
		switch (ch) {
83
		switch (ch) {
83
		case 'm':
84
		case 'm':
84
			if (strcmp(optarg, "trace") == 0)
85
			if (strcmp(optarg, "aslr") == 0)
86
				mode = MODE_ASLR;
87
			else if (strcmp(optarg, "trace") == 0)
85
				mode = MODE_TRACE;
88
				mode = MODE_TRACE;
86
			else if (strcmp(optarg, "trapcap") == 0)
89
			else if (strcmp(optarg, "trapcap") == 0)
87
				mode = MODE_TRAPCAP;
90
				mode = MODE_TRAPCAP;
Lines 121-126 main(int argc, char *argv[]) Link Here
121
124
122
	if (query) {
125
	if (query) {
123
		switch (mode) {
126
		switch (mode) {
127
		case MODE_ASLR:
128
			error = procctl(P_PID, pid, PROC_ASLR_STATUS, &arg);
129
			break;
124
		case MODE_TRACE:
130
		case MODE_TRACE:
125
			error = procctl(P_PID, pid, PROC_TRACE_STATUS, &arg);
131
			error = procctl(P_PID, pid, PROC_TRACE_STATUS, &arg);
126
			break;
132
			break;
Lines 134-139 main(int argc, char *argv[]) Link Here
134
		if (error != 0)
140
		if (error != 0)
135
			err(1, "procctl status");
141
			err(1, "procctl status");
136
		switch (mode) {
142
		switch (mode) {
143
		case MODE_ASLR:
144
			switch (arg & ~PROC_ASLR_ACTIVE) {
145
			case PROC_ASLR_FORCE_ENABLE:
146
				printf("force enabled");
147
				break;
148
			case PROC_ASLR_FORCE_DISABLE:
149
				printf("force disabled");
150
				break;
151
			case PROC_ASLR_NOFORCE:
152
				printf("not forced");
153
				break;
154
			}
155
			if ((arg & PROC_ASLR_ACTIVE) != 0)
156
				printf(", active\n");
157
			else
158
				printf(", not active\n");
159
			break;
137
		case MODE_TRACE:
160
		case MODE_TRACE:
138
			if (arg == -1)
161
			if (arg == -1)
139
				printf("disabled\n");
162
				printf("disabled\n");
Lines 155-160 main(int argc, char *argv[]) Link Here
155
		}
178
		}
156
	} else {
179
	} else {
157
		switch (mode) {
180
		switch (mode) {
181
		case MODE_ASLR:
182
			arg = enable ? PROC_ASLR_FORCE_ENABLE :
183
			    PROC_ASLR_FORCE_DISABLE;
184
			error = procctl(P_PID, pid, PROC_ASLR_CTL, &arg);
185
			break;
158
		case MODE_TRACE:
186
		case MODE_TRACE:
159
			arg = enable ? PROC_TRACE_CTL_ENABLE :
187
			arg = enable ? PROC_TRACE_CTL_ENABLE :
160
			    PROC_TRACE_CTL_DISABLE;
188
			    PROC_TRACE_CTL_DISABLE;

Return to bug 208580