diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/imgact_aout.c | 83 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 25 |
2 files changed, 85 insertions, 23 deletions
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index a783c41..2f168d8 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/imgact.h> #include <sys/imgact_aout.h> #include <sys/kernel.h> +#include <sys/limits.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mutex.h> @@ -52,9 +53,18 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_object.h> #include <vm/vm_param.h> +#ifdef __amd64__ +#include <compat/freebsd32/freebsd32_signal.h> +#include <compat/freebsd32/freebsd32_util.h> +#include <compat/freebsd32/freebsd32_proto.h> +#include <compat/freebsd32/freebsd32_syscall.h> +#include <compat/ia32/ia32_signal.h> +#endif + static int exec_aout_imgact(struct image_params *imgp); static int aout_fixup(register_t **stack_base, struct image_params *imgp); +#if defined(__i386__) struct sysentvec aout_sysvec = { .sv_size = SYS_MAXSYSCALL, .sv_table = sysent, @@ -83,31 +93,69 @@ struct sysentvec aout_sysvec = { .sv_setregs = exec_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, - .sv_flags = SV_ABI_FREEBSD | SV_AOUT | -#if defined(__i386__) - SV_IA32 | SV_ILP32 -#else -#error Choose SV_XXX flags for the platform -#endif - , + .sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32, .sv_set_syscall_retval = cpu_set_syscall_retval, .sv_fetch_syscall_args = cpu_fetch_syscall_args, .sv_syscallnames = syscallnames, .sv_schedtail = NULL, }; +#elif defined(__amd64__) + +#define AOUT32_USRSTACK 0xbfc0000 +#define AOUT32_PS_STRINGS \ + (AOUT32_USRSTACK - sizeof(struct freebsd32_ps_strings)) + +extern const char *freebsd32_syscallnames[]; +extern u_long ia32_maxssiz; + +struct sysentvec aout_sysvec = { + .sv_size = FREEBSD32_SYS_MAXSYSCALL, + .sv_table = freebsd32_sysent, + .sv_mask = 0, + .sv_sigsize = 0, + .sv_sigtbl = NULL, + .sv_errsize = 0, + .sv_errtbl = NULL, + .sv_transtrap = NULL, + .sv_fixup = aout_fixup, + .sv_sendsig = ia32_sendsig, + .sv_sigcode = ia32_sigcode, + .sv_szsigcode = &sz_ia32_sigcode, + .sv_prepsyscall = NULL, + .sv_name = "FreeBSD a.out", + .sv_coredump = NULL, + .sv_imgact_try = NULL, + .sv_minsigstksz = MINSIGSTKSZ, + .sv_pagesize = IA32_PAGE_SIZE, + .sv_minuser = 0, + .sv_maxuser = AOUT32_USRSTACK, + .sv_usrstack = AOUT32_USRSTACK, + .sv_psstrings = AOUT32_PS_STRINGS, + .sv_stackprot = VM_PROT_ALL, + .sv_copyout_strings = freebsd32_copyout_strings, + .sv_setregs = ia32_setregs, + .sv_fixlimit = ia32_fixlimit, + .sv_maxssiz = &ia32_maxssiz, + .sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32, + .sv_set_syscall_retval = ia32_set_syscall_retval, + .sv_fetch_syscall_args = ia32_fetch_syscall_args, + .sv_syscallnames = freebsd32_syscallnames, +}; +#else +#error "Port me" +#endif + static int -aout_fixup(stack_base, imgp) - register_t **stack_base; - struct image_params *imgp; +aout_fixup(register_t **stack_base, struct image_params *imgp) { - return (suword(--(*stack_base), imgp->args->argc)); + *(char **)stack_base -= sizeof(uint32_t); + return (suword(*stack_base, imgp->args->argc)); } static int -exec_aout_imgact(imgp) - struct image_params *imgp; +exec_aout_imgact(struct image_params *imgp) { const struct exec *a_out = (const struct exec *) imgp->image_header; struct vmspace *vmspace; @@ -175,7 +223,14 @@ exec_aout_imgact(imgp) a_out->a_entry >= virtual_offset + a_out->a_text || /* text and data size must each be page rounded */ - a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) + a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK + +#ifdef __amd64__ + || + /* overflows */ + virtual_offset + a_out->a_text + a_out->a_data + bss_size > UINT_MAX +#endif + ) return (-1); /* text + data can't exceed file size */ diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index fe66591..649339b 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3898,14 +3898,20 @@ struct ogetdirentries_args { }; #endif int -ogetdirentries(td, uap) - struct thread *td; - register struct ogetdirentries_args /* { - int fd; - char *buf; - u_int count; - long *basep; - } */ *uap; +ogetdirentries(struct thread *td, struct ogetdirentries_args *uap) +{ + long loff; + int error; + + error = kern_ogetdirentries(td, uap, &loff); + if (error == 0) + error = copyout(&loff, uap->basep, sizeof(long)); + return (error); +} + +int +kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, + long *ploff) { struct vnode *vp; struct file *fp; @@ -4024,9 +4030,10 @@ unionread: } VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); - error = copyout(&loff, uap->basep, sizeof(long)); fdrop(fp, td); td->td_retval[0] = uap->count - auio.uio_resid; + if (error == 0) + *ploff = loff; return (error); } #endif /* COMPAT_43 */ |