mbox series

[RFC,0/9] Landlock supervise: a mechanism for interactive permission requests

Message ID cover.1741047969.git.m@maowtm.org (mailing list archive)
Headers show
Series Landlock supervise: a mechanism for interactive permission requests | expand

Message

Tingmao Wang March 4, 2025, 1:12 a.m. UTC
Landlock supervise: a mechanism for interactive permission requests

Hi,

I would like to propose an extension to Landlock to support a "supervisor"
mode, which would enable a user program to sandbox applications (or
itself) in a dynamic, fine-grained, and potentially temporary way.
Practically, this makes it easy to give maximal control to the user,
perhaps in the form of a "just in time" permission prompt.  Read on, or
check the sandboxer program in the last patch for a "demo".

To Jan Kara and other fanotify reviewers, I've included you in this patch
as Mickaël suggested that we could potentially extend and re-use the
fanotify uapi and code instead of creating an entirely new representation
for permission requests and mechanism for passing it (as this patch
currently does).  I've not really thought out how that would work (there
will probably have to be some extension of the fanotify-fd uapi since
landlock handles more than FS access), but I think it is a promising idea,
hence I would like to hear your thoughts if you could spare a moment to
look at this.  A good outcome could also be that we add the necessary
hooks so that both this and fanotify (but really fsnotify?) can have _perm
events for create/delete/rename etc.

FS mailing list - I've CC'd this patchset to you too - even though the
patch doesn't currently touch any FS code, this is very FS related, and
also, in order to address an inode lock related problem which I will
mention in patch 6 of this series, future versions of this patch will
likely need to add a few more LSM hooks.  Especially for that part, but
also other bits of this project, a pair of eyes from the FS community
would be very helpful.

To Tycho Andersen -- I'm CC'ing you as you've worked on the seccomp-unotify
feature which is also quite related, so if you could spare some time for a
quick review, or provide some suggestions, that would be very appreciated
:)

I'm submitting this series as a non-production-ready, proof-of-concept
RFC, and I would appreciate feedback on any aspects of the design or
implementation.  Note that due to the PoC nature of this, I have not
handled checkpatch.pl errors etc.  I also welcome suggestions for
alternative names for this feature (e.g. landlock-unotify?
landlock-perm?).  At this point I'm very keen to hear some initial
feedback from the community before investing further into polishing this
patch.

(I've briefly pitched the overall idea to Mickaël, but he has not reviewed
the patch yet)


Why extend landlock?
--------------------

While this feature could be implemented as its own LSM, I feel like it is
a natural extension to landlock -- landlock has already defined a set of
fine-grained access requests with the intention to add more (and not just
for FS alone), is designed to be an unprivileged, stackable,
process-scoped, ad-hoc mechanism with no persistent state, which works
well as a generic API to support a dynamic sandbox, and landlock is
already doing the path traversal work to evaluate hierarchical filesystem
rules, which would also be useful for a performant dynamic sandbox
implementation.


Use cases
---------

I have several potential use cases in mind that will benefit from
landlock-supervise, for example:

1. A patch to firejail (I have not discussed with the firejail maintainers
on this yet - wanted to see the reception of this kernel patch first)
which can leverage landlock in a highly flexible way, prompting the user
for permission to access "extra" files after the sandbox has started
(without e.g. having to restart a very stateful GUI program).

This way of using landlock can potentially replace its current approach of
using bind mounts (as it will allow implementing "blacklists"), allowing
unprivileged sandbox creation (although need to check with firejail if
there are other factors preventing this).  This also allows editing
profiles "live" in a highly interactive way (i.e. the user can choose
"allow and remember" on a permission request which will also add the newly
allowed path to a local firejail profile, all automatically)

