Map com.apple extended attributes to org.apple

Keeping the com.apple prefix can trigger all kinds of Finder errors
when copying files to the virtual volume.
This commit is contained in:
Benjamin Fleischer 2025-05-05 11:42:53 +02:00
parent 1577cc93ce
commit fe3bd00378
3 changed files with 48 additions and 67 deletions

View File

@ -47,12 +47,6 @@ typedef unsigned int u_int;
typedef unsigned long u_long;
#endif
#define G_PREFIX "org"
#define G_KAUTH_FILESEC_XATTR G_PREFIX ".apple.system.Security"
#define A_PREFIX "com"
#define A_KAUTH_FILESEC_XATTR A_PREFIX ".apple.system.Security"
#define XATTR_APPLE_PREFIX "com.apple."
struct loopback {
uint32_t blocksize;
bool case_insensitive;
@ -759,19 +753,11 @@ loopback_setxattr(const char *path, const char *name, const char *value,
int res;
flags |= XATTR_NOFOLLOW;
if (!strncmp(name, XATTR_APPLE_PREFIX, sizeof(XATTR_APPLE_PREFIX) - 1)) {
flags &= ~(XATTR_NOSECURITY);
}
if (!strcmp(name, A_KAUTH_FILESEC_XATTR)) {
char new_name[MAXPATHLEN];
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
if (strncmp(name, "com.apple.", 10) == 0) {
char new_name[MAXPATHLEN] = "org.apple.";
strncpy(new_name + 10, name + 10, sizeof(new_name) - 10);
res = setxattr(path, new_name, value, size, position, flags);
} else {
res = setxattr(path, name, value, size, position, flags);
}
@ -789,15 +775,11 @@ loopback_getxattr(const char *path, const char *name, char *value, size_t size,
{
int res;
if (strcmp(name, A_KAUTH_FILESEC_XATTR) == 0) {
char new_name[MAXPATHLEN];
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
if (strncmp(name, "com.apple.", 10) == 0) {
char new_name[MAXPATHLEN] = "org.apple.";
strncpy(new_name + 10, name + 10, sizeof(new_name) - 10);
res = getxattr(path, new_name, value, size, position, XATTR_NOFOLLOW);
} else {
res = getxattr(path, name, value, size, position, XATTR_NOFOLLOW);
}
@ -819,10 +801,10 @@ loopback_listxattr(const char *path, char *list, size_t size)
char *curr = list;
do {
size_t thislen = strlen(curr) + 1;
if (strcmp(curr, G_KAUTH_FILESEC_XATTR) == 0) {
memmove(curr, curr + thislen, res - len - thislen);
res -= thislen;
break;
if (strncmp(curr, "com.apple.", 10) == 0) {
curr[0] = 'o';
curr[1] = 'r';
curr[2] = 'g';
}
curr += thislen;
len += thislen;
@ -850,15 +832,11 @@ loopback_removexattr(const char *path, const char *name)
{
int res;
if (strcmp(name, A_KAUTH_FILESEC_XATTR) == 0) {
char new_name[MAXPATHLEN];
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
if (strncmp(name, "com.apple.", 10) == 0) {
char new_name[MAXPATHLEN] = "org.apple.";
strncpy(new_name + 10, name + 10, sizeof(new_name) - 10);
res = removexattr(path, new_name, XATTR_NOFOLLOW);
} else {
res = removexattr(path, name, XATTR_NOFOLLOW);
}

View File

@ -557,12 +557,6 @@
#pragma mark Extended Attributes
#define G_PREFIX "org"
#define G_KAUTH_FILESEC_XATTR G_PREFIX ".apple.system.Security"
#define A_PREFIX "com"
#define A_KAUTH_FILESEC_XATTR A_PREFIX ".apple.system.Security"
#define XATTR_APPLE_PREFIX "com.apple."
- (NSArray *)extendedAttributesOfItemAtPath:(NSString *)path error:(NSError **)error {
NSString *p = [rootPath_ stringByAppendingString:path];
@ -587,9 +581,10 @@
char *ptr = (char *)[data bytes];
while (ptr < (((char *)[data bytes]) + size)) {
NSString *s = [NSString stringWithUTF8String:ptr];
if (strcmp(ptr, G_KAUTH_FILESEC_XATTR) != 0) {
[contents addObject:s];
if ([s hasPrefix:@"com.apple."]) {
s = [@"org.apple." stringByAppendingString: [s substringFromIndex:10]];
}
[contents addObject:s];
ptr += ([s length] + 1);
}
return contents;
@ -601,14 +596,11 @@
error:(NSError **)error {
NSString *p = [rootPath_ stringByAppendingString:path];
const char *n = [name UTF8String];
if (strcmp(n, A_KAUTH_FILESEC_XATTR) == 0) {
char new_name[MAXPATHLEN];
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
n = new_name;
if ([name hasPrefix:@"com.apple."]) {
name = [@"org.apple." stringByAppendingString: [name substringFromIndex:10]];
}
const char *n = [name UTF8String];
ssize_t size = getxattr([p UTF8String], n, NULL, 0, (uint32_t)position,
XATTR_NOFOLLOW);
if (size < 0) {
@ -644,19 +636,12 @@
NSString *p = [rootPath_ stringByAppendingString:path];
if ([name hasPrefix:@"com.apple."]) {
name = [@"org.apple." stringByAppendingString: [name substringFromIndex:10]];
}
const char *n = [name UTF8String];
if (strcmp(n, A_KAUTH_FILESEC_XATTR) == 0) {
char new_name[MAXPATHLEN];
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
n = new_name;
}
options |= XATTR_NOFOLLOW;
if (!strncmp(n, XATTR_APPLE_PREFIX, sizeof(XATTR_APPLE_PREFIX) - 1)) {
options &= ~(XATTR_NOSECURITY);
}
int ret = setxattr([p UTF8String], n, [value bytes], [value length],
(uint32_t)position, options);
if (ret == -1) {
@ -674,14 +659,11 @@
error:(NSError **)error {
NSString *p = [rootPath_ stringByAppendingString:path];
const char *n = [name UTF8String];
if (strcmp(n, A_KAUTH_FILESEC_XATTR) == 0) {
char new_name[MAXPATHLEN];
memcpy(new_name, A_KAUTH_FILESEC_XATTR, sizeof(A_KAUTH_FILESEC_XATTR));
memcpy(new_name, G_PREFIX, sizeof(G_PREFIX) - 1);
n = new_name;
if ([name hasPrefix:@"com.apple."]) {
name = [@"org.apple." stringByAppendingString: [name substringFromIndex:10]];
}
const char *n = [name UTF8String];
int res = removexattr([p UTF8String], n, XATTR_NOFOLLOW);
if (res == -1) {
if (error) {

View File

@ -297,7 +297,14 @@ public final class LoopbackFS: NSObject {
// Extract attribute names:
let list = data.split(separator: 0).compactMap {
String(data: Data($0), encoding: .utf8)
guard var name = String(data: Data($0), encoding: .utf8) else {
return nil as String?
}
if name.hasPrefix("com.apple.") {
name = "org.apple." + name[name.index(name.startIndex, offsetBy: 10)...]
}
return name
}
return list
}
@ -307,6 +314,10 @@ public final class LoopbackFS: NSObject {
let originalUrl = URL(fileURLWithPath: rootPath.appending(path))
return try originalUrl.withUnsafeFileSystemRepresentation { fileSystemPath -> Data in
var name = name
if name.hasPrefix("com.apple.") {
name = "org.apple." + name[name.index(name.startIndex, offsetBy: 10)...]
}
// Determine attribute size:
let length = getxattr(fileSystemPath, name, nil, 0, UInt32(position), XATTR_NOFOLLOW)
@ -339,6 +350,11 @@ public final class LoopbackFS: NSObject {
// TODO: Why is this necessary?
let newOptions = options & ~(XATTR_NOSECURITY | XATTR_NODEFAULT)
var name = name
if name.hasPrefix("com.apple.") {
name = "org.apple." + name[name.index(name.startIndex, offsetBy: 10)...]
}
let result = value.withUnsafeBytes {
setxattr(fileSystemPath, name, $0.baseAddress?.assumingMemoryBound(to: Int8.self), value.count, UInt32(position), newOptions | XATTR_NOFOLLOW)
}
@ -350,6 +366,11 @@ public final class LoopbackFS: NSObject {
let originalUrl = URL(fileURLWithPath: rootPath.appending(path))
try originalUrl.withUnsafeFileSystemRepresentation { fileSystemPath in
var name = name
if name.hasPrefix("com.apple.") {
name = "org.apple." + name[name.index(name.startIndex, offsetBy: 10)...]
}
let result = removexattr(fileSystemPath, name, XATTR_NOFOLLOW)
guard result >= 0 else { throw NSError(posixErrorCode: errno) }
}