Local Network Privacy FAQ-17

This thread has been locked by a moderator.

This post is part of the Local Network Privacy FAQ.

Why does local network privacy get confused when I install two variants of my app?

Local network privacy relies on NECP, a subsystem on Apple platforms that controls which programs have access to which network interfaces. For a brief introduction to this, see A Peek Behind the NECP Curtain.

Internally, NECP uses a program’s main executable Mach-O UUID (LC_UUID) to track the identity of that program. If you have two programs with the same UUID, NECP might get confused (r. 30421029).

This most commonly happens when you have two variants of the same app that you build from the same source code. For example, you might have a Pro and a Lite version of your app that use the same code. Or you might a core app implementation that you ‘skin’ for different customers by changing just the resources.

If you encounter weird local network privacy interactions between two apps, check their LC_UUID values. To do this, run dwarfdump against the app’s main executable. For example:

% dwarfdump --uuid Test725715-A.app/Test725715-A
UUID: 2406B68D-B76A-3D70-8264-16F4A8E07DC0 (arm64) Test725715-A.app/Test725715-A
% dwarfdump --uuid Test725715-B.app/Test725715-B
UUID: D4D74EA8-FC68-3925-92AB-7B279DA095F9 (arm64) Test725715-B.app/Test725715-B

Note While macOS doesn’t support local network privacy, duplicate UUIDs can cause weird problems with other NECP-based systems. macOS apps have a slightly different bundle structure, so insert Contents/MacOS/ in the path you pass to dwarfdump. For example, if you have a macOS app called Test725715-A, use the path Test725715-A.app/Contents/MacOS/Test725715.

In this example the UUIDs are different, which is what you’d expect. If you see the same UUID for both apps, take steps to fix that.

If you’re using Xcode, the easiest way to ensure that you have different UUIDs is to build your app from different source code. Here’s one approach that works:

  1. Create two source files, Unique-A.m and Unique-B.m.

  2. Add each file to its corresponding target.

  3. In each file define a string constant with the same name and a different value. For example, Unique-A.m might have:

    const char * gUnique = "Hello from app A!";
    

    while Unique-B.m has:

    const char * gUnique = "Hello from app B!";
    
  4. In your main function, add code to print that value:

    extern char * gUnique
    
    int main(…) {
        …
        printf("%s\n", gUnique);
        …
    }
    

IMPORTANT Printing gUnique ensures that it’s not dead stripped.

Now rebuild your apps and run the dwarfdump test again to confirm that each variant has a different UUID.

Note This example is in Objective-C because this issue is less common with Swift code. That’s because in Swift the app’s name becomes the module name. This is reflected in the Swift runtime metadata, which is linked into the app, causing each app to have a different UUID.

If you’re building your app with third-party tooling, consult the tool’s vendor as to how best to resolve this issue with their tools.

Back to the FAQ

Up vote post of eskimo
355 views