2. A "protected" mode for common development environments (e.g. VSCode or
a terminal can be launched "protected") that doesn't compromise on
ease-of-use.  File access to $PWD at launch can be allowed, and access to
other places can be allowed ad-hoc by the developer with hopefully one UI
click.  Since landlock can also be used to restrict network access, such a
protected mode can also restrict outgoing connections by default (but ask
the user if they allow it for all or certain processes, on the first
attempt to connect).

Recently there has been incidents of secret-stealing malware targeting
developers (on Linux) by social engineering them to open and build/run a
project. [1]  The hope is that landlock-supervise can drive adoption of
sandboxes for developers and others by making them more user-friendly.

In addition to the above, I also hope that this would help with landlock
adoption even in non-interaction-heavy scenarios, by allowing application
developers the choice to gracefully recover from over-restrictive rulesets
and collect failure metrics, until they are confident that actually
blocking non-allowed accesses would not break their application or degrade
the user experience.

I have more exploration to do regarding applying this to applications, but
I do have a working proof of concept already (implemented as an
enhancement to the sandboxer example). Here is a shortened output:

    bash # env LL_FS_RO=/usr:/lib:/bin:/etc:/dev:/proc LL_FS_RW= LL_SUPERVISE=1 ./sandboxer bash -i
    bash # echo "Hi, $(whoami)!"
    Hi, root!
    bash # ls /
    ------------- Sandboxer access request -------------
    Process ls[166] (/usr/bin/ls) wants to read
      /
    (y)es/(a)lways/(n)o > y
    ----------------------------------------------------
    bin
    boot
    dev
    ...
    usr
    var
    bash # echo 'evil' >> /etc/profile
    (a spurious create request due to current issue with dcache miss is omitted)
    ------------- Sandboxer access request -------------
    Process bash[163] (/usr/bin/bash) wants to read/write
      /etc/profile
    (y)es/(a)lways/(n)o > n
    ----------------------------------------------------
    bash: /etc/profile: Permission denied
    bash #


Alternatives
------------

I have looked for existing ways to implement the proposed use cases (at
least for FS access), and three main approaches stand out to me:

1. Fanotify: there is already FAM_OPEN_PERM which waits for an allow/deny
response from a fanotify listener.  However, it does not currently have
the equivalent _PERM for file creation, deletion, rename and linking, and
it is also not designed for unprivileged, process-scoped use (unlike
landlock).

2. Seccomp-unotify: this can be used to trap all syscalls and give the
sandbox a chance to allow or deny any one of them. However, a correct,
TOCTOU-proof implementation will likely require handling a large number of
fs-related syscalls in user-space, with the sandboxer opening the file or
carrying out the operation on behalf of the sandboxee.  This is probably
going to be extremely complex and makes everything less performant.

3. Using a FUSE filesystem which gates access.  This is actually an
approach taken by an existing sandbox solution - flatpak [2], however it
requires either tight integration with the application (and thus doesn't
work well for the mentioned use cases), or if one wants to sandbox a
program "transparently", SYS_ADMIN to chroot.


I've tested that what I have here works with the enhanced sandboxer, but
have yet to write any self tests or do extensive testing or perf
measurements.  I have also yet to implement support for supervising tcp
rules as well as FS refer operations.

Base commit: 78332fdb956f18accfbca5993b10c5ed69f00a2c (tag:
landlock-6.14-rc5, mic/next)


[1]: https://cybersecuritynews.com/beware-of-lazarus-linkedin-recruiting-scam/
[2]: https://flatpak.github.io/xdg-desktop-portal/docs/documents-and-fuse.html


