Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Dec 2025 17:02:47 +0100
From:      Andrea Cocito <andrea@cocito.eu>
To:        Peter Pentchev <roam@ringlet.net>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Retrieving the kid/jailname of connected peer for a unix socket
Message-ID:  <35A6E88C-FE2C-4EC4-8AED-998D4FA5D965@cocito.eu>
In-Reply-To: <aUq3Kae4qd8_X-bM@straylight.m.ringlet.net>
References:  <7878EFBC-2BCF-42ED-9BFC-D96DC0DDC23A@cocito.eu> <aUq3Kae4qd8_X-bM@straylight.m.ringlet.net>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
On 23 Dec 2025, at 16:37, Peter Pentchev <roam@ringlet.net> wrote:
> If you are afraid that some process will deliberately try to circumvent your
> access control by passing the fd, then I don't think you can really guard
> against that. Assume that your check is instantaneous; in that case, what would
> prevent a process to connect(), wait until you perform the access control check,
> then pass the fd to another process that will issue requests? Even if your
> check is not instantaneous (which it cannot possibly be, as you've found),
> still a rogue process can e.g. connect(), sleep(1), and then pass the fd.
> 
> What exactly is the threat scenario you are trying to mitigate?

Hi,

The (theoretical, I cannot imagine it being exploited in practice, but still the man pages warn against using a pid for any authorisation everywhere):
1. Attacker starts process with pid P in jail X and performs a connect()
2. Attacker manages to slow down the server in order to delay it’s accept()
3. Then process P passes the fd to process Q and exit()s
4. Sometimes pid P is re-used in another, unrelated, jail Y
5. When the server does accept()-> getsockopt()-> sysctl() it gets jail=Y

The idea that a process does connect() and then passes the fd to another in a different jail is not an issue: I assume that the twi jails are not co-operating in the attack (if they are each of them could simply use its own “credentials” to make any request they want).

I was wondering if there is any kernel API that allows to directly get “The jail of the process *currently* connected to this pipe”, or at least the pid of the process *currently* connected (neither the one which made the connect() nor the one which sent some data, as that could be cluttered by buffering too... so even checking LOCAL_CREDS on received traffic would not really make the thing deterministically safe).

Thanks,

A.



[-- Attachment #2 --]
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><meta http-equiv="content-type" content="text/html; charset=utf-8"><div style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">On 23 Dec 2025, at 16:37, Peter Pentchev &lt;roam@ringlet.net&gt; wrote:<br><div><blockquote type="cite"><div><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">If you are afraid that some process will deliberately try to circumvent your</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">access control by passing the fd, then I don't think you can really guard</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">against that. Assume that your check is instantaneous; in that case, what would</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">prevent a process to connect(), wait until you perform the access control check,</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">then pass the fd to another process that will issue requests? Even if your</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">check is not instantaneous (which it cannot possibly be, as you've found),</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">still a rogue process can e.g. connect(), sleep(1), and then pass the fd.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 24px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;">What exactly is the threat scenario you are trying to mitigate?</span></div></blockquote><br></div><div>Hi,</div><div><br></div><div>The (theoretical, I cannot imagine it being exploited in practice, but still the man pages warn against using a pid for any authorisation everywhere):</div><div>1. Attacker starts process with pid P in jail X and performs a connect()</div><div>2. Attacker manages to slow down the server in order to delay it’s accept()</div><div>3. Then process P passes the fd to process Q and exit()s</div><div>4. Sometimes pid P is re-used in another, unrelated, jail Y</div><div>5. When the server does accept()-&gt; getsockopt()-&gt; sysctl() it gets jail=Y</div><div><br></div><div>The idea that a process does connect() and then passes the fd to another in a different jail is not an issue: I assume that the twi jails are not co-operating in the attack (if they are each of them could simply use its own “credentials” to make any request they want).</div><div><br></div><div>I was wondering if there is any kernel API that allows to directly get “The jail of the process *currently* connected to this pipe”, or at least the pid of the process *currently* connected (neither the one which made the connect() nor the one which sent some data, as that could be cluttered by buffering too... so even checking LOCAL_CREDS on received traffic would not really make the thing deterministically safe).</div><div><br></div><div>Thanks,</div><div><br></div><div>A.</div><div><br></div><div><br></div></div></body></html>
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?35A6E88C-FE2C-4EC4-8AED-998D4FA5D965>