From: John Marino Date: Thu, 19 May 2011 22:33:16 +0000 (+0200) Subject: kernel ELF: Improve OS Release Date handling X-Git-Tag: v2.12.0~589 X-Git-Url: https://gitweb.dragonflybsd.org/~nant/dragonfly.git/commitdiff_plain/f2000797b7851b6d16f7191e0c8ff011ffb15265 kernel ELF: Improve OS Release Date handling This brings in FreeBSD's method of having separate OS Release Date (osreldate) handling for each brand. Previously the decoding method was hardcoded for *BSD, which meant it was broken for the Linux brand. Now all supported brands (DragonFly, FreeBSD, Linux) are retrieving the osreldate values correctly. --- diff --git a/sys/emulation/linux/i386/linux_sysvec.c b/sys/emulation/linux/i386/linux_sysvec.c index 8f6f3d36bc..f819797c49 100644 --- a/sys/emulation/linux/i386/linux_sysvec.c +++ b/sys/emulation/linux/i386/linux_sysvec.c @@ -26,7 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/i386/linux/linux_sysvec.c,v 1.55.2.9 2002/01/12 11:03:30 bde Exp $ - * $DragonFly: src/sys/emulation/linux/i386/linux_sysvec.c,v 1.31 2008/04/21 15:47:53 dillon Exp $ */ /* XXX we use functions that might not exist. */ @@ -98,6 +97,7 @@ static void linux_prepsyscall (struct trapframe *tf, int *args, u_int *code, caddr_t *params); static void linux_sendsig (sig_t catcher, int sig, sigset_t *mask, u_long code); +static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel); static eventhandler_tag linux_exec_tag; static eventhandler_tag linux_exit_tag; @@ -830,21 +830,47 @@ struct sysentvec elf_linux_sysvec = { static const char GNU_ABI_VENDOR[] = "GNU"; static const char SUSE_ABI_VENDOR[] = "SuSE"; +static int GNULINUX_ABI_DESC = 0; + +static boolean_t +linux_trans_osrel(const Elf_Note *note, int32_t *osrel) +{ + const Elf32_Word *desc; + uintptr_t p; + + p = (uintptr_t)(note + 1); + p += roundup2(note->n_namesz, sizeof(Elf32_Addr)); + + desc = (const Elf32_Word *)p; + if (desc[0] != GNULINUX_ABI_DESC) + return (FALSE); + /* + * For Linux we encode osrel as follows: + * VVVMMMIII (version, major, minor) + */ + *osrel = desc[1] * 1000000 + + desc[2] * 1000 + + desc[3]; + + return (TRUE); +} static Elf_Brandnote linux32_generic_brandnote = { - .hdr.n_namesz = sizeof(GNU_ABI_VENDOR), - .hdr.n_descsz = 16, - .hdr.n_type = 1, - .vendor = GNU_ABI_VENDOR, - .flags = 0, + .hdr.n_namesz = sizeof(GNU_ABI_VENDOR), + .hdr.n_descsz = 16, + .hdr.n_type = 1, + .vendor = GNU_ABI_VENDOR, + .flags = BN_TRANSLATE_OSREL, + .trans_osrel = linux_trans_osrel, }; static Elf_Brandnote linux32_suse_brandnote = { - .hdr.n_namesz = sizeof(SUSE_ABI_VENDOR), - .hdr.n_descsz = 16, - .hdr.n_type = 1, - .vendor = SUSE_ABI_VENDOR, - .flags = 0, + .hdr.n_namesz = sizeof(SUSE_ABI_VENDOR), + .hdr.n_descsz = 16, + .hdr.n_type = 1, + .vendor = SUSE_ABI_VENDOR, + .flags = BN_TRANSLATE_OSREL, + .trans_osrel = linux_trans_osrel, }; static Elf32_Brandinfo linux32_brand = { diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 4915b31efa..b805836644 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -83,6 +83,8 @@ static int __elfN(load_section)(struct proc *p, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot); static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp); +static boolean_t __elfN(bsd_trans_osrel)(const Elf_Note *note, + int32_t *osrel); static boolean_t __elfN(check_note)(struct image_params *imgp, Elf_Brandnote *checknote, int32_t *osrel); static boolean_t check_PT_NOTE(struct image_params *imgp, @@ -118,7 +120,8 @@ Elf_Brandnote __elfN(dragonfly_brandnote) = { .hdr.n_descsz = sizeof(int32_t), .hdr.n_type = 1, .vendor = DRAGONFLY_ABI_VENDOR, - .flags = BN_CAN_FETCH_OSREL, + .flags = BN_TRANSLATE_OSREL, + .trans_osrel = __elfN(bsd_trans_osrel), }; Elf_Brandnote __elfN(freebsd_brandnote) = { @@ -126,7 +129,8 @@ Elf_Brandnote __elfN(freebsd_brandnote) = { .hdr.n_descsz = sizeof(int32_t), .hdr.n_type = 1, .vendor = FREEBSD_ABI_VENDOR, - .flags = BN_CAN_FETCH_OSREL, + .flags = BN_TRANSLATE_OSREL, + .trans_osrel = __elfN(bsd_trans_osrel), }; int @@ -1724,11 +1728,9 @@ check_PT_NOTE(struct image_params *imgp, Elf_Brandnote *checknote, && (strncmp(checknote->vendor, note_name, checknote->hdr.n_namesz) == 0)) { /* Fetch osreldata from ABI.note-tag */ - if ((checknote->flags & BN_CAN_FETCH_OSREL) != 0 && - osrel != NULL) - *osrel = *(const int32_t *) (note_name + - roundup2(checknote->hdr.n_namesz, - sizeof(Elf32_Addr))); + if ((checknote->flags & BN_TRANSLATE_OSREL) != 0 && + checknote->trans_osrel != NULL) + return (checknote->trans_osrel(note, osrel)); found = TRUE; break; } @@ -1797,6 +1799,18 @@ extract_interpreter(struct image_params *imgp, const Elf_Phdr *pinterpreter, return (result_success); } +static boolean_t +__elfN(bsd_trans_osrel)(const Elf_Note *note, int32_t *osrel) +{ + uintptr_t p; + + p = (uintptr_t)(note + 1); + p += roundup2(note->n_namesz, sizeof(Elf32_Addr)); + *osrel = *(const int32_t *)(p); + + return (TRUE); +} + /* * Tell kern_execve.c about it, with a little help from the linker. */ diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h index ad31c49b48..dd4a0bca32 100644 --- a/sys/sys/imgact_elf.h +++ b/sys/sys/imgact_elf.h @@ -61,6 +61,7 @@ typedef struct { Elf_Note hdr; const char * vendor; int flags; + boolean_t (*trans_osrel)(const Elf_Note *, int32_t *); } Elf_Brandnote; typedef struct { @@ -82,7 +83,8 @@ __ElfType(Brandinfo); #define BI_CAN_EXEC_DYN 0x0001 #define BI_BRAND_NOTE 0x0002 /* May have note.ABI-tag section. */ #define BI_BRAND_NOTE_MANDATORY 0x0004 /* Must have note.ABI-tag section. */ -#define BN_CAN_FETCH_OSREL 0x0001 +#define BN_CAN_FETCH_OSREL 0x0001 /* No longer used */ +#define BN_TRANSLATE_OSREL 0x0002 /* New osreldate function pointer */ int __elfN(brand_inuse) (Elf_Brandinfo *entry); int __elfN(insert_brand_entry) (Elf_Brandinfo *entry);