Mount approval callback on mac OS X

743 views Asked by At

I want to Authorize USB/CD on Mac OS X. Now i am using DiskArbitration framework to get MountApprovalCallback in user mode. But the problem with this callback is that there is no assurance of it. And if i'll get callback i am using CFUserNotificationReceiveResponse() to accept password from user. But when prompt is shown at the same time user can open DiskUtility and can mount a device

So,

  1. Is there any other way to get mount approval callback or to authorize a device?
  2. How i can handle it in kernel mode?

Thanks in advance.

1

There are 1 answers

4
pmdj On

In a kext, you can get an authorisation callback for file system mount callbacks via the mpo_mount_check_mount callback in the MAC (TrustedBSD) policy framework. You can decide whether the mount should go ahead or not in there. I suspect you won't get any information about the logged-in user from the cred argument, as the mount syscall is probably initiated by the daemon running as root. I don't know what you're actually trying to do, so this might not be the best way to approach the problem for your specific case.

/**
  @brief Access control check for mounting a file system
  @param cred Subject credential
  @param vp Vnode that is to be the mount point
  @param vlabel Label associated with the vnode
  @param cnp Component name for vp
  @param vfc_name Filesystem type name

  Determine whether the subject identified by the credential can perform
  the mount operation on the target vnode.

  @return Return 0 if access is granted, otherwise an appropriate value for
  errno should be returned.
*/
typedef int mpo_mount_check_mount_t(
    kauth_cred_t cred,
    struct vnode *vp,
    struct label *vlabel,
    struct componentname *cnp,
    const char *vfc_name
);

Note that this is an unsupported KPI, so Apple says it might go away or break in a future release. Indeed, the policy callback function signatures frequently change between major OS X releases, so you may need to check OS X version at runtime and use different functions for different versions. You'll also need to stay up to date with any betas that Apple releases, to see if they break your code.

With that out of the way, here's how you actually use it:

  • You'll need to link against the MAC framework KPI, so add com.apple.kpi.dsep to your kext's OSBundleLibraries dictionary. (it uses darwin versioning, so use the same version as for the other com.apple.kpi.* bundles)
  • #include <security/mac_policy.h> in your code (it's already provided in Kernel.framework)
  • Create a global variable, or allocate some memory on startup to hold a struct mac_policy_ops, and initialise any of the function pointer fields you're interested in, e.g. mpo_mount_check_mount.
  • When your kext starts up, register your policy using mac_policy_register() and save the handle it returns. You'll need to configure your policy using a mac_policy_conf struct, where you set mpc_ops to point to your policy struct, mpc_loadtime_flags to MPC_LOADTIME_FLAG_UNLOADOK, mpc_name to a reverse-DNS identifier for your kext, mpc_fullname to a human-readable string, and zero-initialise everything else.
  • You will immediately start receiving calls to your callbacks, possibly concurrently from many threads and processes, so be sure to make your callbacks threadsafe.
  • Before unloading, your kext needs to deregister using mac_policy_unregister() and the handle you received from mac_policy_register().

A lot more information can be found in the header file.