+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of concurrent aio requests. Makes sure
+ * the system wide limit is greater than the per process
+ * limit.
+ */
+static int
+sysctl_aiomax(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen)
+{
+ int error = 0;
+ int new_value;
+
+ if ( oldp && *oldlenp < sizeof(int) )
+ return (ENOMEM);
+ if ( newp && newlen != sizeof(int) )
+ return (EINVAL);
+
+ *oldlenp = sizeof(int);
+ if ( oldp )
+ error = copyout( &aio_max_requests, oldp, sizeof(int) );
+ if ( error == 0 && newp )
+ error = copyin( newp, &new_value, sizeof(int) );
+ if ( error == 0 && newp ) {
+ if ( new_value >= aio_max_requests_per_process )
+ aio_max_requests = new_value;
+ else
+ error = EINVAL;
+ }
+ return( error );
+
+} /* sysctl_aiomax */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of concurrent aio requests per process.
+ * Makes sure per process limit is less than the system wide
+ * limit.
+ */
+static int
+sysctl_aioprocmax(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen )
+{
+ int error = 0;
+ int new_value = 0;
+
+ if ( oldp && *oldlenp < sizeof(int) )
+ return (ENOMEM);
+ if ( newp && newlen != sizeof(int) )
+ return (EINVAL);
+
+ *oldlenp = sizeof(int);
+ if ( oldp )
+ error = copyout( &aio_max_requests_per_process, oldp, sizeof(int) );
+ if ( error == 0 && newp )
+ error = copyin( newp, &new_value, sizeof(int) );
+ if ( error == 0 && newp ) {
+ if ( new_value <= aio_max_requests && new_value >= AIO_LISTIO_MAX )
+ aio_max_requests_per_process = new_value;
+ else
+ error = EINVAL;
+ }
+ return( error );
+
+} /* sysctl_aioprocmax */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of async IO worker threads.
+ * We only allow an increase in the number of worker threads.
+ */
+static int
+sysctl_aiothreads(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen)
+{
+ int error = 0;
+ int new_value;
+
+ if ( oldp && *oldlenp < sizeof(int) )
+ return (ENOMEM);
+ if ( newp && newlen != sizeof(int) )
+ return (EINVAL);
+
+ *oldlenp = sizeof(int);
+ if ( oldp )
+ error = copyout( &aio_worker_threads, oldp, sizeof(int) );
+ if ( error == 0 && newp )
+ error = copyin( newp, &new_value, sizeof(int) );
+ if ( error == 0 && newp ) {
+ if (new_value > aio_worker_threads ) {
+ _aio_create_worker_threads( (new_value - aio_worker_threads) );
+ aio_worker_threads = new_value;
+ }
+ else
+ error = EINVAL;
+ }
+ return( error );
+
+} /* sysctl_aiothreads */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of processes per UID.
+ * Makes sure per UID limit is less than the system wide limit.
+ */
+static int
+sysctl_maxprocperuid(user_addr_t oldp, size_t *oldlenp,
+ user_addr_t newp, size_t newlen)
+{
+ int error = 0;
+ int new_value;
+
+ if ( oldp != USER_ADDR_NULL && *oldlenp < sizeof(int) )
+ return (ENOMEM);
+ if ( newp != USER_ADDR_NULL && newlen != sizeof(int) )
+ return (EINVAL);
+
+ *oldlenp = sizeof(int);
+ if ( oldp != USER_ADDR_NULL )
+ error = copyout( &maxprocperuid, oldp, sizeof(int) );
+ if ( error == 0 && newp != USER_ADDR_NULL ) {
+ error = copyin( newp, &new_value, sizeof(int) );
+ if ( error == 0 ) {
+ AUDIT_ARG(value, new_value);
+ if ( new_value <= maxproc && new_value > 0 )
+ maxprocperuid = new_value;
+ else
+ error = EINVAL;
+ }
+ else
+ error = EINVAL;
+ }
+ return( error );
+
+} /* sysctl_maxprocperuid */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for max number of files per process.
+ * Makes sure per process limit is less than the system-wide limit.
+ */
+static int
+sysctl_maxfilesperproc(user_addr_t oldp, size_t *oldlenp,
+ user_addr_t newp, size_t newlen)
+{
+ int error = 0;
+ int new_value;
+
+ if ( oldp != USER_ADDR_NULL && *oldlenp < sizeof(int) )
+ return (ENOMEM);
+ if ( newp != USER_ADDR_NULL && newlen != sizeof(int) )
+ return (EINVAL);
+
+ *oldlenp = sizeof(int);
+ if ( oldp != USER_ADDR_NULL )
+ error = copyout( &maxfilesperproc, oldp, sizeof(int) );
+ if ( error == 0 && newp != USER_ADDR_NULL ) {
+ error = copyin( newp, &new_value, sizeof(int) );
+ if ( error == 0 ) {
+ AUDIT_ARG(value, new_value);
+ if ( new_value < maxfiles && new_value > 0 )
+ maxfilesperproc = new_value;
+ else
+ error = EINVAL;
+ }
+ else
+ error = EINVAL;
+ }
+ return( error );
+
+} /* sysctl_maxfilesperproc */
+
+
+/*
+ * Validate parameters and get old / set new parameters
+ * for the system-wide limit on the max number of processes.
+ * Makes sure the system-wide limit is less than the configured hard
+ * limit set at kernel compilation.
+ */
+static int
+sysctl_maxproc(user_addr_t oldp, size_t *oldlenp,
+ user_addr_t newp, size_t newlen )
+{
+ int error = 0;
+ int new_value;
+
+ if ( oldp != USER_ADDR_NULL && *oldlenp < sizeof(int) )
+ return (ENOMEM);
+ if ( newp != USER_ADDR_NULL && newlen != sizeof(int) )
+ return (EINVAL);
+
+ *oldlenp = sizeof(int);
+ if ( oldp != USER_ADDR_NULL )
+ error = copyout( &maxproc, oldp, sizeof(int) );
+ if ( error == 0 && newp != USER_ADDR_NULL ) {
+ error = copyin( newp, &new_value, sizeof(int) );
+ if ( error == 0 ) {
+ AUDIT_ARG(value, new_value);
+ if ( new_value <= hard_maxproc && new_value > 0 )
+ maxproc = new_value;
+ else
+ error = EINVAL;
+ }
+ else
+ error = EINVAL;
+ }
+ 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");
+