Page 1 of 1

Passing file descriptor from kernel to process

PostPosted: Tue May 16, 2017 6:30 am
by adam81
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.


Re: Passing file descriptor from kernel to process

PostPosted: Wed May 17, 2017 11:39 am
by morpheus
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.

Re: Passing file descriptor from kernel to process

PostPosted: Thu Jun 01, 2017 10:33 am
by adam81
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

Re: Passing file descriptor from kernel to process

PostPosted: Thu Jun 01, 2017 1:55 pm
by morpheus
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.