struct54
struct54

Reputation: 196

Mmap a block device on Mac OS X?

I want to access an encrypted core storage volume in my program. My plan is to mmap the decrypting block device to be able to jump around in the file system structures with ease and without having to deal with the crypto myself.

While mapping a big file works like a charm, I am getting an EINVAL error on the mmap syscall in the following code:

#include <stddef.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>

int main(int argc, char *argv[])
{
  int fd = open("/dev/disk2", O_RDONLY); // this works fine
  if (fd < 0)
  {
    perror("Could not open file"); return(-1);
  }

  int pagesize = getpagesize(); // page size is 4096 on my system
  void* address = mmap(NULL, pagesize, PROT_READ, MAP_SHARED | MAP_FILE, fd, 0); // try to map first page
  if (address == MAP_FAILED)
  {
    perror("Could not mmap"); // Error complaining about an invalid argument
  }
}

The device has a size of 112 GB and I am compiling with clang mmap.c -O0 -o mmap on Mavericks 10.9.3 for x86_64. My system has 4 GB of RAM and > 10 GB of free hard disk space.

The man-Page mmap(2) only lists the following explanations for an EINVAL error, but these do not seem to apply:

  • MAP_FIXED was specified and the addr argument was not page aligned, or part of the desired address space resides out of the valid address space for a user process.
  • flags does not include either MAP_PRIVATE or MAP_SHARED.
  • The len argument was negative.
  • The offset argument was not page-aligned based on the page size as returned by getpagesize(3).

[...]

  • The flags parameter must specify either MAP_PRIVATE or MAP_SHARED.
  • The size parameter must not be 0.
  • The off parameter must be a multiple of pagesize, as returned by sysconf().

While I have not figured out all the nitty gritty details of the implementation, the comments on this XNU kernel source file explicitly mention being able to map a block device (as long as it's shared): https://www.opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_mman.c

What am I missing?

Upvotes: 2

Views: 1178

Answers (1)

IntellectualKitty
IntellectualKitty

Reputation: 683

Your problem might be using MAP_FILE since this indicates a regular file rather than a block device.

If that doesn't work, trying calling fstat() after you open the file and check the file's length. When I use stat -x to get the information about the block devices on my system, the file sizes are reported as zero (ls -l reported the sizes as "1,"). A zero-length file might also prevent you from being able to create a mapping.

Upvotes: 1

Related Questions