Beispiel #1
0
static int
darwin_sysctl_redispatch(SYSCTLFN_ARGS)
{

	/*
	 * put namelen and name back at the top
	 */
	namelen += (name - oname);
	name = oname;

	/*
	 * call into (via NULL) main native tree
	 */
	return sysctl_dispatch(SYSCTLFN_CALL(NULL));
}
Beispiel #2
0
int
netbsd32___sysctl(struct lwp *l, const struct netbsd32___sysctl_args *uap, register_t *retval)
{
	/* {
		syscallarg(netbsd32_intp) name;
		syscallarg(u_int) namelen;
		syscallarg(netbsd32_voidp) old;
		syscallarg(netbsd32_size_tp) oldlenp;
		syscallarg(netbsd32_voidp) new;
		syscallarg(netbsd32_size_t) newlen;
	} */
	const struct sysctlnode *pnode;
	netbsd32_size_t netbsd32_oldlen;
	size_t oldlen, *oldlenp, savelen;
	int name[CTL_MAXNAME], error, nerror, *namep;
	void *newp, *oldp;

	/*
	 * get and convert 32 bit size_t to native size_t
	 */
	namep = SCARG_P32(uap, name);
	oldp = SCARG_P32(uap, oldv);
	newp = SCARG_P32(uap, newv);
	oldlenp = SCARG_P32(uap, oldlenp);
	oldlen = 0;
	if (oldlenp != NULL) {
		error = copyin(oldlenp, &netbsd32_oldlen,
			       sizeof(netbsd32_oldlen));
		if (error)
			return (error);
		oldlen = netbsd32_oldlen;
	}
	savelen = oldlen;

	/*
	 * retrieve name and see if we need to dispatch this query to
	 * the shadow tree.  if we find it in the shadow tree,
	 * dispatch to there, otherwise NULL means use the built-in
	 * default main tree.
	 */
	if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 1)
		return (EINVAL);
	error = copyin(namep, &name[0], SCARG(uap, namelen) * sizeof(int));
        if (error)
                return (error);

	ktrmib(name, SCARG(uap, namelen));

	sysctl_lock(newp != NULL);
	pnode = &netbsd32_sysctl_root;
	error = sysctl_locate(l, &name[0], SCARG(uap, namelen), &pnode, NULL);
	pnode = (error == 0) ? &netbsd32_sysctl_root : NULL;
	error = sysctl_dispatch(&name[0], SCARG(uap, namelen),
				oldp, &oldlen,
				newp, SCARG(uap, newlen),
				&name[0], l, pnode);
	sysctl_unlock();

	/*
	 * reset caller's oldlen, even if we got an error
	 */
	if (oldlenp) {
		netbsd32_oldlen = oldlen;
                nerror = copyout(&netbsd32_oldlen, oldlenp,
				 sizeof(netbsd32_oldlen));
                if (error == 0)
                        error = nerror;
	}

	/*
	 * if the only problem is that we weren't given enough space,
	 * that's an ENOMEM error
	 */
	if (error == 0 && oldp != NULL && savelen < oldlen)
		error = ENOMEM;

	return (error);
}
Beispiel #3
0
/*
 * linux sysctl system call
 */
int
linux_sys___sysctl(struct lwp *l, const struct linux_sys___sysctl_args *uap, register_t *retval)
{
	struct linux___sysctl ls;
	int error, nerror, name[CTL_MAXNAME];
	size_t savelen = 0, oldlen = 0;

	/*
	 * get linux args structure
	 */
	if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
		return error;

	/*
	 * get oldlen
	 */
	oldlen = 0;
	if (ls.oldlenp != NULL) {
		error = copyin(ls.oldlenp, &oldlen, sizeof(oldlen));
		if (error)
			return (error);
	}
	savelen = oldlen;

	/*
	 * top-level sysctl names may or may not be non-terminal, but
	 * we don't care
	 */
	if (ls.nlen > CTL_MAXNAME || ls.nlen < 1)
		return (ENOTDIR);
	error = copyin(ls.name, &name, ls.nlen * sizeof(int));
	if (error)
		return (error);

	ktrmib(name, ls.nlen);

	/*
	 * dispatch request into linux sysctl tree
	 */
	sysctl_lock(ls.newval != NULL);
	error = sysctl_dispatch(&name[0], ls.nlen,
				ls.oldval, &oldlen,
				ls.newval, ls.newlen,
				&name[0], l, &linux_sysctl_root);
	sysctl_unlock();

	/*
	 * reset caller's oldlen, even if we got an error
	 */
	if (ls.oldlenp) {
		nerror = copyout(&oldlen, ls.oldlenp, sizeof(oldlen));
		if (error == 0)
			error = nerror;
	}

	/*
	 * if the only problem is that we weren't given enough space,
	 * that's an ENOMEM error
	 */
	if (error == 0 && ls.oldval != NULL && savelen < oldlen)
		error = ENOMEM;

	return (error);
}
Beispiel #4
0
/*
 * Linux compatible /proc/version. Only active when the -o linux
 * mountflag is used.
 */
int
procfs_doversion(struct lwp *curl, struct proc *p,
    struct pfsnode *pfs, struct uio *uio)
{
	char *bf;
	char lostype[20], losrelease[20], lversion[80];
	const char *postype, *posrelease, *pversion;
	const char *emulname = curlwp->l_proc->p_emul->e_name;
	int len;
	int error = 0;
	int nm[4];
	size_t buflen;

