* Questions and concerns about BPF-selected interpreter
@ 2026-07-22 0:24 Cole Faust
2026-07-22 0:26 ` Cole Faust
2026-07-22 10:36 ` Christian Brauner
0 siblings, 2 replies; 10+ messages in thread
From: Cole Faust @ 2026-07-22 0:24 UTC (permalink / raw)
To: brauner, farid.m.zakaria; +Cc: linux-fsdevel, Jann Horn
Hi Christian, Farid,
My name is Cole, I work on the android build system. We have similar
goals for creating hermetic and relocatable builds in our build system
(a custom, android-specific one). I was very excited when I saw Farid
working on $ORIGIN support, but then somewhat disappointed when I saw
the new BPF-based solution.
Our usecase is mostly to decouple the glibc version used in the
android build from the host machine. We've had several instances where
our CI machines are running old glibc versions that cause problems,
and they're not trivial to update. Ideally you should be able to
download the android source and build it on a modern linux kernel,
regardless of the userspace.
To register a binfmt_misc handler, you need either root + modifying
global state on the host, or to make a user+mount namespace. But if we
use a mount namespace, couldn't we just mount the interpreter we want
to use at a fixed path? I thought one of the main goals of this
features was to avoid the use of namespaces because they don't always
nest well; Farid called this out as a problem with buck2's sandboxing.
In android, we don't yet have any nested sandboxing but there have
been conversations about increasing security of the build using
something like gvisor to isolate the build from the kernel, in wake of
the recent AI-discovered local privilege escalations, after which
these complicated kernel features are likely to stop working. And
requiring root is definitely out of the question.
I also wanted to ask about the security of this bpf solution. I
understand there are some security concerns about $ORIGIN. Why is this
new binfmt_misc + bpf solution better? An attacker will still have
more opportunity to place a malicious loader relative to the
executable. With the binfmt_misc solution, you will be able to only
have it active for certain things, like a build, but that's only if
you use the user+mount namespace to scope it. From what I understand,
Farid plans on registering the handler globally and persistently on
NixOS systems that want relocatable builds, does that not make those
systems susceptible to these concerns? (correct me if that's not your
plan, Farid)
I can't really think of a better solution than the originally-proposed
$ORIGIN support for build systems to use. I don't care about setuid or
complicated filesystems like memfd, so I would hope it would be
straightforward to just error out if AT_SECURE is set or if any issue
arises like not being able to determine the directory of the
executable. IMO it's fine if it only works in simple, known-safe
cases.
Thanks to both of you for working on this, please let me know what you think.
- Cole
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 0:24 Questions and concerns about BPF-selected interpreter Cole Faust
@ 2026-07-22 0:26 ` Cole Faust
2026-07-22 3:58 ` Farid Zakaria
2026-07-22 5:19 ` Farid Zakaria
2026-07-22 10:36 ` Christian Brauner
1 sibling, 2 replies; 10+ messages in thread
From: Cole Faust @ 2026-07-22 0:26 UTC (permalink / raw)
To: brauner, Farid Zakaria; +Cc: linux-fsdevel, Jann Horn
Correcting Farid's email.
On Tue, Jul 21, 2026 at 5:24 PM Cole Faust <colefaust@google.com> wrote:
>
> Hi Christian, Farid,
>
> My name is Cole, I work on the android build system. We have similar
> goals for creating hermetic and relocatable builds in our build system
> (a custom, android-specific one). I was very excited when I saw Farid
> working on $ORIGIN support, but then somewhat disappointed when I saw
> the new BPF-based solution.
>
> Our usecase is mostly to decouple the glibc version used in the
> android build from the host machine. We've had several instances where
> our CI machines are running old glibc versions that cause problems,
> and they're not trivial to update. Ideally you should be able to
> download the android source and build it on a modern linux kernel,
> regardless of the userspace.
>
> To register a binfmt_misc handler, you need either root + modifying
> global state on the host, or to make a user+mount namespace. But if we
> use a mount namespace, couldn't we just mount the interpreter we want
> to use at a fixed path? I thought one of the main goals of this
> features was to avoid the use of namespaces because they don't always
> nest well; Farid called this out as a problem with buck2's sandboxing.
> In android, we don't yet have any nested sandboxing but there have
> been conversations about increasing security of the build using
> something like gvisor to isolate the build from the kernel, in wake of
> the recent AI-discovered local privilege escalations, after which
> these complicated kernel features are likely to stop working. And
> requiring root is definitely out of the question.
>
> I also wanted to ask about the security of this bpf solution. I
> understand there are some security concerns about $ORIGIN. Why is this
> new binfmt_misc + bpf solution better? An attacker will still have
> more opportunity to place a malicious loader relative to the
> executable. With the binfmt_misc solution, you will be able to only
> have it active for certain things, like a build, but that's only if
> you use the user+mount namespace to scope it. From what I understand,
> Farid plans on registering the handler globally and persistently on
> NixOS systems that want relocatable builds, does that not make those
> systems susceptible to these concerns? (correct me if that's not your
> plan, Farid)
>
> I can't really think of a better solution than the originally-proposed
> $ORIGIN support for build systems to use. I don't care about setuid or
> complicated filesystems like memfd, so I would hope it would be
> straightforward to just error out if AT_SECURE is set or if any issue
> arises like not being able to determine the directory of the
> executable. IMO it's fine if it only works in simple, known-safe
> cases.
>
> Thanks to both of you for working on this, please let me know what you think.
> - Cole
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 0:26 ` Cole Faust
@ 2026-07-22 3:58 ` Farid Zakaria
2026-07-22 4:10 ` Farid Zakaria
2026-07-22 5:19 ` Farid Zakaria
1 sibling, 1 reply; 10+ messages in thread
From: Farid Zakaria @ 2026-07-22 3:58 UTC (permalink / raw)
To: Cole Faust, brauner, Farid Zakaria; +Cc: linux-fsdevel, Jann Horn
On Tue Jul 21, 2026 at 5:26 PM PDT, Cole Faust wrote:
> Correcting Farid's email.
>
> On Tue, Jul 21, 2026 at 5:24 PM Cole Faust <colefaust@google.com> wrote:
>>
>> Hi Christian, Farid,
>>
>> My name is Cole, I work on the android build system. We have similar
>> goals for creating hermetic and relocatable builds in our build system
>> (a custom, android-specific one). I was very excited when I saw Farid
>> working on $ORIGIN support, but then somewhat disappointed when I saw
>> the new BPF-based solution.
>>
>> Our usecase is mostly to decouple the glibc version used in the
>> android build from the host machine. We've had several instances where
>> our CI machines are running old glibc versions that cause problems,
>> and they're not trivial to update. Ideally you should be able to
>> download the android source and build it on a modern linux kernel,
>> regardless of the userspace.
>>
>> To register a binfmt_misc handler, you need either root + modifying
>> global state on the host, or to make a user+mount namespace. But if we
>> use a mount namespace, couldn't we just mount the interpreter we want
>> to use at a fixed path? I thought one of the main goals of this
>> features was to avoid the use of namespaces because they don't always
>> nest well; Farid called this out as a problem with buck2's sandboxing.
>> In android, we don't yet have any nested sandboxing but there have
>> been conversations about increasing security of the build using
>> something like gvisor to isolate the build from the kernel, in wake of
>> the recent AI-discovered local privilege escalations, after which
>> these complicated kernel features are likely to stop working. And
>> requiring root is definitely out of the question.
>>
>> I also wanted to ask about the security of this bpf solution. I
>> understand there are some security concerns about $ORIGIN. Why is this
>> new binfmt_misc + bpf solution better? An attacker will still have
>> more opportunity to place a malicious loader relative to the
>> executable. With the binfmt_misc solution, you will be able to only
>> have it active for certain things, like a build, but that's only if
>> you use the user+mount namespace to scope it. From what I understand,
>> Farid plans on registering the handler globally and persistently on
>> NixOS systems that want relocatable builds, does that not make those
>> systems susceptible to these concerns? (correct me if that's not your
>> plan, Farid)
>>
>> I can't really think of a better solution than the originally-proposed
>> $ORIGIN support for build systems to use. I don't care about setuid or
>> complicated filesystems like memfd, so I would hope it would be
>> straightforward to just error out if AT_SECURE is set or if any issue
>> arises like not being able to determine the directory of the
>> executable. IMO it's fine if it only works in simple, known-safe
>> cases.
>>
>> Thanks to both of you for working on this, please let me know what you think.
>> - Cole
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 3:58 ` Farid Zakaria
@ 2026-07-22 4:10 ` Farid Zakaria
0 siblings, 0 replies; 10+ messages in thread
From: Farid Zakaria @ 2026-07-22 4:10 UTC (permalink / raw)
To: Cole Faust, brauner, Farid Zakaria; +Cc: linux-fsdevel, Jann Horn
Ah sorry for the empty send.
I'm trying to learn aerc email client and couldn't figure it out.
(Back to gmail for this one)
I wanted to CC @Alessandro Di Federico
On Tue, Jul 21, 2026 at 8:59 PM Farid Zakaria <farid.m.zakaria@gmail.com> wrote:
>
> On Tue Jul 21, 2026 at 5:26 PM PDT, Cole Faust wrote:
> > Correcting Farid's email.
> >
> > On Tue, Jul 21, 2026 at 5:24 PM Cole Faust <colefaust@google.com> wrote:
> >>
> >> Hi Christian, Farid,
> >>
> >> My name is Cole, I work on the android build system. We have similar
> >> goals for creating hermetic and relocatable builds in our build system
> >> (a custom, android-specific one). I was very excited when I saw Farid
> >> working on $ORIGIN support, but then somewhat disappointed when I saw
> >> the new BPF-based solution.
> >>
> >> Our usecase is mostly to decouple the glibc version used in the
> >> android build from the host machine. We've had several instances where
> >> our CI machines are running old glibc versions that cause problems,
> >> and they're not trivial to update. Ideally you should be able to
> >> download the android source and build it on a modern linux kernel,
> >> regardless of the userspace.
> >>
> >> To register a binfmt_misc handler, you need either root + modifying
> >> global state on the host, or to make a user+mount namespace. But if we
> >> use a mount namespace, couldn't we just mount the interpreter we want
> >> to use at a fixed path? I thought one of the main goals of this
> >> features was to avoid the use of namespaces because they don't always
> >> nest well; Farid called this out as a problem with buck2's sandboxing.
> >> In android, we don't yet have any nested sandboxing but there have
> >> been conversations about increasing security of the build using
> >> something like gvisor to isolate the build from the kernel, in wake of
> >> the recent AI-discovered local privilege escalations, after which
> >> these complicated kernel features are likely to stop working. And
> >> requiring root is definitely out of the question.
> >>
> >> I also wanted to ask about the security of this bpf solution. I
> >> understand there are some security concerns about $ORIGIN. Why is this
> >> new binfmt_misc + bpf solution better? An attacker will still have
> >> more opportunity to place a malicious loader relative to the
> >> executable. With the binfmt_misc solution, you will be able to only
> >> have it active for certain things, like a build, but that's only if
> >> you use the user+mount namespace to scope it. From what I understand,
> >> Farid plans on registering the handler globally and persistently on
> >> NixOS systems that want relocatable builds, does that not make those
> >> systems susceptible to these concerns? (correct me if that's not your
> >> plan, Farid)
> >>
> >> I can't really think of a better solution than the originally-proposed
> >> $ORIGIN support for build systems to use. I don't care about setuid or
> >> complicated filesystems like memfd, so I would hope it would be
> >> straightforward to just error out if AT_SECURE is set or if any issue
> >> arises like not being able to determine the directory of the
> >> executable. IMO it's fine if it only works in simple, known-safe
> >> cases.
> >>
> >> Thanks to both of you for working on this, please let me know what you think.
> >> - Cole
>
Hey Cole,
Thanks for the response. Funny timing since Alessandro, who've I added
to the email, also reached out privately and I referred him to the
mailing list [1]. You also might want to cross-post this there as it's
the original thread containing the use-cases and rationale if you can
speak publicly on the matter for Android.
Is the Android build system Blaze (I'm a Xoogler)? I think although
the namespacing can be funky, even with the BPF solution we could
leverage this at my current company (Meta) with buck2 to alleviate
problems with building against a single monolithic glibc that I am
excited about.
Very cool to here that you have the same issue as well; seems like
there is a more well-understood need to have the interpreter support
$ORIGIN than many think -- or at least that's the assesment from those
on the mailing list. [2]
I think the BPF solution Christian recommended and ultimately put
forward is technically very cool; the idea to programmatically hook
into binfmt_misc sounded cool although more than what's necessary for
the $ORIGIN support. It's kind of neat that's a superset of every
binfmt_misc solution out there now.
I'm pragmatic and appreciated Christian working with me towards a
solution. My idea was to hopefully get a more understood rationale for
the need for $ORIGIN by deploying it with the BPF, albeit in a limited
capacity due to the root privilege, to make a stronger case in the
future for something builtin.
[1] https://lore.kernel.org/all/20260722011217.45e79a08@spawn/
[2] https://lore.kernel.org/all/20260626172832.366deaac@pumpkin/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 0:26 ` Cole Faust
2026-07-22 3:58 ` Farid Zakaria
@ 2026-07-22 5:19 ` Farid Zakaria
2026-07-22 19:39 ` Cole Faust
1 sibling, 1 reply; 10+ messages in thread
From: Farid Zakaria @ 2026-07-22 5:19 UTC (permalink / raw)
To: Cole Faust; +Cc: brauner, linux-fsdevel, Jann Horn, Alessandro Di Federico
Third time's the charm. I don't see the email on the mailing list so
I'm not sure if it was delivered.
(Sending it again. Sorry for the duplicates if it made it's way
through; I'm having an off day with email I guess)
On Tue, Jul 21, 2026 at 5:26 PM Cole Faust <colefaust@google.com> wrote:
>
> Correcting Farid's email.
>
> On Tue, Jul 21, 2026 at 5:24 PM Cole Faust <colefaust@google.com> wrote:
> >
> > Hi Christian, Farid,
> >
> > My name is Cole, I work on the android build system. We have similar
> > goals for creating hermetic and relocatable builds in our build system
> > (a custom, android-specific one). I was very excited when I saw Farid
> > working on $ORIGIN support, but then somewhat disappointed when I saw
> > the new BPF-based solution.
> >
> > Our usecase is mostly to decouple the glibc version used in the
> > android build from the host machine. We've had several instances where
> > our CI machines are running old glibc versions that cause problems,
> > and they're not trivial to update. Ideally you should be able to
> > download the android source and build it on a modern linux kernel,
> > regardless of the userspace.
> >
> > To register a binfmt_misc handler, you need either root + modifying
> > global state on the host, or to make a user+mount namespace. But if we
> > use a mount namespace, couldn't we just mount the interpreter we want
> > to use at a fixed path? I thought one of the main goals of this
> > features was to avoid the use of namespaces because they don't always
> > nest well; Farid called this out as a problem with buck2's sandboxing.
> > In android, we don't yet have any nested sandboxing but there have
> > been conversations about increasing security of the build using
> > something like gvisor to isolate the build from the kernel, in wake of
> > the recent AI-discovered local privilege escalations, after which
> > these complicated kernel features are likely to stop working. And
> > requiring root is definitely out of the question.
> >
> > I also wanted to ask about the security of this bpf solution. I
> > understand there are some security concerns about $ORIGIN. Why is this
> > new binfmt_misc + bpf solution better? An attacker will still have
> > more opportunity to place a malicious loader relative to the
> > executable. With the binfmt_misc solution, you will be able to only
> > have it active for certain things, like a build, but that's only if
> > you use the user+mount namespace to scope it. From what I understand,
> > Farid plans on registering the handler globally and persistently on
> > NixOS systems that want relocatable builds, does that not make those
> > systems susceptible to these concerns? (correct me if that's not your
> > plan, Farid)
> >
> > I can't really think of a better solution than the originally-proposed
> > $ORIGIN support for build systems to use. I don't care about setuid or
> > complicated filesystems like memfd, so I would hope it would be
> > straightforward to just error out if AT_SECURE is set or if any issue
> > arises like not being able to determine the directory of the
> > executable. IMO it's fine if it only works in simple, known-safe
> > cases.
> >
> > Thanks to both of you for working on this, please let me know what you think.
> > - Cole
Hey Cole,
Thanks for the response. Funny timing since Alessandro, who've I added
to the email, also reached out privately and I referred him to the
mailing list [1]. You also might want to cross-post this there as it's
the original thread containing the use-cases and rationale if you can
speak publicly on the matter for Android.
Is the Android build system Blaze (I'm a Xoogler)? I think although
the namespacing can be funky, even with the BPF solution we could
leverage this at my current company (Meta) with buck2 to alleviate
problems with building against a single monolithic glibc that I am
excited about.
Very cool to here that you have the same issue as well; seems like
there is a more well-understood need to have the interpreter support
$ORIGIN than many think -- or at least that's the assesment from those
on the mailing list. [2]
I think the BPF solution Christian recommended and ultimately put
forward is technically very cool; the idea to programmatically hook
into binfmt_misc sounded cool although more than what's necessary for
the $ORIGIN support. It's kind of neat that's a superset of every
binfmt_misc solution out there now.
I'm pragmatic and appreciated Christian working with me towards a
solution. My idea was to hopefully get a more understood rationale for
the need for $ORIGIN by deploying it with the BPF, albeit in a limited
capacity due to the root privilege, to make a stronger case in the
future for something builtin.
[1] https://lore.kernel.org/all/20260722011217.45e79a08@spawn/
[2] https://lore.kernel.org/all/20260626172832.366deaac@pumpkin/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 0:24 Questions and concerns about BPF-selected interpreter Cole Faust
2026-07-22 0:26 ` Cole Faust
@ 2026-07-22 10:36 ` Christian Brauner
2026-07-22 19:29 ` Cole Faust
1 sibling, 1 reply; 10+ messages in thread
From: Christian Brauner @ 2026-07-22 10:36 UTC (permalink / raw)
To: Cole Faust; +Cc: farid.m.zakaria, linux-fsdevel, Jann Horn
On Tue, Jul 21, 2026 at 05:24:21PM -0700, Cole Faust wrote:
> Hi Christian, Farid,
>
> My name is Cole, I work on the android build system. We have similar
> goals for creating hermetic and relocatable builds in our build system
> (a custom, android-specific one). I was very excited when I saw Farid
> working on $ORIGIN support, but then somewhat disappointed when I saw
> the new BPF-based solution.
>
> Our usecase is mostly to decouple the glibc version used in the
> android build from the host machine. We've had several instances where
> our CI machines are running old glibc versions that cause problems,
> and they're not trivial to update. Ideally you should be able to
> download the android source and build it on a modern linux kernel,
> regardless of the userspace.
>
> To register a binfmt_misc handler, you need either root + modifying
> global state on the host, or to make a user+mount namespace. But if we
> use a mount namespace, couldn't we just mount the interpreter we want
> to use at a fixed path? I thought one of the main goals of this
> features was to avoid the use of namespaces because they don't always
> nest well; Farid called this out as a problem with buck2's sandboxing.
> In android, we don't yet have any nested sandboxing but there have
> been conversations about increasing security of the build using
> something like gvisor to isolate the build from the kernel, in wake of
> the recent AI-discovered local privilege escalations, after which
> these complicated kernel features are likely to stop working. And
> requiring root is definitely out of the question.
If a single fixed path solves your problem then you indeed don't need
any of this. A bind-mount expresses one fixed path pointing to one
loader. The handler exists for programmable dispatch so that you match
binaries to whatever load you want, use multiple toolchains, allow
multiple generations coexisting, per-architecture emulators, etc.
A one-line binfmt_misc registration is considerably less invasive than
the glibc update you can't do. Plus, it's visible, revocable, and
scopable to precisely the formats it matches. You can have the most
restrictive policy ever that makes sure only one specific workload is
able to use $ORIGIN during build.
And gvisor doesn't forward execve() to the host kernel at all. The
Sentry reimplements the whole exec path in Go. There is no binfmt_misc
and even if we added $ORIGIN support to the kernel it would be invisible
to gvisor. Under gvisor you can just patch gvisor without any
involvement
from us at all.
gvisor doesn't forward execve() to the host kernel at all. The Sentry
reimplements the whole exec path in Go. There is no binfmt_misc and even
if we added $ORIGIN support to the kernel it would be invisible to
gvisor. Under gvisor you can just patch gvisor without any involvement
from us at all.
Fwiw, with $ORIGIN support it's worse. On any kernel or sandbox that
doesn't implement $ORIGIN this doesn't fail cleanly. A PT_INTERP of
$ORIGIN/ld.so isn't absolute and so Linux resolves it relative to the
caller's working directory. Execute such a "relocatable" binary with an
attacker-controlled working directory and ./$ORIGIN/ld.so is your
loader.
So $ORIGIN-tagged binaries are actively dangerous precisely on the old
unupdatable machines and future sandboxes you're describing. A
binfmt_misc handler that isn't registered simply does nothing.
> I also wanted to ask about the security of this bpf solution. I
> understand there are some security concerns about $ORIGIN. Why is this
> new binfmt_misc + bpf solution better? An attacker will still have
> more opportunity to place a malicious loader relative to the
> executable. With the binfmt_misc solution, you will be able to only
> have it active for certain things, like a build, but that's only if
> you use the user+mount namespace to scope it. From what I understand,
> Farid plans on registering the handler globally and persistently on
> NixOS systems that want relocatable builds, does that not make those
> systems susceptible to these concerns? (correct me if that's not your
> plan, Farid)
>
> I can't really think of a better solution than the originally-proposed
> $ORIGIN support for build systems to use. I don't care about setuid or
> complicated filesystems like memfd, so I would hope it would be
> straightforward to just error out if AT_SECURE is set or if any issue
> arises like not being able to determine the directory of the
> executable. IMO it's fine if it only works in simple, known-safe
> cases.
This is very focussed on the $ORIGIN case and it's understandable. This
is a very specific policy. I understand how it can be useful for a
distribution like nixos that wants to make the loader relative to the
binary everywhere or to some build system.
But this sort of decision is policy and policy doesn't belong into the
kernel, it belongs into userspace. The kernel's job in this scenario is
to give userspace the tools to implement such policy in a way that it is
flexible and doesn't just serve a single use-case.
binfmt_misc exists to move custom binary policy out of the kernel and
let userspace handle it however it sees fit. As such it is the perfect
fit for implementing what loader to use for what binary.
The power of this proposal is that $ORIGIN is just one single policy
that can be implemented. But it also allows for other custom policies.
You could even label binaries with xattrs and use those to decide what
loader to use. You could scope it to cgroup or whatever. That's useful
and I have use-cases for such policies in other projects.
In other words, I think implementing a very custom policy into the core
elf loader is a dead-end even if the AT_SECURE and memfd cases simply
error out. Every such carve-out becomes frozen uapi. The same binary
then runs or fails depending on whether it was reached by path, by fd,
as a memfd, or through an overlay. Each of those answers is someone's
future regression report and none of them can be changed afterwards.
Note that the implicit argument made further up is that the security
posture of having native $ORIGIN support is stronger than having a way
to implement whatever policy - including $ORIGIN - via binfmt_misc.
That's very obviously false.
Implementing $ORIGIN natively means we start shipping a static, custom
policy _to everyone_ out there next release. Whereas binfmt_misc does
_nothing_ and only affects users that actually do need this custom
policy and do set it up. And once they have set it up the existence of a
policy is even visible via binfmt_misc.
So the security story of enabling $ORIGIN in core elf code is a lot
weaker: it's inflexible, it's unclear what holes it opens up, and users
will be surprised by it.
If users don't care about the bpf policy support for binfmt_misc and are
worried about someone registering a bpf handler: CONFIG_BINFMT_MISC_BPF=n
Btw, the exact semantics you're asking for ($ORIGIN-prefixed PT_INTERP
resolved against the binary's directory and hard failure for everything
unusual) are about a hundred lines of bpf on top of what is already
in the tree. The $ORIGIN demo handler written for the series does
exactly that, including failing closed instead of falling back to the
cwd-relative lookup mentioned above. So you can deploy the policy you
want today on hosts you administer, collect data on how it behaves in
practice, and if a blessed subset ever emerges that conversation can be
had with evidence. An in-kernel $ORIGIN can always be added later as one
more policy. Once shipped it can never be unshipped.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 10:36 ` Christian Brauner
@ 2026-07-22 19:29 ` Cole Faust
2026-07-23 0:16 ` Farid Zakaria
2026-07-23 13:15 ` Christian Brauner
0 siblings, 2 replies; 10+ messages in thread
From: Cole Faust @ 2026-07-22 19:29 UTC (permalink / raw)
To: Christian Brauner; +Cc: farid.m.zakaria, linux-fsdevel, Jann Horn
Hi Christian,
Thanks for the response. You mention a couple of times that we could
install the binfmt_misc handler and go from there, ("A one-line
binfmt_misc registration is considerably less invasive than
the glibc update you can't do", "So you can deploy the policy you want
today on hosts you administer"), but we don't control the hosts that
build android. We work with many partner companies (Samsung, Qualcomm,
etc) and have basically no visibility into how their hosts are setup,
and we certainly don't get root access. So I think it's literally
impossible for us to install a global binfmt_misc handler. We could
use user/mount namespaces to install a scoped one, but in practice we
only have 1 version of glibc used in the build, so we might as well
just bind mount it to /lib64/ld-linux-x86-64.so.2 if we were going to
use mount namespaces. So while this new binfmt_misc feature is cool,
and allows for a lot of flexibility, I don't think we would ever use
it. This means that we also wouldn't have an opportunity to "collect
data" on how it works.
Another point I'd like to call out is that we build a bunch of tools
that users will use outside of the build, like adb. It would be nice
if those tools also weren't dependant on the host system. With the
binfmt_misc solution, you'd have to run a wrapper tool to set up the
binfmt_misc handler in a mount namespace (or again, just remount the
interpreter to a fixed path) before you could run adb, which is more
friction for users.
Re: the gvisor / additional sandbox concerns, I'd like to not get into
the weeds too much on this. There are many possibilities to consider
(another being the default docker config doesn't allow mounts), so I'd
rather that we consider it a requirement to be able to use a local
interpreter without any namespaces.
Regarding security, it seems your stance is that it's safer for system
admins to opt-in to this new functionality, so that if it has security
flaws, it's their problem. I think that's a dangerous stance to take.
I could see distros like nixos opting into this because they need it
and opening themselves up to problems that they are left on their own
to defend against. If we're going to allow this, making sure we've
considered security thoroughly enough that it can be made opt-out
instead of opt-in seems safer for those users. If $ORIGIN support is
too dangerous to be opt-out, it's probably too dangerous to be opt-in.
I see your concerns about old systems running $ORIGIN binaries and
treating them as `./$ORIGIN`. Could we potentially fix that by making
a new PT_INTERP_ORIGIN section? Binaries would only be allowed to have
one of PT_INTERP or PT_INTERP_ORIGIN, so a PT_INTERP_ORIGIN binary
would fail to run on an old system, as it doesn't have a PT_INTERP
section.
> In other words, I think implementing a very custom policy into the core elf loader is a dead-end even if the AT_SECURE and memfd cases simply error out. Every such carve-out becomes frozen uapi. The same binary then runs or fails depending on whether it was reached by path, by fd, as a memfd, or through an overlay. Each of those answers is someone's future regression report and none of them can be changed afterwards.
Are we considering cases where the kernel errors out as API? Wouldn't
that mean adding the B and L binfmt_misc handlers are also breaking
api changes, as trying to register a handler with those types before
would've errored? IMO, erroring out explicitly reserves the API space
for the future. But I'm not a kernel dev.
> An in-kernel $ORIGIN can always be added later as one more policy. Once shipped it can never be unshipped.
This is understandable. I'm not saying we should rush into adding
$ORIGIN support right now, I just wanted to keep the conversation of
it alive, and not declare victory just yet with the binfmt_misc
solution, as it doesn't cover the usecases most interesting to us. As
is, we won't be able to use the binfmt_misc solution, which is fine,
it's no worse of a state than we were in without it, but I would like
to see something more useful later on.
On Wed, Jul 22, 2026 at 3:37 AM Christian Brauner <brauner@kernel.org> wrote:
>
> On Tue, Jul 21, 2026 at 05:24:21PM -0700, Cole Faust wrote:
> > Hi Christian, Farid,
> >
> > My name is Cole, I work on the android build system. We have similar
> > goals for creating hermetic and relocatable builds in our build system
> > (a custom, android-specific one). I was very excited when I saw Farid
> > working on $ORIGIN support, but then somewhat disappointed when I saw
> > the new BPF-based solution.
> >
> > Our usecase is mostly to decouple the glibc version used in the
> > android build from the host machine. We've had several instances where
> > our CI machines are running old glibc versions that cause problems,
> > and they're not trivial to update. Ideally you should be able to
> > download the android source and build it on a modern linux kernel,
> > regardless of the userspace.
> >
> > To register a binfmt_misc handler, you need either root + modifying
> > global state on the host, or to make a user+mount namespace. But if we
> > use a mount namespace, couldn't we just mount the interpreter we want
> > to use at a fixed path? I thought one of the main goals of this
> > features was to avoid the use of namespaces because they don't always
> > nest well; Farid called this out as a problem with buck2's sandboxing.
> > In android, we don't yet have any nested sandboxing but there have
> > been conversations about increasing security of the build using
> > something like gvisor to isolate the build from the kernel, in wake of
> > the recent AI-discovered local privilege escalations, after which
> > these complicated kernel features are likely to stop working. And
> > requiring root is definitely out of the question.
>
> If a single fixed path solves your problem then you indeed don't need
> any of this. A bind-mount expresses one fixed path pointing to one
> loader. The handler exists for programmable dispatch so that you match
> binaries to whatever load you want, use multiple toolchains, allow
> multiple generations coexisting, per-architecture emulators, etc.
>
> A one-line binfmt_misc registration is considerably less invasive than
> the glibc update you can't do. Plus, it's visible, revocable, and
> scopable to precisely the formats it matches. You can have the most
> restrictive policy ever that makes sure only one specific workload is
> able to use $ORIGIN during build.
>
> And gvisor doesn't forward execve() to the host kernel at all. The
> Sentry reimplements the whole exec path in Go. There is no binfmt_misc
> and even if we added $ORIGIN support to the kernel it would be invisible
> to gvisor. Under gvisor you can just patch gvisor without any
> involvement
> from us at all.
>
> gvisor doesn't forward execve() to the host kernel at all. The Sentry
> reimplements the whole exec path in Go. There is no binfmt_misc and even
> if we added $ORIGIN support to the kernel it would be invisible to
> gvisor. Under gvisor you can just patch gvisor without any involvement
> from us at all.
>
> Fwiw, with $ORIGIN support it's worse. On any kernel or sandbox that
> doesn't implement $ORIGIN this doesn't fail cleanly. A PT_INTERP of
> $ORIGIN/ld.so isn't absolute and so Linux resolves it relative to the
> caller's working directory. Execute such a "relocatable" binary with an
> attacker-controlled working directory and ./$ORIGIN/ld.so is your
> loader.
>
> So $ORIGIN-tagged binaries are actively dangerous precisely on the old
> unupdatable machines and future sandboxes you're describing. A
> binfmt_misc handler that isn't registered simply does nothing.
>
> > I also wanted to ask about the security of this bpf solution. I
> > understand there are some security concerns about $ORIGIN. Why is this
> > new binfmt_misc + bpf solution better? An attacker will still have
> > more opportunity to place a malicious loader relative to the
> > executable. With the binfmt_misc solution, you will be able to only
> > have it active for certain things, like a build, but that's only if
> > you use the user+mount namespace to scope it. From what I understand,
> > Farid plans on registering the handler globally and persistently on
> > NixOS systems that want relocatable builds, does that not make those
> > systems susceptible to these concerns? (correct me if that's not your
> > plan, Farid)
> >
> > I can't really think of a better solution than the originally-proposed
> > $ORIGIN support for build systems to use. I don't care about setuid or
> > complicated filesystems like memfd, so I would hope it would be
> > straightforward to just error out if AT_SECURE is set or if any issue
> > arises like not being able to determine the directory of the
> > executable. IMO it's fine if it only works in simple, known-safe
> > cases.
>
> This is very focussed on the $ORIGIN case and it's understandable. This
> is a very specific policy. I understand how it can be useful for a
> distribution like nixos that wants to make the loader relative to the
> binary everywhere or to some build system.
>
> But this sort of decision is policy and policy doesn't belong into the
> kernel, it belongs into userspace. The kernel's job in this scenario is
> to give userspace the tools to implement such policy in a way that it is
> flexible and doesn't just serve a single use-case.
>
> binfmt_misc exists to move custom binary policy out of the kernel and
> let userspace handle it however it sees fit. As such it is the perfect
> fit for implementing what loader to use for what binary.
>
> The power of this proposal is that $ORIGIN is just one single policy
> that can be implemented. But it also allows for other custom policies.
> You could even label binaries with xattrs and use those to decide what
> loader to use. You could scope it to cgroup or whatever. That's useful
> and I have use-cases for such policies in other projects.
>
> In other words, I think implementing a very custom policy into the core
> elf loader is a dead-end even if the AT_SECURE and memfd cases simply
> error out. Every such carve-out becomes frozen uapi. The same binary
> then runs or fails depending on whether it was reached by path, by fd,
> as a memfd, or through an overlay. Each of those answers is someone's
> future regression report and none of them can be changed afterwards.
>
> Note that the implicit argument made further up is that the security
> posture of having native $ORIGIN support is stronger than having a way
> to implement whatever policy - including $ORIGIN - via binfmt_misc.
> That's very obviously false.
>
> Implementing $ORIGIN natively means we start shipping a static, custom
> policy _to everyone_ out there next release. Whereas binfmt_misc does
> _nothing_ and only affects users that actually do need this custom
> policy and do set it up. And once they have set it up the existence of a
> policy is even visible via binfmt_misc.
>
> So the security story of enabling $ORIGIN in core elf code is a lot
> weaker: it's inflexible, it's unclear what holes it opens up, and users
> will be surprised by it.
>
> If users don't care about the bpf policy support for binfmt_misc and are
> worried about someone registering a bpf handler: CONFIG_BINFMT_MISC_BPF=n
>
> Btw, the exact semantics you're asking for ($ORIGIN-prefixed PT_INTERP
> resolved against the binary's directory and hard failure for everything
> unusual) are about a hundred lines of bpf on top of what is already
> in the tree. The $ORIGIN demo handler written for the series does
> exactly that, including failing closed instead of falling back to the
> cwd-relative lookup mentioned above. So you can deploy the policy you
> want today on hosts you administer, collect data on how it behaves in
> practice, and if a blessed subset ever emerges that conversation can be
> had with evidence. An in-kernel $ORIGIN can always be added later as one
> more policy. Once shipped it can never be unshipped.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 5:19 ` Farid Zakaria
@ 2026-07-22 19:39 ` Cole Faust
0 siblings, 0 replies; 10+ messages in thread
From: Cole Faust @ 2026-07-22 19:39 UTC (permalink / raw)
To: Farid Zakaria; +Cc: brauner, linux-fsdevel, Jann Horn, Alessandro Di Federico
Hi Farid,
No, the android build system is a custom one called soong. There was
an effort to migrate from soong to bazel (which is when I joined the
team), but it was cancelled in 2023.
Yes, I think $ORIGIN is very widely applicable for basically any build
system. And redistributable linux binaries in general, since the
kernel is the only stable part of linux, making apps that only depend
on the kernel would be very useful for linux app development.
The binfmt_misc thing is technically cool but seems to have limited
use due to its reliance on root or mount namespaces. It seems more
designed for system administrators than for app developers. Still,
it's a step in the right direction.
-Cole
On Tue, Jul 21, 2026 at 10:19 PM Farid Zakaria
<farid.m.zakaria@gmail.com> wrote:
>
> Third time's the charm. I don't see the email on the mailing list so
> I'm not sure if it was delivered.
> (Sending it again. Sorry for the duplicates if it made it's way
> through; I'm having an off day with email I guess)
>
> On Tue, Jul 21, 2026 at 5:26 PM Cole Faust <colefaust@google.com> wrote:
> >
> > Correcting Farid's email.
> >
> > On Tue, Jul 21, 2026 at 5:24 PM Cole Faust <colefaust@google.com> wrote:
> > >
> > > Hi Christian, Farid,
> > >
> > > My name is Cole, I work on the android build system. We have similar
> > > goals for creating hermetic and relocatable builds in our build system
> > > (a custom, android-specific one). I was very excited when I saw Farid
> > > working on $ORIGIN support, but then somewhat disappointed when I saw
> > > the new BPF-based solution.
> > >
> > > Our usecase is mostly to decouple the glibc version used in the
> > > android build from the host machine. We've had several instances where
> > > our CI machines are running old glibc versions that cause problems,
> > > and they're not trivial to update. Ideally you should be able to
> > > download the android source and build it on a modern linux kernel,
> > > regardless of the userspace.
> > >
> > > To register a binfmt_misc handler, you need either root + modifying
> > > global state on the host, or to make a user+mount namespace. But if we
> > > use a mount namespace, couldn't we just mount the interpreter we want
> > > to use at a fixed path? I thought one of the main goals of this
> > > features was to avoid the use of namespaces because they don't always
> > > nest well; Farid called this out as a problem with buck2's sandboxing.
> > > In android, we don't yet have any nested sandboxing but there have
> > > been conversations about increasing security of the build using
> > > something like gvisor to isolate the build from the kernel, in wake of
> > > the recent AI-discovered local privilege escalations, after which
> > > these complicated kernel features are likely to stop working. And
> > > requiring root is definitely out of the question.
> > >
> > > I also wanted to ask about the security of this bpf solution. I
> > > understand there are some security concerns about $ORIGIN. Why is this
> > > new binfmt_misc + bpf solution better? An attacker will still have
> > > more opportunity to place a malicious loader relative to the
> > > executable. With the binfmt_misc solution, you will be able to only
> > > have it active for certain things, like a build, but that's only if
> > > you use the user+mount namespace to scope it. From what I understand,
> > > Farid plans on registering the handler globally and persistently on
> > > NixOS systems that want relocatable builds, does that not make those
> > > systems susceptible to these concerns? (correct me if that's not your
> > > plan, Farid)
> > >
> > > I can't really think of a better solution than the originally-proposed
> > > $ORIGIN support for build systems to use. I don't care about setuid or
> > > complicated filesystems like memfd, so I would hope it would be
> > > straightforward to just error out if AT_SECURE is set or if any issue
> > > arises like not being able to determine the directory of the
> > > executable. IMO it's fine if it only works in simple, known-safe
> > > cases.
> > >
> > > Thanks to both of you for working on this, please let me know what you think.
> > > - Cole
>
> Hey Cole,
>
> Thanks for the response. Funny timing since Alessandro, who've I added
> to the email, also reached out privately and I referred him to the
> mailing list [1]. You also might want to cross-post this there as it's
> the original thread containing the use-cases and rationale if you can
> speak publicly on the matter for Android.
>
> Is the Android build system Blaze (I'm a Xoogler)? I think although
> the namespacing can be funky, even with the BPF solution we could
> leverage this at my current company (Meta) with buck2 to alleviate
> problems with building against a single monolithic glibc that I am
> excited about.
>
> Very cool to here that you have the same issue as well; seems like
> there is a more well-understood need to have the interpreter support
> $ORIGIN than many think -- or at least that's the assesment from those
> on the mailing list. [2]
>
> I think the BPF solution Christian recommended and ultimately put
> forward is technically very cool; the idea to programmatically hook
> into binfmt_misc sounded cool although more than what's necessary for
> the $ORIGIN support. It's kind of neat that's a superset of every
> binfmt_misc solution out there now.
>
> I'm pragmatic and appreciated Christian working with me towards a
> solution. My idea was to hopefully get a more understood rationale for
> the need for $ORIGIN by deploying it with the BPF, albeit in a limited
> capacity due to the root privilege, to make a stronger case in the
> future for something builtin.
>
> [1] https://lore.kernel.org/all/20260722011217.45e79a08@spawn/
> [2] https://lore.kernel.org/all/20260626172832.366deaac@pumpkin/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 19:29 ` Cole Faust
@ 2026-07-23 0:16 ` Farid Zakaria
2026-07-23 13:15 ` Christian Brauner
1 sibling, 0 replies; 10+ messages in thread
From: Farid Zakaria @ 2026-07-23 0:16 UTC (permalink / raw)
To: Cole Faust, Christian Brauner; +Cc: farid.m.zakaria, linux-fsdevel, Jann Horn
On Wed Jul 22, 2026 at 12:29 PM PDT, Cole Faust wrote:
> Hi Christian,
>
> Thanks for the response. You mention a couple of times that we could
> install the binfmt_misc handler and go from there, ("A one-line
> binfmt_misc registration is considerably less invasive than
> the glibc update you can't do", "So you can deploy the policy you want
> today on hosts you administer"), but we don't control the hosts that
> build android. We work with many partner companies (Samsung, Qualcomm,
> etc) and have basically no visibility into how their hosts are setup,
> and we certainly don't get root access. So I think it's literally
> impossible for us to install a global binfmt_misc handler. We could
> use user/mount namespaces to install a scoped one, but in practice we
> only have 1 version of glibc used in the build, so we might as well
> just bind mount it to /lib64/ld-linux-x86-64.so.2 if we were going to
> use mount namespaces. So while this new binfmt_misc feature is cool,
> and allows for a lot of flexibility, I don't think we would ever use
> it. This means that we also wouldn't have an opportunity to "collect
> data" on how it works.
>
> Another point I'd like to call out is that we build a bunch of tools
> that users will use outside of the build, like adb. It would be nice
> if those tools also weren't dependant on the host system. With the
> binfmt_misc solution, you'd have to run a wrapper tool to set up the
> binfmt_misc handler in a mount namespace (or again, just remount the
> interpreter to a fixed path) before you could run adb, which is more
> friction for users.
>
> Re: the gvisor / additional sandbox concerns, I'd like to not get into
> the weeds too much on this. There are many possibilities to consider
> (another being the default docker config doesn't allow mounts), so I'd
> rather that we consider it a requirement to be able to use a local
> interpreter without any namespaces.
>
> Regarding security, it seems your stance is that it's safer for system
> admins to opt-in to this new functionality, so that if it has security
> flaws, it's their problem. I think that's a dangerous stance to take.
> I could see distros like nixos opting into this because they need it
> and opening themselves up to problems that they are left on their own
> to defend against. If we're going to allow this, making sure we've
> considered security thoroughly enough that it can be made opt-out
> instead of opt-in seems safer for those users. If $ORIGIN support is
> too dangerous to be opt-out, it's probably too dangerous to be opt-in.
>
> I see your concerns about old systems running $ORIGIN binaries and
> treating them as `./$ORIGIN`. Could we potentially fix that by making
> a new PT_INTERP_ORIGIN section? Binaries would only be allowed to have
> one of PT_INTERP or PT_INTERP_ORIGIN, so a PT_INTERP_ORIGIN binary
> would fail to run on an old system, as it doesn't have a PT_INTERP
> section.
>
It's funny you mention PT_INTERP_ORIGIN as that's what was also proposed
on the mailing list here by Alessandro [1]
I also proposed PT_INTERP_NIX in the BPF example. We probably should
collaborate on a single proposal; we should (can) propose it to the ABI
at generic-abi@googlegroups.com or wherever it is discussed.
Once this lands, I liked the systemd solution Christian also offered
here [2].
We can propose this upstream to Debian & Fedora. That way at least you
have a gating function for clients by suggesting that they need Fedora
or Debian version >= X (which you presumably already set).
Happy to discuss this privately as well. I will continue to follow the
thread (hopefully I am now tagged with my correct email) and will
propose it upstream to NixOS as well -- although large changes like this
are always more political to get merged in.
Cool to see all the interest in the topic though.
>> In other words, I think implementing a very custom policy into the core elf loader is a dead-end even if the AT_SECURE and memfd cases simply error out. Every such carve-out becomes frozen uapi. The same binary then runs or fails depending on whether it was reached by path, by fd, as a memfd, or through an overlay. Each of those answers is someone's future regression report and none of them can be changed afterwards.
>
> Are we considering cases where the kernel errors out as API? Wouldn't
> that mean adding the B and L binfmt_misc handlers are also breaking
> api changes, as trying to register a handler with those types before
> would've errored? IMO, erroring out explicitly reserves the API space
> for the future. But I'm not a kernel dev.
>
>> An in-kernel $ORIGIN can always be added later as one more policy. Once shipped it can never be unshipped.
>
> This is understandable. I'm not saying we should rush into adding
> $ORIGIN support right now, I just wanted to keep the conversation of
> it alive, and not declare victory just yet with the binfmt_misc
> solution, as it doesn't cover the usecases most interesting to us. As
> is, we won't be able to use the binfmt_misc solution, which is fine,
> it's no worse of a state than we were in without it, but I would like
> to see something more useful later on.
>
>
>
> On Wed, Jul 22, 2026 at 3:37 AM Christian Brauner <brauner@kernel.org> wrote:
>>
>> On Tue, Jul 21, 2026 at 05:24:21PM -0700, Cole Faust wrote:
>> > Hi Christian, Farid,
>> >
>> > My name is Cole, I work on the android build system. We have similar
>> > goals for creating hermetic and relocatable builds in our build system
>> > (a custom, android-specific one). I was very excited when I saw Farid
>> > working on $ORIGIN support, but then somewhat disappointed when I saw
>> > the new BPF-based solution.
>> >
>> > Our usecase is mostly to decouple the glibc version used in the
>> > android build from the host machine. We've had several instances where
>> > our CI machines are running old glibc versions that cause problems,
>> > and they're not trivial to update. Ideally you should be able to
>> > download the android source and build it on a modern linux kernel,
>> > regardless of the userspace.
>> >
>> > To register a binfmt_misc handler, you need either root + modifying
>> > global state on the host, or to make a user+mount namespace. But if we
>> > use a mount namespace, couldn't we just mount the interpreter we want
>> > to use at a fixed path? I thought one of the main goals of this
>> > features was to avoid the use of namespaces because they don't always
>> > nest well; Farid called this out as a problem with buck2's sandboxing.
>> > In android, we don't yet have any nested sandboxing but there have
>> > been conversations about increasing security of the build using
>> > something like gvisor to isolate the build from the kernel, in wake of
>> > the recent AI-discovered local privilege escalations, after which
>> > these complicated kernel features are likely to stop working. And
>> > requiring root is definitely out of the question.
>>
>> If a single fixed path solves your problem then you indeed don't need
>> any of this. A bind-mount expresses one fixed path pointing to one
>> loader. The handler exists for programmable dispatch so that you match
>> binaries to whatever load you want, use multiple toolchains, allow
>> multiple generations coexisting, per-architecture emulators, etc.
>>
>> A one-line binfmt_misc registration is considerably less invasive than
>> the glibc update you can't do. Plus, it's visible, revocable, and
>> scopable to precisely the formats it matches. You can have the most
>> restrictive policy ever that makes sure only one specific workload is
>> able to use $ORIGIN during build.
>>
>> And gvisor doesn't forward execve() to the host kernel at all. The
>> Sentry reimplements the whole exec path in Go. There is no binfmt_misc
>> and even if we added $ORIGIN support to the kernel it would be invisible
>> to gvisor. Under gvisor you can just patch gvisor without any
>> involvement
>> from us at all.
>>
>> gvisor doesn't forward execve() to the host kernel at all. The Sentry
>> reimplements the whole exec path in Go. There is no binfmt_misc and even
>> if we added $ORIGIN support to the kernel it would be invisible to
>> gvisor. Under gvisor you can just patch gvisor without any involvement
>> from us at all.
>>
>> Fwiw, with $ORIGIN support it's worse. On any kernel or sandbox that
>> doesn't implement $ORIGIN this doesn't fail cleanly. A PT_INTERP of
>> $ORIGIN/ld.so isn't absolute and so Linux resolves it relative to the
>> caller's working directory. Execute such a "relocatable" binary with an
>> attacker-controlled working directory and ./$ORIGIN/ld.so is your
>> loader.
>>
>> So $ORIGIN-tagged binaries are actively dangerous precisely on the old
>> unupdatable machines and future sandboxes you're describing. A
>> binfmt_misc handler that isn't registered simply does nothing.
>>
>> > I also wanted to ask about the security of this bpf solution. I
>> > understand there are some security concerns about $ORIGIN. Why is this
>> > new binfmt_misc + bpf solution better? An attacker will still have
>> > more opportunity to place a malicious loader relative to the
>> > executable. With the binfmt_misc solution, you will be able to only
>> > have it active for certain things, like a build, but that's only if
>> > you use the user+mount namespace to scope it. From what I understand,
>> > Farid plans on registering the handler globally and persistently on
>> > NixOS systems that want relocatable builds, does that not make those
>> > systems susceptible to these concerns? (correct me if that's not your
>> > plan, Farid)
>> >
>> > I can't really think of a better solution than the originally-proposed
>> > $ORIGIN support for build systems to use. I don't care about setuid or
>> > complicated filesystems like memfd, so I would hope it would be
>> > straightforward to just error out if AT_SECURE is set or if any issue
>> > arises like not being able to determine the directory of the
>> > executable. IMO it's fine if it only works in simple, known-safe
>> > cases.
>>
>> This is very focussed on the $ORIGIN case and it's understandable. This
>> is a very specific policy. I understand how it can be useful for a
>> distribution like nixos that wants to make the loader relative to the
>> binary everywhere or to some build system.
>>
>> But this sort of decision is policy and policy doesn't belong into the
>> kernel, it belongs into userspace. The kernel's job in this scenario is
>> to give userspace the tools to implement such policy in a way that it is
>> flexible and doesn't just serve a single use-case.
>>
>> binfmt_misc exists to move custom binary policy out of the kernel and
>> let userspace handle it however it sees fit. As such it is the perfect
>> fit for implementing what loader to use for what binary.
>>
>> The power of this proposal is that $ORIGIN is just one single policy
>> that can be implemented. But it also allows for other custom policies.
>> You could even label binaries with xattrs and use those to decide what
>> loader to use. You could scope it to cgroup or whatever. That's useful
>> and I have use-cases for such policies in other projects.
>>
>> In other words, I think implementing a very custom policy into the core
>> elf loader is a dead-end even if the AT_SECURE and memfd cases simply
>> error out. Every such carve-out becomes frozen uapi. The same binary
>> then runs or fails depending on whether it was reached by path, by fd,
>> as a memfd, or through an overlay. Each of those answers is someone's
>> future regression report and none of them can be changed afterwards.
>>
>> Note that the implicit argument made further up is that the security
>> posture of having native $ORIGIN support is stronger than having a way
>> to implement whatever policy - including $ORIGIN - via binfmt_misc.
>> That's very obviously false.
>>
>> Implementing $ORIGIN natively means we start shipping a static, custom
>> policy _to everyone_ out there next release. Whereas binfmt_misc does
>> _nothing_ and only affects users that actually do need this custom
>> policy and do set it up. And once they have set it up the existence of a
>> policy is even visible via binfmt_misc.
>>
>> So the security story of enabling $ORIGIN in core elf code is a lot
>> weaker: it's inflexible, it's unclear what holes it opens up, and users
>> will be surprised by it.
>>
>> If users don't care about the bpf policy support for binfmt_misc and are
>> worried about someone registering a bpf handler: CONFIG_BINFMT_MISC_BPF=n
>>
>> Btw, the exact semantics you're asking for ($ORIGIN-prefixed PT_INTERP
>> resolved against the binary's directory and hard failure for everything
>> unusual) are about a hundred lines of bpf on top of what is already
>> in the tree. The $ORIGIN demo handler written for the series does
>> exactly that, including failing closed instead of falling back to the
>> cwd-relative lookup mentioned above. So you can deploy the policy you
>> want today on hosts you administer, collect data on how it behaves in
>> practice, and if a blessed subset ever emerges that conversation can be
>> had with evidence. An in-kernel $ORIGIN can always be added later as one
>> more policy. Once shipped it can never be unshipped.
[1] https://lore.kernel.org/linux-fsdevel/20260722011217.45e79a08@spawn/#t
[2] https://lore.kernel.org/linux-fsdevel/20260722-raser-leselust-konsolidieren-05f8e36a0782@brauner/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Questions and concerns about BPF-selected interpreter
2026-07-22 19:29 ` Cole Faust
2026-07-23 0:16 ` Farid Zakaria
@ 2026-07-23 13:15 ` Christian Brauner
1 sibling, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2026-07-23 13:15 UTC (permalink / raw)
To: Cole Faust; +Cc: farid.m.zakaria, linux-fsdevel, Jann Horn
On Wed, Jul 22, 2026 at 12:29:14PM -0700, Cole Faust wrote:
> Hi Christian,
Hey, this is a really petty complaint but general protocol for lkml
threads is bottom- or inline posting. This makes it a bit harder to keep
everythin in order.
>
> Thanks for the response. You mention a couple of times that we could
Thank you for your arguments.
> install the binfmt_misc handler and go from there, ("A one-line
> binfmt_misc registration is considerably less invasive than
> the glibc update you can't do", "So you can deploy the policy you want
> today on hosts you administer"), but we don't control the hosts that
> build android. We work with many partner companies (Samsung, Qualcomm,
> etc) and have basically no visibility into how their hosts are setup,
> and we certainly don't get root access. So I think it's literally
> impossible for us to install a global binfmt_misc handler. We could
> use user/mount namespaces to install a scoped one, but in practice we
> only have 1 version of glibc used in the build, so we might as well
> just bind mount it to /lib64/ld-linux-x86-64.so.2 if we were going to
> use mount namespaces. So while this new binfmt_misc feature is cool,
> and allows for a lot of flexibility, I don't think we would ever use
> it. This means that we also wouldn't have an opportunity to "collect
> data" on how it works.
That's a fair point. If you don't control the hosts you can't register a
handler on them. But the exact same is true for native $ORIGIN. You
can't put a new kernel on Samsung's build machines either. Native
$ORIGIN reaches those hosts the same way a handler does. The host gets a
distro refresh at some point and you gate on the version which afaiu you
already do in some form.
So reach and timeline seem similar. The difference is what is frozen
once it arrives. With native $ORIGIN the resolution semantics are kernel
ABI forever. With a marker header plus a distro-shipped handler the
semantics live in a small userspace program that the distro can fix,
tighten, or extend in a regular update. Same machines, same delay, very
different cost when something inevitably needs to change.
And the deployment data doesn't have to come from android. nixos and
rev.ng style deployments will generate it.
> Another point I'd like to call out is that we build a bunch of tools
> that users will use outside of the build, like adb. It would be nice
> if those tools also weren't dependant on the host system. With the
> binfmt_misc solution, you'd have to run a wrapper tool to set up the
> binfmt_misc handler in a mount namespace (or again, just remount the
> interpreter to a fixed path) before you could run adb, which is more
> friction for users.
Tools you hand to arbitrary end users won't be covered by any
kernel-side mechanism for years no matter which one wins because most
user machines run old kernels. If adb must work on any host today the
answer is toolchain-side. Either static linking or a small bootstrap
that locates the bundled loader relative to /proc/self/exe. That's
independent of this whole discussion imho.
> Re: the gvisor / additional sandbox concerns, I'd like to not get into
> the weeds too much on this. There are many possibilities to consider
> (another being the default docker config doesn't allow mounts), so I'd
> rather that we consider it a requirement to be able to use a local
> interpreter without any namespaces.
Sure. Note that with a distro-shipped default policy that requirement is
met. The user just execs the binary. No namespaces, no root, no wrapper.
The privileged part happened once, when the distro was assembled.
> Regarding security, it seems your stance is that it's safer for system
> admins to opt-in to this new functionality, so that if it has security
> flaws, it's their problem. I think that's a dangerous stance to take.
> I could see distros like nixos opting into this because they need it
> and opening themselves up to problems that they are left on their own
> to defend against. If we're going to allow this, making sure we've
> considered security thoroughly enough that it can be made opt-out
> instead of opt-in seems safer for those users. If $ORIGIN support is
> too dangerous to be opt-out, it's probably too dangerous to be opt-in.
That's not my stance. The point isn't to shift liability to admins.
The point is that whether resolving a loader relative to the binary is
safe depends on invariants of the concrete deployment. Is the tree
immutable? Who may write to it? Which prefixes are trusted? The kernel
doesn't know any of that. So no amount of security consideration
produces semantics that are safe to turn on for everyone.
A nixos handler that only fires for /nix/store is safe because the store
is root-owned and immutable. The same semantics pointed at a
world-writable directory are a hole. Only the deployment knows which of
the two it is.
"if it's too dangerous to be opt-out it's too dangerous to be opt-in" is
a bit of a trick imho. By that logic no LSM policy, no sysctl, no
sudoers, and no PAM configuration could exist. Security policy that
depends on context is configured. That's not a defect.
Distros can configure this however they see fit.
> I see your concerns about old systems running $ORIGIN binaries and
> treating them as `./$ORIGIN`. Could we potentially fix that by making
> a new PT_INTERP_ORIGIN section? Binaries would only be allowed to have
> one of PT_INTERP or PT_INTERP_ORIGIN, so a PT_INTERP_ORIGIN binary
> would fail to run on an old system, as it doesn't have a PT_INTERP
> section.
A new program header type as a pure marker is completely fine by me
and a lot better than hiding magic strings in PT_INTERP.
The handler matches on it, the distro ships the default policy for it,
and the 'L' series does the substitution. Alessandro floated the same
idea as PT_INTERP_WITH_ORIGIN and Farid as PT_INTERP_NIX.
But an old kernel doesn't cleanly refuse such a binary.
load_elf_binary() simply ignores program header types it doesn't know. A
binary with PT_INTERP_ORIGIN and no PT_INTERP loads as static and jumps
to an entry point that was never relocated and so crashes instead of
failing with a clean error.
Where I remain firm is the split. The header names the intent and the
handler implements the semantics. If deployments later show that one
specific resolution policy is stable and safe, graduating that subset
into the kernel is a discussion we can have.
> > In other words, I think implementing a very custom policy into the core elf loader is a dead-end even if the AT_SECURE and memfd cases simply error out. Every such carve-out becomes frozen uapi. The same binary then runs or fails depending on whether it was reached by path, by fd, as a memfd, or through an overlay. Each of those answers is someone's future regression report and none of them can be changed afterwards.
>
> Are we considering cases where the kernel errors out as API? Wouldn't
> that mean adding the B and L binfmt_misc handlers are also breaking
> api changes, as trying to register a handler with those types before
> would've errored? IMO, erroring out explicitly reserves the API space
> for the future. But I'm not a kernel dev.
No. Registering a handler is a root-only configuration interface.
Accepting a new flag there is ordinary interface evolution. Same as a
new mount option or a new prctl. It's deterministic. The same string
fails on an old kernel and works on a new one and whoever registers
checks for that.
What I called frozen uapi is the exec behavior of arbitrary binaries.
With native $ORIGIN the same binary succeeds or fails depending on how
it was reached and those context-dependent outcomes are exactly what
userspace silently grows dependencies on and what we can never change
afterwards. Erroring out reserves design space when the error is
deterministic and context-free. These aren't.
>
> > An in-kernel $ORIGIN can always be added later as one more policy. Once shipped it can never be unshipped.
>
> This is understandable. I'm not saying we should rush into adding
> $ORIGIN support right now, I just wanted to keep the conversation of
> it alive, and not declare victory just yet with the binfmt_misc
> solution, as it doesn't cover the usecases most interesting to us. As
> is, we won't be able to use the binfmt_misc solution, which is fine,
> it's no worse of a state than we were in without it, but I would like
> to see something more useful later on.
Keeping it alive is welcome and nothing here is declared victory. My
pushback is about which layer owns which piece. The marker header via
generic-abi or whatever plus distro-shipped default policy gets you and
Alessandro by-default behavior on the systems that matter without
freezing resolution semantics into core elf on day one.
> On Wed, Jul 22, 2026 at 3:37 AM Christian Brauner <brauner@kernel.org> wrote:
> >
> > On Tue, Jul 21, 2026 at 05:24:21PM -0700, Cole Faust wrote:
> > > Hi Christian, Farid,
> > >
> > > My name is Cole, I work on the android build system. We have similar
> > > goals for creating hermetic and relocatable builds in our build system
> > > (a custom, android-specific one). I was very excited when I saw Farid
> > > working on $ORIGIN support, but then somewhat disappointed when I saw
> > > the new BPF-based solution.
> > >
> > > Our usecase is mostly to decouple the glibc version used in the
> > > android build from the host machine. We've had several instances where
> > > our CI machines are running old glibc versions that cause problems,
> > > and they're not trivial to update. Ideally you should be able to
> > > download the android source and build it on a modern linux kernel,
> > > regardless of the userspace.
> > >
> > > To register a binfmt_misc handler, you need either root + modifying
> > > global state on the host, or to make a user+mount namespace. But if we
> > > use a mount namespace, couldn't we just mount the interpreter we want
> > > to use at a fixed path? I thought one of the main goals of this
> > > features was to avoid the use of namespaces because they don't always
> > > nest well; Farid called this out as a problem with buck2's sandboxing.
> > > In android, we don't yet have any nested sandboxing but there have
> > > been conversations about increasing security of the build using
> > > something like gvisor to isolate the build from the kernel, in wake of
> > > the recent AI-discovered local privilege escalations, after which
> > > these complicated kernel features are likely to stop working. And
> > > requiring root is definitely out of the question.
> >
> > If a single fixed path solves your problem then you indeed don't need
> > any of this. A bind-mount expresses one fixed path pointing to one
> > loader. The handler exists for programmable dispatch so that you match
> > binaries to whatever load you want, use multiple toolchains, allow
> > multiple generations coexisting, per-architecture emulators, etc.
> >
> > A one-line binfmt_misc registration is considerably less invasive than
> > the glibc update you can't do. Plus, it's visible, revocable, and
> > scopable to precisely the formats it matches. You can have the most
> > restrictive policy ever that makes sure only one specific workload is
> > able to use $ORIGIN during build.
> >
> > And gvisor doesn't forward execve() to the host kernel at all. The
> > Sentry reimplements the whole exec path in Go. There is no binfmt_misc
> > and even if we added $ORIGIN support to the kernel it would be invisible
> > to gvisor. Under gvisor you can just patch gvisor without any
> > involvement
> > from us at all.
> >
> > gvisor doesn't forward execve() to the host kernel at all. The Sentry
> > reimplements the whole exec path in Go. There is no binfmt_misc and even
> > if we added $ORIGIN support to the kernel it would be invisible to
> > gvisor. Under gvisor you can just patch gvisor without any involvement
> > from us at all.
> >
> > Fwiw, with $ORIGIN support it's worse. On any kernel or sandbox that
> > doesn't implement $ORIGIN this doesn't fail cleanly. A PT_INTERP of
> > $ORIGIN/ld.so isn't absolute and so Linux resolves it relative to the
> > caller's working directory. Execute such a "relocatable" binary with an
> > attacker-controlled working directory and ./$ORIGIN/ld.so is your
> > loader.
> >
> > So $ORIGIN-tagged binaries are actively dangerous precisely on the old
> > unupdatable machines and future sandboxes you're describing. A
> > binfmt_misc handler that isn't registered simply does nothing.
> >
> > > I also wanted to ask about the security of this bpf solution. I
> > > understand there are some security concerns about $ORIGIN. Why is this
> > > new binfmt_misc + bpf solution better? An attacker will still have
> > > more opportunity to place a malicious loader relative to the
> > > executable. With the binfmt_misc solution, you will be able to only
> > > have it active for certain things, like a build, but that's only if
> > > you use the user+mount namespace to scope it. From what I understand,
> > > Farid plans on registering the handler globally and persistently on
> > > NixOS systems that want relocatable builds, does that not make those
> > > systems susceptible to these concerns? (correct me if that's not your
> > > plan, Farid)
> > >
> > > I can't really think of a better solution than the originally-proposed
> > > $ORIGIN support for build systems to use. I don't care about setuid or
> > > complicated filesystems like memfd, so I would hope it would be
> > > straightforward to just error out if AT_SECURE is set or if any issue
> > > arises like not being able to determine the directory of the
> > > executable. IMO it's fine if it only works in simple, known-safe
> > > cases.
> >
> > This is very focussed on the $ORIGIN case and it's understandable. This
> > is a very specific policy. I understand how it can be useful for a
> > distribution like nixos that wants to make the loader relative to the
> > binary everywhere or to some build system.
> >
> > But this sort of decision is policy and policy doesn't belong into the
> > kernel, it belongs into userspace. The kernel's job in this scenario is
> > to give userspace the tools to implement such policy in a way that it is
> > flexible and doesn't just serve a single use-case.
> >
> > binfmt_misc exists to move custom binary policy out of the kernel and
> > let userspace handle it however it sees fit. As such it is the perfect
> > fit for implementing what loader to use for what binary.
> >
> > The power of this proposal is that $ORIGIN is just one single policy
> > that can be implemented. But it also allows for other custom policies.
> > You could even label binaries with xattrs and use those to decide what
> > loader to use. You could scope it to cgroup or whatever. That's useful
> > and I have use-cases for such policies in other projects.
> >
> > In other words, I think implementing a very custom policy into the core
> > elf loader is a dead-end even if the AT_SECURE and memfd cases simply
> > error out. Every such carve-out becomes frozen uapi. The same binary
> > then runs or fails depending on whether it was reached by path, by fd,
> > as a memfd, or through an overlay. Each of those answers is someone's
> > future regression report and none of them can be changed afterwards.
> >
> > Note that the implicit argument made further up is that the security
> > posture of having native $ORIGIN support is stronger than having a way
> > to implement whatever policy - including $ORIGIN - via binfmt_misc.
> > That's very obviously false.
> >
> > Implementing $ORIGIN natively means we start shipping a static, custom
> > policy _to everyone_ out there next release. Whereas binfmt_misc does
> > _nothing_ and only affects users that actually do need this custom
> > policy and do set it up. And once they have set it up the existence of a
> > policy is even visible via binfmt_misc.
> >
> > So the security story of enabling $ORIGIN in core elf code is a lot
> > weaker: it's inflexible, it's unclear what holes it opens up, and users
> > will be surprised by it.
> >
> > If users don't care about the bpf policy support for binfmt_misc and are
> > worried about someone registering a bpf handler: CONFIG_BINFMT_MISC_BPF=n
> >
> > Btw, the exact semantics you're asking for ($ORIGIN-prefixed PT_INTERP
> > resolved against the binary's directory and hard failure for everything
> > unusual) are about a hundred lines of bpf on top of what is already
> > in the tree. The $ORIGIN demo handler written for the series does
> > exactly that, including failing closed instead of falling back to the
> > cwd-relative lookup mentioned above. So you can deploy the policy you
> > want today on hosts you administer, collect data on how it behaves in
> > practice, and if a blessed subset ever emerges that conversation can be
> > had with evidence. An in-kernel $ORIGIN can always be added later as one
> > more policy. Once shipped it can never be unshipped.
--
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-07-23 13:15 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-22 0:24 Questions and concerns about BPF-selected interpreter Cole Faust
2026-07-22 0:26 ` Cole Faust
2026-07-22 3:58 ` Farid Zakaria
2026-07-22 4:10 ` Farid Zakaria
2026-07-22 5:19 ` Farid Zakaria
2026-07-22 19:39 ` Cole Faust
2026-07-22 10:36 ` Christian Brauner
2026-07-22 19:29 ` Cole Faust
2026-07-23 0:16 ` Farid Zakaria
2026-07-23 13:15 ` Christian Brauner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox