1
0
Fork 0

darwin: rewrite mount_get_mountpoint

Rewrite most of mount_get_mountpoint for Darwin using the
DiskArbitration API instead of the more low level getfsstat.

This fixes a memory over-read leading to a crash when the system
has more than 128 mounts.

Additionally it changes the logic a bit, now it is first checked
if the path exists and is a folder, if that is not the case, try
to interpret it as BSD mount name, this makes BSD names like 'disk2'
work (provided there is no folder/image with that name) as expected.

Reported by Collin Allen.

Fix #21
This commit is contained in:
Marvin Scholz 2019-10-03 23:47:56 +02:00 committed by Petri Hintukainen
parent 24bdc8af37
commit 406a430213
2 changed files with 43 additions and 24 deletions

View File

@ -46,6 +46,7 @@ case "${host_os}" in
;;
*darwin*)
SYS=darwin
EXTRA_LIBS="${EXTRA_LIBS} -framework CoreFoundation -framework DiskArbitration"
;;
netbsd*)
SYS=netbsd

View File

@ -29,35 +29,53 @@
#define _DARWIN_C_SOURCE
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <DiskArbitration/DADisk.h>
static char *bsdname_get_mountpoint(const char *device_path)
{
char *result = NULL;
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
if (session) {
DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, device_path);
if (disk) {
CFDictionaryRef desc = DADiskCopyDescription(disk);
if (desc) {
// Get Volume path as CFURL
CFURLRef url = CFDictionaryGetValue(desc, kDADiskDescriptionVolumePathKey);
if (url) {
// Copy Volume path as C char array
char tmp_path[PATH_MAX];
if (CFURLGetFileSystemRepresentation(url, true, (UInt8*)tmp_path, sizeof(tmp_path))) {
result = str_dup(tmp_path);
}
}
CFRelease(desc);
}
CFRelease(disk);
}
CFRelease(session);
}
return result;
}
char *mount_get_mountpoint(const char *device_path)
{
struct stat st;
if (stat (device_path, &st) ) {
return str_dup(device_path);
}
/* If it's a directory, all is good */
if (S_ISDIR(st.st_mode)) {
return str_dup(device_path);
}
struct statfs mbuf[128];
int fs_count;
if ( (fs_count = getfsstat (NULL, 0, MNT_NOWAIT)) != -1 ) {
getfsstat (mbuf, fs_count * sizeof(mbuf[0]), MNT_NOWAIT);
for ( int i = 0; i < fs_count; ++i) {
if (!strcmp (mbuf[i].f_mntfromname, device_path)) {
return str_dup (mbuf[i].f_mntonname);
}
if (stat(device_path, &st) == 0) {
// If it's a directory, all is good
if (S_ISDIR(st.st_mode)) {
return str_dup(device_path);
}
}
return str_dup (device_path);
char *mountpoint = bsdname_get_mountpoint(device_path);
if (mountpoint) {
return mountpoint;
}
return str_dup(device_path);
}