Passing file descriptor from kernel to process

Questions and Answers about all things *OS (macOS, iOS, tvOS, watchOS)

Passing file descriptor from kernel to process

Postby adam81 » Tue May 16, 2017 6:30 am

Hello my friend.
First, I'd say that I'm a longtime dedicated reader of this forum which taught me a lot about OS X.

Now I'm building a daemon which sends notifications about files that are being opened for read.
For that I'm using kext that runs kauth framework kernel notifications which is pretty straightforward.

But now I also want to be able to read those files from my daemon context which runs under root privilege.
However, if I try to read files from a remote mount drive, I must have the same credentials as the process that read the file.
I could do it from the kernel context of the process that read the file using 'ctx' and 'vnode' which are inputs to kauth vnode scope callback

Code: Select all
          kauth_cred_t vp_cred = vfs_context_ucred(ctx);
          char *buf = NULL;
          buf = (char *)IOMalloc(file_size);

          int kret = vn_rdwr(UIO_READ, vp, (caddr_t)buf,
                         file_size, 0, UIO_SYSSPACE, 0, vp_cred, &resid, proc);


So I want to pass the reading credentials and other relevant information about the file from the kauth context to my daemon and somehow create a file descriptor
to be able to read the file from user-land.

I know that there's a way of doing this file descriptor duplication between 2 seperate processes using the syscall sendmsg/recvmsg with cmsg type of SCM_RIGHTS.
but this require the cooperation of the reading process to perform the sendmsg properly ...

my question is whether there's a way to pass the file descriptor from kernel space (from the kauth callback function) or to create such descriptor from the credentials and file vnode. I gave up trying to look for KPI, but perhaps there's an easy way to do so using non-exported symbols.

thanks,
Adam
adam81
 
Posts: 18
Joined: Mon Jan 25, 2016 9:26 am

Re: Passing file descriptor from kernel to process

Postby morpheus » Wed May 17, 2017 11:39 am

Hi Adam,

The FD is a kernel object. You can't just pass it around. What you need to do is copy it into the target process as a struct fileproc * into the process' fd_ofiles. This will magically "open" the file for the user mode process, but you'll still need to indicate the descriptor number to user space somehow.For sample code, look at the implementation of dup2() in kernel.
morpheus
Site Admin
 
Posts: 532
Joined: Thu Apr 11, 2013 6:24 pm

Re: Passing file descriptor from kernel to process

Postby adam81 » Thu Jun 01, 2017 10:33 am

Thanks for your reply Morpheus,

The reference from dup2 indeed helped me to achieve my goal.
However, I just found another interesting approach using Mach mechanism for doing this `fileport_makeport` and `fileport_makefd`. This is not public API, but if I pass this obstacle, would it be possible to use this method to achieve my goal ? can I call `fileport_makeport` from my kauth callback event, and catch it with `fileport_makeport` from my daemon ? perhaps do you have some reference for sending mach message from kernel to user entity ?

thanks again
Adam
adam81
 
Posts: 18
Joined: Mon Jan 25, 2016 9:26 am

Re: Passing file descriptor from kernel to process

Postby morpheus » Thu Jun 01, 2017 1:55 pm

file ports are a Mach construct introduced in 10.7 (xnu 1699) when AAPL realized that they can pass ports in Mach messages, but not file descriptors. So the idea is to simply box an FD in a Mach port. Then the kernel copies the port, but if fact copies the descriptor.

Passing a message from kernel to user is a simple matter - mach_msg_from_kernel_proper. but bear in mind that you would have to sift through the process' ipc_space to find the destination port. Otherwise, the kernel can only "see" host/task/thread special ports, which it owns anyway.
morpheus
Site Admin
 
Posts: 532
Joined: Thu Apr 11, 2013 6:24 pm


Return to Questions and Answers

Who is online

Users browsing this forum: No registered users and 0 guests