Merge tag 'landlock-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux

Pull landlock fixes from Mickaël Salaün:
"This fixes TCP handling, tests, documentation, non-audit elided code,
and minor cosmetic changes"

* tag 'landlock-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux:
landlock: Clarify documentation for the IOCTL access right
selftests/landlock: Properly close a file descriptor
landlock: Improve the comment for domain_is_scoped
selftests/landlock: Use scoped_base_variants.h for ptrace_test
selftests/landlock: Fix missing semicolon
selftests/landlock: Fix typo in fs_test
landlock: Optimize stack usage when !CONFIG_AUDIT
landlock: Fix spelling
landlock: Clean up hook_ptrace_access_check()
landlock: Improve erratum documentation
landlock: Remove useless include
landlock: Fix wrong type usage
selftests/landlock: NULL-terminate unix pathname addresses
selftests/landlock: Remove invalid unix socket bind()
selftests/landlock: Add missing connect(minimal AF_UNSPEC) test
selftests/landlock: Fix TCP bind(AF_UNSPEC) test case
landlock: Fix TCP handling of short AF_UNSPEC addresses
landlock: Fix formatting

+170 -269
+17 -20
include/uapi/linux/landlock.h
··· 216 216 * :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with 217 217 * ``O_TRUNC``. This access right is available since the third version of the 218 218 * Landlock ABI. 219 + * - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened 220 + * character or block device. 221 + * 222 + * This access right applies to all `ioctl(2)` commands implemented by device 223 + * drivers. However, the following common IOCTL commands continue to be 224 + * invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right: 225 + * 226 + * * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``), 227 + * * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``), 228 + * * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``, 229 + * ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``) 230 + * * Some IOCTL commands which do not make sense when used with devices, but 231 + * whose implementations are safe and return the right error codes 232 + * (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``) 233 + * 234 + * This access right is available since the fifth version of the Landlock 235 + * ABI. 219 236 * 220 237 * Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used 221 238 * with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as ··· 291 274 * 292 275 * If multiple requirements are not met, the ``EACCES`` error code takes 293 276 * precedence over ``EXDEV``. 294 - * 295 - * The following access right applies both to files and directories: 296 - * 297 - * - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened 298 - * character or block device. 299 - * 300 - * This access right applies to all `ioctl(2)` commands implemented by device 301 - * drivers. However, the following common IOCTL commands continue to be 302 - * invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right: 303 - * 304 - * * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``), 305 - * * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``), 306 - * * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``, 307 - * ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``) 308 - * * Some IOCTL commands which do not make sense when used with devices, but 309 - * whose implementations are safe and return the right error codes 310 - * (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``) 311 - * 312 - * This access right is available since the fifth version of the Landlock 313 - * ABI. 314 277 * 315 278 * .. warning:: 316 279 *
+1 -1
security/landlock/audit.c
··· 191 191 long youngest_layer = -1; 192 192 193 193 for_each_set_bit(access_bit, &access_req, layer_masks_size) { 194 - const access_mask_t mask = (*layer_masks)[access_bit]; 194 + const layer_mask_t mask = (*layer_masks)[access_bit]; 195 195 long layer; 196 196 197 197 if (!mask)
+1 -1
security/landlock/domain.h
··· 97 97 */ 98 98 atomic64_t num_denials; 99 99 /** 100 - * @id: Landlock domain ID, sets once at domain creation time. 100 + * @id: Landlock domain ID, set once at domain creation time. 101 101 */ 102 102 u64 id; 103 103 /**
+1 -1
security/landlock/errata/abi-6.h
··· 9 9 * This fix addresses an issue where signal scoping was overly restrictive, 10 10 * preventing sandboxed threads from signaling other threads within the same 11 11 * process if they belonged to different domains. Because threads are not 12 - * security boundaries, user space might assume that any thread within the same 12 + * security boundaries, user space might assume that all threads within the same 13 13 * process can send signals between themselves (see :manpage:`nptl(7)` and 14 14 * :manpage:`libpsx(3)`). Consistent with :manpage:`ptrace(2)` behavior, direct 15 15 * interaction between threads of the same process should always be allowed.
+11 -3
security/landlock/fs.c
··· 939 939 } 940 940 path_put(&walker_path); 941 941 942 - if (!allowed_parent1) { 942 + /* 943 + * Check CONFIG_AUDIT to enable elision of log_request_parent* and 944 + * associated caller's stack variables thanks to dead code elimination. 945 + */ 946 + #ifdef CONFIG_AUDIT 947 + if (!allowed_parent1 && log_request_parent1) { 943 948 log_request_parent1->type = LANDLOCK_REQUEST_FS_ACCESS; 944 949 log_request_parent1->audit.type = LSM_AUDIT_DATA_PATH; 945 950 log_request_parent1->audit.u.path = *path; ··· 954 949 ARRAY_SIZE(*layer_masks_parent1); 955 950 } 956 951 957 - if (!allowed_parent2) { 952 + if (!allowed_parent2 && log_request_parent2) { 958 953 log_request_parent2->type = LANDLOCK_REQUEST_FS_ACCESS; 959 954 log_request_parent2->audit.type = LSM_AUDIT_DATA_PATH; 960 955 log_request_parent2->audit.u.path = *path; ··· 963 958 log_request_parent2->layer_masks_size = 964 959 ARRAY_SIZE(*layer_masks_parent2); 965 960 } 961 + #endif /* CONFIG_AUDIT */ 962 + 966 963 return allowed_parent1 && allowed_parent2; 967 964 } 968 965 ··· 1321 1314 * second call to iput() for the same Landlock object. Also 1322 1315 * checks I_NEW because such inode cannot be tied to an object. 1323 1316 */ 1324 - if (inode_state_read(inode) & (I_FREEING | I_WILL_FREE | I_NEW)) { 1317 + if (inode_state_read(inode) & 1318 + (I_FREEING | I_WILL_FREE | I_NEW)) { 1325 1319 spin_unlock(&inode->i_lock); 1326 1320 continue; 1327 1321 }
+67 -51
security/landlock/net.c
··· 71 71 72 72 switch (address->sa_family) { 73 73 case AF_UNSPEC: 74 + if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 75 + /* 76 + * Connecting to an address with AF_UNSPEC dissolves 77 + * the TCP association, which have the same effect as 78 + * closing the connection while retaining the socket 79 + * object (i.e., the file descriptor). As for dropping 80 + * privileges, closing connections is always allowed. 81 + * 82 + * For a TCP access control system, this request is 83 + * legitimate. Let the network stack handle potential 84 + * inconsistencies and return -EINVAL if needed. 85 + */ 86 + return 0; 87 + } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 88 + /* 89 + * Binding to an AF_UNSPEC address is treated 90 + * differently by IPv4 and IPv6 sockets. The socket's 91 + * family may change under our feet due to 92 + * setsockopt(IPV6_ADDRFORM), but that's ok: we either 93 + * reject entirely or require 94 + * %LANDLOCK_ACCESS_NET_BIND_TCP for the given port, so 95 + * it cannot be used to bypass the policy. 96 + * 97 + * IPv4 sockets map AF_UNSPEC to AF_INET for 98 + * retrocompatibility for bind accesses, only if the 99 + * address is INADDR_ANY (cf. __inet_bind). IPv6 100 + * sockets always reject it. 101 + * 102 + * Checking the address is required to not wrongfully 103 + * return -EACCES instead of -EAFNOSUPPORT or -EINVAL. 104 + * We could return 0 and let the network stack handle 105 + * these checks, but it is safer to return a proper 106 + * error and test consistency thanks to kselftest. 107 + */ 108 + if (sock->sk->__sk_common.skc_family == AF_INET) { 109 + const struct sockaddr_in *const sockaddr = 110 + (struct sockaddr_in *)address; 111 + 112 + if (addrlen < sizeof(struct sockaddr_in)) 113 + return -EINVAL; 114 + 115 + if (sockaddr->sin_addr.s_addr != 116 + htonl(INADDR_ANY)) 117 + return -EAFNOSUPPORT; 118 + } else { 119 + if (addrlen < SIN6_LEN_RFC2133) 120 + return -EINVAL; 121 + else 122 + return -EAFNOSUPPORT; 123 + } 124 + } else { 125 + WARN_ON_ONCE(1); 126 + } 127 + /* Only for bind(AF_UNSPEC+INADDR_ANY) on IPv4 socket. */ 128 + fallthrough; 74 129 case AF_INET: { 75 130 const struct sockaddr_in *addr4; 76 131 ··· 174 119 return 0; 175 120 } 176 121 177 - /* Specific AF_UNSPEC handling. */ 178 - if (address->sa_family == AF_UNSPEC) { 179 - /* 180 - * Connecting to an address with AF_UNSPEC dissolves the TCP 181 - * association, which have the same effect as closing the 182 - * connection while retaining the socket object (i.e., the file 183 - * descriptor). As for dropping privileges, closing 184 - * connections is always allowed. 185 - * 186 - * For a TCP access control system, this request is legitimate. 187 - * Let the network stack handle potential inconsistencies and 188 - * return -EINVAL if needed. 189 - */ 190 - if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) 191 - return 0; 192 - 193 - /* 194 - * For compatibility reason, accept AF_UNSPEC for bind 195 - * accesses (mapped to AF_INET) only if the address is 196 - * INADDR_ANY (cf. __inet_bind). Checking the address is 197 - * required to not wrongfully return -EACCES instead of 198 - * -EAFNOSUPPORT. 199 - * 200 - * We could return 0 and let the network stack handle these 201 - * checks, but it is safer to return a proper error and test 202 - * consistency thanks to kselftest. 203 - */ 204 - if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 205 - /* addrlen has already been checked for AF_UNSPEC. */ 206 - const struct sockaddr_in *const sockaddr = 207 - (struct sockaddr_in *)address; 208 - 209 - if (sock->sk->__sk_common.skc_family != AF_INET) 210 - return -EINVAL; 211 - 212 - if (sockaddr->sin_addr.s_addr != htonl(INADDR_ANY)) 213 - return -EAFNOSUPPORT; 214 - } 215 - } else { 216 - /* 217 - * Checks sa_family consistency to not wrongfully return 218 - * -EACCES instead of -EINVAL. Valid sa_family changes are 219 - * only (from AF_INET or AF_INET6) to AF_UNSPEC. 220 - * 221 - * We could return 0 and let the network stack handle this 222 - * check, but it is safer to return a proper error and test 223 - * consistency thanks to kselftest. 224 - */ 225 - if (address->sa_family != sock->sk->__sk_common.skc_family) 226 - return -EINVAL; 227 - } 122 + /* 123 + * Checks sa_family consistency to not wrongfully return 124 + * -EACCES instead of -EINVAL. Valid sa_family changes are 125 + * only (from AF_INET or AF_INET6) to AF_UNSPEC. 126 + * 127 + * We could return 0 and let the network stack handle this 128 + * check, but it is safer to return a proper error and test 129 + * consistency thanks to kselftest. 130 + */ 131 + if (address->sa_family != sock->sk->__sk_common.skc_family && 132 + address->sa_family != AF_UNSPEC) 133 + return -EINVAL; 228 134 229 135 id.key.data = (__force uintptr_t)port; 230 136 BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data));
-1
security/landlock/ruleset.c
··· 23 23 #include <linux/workqueue.h> 24 24 25 25 #include "access.h" 26 - #include "audit.h" 27 26 #include "domain.h" 28 27 #include "limits.h" 29 28 #include "object.h"
+6 -6
security/landlock/task.c
··· 86 86 const unsigned int mode) 87 87 { 88 88 const struct landlock_cred_security *parent_subject; 89 - const struct landlock_ruleset *child_dom; 90 89 int err; 91 90 92 91 /* Quick return for non-landlocked tasks. */ ··· 95 96 96 97 scoped_guard(rcu) 97 98 { 98 - child_dom = landlock_get_task_domain(child); 99 + const struct landlock_ruleset *const child_dom = 100 + landlock_get_task_domain(child); 99 101 err = domain_ptrace(parent_subject->domain, child_dom); 100 102 } 101 103 ··· 166 166 } 167 167 168 168 /** 169 - * domain_is_scoped - Checks if the client domain is scoped in the same 170 - * domain as the server. 169 + * domain_is_scoped - Check if an interaction from a client/sender to a 170 + * server/receiver should be restricted based on scope controls. 171 171 * 172 172 * @client: IPC sender domain. 173 173 * @server: IPC receiver domain. 174 174 * @scope: The scope restriction criteria. 175 175 * 176 - * Returns: True if the @client domain is scoped to access the @server, 177 - * unless the @server is also scoped in the same domain as @client. 176 + * Returns: True if @server is in a different domain from @client, and @client 177 + * is scoped to access @server (i.e. access should be denied). 178 178 */ 179 179 static bool domain_is_scoped(const struct landlock_ruleset *const client, 180 180 const struct landlock_ruleset *const server,
+1
tools/testing/selftests/landlock/common.h
··· 237 237 struct sockaddr_un unix_addr; 238 238 socklen_t unix_addr_len; 239 239 }; 240 + struct sockaddr_storage _largest; 240 241 }; 241 242 }; 242 243
+15 -19
tools/testing/selftests/landlock/fs_test.c
··· 4362 4362 { 4363 4363 const char *const path = file1_s1d1; 4364 4364 int srv_fd, cli_fd, ruleset_fd; 4365 - socklen_t size; 4366 - struct sockaddr_un srv_un, cli_un; 4365 + struct sockaddr_un srv_un = { 4366 + .sun_family = AF_UNIX, 4367 + }; 4368 + struct sockaddr_un cli_un = { 4369 + .sun_family = AF_UNIX, 4370 + }; 4367 4371 const struct landlock_ruleset_attr attr = { 4368 4372 .handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL_DEV, 4369 4373 }; 4370 4374 4371 4375 /* Sets up a server */ 4372 - srv_un.sun_family = AF_UNIX; 4373 - strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path)); 4374 - 4375 4376 ASSERT_EQ(0, unlink(path)); 4376 4377 srv_fd = socket(AF_UNIX, SOCK_STREAM, 0); 4377 4378 ASSERT_LE(0, srv_fd); 4378 4379 4379 - size = offsetof(struct sockaddr_un, sun_path) + strlen(srv_un.sun_path); 4380 - ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, size)); 4380 + strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path)); 4381 + ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, sizeof(srv_un))); 4382 + 4381 4383 ASSERT_EQ(0, listen(srv_fd, 10 /* qlen */)); 4382 4384 4383 4385 /* Enables Landlock. */ ··· 4389 4387 ASSERT_EQ(0, close(ruleset_fd)); 4390 4388 4391 4389 /* Sets up a client connection to it */ 4392 - cli_un.sun_family = AF_UNIX; 4393 4390 cli_fd = socket(AF_UNIX, SOCK_STREAM, 0); 4394 4391 ASSERT_LE(0, cli_fd); 4395 4392 4396 - size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path); 4397 - ASSERT_EQ(0, bind(cli_fd, (struct sockaddr *)&cli_un, size)); 4398 - 4399 - bzero(&cli_un, sizeof(cli_un)); 4400 - cli_un.sun_family = AF_UNIX; 4401 4393 strncpy(cli_un.sun_path, path, sizeof(cli_un.sun_path)); 4402 - size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path); 4403 - 4404 - ASSERT_EQ(0, connect(cli_fd, (struct sockaddr *)&cli_un, size)); 4394 + ASSERT_EQ(0, 4395 + connect(cli_fd, (struct sockaddr *)&cli_un, sizeof(cli_un))); 4405 4396 4406 4397 /* FIONREAD and other IOCTLs should not be forbidden. */ 4407 4398 EXPECT_EQ(0, test_fionread_ioctl(cli_fd)); 4408 4399 4409 - ASSERT_EQ(0, close(cli_fd)); 4400 + EXPECT_EQ(0, close(cli_fd)); 4401 + EXPECT_EQ(0, close(srv_fd)); 4410 4402 } 4411 4403 4412 4404 /* clang-format off */ ··· 7070 7074 return -E2BIG; 7071 7075 7072 7076 /* 7073 - * It is assume that absolute_path does not contain control characters nor 7074 - * spaces, see audit_string_contains_control(). 7077 + * It is assumed that absolute_path does not contain control 7078 + * characters nor spaces, see audit_string_contains_control(). 7075 7079 */ 7076 7080 absolute_path = realpath(path, NULL); 7077 7081 if (!absolute_path)
+28 -2
tools/testing/selftests/landlock/net_test.c
··· 121 121 { 122 122 switch (srv->protocol.domain) { 123 123 case AF_UNSPEC: 124 + if (minimal) 125 + return sizeof(sa_family_t); 126 + return sizeof(struct sockaddr_storage); 127 + 124 128 case AF_INET: 125 129 return sizeof(srv->ipv4_addr); 126 130 ··· 762 758 bind_fd = socket_variant(&self->srv0); 763 759 ASSERT_LE(0, bind_fd); 764 760 761 + /* Tries to bind with too small addrlen. */ 762 + EXPECT_EQ(-EINVAL, bind_variant_addrlen( 763 + bind_fd, &self->unspec_any0, 764 + get_addrlen(&self->unspec_any0, true) - 1)); 765 + 765 766 /* Allowed bind on AF_UNSPEC/INADDR_ANY. */ 766 767 ret = bind_variant(bind_fd, &self->unspec_any0); 767 768 if (variant->prot.domain == AF_INET) { ··· 775 766 TH_LOG("Failed to bind to unspec/any socket: %s", 776 767 strerror(errno)); 777 768 } 769 + } else if (variant->prot.domain == AF_INET6) { 770 + EXPECT_EQ(-EAFNOSUPPORT, ret); 778 771 } else { 779 772 EXPECT_EQ(-EINVAL, ret); 780 773 } ··· 803 792 } else { 804 793 EXPECT_EQ(0, ret); 805 794 } 795 + } else if (variant->prot.domain == AF_INET6) { 796 + EXPECT_EQ(-EAFNOSUPPORT, ret); 806 797 } else { 807 798 EXPECT_EQ(-EINVAL, ret); 808 799 } ··· 814 801 bind_fd = socket_variant(&self->srv0); 815 802 ASSERT_LE(0, bind_fd); 816 803 ret = bind_variant(bind_fd, &self->unspec_srv0); 817 - if (variant->prot.domain == AF_INET) { 804 + if (variant->prot.domain == AF_INET || 805 + variant->prot.domain == AF_INET6) { 818 806 EXPECT_EQ(-EAFNOSUPPORT, ret); 819 807 } else { 820 808 EXPECT_EQ(-EINVAL, ret) ··· 906 892 EXPECT_EQ(0, close(ruleset_fd)); 907 893 } 908 894 909 - ret = connect_variant(connect_fd, &self->unspec_any0); 895 + /* Try to re-disconnect with a truncated address struct. */ 896 + EXPECT_EQ(-EINVAL, 897 + connect_variant_addrlen( 898 + connect_fd, &self->unspec_any0, 899 + get_addrlen(&self->unspec_any0, true) - 1)); 900 + 901 + /* 902 + * Re-disconnect, with a minimal sockaddr struct (just a 903 + * bare af_family=AF_UNSPEC field). 904 + */ 905 + ret = connect_variant_addrlen(connect_fd, &self->unspec_any0, 906 + get_addrlen(&self->unspec_any0, 907 + true)); 910 908 if (self->srv0.protocol.domain == AF_UNIX && 911 909 self->srv0.protocol.type == SOCK_STREAM) { 912 910 EXPECT_EQ(-EINVAL, ret);
+5 -149
tools/testing/selftests/landlock/ptrace_test.c
··· 86 86 } 87 87 88 88 /* clang-format off */ 89 - FIXTURE(hierarchy) {}; 89 + FIXTURE(scoped_domains) {}; 90 90 /* clang-format on */ 91 - 92 - FIXTURE_VARIANT(hierarchy) 93 - { 94 - const bool domain_both; 95 - const bool domain_parent; 96 - const bool domain_child; 97 - }; 98 91 99 92 /* 100 93 * Test multiple tracing combinations between a parent process P1 and a child ··· 97 104 * restriction is enforced in addition to any Landlock check, which means that 98 105 * all P2 requests to trace P1 would be denied. 99 106 */ 107 + #include "scoped_base_variants.h" 100 108 101 - /* 102 - * No domain 103 - * 104 - * P1-. P1 -> P2 : allow 105 - * \ P2 -> P1 : allow 106 - * 'P2 107 - */ 108 - /* clang-format off */ 109 - FIXTURE_VARIANT_ADD(hierarchy, allow_without_domain) { 110 - /* clang-format on */ 111 - .domain_both = false, 112 - .domain_parent = false, 113 - .domain_child = false, 114 - }; 115 - 116 - /* 117 - * Child domain 118 - * 119 - * P1--. P1 -> P2 : allow 120 - * \ P2 -> P1 : deny 121 - * .'-----. 122 - * | P2 | 123 - * '------' 124 - */ 125 - /* clang-format off */ 126 - FIXTURE_VARIANT_ADD(hierarchy, allow_with_one_domain) { 127 - /* clang-format on */ 128 - .domain_both = false, 129 - .domain_parent = false, 130 - .domain_child = true, 131 - }; 132 - 133 - /* 134 - * Parent domain 135 - * .------. 136 - * | P1 --. P1 -> P2 : deny 137 - * '------' \ P2 -> P1 : allow 138 - * ' 139 - * P2 140 - */ 141 - /* clang-format off */ 142 - FIXTURE_VARIANT_ADD(hierarchy, deny_with_parent_domain) { 143 - /* clang-format on */ 144 - .domain_both = false, 145 - .domain_parent = true, 146 - .domain_child = false, 147 - }; 148 - 149 - /* 150 - * Parent + child domain (siblings) 151 - * .------. 152 - * | P1 ---. P1 -> P2 : deny 153 - * '------' \ P2 -> P1 : deny 154 - * .---'--. 155 - * | P2 | 156 - * '------' 157 - */ 158 - /* clang-format off */ 159 - FIXTURE_VARIANT_ADD(hierarchy, deny_with_sibling_domain) { 160 - /* clang-format on */ 161 - .domain_both = false, 162 - .domain_parent = true, 163 - .domain_child = true, 164 - }; 165 - 166 - /* 167 - * Same domain (inherited) 168 - * .-------------. 169 - * | P1----. | P1 -> P2 : allow 170 - * | \ | P2 -> P1 : allow 171 - * | ' | 172 - * | P2 | 173 - * '-------------' 174 - */ 175 - /* clang-format off */ 176 - FIXTURE_VARIANT_ADD(hierarchy, allow_sibling_domain) { 177 - /* clang-format on */ 178 - .domain_both = true, 179 - .domain_parent = false, 180 - .domain_child = false, 181 - }; 182 - 183 - /* 184 - * Inherited + child domain 185 - * .-----------------. 186 - * | P1----. | P1 -> P2 : allow 187 - * | \ | P2 -> P1 : deny 188 - * | .-'----. | 189 - * | | P2 | | 190 - * | '------' | 191 - * '-----------------' 192 - */ 193 - /* clang-format off */ 194 - FIXTURE_VARIANT_ADD(hierarchy, allow_with_nested_domain) { 195 - /* clang-format on */ 196 - .domain_both = true, 197 - .domain_parent = false, 198 - .domain_child = true, 199 - }; 200 - 201 - /* 202 - * Inherited + parent domain 203 - * .-----------------. 204 - * |.------. | P1 -> P2 : deny 205 - * || P1 ----. | P2 -> P1 : allow 206 - * |'------' \ | 207 - * | ' | 208 - * | P2 | 209 - * '-----------------' 210 - */ 211 - /* clang-format off */ 212 - FIXTURE_VARIANT_ADD(hierarchy, deny_with_nested_and_parent_domain) { 213 - /* clang-format on */ 214 - .domain_both = true, 215 - .domain_parent = true, 216 - .domain_child = false, 217 - }; 218 - 219 - /* 220 - * Inherited + parent and child domain (siblings) 221 - * .-----------------. 222 - * | .------. | P1 -> P2 : deny 223 - * | | P1 . | P2 -> P1 : deny 224 - * | '------'\ | 225 - * | \ | 226 - * | .--'---. | 227 - * | | P2 | | 228 - * | '------' | 229 - * '-----------------' 230 - */ 231 - /* clang-format off */ 232 - FIXTURE_VARIANT_ADD(hierarchy, deny_with_forked_domain) { 233 - /* clang-format on */ 234 - .domain_both = true, 235 - .domain_parent = true, 236 - .domain_child = true, 237 - }; 238 - 239 - FIXTURE_SETUP(hierarchy) 109 + FIXTURE_SETUP(scoped_domains) 240 110 { 241 111 } 242 112 243 - FIXTURE_TEARDOWN(hierarchy) 113 + FIXTURE_TEARDOWN(scoped_domains) 244 114 { 245 115 } 246 116 247 117 /* Test PTRACE_TRACEME and PTRACE_ATTACH for parent and child. */ 248 - TEST_F(hierarchy, trace) 118 + TEST_F(scoped_domains, trace) 249 119 { 250 120 pid_t child, parent; 251 121 int status, err_proc_read;
+10 -13
tools/testing/selftests/landlock/scoped_abstract_unix_test.c
··· 543 543 544 544 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 545 545 ASSERT_EQ(grand_child, waitpid(grand_child, &status, 0)); 546 - EXPECT_EQ(0, close(stream_server_child)) 546 + EXPECT_EQ(0, close(stream_server_child)); 547 547 EXPECT_EQ(0, close(dgram_server_child)); 548 548 return; 549 549 } ··· 779 779 780 780 TEST_F(various_address_sockets, scoped_pathname_sockets) 781 781 { 782 - socklen_t size_stream, size_dgram; 783 782 pid_t child; 784 783 int status; 785 784 char buf_child, buf_parent; ··· 797 798 /* Pathname address. */ 798 799 snprintf(stream_pathname_addr.sun_path, 799 800 sizeof(stream_pathname_addr.sun_path), "%s", stream_path); 800 - size_stream = offsetof(struct sockaddr_un, sun_path) + 801 - strlen(stream_pathname_addr.sun_path); 802 801 snprintf(dgram_pathname_addr.sun_path, 803 802 sizeof(dgram_pathname_addr.sun_path), "%s", dgram_path); 804 - size_dgram = offsetof(struct sockaddr_un, sun_path) + 805 - strlen(dgram_pathname_addr.sun_path); 806 803 807 804 /* Abstract address. */ 808 805 memset(&stream_abstract_addr, 0, sizeof(stream_abstract_addr)); ··· 836 841 /* Connects with pathname sockets. */ 837 842 stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0); 838 843 ASSERT_LE(0, stream_pathname_socket); 839 - ASSERT_EQ(0, connect(stream_pathname_socket, 840 - &stream_pathname_addr, size_stream)); 844 + ASSERT_EQ(0, 845 + connect(stream_pathname_socket, &stream_pathname_addr, 846 + sizeof(stream_pathname_addr))); 841 847 ASSERT_EQ(1, write(stream_pathname_socket, "b", 1)); 842 848 EXPECT_EQ(0, close(stream_pathname_socket)); 843 849 ··· 846 850 dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 847 851 ASSERT_LE(0, dgram_pathname_socket); 848 852 err = sendto(dgram_pathname_socket, "c", 1, 0, 849 - &dgram_pathname_addr, size_dgram); 853 + &dgram_pathname_addr, sizeof(dgram_pathname_addr)); 850 854 EXPECT_EQ(1, err); 851 855 852 856 /* Sends with connection. */ 853 - ASSERT_EQ(0, connect(dgram_pathname_socket, 854 - &dgram_pathname_addr, size_dgram)); 857 + ASSERT_EQ(0, 858 + connect(dgram_pathname_socket, &dgram_pathname_addr, 859 + sizeof(dgram_pathname_addr))); 855 860 ASSERT_EQ(1, write(dgram_pathname_socket, "d", 1)); 856 861 EXPECT_EQ(0, close(dgram_pathname_socket)); 857 862 ··· 907 910 stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0); 908 911 ASSERT_LE(0, stream_pathname_socket); 909 912 ASSERT_EQ(0, bind(stream_pathname_socket, &stream_pathname_addr, 910 - size_stream)); 913 + sizeof(stream_pathname_addr))); 911 914 ASSERT_EQ(0, listen(stream_pathname_socket, backlog)); 912 915 913 916 dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 914 917 ASSERT_LE(0, dgram_pathname_socket); 915 918 ASSERT_EQ(0, bind(dgram_pathname_socket, &dgram_pathname_addr, 916 - size_dgram)); 919 + sizeof(dgram_pathname_addr))); 917 920 918 921 /* Sets up abstract servers. */ 919 922 stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0);
+7 -2
tools/testing/selftests/landlock/scoped_base_variants.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 2 /* 3 - * Landlock scoped_domains variants 3 + * Landlock scoped_domains test variant definition. 4 4 * 5 - * See the hierarchy variants from ptrace_test.c 5 + * This file defines a fixture variant "scoped_domains" that has all 6 + * permutations of parent/child process being in separate or shared 7 + * Landlock domain, or not being in a Landlock domain at all. 8 + * 9 + * Scoped access tests can include this file to avoid repeating these 10 + * combinations. 6 11 * 7 12 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net> 8 13 * Copyright © 2019-2020 ANSSI