Tingmao Wang (9):
  Define the supervisor and event structure
  Refactor per-layer information in rulesets and rules
  Adds a supervisor reference in the per-layer information
  User-space API for creating a supervisor-fd
  Define user structure for events and responses.
  Creating supervisor events for filesystem operations
  Implement fdinfo for ruleset and supervisor fd
  Implement fops for supervisor-fd
  Enhance the sandboxer example to support landlock-supervise

 include/uapi/linux/landlock.h | 119 ++++++
 samples/landlock/sandboxer.c  | 759 +++++++++++++++++++++++++++++++++-
 security/landlock/Makefile    |   2 +-
 security/landlock/fs.c        | 134 +++++-
 security/landlock/ruleset.c   |  49 ++-
 security/landlock/ruleset.h   |  66 +--
 security/landlock/supervise.c | 194 +++++++++
 security/landlock/supervise.h | 171 ++++++++
 security/landlock/syscalls.c  | 621 +++++++++++++++++++++++++++-
 9 files changed, 2036 insertions(+), 79 deletions(-)
 create mode 100644 security/landlock/supervise.c
 create mode 100644 security/landlock/supervise.h

--
2.39.5

Comments

Mickaël Salaün March 4, 2025, 7:48 p.m. UTC | #1
On Tue, Mar 04, 2025 at 01:12:56AM +0000, Tingmao Wang wrote:
> Landlock supervise: a mechanism for interactive permission requests
> 
> Hi,
> 
> I would like to propose an extension to Landlock to support a "supervisor"
> mode, which would enable a user program to sandbox applications (or
> itself) in a dynamic, fine-grained, and potentially temporary way.
> Practically, this makes it easy to give maximal control to the user,
> perhaps in the form of a "just in time" permission prompt.  Read on, or
> check the sandboxer program in the last patch for a "demo".

Thanks for this RFC, this is very promising!

> 
> To Jan Kara and other fanotify reviewers, I've included you in this patch
> as Mickaël suggested that we could potentially extend and re-use the
> fanotify uapi and code instead of creating an entirely new representation
> for permission requests and mechanism for passing it (as this patch
> currently does).  I've not really thought out how that would work (there
> will probably have to be some extension of the fanotify-fd uapi since
> landlock handles more than FS access), but I think it is a promising idea,
> hence I would like to hear your thoughts if you could spare a moment to
> look at this.  A good outcome could also be that we add the necessary
> hooks so that both this and fanotify (but really fsnotify?) can have _perm
> events for create/delete/rename etc.
> 
> FS mailing list - I've CC'd this patchset to you too - even though the
> patch doesn't currently touch any FS code, this is very FS related, and
> also, in order to address an inode lock related problem which I will
> mention in patch 6 of this series, future versions of this patch will
> likely need to add a few more LSM hooks.  Especially for that part, but
> also other bits of this project, a pair of eyes from the FS community
> would be very helpful.
> 
> To Tycho Andersen -- I'm CC'ing you as you've worked on the seccomp-unotify
> feature which is also quite related, so if you could spare some time for a
> quick review, or provide some suggestions, that would be very appreciated
> :)
> 
> I'm submitting this series as a non-production-ready, proof-of-concept
> RFC, and I would appreciate feedback on any aspects of the design or
> implementation.  Note that due to the PoC nature of this, I have not
> handled checkpatch.pl errors etc.  I also welcome suggestions for
> alternative names for this feature (e.g. landlock-unotify?
> landlock-perm?).  At this point I'm very keen to hear some initial
> feedback from the community before investing further into polishing this
> patch.
> 
> (I've briefly pitched the overall idea to Mickaël, but he has not reviewed
> the patch yet)
> 
> 
> Why extend landlock?
> --------------------
> 
> While this feature could be implemented as its own LSM, I feel like it is
> a natural extension to landlock -- landlock has already defined a set of
> fine-grained access requests with the intention to add more (and not just
> for FS alone), is designed to be an unprivileged, stackable,
> process-scoped, ad-hoc mechanism with no persistent state, which works
> well as a generic API to support a dynamic sandbox, and landlock is
> already doing the path traversal work to evaluate hierarchical filesystem
> rules, which would also be useful for a performant dynamic sandbox
> implementation.

I agree, that would be a great Landlock feature.

