From patchwork Wed Sep 4 10:48:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790471 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 552C91482E1; Wed, 4 Sep 2024 10:48:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446921; cv=none; b=CDSvvP2QWZyG0epgLRiKE2bh8TLbHyLPYVzGIeJbvo7PfJErUihFw4JO73fsGfkNgY4nuQpm2X/Hz7LwkIWjzPAQjiuJ75ril/n90QkpRSJy/asyByxjEr8Nc3WLec8RfbySf+4lq+dFkgUyDeTh0wcT7pQqoDpprJKgwvvDf6A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446921; c=relaxed/simple; bh=rhlMClKnmpAjwb7mSFb3Qgkk0e87bohGlxYhJyen6UI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Yx9LGs5wsVLfdSf+vjpOW5tyq+NfmvKYTigRC4AGqzC+mRvmxINElLdYKTINogIctd9y7dVQbs8TvZA0/TqQ/MgVHFPBOAobjIb8qFSljfiZy4Yw/Y+8UIDpLHM3sHScnPEsNDGo63jnZ4RgCtJJ9l56gM2WjYWi0NTZC+Xw0uA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.163.48]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4WzK2j5Fw8zyRR9; Wed, 4 Sep 2024 18:47:57 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id B9D4C18005F; Wed, 4 Sep 2024 18:48:35 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:33 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 01/19] landlock: Support socket access-control Date: Wed, 4 Sep 2024 18:48:06 +0800 Message-ID: <20240904104824.1844082-2-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Landlock implements the `LANDLOCK_RULE_NET_PORT` rule type, which provides fine-grained control of actions for a specific protocol. Any action or protocol that is not supported by this rule can not be controlled. As a result, protocols for which fine-grained control is not supported can be used in a sandboxed system and lead to vulnerabilities or unexpected behavior. Controlling the protocols used will allow to use only those that are necessary for the system and/or which have fine-grained Landlock control through others types of rules (e.g. TCP bind/connect control with `LANDLOCK_RULE_NET_PORT`, UNIX bind control with `LANDLOCK_RULE_PATH_BENEATH`). Consider following examples: * Server may want to use only TCP sockets for which there is fine-grained control of bind(2) and connect(2) actions [1]. * System that does not need a network or that may want to disable network for security reasons (e.g. [2]) can achieve this by restricting the use of all possible protocols. This patch implements such control by restricting socket creation in a sandboxed process. Add `LANDLOCK_RULE_SOCKET` rule type that restricts actions on sockets. This rule uses values of address family and socket type (Cf. socket(2)) to determine sockets that should be restricted. This is represented in a landlock_socket_attr struct: struct landlock_socket_attr { __u64 allowed_access; int family; /* same as domain in socket(2) */ int type; /* see socket(2) */ }; Support socket rule storage in landlock ruleset. Add `LANDLOCK_ACCESS_SOCKET_CREATE` access right that corresponds to the creation of user space sockets. In the case of connection-based socket types, this does not restrict the actions that result in creation of sockets used for messaging between already existing endpoints (e.g. accept(2), SCTP_SOCKOPT_PEELOFF). Also, this does not restrict any other socket-related actions such as bind(2) or send(2). All restricted actions are enlisted in the documentation of this access right. As with all other access rights, using `LANDLOCK_ACCESS_SOCKET_CREATE` does not affect the actions on sockets which were created before sandboxing. Add socket.c file that will contain socket rules management and hooks. Implement helper pack_socket_key() to convert 32-bit family and type alues into uintptr_t. This is possible due to the fact that these values are limited to AF_MAX (=46), SOCK_MAX (=11) constants. Assumption is checked in build-time by the helper. Support socket rules in landlock syscalls. Change ABI version to 6. [1] https://lore.kernel.org/all/ZJvy2SViorgc+cZI@google.com/ [2] https://cr.yp.to/unix/disablenetwork.html Closes: https://github.com/landlock-lsm/linux/issues/6 Signed-off-by: Mikhail Ivanov --- Changes since v2: * Refactors access_mask for `LANDLOCK_RULE_SOCKET`. * Changes type of 'socket_key.packed' from 'uintptr_t' to 'unsigned int' in order to fix UB in pack_socket_key(). * Accepts (AF_INET, SOCK_PACKET) as an alias for (AF_PACKET, SOCK_PACKET) in landlock_append_socket_rule(). * Fixes documentation. * Rewrites commit message. * Fixes grammar. * Minor fixes. Changes since v1: * Reverts landlock_key.data type from u64 to uinptr_t. * Adds helper to pack domain and type values into uintptr_t. * Denies inserting socket rule with invalid family and type. * Renames 'domain' to 'family' in landlock_socket_attr. * Updates ABI version to 6 since ioctl patches changed it to 5. * Formats code with clang-format. * Minor fixes. --- include/uapi/linux/landlock.h | 61 ++++++++++++++++- security/landlock/Makefile | 2 +- security/landlock/limits.h | 4 ++ security/landlock/ruleset.c | 33 +++++++++- security/landlock/ruleset.h | 45 ++++++++++++- security/landlock/socket.c | 69 ++++++++++++++++++++ security/landlock/socket.h | 17 +++++ security/landlock/syscalls.c | 66 +++++++++++++++++-- tools/testing/selftests/landlock/base_test.c | 2 +- 9 files changed, 287 insertions(+), 12 deletions(-) create mode 100644 security/landlock/socket.c create mode 100644 security/landlock/socket.h diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index 2c8dbc74b955..d9da9f2c0640 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -44,6 +44,13 @@ struct landlock_ruleset_attr { * flags`_). */ __u64 handled_access_net; + + /** + * @handled_access_socket: Bitmask of actions (cf. `Socket flags`_) + * that is handled by this ruleset and should then be forbidden if no + * rule explicitly allow them. + */ + __u64 handled_access_socket; }; /* @@ -72,6 +79,11 @@ enum landlock_rule_type { * landlock_net_port_attr . */ LANDLOCK_RULE_NET_PORT, + /** + * @LANDLOCK_RULE_SOCKET: Type of a &struct + * landlock_socket_attr . + */ + LANDLOCK_RULE_SOCKET, }; /** @@ -123,6 +135,32 @@ struct landlock_net_port_attr { __u64 port; }; +/** + * struct landlock_socket_attr - Socket definition + * + * Argument of sys_landlock_add_rule(). + */ +struct landlock_socket_attr { + /** + * @allowed_access: Bitmask of allowed access for a socket + * (cf. `Socket flags`_). + */ + __u64 allowed_access; + /** + * @family: Protocol family used for communication + * (same as domain in socket(2)). + * + * This argument is considered valid if it is in the range [0, AF_MAX). + */ + int family; + /** + * @type: Socket type (see socket(2)). + * + * This argument is considered valid if it is in the range [0, SOCK_MAX). + */ + int type; +}; + /** * DOC: fs_access * @@ -259,7 +297,7 @@ struct landlock_net_port_attr { * DOC: net_access * * Network flags - * ~~~~~~~~~~~~~~~~ + * ~~~~~~~~~~~~~ * * These flags enable to restrict a sandboxed process to a set of network * actions. This is supported since the Landlock ABI version 4. @@ -274,4 +312,25 @@ struct landlock_net_port_attr { #define LANDLOCK_ACCESS_NET_BIND_TCP (1ULL << 0) #define LANDLOCK_ACCESS_NET_CONNECT_TCP (1ULL << 1) /* clang-format on */ + +/** + * DOC: socket_access + * + * Socket flags + * ~~~~~~~~~~~~ + * + * These flags restrict actions on sockets for a sandboxed process (e.g. socket + * creation). Sockets opened before sandboxing are not subject to these + * restrictions. This is supported since the Landlock ABI version 6. + * + * The following access right apply only to sockets: + * + * - %LANDLOCK_ACCESS_SOCKET_CREATE: Create an user space socket. This access + * right restricts following operations: + * * :manpage:`socket(2)`, :manpage:`socketpair(2)`, + * * ``IORING_OP_SOCKET`` io_uring operation (see :manpage:`io_uring_enter(2)`), + */ +/* clang-format off */ +#define LANDLOCK_ACCESS_SOCKET_CREATE (1ULL << 0) +/* clang-format on */ #endif /* _UAPI_LINUX_LANDLOCK_H */ diff --git a/security/landlock/Makefile b/security/landlock/Makefile index b4538b7cf7d2..ff1dd98f6a1b 100644 --- a/security/landlock/Makefile +++ b/security/landlock/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o landlock-y := setup.o syscalls.o object.o ruleset.o \ - cred.o task.o fs.o + cred.o task.o fs.o socket.o landlock-$(CONFIG_INET) += net.o diff --git a/security/landlock/limits.h b/security/landlock/limits.h index 4eb643077a2a..2c04dca414c7 100644 --- a/security/landlock/limits.h +++ b/security/landlock/limits.h @@ -26,6 +26,10 @@ #define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1) #define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET) +#define LANDLOCK_LAST_ACCESS_SOCKET LANDLOCK_ACCESS_SOCKET_CREATE +#define LANDLOCK_MASK_ACCESS_SOCKET ((LANDLOCK_LAST_ACCESS_SOCKET << 1) - 1) +#define LANDLOCK_NUM_ACCESS_SOCKET __const_hweight64(LANDLOCK_MASK_ACCESS_SOCKET) + /* clang-format on */ #endif /* _SECURITY_LANDLOCK_LIMITS_H */ diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c index 6ff232f58618..9bf5e5e88544 100644 --- a/security/landlock/ruleset.c +++ b/security/landlock/ruleset.c @@ -40,6 +40,7 @@ static struct landlock_ruleset *create_ruleset(const u32 num_layers) #if IS_ENABLED(CONFIG_INET) new_ruleset->root_net_port = RB_ROOT; #endif /* IS_ENABLED(CONFIG_INET) */ + new_ruleset->root_socket = RB_ROOT; new_ruleset->num_layers = num_layers; /* @@ -52,12 +53,13 @@ static struct landlock_ruleset *create_ruleset(const u32 num_layers) struct landlock_ruleset * landlock_create_ruleset(const access_mask_t fs_access_mask, - const access_mask_t net_access_mask) + const access_mask_t net_access_mask, + const access_mask_t socket_access_mask) { struct landlock_ruleset *new_ruleset; /* Informs about useless ruleset. */ - if (!fs_access_mask && !net_access_mask) + if (!fs_access_mask && !net_access_mask && !socket_access_mask) return ERR_PTR(-ENOMSG); new_ruleset = create_ruleset(1); if (IS_ERR(new_ruleset)) @@ -66,6 +68,9 @@ landlock_create_ruleset(const access_mask_t fs_access_mask, landlock_add_fs_access_mask(new_ruleset, fs_access_mask, 0); if (net_access_mask) landlock_add_net_access_mask(new_ruleset, net_access_mask, 0); + if (socket_access_mask) + landlock_add_socket_access_mask(new_ruleset, socket_access_mask, + 0); return new_ruleset; } @@ -89,6 +94,9 @@ static bool is_object_pointer(const enum landlock_key_type key_type) return false; #endif /* IS_ENABLED(CONFIG_INET) */ + case LANDLOCK_KEY_SOCKET: + return false; + default: WARN_ON_ONCE(1); return false; @@ -146,6 +154,9 @@ static struct rb_root *get_root(struct landlock_ruleset *const ruleset, return &ruleset->root_net_port; #endif /* IS_ENABLED(CONFIG_INET) */ + case LANDLOCK_KEY_SOCKET: + return &ruleset->root_socket; + default: WARN_ON_ONCE(1); return ERR_PTR(-EINVAL); @@ -395,6 +406,11 @@ static int merge_ruleset(struct landlock_ruleset *const dst, goto out_unlock; #endif /* IS_ENABLED(CONFIG_INET) */ + /* Merges the @src socket tree. */ + err = merge_tree(dst, src, LANDLOCK_KEY_SOCKET); + if (err) + goto out_unlock; + out_unlock: mutex_unlock(&src->lock); mutex_unlock(&dst->lock); @@ -458,6 +474,11 @@ static int inherit_ruleset(struct landlock_ruleset *const parent, goto out_unlock; #endif /* IS_ENABLED(CONFIG_INET) */ + /* Copies the @parent socket tree. */ + err = inherit_tree(parent, child, LANDLOCK_KEY_SOCKET); + if (err) + goto out_unlock; + if (WARN_ON_ONCE(child->num_layers <= parent->num_layers)) { err = -EINVAL; goto out_unlock; @@ -494,6 +515,10 @@ static void free_ruleset(struct landlock_ruleset *const ruleset) free_rule(freeme, LANDLOCK_KEY_NET_PORT); #endif /* IS_ENABLED(CONFIG_INET) */ + rbtree_postorder_for_each_entry_safe(freeme, next, + &ruleset->root_socket, node) + free_rule(freeme, LANDLOCK_KEY_SOCKET); + put_hierarchy(ruleset->hierarchy); kfree(ruleset); } @@ -704,6 +729,10 @@ landlock_init_layer_masks(const struct landlock_ruleset *const domain, break; #endif /* IS_ENABLED(CONFIG_INET) */ + case LANDLOCK_KEY_SOCKET: + get_access_mask = landlock_get_socket_access_mask; + num_access = LANDLOCK_NUM_ACCESS_SOCKET; + break; default: WARN_ON_ONCE(1); return 0; diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h index 0f1b5b4c8f6b..5cf7251e11ca 100644 --- a/security/landlock/ruleset.h +++ b/security/landlock/ruleset.h @@ -42,6 +42,7 @@ static_assert(sizeof(unsigned long) >= sizeof(access_mask_t)); struct access_masks { access_mask_t fs : LANDLOCK_NUM_ACCESS_FS; access_mask_t net : LANDLOCK_NUM_ACCESS_NET; + access_mask_t socket : LANDLOCK_NUM_ACCESS_SOCKET; }; typedef u16 layer_mask_t; @@ -92,6 +93,12 @@ enum landlock_key_type { * node keys. */ LANDLOCK_KEY_NET_PORT, + + /** + * @LANDLOCK_KEY_SOCKET: Type of &landlock_ruleset.root_socket's + * node keys. + */ + LANDLOCK_KEY_SOCKET, }; /** @@ -177,6 +184,15 @@ struct landlock_ruleset { struct rb_root root_net_port; #endif /* IS_ENABLED(CONFIG_INET) */ + /** + * @root_socket: Root of a red-black tree containing &struct + * landlock_rule nodes with socket type, described by (family, type) + * pair (see socket(2)). Once a ruleset is tied to a + * process (i.e. as a domain), this tree is immutable until @usage + * reaches zero. + */ + struct rb_root root_socket; + /** * @hierarchy: Enables hierarchy identification even when a parent * domain vanishes. This is needed for the ptrace protection. @@ -215,8 +231,10 @@ struct landlock_ruleset { */ u32 num_layers; /** - * @access_masks: Contains the subset of filesystem and - * network actions that are restricted by a ruleset. + * @access_masks: Contains the subset of filesystem, + * network and socket actions that are restricted by + * a ruleset. + * * A domain saves all layers of merged rulesets in a * stack (FAM), starting from the first layer to the * last one. These layers are used when merging @@ -233,7 +251,8 @@ struct landlock_ruleset { struct landlock_ruleset * landlock_create_ruleset(const access_mask_t access_mask_fs, - const access_mask_t access_mask_net); + const access_mask_t access_mask_net, + const access_mask_t access_mask_socket); void landlock_put_ruleset(struct landlock_ruleset *const ruleset); void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset); @@ -280,6 +299,19 @@ landlock_add_net_access_mask(struct landlock_ruleset *const ruleset, ruleset->access_masks[layer_level].net |= net_mask; } +static inline void +landlock_add_socket_access_mask(struct landlock_ruleset *const ruleset, + const access_mask_t socket_access_mask, + const u16 layer_level) +{ + access_mask_t socket_mask = socket_access_mask & + LANDLOCK_MASK_ACCESS_SOCKET; + + /* Should already be checked in sys_landlock_create_ruleset(). */ + WARN_ON_ONCE(socket_access_mask != socket_mask); + ruleset->access_masks[layer_level].socket |= socket_mask; +} + static inline access_mask_t landlock_get_raw_fs_access_mask(const struct landlock_ruleset *const ruleset, const u16 layer_level) @@ -303,6 +335,13 @@ landlock_get_net_access_mask(const struct landlock_ruleset *const ruleset, return ruleset->access_masks[layer_level].net; } +static inline access_mask_t +landlock_get_socket_access_mask(const struct landlock_ruleset *const ruleset, + const u16 layer_level) +{ + return ruleset->access_masks[layer_level].socket; +} + bool landlock_unmask_layers(const struct landlock_rule *const rule, const access_mask_t access_request, layer_mask_t (*const layer_masks)[], diff --git a/security/landlock/socket.c b/security/landlock/socket.c new file mode 100644 index 000000000000..cad89bb91678 --- /dev/null +++ b/security/landlock/socket.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Landlock LSM - Socket management and hooks + * + * Copyright © 2024 Huawei Tech. Co., Ltd. + */ + +#include +#include +#include + +#include "limits.h" +#include "ruleset.h" +#include "socket.h" + +static uintptr_t pack_socket_key(const int family, const int type) +{ + union { + struct { + unsigned short family, type; + } __packed data; + unsigned int packed; + } socket_key; + + /* + * Checks that all supported socket families and types can be stored + * in socket_key. + */ + BUILD_BUG_ON(AF_MAX >= (typeof(socket_key.data.family))~0); + BUILD_BUG_ON(SOCK_MAX >= (typeof(socket_key.data.type))~0); + + /* Checks that socket_key can be stored in landlock_key. */ + BUILD_BUG_ON(sizeof(socket_key.data) > sizeof(socket_key.packed)); + BUILD_BUG_ON(sizeof(socket_key.packed) > + sizeof_field(union landlock_key, data)); + + socket_key.data.family = (unsigned short)family; + socket_key.data.type = (unsigned short)type; + + return socket_key.packed; +} + +int landlock_append_socket_rule(struct landlock_ruleset *const ruleset, + int family, int type, + access_mask_t access_rights) +{ + int err; + /* + * (AF_INET, SOCK_PACKET) is an alias for (AF_PACKET, SOCK_PACKET) + * (Cf. __sock_create). + */ + if (family == AF_INET && type == SOCK_PACKET) + family = AF_PACKET; + + const struct landlock_id id = { + .key.data = pack_socket_key(family, type), + .type = LANDLOCK_KEY_SOCKET, + }; + + /* Transforms relative access rights to absolute ones. */ + access_rights |= LANDLOCK_MASK_ACCESS_SOCKET & + ~landlock_get_socket_access_mask(ruleset, 0); + + mutex_lock(&ruleset->lock); + err = landlock_insert_rule(ruleset, id, access_rights); + mutex_unlock(&ruleset->lock); + + return err; +} diff --git a/security/landlock/socket.h b/security/landlock/socket.h new file mode 100644 index 000000000000..8519357f1c39 --- /dev/null +++ b/security/landlock/socket.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Landlock LSM - Socket management and hooks + * + * Copyright © 2024 Huawei Tech. Co., Ltd. + */ + +#ifndef _SECURITY_LANDLOCK_SOCKET_H +#define _SECURITY_LANDLOCK_SOCKET_H + +#include "ruleset.h" + +int landlock_append_socket_rule(struct landlock_ruleset *const ruleset, + const int family, const int type, + access_mask_t access_rights); + +#endif /* _SECURITY_LANDLOCK_SOCKET_H */ diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index ccc8bc6c1584..026033e4ecb6 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -24,12 +24,14 @@ #include #include #include +#include #include #include "cred.h" #include "fs.h" #include "limits.h" #include "net.h" +#include "socket.h" #include "ruleset.h" #include "setup.h" @@ -88,7 +90,8 @@ static void build_check_abi(void) struct landlock_ruleset_attr ruleset_attr; struct landlock_path_beneath_attr path_beneath_attr; struct landlock_net_port_attr net_port_attr; - size_t ruleset_size, path_beneath_size, net_port_size; + struct landlock_socket_attr socket_attr; + size_t ruleset_size, path_beneath_size, net_port_size, socket_size; /* * For each user space ABI structures, first checks that there is no @@ -97,8 +100,9 @@ static void build_check_abi(void) */ ruleset_size = sizeof(ruleset_attr.handled_access_fs); ruleset_size += sizeof(ruleset_attr.handled_access_net); + ruleset_size += sizeof(ruleset_attr.handled_access_socket); BUILD_BUG_ON(sizeof(ruleset_attr) != ruleset_size); - BUILD_BUG_ON(sizeof(ruleset_attr) != 16); + BUILD_BUG_ON(sizeof(ruleset_attr) != 24); path_beneath_size = sizeof(path_beneath_attr.allowed_access); path_beneath_size += sizeof(path_beneath_attr.parent_fd); @@ -109,6 +113,12 @@ static void build_check_abi(void) net_port_size += sizeof(net_port_attr.port); BUILD_BUG_ON(sizeof(net_port_attr) != net_port_size); BUILD_BUG_ON(sizeof(net_port_attr) != 16); + + socket_size = sizeof(socket_attr.allowed_access); + socket_size += sizeof(socket_attr.family); + socket_size += sizeof(socket_attr.type); + BUILD_BUG_ON(sizeof(socket_attr) != socket_size); + BUILD_BUG_ON(sizeof(socket_attr) != 16); } /* Ruleset handling */ @@ -149,7 +159,7 @@ static const struct file_operations ruleset_fops = { .write = fop_dummy_write, }; -#define LANDLOCK_ABI_VERSION 5 +#define LANDLOCK_ABI_VERSION 6 /** * sys_landlock_create_ruleset - Create a new ruleset @@ -213,9 +223,15 @@ SYSCALL_DEFINE3(landlock_create_ruleset, LANDLOCK_MASK_ACCESS_NET) return -EINVAL; + /* Checks socket content (and 32-bits cast). */ + if ((ruleset_attr.handled_access_socket | + LANDLOCK_MASK_ACCESS_SOCKET) != LANDLOCK_MASK_ACCESS_SOCKET) + return -EINVAL; + /* Checks arguments and transforms to kernel struct. */ ruleset = landlock_create_ruleset(ruleset_attr.handled_access_fs, - ruleset_attr.handled_access_net); + ruleset_attr.handled_access_net, + ruleset_attr.handled_access_socket); if (IS_ERR(ruleset)) return PTR_ERR(ruleset); @@ -371,6 +387,45 @@ static int add_rule_net_port(struct landlock_ruleset *ruleset, net_port_attr.allowed_access); } +static int add_rule_socket(struct landlock_ruleset *ruleset, + const void __user *const rule_attr) +{ + struct landlock_socket_attr socket_attr; + int family, type; + int res; + access_mask_t mask; + + /* Copies raw user space buffer. */ + res = copy_from_user(&socket_attr, rule_attr, sizeof(socket_attr)); + if (res) + return -EFAULT; + + /* + * Informs about useless rule: empty allowed_access (i.e. deny rules) + * are ignored by socket actions. + */ + if (!socket_attr.allowed_access) + return -ENOMSG; + + /* Checks that allowed_access matches the @ruleset constraints. */ + mask = landlock_get_socket_access_mask(ruleset, 0); + if ((socket_attr.allowed_access | mask) != mask) + return -EINVAL; + + family = socket_attr.family; + type = socket_attr.type; + + /* Denies inserting a rule with family and type outside the range. */ + if (family < 0 || family >= AF_MAX) + return -EINVAL; + if (type < 0 || type >= SOCK_MAX) + return -EINVAL; + + /* Imports the new rule. */ + return landlock_append_socket_rule(ruleset, family, type, + socket_attr.allowed_access); +} + /** * sys_landlock_add_rule - Add a new rule to a ruleset * @@ -430,6 +485,9 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd, case LANDLOCK_RULE_NET_PORT: err = add_rule_net_port(ruleset, rule_attr); break; + case LANDLOCK_RULE_SOCKET: + err = add_rule_socket(ruleset, rule_attr); + break; default: err = -EINVAL; break; diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c index 3b26bf3cf5b9..1bc16fde2e8a 100644 --- a/tools/testing/selftests/landlock/base_test.c +++ b/tools/testing/selftests/landlock/base_test.c @@ -76,7 +76,7 @@ TEST(abi_version) const struct landlock_ruleset_attr ruleset_attr = { .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE, }; - ASSERT_EQ(5, landlock_create_ruleset(NULL, 0, + ASSERT_EQ(6, landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION)); ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, From patchwork Wed Sep 4 10:48:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790472 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12C9517BECC; Wed, 4 Sep 2024 10:48:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446923; cv=none; b=EDadu0Q6b4srU1tSMUN1/iNueMlqVvl8ab9rNG8CW7P/PQF9iUj//Br/9eUTFgBQj/B/PN1GaJgLcJISUzILYoLkqjmLOaGMKLWfqzTLGBgvoIIuDIArDQF17cnepKutz7WfLZrxJu2PxJRkLsLeqQkjs4Knedi5XQFV8YnTLrk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446923; c=relaxed/simple; bh=9cgw1uMixmrGnP5Q7HvLQkDkkHx6GoAcxELiQiyBbHQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JjaVztLAJg+/u0UuyiE/tpiD5340q6mkdPooM+kPxhsMRs96eg/E0qxmKY2ZGJyQtyDaoazQ5pkXoY1dSt7NBlTtv+naBYsAndgIaO16eu6l2irQg9lb4uCPqQwjHOLwMhiAP7KcCNwwap9YP2Pu7bDD128hXUwAiTPd0ht5mDE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.163]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4WzK352N5xz1j839; Wed, 4 Sep 2024 18:48:17 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 7878A180042; Wed, 4 Sep 2024 18:48:37 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:35 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 02/19] landlock: Add hook on socket creation Date: Wed, 4 Sep 2024 18:48:07 +0800 Message-ID: <20240904104824.1844082-3-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add hook on security_socket_post_create(), which checks whether the socket type and address family are allowed by domain. Hook is called after initializing the socket to let network stack to perform all necessary internal checks. Signed-off-by: Mikhail Ivanov --- Changes since v2: * Adds check in `hook_socket_create()` to not restrict kernel space sockets. * Inlines `current_check_access_socket()` in the `hook_socket_create()`. * Fixes commit message. Changes since v1: * Uses lsm hook arguments instead of struct socket fields as family-type values. * Packs socket family and type using helper. * Fixes commit message. * Formats with clang-format. --- security/landlock/setup.c | 2 ++ security/landlock/socket.c | 68 ++++++++++++++++++++++++++++++++++++++ security/landlock/socket.h | 2 ++ 3 files changed, 72 insertions(+) diff --git a/security/landlock/setup.c b/security/landlock/setup.c index 28519a45b11f..fd4e7e8f3cb2 100644 --- a/security/landlock/setup.c +++ b/security/landlock/setup.c @@ -14,6 +14,7 @@ #include "cred.h" #include "fs.h" #include "net.h" +#include "socket.h" #include "setup.h" #include "task.h" @@ -37,6 +38,7 @@ static int __init landlock_init(void) landlock_add_task_hooks(); landlock_add_fs_hooks(); landlock_add_net_hooks(); + landlock_add_socket_hooks(); landlock_initialized = true; pr_info("Up and running.\n"); return 0; diff --git a/security/landlock/socket.c b/security/landlock/socket.c index cad89bb91678..60dbcf38540e 100644 --- a/security/landlock/socket.c +++ b/security/landlock/socket.c @@ -8,7 +8,9 @@ #include #include #include +#include +#include "cred.h" #include "limits.h" #include "ruleset.h" #include "socket.h" @@ -67,3 +69,69 @@ int landlock_append_socket_rule(struct landlock_ruleset *const ruleset, return err; } + +static access_mask_t +get_raw_handled_socket_accesses(const struct landlock_ruleset *const domain) +{ + access_mask_t access_dom = 0; + size_t layer_level; + + for (layer_level = 0; layer_level < domain->num_layers; layer_level++) + access_dom |= + landlock_get_socket_access_mask(domain, layer_level); + return access_dom; +} + +static const struct landlock_ruleset *get_current_socket_domain(void) +{ + const struct landlock_ruleset *const dom = + landlock_get_current_domain(); + + if (!dom || !get_raw_handled_socket_accesses(dom)) + return NULL; + + return dom; +} + +static int hook_socket_create(struct socket *const sock, int family, int type, + int protocol, int kern) +{ + layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_SOCKET] = {}; + const struct landlock_rule *rule; + access_mask_t handled_access; + struct landlock_id id = { + .type = LANDLOCK_KEY_SOCKET, + }; + const struct landlock_ruleset *dom; + + /* Checks only user space sockets. */ + if (kern) + return 0; + + dom = get_current_socket_domain(); + if (!dom) + return 0; + if (WARN_ON_ONCE(dom->num_layers < 1)) + return -EACCES; + + id.key.data = pack_socket_key(family, type); + + rule = landlock_find_rule(dom, id); + handled_access = + landlock_init_layer_masks(dom, LANDLOCK_ACCESS_SOCKET_CREATE, + &layer_masks, LANDLOCK_KEY_SOCKET); + if (landlock_unmask_layers(rule, handled_access, &layer_masks, + ARRAY_SIZE(layer_masks))) + return 0; + return -EACCES; +} + +static struct security_hook_list landlock_hooks[] __ro_after_init = { + LSM_HOOK_INIT(socket_post_create, hook_socket_create), +}; + +__init void landlock_add_socket_hooks(void) +{ + security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), + &landlock_lsmid); +} diff --git a/security/landlock/socket.h b/security/landlock/socket.h index 8519357f1c39..5c36eae9732f 100644 --- a/security/landlock/socket.h +++ b/security/landlock/socket.h @@ -10,6 +10,8 @@ #include "ruleset.h" +__init void landlock_add_socket_hooks(void); + int landlock_append_socket_rule(struct landlock_ruleset *const ruleset, const int family, const int type, access_mask_t access_rights); From patchwork Wed Sep 4 10:48:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790473 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B7051CF7AD; Wed, 4 Sep 2024 10:48:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446924; cv=none; b=U4qShXxxhYMete+GvVIrhLKg3KofjmY0nKP8E6Sk3XVf5p4Hp4mDy+Z7ko9cGE4fHiBJrHiE2QVtaQotB5sVT/FkPOlPsl08mTnq7iljhCVHulTfIBSOLsxFYAGObi+UUPDYmVZnvbLD9pp3ofbPAIt0SOhW6HYqWdrKLvAKCuM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446924; c=relaxed/simple; bh=xmSJBwy7F/nNdH3QFzvoVp49GKocm+0wpzPE0jnzqCM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QUBvNBUx0iRxPZ7rJ8Elb0GY6BA18wFP1FmROWNwa32vkNaCWDVGGXKfVAgonizAGgR9k6PdAeJdzQaZsgh6BW5U8qC25IP20qp2lzX/Jpmk6YbC+nbPcBQP5n3lJ0Es9TRpMP7Wip8bxdLub/iLCJ0ixbxBjSd3IgJtP4XmLrc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.162.112]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4WzJzW4k7Gz1HJ8t; Wed, 4 Sep 2024 18:45:11 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 22D691401E9; Wed, 4 Sep 2024 18:48:39 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:37 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 03/19] selftests/landlock: Test basic socket restriction Date: Wed, 4 Sep 2024 18:48:08 +0800 Message-ID: <20240904104824.1844082-4-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Initiate socket_test.c selftests. Add `protocol` fixture to test all possible family+type variants that can be used to create user space socket. Add all options required by this protocols in config. Support CAP_NET_RAW capability which is required by some protocols. Add simple socket access right checking test. Signed-off-by: Mikhail Ivanov Reviewed-by: Günther Noack --- Changes since v2: * Extends variants of `protocol` fixture with every socket protocol that can be used to create user space sockets. * Adds `SYS_ADMIN`, `NET_ADMIN` and `NET_RAW` capabilities required for some socket protocols. * Removes network namespace creation in `protocol` fixture setup. Sockets of some protocols can be created only in initial network namespace. This shouldn't cause any issues until `protocol` fixture is used in connection or binding tests. * Extends config file with a set of options required by socket protocols. * Adds CAP_NET_RAW capability to landlock selftests which is required to create sockets of some protocols. * Adds protocol field to the `protocol` fixture. * Adds test_socket_variant() helper and changes the signature of test_socket() helper. * Checks socket(2) when ruleset is not established. * Removes checks for AF_UNSPEC. This is moved to unsupported_af_and_prot test. * Removes `service_fixture` struct. * Minor fixes. * Refactors commit message and title. Changes since v1: * Replaces test_socket_create() and socket_variant() helpers with test_socket(). * Renames domain to family in protocol fixture. * Remove AF_UNSPEC fixture entry and add unspec_srv0 fixture field to check AF_UNSPEC socket creation case. * Formats code with clang-format. * Refactors commit message. --- tools/testing/selftests/landlock/common.h | 1 + tools/testing/selftests/landlock/config | 47 +++ .../testing/selftests/landlock/socket_test.c | 297 ++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 tools/testing/selftests/landlock/socket_test.c diff --git a/tools/testing/selftests/landlock/common.h b/tools/testing/selftests/landlock/common.h index 7e2b431b9f90..28df49fa22d5 100644 --- a/tools/testing/selftests/landlock/common.h +++ b/tools/testing/selftests/landlock/common.h @@ -66,6 +66,7 @@ static void _init_caps(struct __test_metadata *const _metadata, bool drop_all) CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, CAP_SYS_CHROOT, + CAP_NET_RAW, /* clang-format on */ }; const unsigned int noroot = SECBIT_NOROOT | SECBIT_NOROOT_LOCKED; diff --git a/tools/testing/selftests/landlock/config b/tools/testing/selftests/landlock/config index 29af19c4e9f9..0b8e906ca59b 100644 --- a/tools/testing/selftests/landlock/config +++ b/tools/testing/selftests/landlock/config @@ -13,3 +13,50 @@ CONFIG_SHMEM=y CONFIG_SYSFS=y CONFIG_TMPFS=y CONFIG_TMPFS_XATTR=y + +# +# Support of socket protocols for socket_test +# +CONFIG_AF_KCM=y +CONFIG_AF_RXRPC=y +CONFIG_ATALK=y +CONFIG_ATM=y +CONFIG_AX25=y +CONFIG_BPF_SYSCALL=y +CONFIG_BT=y +CONFIG_CAIF=y +CONFIG_CAN_BCM=y +CONFIG_CAN=y +CONFIG_CRYPTO_USER_API_AEAD=y +CONFIG_CRYPTO=y +CONFIG_HAMRADIO=y +CONFIG_IEEE802154_SOCKET=y +CONFIG_IEEE802154=y +CONFIG_INET=y +CONFIG_INFINIBAND=y +CONFIG_IP_SCTP=y +CONFIG_ISDN=y +CONFIG_LLC2=y +CONFIG_LLC=y +CONFIG_MCTP=y +CONFIG_MISDN=y +CONFIG_NETDEVICES=y +CONFIG_NET_KEY=y +CONFIG_NETROM=y +CONFIG_NFC=y +CONFIG_PACKET=y +CONFIG_PCI=y +CONFIG_PHONET=y +CONFIG_PPPOE=y +CONFIG_PPP=y +CONFIG_QRTR=y +CONFIG_RDS=y +CONFIG_ROSE=y +CONFIG_SMC=y +CONFIG_TIPC=y +CONFIG_UNIX=y +CONFIG_VMWARE_VMCI_VSOCKETS=y +CONFIG_VMWARE_VMCI=y +CONFIG_VSOCKETS=y +CONFIG_X25=y +CONFIG_XDP_SOCKETS=y \ No newline at end of file diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c new file mode 100644 index 000000000000..63bb269c9d07 --- /dev/null +++ b/tools/testing/selftests/landlock/socket_test.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Landlock tests - Socket + * + * Copyright © 2024 Huawei Tech. Co., Ltd. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +struct protocol_variant { + int family; + int type; + int protocol; +}; + +static int test_socket(int family, int type, int protocol) +{ + int fd; + + fd = socket(family, type | SOCK_CLOEXEC, protocol); + if (fd < 0) + return errno; + /* + * Mixing error codes from close(2) and socket(2) should not lead to any + * (access type) confusion for this test. + */ + if (close(fd) != 0) + return errno; + return 0; +} + +static int test_socket_variant(const struct protocol_variant *const prot) +{ + return test_socket(prot->family, prot->type, prot->protocol); +} + +FIXTURE(protocol) +{ + struct protocol_variant prot; +}; + +FIXTURE_VARIANT(protocol) +{ + const struct protocol_variant prot; +}; + +FIXTURE_SETUP(protocol) +{ + disable_caps(_metadata); + self->prot = variant->prot; + + /* + * Some address families require this caps to be set + * (e.g. AF_CAIF, AF_KEY). + */ + set_cap(_metadata, CAP_SYS_ADMIN); + set_cap(_metadata, CAP_NET_ADMIN); + set_cap(_metadata, CAP_NET_RAW); +}; + +FIXTURE_TEARDOWN(protocol) +{ + clear_cap(_metadata, CAP_SYS_ADMIN); + clear_cap(_metadata, CAP_NET_ADMIN); + clear_cap(_metadata, CAP_NET_RAW); +} + +#define PROTOCOL_VARIANT_EXT_ADD(family_, type_, protocol_) \ + FIXTURE_VARIANT_ADD(protocol, family_##_##type_) \ + { \ + .prot = { \ + .family = AF_##family_, \ + .type = SOCK_##type_, \ + .protocol = protocol_, \ + }, \ + } + +#define PROTOCOL_VARIANT_ADD(family, type) \ + PROTOCOL_VARIANT_EXT_ADD(family, type, 0) + +/* + * Every protocol that can be used to create socket using create() method + * of net_proto_family structure is tested (e.g. this method is used to + * create socket with socket(2)). + * + * List of address families that are not tested: + * - AF_ASH, AF_SNA, AF_WANPIPE, AF_NETBEUI, AF_IPX, AF_DECNET, AF_ECONET + * and AF_IRDA are not implemented in kernel. + * - AF_BRIDGE, AF_MPLS can't be used for creating sockets. + * - AF_SECURITY - pseudo AF (Cf. socket.h). + * - AF_IB is reserved by infiniband. + */ + +/* Cf. unix_create */ +PROTOCOL_VARIANT_ADD(UNIX, STREAM); +PROTOCOL_VARIANT_ADD(UNIX, RAW); +PROTOCOL_VARIANT_ADD(UNIX, DGRAM); +PROTOCOL_VARIANT_ADD(UNIX, SEQPACKET); + +/* Cf. inet_create */ +PROTOCOL_VARIANT_ADD(INET, STREAM); +PROTOCOL_VARIANT_ADD(INET, DGRAM); +PROTOCOL_VARIANT_EXT_ADD(INET, RAW, IPPROTO_TCP); +PROTOCOL_VARIANT_EXT_ADD(INET, SEQPACKET, IPPROTO_SCTP); + +/* Cf. ax25_create */ +PROTOCOL_VARIANT_ADD(AX25, DGRAM); +PROTOCOL_VARIANT_ADD(AX25, SEQPACKET); +PROTOCOL_VARIANT_ADD(AX25, RAW); + +/* Cf. atalk_create */ +PROTOCOL_VARIANT_ADD(APPLETALK, RAW); +PROTOCOL_VARIANT_ADD(APPLETALK, DGRAM); + +/* Cf. nr_create */ +PROTOCOL_VARIANT_ADD(NETROM, SEQPACKET); + +/* Cf. pvc_create */ +PROTOCOL_VARIANT_ADD(ATMPVC, DGRAM); +PROTOCOL_VARIANT_ADD(ATMPVC, RAW); +PROTOCOL_VARIANT_ADD(ATMPVC, RDM); +PROTOCOL_VARIANT_ADD(ATMPVC, SEQPACKET); +PROTOCOL_VARIANT_ADD(ATMPVC, DCCP); +PROTOCOL_VARIANT_ADD(ATMPVC, PACKET); + +/* Cf. x25_create */ +PROTOCOL_VARIANT_ADD(X25, SEQPACKET); + +/* Cf. inet6_create */ +PROTOCOL_VARIANT_ADD(INET6, STREAM); +PROTOCOL_VARIANT_ADD(INET6, DGRAM); +PROTOCOL_VARIANT_EXT_ADD(INET6, RAW, IPPROTO_TCP); + +/* Cf. rose_create */ +PROTOCOL_VARIANT_ADD(ROSE, SEQPACKET); + +/* Cf. pfkey_create */ +PROTOCOL_VARIANT_EXT_ADD(KEY, RAW, PF_KEY_V2); + +/* Cf. netlink_create */ +PROTOCOL_VARIANT_ADD(NETLINK, RAW); +PROTOCOL_VARIANT_ADD(NETLINK, DGRAM); + +/* Cf. packet_create */ +PROTOCOL_VARIANT_ADD(PACKET, DGRAM); +PROTOCOL_VARIANT_ADD(PACKET, RAW); +PROTOCOL_VARIANT_ADD(PACKET, PACKET); + +/* Cf. svc_create */ +PROTOCOL_VARIANT_ADD(ATMSVC, DGRAM); +PROTOCOL_VARIANT_ADD(ATMSVC, RAW); +PROTOCOL_VARIANT_ADD(ATMSVC, RDM); +PROTOCOL_VARIANT_ADD(ATMSVC, SEQPACKET); +PROTOCOL_VARIANT_ADD(ATMSVC, DCCP); +PROTOCOL_VARIANT_ADD(ATMSVC, PACKET); + +/* Cf. rds_create */ +PROTOCOL_VARIANT_ADD(RDS, SEQPACKET); + +/* Cf. pppox_create + pppoe_create */ +PROTOCOL_VARIANT_ADD(PPPOX, STREAM); +PROTOCOL_VARIANT_ADD(PPPOX, DGRAM); +PROTOCOL_VARIANT_ADD(PPPOX, RAW); +PROTOCOL_VARIANT_ADD(PPPOX, RDM); +PROTOCOL_VARIANT_ADD(PPPOX, SEQPACKET); +PROTOCOL_VARIANT_ADD(PPPOX, DCCP); +PROTOCOL_VARIANT_ADD(PPPOX, PACKET); + +/* Cf. llc_ui_create */ +PROTOCOL_VARIANT_ADD(LLC, DGRAM); +PROTOCOL_VARIANT_ADD(LLC, STREAM); + +/* Cf. can_create */ +PROTOCOL_VARIANT_EXT_ADD(CAN, DGRAM, CAN_BCM); + +/* Cf. tipc_sk_create */ +PROTOCOL_VARIANT_ADD(TIPC, STREAM); +PROTOCOL_VARIANT_ADD(TIPC, SEQPACKET); +PROTOCOL_VARIANT_ADD(TIPC, DGRAM); +PROTOCOL_VARIANT_ADD(TIPC, RDM); + +/* Cf. l2cap_sock_create */ +#ifndef __s390x__ +PROTOCOL_VARIANT_ADD(BLUETOOTH, SEQPACKET); +PROTOCOL_VARIANT_ADD(BLUETOOTH, STREAM); +PROTOCOL_VARIANT_ADD(BLUETOOTH, DGRAM); +PROTOCOL_VARIANT_ADD(BLUETOOTH, RAW); +#endif + +/* Cf. iucv_sock_create */ +#ifdef __s390x__ +PROTOCOL_VARIANT_ADD(IUCV, STREAM); +PROTOCOL_VARIANT_ADD(IUCV, SEQPACKET); +#endif + +/* Cf. rxrpc_create */ +PROTOCOL_VARIANT_EXT_ADD(RXRPC, DGRAM, PF_INET); + +/* Cf. mISDN_sock_create */ +#define ISDN_P_BASE 0 /* Cf. linux/mISDNif.h */ +#define ISDN_P_TE_S0 0x01 /* Cf. linux/mISDNif.h */ +PROTOCOL_VARIANT_EXT_ADD(ISDN, RAW, ISDN_P_BASE); +PROTOCOL_VARIANT_EXT_ADD(ISDN, DGRAM, ISDN_P_TE_S0); + +/* Cf. pn_socket_create */ +PROTOCOL_VARIANT_ADD(PHONET, DGRAM); +PROTOCOL_VARIANT_ADD(PHONET, SEQPACKET); + +/* Cf. ieee802154_create */ +PROTOCOL_VARIANT_ADD(IEEE802154, RAW); +PROTOCOL_VARIANT_ADD(IEEE802154, DGRAM); + +/* Cf. caif_create */ +PROTOCOL_VARIANT_ADD(CAIF, SEQPACKET); +PROTOCOL_VARIANT_ADD(CAIF, STREAM); + +/* Cf. alg_create */ +PROTOCOL_VARIANT_ADD(ALG, SEQPACKET); + +/* Cf. nfc_sock_create + rawsock_create */ +PROTOCOL_VARIANT_ADD(NFC, SEQPACKET); + +/* Cf. vsock_create */ +#if defined(__x86_64__) || defined(__aarch64__) +PROTOCOL_VARIANT_ADD(VSOCK, DGRAM); +PROTOCOL_VARIANT_ADD(VSOCK, STREAM); +PROTOCOL_VARIANT_ADD(VSOCK, SEQPACKET); +#endif + +/* Cf. kcm_create */ +PROTOCOL_VARIANT_EXT_ADD(KCM, DGRAM, KCMPROTO_CONNECTED); +PROTOCOL_VARIANT_EXT_ADD(KCM, SEQPACKET, KCMPROTO_CONNECTED); + +/* Cf. qrtr_create */ +PROTOCOL_VARIANT_ADD(QIPCRTR, DGRAM); + +/* Cf. smc_create */ +#ifndef __alpha__ +PROTOCOL_VARIANT_ADD(SMC, STREAM); +#endif + +/* Cf. xsk_create */ +PROTOCOL_VARIANT_ADD(XDP, RAW); + +/* Cf. mctp_pf_create */ +PROTOCOL_VARIANT_ADD(MCTP, DGRAM); + +TEST_F(protocol, create) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + const struct landlock_socket_attr create_socket_attr = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = self->prot.family, + .type = self->prot.type, + }; + int ruleset_fd; + + /* Tries to create a socket when ruleset is not established. */ + ASSERT_EQ(0, test_socket_variant(&self->prot)); + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &create_socket_attr, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* Tries to create a socket when protocol is allowed. */ + EXPECT_EQ(0, test_socket_variant(&self->prot)); + + /* Denied create. */ + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* Tries to create a socket when protocol is restricted. */ + EXPECT_EQ(EACCES, test_socket_variant(&self->prot)); +} + +TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790474 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EF8961482E1; Wed, 4 Sep 2024 10:48:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446925; cv=none; b=gA9vKQ/Cm9DxzTV62HkXBFcJg4LEbn6PzfSeavPNMju9tnnTOJ0AsmG3D9tonUvi8GHknirC8DT8ndn2Mqfm96TMKrMs06Pi+t0BQv2g67EewJbVjxkXbmtzT/kSDy1uWBYvxYl0jtA221RWanGd3GTH2NAkQUSSsDFCGN8BPjc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446925; c=relaxed/simple; bh=XUNlpDrTDDyxqVvAj2OosIsnUgTacBe2iUBuvvfCjCM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AxkLU96dXuKqCR96ZmRWYykW2bQjBtBuhTrH3tdniK+FdBz2jZVEjBGOgMZ0g6aSnY9o9VKKhtmEYU+q3rjHqX71whn1/+oQxSjRZq0yjW+mIFIvP4MWnomIG624p/ZR97AtJVXkLmBkPt2h1/o/ik/EmrKWCZckBQntZiueFVU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.163.44]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4WzJzY2DDCz1HJ8v; Wed, 4 Sep 2024 18:45:13 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id C1C8E1400D7; Wed, 4 Sep 2024 18:48:40 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:39 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 04/19] selftests/landlock: Test adding a rule with each supported access Date: Wed, 4 Sep 2024 18:48:09 +0800 Message-ID: <20240904104824.1844082-5-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test that checks the possibility of adding rule of `LANDLOCK_RULE_SOCKET` type with all possible access rights. Signed-off-by: Mikhail Ivanov Reviewed-by: Günther Noack --- Changes since v2: * Replaces EXPECT_EQ with ASSERT_EQ for close(). * Refactors commit message and title. Changes since v1: * Formats code with clang-format. * Refactors commit message. --- .../testing/selftests/landlock/socket_test.c | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index 63bb269c9d07..cb23efd3ccc9 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -16,6 +16,9 @@ #include "common.h" +#define ACCESS_LAST LANDLOCK_ACCESS_SOCKET_CREATE +#define ACCESS_ALL LANDLOCK_ACCESS_SOCKET_CREATE + struct protocol_variant { int family; int type; @@ -294,4 +297,32 @@ TEST_F(protocol, create) EXPECT_EQ(EACCES, test_socket_variant(&self->prot)); } +TEST_F(protocol, socket_access_rights) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = ACCESS_ALL, + }; + struct landlock_socket_attr protocol = { + .family = self->prot.family, + .type = self->prot.type, + }; + int ruleset_fd; + __u64 access; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + for (access = 1; access <= ACCESS_LAST; access <<= 1) { + protocol.allowed_access = access; + EXPECT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &protocol, 0)) + { + TH_LOG("Failed to add rule with access 0x%llx: %s", + access, strerror(errno)); + } + } + ASSERT_EQ(0, close(ruleset_fd)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790475 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 939791CFECB; Wed, 4 Sep 2024 10:48:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446927; cv=none; b=NjpFGJY96Mh2wKuJm9f9ZjHtsots+eVFyXpsSC+Oyq57G/N4jknBlrLX2aH13I2MM9kYA1qKQPbzSpxA4aarAskALUiLfTBW+tPfzTCxkaXA7+pni3kiRoz/ZdaNk8aLraewiffrBdtHDLw6/8KcVe50XWjJluGddCvO+OSW3oM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446927; c=relaxed/simple; bh=DMWIp23DCEJuE85kq8d8o/CuzEiXpGfF0Ueszsrw4oE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dhrgwuqAyvWigfmw2CtuhX1y5U5AvZOXX+Cg9K3TWFxgSU4RD9FvdVZc+ND7O3ObTzZqKbkQsCZVMmOr1KV3OXdVlegcK3JAVmytrxfUwUrsnihWsXKa4wQPn4FkNkNYj3KAbzga9oP/JDqVr2ImBj0cD3JElJn+3RTbwvychGk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.234]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4WzJzZ6cDpz1HJ8y; Wed, 4 Sep 2024 18:45:14 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 651601402CC; Wed, 4 Sep 2024 18:48:42 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:40 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 05/19] selftests/landlock: Test adding a rule for each unknown access Date: Wed, 4 Sep 2024 18:48:10 +0800 Message-ID: <20240904104824.1844082-6-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test that validates behaviour of Landlock after rule with unknown access is added. Signed-off-by: Mikhail Ivanov Reviewed-by: Günther Noack --- Changes since v2: * Replaces EXPECT_EQ with ASSERT_EQ for close(). * Refactors commit title. Changes since v1: * Refactors commit messsage. --- .../testing/selftests/landlock/socket_test.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index cb23efd3ccc9..811bdaa95a7a 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -325,4 +325,30 @@ TEST_F(protocol, socket_access_rights) ASSERT_EQ(0, close(ruleset_fd)); } +TEST_F(protocol, rule_with_unknown_access) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = ACCESS_ALL, + }; + struct landlock_socket_attr protocol = { + .family = self->prot.family, + .type = self->prot.type, + }; + int ruleset_fd; + __u64 access; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + for (access = 1ULL << 63; access != ACCESS_LAST; access >>= 1) { + protocol.allowed_access = access; + EXPECT_EQ(-1, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &protocol, 0)); + EXPECT_EQ(EINVAL, errno); + } + ASSERT_EQ(0, close(ruleset_fd)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790476 Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9614E1482E1; Wed, 4 Sep 2024 10:48:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.190 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446928; cv=none; b=XxpRE0skhCdXQ/757DiWeDsFpC8TXbAcpJebIRoOYHzjVNvkJNvPvensz2ErmLk4pIcAAuKqYUKReQCRLLVGROY7n7tntOwXKpjBaoLCJhIwr5ryNgFmHvx55M0aUlFdbAYWRAu3DJRobQEvPoTekktg96XgFksiWTKmJZac/mE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446928; c=relaxed/simple; bh=G/cMFLqgfAz+tSXEyxmiE1H2LQoIMCFLFXGzTqt91ec=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fwTstyQsmDFbv8kXlMiJcD+g/Pq2e5biRBQLouEAFvZKpiw8x7DTu5IjIGlm81CzjRWSztquRQjQyFrwK8Sy2gP3fOkCK1AmLHP3onLhVt3kGFdgW6sfB4oTGLZobX8eXvqgvl9ByM7L3AqGcsggrqgzvbg/NeWeIlo60ZhWAeE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.190 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.163.44]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4WzJxt6ymdz20nMc; Wed, 4 Sep 2024 18:43:46 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 0DEAF1400D7; Wed, 4 Sep 2024 18:48:44 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:42 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 06/19] selftests/landlock: Test adding a rule for unhandled access Date: Wed, 4 Sep 2024 18:48:11 +0800 Message-ID: <20240904104824.1844082-7-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test that validates behaviour of Landlock after rule with unhandled access is added. Signed-off-by: Mikhail Ivanov --- Changes since v2: * Replaces EXPECT_EQ with ASSERT_EQ for close(). * Refactors commit title and message. Changes since v1: * Refactors commit message. --- .../testing/selftests/landlock/socket_test.c | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index 811bdaa95a7a..d2fedfca7193 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -351,4 +351,37 @@ TEST_F(protocol, rule_with_unknown_access) ASSERT_EQ(0, close(ruleset_fd)); } +TEST_F(protocol, rule_with_unhandled_access) +{ + struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + struct landlock_socket_attr protocol = { + .family = self->prot.family, + .type = self->prot.type, + }; + int ruleset_fd; + __u64 access; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + for (access = 1; access > 0; access <<= 1) { + int err; + + protocol.allowed_access = access; + err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &protocol, 0); + if (access == ruleset_attr.handled_access_socket) { + EXPECT_EQ(0, err); + } else { + EXPECT_EQ(-1, err); + EXPECT_EQ(EINVAL, errno); + } + } + + ASSERT_EQ(0, close(ruleset_fd)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790477 Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF16A1D017D; Wed, 4 Sep 2024 10:48:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.190 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446929; cv=none; b=sD6Szo3jMBLvUtKJwpkLPAAkrXw1FYTl3DkrJ7dG6lN74/FI4J5KQnNd7/SQ/xElAQ1kIzKAmQvcUlGl3zeME/gm35jwlDmDV4xyoq//LVO3AFsBkaJwG8DAr3acv7xv1JeXVtrNHnKr9vN3xr5Dxt+zymGK/NDfyBwYL6fomdY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446929; c=relaxed/simple; bh=INxD17Lg/eVdr27iVj8BOakDoLc9Zrxd0IomBcFihJA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mkZqSfYxfxO4qb1qYXHcEIUpwvRwUkKYOW0jpYKaxpvB0frkleHRMTy7tRH2YDlsYG5+zXLJQucy8qGBZob2XSdjiBGdIvZ8yRuRQKg5bErNEYk4xyqmhf2xL2+6j/Y6eJAB4MSbSo6zbI6O3D+HXxdPn21Ri8WeIDvgggStNlo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.190 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.163]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4WzJxw4QVcz20nPj; Wed, 4 Sep 2024 18:43:48 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id A9B52180042; Wed, 4 Sep 2024 18:48:45 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:43 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 07/19] selftests/landlock: Test adding a rule for empty access Date: Wed, 4 Sep 2024 18:48:12 +0800 Message-ID: <20240904104824.1844082-8-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test that validates behaviour of Landlock after rule with empty access is added. Signed-off-by: Mikhail Ivanov Reviewed-by: Günther Noack --- Changes since v2: * Renames protocol.inval into protocol.rule_with_empty_access. * Replaces ASSERT_EQ with EXPECT_EQ for landlock_add_rule(). * Closes ruleset_fd. * Refactors commit message and title. * Minor fixes. Changes since v1: * Refactors commit message. --- .../testing/selftests/landlock/socket_test.c | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index d2fedfca7193..d323f649a183 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -384,4 +384,37 @@ TEST_F(protocol, rule_with_unhandled_access) ASSERT_EQ(0, close(ruleset_fd)); } +TEST_F(protocol, rule_with_empty_access) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE + }; + struct landlock_socket_attr protocol_allowed = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = self->prot.family, + .type = self->prot.type, + }; + struct landlock_socket_attr protocol_denied = { + .allowed_access = 0, + .family = self->prot.family, + .type = self->prot.type, + }; + int ruleset_fd; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Checks zero access value. */ + EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &protocol_denied, 0)); + EXPECT_EQ(ENOMSG, errno); + + /* Adds with legitimate value. */ + EXPECT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &protocol_allowed, 0)); + + ASSERT_EQ(0, close(ruleset_fd)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790478 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C5EFE1D04B7; Wed, 4 Sep 2024 10:48:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446932; cv=none; b=gzGO2TYaPpiJ0rLkmIPaz68rQ/WFZywwdzycQcmyON2rCCsnPQxkCo0UIrIS3rFQ1nUxy4CLR5PzKDYASbkHsa9UBZe1EhdUkCcAwD2g2fP8bS2VXMCg2xafm+4R6I5Ua2tgtph1EwibZj5Dl+1N9xrFGNKST3900yjeU2f9b4U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446932; c=relaxed/simple; bh=1TZhJzlO00aCdwJpkKrXG/0VbvdylOHLISqm2YEswCs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AP/duVWT07PYYiGv201e08fHhBbUljFwMt91g10Rl1v830y23sxAJ8CWq5ekHrHUtnBCYbRVT61mXbax7IZ1ZthnB4mTk4kh6sfNnZq2wm7j/rJd9jVU9Cj8f3iApl9jzn6MbX73qRmaVZxQtn30gOMJT0obYCEy6iTS+svN8Jc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.163.252]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4WzK1D1l7LzgYvP; Wed, 4 Sep 2024 18:46:40 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 73A47180AE6; Wed, 4 Sep 2024 18:48:47 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:45 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 08/19] selftests/landlock: Test overlapped restriction Date: Wed, 4 Sep 2024 18:48:13 +0800 Message-ID: <20240904104824.1844082-9-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test that validates Landlock behaviour with overlapped socket restriction. Signed-off-by: Mikhail Ivanov Reviewed-by: Günther Noack --- Changes since v2: * Removes `tcp_layers` fixture and replaces it with `protocol` fixture for this test. protocol.ruleset_overlap tests every layers depth in a single run. * Adds add_ruleset_layer() helper that enforces ruleset and allows access if such is given. * Replaces EXPECT_EQ with ASSERT_EQ for close(). * Refactors commit message and title. Changes since v1: * Replaces test_socket_create() with test_socket(). * Formats code with clang-format. * Refactors commit message. * Minor fixes. --- .../testing/selftests/landlock/socket_test.c | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index d323f649a183..e7b4165a85cd 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -417,4 +417,50 @@ TEST_F(protocol, rule_with_empty_access) ASSERT_EQ(0, close(ruleset_fd)); } +static void add_ruleset_layer(struct __test_metadata *const _metadata, + const struct landlock_socket_attr *socket_attr) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + int ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + if (socket_attr) { + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + socket_attr, 0)); + } + + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); +} + +TEST_F(protocol, ruleset_overlap) +{ + const struct landlock_socket_attr create_socket_attr = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = self->prot.family, + .type = self->prot.type, + }; + + /* socket(2) is allowed if there are no restrictions. */ + ASSERT_EQ(0, test_socket_variant(&self->prot)); + + /* Creates ruleset with socket(2) allowed. */ + add_ruleset_layer(_metadata, &create_socket_attr); + EXPECT_EQ(0, test_socket_variant(&self->prot)); + + /* Adds ruleset layer with socket(2) restricted. */ + add_ruleset_layer(_metadata, NULL); + EXPECT_EQ(EACCES, test_socket_variant(&self->prot)); + + /* + * Adds ruleset layer with socket(2) allowed. socket(2) is restricted + * by second layer of the ruleset. + */ + add_ruleset_layer(_metadata, &create_socket_attr); + EXPECT_EQ(EACCES, test_socket_variant(&self->prot)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790479 Received: from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 721921CF7A3; Wed, 4 Sep 2024 10:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.255 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446933; cv=none; b=FZFKIEeqIG7zURZekWpZ/c7TW4WZ+P2+dDSwuT+8FjRvWGrSWC49rEqtygh1CWSfZE8JHl16jnoJJ0/sckXmXnInS7Qcn2RR82IdpzXPZZVzibCgCOcACozYF6PdmpU0RO8E1Ewbyl06jUYxTyTKefnX3gurCyK8/8Q2z8B4oDU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446933; c=relaxed/simple; bh=RVjnyh+6CO1rYLpDpkpy2GoNNQ7qT2FNCytzNZCL/dI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=H4bTG9IfFawNYJlTl7XePcqoHYpADyNHEOCabXY8G8VpNjLCQrQuRjuYZ2hlu1TNjrf6U1t1m68yHgBJjQUnFc6ikd+qWPwO41gYJmRlmRg62QZhe832JcJWUafBcEH1uWTO2onwwcIIfRSeLhZvwp76rXr2gYuAB1ncvvT5cZ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.255 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.162.254]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4WzK2b65DQz1BJnD; Wed, 4 Sep 2024 18:47:51 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 3D714180105; Wed, 4 Sep 2024 18:48:49 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:47 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 09/19] selftests/landlock: Test creating a ruleset with unknown access Date: Wed, 4 Sep 2024 18:48:14 +0800 Message-ID: <20240904104824.1844082-10-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test that validates behaviour of Landlock after ruleset with unknown access is created. Signed-off-by: Mikhail Ivanov Reviewed-by: Günther Noack --- Changes since v2: * Removes fixture `mini`. Network namespace is not used, so this fixture has become useless. * Changes commit title and message. Changes since v1: * Refactors commit message. --- tools/testing/selftests/landlock/socket_test.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index e7b4165a85cd..dee676c11227 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -463,4 +463,20 @@ TEST_F(protocol, ruleset_overlap) EXPECT_EQ(EACCES, test_socket_variant(&self->prot)); } +TEST(ruleset_with_unknown_access) +{ + __u64 access_mask; + + for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST; + access_mask >>= 1) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = access_mask, + }; + + EXPECT_EQ(-1, landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0)); + EXPECT_EQ(EINVAL, errno); + } +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790480 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 283741CF7A7; Wed, 4 Sep 2024 10:48:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446936; cv=none; b=DIaXRfBE289RD/f3CpsHGAA/65b57wYtz81iymIswr/2JlJcNZfutgnlZX7/6UsX3290kc3J36K/mqJhsW4thbJgHSY4RM6zfF1O+icMuraQ7bnI/WikDHTGnUcZCa3SrIbcaMNkYgdM4WQIF7eWeib6bfy64LLABvD3g12hepg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446936; c=relaxed/simple; bh=mKZP5+CKYGd+y0oYMNEDWGiKmfZ+LyvUbBETAARZ7JQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DBrHkGDDMWjXNQ99TgXVcPiqdf5IxrHrgCEe4EsK94o5yECLWUCsO6uiy+i82e8OUDWFgaEEqiUh0C4pen9EDUorhl2hv8kabwvyfclceGvilBUy8iG2jbEaXJPcwCCP6TX0pZ61My3rdZDdEKN3whbQCHFkHlvfeKMKYdiI6NE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.234]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4WzJzl3lkHz1HJ8v; Wed, 4 Sep 2024 18:45:23 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 01AEA1402CC; Wed, 4 Sep 2024 18:48:51 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:49 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 10/19] selftests/landlock: Test adding a rule with family and type outside the range Date: Wed, 4 Sep 2024 18:48:15 +0800 Message-ID: <20240904104824.1844082-11-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Create `prot_outside_range` fixture. It is used to iterate through the various family and type pairs that do not fit the valid range. Add test validating that adding a rule for sockets that do not match the ranges (0 <= domain < AF_MAX), (0 <= type < SOCK_MAX) is prohibited. Signed-off-by: Mikhail Ivanov --- Changes since v2: * Removes restriction checks on maximum family and type values. Such checking is performed in protocol.create now. * Renames this test into `rule_with_prot_outside_range` * Creates `prot_outside_range` fixture. It is used to iterate through the various family and type pairs that doesn't fit valid range. Removes CHECK_RULE_OVERFLOW entries. * Checks unrestricted socket(2) with family and type outside the range. * Closes ruleset_fd. * Refactors commit title. --- .../testing/selftests/landlock/socket_test.c | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index dee676c11227..047603abc5a7 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -479,4 +479,106 @@ TEST(ruleset_with_unknown_access) } } +FIXTURE(prot_outside_range) +{ + struct protocol_variant prot; +}; + +FIXTURE_VARIANT(prot_outside_range) +{ + struct protocol_variant prot; +}; + +FIXTURE_SETUP(prot_outside_range) +{ + self->prot = variant->prot; +}; + +FIXTURE_TEARDOWN(prot_outside_range) +{ +} + +/* Cf. include/linux/net.h */ +#define SOCK_MAX (SOCK_PACKET + 1) +#define NEGATIVE_MAX (-1) +/* Cf. linux/net.h */ +#define SOCK_TYPE_MASK 0xf + +#define SOCK_STREAM_FLAG1 (SOCK_STREAM | SOCK_NONBLOCK) +#define SOCK_STREAM_FLAG2 (SOCK_STREAM | SOCK_CLOEXEC) + +#define INVAL_PROTOCOL_VARIANT_ADD(family_, type_) \ + FIXTURE_VARIANT_ADD(prot_outside_range, family_##_##type_) \ + { \ + .prot = { \ + .family = family_, \ + .type = type_, \ + }, \ + } + +INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, INT32_MIN); +INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, NEGATIVE_MAX); +INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, SOCK_STREAM); +INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, SOCK_MAX); +INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, INT32_MAX); + +INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, INT32_MIN); +INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, NEGATIVE_MAX); +INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, SOCK_STREAM); +INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, SOCK_MAX); +INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, INT32_MAX); + +INVAL_PROTOCOL_VARIANT_ADD(AF_INET, INT32_MIN); +INVAL_PROTOCOL_VARIANT_ADD(AF_INET, NEGATIVE_MAX); +INVAL_PROTOCOL_VARIANT_ADD(AF_INET, SOCK_MAX); +INVAL_PROTOCOL_VARIANT_ADD(AF_INET, INT32_MAX); + +INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, INT32_MIN); +INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, NEGATIVE_MAX); +INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, SOCK_STREAM); +INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, SOCK_MAX); +INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, INT32_MAX); + +INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, INT32_MIN); +INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, NEGATIVE_MAX); +INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, SOCK_STREAM); +INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, SOCK_MAX); +INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, INT32_MAX); + +TEST_F(prot_outside_range, add_rule) +{ + int family = self->prot.family; + int type = self->prot.type; + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + struct landlock_socket_attr create_socket_overflow = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = family, + .type = type, + }; + int ruleset_fd; + + /* Checks type flags using __sys_socket_create. */ + if ((type & ~SOCK_TYPE_MASK) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) { + ASSERT_EQ(EINVAL, test_socket_variant(&self->prot)); + } + /* Checks range using __sock_create. */ + else if (family >= AF_MAX || family < 0) { + ASSERT_EQ(EAFNOSUPPORT, test_socket_variant(&self->prot)); + } else { + ASSERT_EQ(EINVAL, test_socket_variant(&self->prot)); + } + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &create_socket_overflow, 0)); + EXPECT_EQ(EINVAL, errno); + + ASSERT_EQ(0, close(ruleset_fd)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790481 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA3FF1CF7B6; Wed, 4 Sep 2024 10:48:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446937; cv=none; b=PdRoqjLdRcxQpKkzciFFw58IfKXA7zef3uOgCBMetsqEPINo7niw2bQvi37CtArHZX3hrT/HiYexV9EUsCcOoCreP4pjzG0+U7beoJB5wDw0xj9YiX/3Ex4zWh8KRRm2DK02CR5R8HhMqCFZcsah+wIxobeYwpdy64SkJbJE+9U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446937; c=relaxed/simple; bh=VjOv1Lsiw2OAH0XdfkzBC/mSzqms7nq+pG+WZu42Ksc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uglZgdXroozOC/R/u4AvlOVZ5WXjZM+DHSK0NsgeHP+XzrpAzQqQ5dcgQCW9pTbYebIonD6fuyFIjJegBNTMtUmdfwjYx5UB4gSgJ1JNmDw0fpqpkE8voqSAtRV5qvj5965rmlOzJFnMUd/o+Vs1HW9ND1sy3osMQoxWI1qR6FU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.194]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4WzK2f6rmxzyR1J; Wed, 4 Sep 2024 18:47:54 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 9E36C1402E1; Wed, 4 Sep 2024 18:48:52 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:50 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 11/19] selftests/landlock: Test unsupported protocol restriction Date: Wed, 4 Sep 2024 18:48:16 +0800 Message-ID: <20240904104824.1844082-12-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test validating that Landlock doesn't wrongfully return EACCES for unsupported address family and protocol. Signed-off-by: Mikhail Ivanov --- Changes since v1: * Adds socket(2) error code check when ruleset is not established. * Tests unsupported family for error code consistency. * Renames test to `unsupported_af_and_prot`. * Refactors commit title and message. * Minor fixes. --- .../testing/selftests/landlock/socket_test.c | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index 047603abc5a7..ff5ace711697 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -581,4 +581,51 @@ TEST_F(prot_outside_range, add_rule) ASSERT_EQ(0, close(ruleset_fd)); } +TEST(unsupported_af_and_prot) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + struct landlock_socket_attr socket_af_unsupported = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = AF_UNSPEC, + .type = SOCK_STREAM, + }; + struct landlock_socket_attr socket_prot_unsupported = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = AF_UNIX, + .type = SOCK_PACKET, + }; + int ruleset_fd; + + /* Tries to create a socket when ruleset is not established. */ + ASSERT_EQ(EAFNOSUPPORT, test_socket(AF_UNSPEC, SOCK_STREAM, 0)); + ASSERT_EQ(ESOCKTNOSUPPORT, test_socket(AF_UNIX, SOCK_PACKET, 0)); + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + EXPECT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &socket_af_unsupported, 0)); + EXPECT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &socket_prot_unsupported, 0)); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* Tries to create a socket when protocols are allowed. */ + EXPECT_EQ(EAFNOSUPPORT, test_socket(AF_UNSPEC, SOCK_STREAM, 0)); + EXPECT_EQ(ESOCKTNOSUPPORT, test_socket(AF_UNIX, SOCK_PACKET, 0)); + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* Tries to create a socket when protocols are restricted. */ + EXPECT_EQ(EAFNOSUPPORT, test_socket(AF_UNSPEC, SOCK_STREAM, 0)); + EXPECT_EQ(ESOCKTNOSUPPORT, test_socket(AF_UNIX, SOCK_PACKET, 0)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790482 Received: from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2CC7F635; Wed, 4 Sep 2024 10:48:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.255 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446938; cv=none; b=fNmsp/95rjdRbDoe9Ildmj4Fv08PMzdiop1i9frl8VceFNGdgY4eI78zlKIDed83tZ+mU/0/Xo9JZjswLp/azgjy2xUOSdpUIPrTVAXcGRyRU+I9qtHl1yUQwJYK6MdXSngk1+OFwa7QTAdLcxMWn4sHVofPl858TH2gPr1MfJc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446938; c=relaxed/simple; bh=tPvunVaZWlh8tfqE1t0F9FXoxdU7bk6AXubYP/7CZJw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kuXT+bgbGPyakc8PcrMMUgk0Doax892w9SBT0VTRgTeSFiKU4SCohKRtWGnpNtixpFHKbG5snftopPwNfLdpAqPNaxqO630KOLQqhCc21aI2G9go+sEkIWJ1zTbNYWZfCohMmlT0qivP/n0JuBidkkl7clqedL3grUiNDn72m1M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.255 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.162.254]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4WzK2h6TN5z13Kwk; Wed, 4 Sep 2024 18:47:56 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 49AF4180105; Wed, 4 Sep 2024 18:48:54 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:52 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 12/19] selftests/landlock: Test that kernel space sockets are not restricted Date: Wed, 4 Sep 2024 18:48:17 +0800 Message-ID: <20240904104824.1844082-13-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test validating that Landlock provides restriction of user space sockets only. Signed-off-by: Mikhail Ivanov Reviewed-by: Günther Noack --- .../testing/selftests/landlock/socket_test.c | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index ff5ace711697..23698b8c2f4d 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -7,7 +7,7 @@ #define _GNU_SOURCE -#include +#include "landlock.h" #include #include #include @@ -628,4 +628,41 @@ TEST(unsupported_af_and_prot) EXPECT_EQ(ESOCKTNOSUPPORT, test_socket(AF_UNIX, SOCK_PACKET, 0)); } +TEST(kernel_socket) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + struct landlock_socket_attr smc_socket_create = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = AF_SMC, + .type = SOCK_STREAM, + }; + int ruleset_fd; + + /* + * Checks that SMC socket is created sucessfuly without + * landlock restrictions. + */ + ASSERT_EQ(0, test_socket(AF_SMC, SOCK_STREAM, 0)); + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &smc_socket_create, 0)); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* + * During the creation of an SMC socket, an internal service TCP socket + * is also created (Cf. smc_create_clcsk). + * + * Checks that Landlock does not restrict creation of the kernel space + * socket. + */ + EXPECT_EQ(0, test_socket(AF_SMC, SOCK_STREAM, 0)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790483 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2779A1D1720; Wed, 4 Sep 2024 10:48:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446940; cv=none; b=ScvXQO85QeCtyvxT4gBv66get0FYR2yMznQclYwu5kpnm/ilqHgTNdaSog7ZuV0OCH6J9EJvP+Gri0nB7a8LMDF4XkgPAuOsZXvZD2gUKLNmcdZ6x2yl+JJL00UsQfAgyDObI+0/HYbAkx7Sry9byQ0Vz8OMGxHrUPiuhzORYJg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446940; c=relaxed/simple; bh=D5KHLBvSpUNoPH0YzEK4QnfJ06v6mtAo4+KLOZb9oSI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Xoa/HsJcAS624E4dWucTL/7zT9j3m/NmntqWvGidF6uz9KpK4tcAOdxYNtlcbJezGOLakpf+wMXvBqR5ISa7xKod13pRULYW/N1D7dk3Dpqa5oD9BfWktkQk9EkZJLnwkJ97DunAWc4EAmcbQ2IprdGdiYQHuozQnWH9Zme3iuU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.163.252]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4WzK1N546zzgYvP; Wed, 4 Sep 2024 18:46:48 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id E6BB7180AE6; Wed, 4 Sep 2024 18:48:55 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:54 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 13/19] selftests/landlock: Test packet protocol alias Date: Wed, 4 Sep 2024 18:48:18 +0800 Message-ID: <20240904104824.1844082-14-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) (AF_INET, SOCK_PACKET) is an alias for (AF_PACKET, SOCK_PACKET) (Cf. __sock_create). Landlock shouldn't restrict one pair if the other was allowed. Add `packet_protocol` fixture and test to validate these scenarios. Signed-off-by: Mikhail Ivanov --- .../testing/selftests/landlock/socket_test.c | 75 ++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index 23698b8c2f4d..8fc507bf902a 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -7,7 +7,7 @@ #define _GNU_SOURCE -#include "landlock.h" +#include #include #include #include @@ -665,4 +665,77 @@ TEST(kernel_socket) EXPECT_EQ(0, test_socket(AF_SMC, SOCK_STREAM, 0)); } +FIXTURE(packet_protocol) +{ + struct protocol_variant prot_allowed, prot_tested; +}; + +FIXTURE_VARIANT(packet_protocol) +{ + bool packet; +}; + +FIXTURE_SETUP(packet_protocol) +{ + self->prot_allowed.type = self->prot_tested.type = SOCK_PACKET; + + self->prot_allowed.family = variant->packet ? AF_PACKET : AF_INET; + self->prot_tested.family = variant->packet ? AF_INET : AF_PACKET; + + /* Packet protocol requires NET_RAW to be set (Cf. packet_create). */ + set_cap(_metadata, CAP_NET_RAW); +}; + +FIXTURE_TEARDOWN(packet_protocol) +{ + clear_cap(_metadata, CAP_NET_RAW); +} + +/* clang-format off */ +FIXTURE_VARIANT_ADD(packet_protocol, packet_allows_inet) { + /* clang-format on */ + .packet = true, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(packet_protocol, inet_allows_packet) { + /* clang-format on */ + .packet = false, +}; + +TEST_F(packet_protocol, alias_restriction) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + struct landlock_socket_attr packet_socket_create = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = self->prot_allowed.family, + .type = self->prot_allowed.type, + }; + int ruleset_fd; + + /* + * Checks that packet socket is created sucessfuly without + * landlock restrictions. + */ + ASSERT_EQ(0, test_socket_variant(&self->prot_tested)); + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &packet_socket_create, 0)); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* + * (AF_INET, SOCK_PACKET) is an alias for the (AF_PACKET, SOCK_PACKET) + * (Cf. __sock_create). Checks that Landlock does not restrict one pair + * if the other was allowed. + */ + EXPECT_EQ(0, test_socket_variant(&self->prot_tested)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790484 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 74B1B1CF7CD; Wed, 4 Sep 2024 10:48:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446941; cv=none; b=X7THqabYGEfvJrLB1fumOmVSvyJVS8Do4d9hV3vuuUl6LHywNls7xUJa0HmGW+sd3cAbGGHO+M6jXOF0w4ug5be7g6r3VNwCLVyn2n5efYaYHML2O8R4nuXLNEEA3QEflaqMJ5plxLf/q0xJ+BEOrCgXwVbHDwBR/LnBmfpHy68= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446941; c=relaxed/simple; bh=we4WZUGk5ZmrA1eAHN+Z5KDLZe5xE3AfMYBOX+apLjU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pfMqpgB3q32r7rgWOIxH6+Qc+BfMGHAMPz0WDZoVtqDW45foSp7CodYv7uIBFOvIUgoQcJYUaAHiKscuD1MQQUFlSfa6RzooikOeDk6p7gQPNcbBjtV0JY5cq9UXBI6RCEAcQMfLKHNOaaPtyR1VxjwiaPoaZLsvqCCY8Rfpx8A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.105]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4WzK1h6SvWzpTwX; Wed, 4 Sep 2024 18:47:04 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 8A6CD140137; Wed, 4 Sep 2024 18:48:57 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:55 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 14/19] selftests/landlock: Test socketpair(2) restriction Date: Wed, 4 Sep 2024 18:48:19 +0800 Message-ID: <20240904104824.1844082-15-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test that checks the restriction on socket creation using socketpair(2). Add `socket_creation` fixture to configure sandboxing in tests in which different socket creation actions are tested. Signed-off-by: Mikhail Ivanov --- .../testing/selftests/landlock/socket_test.c | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index 8fc507bf902a..67db0e1c1121 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -738,4 +738,105 @@ TEST_F(packet_protocol, alias_restriction) EXPECT_EQ(0, test_socket_variant(&self->prot_tested)); } +static int test_socketpair(int family, int type, int protocol) +{ + int fds[2]; + int err; + + err = socketpair(family, type | SOCK_CLOEXEC, protocol, fds); + if (err) + return errno; + /* + * Mixing error codes from close(2) and socketpair(2) should not lead to + * any (access type) confusion for this test. + */ + if (close(fds[0]) != 0) + return errno; + if (close(fds[1]) != 0) + return errno; + return 0; +} + +FIXTURE(socket_creation) +{ + bool sandboxed; + bool allowed; +}; + +FIXTURE_VARIANT(socket_creation) +{ + bool sandboxed; + bool allowed; +}; + +FIXTURE_SETUP(socket_creation) +{ + self->sandboxed = variant->sandboxed; + self->allowed = variant->allowed; + + setup_loopback(_metadata); +}; + +FIXTURE_TEARDOWN(socket_creation) +{ +} + +/* clang-format off */ +FIXTURE_VARIANT_ADD(socket_creation, no_sandbox) { + /* clang-format on */ + .sandboxed = false, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(socket_creation, sandbox_allow) { + /* clang-format on */ + .sandboxed = true, + .allowed = true, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(socket_creation, sandbox_deny) { + /* clang-format on */ + .sandboxed = true, + .allowed = false, +}; + +TEST_F(socket_creation, socketpair) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + struct landlock_socket_attr unix_socket_create = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = AF_UNIX, + .type = SOCK_STREAM, + }; + int ruleset_fd; + + if (self->sandboxed) { + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + if (self->allowed) { + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, + LANDLOCK_RULE_SOCKET, + &unix_socket_create, 0)); + } + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + } + + if (!self->sandboxed || self->allowed) { + /* + * Tries to create sockets when ruleset is not established + * or protocol is allowed. + */ + EXPECT_EQ(0, test_socketpair(AF_UNIX, SOCK_STREAM, 0)); + } else { + /* Tries to create sockets when protocol is restricted. */ + EXPECT_EQ(EACCES, test_socketpair(AF_UNIX, SOCK_STREAM, 0)); + } +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790485 Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 768501D220C; Wed, 4 Sep 2024 10:49:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.190 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446943; cv=none; b=M+xVfTyDLg+xKRiRNlN5RVzWLjSDBQppXct8e8rcKrlL4h8DOH4LlWT1+xYinDAbt0scqBe09HxIk0sLXif4gIWdykemw1Jnxb6Gx7qLdKvgrx3Dm9kSePOlc7Ins4wnR2fLSbjvODOntDLOYzd1G0nTSJ2XqA0ACzbp5+ij1kc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446943; c=relaxed/simple; bh=ZQhcZ7oABbdgp64nuh8UmhP5SCvaqs8uKBtCbxWMHX0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=orXkfoKzg4sAH1xMO8d2FHeuVr9bgf2FVzcgH2HhnZFNCdXfRZ9JL3gJT3tRqz1sKKjq5aB/tnATAJjcqR7I347cSz2wdmU0bDgixW/FOmF3c9kyz+t6bbB7iUn8I0Nt3WR1cCpA7gVWDVYrQjm+6duIkC9Utll6zrlNmmBwoYw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.190 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.163.17]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4WzJyB1vspz20nLj; Wed, 4 Sep 2024 18:44:02 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 5375C1A0188; Wed, 4 Sep 2024 18:48:59 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:57 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 15/19] selftests/landlock: Test SCTP peeloff restriction Date: Wed, 4 Sep 2024 18:48:20 +0800 Message-ID: <20240904104824.1844082-16-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) It is possible to branch off an SCTP UDP association into a separate user space UDP socket. Add test validating that such scenario is not restricted by Landlock. Move setup_loopback() helper from net_test to common.h to use it to enable connection in this test. Signed-off-by: Mikhail Ivanov --- tools/testing/selftests/landlock/common.h | 12 +++ tools/testing/selftests/landlock/net_test.c | 11 -- .../testing/selftests/landlock/socket_test.c | 102 +++++++++++++++++- 3 files changed, 113 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/landlock/common.h b/tools/testing/selftests/landlock/common.h index 28df49fa22d5..07d959a8ac7b 100644 --- a/tools/testing/selftests/landlock/common.h +++ b/tools/testing/selftests/landlock/common.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "../kselftest_harness.h" @@ -227,3 +228,14 @@ enforce_ruleset(struct __test_metadata *const _metadata, const int ruleset_fd) TH_LOG("Failed to enforce ruleset: %s", strerror(errno)); } } + +static void setup_loopback(struct __test_metadata *const _metadata) +{ + set_cap(_metadata, CAP_SYS_ADMIN); + ASSERT_EQ(0, unshare(CLONE_NEWNET)); + clear_cap(_metadata, CAP_SYS_ADMIN); + + set_ambient_cap(_metadata, CAP_NET_ADMIN); + ASSERT_EQ(0, system("ip link set dev lo up")); + clear_ambient_cap(_metadata, CAP_NET_ADMIN); +} diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c index f21cfbbc3638..0b8386657c72 100644 --- a/tools/testing/selftests/landlock/net_test.c +++ b/tools/testing/selftests/landlock/net_test.c @@ -103,17 +103,6 @@ static int set_service(struct service_fixture *const srv, return 1; } -static void setup_loopback(struct __test_metadata *const _metadata) -{ - set_cap(_metadata, CAP_SYS_ADMIN); - ASSERT_EQ(0, unshare(CLONE_NEWNET)); - clear_cap(_metadata, CAP_SYS_ADMIN); - - set_ambient_cap(_metadata, CAP_NET_ADMIN); - ASSERT_EQ(0, system("ip link set dev lo up")); - clear_ambient_cap(_metadata, CAP_NET_ADMIN); -} - static bool is_restricted(const struct protocol_variant *const prot, const enum sandbox_type sandbox) { diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index 67db0e1c1121..2ab27196fa3d 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -11,8 +11,11 @@ #include #include #include -#include +#include +#include +#include #include +#include #include "common.h" @@ -839,4 +842,101 @@ TEST_F(socket_creation, socketpair) } } +static const char loopback_ipv4[] = "127.0.0.1"; +static const int backlog = 10; +static const int loopback_port = 1024; + +TEST_F(socket_creation, sctp_peeloff) +{ + int status, ret; + pid_t child; + struct sockaddr_in addr; + int server_fd; + + server_fd = + socket(AF_INET, SOCK_SEQPACKET | SOCK_CLOEXEC, IPPROTO_SCTP); + ASSERT_LE(0, server_fd); + + addr.sin_family = AF_INET; + addr.sin_port = htons(loopback_port); + addr.sin_addr.s_addr = inet_addr(loopback_ipv4); + + ASSERT_EQ(0, bind(server_fd, &addr, sizeof(addr))); + ASSERT_EQ(0, listen(server_fd, backlog)); + + child = fork(); + ASSERT_LE(0, child); + if (child == 0) { + int client_fd; + sctp_peeloff_flags_arg_t peeloff; + socklen_t peeloff_size = sizeof(peeloff); + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + struct landlock_socket_attr sctp_socket_create = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = AF_INET, + .type = SOCK_SEQPACKET, + }; + + /* Closes listening socket for the child. */ + ASSERT_EQ(0, close(server_fd)); + + client_fd = socket(AF_INET, SOCK_SEQPACKET | SOCK_CLOEXEC, + IPPROTO_SCTP); + ASSERT_LE(0, client_fd); + + /* + * Establishes connection between sockets and + * gets SCTP association id. + */ + ret = setsockopt(client_fd, IPPROTO_SCTP, SCTP_SOCKOPT_CONNECTX, + &addr, sizeof(addr)); + ASSERT_LE(0, ret); + + if (self->sandboxed) { + /* Denies creation of SCTP sockets. */ + int ruleset_fd = landlock_create_ruleset( + &ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + if (self->allowed) { + ASSERT_EQ(0, landlock_add_rule( + ruleset_fd, + LANDLOCK_RULE_SOCKET, + &sctp_socket_create, 0)); + } + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + } + /* + * Branches off current SCTP association into a separate socket + * and returns it to user space. + */ + peeloff.p_arg.associd = ret; + ret = getsockopt(client_fd, IPPROTO_SCTP, SCTP_SOCKOPT_PEELOFF, + &peeloff, &peeloff_size); + + /* + * Creation of SCTP socket by branching off existing SCTP association + * should not be restricted by Landlock. + */ + EXPECT_LE(0, ret); + + /* Closes peeloff socket if such was created. */ + if (!ret) { + ASSERT_EQ(0, close(peeloff.p_arg.sd)); + } + ASSERT_EQ(0, close(client_fd)); + _exit(_metadata->exit_code); + return; + } + + ASSERT_EQ(child, waitpid(child, &status, 0)); + ASSERT_EQ(1, WIFEXITED(status)); + ASSERT_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + ASSERT_EQ(0, close(server_fd)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790486 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04A97635; Wed, 4 Sep 2024 10:49:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446945; cv=none; b=sbgbBSabf9f1tGQLrk042VYFaEzgAotRebQ+84CAk/pxRGPws3fN++DoJCR9W8AnIMjjpI5JoKrl4atoxrBW/45dSa7bs1u/LsefSwHebKsliCRtRnqJs3NOcqOhMerydap8wL+vR7QQEpNrMjqYqef//USY9+o4ZgLP+eoaC3g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446945; c=relaxed/simple; bh=T6GtqoJzV0efJ7P94ycJVbkR65k3kEAMIOFHO2iTWrU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=iRRuDA06DKjKoF5ZqsT7AEgHkGBGHM4Lx3Im5DDi2XYIwjHSfEcAjq6wpjMwLwpw2SKhhVOhTO6ARNdmpwXbvUyAvt0kwm+psrOKRGiPYTM6Rm4nnUfdh0w25BAUxsQCfX/7ZZq4kO4eRADzykvDqfvITRdIh+8nA9YKbRnJ/Mo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.214]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4WzK3X6mzZz1j849; Wed, 4 Sep 2024 18:48:40 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 1BB541A016C; Wed, 4 Sep 2024 18:49:01 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:48:59 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 16/19] selftests/landlock: Test that accept(2) is not restricted Date: Wed, 4 Sep 2024 18:48:21 +0800 Message-ID: <20240904104824.1844082-17-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add test validating that socket creation with accept(2) is not restricted by Landlock. Signed-off-by: Mikhail Ivanov --- .../testing/selftests/landlock/socket_test.c | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c index 2ab27196fa3d..052dbe0d1227 100644 --- a/tools/testing/selftests/landlock/socket_test.c +++ b/tools/testing/selftests/landlock/socket_test.c @@ -939,4 +939,75 @@ TEST_F(socket_creation, sctp_peeloff) ASSERT_EQ(0, close(server_fd)); } +TEST_F(socket_creation, accept) +{ + int status; + pid_t child; + struct sockaddr_in addr; + int server_fd, client_fd; + char buf; + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, + }; + struct landlock_socket_attr tcp_socket_create = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = AF_INET, + .type = SOCK_STREAM, + }; + + server_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); + ASSERT_LE(0, server_fd); + + addr.sin_family = AF_INET; + addr.sin_port = htons(loopback_port); + addr.sin_addr.s_addr = inet_addr(loopback_ipv4); + + ASSERT_EQ(0, bind(server_fd, &addr, sizeof(addr))); + ASSERT_EQ(0, listen(server_fd, backlog)); + + child = fork(); + ASSERT_LE(0, child); + if (child == 0) { + /* Closes listening socket for the child. */ + ASSERT_EQ(0, close(server_fd)); + + client_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); + ASSERT_LE(0, client_fd); + + ASSERT_EQ(0, connect(client_fd, &addr, sizeof(addr))); + EXPECT_EQ(1, write(client_fd, ".", 1)); + + ASSERT_EQ(0, close(client_fd)); + _exit(_metadata->exit_code); + return; + } + + if (self->sandboxed) { + int ruleset_fd = landlock_create_ruleset( + &ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + if (self->allowed) { + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, + LANDLOCK_RULE_SOCKET, + &tcp_socket_create, 0)); + } + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + } + + client_fd = accept(server_fd, NULL, 0); + + /* accept(2) should not be restricted by Landlock. */ + EXPECT_LE(0, client_fd); + + EXPECT_EQ(1, read(client_fd, &buf, 1)); + EXPECT_EQ('.', buf); + + ASSERT_EQ(child, waitpid(child, &status, 0)); + ASSERT_EQ(1, WIFEXITED(status)); + ASSERT_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + ASSERT_EQ(0, close(server_fd)); +} + TEST_HARNESS_MAIN From patchwork Wed Sep 4 10:48:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790487 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A214F1CFEAB; Wed, 4 Sep 2024 10:49:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446946; cv=none; b=V8VZhcDNPhNmQFkN3Z+ItTjj6syDMV2J9Pn5XGgjm1yq4LBq++qi58syySKMsF/Eo6o/Ju8PDsyHshsnUcc4pcyc6eUCRGlVSgFNNqtIvln4aMmyHxWj0AsTUffCXp5j8nEdr1dXK8tSZ+S76ai99b37YukRd0pffE9105+7UJo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446946; c=relaxed/simple; bh=9U/ib4/w/+BXpfPUe69d2A4jP4W7vuNzlLQWjhhSUkg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YWuUeXS8ysmehbhFu5Uig/s0iJiyVE43o6NHXTozpqfS5x6ToBUG7NP0S2F0yb44GaWFnjLwber1+/djHvz0pYZmNVQLKeaGLq9KOOqqbkU+vwlH4ODycq6f291h0HMGwNHWkQskXRv8DY6N+3ehmOAiKmHggWUlkPZcyI/vZ38= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.234]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4WzK3Z47rJz1j84D; Wed, 4 Sep 2024 18:48:42 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id B4E841402CC; Wed, 4 Sep 2024 18:49:02 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:49:01 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 17/19] samples/landlock: Replace atoi() with strtoull() in populate_ruleset_net() Date: Wed, 4 Sep 2024 18:48:22 +0800 Message-ID: <20240904104824.1844082-18-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add str2num() helper and replace atoi() with it. atoi() does not provide overflow checks, checks of invalid characters in a string and it is recommended to use strtol-like functions (Cf. atoi() manpage). Signed-off-by: Mikhail Ivanov --- samples/landlock/sandboxer.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c index e8223c3e781a..d4dba9e4ce89 100644 --- a/samples/landlock/sandboxer.c +++ b/samples/landlock/sandboxer.c @@ -150,6 +150,26 @@ static int populate_ruleset_fs(const char *const env_var, const int ruleset_fd, return ret; } +static int str2num(const char *numstr, unsigned long long *num_dst) +{ + char *endptr = NULL; + int err = 1; + unsigned long long num; + + errno = 0; + num = strtoull(numstr, &endptr, 0); + if (errno != 0) + goto out; + + if (*endptr != '\0') + goto out; + + *num_dst = num; + err = 0; +out: + return err; +} + static int populate_ruleset_net(const char *const env_var, const int ruleset_fd, const __u64 allowed_access) { @@ -168,7 +188,12 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd, env_port_name_next = env_port_name; while ((strport = strsep(&env_port_name_next, ENV_DELIMITER))) { - net_port.port = atoi(strport); + if (str2num(strport, &net_port.port)) { + fprintf(stderr, + "Failed to convert \"%s\" into a number\n", + strport); + goto out_free_name; + } if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, &net_port, 0)) { fprintf(stderr, From patchwork Wed Sep 4 10:48:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790488 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 534871D3195; Wed, 4 Sep 2024 10:49:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446948; cv=none; b=t2A2ze/Ja85Y9lODofxDGb+OFJJ3xQ6KtLGVi4XRzmh943AM6H+9h/M0W18XYWu8POmoCNBSjvzVGzzwQinW5rLvbAk/PzDA7yCAXynwQJFD+dlM2y6hhs3xCk57YTNfZb9n7HCtZoabfRLybrTda2pDTDjqk8eOSC8wM8tsKZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446948; c=relaxed/simple; bh=MnTVEv0OPDyrBu53ehWhbTDD7SNVHBcs646S3Eq1vZQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pPGZ06Ei4+tPhGYpztZIkjF+JXlnLxjQHx0mySGKh7/xUHxAXsU4HcKIyCP+AuGVxqQA7J0etGWB9Oo6asJfSoHYIkErkpvZqqW5iIvf77aa0cnBTHBBrMLeTNmlMkr9EaF0xIP1ox5LsFDboQaLOCVuYmjBKyjDAbK4mjrL14I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.88.194]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4WzK2t60T6zyQyK; Wed, 4 Sep 2024 18:48:06 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 807671400CA; Wed, 4 Sep 2024 18:49:04 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:49:02 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 18/19] samples/landlock: Support socket protocol restrictions Date: Wed, 4 Sep 2024 18:48:23 +0800 Message-ID: <20240904104824.1844082-19-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Add socket protocol control support in sandboxer demo. It's possible to allow a sandboxer to create sockets with specified family and type values. This is controlled with the new LL_SOCKET_CREATE environment variable. Single token in this variable looks like this: 'FAMILY.TYPE', where FAMILY and TYPE are integers corresponding to the number of address family and socket type. Add parse_socket_protocol() method to parse socket family and type strings into integers. Change LANDLOCK_ABI_LAST to 6. Signed-off-by: Mikhail Ivanov --- Changes since v2: * Changes representation of socket protocol in LL_SOCKET_CREATE into pair of integer values. * Changes commit message. * Minor fixes. Changes since v1: * Refactors get_socket_protocol(). Rename it to parse_socket_protocol(). * Changes LANDLOCK_ABI_LAST to 6 since ioctl patchlist updated it to 5. * Refactors commit message. * Formats with clang-format. * Minor changes. --- samples/landlock/sandboxer.c | 108 ++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 13 deletions(-) diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c index d4dba9e4ce89..1669095f9373 100644 --- a/samples/landlock/sandboxer.c +++ b/samples/landlock/sandboxer.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -55,8 +56,11 @@ static inline int landlock_restrict_self(const int ruleset_fd, #define ENV_FS_RW_NAME "LL_FS_RW" #define ENV_TCP_BIND_NAME "LL_TCP_BIND" #define ENV_TCP_CONNECT_NAME "LL_TCP_CONNECT" +#define ENV_SOCKET_CREATE_NAME "LL_SOCKET_CREATE" #define ENV_DELIMITER ":" +#define ENV_TOKEN_INTERNAL_DELIMITER "." + static int parse_path(char *env_path, const char ***const path_list) { int i, num_paths = 0; @@ -209,6 +213,65 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd, return ret; } +static int populate_ruleset_socket(const char *const env_var, + const int ruleset_fd, + const __u64 allowed_access) +{ + int ret = 1; + char *env_protocol_name, *strprotocol, *strfamily, *strtype; + unsigned long long family_ull, type_ull; + struct landlock_socket_attr protocol = { + .allowed_access = allowed_access, + }; + + env_protocol_name = getenv(env_var); + if (!env_protocol_name) + return 0; + env_protocol_name = strdup(env_protocol_name); + unsetenv(env_var); + + while ((strprotocol = strsep(&env_protocol_name, ENV_DELIMITER))) { + strfamily = strsep(&strprotocol, ENV_TOKEN_INTERNAL_DELIMITER); + strtype = strsep(&strprotocol, ENV_TOKEN_INTERNAL_DELIMITER); + + if (!strtype) { + fprintf(stderr, + "Failed to extract socket protocol with " + "unspecified type value\n"); + goto out_free_name; + } + + if (str2num(strfamily, &family_ull)) { + fprintf(stderr, + "Failed to convert \"%s\" into a number\n", + strfamily); + goto out_free_name; + } + if (str2num(strtype, &type_ull)) { + fprintf(stderr, + "Failed to convert \"%s\" into a number\n", + strtype); + goto out_free_name; + } + protocol.family = (int)family_ull; + protocol.type = (int)type_ull; + + if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &protocol, 0)) { + fprintf(stderr, + "Failed to update the ruleset with " + "family \"%s\" and type \"%s\": %s\n", + strfamily, strtype, strerror(errno)); + goto out_free_name; + } + } + ret = 0; + +out_free_name: + free(env_protocol_name); + return ret; +} + /* clang-format off */ #define ACCESS_FS_ROUGHLY_READ ( \ @@ -233,14 +296,14 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd, /* clang-format on */ -#define LANDLOCK_ABI_LAST 5 +#define LANDLOCK_ABI_LAST 6 int main(const int argc, char *const argv[], char *const *const envp) { const char *cmd_path; char *const *cmd_argv; int ruleset_fd, abi; - char *env_port_name; + char *env_optional_name; __u64 access_fs_ro = ACCESS_FS_ROUGHLY_READ, access_fs_rw = ACCESS_FS_ROUGHLY_READ | ACCESS_FS_ROUGHLY_WRITE; @@ -248,18 +311,19 @@ int main(const int argc, char *const argv[], char *const *const envp) .handled_access_fs = access_fs_rw, .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP, + .handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE, }; if (argc < 2) { fprintf(stderr, - "usage: %s=\"...\" %s=\"...\" %s=\"...\" %s=\"...\"%s " + "usage: %s=\"...\" %s=\"...\" %s=\"...\" %s=\"...\" %s=\"...\"%s " " [args]...\n\n", ENV_FS_RO_NAME, ENV_FS_RW_NAME, ENV_TCP_BIND_NAME, - ENV_TCP_CONNECT_NAME, argv[0]); + ENV_TCP_CONNECT_NAME, ENV_SOCKET_CREATE_NAME, argv[0]); fprintf(stderr, "Execute a command in a restricted environment.\n\n"); fprintf(stderr, - "Environment variables containing paths and ports " + "Environment variables containing paths, ports and protocols " "each separated by a colon:\n"); fprintf(stderr, "* %s: list of paths allowed to be used in a read-only way.\n", @@ -268,7 +332,7 @@ int main(const int argc, char *const argv[], char *const *const envp) "* %s: list of paths allowed to be used in a read-write way.\n\n", ENV_FS_RW_NAME); fprintf(stderr, - "Environment variables containing ports are optional " + "Environment variables containing ports or protocols are optional " "and could be skipped.\n"); fprintf(stderr, "* %s: list of ports allowed to bind (server).\n", @@ -276,15 +340,19 @@ int main(const int argc, char *const argv[], char *const *const envp) fprintf(stderr, "* %s: list of ports allowed to connect (client).\n", ENV_TCP_CONNECT_NAME); + fprintf(stderr, + "* %s: list of socket protocols allowed to be created.\n", + ENV_SOCKET_CREATE_NAME); fprintf(stderr, "\nexample:\n" "%s=\"${PATH}:/lib:/usr:/proc:/etc:/dev/urandom\" " "%s=\"/dev/null:/dev/full:/dev/zero:/dev/pts:/tmp\" " "%s=\"9418\" " "%s=\"80:443\" " + "%s=\"10.2:1.1\" " "%s bash -i\n\n", ENV_FS_RO_NAME, ENV_FS_RW_NAME, ENV_TCP_BIND_NAME, - ENV_TCP_CONNECT_NAME, argv[0]); + ENV_TCP_CONNECT_NAME, ENV_SOCKET_CREATE_NAME, argv[0]); fprintf(stderr, "This sandboxer can use Landlock features " "up to ABI version %d.\n", @@ -351,7 +419,11 @@ int main(const int argc, char *const argv[], char *const *const envp) case 4: /* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */ ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV; - + __attribute__((fallthrough)); + case 5: + /* Removes socket support for ABI < 6 */ + ruleset_attr.handled_access_socket &= + ~LANDLOCK_ACCESS_SOCKET_CREATE; fprintf(stderr, "Hint: You should update the running kernel " "to leverage Landlock features " @@ -371,18 +443,23 @@ int main(const int argc, char *const argv[], char *const *const envp) access_fs_rw &= ruleset_attr.handled_access_fs; /* Removes bind access attribute if not supported by a user. */ - env_port_name = getenv(ENV_TCP_BIND_NAME); - if (!env_port_name) { + env_optional_name = getenv(ENV_TCP_BIND_NAME); + if (!env_optional_name) { ruleset_attr.handled_access_net &= ~LANDLOCK_ACCESS_NET_BIND_TCP; } /* Removes connect access attribute if not supported by a user. */ - env_port_name = getenv(ENV_TCP_CONNECT_NAME); - if (!env_port_name) { + env_optional_name = getenv(ENV_TCP_CONNECT_NAME); + if (!env_optional_name) { ruleset_attr.handled_access_net &= ~LANDLOCK_ACCESS_NET_CONNECT_TCP; } - + /* Removes socket create access attribute if not supported by a user. */ + env_optional_name = getenv(ENV_SOCKET_CREATE_NAME); + if (!env_optional_name) { + ruleset_attr.handled_access_socket &= + ~LANDLOCK_ACCESS_SOCKET_CREATE; + } ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); if (ruleset_fd < 0) { @@ -406,6 +483,11 @@ int main(const int argc, char *const argv[], char *const *const envp) goto err_close_ruleset; } + if (populate_ruleset_socket(ENV_SOCKET_CREATE_NAME, ruleset_fd, + LANDLOCK_ACCESS_SOCKET_CREATE)) { + goto err_close_ruleset; + } + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { perror("Failed to restrict privileges"); goto err_close_ruleset; From patchwork Wed Sep 4 10:48:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13790489 Received: from szxga06-in.huawei.com (szxga06-in.huawei.com [45.249.212.32]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 78DC91CF7B1; Wed, 4 Sep 2024 10:49:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.32 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446950; cv=none; b=NfVBuy5T2QX5iYES1HCDzvhaDEoWynTyayd4sRwKPl0+URZc4zTbfNjx5/E9o97yG+4NzuiCm2eDjVHo2eKTdWKj97iTs8/LbGvLcpuzYSccJBMHxHgyCblTKWutMXWxN1YRw0UMQVUS1EUztytPW5WgpSyvydfpzQydxX1IhLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725446950; c=relaxed/simple; bh=320TKFw25kQyKSDRTjKicEFKtLjUgdWcjO8fDh6C8ts=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oTyx8cOfJDNncGgxzZM/1TwOVLz04OqGlLCTFWH7J40Ff1mJg/Oo+gQEIMPkyyxSn5qBnbnwePeVaiazk5vTbDs0pAFjQIzdk98tN5XAVEqSty/MtcY8YfzWHzwNVUPaVfIvgmlRxg5fr/xAdZZw5cUiV0rh/HtcEyYvZlQ1nuI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=45.249.212.32 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.19.163.44]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4WzK1j3hT9z1xwMM; Wed, 4 Sep 2024 18:47:05 +0800 (CST) Received: from kwepemj200016.china.huawei.com (unknown [7.202.194.28]) by mail.maildlp.com (Postfix) with ESMTPS id 463961400D7; Wed, 4 Sep 2024 18:49:06 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by kwepemj200016.china.huawei.com (7.202.194.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Sep 2024 18:49:04 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v3 19/19] landlock: Document socket rule type support Date: Wed, 4 Sep 2024 18:48:24 +0800 Message-ID: <20240904104824.1844082-20-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> References: <20240904104824.1844082-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml500004.china.huawei.com (7.188.26.250) To kwepemj200016.china.huawei.com (7.202.194.28) Extend documentation with socket rule type description. Signed-off-by: Mikhail Ivanov --- Documentation/userspace-api/landlock.rst | 46 ++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst index 37dafce8038b..4bf45064faa1 100644 --- a/Documentation/userspace-api/landlock.rst +++ b/Documentation/userspace-api/landlock.rst @@ -33,7 +33,7 @@ A Landlock rule describes an action on an object which the process intends to perform. A set of rules is aggregated in a ruleset, which can then restrict the thread enforcing it, and its future children. -The two existing types of rules are: +The three existing types of rules are: Filesystem rules For these rules, the object is a file hierarchy, @@ -44,14 +44,19 @@ Network rules (since ABI v4) For these rules, the object is a TCP port, and the related actions are defined with `network access rights`. +Socket rules (since ABI v6) + For these rules, the object is a pair of an address family and a socket type, + and the related actions are defined with `socket access rights`. + Defining and enforcing a security policy ---------------------------------------- We first need to define the ruleset that will contain our rules. For this example, the ruleset will contain rules that only allow filesystem -read actions and establish a specific TCP connection. Filesystem write -actions and other TCP actions will be denied. +read actions, create TCP sockets and establish a specific TCP connection. +Filesystem write actions, creating non-TCP sockets and other TCP +actions will be denied. The ruleset then needs to handle both these kinds of actions. This is required for backward and forward compatibility (i.e. the kernel and user @@ -81,6 +86,8 @@ to be explicit about the denied-by-default access rights. .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP, + .handled_access_socket = + LANDLOCK_ACCESS_SOCKET_CREATE, }; Because we may not know on which kernel version an application will be @@ -119,6 +126,11 @@ version, and only use the available subset of access rights: case 4: /* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */ ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV; + __attribute__((fallthrough)); + case 5: + /* Removes socket support for ABI < 6 */ + ruleset_attr.handled_access_socket &= + ~LANDLOCK_ACCESS_SOCKET_CREATE; } This enables to create an inclusive ruleset that will contain our rules. @@ -170,6 +182,20 @@ for the ruleset creation, by filtering access rights according to the Landlock ABI version. In this example, this is not required because all of the requested ``allowed_access`` rights are already available in ABI 1. +For socket access-control, we can add a rule to allow TCP sockets creation. UNIX, +UDP IP and other protocols will be denied by the ruleset. + +.. code-block:: c + + struct landlock_net_port_attr tcp_socket = { + .allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE, + .family = AF_INET, + .type = SOCK_STREAM, + }; + + err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET, + &tcp_socket, 0); + For network access-control, we can add a set of rules that allow to use a port number for a specific action: HTTPS connections. @@ -186,7 +212,8 @@ number for a specific action: HTTPS connections. The next step is to restrict the current thread from gaining more privileges (e.g. through a SUID binary). We now have a ruleset with the first rule allowing read access to ``/usr`` while denying all other handled accesses for -the filesystem, and a second rule allowing HTTPS connections. +the filesystem, a second rule allowing TCP sockets and a third rule allowing +HTTPS connections. .. code-block:: c @@ -404,7 +431,7 @@ Access rights ------------- .. kernel-doc:: include/uapi/linux/landlock.h - :identifiers: fs_access net_access + :identifiers: fs_access net_access socket_access Creating a new ruleset ---------------------- @@ -423,7 +450,7 @@ Extending a ruleset .. kernel-doc:: include/uapi/linux/landlock.h :identifiers: landlock_rule_type landlock_path_beneath_attr - landlock_net_port_attr + landlock_net_port_attr landlock_socket_attr Enforcing a ruleset ------------------- @@ -541,6 +568,13 @@ earlier ABI. Starting with the Landlock ABI version 5, it is possible to restrict the use of :manpage:`ioctl(2)` using the new ``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right. +Socket support (ABI < 6) +------------------------- + +Starting with the Landlock ABI version 6, it is now possible to restrict +creation of user space sockets to only a set of allowed protocols thanks +to the new ``LANDLOCK_ACCESS_SOCKET_CREATE`` access right. + .. _kernel_support: Kernel support