]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_sysctl.c
xnu-792.18.15.tar.gz
[apple/xnu.git] / bsd / kern / kern_sysctl.c
index 0d1b7d533c950089b469971f50b6162680c5b9e3..292085e1d84f5dfba4bb0717f993b5274bd958d8 100644 (file)
@@ -108,9 +108,14 @@ extern vm_map_t bsd_pageable_map;
 #include <pexpert/pexpert.h>
 
 #include <machine/machine_routines.h>
+#include <machine/exec.h>
 
 #include <vm/vm_protos.h>
 
+#ifdef __i386__
+#include <i386/cpuid.h>
+#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");
+