> 
> 
> Use cases
> ---------
> 
> I have several potential use cases in mind that will benefit from
> landlock-supervise, for example:
> 
> 1. A patch to firejail (I have not discussed with the firejail maintainers
> on this yet - wanted to see the reception of this kernel patch first)
> which can leverage landlock in a highly flexible way, prompting the user
> for permission to access "extra" files after the sandbox has started
> (without e.g. having to restart a very stateful GUI program).
> 
> This way of using landlock can potentially replace its current approach of
> using bind mounts (as it will allow implementing "blacklists"), allowing
> unprivileged sandbox creation (although need to check with firejail if
> there are other factors preventing this).  This also allows editing
> profiles "live" in a highly interactive way (i.e. the user can choose
> "allow and remember" on a permission request which will also add the newly
> allowed path to a local firejail profile, all automatically)
> 
> 2. A "protected" mode for common development environments (e.g. VSCode or
> a terminal can be launched "protected") that doesn't compromise on
> ease-of-use.  File access to $PWD at launch can be allowed, and access to
> other places can be allowed ad-hoc by the developer with hopefully one UI
> click.  Since landlock can also be used to restrict network access, such a
> protected mode can also restrict outgoing connections by default (but ask
> the user if they allow it for all or certain processes, on the first
> attempt to connect).
> 
> Recently there has been incidents of secret-stealing malware targeting
> developers (on Linux) by social engineering them to open and build/run a
> project. [1]  The hope is that landlock-supervise can drive adoption of
> sandboxes for developers and others by making them more user-friendly.
> 
> In addition to the above, I also hope that this would help with landlock
> adoption even in non-interaction-heavy scenarios, by allowing application
> developers the choice to gracefully recover from over-restrictive rulesets
> and collect failure metrics, until they are confident that actually
> blocking non-allowed accesses would not break their application or degrade
> the user experience.

Another interesting use case is to trace programs and get an
unprivileged "permissive" mode to quickly create sandbox policies.

> 
> I have more exploration to do regarding applying this to applications, but
> I do have a working proof of concept already (implemented as an
> enhancement to the sandboxer example). Here is a shortened output:
> 
>     bash # env LL_FS_RO=/usr:/lib:/bin:/etc:/dev:/proc LL_FS_RW= LL_SUPERVISE=1 ./sandboxer bash -i
>     bash # echo "Hi, $(whoami)!"
>     Hi, root!
>     bash # ls /
>     ------------- Sandboxer access request -------------
>     Process ls[166] (/usr/bin/ls) wants to read
>       /
>     (y)es/(a)lways/(n)o > y
>     ----------------------------------------------------
>     bin
>     boot
>     dev
>     ...
>     usr
>     var
>     bash # echo 'evil' >> /etc/profile
>     (a spurious create request due to current issue with dcache miss is omitted)
>     ------------- Sandboxer access request -------------
>     Process bash[163] (/usr/bin/bash) wants to read/write
>       /etc/profile
>     (y)es/(a)lways/(n)o > n
>     ----------------------------------------------------
>     bash: /etc/profile: Permission denied
>     bash #
> 
> 
> Alternatives
> ------------
> 
> I have looked for existing ways to implement the proposed use cases (at
> least for FS access), and three main approaches stand out to me:
> 
> 1. Fanotify: there is already FAM_OPEN_PERM which waits for an allow/deny
> response from a fanotify listener.  However, it does not currently have
> the equivalent _PERM for file creation, deletion, rename and linking, and
> it is also not designed for unprivileged, process-scoped use (unlike
> landlock).

As discussed, I was thinking about whether or not it would be possible
to use the fanotify interface (e.g. fanotify_init(), fanotify FD...),
but looking at your code, I think it would mostly increase complexity.
There are also the issue with the Landlock semantic (e.g. access rights)
which does not map 1:1 to the fanotify one.  A last thing is that
fanotify is deeply tied to the VFS.  So, unless someone has a better
idea, let's continue with your approach.

