Date: Tue, 23 Dec 2025 13:54:31 +0100 From: Andrea Cocito <andrea@cocito.eu> To: freebsd-hackers@freebsd.org Subject: Retrieving the kid/jailname of connected peer for a unix socket Message-ID: <7878EFBC-2BCF-42ED-9BFC-D96DC0DDC23A@cocito.eu>
index | next in thread | raw e-mail
Hello hackers,
I am working on a project in which I run a “web server” bound to a unix socket; the socket lives in a directory that is re-mounted as a read only nulls in various jails, so processes in each jail can make requests to this “server”.
I need the server to be able to know from which jail the request comes, and this is needed as an authentication method.
So far the best I could do is a three-step approach:
1. I retrieve the pid of the process connected to the other side of the socket: getsockopt(fd, SOL_LOCAL, LOCAL_PEERCRED,…)
2. I map that pid to a jid: int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, static_cast<int>(pid) }; sysctl(mib, 4, &kp, &len, nullptr, 0)
3. I map the kid to jail name with jail_getname()
As LOCAL_PEERCRED returns the peers’ credentials "as they were captured when the socket connection was established” and there could be a small delay before we accept() there is an unlikely but formally possible TOC-TOU issue that potentially could be exploited as follows:
a. A process with pid P in a jail starts and attempts a connect()
b. In the meanwhile a connect-bomb or other “overloading” technique slows down the server
c. Process P passes the fd to process Q and exit()s
d. If when we accept() another process (potentially in another jail) has got pid P... we get the wrong information
As a mitigation I am currently resolving fd->credentials->jid->name as soon as possible server-side and obviously using randomized pids, but there is still a formal delay in accept() and I understand I am violating the golden rule “do not use a pid to grant permissions/authenticate”. I also tried to investigate other safety options (like check that pid actually started before the connection took place) but it seems that nothing from the kernel exposes the “timestamp when connect() was called”, so I always have the connect()-to-accept() windows of risk.
So the question is: am I missing some simpler or safer way to get the "jail id of the process which connected to the other side of this unix socket", besides embarking into “set LOCAL_CREDS_PERSISTENT and check LOCAL_CREDS on received traffic”, which would be quite complex to plumb into Crow-http?
Thank you for any comment/hint and have an hacking Christmas.
A.
PS: I do not consider any TOCTOU between steps 2 and 3 above as I consider the parent machine “safe” and give for sure that no-one will create a jail with a different name and the same jid inbetween,
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?7878EFBC-2BCF-42ED-9BFC-D96DC0DDC23A>
