diff --git a/sys/cpu/i386/include/elf.h b/sys/cpu/i386/include/elf.h index ae950f3..eb65225 100644 --- a/sys/cpu/i386/include/elf.h +++ b/sys/cpu/i386/include/elf.h @@ -73,16 +73,16 @@ typedef struct { __ElfType(Auxinfo); /* Values for a_type. */ -#define AT_NULL 0 /* Terminates the vector. */ -#define AT_IGNORE 1 /* Ignored entry. */ -#define AT_EXECFD 2 /* File descriptor of program to load. */ -#define AT_PHDR 3 /* Program header of program already loaded. */ -#define AT_PHENT 4 /* Size of each program header entry. */ -#define AT_PHNUM 5 /* Number of program header entries. */ -#define AT_PAGESZ 6 /* Page size in bytes. */ -#define AT_BASE 7 /* Interpreter's base address. */ -#define AT_FLAGS 8 /* Flags (unused for i386). */ -#define AT_ENTRY 9 /* Where interpreter should transfer control. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_EXECFD 2 /* File descriptor of program to load. */ +#define AT_PHDR 3 /* Program header of program already loaded. */ +#define AT_PHENT 4 /* Size of each program header entry. */ +#define AT_PHNUM 5 /* Number of program header entries. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_BASE 7 /* Interpreter's base address. */ +#define AT_FLAGS 8 /* Flags (unused for i386). */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ /* * The following non-standard values are used for passing information @@ -92,19 +92,26 @@ __ElfType(Auxinfo); * Unfortunately, these overlap the Linux non-standard values, so they * must not be used in the same context. */ -#define AT_BRK 10 /* Starting point for sbrk and brk. */ -#define AT_DEBUG 11 /* Debugging level. */ +#define AT_BRK 10 /* Starting point for sbrk and brk. */ +#define AT_DEBUG 11 /* Debugging level. */ /* * The following non-standard values are used in Linux ELF binaries. */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ - -#define AT_COUNT 15 /* Count of defined aux entry types. */ +#define AT_NOTELF 10 /* Program is not ELF ?? */ +#define AT_UID 11 /* Real uid. */ +#define AT_EUID 12 /* Effective uid. */ +#define AT_GID 13 /* Real gid. */ +#define AT_EGID 14 /* Effective gid. */ +#define AT_EXECPATH 15 /* Path to the executable. */ +#define AT_CANARY 16 /* Canary for SSP. */ +#define AT_CANARYLEN 17 /* Length of the canary. */ +#define AT_OSRELDATE 18 /* OSRELDATE. */ +#define AT_NCPUS 19 /* Number of CPUs. */ +#define AT_PAGESIZES 20 /* Pagesizes. */ +#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ + +#define AT_COUNT 22 /* Count of defined aux entry types. */ /* * Relocation types. diff --git a/sys/cpu/i386/include/param.h b/sys/cpu/i386/include/param.h index cb90e4b..ebcc09e 100644 --- a/sys/cpu/i386/include/param.h +++ b/sys/cpu/i386/include/param.h @@ -132,6 +132,8 @@ #define IOPAGES 2 /* pages of i/o permission bitmap */ #define UPAGES 4 /* pages of u-area */ +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + /* * Ceiling on amount of swblock kva space, can be changed via * kern.maxswzone /boot/loader.conf variable. diff --git a/sys/cpu/x86_64/include/elf.h b/sys/cpu/x86_64/include/elf.h index f57d450..35022d3 100644 --- a/sys/cpu/x86_64/include/elf.h +++ b/sys/cpu/x86_64/include/elf.h @@ -101,8 +101,15 @@ __ElfType(Auxinfo); #define AT_EUID 12 /* Effective uid. */ #define AT_GID 13 /* Real gid. */ #define AT_EGID 14 /* Effective gid. */ - -#define AT_COUNT 15 /* Count of defined aux entry types. */ +#define AT_EXECPATH 15 /* Path to the executable. */ +#define AT_CANARY 16 /* Canary for SSP */ +#define AT_CANARYLEN 17 /* Length of the canary. */ +#define AT_OSRELDATE 18 /* OSRELDATE. */ +#define AT_NCPUS 19 /* Number of CPUs. */ +#define AT_PAGESIZES 20 /* Pagesizes. */ +#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ + +#define AT_COUNT 22 /* Count of defined aux entry types. */ /* * Relocation types. diff --git a/sys/cpu/x86_64/include/param.h b/sys/cpu/x86_64/include/param.h index d23ae69..6776858 100644 --- a/sys/cpu/x86_64/include/param.h +++ b/sys/cpu/x86_64/include/param.h @@ -147,6 +147,8 @@ #define IOPAGES 2 /* pages of i/o permission bitmap */ #define UPAGES 4 /* pages of u-area */ +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + /* * Ceiling on amount of swblock kva space, can be changed via * kern.maxswzone /boot/loader.conf variable. On 64 bit machines diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 72d3ef1..d523fb5 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -118,6 +118,8 @@ static struct sysentvec elf_freebsd_sysvec = { MINSIGSTKSZ }; +extern int osreldate; + static Elf_Brandinfo freebsd_brand_info = { ELFOSABI_FREEBSD, "FreeBSD", @@ -926,6 +928,18 @@ elf_freebsd_fixup(register_t **stack_base, struct image_params *imgp) AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); + if (imgp->execpathp != 0) + AUXARGS_ENTRY(pos, AT_EXECPATH, imgp->execpathp); + AUXARGS_ENTRY(pos, AT_OSRELDATE, osreldate); + if (imgp->canary != 0) { + AUXARGS_ENTRY(pos, AT_CANARY, imgp->canary); + AUXARGS_ENTRY(pos, AT_CANARYLEN, imgp->canarylen); + } + AUXARGS_ENTRY(pos, AT_NCPUS, ncpus); + if (imgp->pagesizes != 0) { + AUXARGS_ENTRY(pos, AT_PAGESIZES, imgp->pagesizes); + AUXARGS_ENTRY(pos, AT_PAGESIZESLEN, imgp->pagesizeslen); + } AUXARGS_ENTRY(pos, AT_NULL, 0); kfree(imgp->auxargs, M_TEMP); @@ -990,8 +1004,6 @@ static int elf_putsigs(struct lwp *, elf_buf_t); static int elf_puttextvp(struct proc *, elf_buf_t); static int elf_putfiles(struct proc *, elf_buf_t, struct file *); -extern int osreldate; - int elf_coredump(struct lwp *lp, int sig, struct vnode *vp, off_t limit) { diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 08e9a10..e118550 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -219,6 +219,12 @@ kern_execve(struct nlookupdata *nd, struct image_args *args) imgp->vp = NULL; imgp->firstpage = NULL; imgp->ps_strings = 0; + imgp->execpath = imgp->freepath = NULL; + imgp->execpathp = 0; + imgp->canary = 0; + imgp->canarylen = 0; + imgp->pagesizes = 0; + imgp->pagesizeslen = 0; imgp->image_header = NULL; interpret: @@ -309,6 +315,15 @@ interpret: } /* + * Do the best to calculate the full path to the image file. + */ + if (imgp->auxargs != NULL && + ((args->fname != NULL && args->fname[0] == '/') || + vn_fullpath(imgp->proc, imgp->vp, &imgp->execpath, &imgp->freepath, 0) != + 0)) + imgp->execpath = args->fname; + + /* * Copy out strings (args and env) and initialize stack base */ stack_base = exec_copyout_strings(imgp); @@ -518,6 +533,8 @@ exec_fail_dealloc: return (0); } + kfree(imgp->freepath, M_TEMP); + exec_fail: /* * we're done here, clear P_INEXEC if we were the ones that @@ -883,12 +900,20 @@ exec_copyout_strings(struct image_params *imgp) char *stringp, *destp; register_t *stack_base; struct ps_strings *arginfo; + size_t execpath_len; int szsigcode; + int szps; + char canary[sizeof(long) * 8]; + szps = sizeof(pagesizes[0]) * MAXPAGESIZES; /* * Calculate string base and vector table pointers. * Also deal with signal trampoline code for this exec type. */ + if (imgp->execpath != NULL && imgp->auxargs != NULL) + execpath_len = strlen(imgp->execpath) + 1; + else + execpath_len = 0; arginfo = (struct ps_strings *)PS_STRINGS; szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); if (stackgap_random != 0) @@ -896,6 +921,9 @@ exec_copyout_strings(struct image_params *imgp) else sgap = 0; destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - sgap - + roundup(execpath_len, sizeof(char *)) - + roundup(sizeof(canary), sizeof(char *)) - + roundup(szps, sizeof(char *)) - roundup((ARG_MAX - imgp->args->space), sizeof(char *)); /* @@ -906,6 +934,32 @@ exec_copyout_strings(struct image_params *imgp) ((caddr_t)arginfo - szsigcode), szsigcode); /* + * Copy the image path for the rtld. + */ + if (execpath_len != 0) { + imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len; + copyout(imgp->execpath, (void *)imgp->execpathp, + execpath_len); + } + + /* + * Prepare the canary for SSP. + */ + karc4rand(canary, sizeof(canary)); + imgp->canary = (uintptr_t)arginfo - szsigcode - execpath_len - + sizeof(canary); + copyout(canary, (void *)imgp->canary, sizeof(canary)); + imgp->canarylen = sizeof(canary); + + /* + * Prepare the pagesizes array. + */ + imgp->pagesizes = (uintptr_t)arginfo - szsigcode - execpath_len - + roundup(sizeof(canary), sizeof(char *)) - szps; + copyout(pagesizes, (void *)imgp->pagesizes, szps); + imgp->pagesizeslen = szps; + + /* * If we have a valid auxargs ptr, prepare some room * on the stack. * diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index f65425b..e64df6f 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -158,6 +158,18 @@ static char machine_arch[] = MACHINE_ARCH; SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD, machine_arch, 0, "Cpu architecture"); +u_long pagesizes[MAXPAGESIZES] = { PAGE_SIZE }; + +static int +sysctl_hw_pagesizes(SYSCTL_HANDLER_ARGS) +{ + int error = SYSCTL_OUT(req, pagesizes, sizeof(pagesizes)); + return (error); +} + +SYSCTL_PROC(_hw, OID_AUTO, pagesizes, CTLTYPE_ULONG | CTLFLAG_RD, + NULL, 0, sysctl_hw_pagesizes, "LU", "Supported page sizes"); + char hostname[MAXHOSTNAMELEN]; static int diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 40ca7c3..6ccd48b 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -68,6 +68,13 @@ struct image_params { struct lwbuf *firstpage; /* first page that we mapped */ struct lwbuf firstpage_cache; unsigned long ps_strings; /* PS_STRINGS for BSD/OS binaries */ + char *execpath; + unsigned long execpathp; + char *freepath; + unsigned long canary; + int canarylen; + unsigned long pagesizes; + int pagesizeslen; }; #ifdef _KERNEL diff --git a/sys/sys/systm.h b/sys/sys/systm.h index fd60dd3..f33a1ab 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -70,6 +70,7 @@ extern int selwait; /* select timeout address */ extern u_char curpriority; /* priority of current process */ extern long physmem; /* physical memory */ +extern u_long pagesizes[]; /* supported page sizes */ extern cdev_t dumpdev; /* dump device */ extern u_int64_t dumplo64; /* block number into dumpdev, start of dump */