I have a kext that needs to know what version of OS X it is running on. CocoaDev has an article which describes how to get the OS X version info using Gestalt(), but the code requires Cocoa.
Can I call Gestalt() from a kext?
If so, what #include do I use to define it?
If not, are there any other solutions?
Background:
I'd like to use the same kexts in on all versions of OS X from 10.4 through 10.7.
BUT: The kexts call cdevsw_add, which was changed in Lion in a non-backward-compatible way. Along with (apparently) changes to some kernel programs that call it, the changes mean — per the comment before the routine — that cdevsw_add should be called with a different first argument on 10.7 than on OS X 10.0 through 10.6. (-12 on Lion, -1 on earlier versions.)
If the kexts can determine which version of OS X they are running on, it's easy. (If not, it will be a pain to do — maybe a horrible kludge like building two different versions of the kexts and having the kext-loading code pick which one to load.)
Kernel.framework provides <libkern/version.h>. There are declared some extern variables like version_major, version_minor etc. AFAIK those are exported from the libkern.kpi.
Hope it helps.
You can use sysctl to get the kernel version (scroll down to method 3). It allegedly works when you develop kernel modules.
Here's an example of the method, in case the site ever goes down.
#include <sys/param.h>
#include <sys/sysctl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int mib[] = {CTL_KERN, KERN_OSRELEASE};
size_t len;
sysctl(mib, sizeof mib / sizeof(int), NULL, &len, NULL, 0);
char* kernelVersion = malloc(len);
sysctl(mib, sizeof mib / sizeof(int), kernelVersion, &len, NULL, 0);
printf("Kernel version is %s\n", kernelVersion);
free(kernelVersion);
}
Of course, you'll need to figure out the kernel versions of Snow Leopard and Lion, but that shouldn't be very hard. (I can testify that the kernel version of the current Lion release is 11.0.0.)
Related
On Linux, you can allocate memory at a specific address like so:
void *foo = (void *)0xDEADBEEF;
size_t MyLength = 1024;
void *bar = mmap(foo, MyLength, PROT_READ | PROT_WRITE | MAP_ANONYMOUS | MAP_FIXED, MAP_PRIVATE, -1, 0);
Is this same method also possible on Mac OS, or if not, how does one do this on Mac OS?
My goal is to write a kernel extension to map out (and thus disable) a region of defective memory on a MacBook Pro with a non-removable defective RAM chip.
This is std C. It compiles fine on Xcode. Make sure to add:
#include <sys/mman.h>
Before you invest too much time writing a kernel extension for macOS be aware of its deprecation.
I am trying to port the fantastic ASUS XONAR-series driver for Linux, written by Clemens Ladisch, to Mac OSX.
Right now, a very rough version that compiles is available at: github.com/i3roly/CMI8788
My question is regarding the pthread.h header for OSX. By default, including pthread.h tries to define a structure that is markedly different from the one included through the IOKit drivers. for brevity i will use an informative post from a github post(https://github.com/civetweb/civetweb/issues/364#issuecomment-255438891):
#include <pthread.h>
#include <sys/_types/_mach_port_t.h>
typedef __darwin_mach_port_t mach_port_t;
versus
#include <IOKit/audio/IOAudioDevice.h>
#include <IOKit/IOService.h>
#include <IOKit/IORegistryEntry.h>
#include <IOKit/IOTypes.h>
#include <IOKit/system.h>
#include <mach/mach_types.h>
#include <mach/host_info.h>
#include <mach/message.h>
#include <mach/port.h>
/*
* For kernel code that resides outside of Mach proper, we opaque the
* port structure definition.
*/
struct ipc_port;
typedef struct ipc_port *ipc_port_t;
#define IPC_PORT_NULL ((ipc_port_t) 0UL)
#define IPC_PORT_DEAD ((ipc_port_t)~0UL)
#define IPC_PORT_VALID(port) \
((port) != IPC_PORT_NULL && (port) != IPC_PORT_DEAD)
typedef ipc_port_t mach_port_t;
now, i can get around this by doing
#define _MACH_PORT_T
#include <pthread.h>
but i am not sure if this is a safe solution, since to me it seems the pthreads API for Xcode implies it is only to be used for user-land programs. is this assumption wrong? is using this macro to get around the redefinition problem a reasonable one?
have others tried to write kernel land drivers for OSX using pthreads, and encountered this issue? any insight would be appreciated.
thank you.
stupid question.
i don't know why i didn't remind myself that you CANNOT USE PTHREADS IN KERNEL, especially when i have experience building the linux kernel (which should have served as an easy reminder that YOU CANNOT DO THIS AND IT IS A BAD IDEA)
hits self over the head with a slipper
i have no idea why this didn't click yesterday.
This is my code that works only on Xcode (version 4.5):
#include <stdio.h>
#include <mach/mach_init.h>
#include <mach/mach_vm.h>
#include <sys/types.h>
#include <mach/mach.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <Security/Authorization.h>
int main(int argc, const char * argv[]) {
char test[14] = "Hello World! "; //0x7fff5fbff82a
char value[14] = "Hello Hacker!";
char test1[14];
pointer_t buf;
uint32_t sz;
task_t task;
task_for_pid(current_task(), getpid(), &task);
if (vm_write(current_task(), 0x7fff5fbff82a, (pointer_t)value, 14) == KERN_SUCCESS) {
printf("%s\n", test);
//getchar();
}
if (vm_read(task, 0x7fff5fbff82a, sizeof(char) * 14, &buf, &sz) == KERN_SUCCESS) {
memcpy(test1, (const void *)buf, sz);
printf("%s", test1);
}
return 0;
}
I was trying also ptrace and other things, this is why I include other libraries too.
The first problem is that this works only on Xcode, I can find with the debugger the position (memory address) of a variable (in this case of test), so I change the string with the one on value and then I copy the new value on test on test1.
I actually don't understand how vm_write works (not completely) and the same for task_for_pid(), the 2° problem is that I need to read and write on another process, this is only a test for see if the functions works on the same process, and it works (only on Xcode).
How I can do that on other processes? I need to read a position (how I can find the address of "something"?), this is the first goal.
For your problems, there are solutions:
The first problem: OS X has address space layout randomization. If you want to make your memory images fixed and predictable, you have to compile your code with NOPIE setting. This setting (PIE = Position Independent Executable), is responsible for allowing ASLR, which "slides" the memory by some random value, which changes on every instance.
I actually don't understand how vm_write works (not completely) and the same for task_for_pid():
The Mach APIs operate on the lower level abstractions of "task" and "Thread" which correspond roughly to that of the BSD "process" and "(u)thread" (there are some exceptions, e.g. kernel_task, which does not have a PID, but let's ignore that for now). task_for_pid obtains the task port (think of it as a "handle"), and if you get the port - you are free to do whatever you wish. Basically, the vm_* functions operate on any task port - you can use it on your own process (mach_task_self(), that is), or a port obtained from task_for_pid.
Task for PID actually doesn't necessarily require root (i.e. "sudo"). It requires getting past taskgated on OSX, which traditionally verified membership in procmod or procview groups. You can configure taskgated ( /System/Library/LaunchDaemons/com.apple.taskgated.plist) for debugging purposes. Ultimately, btw, getting the task port will require an entitlement (the same as it now does on iOS). That said, the easiest way, rather than mucking around with system authorizations, etc, is to simply become root.
Did you try to run your app with "sudo"?
You can't read/write other app's memory without sudo.
I have been using Unimotion in my application to read motion sensor values for Apple laptops, but have been unable to port the code to 10.6 64-bit. (I have also tried SMSLib and had the no luck either.)
Is there any simple 10.6 compatible
SMS API?
If there is no alternative, I am also considering patching one of the libraries. Both Unimotion and SMSLib use the following call, which has been deprecated in 10.5 and removed from 10.6 64-bit:
result = IOConnectMethodStructureIStructureO(
dataPort, kernFunc, structureInputSize,
&structureOutputSize, &inputStructure,
outputStructure);
Is there any simple way to replace
this with new IOKit calls?
(This post did not really get me much further)
If there is no alternative, I am also considering patching one of the libraries. Both Unimotion and SMSLib use the following call, which has been deprecated in 10.5 and removed from 10.6 64-bit:
result = IOConnectMethodStructureIStructureO(
dataPort, kernFunc, structureInputSize,
&structureOutputSize, &inputStructure,
outputStructure);
Is there any simple way to replace this with new IOKit calls?
That very document suggests replacements. What about this one?
kern_return_t
IOConnectCallStructMethod(
mach_port_t connection, // In
uint32_t selector, // In
const void *inputStruct, // In
size_t inputStructCnt, // In
void *outputStruct, // Out
size_t *outputStructCnt) // In/Out
As far as I can tell, there should be no difference except for the order of the arguments. That said, I've never used I/O Kit, so I could be missing some critical conceptual difference that will make this call not work as the old one did.
I haven't used this in 10.6, but does this work?
http://code.google.com/p/google-mac-qtz-patches/
We're trying to find out how much physical memory is installed in a machine running Mac OS X. We've found the BSD function sysctl(). The problem is this function wants to return a 32 bit value but some Macs are able to address up to 32 GB which will not fit in a 32 bit value. (Actually even 4 GB won't fit in a 32 bit value.) Is there another API available on OS X (10.4 or later) that will give us this info?
The answer is to use sysctl to get hw.memsize as was suggested in a previous answer. Here's the actual code for doing that.
#include <sys/types.h>
#include <sys/sysctl.h>
...
int mib[2];
int64_t physical_memory;
size_t length;
// Get the Physical memory size
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
length = sizeof(int64_t);
sysctl(mib, 2, &physical_memory, &length, NULL, 0);
Did you try googling?
This seems to be the answer:
http://lists.apple.com/archives/scitech/2005/Aug/msg00004.html
sysctl() does work, you just need to fetch hw.memsize instead of hw.physmem. hw.memsize will give you a uint64_t, so no 32 bit problem.
From Obtaining a Mac’s System Profiler data from shell:
Use system_profiler.
Alternatively you can add the data from vm_statistics_data_t to get the total memory
vm_statistics_data_t vm_stat;
int count = HOST_VM_INFO_COUNT;
kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (integer_t*)&vm_stat, (mach_msg_type_number_t*)&count);