How can I enable local socket under App Sandbox?

Hi.


I am using a local socket for inter-thread communications in my macOS app.

It works well if App Sandbox is off, but does not work otherwise.


What Entitlement Key enables local socket?


I tried com.apple.security.network.server, com.apple.security.files.user-selected.read-only, com.apple.security.files.user-selected.read-write but failed.


Thanks.

Accepted Reply

You shouldn’t need to do anything special to use UNIX domain sockets in a sandboxed app. I just created a test sandboxed app that do the following:

var fds: [Int32] = [ -1, -1 ]
let success = socketpair(AF_UNIX, SOCK_STREAM, 0, &fds) >= 0
assert(success)
let sockIn = fds[0]
let sockOut = fds[1]
Thread.detachNewThread {
    var message = [UInt8]("Hello Cruel World!".utf8)
    let writeResult = write(sockOut, &message, message.count)
    print("wrote:", writeResult)
}
Thread.detachNewThread {
    var message = [UInt8](repeating: 0, count: 256)
    let readResult = read(sockIn, &message, message.count)
    if readResult > 0 {
        let s = String(bytes: message.prefix(readResult), encoding: .utf8) ?? "?"
        print(s)
    }
    print("read:", readResult)
}

It works as expected, printing:

/Users/quinn/Library/Containers/com.example.apple-samplecode.Test126059/Data
wrote: 18
Hello Cruel World!
read: 18

Note I print the home directory to confirm that it is sandboxed. In a non-sandboxed app, this would print the real home directory path,

/Users/quinn
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

You shouldn’t need to do anything special to use UNIX domain sockets in a sandboxed app. I just created a test sandboxed app that do the following:

var fds: [Int32] = [ -1, -1 ]
let success = socketpair(AF_UNIX, SOCK_STREAM, 0, &fds) >= 0
assert(success)
let sockIn = fds[0]
let sockOut = fds[1]
Thread.detachNewThread {
    var message = [UInt8]("Hello Cruel World!".utf8)
    let writeResult = write(sockOut, &message, message.count)
    print("wrote:", writeResult)
}
Thread.detachNewThread {
    var message = [UInt8](repeating: 0, count: 256)
    let readResult = read(sockIn, &message, message.count)
    if readResult > 0 {
        let s = String(bytes: message.prefix(readResult), encoding: .utf8) ?? "?"
        print(s)
    }
    print("read:", readResult)
}

It works as expected, printing:

/Users/quinn/Library/Containers/com.example.apple-samplecode.Test126059/Data
wrote: 18
Hello Cruel World!
read: 18

Note I print the home directory to confirm that it is sandboxed. In a non-sandboxed app, this would print the real home directory path,

/Users/quinn
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

eskimo san,

Thank you for your reply!


I am actually using BlueSocket, which is an open source written by IBM.

The error occurs since the line https://github.com/IBM-Swift/BlueSocket/blob/c46a3d41f5b2401d18bcb46d0101cdc5cd13e307/Sources/Socket/Socket.swift#L2392 returns minus value.


I will try your suggestion and ask if I will encounter other trouble.


UPDATE:

I successfully moved from BlueSocket to Foundation API with socketpair.

Thank you!

The error occurs since the line

Right. That code is trying to use a named UNIX domain socket. I believe it’s possible to do that in a sandboxed app, but if you can get away with using a socket pair then that’s a lot easier.

I successfully moved from BlueSocket to Foundation API with socketpair.

Yay!

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"