Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/imgact_elf.c
Show First 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | static int __elfN(load_file)(struct proc *p, const char *file, u_long *addr, | ||||
u_long *entry); | u_long *entry); | ||||
static int __elfN(load_section)(struct image_params *imgp, vm_ooffset_t offset, | static int __elfN(load_section)(struct image_params *imgp, vm_ooffset_t offset, | ||||
caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot); | caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot); | ||||
static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp); | static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp); | ||||
static bool __elfN(freebsd_trans_osrel)(const Elf_Note *note, | static bool __elfN(freebsd_trans_osrel)(const Elf_Note *note, | ||||
int32_t *osrel); | int32_t *osrel); | ||||
static bool kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel); | static bool kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel); | ||||
static boolean_t __elfN(check_note)(struct image_params *imgp, | static boolean_t __elfN(check_note)(struct image_params *imgp, | ||||
Elf_Brandnote *checknote, int32_t *osrel, uint32_t *fctl0); | Elf_Brandnote *checknote, int32_t *osrel, boolean_t *has_fctl0, | ||||
uint32_t *fctl0); | |||||
static vm_prot_t __elfN(trans_prot)(Elf_Word); | static vm_prot_t __elfN(trans_prot)(Elf_Word); | ||||
static Elf_Word __elfN(untrans_prot)(vm_prot_t); | static Elf_Word __elfN(untrans_prot)(vm_prot_t); | ||||
SYSCTL_NODE(_kern, OID_AUTO, __CONCAT(elf, __ELF_WORD_SIZE), | SYSCTL_NODE(_kern, OID_AUTO, __CONCAT(elf, __ELF_WORD_SIZE), | ||||
CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | ||||
""); | ""); | ||||
#define CORE_BUF_SIZE (16 * 1024) | #define CORE_BUF_SIZE (16 * 1024) | ||||
▲ Show 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static Elf_Brandinfo * | static Elf_Brandinfo * | ||||
__elfN(get_brandinfo)(struct image_params *imgp, const char *interp, | __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, | ||||
int32_t *osrel, uint32_t *fctl0) | int32_t *osrel, uint32_t *fctl0) | ||||
{ | { | ||||
const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; | const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; | ||||
Elf_Brandinfo *bi, *bi_m; | Elf_Brandinfo *bi, *bi_m; | ||||
boolean_t ret; | boolean_t ret, has_fctl0; | ||||
int i, interp_name_len; | int i, interp_name_len; | ||||
interp_name_len = interp != NULL ? strlen(interp) + 1 : 0; | interp_name_len = interp != NULL ? strlen(interp) + 1 : 0; | ||||
/* | /* | ||||
* We support four types of branding -- (1) the ELF EI_OSABI field | * We support four types of branding -- (1) the ELF EI_OSABI field | ||||
* that SCO added to the ELF spec, (2) FreeBSD 3.x's traditional string | * that SCO added to the ELF spec, (2) FreeBSD 3.x's traditional string | ||||
* branding w/in the ELF header, (3) path of the `interp_path' | * branding w/in the ELF header, (3) path of the `interp_path' | ||||
* field, and (4) the ".note.ABI-tag" ELF section. | * field, and (4) the ".note.ABI-tag" ELF section. | ||||
*/ | */ | ||||
/* Look for an ".note.ABI-tag" ELF section */ | /* Look for an ".note.ABI-tag" ELF section */ | ||||
bi_m = NULL; | bi_m = NULL; | ||||
for (i = 0; i < MAX_BRANDS; i++) { | for (i = 0; i < MAX_BRANDS; i++) { | ||||
bi = elf_brand_list[i]; | bi = elf_brand_list[i]; | ||||
if (bi == NULL) | if (bi == NULL) | ||||
continue; | continue; | ||||
if (interp != NULL && (bi->flags & BI_BRAND_ONLY_STATIC) != 0) | if (interp != NULL && (bi->flags & BI_BRAND_ONLY_STATIC) != 0) | ||||
continue; | continue; | ||||
if (hdr->e_machine == bi->machine && (bi->flags & | if (hdr->e_machine == bi->machine && (bi->flags & | ||||
(BI_BRAND_NOTE|BI_BRAND_NOTE_MANDATORY)) != 0) { | (BI_BRAND_NOTE|BI_BRAND_NOTE_MANDATORY)) != 0) { | ||||
has_fctl0 = false; | |||||
*fctl0 = 0; | |||||
*osrel = 0; | |||||
ret = __elfN(check_note)(imgp, bi->brand_note, osrel, | ret = __elfN(check_note)(imgp, bi->brand_note, osrel, | ||||
fctl0); | &has_fctl0, fctl0); | ||||
/* Give brand a chance to veto check_note's guess */ | /* Give brand a chance to veto check_note's guess */ | ||||
if (ret && bi->header_supported) | if (ret && bi->header_supported) { | ||||
ret = bi->header_supported(imgp); | ret = bi->header_supported(imgp, osrel, | ||||
has_fctl0 ? fctl0 : NULL); | |||||
} | |||||
/* | /* | ||||
* If note checker claimed the binary, but the | * If note checker claimed the binary, but the | ||||
* interpreter path in the image does not | * interpreter path in the image does not | ||||
* match default one for the brand, try to | * match default one for the brand, try to | ||||
* search for other brands with the same | * search for other brands with the same | ||||
* interpreter. Either there is better brand | * interpreter. Either there is better brand | ||||
* with the right interpreter, or, failing | * with the right interpreter, or, failing | ||||
* this, we return first brand which accepted | * this, we return first brand which accepted | ||||
Show All 22 Lines | if (bi == NULL || (bi->flags & BI_BRAND_NOTE_MANDATORY) != 0 || | ||||
continue; | continue; | ||||
if (hdr->e_machine == bi->machine && | if (hdr->e_machine == bi->machine && | ||||
(hdr->e_ident[EI_OSABI] == bi->brand || | (hdr->e_ident[EI_OSABI] == bi->brand || | ||||
(bi->compat_3_brand != NULL && | (bi->compat_3_brand != NULL && | ||||
strcmp((const char *)&hdr->e_ident[OLD_EI_BRAND], | strcmp((const char *)&hdr->e_ident[OLD_EI_BRAND], | ||||
bi->compat_3_brand) == 0))) { | bi->compat_3_brand) == 0))) { | ||||
/* Looks good, but give brand a chance to veto */ | /* Looks good, but give brand a chance to veto */ | ||||
if (bi->header_supported == NULL || | if (bi->header_supported == NULL || | ||||
bi->header_supported(imgp)) { | bi->header_supported(imgp, NULL, NULL)) { | ||||
/* | /* | ||||
* Again, prefer strictly matching | * Again, prefer strictly matching | ||||
* interpreter path. | * interpreter path. | ||||
*/ | */ | ||||
if (interp_name_len == 0 && | if (interp_name_len == 0 && | ||||
bi->interp_path == NULL) | bi->interp_path == NULL) | ||||
return (bi); | return (bi); | ||||
if (bi->interp_path != NULL && | if (bi->interp_path != NULL && | ||||
Show All 11 Lines | __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, | ||||
/* No known brand, see if the header is recognized by any brand */ | /* No known brand, see if the header is recognized by any brand */ | ||||
for (i = 0; i < MAX_BRANDS; i++) { | for (i = 0; i < MAX_BRANDS; i++) { | ||||
bi = elf_brand_list[i]; | bi = elf_brand_list[i]; | ||||
if (bi == NULL || bi->flags & BI_BRAND_NOTE_MANDATORY || | if (bi == NULL || bi->flags & BI_BRAND_NOTE_MANDATORY || | ||||
bi->header_supported == NULL) | bi->header_supported == NULL) | ||||
continue; | continue; | ||||
if (hdr->e_machine == bi->machine) { | if (hdr->e_machine == bi->machine) { | ||||
ret = bi->header_supported(imgp); | ret = bi->header_supported(imgp, NULL, NULL); | ||||
if (ret) | if (ret) | ||||
return (bi); | return (bi); | ||||
} | } | ||||
} | } | ||||
/* Lacking a known brand, search for a recognized interpreter. */ | /* Lacking a known brand, search for a recognized interpreter. */ | ||||
if (interp != NULL) { | if (interp != NULL) { | ||||
for (i = 0; i < MAX_BRANDS; i++) { | for (i = 0; i < MAX_BRANDS; i++) { | ||||
bi = elf_brand_list[i]; | bi = elf_brand_list[i]; | ||||
if (bi == NULL || (bi->flags & | if (bi == NULL || (bi->flags & | ||||
(BI_BRAND_NOTE_MANDATORY | BI_BRAND_ONLY_STATIC)) | (BI_BRAND_NOTE_MANDATORY | BI_BRAND_ONLY_STATIC)) | ||||
!= 0) | != 0) | ||||
continue; | continue; | ||||
if (hdr->e_machine == bi->machine && | if (hdr->e_machine == bi->machine && | ||||
bi->interp_path != NULL && | bi->interp_path != NULL && | ||||
/* ELF image p_filesz includes terminating zero */ | /* ELF image p_filesz includes terminating zero */ | ||||
strlen(bi->interp_path) + 1 == interp_name_len && | strlen(bi->interp_path) + 1 == interp_name_len && | ||||
strncmp(interp, bi->interp_path, interp_name_len) | strncmp(interp, bi->interp_path, interp_name_len) | ||||
== 0 && (bi->header_supported == NULL || | == 0 && (bi->header_supported == NULL || | ||||
bi->header_supported(imgp))) | bi->header_supported(imgp, NULL, NULL))) | ||||
return (bi); | return (bi); | ||||
} | } | ||||
} | } | ||||
/* Lacking a recognized interpreter, try the default brand */ | /* Lacking a recognized interpreter, try the default brand */ | ||||
for (i = 0; i < MAX_BRANDS; i++) { | for (i = 0; i < MAX_BRANDS; i++) { | ||||
bi = elf_brand_list[i]; | bi = elf_brand_list[i]; | ||||
if (bi == NULL || (bi->flags & BI_BRAND_NOTE_MANDATORY) != 0 || | if (bi == NULL || (bi->flags & BI_BRAND_NOTE_MANDATORY) != 0 || | ||||
(interp != NULL && (bi->flags & BI_BRAND_ONLY_STATIC) != 0)) | (interp != NULL && (bi->flags & BI_BRAND_ONLY_STATIC) != 0)) | ||||
continue; | continue; | ||||
if (hdr->e_machine == bi->machine && | if (hdr->e_machine == bi->machine && | ||||
__elfN(fallback_brand) == bi->brand && | __elfN(fallback_brand) == bi->brand && | ||||
(bi->header_supported == NULL || | (bi->header_supported == NULL || | ||||
bi->header_supported(imgp))) | bi->header_supported(imgp, NULL, NULL))) | ||||
return (bi); | return (bi); | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
static int | static int | ||||
__elfN(check_header)(const Elf_Ehdr *hdr) | __elfN(check_header)(const Elf_Ehdr *hdr) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 2,204 Lines • ▼ Show 20 Lines | |||||
static Elf_Note fctl_note = { | static Elf_Note fctl_note = { | ||||
.n_namesz = sizeof(FREEBSD_ABI_VENDOR), | .n_namesz = sizeof(FREEBSD_ABI_VENDOR), | ||||
.n_descsz = sizeof(uint32_t), | .n_descsz = sizeof(uint32_t), | ||||
.n_type = NT_FREEBSD_FEATURE_CTL, | .n_type = NT_FREEBSD_FEATURE_CTL, | ||||
}; | }; | ||||
struct fctl_cb_arg { | struct fctl_cb_arg { | ||||
boolean_t *has_fctl0; | |||||
uint32_t *fctl0; | uint32_t *fctl0; | ||||
}; | }; | ||||
static boolean_t | static boolean_t | ||||
note_fctl_cb(const Elf_Note *note, void *arg0, boolean_t *res) | note_fctl_cb(const Elf_Note *note, void *arg0, boolean_t *res) | ||||
{ | { | ||||
struct fctl_cb_arg *arg; | struct fctl_cb_arg *arg; | ||||
const Elf32_Word *desc; | const Elf32_Word *desc; | ||||
uintptr_t p; | uintptr_t p; | ||||
arg = arg0; | arg = arg0; | ||||
p = (uintptr_t)(note + 1); | p = (uintptr_t)(note + 1); | ||||
p += roundup2(note->n_namesz, ELF_NOTE_ROUNDSIZE); | p += roundup2(note->n_namesz, ELF_NOTE_ROUNDSIZE); | ||||
desc = (const Elf32_Word *)p; | desc = (const Elf32_Word *)p; | ||||
*arg->has_fctl0 = TRUE; | |||||
*arg->fctl0 = desc[0]; | *arg->fctl0 = desc[0]; | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
/* | /* | ||||
* Try to find the appropriate ABI-note section for checknote, fetch | * Try to find the appropriate ABI-note section for checknote, fetch | ||||
* the osreldate and feature control flags for binary from the ELF | * the osreldate and feature control flags for binary from the ELF | ||||
* OSABI-note. Only the first page of the image is searched, the same | * OSABI-note. Only the first page of the image is searched, the same | ||||
* as for headers. | * as for headers. | ||||
*/ | */ | ||||
static boolean_t | static boolean_t | ||||
__elfN(check_note)(struct image_params *imgp, Elf_Brandnote *brandnote, | __elfN(check_note)(struct image_params *imgp, Elf_Brandnote *brandnote, | ||||
int32_t *osrel, uint32_t *fctl0) | int32_t *osrel, boolean_t *has_fctl0, uint32_t *fctl0) | ||||
{ | { | ||||
const Elf_Phdr *phdr; | const Elf_Phdr *phdr; | ||||
const Elf_Ehdr *hdr; | const Elf_Ehdr *hdr; | ||||
struct brandnote_cb_arg b_arg; | struct brandnote_cb_arg b_arg; | ||||
struct fctl_cb_arg f_arg; | struct fctl_cb_arg f_arg; | ||||
int i, j; | int i, j; | ||||
hdr = (const Elf_Ehdr *)imgp->image_header; | hdr = (const Elf_Ehdr *)imgp->image_header; | ||||
phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); | phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); | ||||
b_arg.brandnote = brandnote; | b_arg.brandnote = brandnote; | ||||
b_arg.osrel = osrel; | b_arg.osrel = osrel; | ||||
f_arg.has_fctl0 = has_fctl0; | |||||
f_arg.fctl0 = fctl0; | f_arg.fctl0 = fctl0; | ||||
for (i = 0; i < hdr->e_phnum; i++) { | for (i = 0; i < hdr->e_phnum; i++) { | ||||
if (phdr[i].p_type == PT_NOTE && __elfN(parse_notes)(imgp, | if (phdr[i].p_type == PT_NOTE && __elfN(parse_notes)(imgp, | ||||
&brandnote->hdr, brandnote->vendor, &phdr[i], brandnote_cb, | &brandnote->hdr, brandnote->vendor, &phdr[i], brandnote_cb, | ||||
&b_arg)) { | &b_arg)) { | ||||
for (j = 0; j < hdr->e_phnum; j++) { | for (j = 0; j < hdr->e_phnum; j++) { | ||||
if (phdr[j].p_type == PT_NOTE && | if (phdr[j].p_type == PT_NOTE && | ||||
▲ Show 20 Lines • Show All 74 Lines • Show Last 20 Lines |