diff options
-rw-r--r-- | sys/kern/imgact_elf.c | 46 | ||||
-rw-r--r-- | sys/kern/init_main.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 1 | ||||
-rw-r--r-- | sys/kern/kern_mib.c | 1 | ||||
-rw-r--r-- | sys/sys/proc.h | 2 | ||||
-rw-r--r-- | sys/sys/systm.h | 1 |
6 files changed, 49 insertions, 5 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index ab6ab03..03da355 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -597,11 +597,13 @@ fail: return (error); } +static const char FREEBSD_ABI_VENDOR[] = "FreeBSD"; + static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) { const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; - const Elf_Phdr *phdr; + const Elf_Phdr *phdr, *pnote = NULL; Elf_Auxargs *elf_auxargs; struct vmspace *vmspace; vm_prot_t prot; @@ -612,7 +614,9 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) int error = 0, i; const char *interp = NULL; Elf_Brandinfo *brand_info; + const Elf_Note *note, *note_end; char *path; + const char *note_name; struct thread *td = curthread; struct sysentvec *sv; @@ -754,6 +758,9 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) case PT_PHDR: /* Program header table info */ proghdr = phdr[i].p_vaddr; break; + case PT_NOTE: + pnote = &phdr[i]; + break; default: break; } @@ -835,6 +842,41 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) imgp->auxargs = elf_auxargs; imgp->interpreted = 0; + /* + * Try to fetch the osreldate for FreeBSD binary from the ELF + * OSABI-note. Only the first page of the image is searched, + * the same as for headers. + */ + if (pnote != NULL && pnote->p_offset < PAGE_SIZE && + pnote->p_offset + pnote->p_filesz < PAGE_SIZE ) { + note = (const Elf_Note *)(imgp->image_header + pnote->p_offset); + if (!aligned(note, Elf32_Addr)) { + free(imgp->auxargs, M_TEMP); + imgp->auxargs = NULL; + return (ENOEXEC); + } + note_end = (const Elf_Note *)(imgp->image_header + pnote->p_offset + + pnote->p_filesz); + while (note < note_end) { + if (note->n_namesz == sizeof(FREEBSD_ABI_VENDOR) && + note->n_descsz == sizeof(int32_t) && + note->n_type == 1 /* ABI_NOTETYPE */) { + note_name = (const char *)(note + 1); + if (strncmp(FREEBSD_ABI_VENDOR, note_name, + sizeof(FREEBSD_ABI_VENDOR)) == 0) { + imgp->proc->p_osrel = *(const int32_t *) + (note_name + + round_page_ps(sizeof(FREEBSD_ABI_VENDOR), + sizeof(Elf32_Addr))); + break; + } + } + note = (const Elf_Note *)((const char *)(note + 1) + + round_page_ps(note->n_namesz, sizeof(Elf32_Addr)) + + round_page_ps(note->n_descsz, sizeof(Elf32_Addr))); + } + } + return (error); } @@ -901,8 +943,6 @@ static void __elfN(puthdr)(struct thread *, void *, size_t *, int); static void __elfN(putnote)(void *, size_t *, const char *, int, const void *, size_t); -extern int osreldate; - int __elfN(coredump)(td, vp, limit) struct thread *td; diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index b536215..ed76ff8 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -373,9 +373,10 @@ proc0_init(void *dummy __unused) td = &thread0; /* - * Initialize magic number. + * Initialize magic number and osrel. */ p->p_magic = P_MAGIC; + p->p_osrel = osreldate; /* * Initialize thread and process structures. diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index ddeac60..2878b37 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -391,6 +391,7 @@ interpret: if (error) goto exec_fail_dealloc; + imgp->proc->p_osrel = 0; /* * If the current process has a special image activator it * wants to try first, call it. For example, emulating shell diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index 52f8754..c405adf 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -104,7 +104,6 @@ SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, * NOTICE: The *userland* release date is available in * /usr/include/osreldate.h */ -extern int osreldate; SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, "Kernel release date"); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index eaf6f03..7d0aca4 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -561,6 +561,8 @@ struct proc { /* The following fields are all copied upon creation in fork. */ #define p_startcopy p_endzero u_int p_magic; /* (b) Magic number. */ + int p_osrel; /* (x) osreldate for the + binary (from ELF note, if any) */ char p_comm[MAXCOMLEN + 1]; /* (b) Process name. */ struct pgrp *p_pgrp; /* (c + e) Pointer to process group. */ struct sysentvec *p_sysent; /* (b) Syscall dispatch info. */ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 21059ba..6809696 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -101,6 +101,7 @@ extern int maxusers; /* system tune hint */ * in two files. * XXX most of these variables should be const. */ +extern int osreldate; extern int envmode; extern int hintmode; /* 0 = off. 1 = config, 2 = fallback */ extern int dynamic_kenv; |