> 
> 2. Seccomp-unotify: this can be used to trap all syscalls and give the
> sandbox a chance to allow or deny any one of them. However, a correct,
> TOCTOU-proof implementation will likely require handling a large number of
> fs-related syscalls in user-space, with the sandboxer opening the file or
> carrying out the operation on behalf of the sandboxee.  This is probably
> going to be extremely complex and makes everything less performant.

We should get inspiration from the fanotify and seccomp-notify features
(while implementing the minimum for now) but also identify their design
issues and caveats.

Tycho, Christian, Kees, any suggestion?

> 
> 3. Using a FUSE filesystem which gates access.  This is actually an
> approach taken by an existing sandbox solution - flatpak [2], however it
> requires either tight integration with the application (and thus doesn't
> work well for the mentioned use cases), or if one wants to sandbox a
> program "transparently", SYS_ADMIN to chroot.

Android's SDCardFS is another example of such use.

> 
> 
> I've tested that what I have here works with the enhanced sandboxer, but
> have yet to write any self tests or do extensive testing or perf
> measurements.  I have also yet to implement support for supervising tcp
> rules as well as FS refer operations.

One of the main suggestion would be to align with the audit patch series
semantic and the defined "blockers":
https://lore.kernel.org/all/20250131163059.1139617-1-mic@digikod.net/
I'll send another series soon.

> 
> Base commit: 78332fdb956f18accfbca5993b10c5ed69f00a2c (tag:
> landlock-6.14-rc5, mic/next)
> 
> 
> [1]: https://cybersecuritynews.com/beware-of-lazarus-linkedin-recruiting-scam/
> [2]: https://flatpak.github.io/xdg-desktop-portal/docs/documents-and-fuse.html
> 
> 
> Tingmao Wang (9):
>   Define the supervisor and event structure
>   Refactor per-layer information in rulesets and rules
>   Adds a supervisor reference in the per-layer information
>   User-space API for creating a supervisor-fd
>   Define user structure for events and responses.
>   Creating supervisor events for filesystem operations
>   Implement fdinfo for ruleset and supervisor fd
>   Implement fops for supervisor-fd
>   Enhance the sandboxer example to support landlock-supervise
> 
>  include/uapi/linux/landlock.h | 119 ++++++
>  samples/landlock/sandboxer.c  | 759 +++++++++++++++++++++++++++++++++-
>  security/landlock/Makefile    |   2 +-
>  security/landlock/fs.c        | 134 +++++-
>  security/landlock/ruleset.c   |  49 ++-
>  security/landlock/ruleset.h   |  66 +--
>  security/landlock/supervise.c | 194 +++++++++
>  security/landlock/supervise.h | 171 ++++++++
>  security/landlock/syscalls.c  | 621 +++++++++++++++++++++++++++-
>  9 files changed, 2036 insertions(+), 79 deletions(-)
>  create mode 100644 security/landlock/supervise.c
>  create mode 100644 security/landlock/supervise.h
> 
> --
> 2.39.5
>
Tingmao Wang March 6, 2025, 2:57 a.m. UTC | #2
On 3/4/25 19:48, Mickaël Salaün wrote:

> Thanks for this RFC, this is very promising!

Hi Mickaël - thanks for the prompt review and for your support! I have 
read your replies and have some thoughts already, but I kept getting 
distracted by other stuff and so haven't had much chance to express 
them.  I will address some first today and some more over the weekend.

> Another interesting use case is to trace programs and get an
> unprivileged "permissive" mode to quickly create sandbox policies.

Yes that would also be a good use. I thought of this initially but was 
thinking "I guess you can always do that with audit" but if we have 
landlock supervise maybe that would be an easier thing for tools to 
build upon...?

> As discussed, I was thinking about whether or not it would be possible
> to use the fanotify interface (e.g. fanotify_init(), fanotify FD...),
> but looking at your code, I think it would mostly increase complexity.
> There are also the issue with the Landlock semantic (e.g. access rights)
> which does not map 1:1 to the fanotify one.  A last thing is that
> fanotify is deeply tied to the VFS.  So, unless someone has a better
> idea, let's continue with your approach.

