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); |