diff --git a/sys/amd64/ia32/ia32_misc.c b/sys/amd64/ia32/ia32_misc.c index 2fa197219010..5a8a7211cf9b 100644 --- a/sys/amd64/ia32/ia32_misc.c +++ b/sys/amd64/ia32/ia32_misc.c @@ -69,3 +69,14 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap) return (sysarch(td, &uap1)); } } + +#ifdef COMPAT_43 +int +ofreebsd32_getpagesize(struct thread *td, + struct ofreebsd32_getpagesize_args *uap) +{ + + td->td_retval[0] = IA32_PAGE_SIZE; + return (0); +} +#endif diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c index 29dd01f69987..2f4187041b4f 100644 --- a/sys/amd64/ia32/ia32_signal.c +++ b/sys/amd64/ia32/ia32_signal.c @@ -300,6 +300,109 @@ freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) * frame pointer, it returns to the user * specified pc, psl. */ + +#ifdef COMPAT_43 +static void +ia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) +{ + struct ia32_sigframe3 sf, *fp; + struct proc *p; + struct thread *td; + struct sigacts *psp; + struct trapframe *regs; + int sig; + int oonstack; + + td = curthread; + p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; + psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); + regs = td->td_frame; + oonstack = sigonstack(regs->tf_rsp); + + /* Allocate space for the signal handler context. */ + if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + fp = (struct ia32_sigframe3 *)(td->td_sigstk.ss_sp + + td->td_sigstk.ss_size - sizeof(sf)); + td->td_sigstk.ss_flags |= SS_ONSTACK; + } else + fp = (struct ia32_sigframe3 *)regs->tf_rsp - 1; + + /* Translate the signal if appropriate. */ + if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) + sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; + + /* Build the argument list for the signal handler. */ + sf.sf_signum = sig; + sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; + if (SIGISMEMBER(psp->ps_siginfo, sig)) { + /* Signal handler installed with SA_SIGINFO. */ + sf.sf_arg2 = (register_t)&fp->sf_siginfo; + sf.sf_siginfo.si_signo = sig; + sf.sf_siginfo.si_code = ksi->ksi_code; + sf.sf_ah = (uintptr_t)catcher; + } else { + /* Old FreeBSD-style arguments. */ + sf.sf_arg2 = ksi->ksi_code; + sf.sf_addr = (register_t)ksi->ksi_addr; + sf.sf_ah = (uintptr_t)catcher; + } + mtx_unlock(&psp->ps_mtx); + PROC_UNLOCK(p); + + /* Save most if not all of trap frame. */ + sf.sf_siginfo.si_sc.sc_eax = regs->tf_rax; + sf.sf_siginfo.si_sc.sc_ebx = regs->tf_rbx; + sf.sf_siginfo.si_sc.sc_ecx = regs->tf_rcx; + sf.sf_siginfo.si_sc.sc_edx = regs->tf_rdx; + sf.sf_siginfo.si_sc.sc_esi = regs->tf_rsi; + sf.sf_siginfo.si_sc.sc_edi = regs->tf_rdi; + sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs; + sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds; + sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss; + sf.sf_siginfo.si_sc.sc_es = regs->tf_es; + sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs; + sf.sf_siginfo.si_sc.sc_gs = regs->tf_gs; + sf.sf_siginfo.si_sc.sc_isp = regs->tf_rsp; + + /* Build the signal context to be used by osigreturn(). */ + sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0; + SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask); + sf.sf_siginfo.si_sc.sc_esp = regs->tf_rsp; + sf.sf_siginfo.si_sc.sc_ebp = regs->tf_rbp; + sf.sf_siginfo.si_sc.sc_eip = regs->tf_rip; + sf.sf_siginfo.si_sc.sc_eflags = regs->tf_rflags; + sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno; + sf.sf_siginfo.si_sc.sc_err = regs->tf_err; + + /* + * Copy the sigframe out to the user's stack. + */ + if (copyout(&sf, fp, sizeof(*fp)) != 0) { +#ifdef DEBUG + printf("process %ld has trashed its stack\n", (long)p->p_pid); +#endif + PROC_LOCK(p); + sigexit(td, SIGILL); + } + + regs->tf_rsp = (uintptr_t)fp; + regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode; + regs->tf_rflags &= ~(PSL_T | PSL_D); + regs->tf_cs = _ucode32sel; + regs->tf_ds = _udatasel; + regs->tf_es = _udatasel; + regs->tf_fs = _udatasel; + regs->tf_ss = _udatasel; + set_pcb_flags(td->td_pcb, PCB_FULL_IRET); + PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); +} +#endif + #ifdef COMPAT_FREEBSD4 static void freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) @@ -440,6 +543,12 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) freebsd4_ia32_sendsig(catcher, ksi, mask); return; } +#endif +#ifdef COMPAT_43 + if (SIGISMEMBER(psp->ps_osigset, sig)) { + ia32_osendsig(catcher, ksi, mask); + return; + } #endif mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; @@ -547,6 +656,64 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) * make sure that the user has not modified the * state to gain improper privileges. */ + +#ifdef COMPAT_43 +int +ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) +{ + struct ia32_sigcontext3 sc, *scp; + struct trapframe *regs; + int eflags, error; + ksiginfo_t ksi; + + regs = td->td_frame; + error = copyin(uap->sigcntxp, &sc, sizeof(sc)); + if (error != 0) + return (error); + scp = ≻ + eflags = scp->sc_eflags; + if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { + return (EINVAL); + } + if (!CS_SECURE(scp->sc_cs)) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trapno = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_rip; + trapsignal(td, &ksi); + return (EINVAL); + } + regs->tf_ds = scp->sc_ds; + regs->tf_es = scp->sc_es; + regs->tf_fs = scp->sc_fs; + regs->tf_gs = scp->sc_gs; + + regs->tf_rax = scp->sc_eax; + regs->tf_rbx = scp->sc_ebx; + regs->tf_rcx = scp->sc_ecx; + regs->tf_rdx = scp->sc_edx; + regs->tf_rsi = scp->sc_esi; + regs->tf_rdi = scp->sc_edi; + regs->tf_cs = scp->sc_cs; + regs->tf_ss = scp->sc_ss; + regs->tf_rbp = scp->sc_ebp; + regs->tf_rsp = scp->sc_esp; + regs->tf_rip = scp->sc_eip; + regs->tf_rflags = eflags; + + if (scp->sc_onstack & 1) + td->td_sigstk.ss_flags |= SS_ONSTACK; + else + td->td_sigstk.ss_flags &= ~SS_ONSTACK; + + kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL, + SIGPROCMASK_OLD); + set_pcb_flags(td->td_pcb, PCB_FULL_IRET); + return (EJUSTRETURN); +} +#endif + #ifdef COMPAT_FREEBSD4 /* * MPSAFE @@ -734,6 +901,9 @@ ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) user_ldt_free(td); else mtx_unlock(&dt_lock); +#ifdef COMPAT_43 + setup_lcall_gate(); +#endif pcb->pcb_fsbase = 0; pcb->pcb_gsbase = 0; diff --git a/sys/amd64/ia32/ia32_sigtramp.S b/sys/amd64/ia32/ia32_sigtramp.S index 945516986600..7d6447011c8c 100644 --- a/sys/amd64/ia32/ia32_sigtramp.S +++ b/sys/amd64/ia32/ia32_sigtramp.S @@ -66,6 +66,35 @@ freebsd4_ia32_sigcode: jmp 1b #endif +#ifdef COMPAT_43 + ALIGN_TEXT +ia32_osigcode: + calll *IA32_SIGF_HANDLER(%esp)/* call signal handler */ + leal IA32_SIGF_SC(%esp),%eax /* get sigcontext */ + pushl %eax + movl $103,%eax /* 3.x SYS_sigreturn */ + pushl %eax /* junk to fake return addr. */ + int $0x80 /* enter kernel with args */ +1: + jmp 1b + + + ALIGN_TEXT +lcall_tramp: + pushl %ebp + movl %esp,%ebp + pushl 0x24(%ebp) /* arg 6 */ + pushl 0x20(%ebp) + pushl 0x1c(%ebp) + pushl 0x18(%ebp) + pushl 0x14(%ebp) + pushl 0x10(%ebp) /* arg 1 */ + pushl 0xc(%ebp) /* gap */ + int $0x80 + leave + lretl +#endif + ALIGN_TEXT esigcode: @@ -78,3 +107,11 @@ sz_ia32_sigcode: sz_freebsd4_ia32_sigcode: .long esigcode-freebsd4_ia32_sigcode #endif +#ifdef COMPAT_43 + .globl sz_ia32_osigcode +sz_ia32_osigcode: + .long esigcode-ia32_osigcode + .globl sz_lcall_tramp +sz_lcall_tramp: + .long esigcode-lcall_tramp +#endif diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c index 9a3488e6ac23..0b46dae7a5e3 100644 --- a/sys/amd64/ia32/ia32_syscall.c +++ b/sys/amd64/ia32/ia32_syscall.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); */ #include "opt_clock.h" +#include "opt_compat.h" #include "opt_cpu.h" #include "opt_isa.h" @@ -78,7 +79,17 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define IDTVEC(name) __CONCAT(X,name) @@ -198,3 +209,45 @@ ia32_syscall_disable(void *dummy) SYSINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_enable, NULL); SYSUNINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_disable, NULL); + +#ifdef COMPAT_43 +int +setup_lcall_gate(void) +{ + struct i386_ldt_args uap; + struct user_segment_descriptor descs[2]; + struct gate_descriptor *ssd; + uint32_t lcall_addr; + int error; + + bzero(&uap, sizeof(uap)); + uap.start = 0; + uap.num = 2; + + /* + * This is the easiest way to cut the space for system + * descriptor in ldt. Manually adjust the descriptor type to + * the call gate later. + */ + bzero(&descs[0], sizeof(descs)); + descs[0].sd_type = SDT_SYSNULL; + descs[1].sd_type = SDT_SYSNULL; + error = amd64_set_ldt(curthread, &uap, descs); + if (error != 0) + return (error); + + lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp; + mtx_lock(&dt_lock); + ssd = (struct gate_descriptor *)(curproc->p_md.md_ldt->ldt_base); + bzero(ssd, sizeof(*ssd)); + ssd->gd_looffset = lcall_addr; + ssd->gd_hioffset = lcall_addr >> 16; + ssd->gd_selector = _ucode32sel; + ssd->gd_type = SDT_SYSCGT; + ssd->gd_dpl = SEL_UPL; + ssd->gd_p = 1; + mtx_unlock(&dt_lock); + + return (0); +} +#endif diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index e7511479bf7f..5772c0e33c6d 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -1454,6 +1454,29 @@ freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) return (ftruncate(td, &ap)); } +#ifdef COMPAT_43 +int +ofreebsd32_getdirentries(struct thread *td, + struct ofreebsd32_getdirentries_args *uap) +{ + struct ogetdirentries_args ap; + int error; + long loff; + int32_t loff_cut; + + ap.fd = uap->fd; + ap.buf = uap->buf; + ap.count = uap->count; + ap.basep = NULL; + error = kern_ogetdirentries(td, &ap, &loff); + if (error == 0) { + loff_cut = loff; + error = copyout(&loff_cut, uap->basep, sizeof(int32_t)); + } + return (error); +} +#endif + int freebsd32_getdirentries(struct thread *td, struct freebsd32_getdirentries_args *uap) @@ -1638,6 +1661,29 @@ copy_stat(struct stat *in, struct stat32 *out) TS_CP(*in, *out, st_birthtim); } +#ifdef COMPAT_43 +static void +copy_ostat(struct stat *in, struct ostat32 *out) +{ + + CP(*in, *out, st_dev); + CP(*in, *out, st_ino); + CP(*in, *out, st_mode); + CP(*in, *out, st_nlink); + CP(*in, *out, st_uid); + CP(*in, *out, st_gid); + CP(*in, *out, st_rdev); + CP(*in, *out, st_size); + TS_CP(*in, *out, st_atim); + TS_CP(*in, *out, st_mtim); + TS_CP(*in, *out, st_ctim); + CP(*in, *out, st_blksize); + CP(*in, *out, st_blocks); + CP(*in, *out, st_flags); + CP(*in, *out, st_gen); +} +#endif + int freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) { @@ -1653,6 +1699,23 @@ freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) return (error); } +#ifdef COMPAT_43 +int +ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap) +{ + struct stat sb; + struct ostat32 sb32; + int error; + + error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); + if (error) + return (error); + copy_ostat(&sb, &sb32); + error = copyout(&sb32, uap->ub, sizeof (sb32)); + return (error); +} +#endif + int freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) { @@ -1668,6 +1731,23 @@ freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) return (error); } +#ifdef COMPAT_43 +int +ofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap) +{ + struct stat ub; + struct ostat32 ub32; + int error; + + error = kern_fstat(td, uap->fd, &ub); + if (error) + return (error); + copy_ostat(&ub, &ub32); + error = copyout(&ub32, uap->ub, sizeof(ub32)); + return (error); +} +#endif + int freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap) { @@ -1698,9 +1778,23 @@ freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) return (error); } -/* - * MPSAFE - */ +#ifdef COMPAT_43 +int +ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap) +{ + struct stat sb; + struct ostat32 sb32; + int error; + + error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); + if (error) + return (error); + copy_ostat(&sb, &sb32); + error = copyout(&sb32, uap->ub, sizeof (sb32)); + return (error); +} +#endif + int freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) { diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 8a4cadff7d73..da421330678b 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -117,9 +117,11 @@ 35 AUE_FCHFLAGS NOPROTO { int fchflags(int fd, int flags); } 36 AUE_SYNC NOPROTO { int sync(void); } 37 AUE_KILL NOPROTO { int kill(int pid, int signum); } -38 AUE_STAT UNIMPL ostat +38 AUE_STAT COMPAT { int freebsd32_stat(char *path, \ + struct ostat32 *ub); } 39 AUE_GETPPID NOPROTO { pid_t getppid(void); } -40 AUE_LSTAT UNIMPL olstat +40 AUE_LSTAT COMPAT { int freebsd32_lstat(char *path, \ + struct ostat *ub); } 41 AUE_DUP NOPROTO { int dup(u_int fd); } 42 AUE_PIPE NOPROTO { int pipe(void); } 43 AUE_GETEGID NOPROTO { gid_t getegid(void); } @@ -153,9 +155,11 @@ 60 AUE_UMASK NOPROTO { int umask(int newmask); } umask \ umask_args int 61 AUE_CHROOT NOPROTO { int chroot(char *path); } -62 AUE_FSTAT OBSOL ofstat +62 AUE_FSTAT COMPAT { int freebsd32_fstat(int fd, \ + struct ostat32 *ub); } 63 AUE_NULL OBSOL ogetkerninfo -64 AUE_NULL OBSOL ogetpagesize +64 AUE_NULL COMPAT { int freebsd32_getpagesize( \ + int32_t dummy); } 65 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \ int flags); } 66 AUE_VFORK NOPROTO { int vfork(void); } @@ -210,7 +214,8 @@ 100 AUE_GETPRIORITY NOPROTO { int getpriority(int which, int who); } 101 AUE_NULL OBSOL osend 102 AUE_NULL OBSOL orecv -103 AUE_NULL OBSOL osigreturn +103 AUE_NULL COMPAT { int freebsd32_sigreturn( \ + struct ia32_sigcontext3 *sigcntxp); } 104 AUE_BIND NOPROTO { int bind(int s, caddr_t name, \ int namelen); } 105 AUE_SETSOCKOPT NOPROTO { int setsockopt(int s, int level, \ @@ -292,7 +297,8 @@ ; 155 is initialized by the NFS code, if present. ; XXX this is a problem!!! 155 AUE_NFS_SVC UNIMPL nfssvc -156 AUE_GETDIRENTRIES OBSOL ogetdirentries +156 AUE_GETDIRENTRIES COMPAT { int freebsd32_getdirentries(int fd, \ + char *buf, u_int count, uint32_t *basep); } 157 AUE_STATFS COMPAT4 { int freebsd32_statfs(char *path, \ struct statfs32 *buf); } 158 AUE_FSTATFS COMPAT4 { int freebsd32_fstatfs(int fd, \ diff --git a/sys/compat/ia32/ia32_genassym.c b/sys/compat/ia32/ia32_genassym.c index 84fb648f90ed..5462a8b78e67 100644 --- a/sys/compat/ia32/ia32_genassym.c +++ b/sys/compat/ia32/ia32_genassym.c @@ -13,6 +13,9 @@ __FBSDID("$FreeBSD$"); ASSYM(IA32_SIGF_HANDLER, offsetof(struct ia32_sigframe, sf_ah)); ASSYM(IA32_SIGF_UC, offsetof(struct ia32_sigframe, sf_uc)); +#ifdef COMPAT_43 +ASSYM(IA32_SIGF_SC, offsetof(struct ia32_sigframe3, sf_siginfo.si_sc)); +#endif ASSYM(IA32_UC_GS, offsetof(struct ia32_ucontext, uc_mcontext.mc_gs)); ASSYM(IA32_UC_FS, offsetof(struct ia32_ucontext, uc_mcontext.mc_fs)); ASSYM(IA32_UC_ES, offsetof(struct ia32_ucontext, uc_mcontext.mc_es)); diff --git a/sys/compat/ia32/ia32_signal.h b/sys/compat/ia32/ia32_signal.h index 757e384df283..0c54caff1ddf 100644 --- a/sys/compat/ia32/ia32_signal.h +++ b/sys/compat/ia32/ia32_signal.h @@ -112,7 +112,7 @@ struct ia32_ucontext4 { }; #endif -#ifdef COMPAT_FREEBSD3 +#ifdef COMPAT_43 struct ia32_sigcontext3 { u_int32_t sc_onstack; u_int32_t sc_mask; @@ -165,7 +165,7 @@ struct ia32_sigframe { struct siginfo32 sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ }; -#ifdef COMPAT_FREEBSD3 +#ifdef COMPAT_43 struct ia32_siginfo3 { struct ia32_sigcontext3 si_sc; int si_signo; @@ -186,10 +186,15 @@ struct ksiginfo; struct image_params; extern char ia32_sigcode[]; extern char freebsd4_ia32_sigcode[]; +extern char ia32_osigcode[]; +extern char lcall_tramp; extern int sz_ia32_sigcode; extern int sz_freebsd4_ia32_sigcode; -extern void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *); -extern void ia32_setregs(struct thread *td, struct image_params *imgp, +extern int sz_ia32_osigcode; +extern int sz_lcall_tramp; +void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *); +void ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack); +int setup_lcall_gate(void); #endif diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c index a7790efd6409..c7edac4f9a23 100644 --- a/sys/compat/ia32/ia32_sysvec.c +++ b/sys/compat/ia32/ia32_sysvec.c @@ -95,14 +95,12 @@ CTASSERT(sizeof(struct ia32_sigframe4) == 408); extern const char *freebsd32_syscallnames[]; -static void ia32_fixlimit(struct rlimit *rl, int which); - SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode"); static u_long ia32_maxdsiz = IA32_MAXDSIZ; SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, ""); TUNABLE_ULONG("compat.ia32.maxdsiz", &ia32_maxdsiz); -static u_long ia32_maxssiz = IA32_MAXSSIZ; +u_long ia32_maxssiz = IA32_MAXSSIZ; SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, ""); TUNABLE_ULONG("compat.ia32.maxssiz", &ia32_maxssiz); static u_long ia32_maxvmem = IA32_MAXVMEM; @@ -206,7 +204,7 @@ elf32_dump_thread(struct thread *td __unused, void *dst __unused, { } -static void +void ia32_fixlimit(struct rlimit *rl, int which) { diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h index 4355daad4f4a..f15349260b3c 100644 --- a/sys/compat/ia32/ia32_util.h +++ b/sys/compat/ia32/ia32_util.h @@ -58,5 +58,6 @@ struct syscall_args; int ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa); void ia32_set_syscall_retval(struct thread *, int); +void ia32_fixlimit(struct rlimit *rl, int which); #endif diff --git a/sys/ia64/ia32/ia32_misc.c b/sys/ia64/ia32/ia32_misc.c index c85e31d97f9a..148e31a6e7cc 100644 --- a/sys/ia64/ia32/ia32_misc.c +++ b/sys/ia64/ia32/ia32_misc.c @@ -48,3 +48,14 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap) return (EOPNOTSUPP); } + +#ifdef COMPAT_43 +int +ofreebsd32_getpagesize(struct thread *td, + struct ofreebsd32_getpagesize_args *uap) +{ + + td->td_retval[0] = IA32_PAGE_SIZE; + return (0); +} +#endif diff --git a/sys/ia64/ia32/ia32_signal.c b/sys/ia64/ia32/ia32_signal.c index e41f0afee280..b8dab9054983 100644 --- a/sys/ia64/ia32/ia32_signal.c +++ b/sys/ia64/ia32/ia32_signal.c @@ -92,6 +92,15 @@ x) */ }; int sz_ia32_sigcode = sizeof(ia32_sigcode); +#ifdef COMPAT_43 +int +ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) +{ + + return (EOPNOTSUPP); +} +#endif + /* * Signal sending has not been implemented on ia64. This causes * the sigtramp code to not understand the arguments and the application diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index a783c410c39c..2f168d89ecdc 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -52,9 +53,18 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef __amd64__ +#include +#include +#include +#include +#include +#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 fe665910a1f3..649339bdff5b 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 @@ ogetdirentries(td, uap) } 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 */ diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 6f239dc0b14f..8ac166502930 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -518,6 +518,7 @@ _snc= snc .if ${MACHINE_CPUARCH} == "amd64" _aac= aac +_aout= aout _acpi= acpi .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _aesni= aesni diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index d4006331fd09..7649f1a6eb32 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -52,6 +52,7 @@ struct kld_file_stat; struct ksiginfo; struct sendfile_args; struct thr_param; +struct ogetdirentries_args; int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg, u_int buflen); @@ -143,6 +144,8 @@ int kern_msgsnd(struct thread *, int, const void *, size_t, int, long); int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *); int kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt); +int kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, + long *ploff); int kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, int mode); int kern_openat(struct thread *td, int fd, char *path,