That sounds sensible - I will keep going with the current direction of a 
landlock-specific uapi. (happy to revisit should other people have 
suggestions)

> Android's SDCardFS is another example of such use.

Interesting - seems like it was deprecated for reasons unrelated to 
security though.

> One of the main suggestion would be to align with the audit patch series
> semantic and the defined "blockers":
> https://lore.kernel.org/all/20250131163059.1139617-1-mic@digikod.net/
> I'll send another series soon.

I will have a read of the existing audit series - are you planning 
significant changes to it in the next one?
Amir Goldstein March 6, 2025, 5:07 p.m. UTC | #3
On Thu, Mar 6, 2025 at 3:57 AM Tingmao Wang <m@maowtm.org> wrote:
>
> On 3/4/25 19:48, Mickaël Salaün wrote:
>
> > Thanks for this RFC, this is very promising!
>
> Hi Mickaël - thanks for the prompt review and for your support! I have
> read your replies and have some thoughts already, but I kept getting
> distracted by other stuff and so haven't had much chance to express
> them.  I will address some first today and some more over the weekend.
>
> > Another interesting use case is to trace programs and get an
> > unprivileged "permissive" mode to quickly create sandbox policies.
>
> Yes that would also be a good use. I thought of this initially but was
> thinking "I guess you can always do that with audit" but if we have
> landlock supervise maybe that would be an easier thing for tools to
> build upon...?
>
> > As discussed, I was thinking about whether or not it would be possible
> > to use the fanotify interface (e.g. fanotify_init(), fanotify FD...),
> > but looking at your code, I think it would mostly increase complexity.
> > There are also the issue with the Landlock semantic (e.g. access rights)
> > which does not map 1:1 to the fanotify one.  A last thing is that
> > fanotify is deeply tied to the VFS.  So, unless someone has a better
> > idea, let's continue with your approach.
>
> That sounds sensible - I will keep going with the current direction of a
> landlock-specific uapi. (happy to revisit should other people have
> suggestions)
>

w.r.t sharing infrastructure with fanotify, I only looked briefly at
your patches
and I have only a vague familiarity with landlock, so I cannot yet form an
opinion whether this is a good idea, but I wanted to give you a few more
data points about fanotify that seem relevant.

1. There is already some intersection of fanotify and audit lsm via the
fanotify_response_info_audit_rule extension for permission
events, so it's kind of a precedent of using fanotify to aid an lsm

2. See this fan_pre_modify-wip branch [1] and specifically commit
  "fanotify: introduce directory entry pre-modify permission events"
I do have an intention to add create/delete/rename permission events.
Note that the new fsnotify hooks are added in to do_ vfs helpers, not very
far from the security_path_ lsm hooks, but not exactly in the same place
because we want to fsnotify hooks to be before taking vfs locks, to allow
listener to write to filesystem from event context.
There are different semantics than just ALLOW/DENY that you need,
therefore, only if we move the security_path_ hooks outside the
vfs locks, our use cases could use the same hooks

3. There is a recent attempt to add BPF filter to fanotify [2]
which is driven among other things from the long standing requirement
to add subtree filtering to fanotify watches.
The challenge with all the attempt to implement a subtree filter so far,
is that adding vfs performance overhead for all the users in the system
is unacceptable.

IIUC, landlock rule set can already express a subtree filter (?),
so it is intriguing to know if there is room for some integration on this
aspect, but my guess is that landlock mostly uses subtree filter
after filtering by specific pids (?), so it can avoid the performance
overhead of a subtree filter on most of the users in the system.

Hope this information is useful.

Thanks,
Amir.

[1] https://github.com/amir73il/linux/commits/fan_pre_modify-wip/
[2] https://lore.kernel.org/linux-fsdevel/20241122225958.1775625-1-song@kernel.org/