	CTASSERT(EMUL_LINUX_KERN_OSTYPE == EMUL_LINUX32_KERN_OSTYPE);
	CTASSERT(EMUL_LINUX_KERN_OSRELEASE == EMUL_LINUX32_KERN_OSRELEASE);
	CTASSERT(EMUL_LINUX_KERN_VERSION == EMUL_LINUX32_KERN_VERSION);

	bf = malloc(LBFSZ, M_TEMP, M_WAITOK);

	sysctl_lock(false);

	if (strncmp(emulname, "linux", 5) == 0) {
		/*
		 * Lookup the emulation ostype, osrelease, and version.
		 * Since compat_linux and compat_linux32 can be built as
		 * modules, we use sysctl to obtain the values instead of
		 * using the symbols directly.
		 */

		if (strcmp(emulname, "linux32") == 0) {
			nm[0] = CTL_EMUL;
			nm[1] = EMUL_LINUX32;
			nm[2] = EMUL_LINUX32_KERN;
		} else {
			nm[0] = CTL_EMUL;
			nm[1] = EMUL_LINUX;
			nm[2] = EMUL_LINUX_KERN;
		}

		nm[3] = EMUL_LINUX_KERN_OSTYPE;
		buflen = sizeof(lostype);
		error = sysctl_dispatch(nm, __arraycount(nm),
		    lostype, &buflen,
		    NULL, 0, NULL, NULL, NULL);
		if (error)
			goto out;

		nm[3] = EMUL_LINUX_KERN_OSRELEASE;
		buflen = sizeof(losrelease);
		error = sysctl_dispatch(nm, __arraycount(nm),
		    losrelease, &buflen,
		    NULL, 0, NULL, NULL, NULL);
		if (error)
			goto out;

		nm[3] = EMUL_LINUX_KERN_VERSION;
		buflen = sizeof(lversion);
		error = sysctl_dispatch(nm, __arraycount(nm),
		    lversion, &buflen,
		    NULL, 0, NULL, NULL, NULL);
		if (error)
			goto out;

		postype = lostype;
		posrelease = losrelease;
		pversion = lversion;
	} else {
		postype = ostype;
		posrelease = osrelease;
		strlcpy(lversion, version, sizeof(lversion));
		if (strchr(lversion, '\n'))
			*strchr(lversion, '\n') = '\0';
		pversion = lversion;
	}

	len = snprintf(bf, LBFSZ,
		"%s version %s (%s@localhost) (gcc version %s) %s\n",
		postype, posrelease, emulname,
#ifdef __VERSION__
		__VERSION__,
#else
		"unknown",
#endif
		pversion);

	if (len == 0)
		goto out;

	error = uiomove_frombuf(bf, len, uio);
out:
	free(bf, M_TEMP);
	sysctl_unlock();
	return error;
}
Beispiel #5
0
int
linux32_sys___sysctl(struct lwp *l, const struct linux32_sys___sysctl_args *uap, register_t *retval)
{
	/* {
		syscallarg(linux32___sysctlp_t) lsp;
	} */
	struct linux32_sysctl ls32;
	int name[CTL_MAXNAME];
	size_t savelen;
	netbsd32_size_t oldlen32;
	size_t oldlen;
	int error;

	/*
	 * Read sysctl arguments 
	 */
	if ((error = copyin(SCARG_P32(uap, lsp), &ls32, sizeof(ls32))) != 0)
		return error;

	/*
	 * Read oldlen
	 */
	if (NETBSD32PTR64(ls32.oldlenp) != NULL) {
		if ((error = copyin(NETBSD32PTR64(ls32.oldlenp), 
		    &oldlen32, sizeof(oldlen32))) != 0)
			return error;
	} else {
		oldlen32 = 0;
	}

	savelen = (size_t)oldlen32;

	/* 
	 * Sanity check nlen
	 */
	if ((ls32.nlen > CTL_MAXNAME) || (ls32.nlen < 1))
		return ENOTDIR;

	/*
	 * Read the sysctl name
	 */
	if ((error = copyin(NETBSD32PTR64(ls32.name), &name, 
	   ls32.nlen * sizeof(int))) != 0)
		return error;

	ktrmib(name, ls32.nlen);
	/*
	 * First try linux32 tree, then linux tree
	 */
	oldlen = (size_t)oldlen32;
	sysctl_lock(NETBSD32PTR64(ls32.newval) != NULL);
	error = sysctl_dispatch(name, ls32.nlen,
				NETBSD32PTR64(ls32.oldval), &oldlen,
				NETBSD32PTR64(ls32.newval), ls32.newlen,
				name, l, &linux32_sysctl_root);
	oldlen32 = (netbsd32_size_t)oldlen;
	sysctl_unlock();

	/*
	 * Check for oldlen overflow (not likely, but who knows...)
	 */
	if (oldlen != oldlen32) {
#ifdef DEBUG_LINUX
		printf("%s: oldlen32 = %d, oldlen = %ld\n", 
		    __func__, oldlen32, oldlen);
#endif
		return EINVAL;
	}

	/*
	 * set caller's oldlen, even if we got an error
	 */
	if (NETBSD32PTR64(ls32.oldlenp)) {
		int nerror;

		nerror = copyout(&oldlen32, 
		    NETBSD32PTR64(ls32.oldlenp), sizeof(oldlen32));

		if (error == 0)
			error = nerror;
	}

	/*
	 * oldlen was too short
	 */
	if ((error == 0) && 
	    (NETBSD32PTR64(ls32.oldval) != NULL) &&
	    (savelen < oldlen32))
		error = ENOMEM;

	return error;
}