[PATCH v8 1/4] Landlock: Add abstract unix socket connect restriction
Jann Horn
jannh at google.com
Tue Aug 6 20:46:43 UTC 2024
On Tue, Aug 6, 2024 at 9:36 PM Mickaël Salaün <mic at digikod.net> wrote:
> On Sat, Aug 03, 2024 at 01:29:09PM +0200, Mickaël Salaün wrote:
> > On Thu, Aug 01, 2024 at 10:02:33PM -0600, Tahera Fahimi wrote:
> > > This patch introduces a new "scoped" attribute to the landlock_ruleset_attr
> > > that can specify "LANDLOCK_SCOPED_ABSTRACT_UNIX_SOCKET" to scope
> > > abstract Unix sockets from connecting to a process outside of
> > > the same landlock domain. It implements two hooks, unix_stream_connect
> > > and unix_may_send to enforce this restriction.
[...]
> Here is a refactoring that is easier to read and avoid potential pointer
> misuse:
>
> static bool domain_is_scoped(const struct landlock_ruleset *const client,
> const struct landlock_ruleset *const server,
> access_mask_t scope)
> {
> int client_layer, server_layer;
> struct landlock_hierarchy *client_walker, *server_walker;
>
> if (WARN_ON_ONCE(!client))
> return false;
>
> client_layer = client->num_layers - 1;
> client_walker = client->hierarchy;
>
> /*
> * client_layer must be a signed integer with greater capacity than
> * client->num_layers to ensure the following loop stops.
> */
> BUILD_BUG_ON(sizeof(client_layer) > sizeof(client->num_layers));
>
> if (!server) {
> /*
> * Walks client's parent domains and checks that none of these
> * domains are scoped.
> */
> for (; client_layer >= 0; client_layer--) {
> if (landlock_get_scope_mask(client, client_layer) &
> scope)
> return true;
> }
> return false;
> }
>
> server_layer = server->num_layers - 1;
> server_walker = server->hierarchy;
>
> /*
> * Walks client's parent domains down to the same hierarchy level as
> * the server's domain, and checks that none of these client's parent
> * domains are scoped.
> */
> for (; client_layer > server_layer; client_layer--) {
> if (landlock_get_scope_mask(client, client_layer) & scope)
> return true;
>
> client_walker = client_walker->parent;
> }
>
> /*
> * Walks server's parent domains down to the same hierarchy level as
> * the client's domain.
> */
> for (; server_layer > client_layer; server_layer--)
> server_walker = server_walker->parent;
>
> for (; client_layer >= 0; client_layer--) {
> if (landlock_get_scope_mask(client, client_layer) & scope) {
> /*
> * Client and server are at the same level in the
> * hierarchy. If the client is scoped, the request is
> * only allowed if this domain is also a server's
> * ancestor.
> */
> if (server_walker == client_walker)
> return false;
>
> return true;
> }
> client_walker = client_walker->parent;
> server_walker = server_walker->parent;
> }
> return false;
> }
I think adding something like this change on top of your code would
make it more concise (though this is entirely untested):
--- /tmp/a 2024-08-06 22:37:33.800158308 +0200
+++ /tmp/b 2024-08-06 22:44:49.539314039 +0200
@@ -15,25 +15,12 @@
* client_layer must be a signed integer with greater capacity than
* client->num_layers to ensure the following loop stops.
*/
BUILD_BUG_ON(sizeof(client_layer) > sizeof(client->num_layers));
- if (!server) {
- /*
- * Walks client's parent domains and checks that none of these
- * domains are scoped.
- */
- for (; client_layer >= 0; client_layer--) {
- if (landlock_get_scope_mask(client, client_layer) &
- scope)
- return true;
- }
- return false;
- }
-
- server_layer = server->num_layers - 1;
- server_walker = server->hierarchy;
+ server_layer = server ? (server->num_layers - 1) : -1;
+ server_walker = server ? server->hierarchy : NULL;
/*
* Walks client's parent domains down to the same hierarchy level as
* the server's domain, and checks that none of these client's parent
* domains are scoped.
More information about the Linux-security-module-archive
mailing list