X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/8f6c56a50524aa785f7e596d52dddfb331e18961..89b3af67bb32e691275bf6fa803d1834b2284115:/bsd/kern/kern_sysctl.c diff --git a/bsd/kern/kern_sysctl.c b/bsd/kern/kern_sysctl.c index 0d1b7d533..292085e1d 100644 --- a/bsd/kern/kern_sysctl.c +++ b/bsd/kern/kern_sysctl.c @@ -108,9 +108,14 @@ extern vm_map_t bsd_pageable_map; #include #include +#include #include +#ifdef __i386__ +#include +#endif + sysctlfn kern_sysctl; #ifdef DEBUG sysctlfn debug_sysctl; @@ -122,10 +127,10 @@ extern sysctlfn cpu_sysctl; extern int aio_max_requests; extern int aio_max_requests_per_process; extern int aio_worker_threads; -extern int maxprocperuid; extern int maxfilesperproc; extern int lowpri_IO_window_msecs; extern int lowpri_IO_delay_msecs; +extern int nx_enabled; static void fill_eproc(struct proc *p, struct eproc *ep); @@ -319,7 +324,7 @@ __sysctl(struct proc *p, struct __sysctl_args *uap, __unused register_t *retval) if (uap->new != USER_ADDR_NULL && ((name[0] == CTL_KERN && !(name[1] == KERN_IPC || name[1] == KERN_PANICINFO || name[1] == KERN_PROCDELAYTERM || - name[1] == KERN_PROC_LOW_PRI_IO)) + name[1] == KERN_PROC_LOW_PRI_IO || name[1] == KERN_PROCNAME || name[1] == KERN_THALTSTACK)) || (name[0] == CTL_HW) || (name[0] == CTL_VM) || (name[0] == CTL_VFS)) @@ -433,9 +438,6 @@ __sysctl(struct proc *p, struct __sysctl_args *uap, __unused register_t *retval) /* * Attributes stored in the kernel. */ -extern char classichandler[32]; -extern uint32_t classichandler_fsid; -extern long classichandler_fileid; __private_extern__ char corefilename[MAXPATHLEN+1]; __private_extern__ int do_coredump; __private_extern__ int sugid_coredump; @@ -474,8 +476,9 @@ sysctl_affinity( return (ENOTSUP); } + static int -sysctl_classic( +sysctl_translate( int *name, u_int namelen, user_addr_t oldBuf, @@ -498,11 +501,60 @@ sysctl_classic( return (EPERM); return sysctl_rdint(oldBuf, oldSize, newBuf, - (p->p_flag & P_CLASSIC) ? 1 : 0); + (p->p_flag & P_TRANSLATED) ? 1 : 0); +} + +int +set_archhandler(struct proc *p, int arch) +{ + int error; + struct nameidata nd; + struct vnode_attr va; + struct vfs_context context; + char *archhandler; + + switch(arch) { + case CPU_TYPE_POWERPC: + archhandler = exec_archhandler_ppc.path; + break; + default: + return (EBADARCH); + } + + context.vc_proc = p; + context.vc_ucred = kauth_cred_get(); + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE32, + CAST_USER_ADDR_T(archhandler), &context); + error = namei(&nd); + if (error) + return (error); + nameidone(&nd); + + /* Check mount point */ + if ((nd.ni_vp->v_mount->mnt_flag & MNT_NOEXEC) || + (nd.ni_vp->v_type != VREG)) { + vnode_put(nd.ni_vp); + return (EACCES); + } + + VATTR_INIT(&va); + VATTR_WANTED(&va, va_fsid); + VATTR_WANTED(&va, va_fileid); + error = vnode_getattr(nd.ni_vp, &va, &context); + if (error) { + vnode_put(nd.ni_vp); + return (error); + } + vnode_put(nd.ni_vp); + + exec_archhandler_ppc.fsid = va.va_fsid; + exec_archhandler_ppc.fileid = (u_long)va.va_fileid; + return 0; } static int -sysctl_classichandler( +sysctl_exec_archhandler_ppc( __unused int *name, __unused u_int namelen, user_addr_t oldBuf, @@ -515,18 +567,18 @@ sysctl_classichandler( size_t len; struct nameidata nd; struct vnode_attr va; - char handler[sizeof(classichandler)]; + char handler[sizeof(exec_archhandler_ppc.path)]; struct vfs_context context; context.vc_proc = p; context.vc_ucred = kauth_cred_get(); if (oldSize) { - len = strlen(classichandler) + 1; + len = strlen(exec_archhandler_ppc.path) + 1; if (oldBuf) { if (*oldSize < len) return (ENOMEM); - error = copyout(classichandler, oldBuf, len); + error = copyout(exec_archhandler_ppc.path, oldBuf, len); if (error) return (error); } @@ -536,44 +588,26 @@ sysctl_classichandler( error = suser(context.vc_ucred, &p->p_acflag); if (error) return (error); - if (newSize >= sizeof(classichandler)) + if (newSize >= sizeof(exec_archhandler_ppc.path)) return (ENAMETOOLONG); error = copyin(newBuf, handler, newSize); if (error) return (error); handler[newSize] = 0; - - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE32, - CAST_USER_ADDR_T(handler), &context); - error = namei(&nd); + strcpy(exec_archhandler_ppc.path, handler); + error = set_archhandler(p, CPU_TYPE_POWERPC); if (error) return (error); - nameidone(&nd); - - /* Check mount point */ - if ((nd.ni_vp->v_mount->mnt_flag & MNT_NOEXEC) || - (nd.ni_vp->v_type != VREG)) { - vnode_put(nd.ni_vp); - return (EACCES); - } - - VATTR_INIT(&va); - VATTR_WANTED(&va, va_fsid); - VATTR_WANTED(&va, va_fileid); - error = vnode_getattr(nd.ni_vp, &va, &context); - if (error) { - vnode_put(nd.ni_vp); - return (error); - } - vnode_put(nd.ni_vp); - - classichandler_fsid = va.va_fsid; - classichandler_fileid = (u_long)va.va_fileid; - strcpy(classichandler, handler); } return 0; } +SYSCTL_NODE(_kern, KERN_EXEC, exec, CTLFLAG_RD, 0, ""); + +SYSCTL_NODE(_kern_exec, OID_AUTO, archhandler, CTLFLAG_RD, 0, ""); + +SYSCTL_STRING(_kern_exec_archhandler, OID_AUTO, powerpc, CTLFLAG_RD, + exec_archhandler_ppc.path, 0, ""); extern int get_kernel_symfile( struct proc *, char **); __private_extern__ int @@ -601,9 +635,11 @@ kern_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp, || name[0] == KERN_IPC || name[0] == KERN_SYSV || name[0] == KERN_AFFINITY - || name[0] == KERN_CLASSIC + || name[0] == KERN_TRANSLATE + || name[0] == KERN_EXEC || name[0] == KERN_PANICINFO - || name[0] == KERN_POSIX) + || name[0] == KERN_POSIX + || name[0] == KERN_TFP) ) return (ENOTDIR); /* overloaded */ @@ -719,12 +755,12 @@ kern_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp, case KERN_AFFINITY: return sysctl_affinity(name+1, namelen-1, oldp, oldlenp, newp, newlen, p); - case KERN_CLASSIC: - return sysctl_classic(name+1, namelen-1, oldp, oldlenp, - newp, newlen, p); + case KERN_TRANSLATE: + return sysctl_translate(name+1, namelen-1, oldp, oldlenp, newp, + newlen, p); case KERN_CLASSICHANDLER: - return sysctl_classichandler(name+1, namelen-1, oldp, oldlenp, - newp, newlen, p); + return sysctl_exec_archhandler_ppc(name+1, namelen-1, oldp, + oldlenp, newp, newlen, p); case KERN_AIOMAX: return( sysctl_aiomax( oldp, oldlenp, newp, newlen ) ); case KERN_AIOPROCMAX: @@ -851,9 +887,76 @@ kern_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp, } return(error); } + case KERN_NX_PROTECTION: + { + int old_value, new_value; + + error = 0; + if (oldp && *oldlenp < sizeof(old_value) ) + return (ENOMEM); + if ( newp && newlen != sizeof(new_value) ) + return(EINVAL); + *oldlenp = sizeof(old_value); + + old_value = nx_enabled; + + if (oldp && (error = copyout( &old_value, oldp, *oldlenp))) + return(error); +#ifdef __i386__ + /* + * Only allow setting if NX is supported on the chip + */ + if (cpuid_extfeatures() & CPUID_EXTFEATURE_XD) { +#endif + if (error == 0 && newp) + error = copyin(newp, &new_value, + sizeof(newlen)); + if (error == 0 && newp) + nx_enabled = new_value; +#ifdef __i386__ + } else if (newp) { + error = ENOTSUP; + } +#endif + return(error); + } case KERN_SHREG_PRIVATIZABLE: /* this kernel does implement shared_region_make_private_np() */ return (sysctl_rdint(oldp, oldlenp, newp, 1)); + case KERN_PROCNAME: + error = sysctl_trstring(oldp, oldlenp, newp, newlen, + &p->p_name[0], (2*MAXCOMLEN+1)); + return (error); + case KERN_THALTSTACK: + { + int old_value, new_value; + + error = 0; + if (oldp && *oldlenp < sizeof(int)) + return (ENOMEM); + if ( newp && newlen != sizeof(int) ) + return(EINVAL); + *oldlenp = sizeof(int); + old_value = (p->p_lflag & P_LTHSIGSTACK)? 1: 0; + if (oldp && (error = copyout( &old_value, oldp, sizeof(int)))) + return(error); + if (error == 0 && newp ) + error = copyin( newp, &new_value, sizeof(int) ); + if (error == 0 && newp) { + if (new_value) { + /* we cannot swich midstream if inuse */ + if ((p->p_sigacts->ps_flags & SAS_ALTSTACK) == SAS_ALTSTACK) + return(EPERM); + p->p_lflag |= P_LTHSIGSTACK; + } else { + /* we cannot swich midstream */ + if ((p->p_lflag & P_LTHSIGSTACK) == P_LTHSIGSTACK) + return(EPERM); + p->p_lflag &= ~P_LTHSIGSTACK; + } + } + return(error); + } default: return (ENOTSUP); } @@ -2095,3 +2198,98 @@ sysctl_maxproc(user_addr_t oldp, size_t *oldlenp, return( error ); } /* sysctl_maxproc */ + +#if __i386__ +static int +sysctl_sysctl_exec_affinity SYSCTL_HANDLER_ARGS +{ + struct proc *cur_proc = req->p; + int error; + + if (req->oldptr != USER_ADDR_NULL) { + cpu_type_t oldcputype = (cur_proc->p_flag & P_AFFINITY) ? CPU_TYPE_POWERPC : CPU_TYPE_I386; + if ((error = SYSCTL_OUT(req, &oldcputype, sizeof(oldcputype)))) + return error; + } + + if (req->newptr != USER_ADDR_NULL) { + cpu_type_t newcputype; + if ((error = SYSCTL_IN(req, &newcputype, sizeof(newcputype)))) + return error; + if (newcputype == CPU_TYPE_I386) + cur_proc->p_flag &= ~P_AFFINITY; + else if (newcputype == CPU_TYPE_POWERPC) + cur_proc->p_flag |= P_AFFINITY; + else + return (EINVAL); + } + + return 0; +} +SYSCTL_PROC(_sysctl, OID_AUTO, proc_exec_affinity, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0, sysctl_sysctl_exec_affinity ,"I","proc_exec_affinity"); +#endif + +static int +fetch_process_cputype( + struct proc *cur_proc, + int *name, + u_int namelen, + cpu_type_t *cputype) +{ + struct proc *p = NULL; + cpu_type_t ret = 0; + + if (namelen == 0) + p = cur_proc; + else if (namelen == 1) { + p = pfind(name[0]); + if (p == NULL) + return (EINVAL); + if ((kauth_cred_getuid(p->p_ucred) != kauth_cred_getuid(kauth_cred_get())) + && suser(kauth_cred_get(), &cur_proc->p_acflag)) + return (EPERM); + } else { + return EINVAL; + } + +#if __i386__ + if (p->p_flag & P_TRANSLATED) { + ret = CPU_TYPE_POWERPC; + } + else +#endif + { + ret = cpu_type(); + if (IS_64BIT_PROCESS(p)) + ret |= CPU_ARCH_ABI64; + } + *cputype = ret; + + return 0; +} + +static int +sysctl_sysctl_native SYSCTL_HANDLER_ARGS +{ + int error; + cpu_type_t proc_cputype = 0; + if ((error = fetch_process_cputype(req->p, (int *)arg1, arg2, &proc_cputype)) != 0) + return error; + int res = 1; + if ((proc_cputype & ~CPU_ARCH_MASK) != (cpu_type() & ~CPU_ARCH_MASK)) + res = 0; + return SYSCTL_OUT(req, &res, sizeof(res)); +} +SYSCTL_PROC(_sysctl, OID_AUTO, proc_native, CTLTYPE_NODE|CTLFLAG_RD, 0, 0, sysctl_sysctl_native ,"I","proc_native"); + +static int +sysctl_sysctl_cputype SYSCTL_HANDLER_ARGS +{ + int error; + cpu_type_t proc_cputype = 0; + if ((error = fetch_process_cputype(req->p, (int *)arg1, arg2, &proc_cputype)) != 0) + return error; + return SYSCTL_OUT(req, &proc_cputype, sizeof(proc_cputype)); +} +SYSCTL_PROC(_sysctl, OID_AUTO, proc_cputype, CTLTYPE_NODE|CTLFLAG_RD, 0, 0, sysctl_sysctl_cputype ,"I","proc_cputype"); +