kernel_sysctlbyname("kern.hostname") returns EPERM

Attempting to acquire the value of the 'kern.hostname' ctl from a kext by calling sysctlbyname() returns EPERM with no hostname returned. sysctlbyname() is aliased to kernel_sysctlbyname():

config/Libkern.exports:839:_sysctlbyname:_kernel_sysctlbyname

Looking at the implementation of kernel_sysctlbyname(), EPERM is returned by sysctl_root(). Not sure how to correctly identify the point of failure.

Alternately, calling

sysctlbyname("hw.ncpu")

does return the value set for the ctl.

The kext was compiled with SYSCTL_DEF_ENABLED defined to have the relevant section of sys/sysctl.h enabled.

bsd_hostname() is a private symbol which is inaccessible to my kext.

% sysctl -n kern.hostname

does return the host name, so the ctl must be set.

Is it possible to get the name of a host from the context of my kext?

Thanks.

Answered by DTS Engineer in 819757022

Looking at the implementation of kernel_sysctlbyname(), EPERM is returned by sysctl_root(). Not sure how to correctly identify the point of failure.

I believe your EPERM failure is coming from this check in sysctl_root:

/*
 * If we're inside the kernel, the OID must be marked as kernel-valid.
 */
if (from_kernel && !(oid->oid_kind & CTLFLAG_KERN))
{
	error = (EPERM);
	goto err;
}

‎sysctl_hostname‎ is defined here and is not marked with CTLFLAG_KERN, and is thus not available in the kernel:

SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
		CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_LOCKED,
		0, 0, sysctl_hostname, "A", "");

Note: On some of our platforms, the full implementation of sysctl_hostname includes additional checks entitlement checks that are not included in the code above. On those platforms, kern.hostname won't work in user space unless the process has the "com.apple.developer.device-information.user-assigned-device-name" entitlement.

bsd_hostname() is a private symbol which is inaccessible to my kext.

FYI, as far as I can tell, "bsd_hostname" is effectively "dead" code. It doesn't appear to be used by XNU or any current KEXT.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Accepted Answer

Looking at the implementation of kernel_sysctlbyname(), EPERM is returned by sysctl_root(). Not sure how to correctly identify the point of failure.

I believe your EPERM failure is coming from this check in sysctl_root:

/*
 * If we're inside the kernel, the OID must be marked as kernel-valid.
 */
if (from_kernel && !(oid->oid_kind & CTLFLAG_KERN))
{
	error = (EPERM);
	goto err;
}

‎sysctl_hostname‎ is defined here and is not marked with CTLFLAG_KERN, and is thus not available in the kernel:

SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
		CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_LOCKED,
		0, 0, sysctl_hostname, "A", "");

Note: On some of our platforms, the full implementation of sysctl_hostname includes additional checks entitlement checks that are not included in the code above. On those platforms, kern.hostname won't work in user space unless the process has the "com.apple.developer.device-information.user-assigned-device-name" entitlement.

bsd_hostname() is a private symbol which is inaccessible to my kext.

FYI, as far as I can tell, "bsd_hostname" is effectively "dead" code. It doesn't appear to be used by XNU or any current KEXT.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

kernel_sysctlbyname("kern.hostname") returns EPERM
 
 
Q