I was trying to call getsockopt(fd, SOL_LOCAL, LOCAL_PEERCRED, ...), and by mistake passed a wrong value for the second parameter where it should be SOL_LOCAL. But the call still succeeded. Then I did more experiments and passed more random values for the second parameter, all succeeded. It seems there is a lack of parameter check in the implementation of getsockopt() , where it should return errors if people pass invalid parameters instead of succeeding silently. Hope the Apple engineers can help to validate and fix it.
This seems to be a bug in the getsockopt
implementation within Unix domains sockets. Presuming you’re calling getsockopt
on a Unix domain socket, the kernel dispatches your request to the Unix domain socket option handler. That checks the option but doesn’t check the level, so you get the Unix domain socket options — LOCAL_PEERCRED
and friends — regardless of what level you supply.
I’d appreciate you filing a bug about this. Please post your bug number so that I can add my own analysis to it.
Congratulations on finding a kernel bug!
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Here’s my basic test code:
import Foundation
import System
func main() throws {
let s = try FileDescriptor.socketPair(AF_UNIX, SOCK_STREAM, 0).0
var cred = xucred()
var credLen = MemoryLayout.size(ofValue: cred)
print("before:", credLen)
try s.getSocketOption(SOL_LOCAL, LOCAL_PEERCRED, &cred, optionLen: &credLen)
print("after:", credLen)
}
try main()
Note This uses the QSocket code from Extra-ordinary Networking.
It prints:
before: 76
after: 76
indicating success.
If you change SOL_LOCAL
to SOL_SOCKET
it prints:
before: 76
after: 4
That’s because the SOL_SOCKET
handling is done at the socket layer, before dispatching down to the Unix domain socket layer. The value of LOCAL_PEERCRED
is 1 which maps to SO_DEBUG
, so you get a CInt
result.
But if you then change SOL_SOCKET
to 12345 you get this:
before: 76
after: 76
indicating that it’s been treated as SOL_LOCAL
/ LOCAL_PEERCRED
.