From patchwork Sun Jul 28 00:25:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743811 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 01AF810F2; Sun, 28 Jul 2024 00:26:21 +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=1722126384; cv=none; b=KR2xi86THra8kEl5yOFl0HwYyNnALDuv3tlQrzMef6DEERyvkHDwkTTkKS1O7Rwv0DA9AGtK0iJe+2Fk9dbWgotGpBPfG9Eu5owT8hTq+2o3t+qqdyFu5dpJLH15ycDvJLdeKGYlxB483E8y5sXeTPCJYoWzUx8nb7ZJW3+637w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126384; c=relaxed/simple; bh=Bq0J4dM/Ssad6W6jRFHjz+IF5IINDQDZBd7EC9wLw2M=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hQb4jBrTI2AZL5ZeMqVFvXN2yxAk/5EX5vZOao58XYgvaUOdQO6aSEblxzWY6iihfhdqu6sRhGEON1xDbXno8bcL4/ElFtSoYF73QH44Hr9g4zExw6koicebJBpekeCKVCXU/ovO4lvcr+1H79WWwbbCEcxEWSH/+rPo4D/GPMQ= 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 4WWj2l4v4fz1L9CK; Sun, 28 Jul 2024 08:26:07 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id 7A6681800D0; Sun, 28 Jul 2024 08:26:14 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:12 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 1/9] landlock: Refactor current_check_access_socket() access right check Date: Sun, 28 Jul 2024 08:25:54 +0800 Message-ID: <20240728002602.3198398-2-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC The current_check_access_socket() function contains a set of address validation checks for bind(2) and connect(2) hooks. Separate them from an actual port access right checking. It is required for the (future) hooks that do not perform address validation. Signed-off-by: Mikhail Ivanov --- security/landlock/net.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/security/landlock/net.c b/security/landlock/net.c index c8bcd29bde09..669ba260342f 100644 --- a/security/landlock/net.c +++ b/security/landlock/net.c @@ -2,7 +2,7 @@ /* * Landlock LSM - Network management and hooks * - * Copyright © 2022-2023 Huawei Tech. Co., Ltd. + * Copyright © 2022-2024 Huawei Tech. Co., Ltd. * Copyright © 2022-2023 Microsoft Corporation */ @@ -61,17 +61,34 @@ static const struct landlock_ruleset *get_current_net_domain(void) return dom; } -static int current_check_access_socket(struct socket *const sock, - struct sockaddr *const address, - const int addrlen, - access_mask_t access_request) +static int check_access_socket(const struct landlock_ruleset *const dom, + __be16 port, access_mask_t access_request) { - __be16 port; layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_NET] = {}; const struct landlock_rule *rule; struct landlock_id id = { .type = LANDLOCK_KEY_NET_PORT, }; + + id.key.data = (__force uintptr_t)port; + BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); + + rule = landlock_find_rule(dom, id); + access_request = landlock_init_layer_masks( + dom, access_request, &layer_masks, LANDLOCK_KEY_NET_PORT); + if (landlock_unmask_layers(rule, access_request, &layer_masks, + ARRAY_SIZE(layer_masks))) + return 0; + + return -EACCES; +} + +static int current_check_access_socket(struct socket *const sock, + struct sockaddr *const address, + const int addrlen, + access_mask_t access_request) +{ + __be16 port; const struct landlock_ruleset *const dom = get_current_net_domain(); if (!dom) @@ -159,17 +176,7 @@ static int current_check_access_socket(struct socket *const sock, return -EINVAL; } - id.key.data = (__force uintptr_t)port; - BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); - - rule = landlock_find_rule(dom, id); - access_request = landlock_init_layer_masks( - dom, access_request, &layer_masks, LANDLOCK_KEY_NET_PORT); - if (landlock_unmask_layers(rule, access_request, &layer_masks, - ARRAY_SIZE(layer_masks))) - return 0; - - return -EACCES; + return check_access_socket(dom, port, access_request); } static int hook_socket_bind(struct socket *const sock, From patchwork Sun Jul 28 00:25:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743813 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 7FF701362; Sun, 28 Jul 2024 00:26:23 +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=1722126387; cv=none; b=MPIRrtuGaHjQUqVXa52AC5h14r0pdCM+NXgENzPciqDj4C+KaSgOO1GyVmFIRfW4/Psfy4A/Gi8TqpvJIExi47oc0fjhXoVSkCTyZcg3cw5yjRnZgidrvV8nid5G4dJVUGmlLZfm241tStRt2spy+tXrmV3bO98kQi5M6w3SOdo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126387; c=relaxed/simple; bh=GTZVFc0zSeeXeCyBwP5m2swx0FvR30y1JM3cEv1GDd4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=R34MW4T03Ov9vMnC8d6CME4YoOrwBXcrQ/JyNAog7qdWfEu6ft4YAvz+BYzoEVNo/874+F0ualzqzdlCQ7Do328XCzDeKMYSJz7Eo04f5LwjtoF8u8O6qB6467/XC5L1KRTwnZdCK5zVeW3a2cLCGyLnIahJ2kNySn6jJ6uCTpk= 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 4WWj2n3N4vz1L9Df; Sun, 28 Jul 2024 08:26:09 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id 45EF0180105; Sun, 28 Jul 2024 08:26:16 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:14 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 2/9] landlock: Support TCP listen access-control Date: Sun, 28 Jul 2024 08:25:55 +0800 Message-ID: <20240728002602.3198398-3-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC LANDLOCK_ACCESS_NET_BIND_TCP is useful to limit the scope of "bindable" ports to forbid a malicious sandboxed process to impersonate a legitimate server process. However, bind(2) might be used by (TCP) clients to set the source port to a (legitimate) value. Controlling the ports that can be used for listening would allow (TCP) clients to explicitly bind to ports that are forbidden for listening. Such control is implemented with a new LANDLOCK_ACCESS_NET_LISTEN_TCP access right that restricts listening on undesired ports with listen(2). It's worth noticing that this access right doesn't affect changing backlog value using listen(2) on already listening socket. * Create new LANDLOCK_ACCESS_NET_LISTEN_TCP flag. * Add hook to socket_listen(), which checks whether the socket is allowed to listen on a binded local port. * Add check_tcp_socket_can_listen() helper, which validates socket attributes before the actual access right check. * Update `struct landlock_net_port_attr` documentation with control of binding to ephemeral port with listen(2) description. * Change ABI version to 6. Closes: https://github.com/landlock-lsm/linux/issues/15 Signed-off-by: Mikhail Ivanov --- include/uapi/linux/landlock.h | 23 +++-- security/landlock/limits.h | 2 +- security/landlock/net.c | 90 ++++++++++++++++++++ security/landlock/syscalls.c | 2 +- tools/testing/selftests/landlock/base_test.c | 2 +- 5 files changed, 108 insertions(+), 11 deletions(-) diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index 68625e728f43..6b8df3293eee 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -104,13 +104,16 @@ struct landlock_net_port_attr { /** * @port: Network port in host endianness. * - * It should be noted that port 0 passed to :manpage:`bind(2)` will - * bind to an available port from a specific port range. This can be - * configured thanks to the ``/proc/sys/net/ipv4/ip_local_port_range`` - * sysctl (also used for IPv6). A Landlock rule with port 0 and the - * ``LANDLOCK_ACCESS_NET_BIND_TCP`` right means that requesting to bind - * on port 0 is allowed and it will automatically translate to binding - * on the related port range. + * It should be noted that some operations cause binding socket to a random + * available port from a specific port range. This can be configured thanks + * to the ``/proc/sys/net/ipv4/ip_local_port_range`` sysctl (also used for + * IPv6). Following operation requests are automatically translate to + * binding on the related port range: + * + * - A Landlock rule with port 0 and the ``LANDLOCK_ACCESS_NET_BIND_TCP`` + * right means that binding on port 0 is allowed. + * - A Landlock rule with port 0 and the ``LANDLOCK_ACCESS_NET_LISTEN_TCP`` + * right means listening without an explicit binding is allowed. */ __u64 port; }; @@ -251,7 +254,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. @@ -261,9 +264,13 @@ struct landlock_net_port_attr { * - %LANDLOCK_ACCESS_NET_BIND_TCP: Bind a TCP socket to a local port. * - %LANDLOCK_ACCESS_NET_CONNECT_TCP: Connect an active TCP socket to * a remote port. + * - %LANDLOCK_ACCESS_NET_LISTEN_TCP: Listen for TCP socket connections on + * a local port. This access right is available since the sixth version + * of the Landlock ABI. */ /* clang-format off */ #define LANDLOCK_ACCESS_NET_BIND_TCP (1ULL << 0) #define LANDLOCK_ACCESS_NET_CONNECT_TCP (1ULL << 1) +#define LANDLOCK_ACCESS_NET_LISTEN_TCP (1ULL << 2) /* clang-format on */ #endif /* _UAPI_LINUX_LANDLOCK_H */ diff --git a/security/landlock/limits.h b/security/landlock/limits.h index 4eb643077a2a..2ef147389474 100644 --- a/security/landlock/limits.h +++ b/security/landlock/limits.h @@ -22,7 +22,7 @@ #define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1) #define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS) -#define LANDLOCK_LAST_ACCESS_NET LANDLOCK_ACCESS_NET_CONNECT_TCP +#define LANDLOCK_LAST_ACCESS_NET LANDLOCK_ACCESS_NET_LISTEN_TCP #define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1) #define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET) diff --git a/security/landlock/net.c b/security/landlock/net.c index 669ba260342f..a29cb27c3f14 100644 --- a/security/landlock/net.c +++ b/security/landlock/net.c @@ -6,10 +6,12 @@ * Copyright © 2022-2023 Microsoft Corporation */ +#include "net/sock.h" #include #include #include #include +#include #include "common.h" #include "cred.h" @@ -194,9 +196,97 @@ static int hook_socket_connect(struct socket *const sock, LANDLOCK_ACCESS_NET_CONNECT_TCP); } +/* + * Checks that socket state and attributes are correct for listen. + * It is required to not wrongfully return -EACCES instead of -EINVAL. + * + * This checker requires sock->sk to be locked. + */ +static int check_tcp_socket_can_listen(struct socket *const sock) +{ + struct sock *sk = sock->sk; + unsigned char cur_sk_state = sk->sk_state; + const struct tcp_ulp_ops *icsk_ulp_ops; + + /* Allows only unconnected TCP socket to listen (cf. inet_listen). */ + if (sock->state != SS_UNCONNECTED) + return -EINVAL; + + /* + * Checks sock state. This is needed to ensure consistency with inet stack + * error handling (cf. __inet_listen_sk). + */ + if (WARN_ON_ONCE(!((1 << cur_sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))) + return -EINVAL; + + icsk_ulp_ops = inet_csk(sk)->icsk_ulp_ops; + + /* + * ULP (Upper Layer Protocol) stands for protocols which are higher than + * transport protocol in OSI model. Linux has an infrastructure that + * allows TCP sockets to support logic of some ULP (e.g. TLS ULP). + * + * Sockets can listen only if ULP control hook has clone method. + */ + if (icsk_ulp_ops && !icsk_ulp_ops->clone) + return -EINVAL; + return 0; +} + +static int hook_socket_listen(struct socket *const sock, const int backlog) +{ + int err = 0; + int family; + __be16 port; + struct sock *sk; + const struct landlock_ruleset *const dom = get_current_net_domain(); + + if (!dom) + return 0; + if (WARN_ON_ONCE(dom->num_layers < 1)) + return -EACCES; + + /* Checks if it's a (potential) TCP socket. */ + if (sock->type != SOCK_STREAM) + return 0; + + sk = sock->sk; + family = sk->__sk_common.skc_family; + /* + * Socket cannot be assigned AF_UNSPEC because this type is used only + * in the context of addresses. + * + * Doesn't restrict listening for non-TCP sockets. + */ + if (family != AF_INET && family != AF_INET6) + return 0; + + lock_sock(sk); + /* + * Calling listen(2) for a listening socket does nothing with its state and + * only changes backlog value (cf. __inet_listen_sk). Checking of listen + * access right is not required. + */ + if (sk->sk_state == TCP_LISTEN) + goto release_nocheck; + + err = check_tcp_socket_can_listen(sock); + if (unlikely(err)) + goto release_nocheck; + + port = htons(inet_sk(sk)->inet_num); + release_sock(sk); + return check_access_socket(dom, port, LANDLOCK_ACCESS_NET_LISTEN_TCP); + +release_nocheck: + release_sock(sk); + return err; +} + static struct security_hook_list landlock_hooks[] __ro_after_init = { LSM_HOOK_INIT(socket_bind, hook_socket_bind), LSM_HOOK_INIT(socket_connect, hook_socket_connect), + LSM_HOOK_INIT(socket_listen, hook_socket_listen), }; __init void landlock_add_net_hooks(void) diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index 03b470f5a85a..3752bcc033d4 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -149,7 +149,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 diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c index 3c1e9f35b531..52b00472a487 100644 --- a/tools/testing/selftests/landlock/base_test.c +++ b/tools/testing/selftests/landlock/base_test.c @@ -75,7 +75,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 Sun Jul 28 00:25:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743809 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 1462810F1; Sun, 28 Jul 2024 00:26:20 +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=1722126384; cv=none; b=EwjBeCK7hsu4xPlRfCvBl/tqL2OlOWA5mj5iGYqWyPczDXEpKQ0eT8ledHZDsLPeNuFBbALF4y93HSA52VMh/ReqP1dqcbwg8dbgqe68n+ETOIYEstbrA+fS6Q6NbRZ2h6Cx/lznJcXlbXjCIQhwFSlAbAvBX7oSjZ4pXTCJGPY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126384; c=relaxed/simple; bh=LN9sJF1ELuFamW2XwjLNaIq9pF5WelaQTpeGs6NP4RA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=etf8OreEEGR9lVaIvoqzZreXm6R94+vrq1ssvsaKOLvfHiw0nfpGFJHXBBXhfEtNidfxbeMpFPbmiu8Mi7LLQOCV5HiUIIdZlWBXYa8oqXmm+rrS3Y3cGkgEAzdTre4DDvgB9MRZtgV2c9olxSWzUYtaZuY4CTANobMFRO3kG9c= 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 4WWj1v63Zjzncnf; Sun, 28 Jul 2024 08:25:23 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id 174B51800A4; Sun, 28 Jul 2024 08:26:18 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:16 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 3/9] selftests/landlock: Support LANDLOCK_ACCESS_NET_LISTEN_TCP Date: Sun, 28 Jul 2024 08:25:56 +0800 Message-ID: <20240728002602.3198398-4-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC * Add listen_variant() to simplify listen(2) return code checking. * Rename test_bind_and_connect() to test_restricted_net_fixture(). * Extend current net rules with LANDLOCK_ACCESS_NET_LISTEN_TCP access. * Rename test port_specific.bind_connect_1023 to port_specific.port_1023. * Check little endian port restriction for listen in ipv4_tcp.port_endianness. * Some local renames and comment changes. Signed-off-by: Mikhail Ivanov --- tools/testing/selftests/landlock/net_test.c | 198 +++++++++++--------- 1 file changed, 107 insertions(+), 91 deletions(-) diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c index f21cfbbc3638..8126f5c0160f 100644 --- a/tools/testing/selftests/landlock/net_test.c +++ b/tools/testing/selftests/landlock/net_test.c @@ -2,7 +2,7 @@ /* * Landlock tests - Network * - * Copyright © 2022-2023 Huawei Tech. Co., Ltd. + * Copyright © 2022-2024 Huawei Tech. Co., Ltd. * Copyright © 2023 Microsoft Corporation */ @@ -22,6 +22,17 @@ #include "common.h" +/* clang-format off */ + +#define ACCESS_LAST LANDLOCK_ACCESS_NET_LISTEN_TCP + +#define ACCESS_ALL ( \ + LANDLOCK_ACCESS_NET_BIND_TCP | \ + LANDLOCK_ACCESS_NET_CONNECT_TCP | \ + LANDLOCK_ACCESS_NET_LISTEN_TCP) + +/* clang-format on */ + const short sock_port_start = (1 << 10); static const char loopback_ipv4[] = "127.0.0.1"; @@ -282,6 +293,16 @@ static int connect_variant(const int sock_fd, return connect_variant_addrlen(sock_fd, srv, get_addrlen(srv, false)); } +static int listen_variant(const int sock_fd, const int backlog) +{ + int ret; + + ret = listen(sock_fd, backlog); + if (ret < 0) + return -errno; + return ret; +} + FIXTURE(protocol) { struct service_fixture srv0, srv1, srv2, unspec_any0, unspec_srv0; @@ -438,9 +459,11 @@ FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_unix_datagram) { }, }; -static void test_bind_and_connect(struct __test_metadata *const _metadata, - const struct service_fixture *const srv, - const bool deny_bind, const bool deny_connect) +static void test_restricted_net_fixture(struct __test_metadata *const _metadata, + const struct service_fixture *const srv, + const bool deny_bind, + const bool deny_connect, + const bool deny_listen) { char buf = '\0'; int inval_fd, bind_fd, client_fd, status, ret; @@ -512,8 +535,14 @@ static void test_bind_and_connect(struct __test_metadata *const _metadata, EXPECT_EQ(0, ret); /* Creates a listening socket. */ - if (srv->protocol.type == SOCK_STREAM) - EXPECT_EQ(0, listen(bind_fd, backlog)); + if (srv->protocol.type == SOCK_STREAM) { + ret = listen_variant(bind_fd, backlog); + if (deny_listen) { + EXPECT_EQ(-EACCES, ret); + } else { + EXPECT_EQ(0, ret); + } + } } child = fork(); @@ -530,7 +559,7 @@ static void test_bind_and_connect(struct __test_metadata *const _metadata, ret = connect_variant(connect_fd, srv); if (deny_connect) { EXPECT_EQ(-EACCES, ret); - } else if (deny_bind) { + } else if (deny_bind || deny_listen) { /* No listening server. */ EXPECT_EQ(-ECONNREFUSED, ret); } else { @@ -545,7 +574,7 @@ static void test_bind_and_connect(struct __test_metadata *const _metadata, /* Accepts connection from the child. */ client_fd = bind_fd; - if (!deny_bind && !deny_connect) { + if (!deny_bind && !deny_connect && !deny_listen) { if (srv->protocol.type == SOCK_STREAM) { client_fd = accept(bind_fd, NULL, 0); ASSERT_LE(0, client_fd); @@ -571,16 +600,15 @@ TEST_F(protocol, bind) { if (variant->sandbox == TCP_SANDBOX) { const struct landlock_ruleset_attr ruleset_attr = { - .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + .handled_access_net = ACCESS_ALL, }; - const struct landlock_net_port_attr tcp_bind_connect_p0 = { - .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + const struct landlock_net_port_attr tcp_not_restricted_p0 = { + .allowed_access = ACCESS_ALL, .port = self->srv0.port, }; - const struct landlock_net_port_attr tcp_connect_p1 = { - .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, + const struct landlock_net_port_attr tcp_denied_bind_p1 = { + .allowed_access = ACCESS_ALL & + ~LANDLOCK_ACCESS_NET_BIND_TCP, .port = self->srv1.port, }; int ruleset_fd; @@ -589,48 +617,47 @@ TEST_F(protocol, bind) sizeof(ruleset_attr), 0); ASSERT_LE(0, ruleset_fd); - /* Allows connect and bind for the first port. */ + /* Allows all actions for the first port. */ ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, - &tcp_bind_connect_p0, 0)); + &tcp_not_restricted_p0, 0)); - /* Allows connect and denies bind for the second port. */ + /* Allows all actions despite bind. */ ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, - &tcp_connect_p1, 0)); + &tcp_denied_bind_p1, 0)); enforce_ruleset(_metadata, ruleset_fd); EXPECT_EQ(0, close(ruleset_fd)); } + bool restricted = is_restricted(&variant->prot, variant->sandbox); /* Binds a socket to the first port. */ - test_bind_and_connect(_metadata, &self->srv0, false, false); + test_restricted_net_fixture(_metadata, &self->srv0, false, false, + false); /* Binds a socket to the second port. */ - test_bind_and_connect(_metadata, &self->srv1, - is_restricted(&variant->prot, variant->sandbox), - false); + test_restricted_net_fixture(_metadata, &self->srv1, restricted, false, + false); /* Binds a socket to the third port. */ - test_bind_and_connect(_metadata, &self->srv2, - is_restricted(&variant->prot, variant->sandbox), - is_restricted(&variant->prot, variant->sandbox)); + test_restricted_net_fixture(_metadata, &self->srv2, restricted, + restricted, restricted); } TEST_F(protocol, connect) { if (variant->sandbox == TCP_SANDBOX) { const struct landlock_ruleset_attr ruleset_attr = { - .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + .handled_access_net = ACCESS_ALL, }; - const struct landlock_net_port_attr tcp_bind_connect_p0 = { - .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + const struct landlock_net_port_attr tcp_not_restricted_p0 = { + .allowed_access = ACCESS_ALL, .port = self->srv0.port, }; - const struct landlock_net_port_attr tcp_bind_p1 = { - .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + const struct landlock_net_port_attr tcp_denied_connect_p1 = { + .allowed_access = ACCESS_ALL & + ~LANDLOCK_ACCESS_NET_CONNECT_TCP, .port = self->srv1.port, }; int ruleset_fd; @@ -639,28 +666,27 @@ TEST_F(protocol, connect) sizeof(ruleset_attr), 0); ASSERT_LE(0, ruleset_fd); - /* Allows connect and bind for the first port. */ + /* Allows all actions for the first port. */ ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, - &tcp_bind_connect_p0, 0)); + &tcp_not_restricted_p0, 0)); - /* Allows bind and denies connect for the second port. */ + /* Allows all actions despite connect. */ ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, - &tcp_bind_p1, 0)); + &tcp_denied_connect_p1, 0)); enforce_ruleset(_metadata, ruleset_fd); EXPECT_EQ(0, close(ruleset_fd)); } - - test_bind_and_connect(_metadata, &self->srv0, false, false); - - test_bind_and_connect(_metadata, &self->srv1, false, - is_restricted(&variant->prot, variant->sandbox)); - - test_bind_and_connect(_metadata, &self->srv2, - is_restricted(&variant->prot, variant->sandbox), - is_restricted(&variant->prot, variant->sandbox)); + bool restricted = is_restricted(&variant->prot, variant->sandbox); + + test_restricted_net_fixture(_metadata, &self->srv0, false, false, + false); + test_restricted_net_fixture(_metadata, &self->srv1, false, restricted, + false); + test_restricted_net_fixture(_metadata, &self->srv2, restricted, + restricted, restricted); } TEST_F(protocol, bind_unspec) @@ -761,7 +787,7 @@ TEST_F(protocol, connect_unspec) ASSERT_LE(0, bind_fd); EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0)); if (self->srv0.protocol.type == SOCK_STREAM) - EXPECT_EQ(0, listen(bind_fd, backlog)); + EXPECT_EQ(0, listen_variant(bind_fd, backlog)); child = fork(); ASSERT_LE(0, child); @@ -1127,8 +1153,8 @@ TEST_F(tcp_layers, ruleset_overlap) * Forbids to connect to the socket because only one ruleset layer * allows connect. */ - test_bind_and_connect(_metadata, &self->srv0, false, - variant->num_layers >= 2); + test_restricted_net_fixture(_metadata, &self->srv0, false, + variant->num_layers >= 2, false); } TEST_F(tcp_layers, ruleset_expand) @@ -1208,11 +1234,12 @@ TEST_F(tcp_layers, ruleset_expand) EXPECT_EQ(0, close(ruleset_fd)); } - test_bind_and_connect(_metadata, &self->srv0, false, - variant->num_layers >= 3); + test_restricted_net_fixture(_metadata, &self->srv0, false, + variant->num_layers >= 3, false); - test_bind_and_connect(_metadata, &self->srv1, variant->num_layers >= 1, - variant->num_layers >= 2); + test_restricted_net_fixture(_metadata, &self->srv1, + variant->num_layers >= 1, + variant->num_layers >= 2, false); } /* clang-format off */ @@ -1230,16 +1257,6 @@ FIXTURE_TEARDOWN(mini) { } -/* clang-format off */ - -#define ACCESS_LAST LANDLOCK_ACCESS_NET_CONNECT_TCP - -#define ACCESS_ALL ( \ - LANDLOCK_ACCESS_NET_BIND_TCP | \ - LANDLOCK_ACCESS_NET_CONNECT_TCP) - -/* clang-format on */ - TEST_F(mini, network_access_rights) { const struct landlock_ruleset_attr ruleset_attr = { @@ -1454,8 +1471,9 @@ TEST_F(mini, tcp_port_overflow) enforce_ruleset(_metadata, ruleset_fd); - test_bind_and_connect(_metadata, &srv_denied, true, true); - test_bind_and_connect(_metadata, &srv_max_allowed, false, false); + test_restricted_net_fixture(_metadata, &srv_denied, true, true, false); + test_restricted_net_fixture(_metadata, &srv_max_allowed, false, false, + false); } FIXTURE(ipv4_tcp) @@ -1485,22 +1503,21 @@ FIXTURE_TEARDOWN(ipv4_tcp) TEST_F(ipv4_tcp, port_endianness) { const struct landlock_ruleset_attr ruleset_attr = { - .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + .handled_access_net = ACCESS_ALL, }; const struct landlock_net_port_attr bind_host_endian_p0 = { .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, /* Host port format. */ .port = self->srv0.port, }; - const struct landlock_net_port_attr connect_big_endian_p0 = { - .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, + const struct landlock_net_port_attr connect_listen_big_endian_p0 = { + .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP | + LANDLOCK_ACCESS_NET_LISTEN_TCP, /* Big endian port format. */ .port = htons(self->srv0.port), }; - const struct landlock_net_port_attr bind_connect_host_endian_p1 = { - .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + const struct landlock_net_port_attr not_restricted_host_endian_p1 = { + .allowed_access = ACCESS_ALL, /* Host port format. */ .port = self->srv1.port, }; @@ -1514,16 +1531,18 @@ TEST_F(ipv4_tcp, port_endianness) ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, &bind_host_endian_p0, 0)); ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, - &connect_big_endian_p0, 0)); + &connect_listen_big_endian_p0, 0)); ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, - &bind_connect_host_endian_p1, 0)); + ¬_restricted_host_endian_p1, 0)); enforce_ruleset(_metadata, ruleset_fd); /* No restriction for big endinan CPU. */ - test_bind_and_connect(_metadata, &self->srv0, false, little_endian); + test_restricted_net_fixture(_metadata, &self->srv0, false, + little_endian, little_endian); /* No restriction for any CPU. */ - test_bind_and_connect(_metadata, &self->srv1, false, false); + test_restricted_net_fixture(_metadata, &self->srv1, false, false, + false); } TEST_F(ipv4_tcp, with_fs) @@ -1691,7 +1710,7 @@ TEST_F(port_specific, bind_connect_zero) ret = bind_variant(bind_fd, &self->srv0); EXPECT_EQ(0, ret); - EXPECT_EQ(0, listen(bind_fd, backlog)); + EXPECT_EQ(0, listen_variant(bind_fd, backlog)); /* Connects on port 0. */ ret = connect_variant(connect_fd, &self->srv0); @@ -1714,26 +1733,23 @@ TEST_F(port_specific, bind_connect_zero) EXPECT_EQ(0, close(bind_fd)); } -TEST_F(port_specific, bind_connect_1023) +TEST_F(port_specific, port_1023) { int bind_fd, connect_fd, ret; - /* Adds a rule layer with bind and connect actions. */ + /* Adds a rule layer with all actions. */ if (variant->sandbox == TCP_SANDBOX) { const struct landlock_ruleset_attr ruleset_attr = { - .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP + .handled_access_net = ACCESS_ALL }; /* A rule with port value less than 1024. */ - const struct landlock_net_port_attr tcp_bind_connect_low_range = { - .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + const struct landlock_net_port_attr tcp_low_range_port = { + .allowed_access = ACCESS_ALL, .port = 1023, }; /* A rule with 1024 port. */ - const struct landlock_net_port_attr tcp_bind_connect = { - .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + const struct landlock_net_port_attr tcp_port_1024 = { + .allowed_access = ACCESS_ALL, .port = 1024, }; int ruleset_fd; @@ -1744,10 +1760,10 @@ TEST_F(port_specific, bind_connect_1023) ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, - &tcp_bind_connect_low_range, 0)); + &tcp_low_range_port, 0)); ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, - &tcp_bind_connect, 0)); + &tcp_port_1024, 0)); enforce_ruleset(_metadata, ruleset_fd); EXPECT_EQ(0, close(ruleset_fd)); @@ -1771,7 +1787,7 @@ TEST_F(port_specific, bind_connect_1023) ret = bind_variant(bind_fd, &self->srv0); clear_cap(_metadata, CAP_NET_BIND_SERVICE); EXPECT_EQ(0, ret); - EXPECT_EQ(0, listen(bind_fd, backlog)); + EXPECT_EQ(0, listen_variant(bind_fd, backlog)); /* Connects on the binded port 1023. */ ret = connect_variant(connect_fd, &self->srv0); @@ -1791,7 +1807,7 @@ TEST_F(port_specific, bind_connect_1023) /* Binds on port 1024. */ ret = bind_variant(bind_fd, &self->srv0); EXPECT_EQ(0, ret); - EXPECT_EQ(0, listen(bind_fd, backlog)); + EXPECT_EQ(0, listen_variant(bind_fd, backlog)); /* Connects on the binded port 1024. */ ret = connect_variant(connect_fd, &self->srv0); From patchwork Sun Jul 28 00:25:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743810 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 4887910FF; Sun, 28 Jul 2024 00:26:21 +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=1722126384; cv=none; b=dyy3nRla73IatKWn4i2gqvjKiyTyBFT3aljmv6Gdw6AvSqIgbjRuEvMkjhAJPSk5vYm/cz8AWulBjnR2DZDAUf5jndJD4+JX/kH6vVpazkjOQfpwSneoI2JXUDh3tGIpWGfPsd9HjIhc9+J4Fn4hPupTlLraHpGiEl0wMR+2tdM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126384; c=relaxed/simple; bh=T1d68LYJQ5PF2V9H1ruSPor7SPuyYu1pjOYSMUxNP3E=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=o+VSmNxg5wamADr5kPfEy1BEoRz0n3V9iiAfEKzMukXN0etywf6FDcg907okjm1qkamJJc92Zo52ivN/jRz6VPRM1vid7YDabKp1NR1HNwmJ152CuQVe8Xwxc5s3ost6Kd8ooF9bze69mvzy0HFU8bpP6Tgij11jBHBzv0qOuuw= 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 4WWj1x3rqDzncqF; Sun, 28 Jul 2024 08:25:25 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id C15891800A4; Sun, 28 Jul 2024 08:26:19 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:18 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 4/9] selftests/landlock: Test listening restriction Date: Sun, 28 Jul 2024 08:25:57 +0800 Message-ID: <20240728002602.3198398-5-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC Add a test for listening restriction. It's similar to protocol.bind and protocol.connect tests. Signed-off-by: Mikhail Ivanov --- tools/testing/selftests/landlock/net_test.c | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c index 8126f5c0160f..b6fe9bde205f 100644 --- a/tools/testing/selftests/landlock/net_test.c +++ b/tools/testing/selftests/landlock/net_test.c @@ -689,6 +689,50 @@ TEST_F(protocol, connect) restricted, restricted); } +TEST_F(protocol, listen) +{ + if (variant->sandbox == TCP_SANDBOX) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = ACCESS_ALL, + }; + const struct landlock_net_port_attr tcp_not_restricted_p0 = { + .allowed_access = ACCESS_ALL, + .port = self->srv0.port, + }; + const struct landlock_net_port_attr tcp_denied_listen_p1 = { + .allowed_access = ACCESS_ALL & + ~LANDLOCK_ACCESS_NET_LISTEN_TCP, + .port = self->srv1.port, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Allows all actions for the first port. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_not_restricted_p0, 0)); + + /* Allows all actions despite listen. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_denied_listen_p1, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + bool restricted = is_restricted(&variant->prot, variant->sandbox); + + test_restricted_net_fixture(_metadata, &self->srv0, false, false, + false); + test_restricted_net_fixture(_metadata, &self->srv1, false, false, + restricted); + test_restricted_net_fixture(_metadata, &self->srv2, restricted, + restricted, restricted); +} + TEST_F(protocol, bind_unspec) { const struct landlock_ruleset_attr ruleset_attr = { From patchwork Sun Jul 28 00:25:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743812 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 B937C1388; Sun, 28 Jul 2024 00:26:23 +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=1722126386; cv=none; b=UsGY5Dc8yQGU4j0zqjXWFUV0VoWkBFvGwReo0iUe8oyiDg35fJAC/2xf9SpJ80osy7PYS0yVtUdjcaqUBHWX5dRjlGrULOTK/lSGnfAt4PElaRYhFrki7xUUX5sGbtiNB3djQoUh5B9fvfCcvtZ7xblgARIK6gyMmZL89RZltSA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126386; c=relaxed/simple; bh=gyfT3CWwUD9Frt4iGtfnezH1VGZQ1U3LrKCn+H6YLZo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SvlsJHCzsKWXhur1fcqI9t7VWyNaN97LPUnv6+BDo3vnZnNvu3X7fS2wjV7hAKlmGRPjtI0YUOxiqM/Mw+1teXrOjKfaWbfgXyowgUMmh2IYAnr3nPTr2XtyZeWU8MUBxAl8N/Z029MkXnEw0KW3eCKXnsvK4gAUah54L1ZYL2k= 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.162.254]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4WWj2t3F34zxVYc; Sun, 28 Jul 2024 08:26:14 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id 87E8D1800D0; Sun, 28 Jul 2024 08:26:21 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:19 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 5/9] selftests/landlock: Test listen on connected socket Date: Sun, 28 Jul 2024 08:25:58 +0800 Message-ID: <20240728002602.3198398-6-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC Test checks that listen(2) doesn't wrongfully return -EACCES instead of -EINVAL when trying to listen for an incorrect socket state. Signed-off-by: Mikhail Ivanov --- tools/testing/selftests/landlock/net_test.c | 65 +++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c index b6fe9bde205f..a8385f1373f6 100644 --- a/tools/testing/selftests/landlock/net_test.c +++ b/tools/testing/selftests/landlock/net_test.c @@ -1644,6 +1644,71 @@ TEST_F(ipv4_tcp, with_fs) EXPECT_EQ(-EACCES, bind_variant(bind_fd, &self->srv1)); } +TEST_F(ipv4_tcp, listen_on_connected) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = ACCESS_ALL, + }; + const struct landlock_net_port_attr tcp_not_restricted_p0 = { + .allowed_access = ACCESS_ALL, + .port = self->srv0.port, + }; + const struct landlock_net_port_attr tcp_denied_listen_p1 = { + .allowed_access = ACCESS_ALL & ~LANDLOCK_ACCESS_NET_LISTEN_TCP, + .port = self->srv1.port, + }; + int ruleset_fd; + int bind_fd, status; + pid_t child; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Allows all actions for the first port. */ + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_not_restricted_p0, 0)); + + /* Deny listen for the second port. */ + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_denied_listen_p1, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + + /* Init listening socket. */ + bind_fd = socket_variant(&self->srv0); + ASSERT_LE(0, bind_fd); + EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0)); + EXPECT_EQ(0, listen_variant(bind_fd, backlog)); + + child = fork(); + ASSERT_LE(0, child); + if (child == 0) { + int connect_fd; + + /* Closes listening socket for the child. */ + EXPECT_EQ(0, close(bind_fd)); + + connect_fd = socket_variant(&self->srv1); + ASSERT_LE(0, connect_fd); + EXPECT_EQ(0, connect_variant(connect_fd, &self->srv0)); + + /* Tries to listen on connected socket. */ + EXPECT_EQ(-EINVAL, listen_variant(connect_fd, backlog)); + + EXPECT_EQ(0, close(connect_fd)); + _exit(_metadata->exit_code); + return; + } + + EXPECT_EQ(child, waitpid(child, &status, 0)); + EXPECT_EQ(1, WIFEXITED(status)); + EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + EXPECT_EQ(0, close(bind_fd)); +} + FIXTURE(port_specific) { struct service_fixture srv0; From patchwork Sun Jul 28 00:25:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743814 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 6C9A1B676; Sun, 28 Jul 2024 00:26:25 +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=1722126388; cv=none; b=EwkH3lA8JtlLwVJCgJfLwyMDhW3sLV7i0de8hoI4pCQ2RSWUPSePeVl+VjAYZiFEhpqs3JgmX1YMaIryYvj2DP/VrYgOsIFQMyFqY5d/Z0zjn5BRBzwJeDAioInYyKLa8glGi57OivIpckFC/+txz4QPXZ1QunuvrxOqiaoepQg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126388; c=relaxed/simple; bh=sbsAmMH2Do9sbVqtKEAT3otrqWu0IWd9rsy6FrLSOhY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ap1AQkKw86Q+sCoiGynjhw+9kqe/gX9usRp/iKlnv8OkLgl8BDJRVG8ENTL0kIuJrTgnFALkcT9+4xSMreaPlsYOJBa3KeEOf2UQog2wG3dj4KJCxBXpZOryWB7KayexNJVrsgbevNAuKGOjKGrc+aJlL6vRUsnDVgLuEf+he5s= 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.163.252]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4WWj2w3xzGz1L9Cq; Sun, 28 Jul 2024 08:26:16 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id 5A2B41800A4; Sun, 28 Jul 2024 08:26:23 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:21 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 6/9] selftests/landlock: Test listening without explicit bind restriction Date: Sun, 28 Jul 2024 08:25:59 +0800 Message-ID: <20240728002602.3198398-7-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC Test scenarios where listen(2) call without explicit bind(2) is allowed and forbidden. Signed-off-by: Mikhail Ivanov --- tools/testing/selftests/landlock/net_test.c | 83 +++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c index a8385f1373f6..1a4c4d1cabc2 100644 --- a/tools/testing/selftests/landlock/net_test.c +++ b/tools/testing/selftests/landlock/net_test.c @@ -1842,6 +1842,89 @@ TEST_F(port_specific, bind_connect_zero) EXPECT_EQ(0, close(bind_fd)); } +TEST_F(port_specific, listen_without_bind_allowed) +{ + if (variant->sandbox == TCP_SANDBOX) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_LISTEN_TCP + }; + const struct landlock_net_port_attr tcp_listen_zero = { + .allowed_access = LANDLOCK_ACCESS_NET_LISTEN_TCP, + .port = 0, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* + * Allow listening without explicit bind + * (cf. landlock_net_port_attr). + */ + EXPECT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_listen_zero, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + int listen_fd, connect_fd; + __u64 port; + + listen_fd = socket_variant(&self->srv0); + ASSERT_LE(0, listen_fd); + + connect_fd = socket_variant(&self->srv0); + ASSERT_LE(0, connect_fd); + /* + * Allow listen(2) to select a random port for the socket, + * since bind(2) wasn't called. + */ + EXPECT_EQ(0, listen_variant(listen_fd, backlog)); + + /* Connects on the binded port. */ + port = get_binded_port(listen_fd, &variant->prot); + EXPECT_NE(0, port); + set_port(&self->srv0, port); + EXPECT_EQ(0, connect_variant(connect_fd, &self->srv0)); + + EXPECT_EQ(0, close(connect_fd)); + EXPECT_EQ(0, close(listen_fd)); +} + +TEST_F(port_specific, listen_without_bind_denied) +{ + if (variant->sandbox == TCP_SANDBOX) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_LISTEN_TCP + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Deny listening. */ + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + int listen_fd, ret; + + listen_fd = socket_variant(&self->srv0); + ASSERT_LE(0, listen_fd); + + /* Checks that listening without explicit binding is prohibited. */ + ret = listen_variant(listen_fd, backlog); + if (is_restricted(&variant->prot, variant->sandbox)) { + /* Denied by Landlock. */ + EXPECT_EQ(-EACCES, ret); + } else { + EXPECT_EQ(0, ret); + } +} + TEST_F(port_specific, port_1023) { int bind_fd, connect_fd, ret; From patchwork Sun Jul 28 00:26:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743815 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 76229EEC0; Sun, 28 Jul 2024 00:26:27 +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=1722126389; cv=none; b=UlfhRh+aAWpn8Uf+9YgAXQ/SH2F9NccuKoqSkxLJaVLME+0IsVEEBiXx2sxlump/qZNHYOk7M57c8tmIcroM1OlD8UcJfhPeK8aMKj3c9cBAg69A5SRc7b52zQYaLunE9qZeGoXm0Po1ORJeUqkdKCiZcW3LBDnB1HX86ydWu80= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126389; c=relaxed/simple; bh=1Lw7jRXd2Z4jblu4O847A7DBHGOXTkU5W9yFUphZv6c=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HrvXbjZ5iArpiCoWMQUibNc0ZtTtMYz51vC0ZBu8mDZ0yw7WdfHcIEDlUqD0cxgeaPa2nL2Ov0WOZlX2KezldzXiCis6rlMzVxAmKJ63av7TeEhBSG24t4TX/u7W/owSIgQGOb4tiT0kJk2bnV4jDVkNhwDmHFXj9c25wDnGyn0= 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.162.254]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4WWhxQ4QnGzyNqG; Sun, 28 Jul 2024 08:21:30 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id 2D2CC1800D0; Sun, 28 Jul 2024 08:26:25 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:23 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 7/9] selftests/landlock: Test listen on ULP socket without clone method Date: Sun, 28 Jul 2024 08:26:00 +0800 Message-ID: <20240728002602.3198398-8-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC Test checks that listen(2) doesn't wrongfully return -EACCES instead of -EINVAL when trying to listen on a socket which is set to ULP that doesn't have clone method in inet_csk(sk)->icsk_ulp_ops (espintcp). Signed-off-by: Mikhail Ivanov --- tools/testing/selftests/landlock/config | 1 + tools/testing/selftests/landlock/net_test.c | 38 +++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/tools/testing/selftests/landlock/config b/tools/testing/selftests/landlock/config index 0086efaa7b68..014401fe6114 100644 --- a/tools/testing/selftests/landlock/config +++ b/tools/testing/selftests/landlock/config @@ -12,3 +12,4 @@ CONFIG_SHMEM=y CONFIG_SYSFS=y CONFIG_TMPFS=y CONFIG_TMPFS_XATTR=y +CONFIG_INET_ESPINTCP=y \ No newline at end of file diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c index 1a4c4d1cabc2..caf5f38996ed 100644 --- a/tools/testing/selftests/landlock/net_test.c +++ b/tools/testing/selftests/landlock/net_test.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1709,6 +1710,43 @@ TEST_F(ipv4_tcp, listen_on_connected) EXPECT_EQ(0, close(bind_fd)); } +TEST_F(ipv4_tcp, espintcp_listen) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = ACCESS_ALL, + }; + const struct landlock_net_port_attr tcp_denied_listen_p0 = { + .allowed_access = ACCESS_ALL & ~LANDLOCK_ACCESS_NET_LISTEN_TCP, + .port = self->srv0.port, + }; + int ruleset_fd; + int listen_fd; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Deny listen. */ + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_denied_listen_p0, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + + listen_fd = socket_variant(&self->srv0); + ASSERT_LE(0, listen_fd); + + /* Set espintcp ULP. */ + EXPECT_EQ(0, setsockopt(listen_fd, IPPROTO_TCP, TCP_ULP, "espintcp", + sizeof("espintcp"))); + + EXPECT_EQ(0, bind_variant(listen_fd, &self->srv0)); + + /* Espintcp ULP doesn't have clone method, so listen is denied. */ + EXPECT_EQ(-EINVAL, listen_variant(listen_fd, backlog)); + EXPECT_EQ(0, close(listen_fd)); +} + FIXTURE(port_specific) { struct service_fixture srv0; From patchwork Sun Jul 28 00:26:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743816 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 12C0C17BA1; Sun, 28 Jul 2024 00:26:28 +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=1722126391; cv=none; b=e1cEywJ5Tar9CCNdr7uTjzJ+QkTXBPDaGLn5BI99wY7oG/4rnDGXguYqgGxhxeonbNu+U/KvOToZGV/tfPXMeHVUXLJCC5TfnGCqWaBaJFtEBZ6GIJ1FmzA174Nwui3exqtfH/r40ofTCcUOEmloZ+6c2QP330c1zQe39j651sg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126391; c=relaxed/simple; bh=VrJ239tW2DJaSArHyYIINEr9yioxZR92psI9DPag0cs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dUkxNsgcLE8HGJBohUmG597mSEeyLYKCKuaNot2Rixix6g1h1MxRJ7rgdh856I2+5S/ndKV/PDRd8jJkoWePd1zD01tIMBhTpNgM9csVP6Bse5H35qXTYXVt1ZllCzi0FAm8sGrKPMcjPFjNPerKmQ8pDecLX0fySq4zAyZdvn4= 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.252]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4WWhxS21vmzyNfn; Sun, 28 Jul 2024 08:21:32 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id CEE781800A4; Sun, 28 Jul 2024 08:26:26 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:25 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 8/9] selftests/landlock: Test changing socket backlog with listen(2) Date: Sun, 28 Jul 2024 08:26:01 +0800 Message-ID: <20240728002602.3198398-9-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC listen(2) can be used to change length of the pending connections queue of the listening socket. Such scenario shouldn't be restricted by Landlock since socket doesn't change its state. * Implement test that validates this case. Signed-off-by: Mikhail Ivanov --- tools/testing/selftests/landlock/net_test.c | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c index caf5f38996ed..31ab7e7442e4 100644 --- a/tools/testing/selftests/landlock/net_test.c +++ b/tools/testing/selftests/landlock/net_test.c @@ -1747,6 +1747,32 @@ TEST_F(ipv4_tcp, espintcp_listen) EXPECT_EQ(0, close(listen_fd)); } +TEST_F(ipv4_tcp, double_listen) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_LISTEN_TCP, + }; + int ruleset_fd; + int listen_fd; + + listen_fd = socket_variant(&self->srv0); + ASSERT_LE(0, listen_fd); + + EXPECT_EQ(0, bind_variant(listen_fd, &self->srv0)); + EXPECT_EQ(0, listen_variant(listen_fd, backlog)); + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Denies listen. */ + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + + /* Tries to change backlog value of listening socket. */ + EXPECT_EQ(0, listen_variant(listen_fd, backlog + 1)); +} + FIXTURE(port_specific) { struct service_fixture srv0; From patchwork Sun Jul 28 00:26:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Ivanov X-Patchwork-Id: 13743817 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 ADC661E519; Sun, 28 Jul 2024 00:26:30 +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=1722126392; cv=none; b=sx8UEU2SUOjd2Ll8TlRHXDATthz+jcMIOMcKwaOL+2FvIZw8UMaW+8ZvV0rUgZVUmjtuNWLeFK7u4z6XD5z1H6PKR7Ymf1hVAvdarwes6t8vzJIiWfVxp8SYiKhcppEi8sUarrPvgi1A3uy9HtXgYSYg7+vuFVONpdPQS69cQjQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722126392; c=relaxed/simple; bh=rSiJD6CB325ZcboYhNJAZRZM+QHB/FdTNMAAaT83eAE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aH4HOGxsB8cTLNVa0mMiIT/t86bEDcvWZtNHRW26Q4pu3m7P5Zq56j549STVH2hb9yiULJ9YkZ8yRYTGK1JaxCfynZv2NhV/X+XZnJxR0PYEShR3gcq8pxLHfosgOcoGDuWGMCJ84swUE13F7yeP2u9Qp50254J4vPPwlCHJYQQ= 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 4WWj313BXCzxVXS; Sun, 28 Jul 2024 08:26:21 +0800 (CST) Received: from dggpemm500020.china.huawei.com (unknown [7.185.36.49]) by mail.maildlp.com (Postfix) with ESMTPS id 856FB180064; Sun, 28 Jul 2024 08:26:28 +0800 (CST) Received: from mscphis02103.huawei.com (10.123.65.215) by dggpemm500020.china.huawei.com (7.185.36.49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Sun, 28 Jul 2024 08:26:26 +0800 From: Mikhail Ivanov To: CC: , , , , , , , Subject: [RFC PATCH v1 9/9] samples/landlock: Support LANDLOCK_ACCESS_NET_LISTEN Date: Sun, 28 Jul 2024 08:26:02 +0800 Message-ID: <20240728002602.3198398-10-ivanov.mikhail1@huawei-partners.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> References: <20240728002602.3198398-1-ivanov.mikhail1@huawei-partners.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: mscpeml100004.china.huawei.com (7.188.51.133) To dggpemm500020.china.huawei.com (7.185.36.49) X-Patchwork-State: RFC Extend sample with TCP listen control logic. Signed-off-by: Mikhail Ivanov --- samples/landlock/sandboxer.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c index e8223c3e781a..3f50cb3f8039 100644 --- a/samples/landlock/sandboxer.c +++ b/samples/landlock/sandboxer.c @@ -55,6 +55,7 @@ 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_TCP_LISTEN_NAME "LL_TCP_LISTEN" #define ENV_DELIMITER ":" static int parse_path(char *env_path, const char ***const path_list) @@ -208,7 +209,7 @@ 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) { @@ -222,15 +223,16 @@ int main(const int argc, char *const argv[], char *const *const envp) struct landlock_ruleset_attr ruleset_attr = { .handled_access_fs = access_fs_rw, .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | - LANDLOCK_ACCESS_NET_CONNECT_TCP, + LANDLOCK_ACCESS_NET_CONNECT_TCP | + LANDLOCK_ACCESS_NET_LISTEN_TCP, }; 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_TCP_LISTEN_NAME, argv[0]); fprintf(stderr, "Execute a command in a restricted environment.\n\n"); fprintf(stderr, @@ -251,15 +253,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 ports allowed to listen (server).\n", + ENV_TCP_LISTEN_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=\"9418\" " "%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_TCP_LISTEN_NAME, argv[0]); fprintf(stderr, "This sandboxer can use Landlock features " "up to ABI version %d.\n", @@ -326,6 +332,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 LANDLOCK_ACCESS_NET_LISTEN support for ABI < 6 */ + ruleset_attr.handled_access_net &= + ~(LANDLOCK_ACCESS_NET_LISTEN_TCP); fprintf(stderr, "Hint: You should update the running kernel " @@ -357,6 +368,12 @@ int main(const int argc, char *const argv[], char *const *const envp) ruleset_attr.handled_access_net &= ~LANDLOCK_ACCESS_NET_CONNECT_TCP; } + /* Removes listen access attribute if not supported by a user. */ + env_port_name = getenv(ENV_TCP_LISTEN_NAME); + if (!env_port_name) { + ruleset_attr.handled_access_net &= + ~LANDLOCK_ACCESS_NET_LISTEN_TCP; + } ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); @@ -380,6 +397,10 @@ int main(const int argc, char *const argv[], char *const *const envp) LANDLOCK_ACCESS_NET_CONNECT_TCP)) { goto err_close_ruleset; } + if (populate_ruleset_net(ENV_TCP_LISTEN_NAME, ruleset_fd, + LANDLOCK_ACCESS_NET_LISTEN_TCP)) { + goto err_close_ruleset; + } if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { perror("Failed to restrict privileges");