[RFC PATCH v1 0/3] Use socket's Landlock domain

Günther Noack gnoack at google.com
Tue Jul 23 13:07:53 UTC 2024


Hello Mickaël!

On Fri, Jul 19, 2024 at 05:06:15PM +0200, Mickaël Salaün wrote:
> While the current approach works, I think we should change the way
> Landlock restricts network actions.  Because this feature is relatively
> new, we can still fix this inconsistency.  In a nutshell, let's follow a
> more capability-based model.  Please let me know what you think.

Thanks for sending the patch.  The implementation with ->f_cred is much simpler
than I had thought it would be.  Some higher level questions:

 * I assume that the plan is to backport this as a fix to older kernels that
   already have the feature?  (Otherwise, we would potentially have backwards
   compatibility issues.)

 * I believe it clashes a little bit with the TCP server example [1],
   which I found a useful use case for the TCP connect/bind and socket
   restriction features.

 * accept(2) on a passive (listen-mode) socket will give you a new socket FD
   -- does that new socket inherit its f_cred from the server socket,
   or does it inherit its f_cred from the thread?

Regarding the TCP server example, the current implementation is *very* simple,
and does the following steps:

 1. create socket with socket(2)
 2. bind(2) the socket to the desired port
 3. enforce a Landlock ruleset that disables all networking features
    (TCP bind, TCP connect and socket creation with the new patch set)
 4. listen(2) on the socket
 5. go into the accept(2) loop

With the old behaviour, step 3 is going to affect the existing passive socket:
It will not be possible any more to bind(2) that passive socket to another port.

With the new behaviour (after your patch), step 3 does *not* affect the existing
socket, and the server socket can be reused to bind(2) to other ports.

Or, in other words: If the relevant domain is tied to the socket at creation
time, that means that a future client connection which takes over the process
might be able to use that socket's Landlock domain, which potentially grants
more permissions than the thread's domain

I think it would be nice if a use case like in the TCP server example would
still be possible with Landlock; there are multiple ways to reach that:

 - We could enforce two layers of Landlock rules, one before socket creation
   that restricts bind(2) to a given port, and one after socket creation that
   restricts other bind(2), create(2) and socket(2) operations.

   Drawbacks:

   - One Landlock layer more, and needs to add a Landlock rule:
     This is a bit more complicated to implement.
   - The bind(2) restriction on the socket is still only per port *number*,
     but it is still possible to bind with that port number on different IP
     addresses.

 - Alternatively, I wish we could just lock the passive server socket in, so
   that it can't be made to reconnect anywhere else.  After all, the socket
   disassociation with connect(2) with AF_UNSPEC seems to be a somewhat obscure
   and seldomly used feature - if we could just disallow that operation, we
   could ensure that this socket gets reused for such a nefarious purpose.

   It would still require two nested Landlock rulesets to make the TCP server
   example work, but they would be a bit simpler than in the alternative above.

 - There are probably more alternatives...?

What do you think?

—Günther

[1] https://wiki.gnoack.org/LandlockTcpServerExample



More information about the Linux-security-module-archive mailing list