Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c +++ sys/kern/imgact_elf.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,10 @@ static int __elfN(load_section)(struct image_params *imgp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot, size_t pagesize); +static int __CONCAT(fat, __elfN(extract_record))(struct vnode *vp, + const FatElf_FEhdr *fhdr, FatElf_record *record); +static int __CONCAT(fat, __elfN(elfpart_extract))(struct image_params *imgp, + Elf_Ehdr *elf_part); static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp); static boolean_t __elfN(freebsd_trans_osrel)(const Elf_Note *note, int32_t *osrel); @@ -748,10 +753,68 @@ } static int +__CONCAT(fat, __elfN(extract_record))(struct vnode *vp, + const FatElf_FEhdr *fhdr, FatElf_record *record) +{ + int i; + struct thread *td = curthread; + + for (i = 0; i < le32toh(fhdr->fe_nrecords); ++i) { + int error = vn_rdwr(UIO_READ, vp, record, sizeof(*record), sizeof(*fhdr) + + sizeof(*record) * i, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, + NOCRED, NULL, td); + if (error != 0) { + printf("vn_rdwr error: %d\n", error); + return error; + } + + Elf_Ehdr hdr = { .e_ident[EI_CLASS] = record->ei_class, + .e_ident[EI_DATA] = record->ei_data, + .e_ident[EI_VERSION] = record->ei_version, + .e_version = record->e_version, .e_machine = record->e_machine, + .e_phentsize = record->e_phentsize }; + + if (__elfN(check_header)(hdr) == 0 && (hdr->e_type == ET_EXEC + || hdr->e_type == ET_DYN)) + break; + } + + return (i >= le32toh(fhdr->fe_nrecords)) ? ENOEXEC : 0; +} + +static int +__CONCAT(fat, __elfN(elfpart_extract))(struct image_params *imgp, + Elf_Ehdr *elf_part) +{ + struct vnode *vp; + struct thread *td; + const FatElf_FEhdr *header; + FatElf_record record; + int error = 0; /* default value, used to determine errors in conditions below */ + + vp = imgp->vp; + td = curthread; + header = (const FatElf_FEhdr *) imgp->image_header; + + error = fatelf_extract_record(vp, header, &record); + if (error != 0) { + printf("fatelf_extract_record error: %d\n", error); + return error; + } + + error = vn_rdwr(UIO_READ, vp, elf_part, sizeof(*elf_part), + record->r_offset, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, + NULL, td); + + return error; +} + +static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) { struct thread *td; const Elf_Ehdr *hdr; + Elf_Ehdr elf_part; const Elf_Phdr *phdr; Elf_Auxargs *elf_auxargs; struct vmspace *vmspace; @@ -765,7 +828,16 @@ int32_t osrel; int error, i, n, interp_name_len, have_interp; - hdr = (const Elf_Ehdr *)imgp->image_header; + if (IS_FATELF((const FatElf_FEhdr *)imgp->image_header)) { + error = fatelf_elfpart_extract(imgp, &elf_part); + if (error != 0) { + printf("Bad FatElf format, error = %d", error); + return ENOEXEC; + } + hdr = (const Elf_Ehdr *) &elf_part; + } else { + hdr = (const Elf_Ehdr *)imgp->image_header; + } /* * Do we have a valid ELF header ? Index: sys/sys/elf_fat.h =================================================================== --- sys/sys/elf_fat.h +++ sys/sys/elf_fat.h @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2016 Mahdi Mokhtari. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_FAT_H_ +#define _SYS_ELF_FAT_H_ + +#include +#include +#include +#include +#include + +/* Values for the magic number bytes. */ +#define FATELF_MAG0 0xFa +#define FATELF_MAG1 't' +#define FATELF_MAG2 0x0E +#define FATELF_MAG3 0x1f +#define FATELF_MAGIC "\xFat\x0E\x1f" /* magic string */ +#define FATELF_MAG_LEN 4 /* magic string size */ + +#define IS_FATELF(fehdr) ((fehdr).fe_magic[EI_MAG0] == FATELF_MAG0 && \ + (fehdr).fe_magic[EI_MAG1] == FATELF_MAG1 && \ + (fehdr).fe_magic[EI_MAG2] == FATELF_MAG2 && \ + (fehdr).fe_magic[EI_MAG3] == FATELF_MAG3) + +typedef struct { + unsigned char fe_magic[4]; /* always SHOULD BE FATELF_MAGIC */ + uint16_t fe_version; /* currently is 0 for FreeBSD */ + uint16_t fe_nrecords; +} FatElf_FEhdr; + +typedef struct { + unsigned char ei_class; + unsigned char ei_data; + unsigned char ei_version; + unsigned char ei_osabi; /* XXX actually NOT used, just for the sake of alignment XXX */ + + uint32_t e_version; /* ELF format version. */ + + uint16_t e_machine; /* Machine architecture. */ + uint16_t e_phentsize; /* Size of program header entry. */ + + uint64_t r_offset; + uint64_t r_size; +} FatElf_record; + +#endif /* !_SYS_ELF_FAT_H_ */