1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Landlock test helpers 4 * 5 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net> 6 * Copyright © 2019-2020 ANSSI 7 * Copyright © 2021 Microsoft Corporation 8 */ 9 10 #include <arpa/inet.h> 11 #include <errno.h> 12 #include <linux/securebits.h> 13 #include <sys/capability.h> 14 #include <sys/prctl.h> 15 #include <sys/socket.h> 16 #include <sys/un.h> 17 #include <sys/wait.h> 18 #include <unistd.h> 19 20 #include "../kselftest_harness.h" 21 #include "wrappers.h" 22 23 #define TMP_DIR "tmp" 24 25 /* TEST_F_FORK() should not be used for new tests. */ 26 #define TEST_F_FORK(fixture_name, test_name) TEST_F(fixture_name, test_name) 27 28 static const char bin_sandbox_and_launch[] = "./sandbox-and-launch"; 29 static const char bin_wait_pipe[] = "./wait-pipe"; 30 static const char bin_wait_pipe_sandbox[] = "./wait-pipe-sandbox"; 31 32 static void _init_caps(struct __test_metadata *const _metadata, bool drop_all) 33 { 34 cap_t cap_p; 35 /* Only these three capabilities are useful for the tests. */ 36 const cap_value_t caps[] = { 37 /* clang-format off */ 38 CAP_AUDIT_CONTROL, 39 CAP_DAC_OVERRIDE, 40 CAP_MKNOD, 41 CAP_NET_ADMIN, 42 CAP_NET_BIND_SERVICE, 43 CAP_SETUID, 44 CAP_SYS_ADMIN, 45 CAP_SYS_CHROOT, 46 /* clang-format on */ 47 }; 48 const unsigned int noroot = SECBIT_NOROOT | SECBIT_NOROOT_LOCKED; 49 50 if ((cap_get_secbits() & noroot) != noroot) 51 EXPECT_EQ(0, cap_set_secbits(noroot)); 52 53 cap_p = cap_get_proc(); 54 EXPECT_NE(NULL, cap_p); 55 EXPECT_NE(-1, cap_clear(cap_p)); 56 if (!drop_all) { 57 EXPECT_NE(-1, cap_set_flag(cap_p, CAP_PERMITTED, 58 ARRAY_SIZE(caps), caps, CAP_SET)); 59 } 60 61 /* Automatically resets ambient capabilities. */ 62 EXPECT_NE(-1, cap_set_proc(cap_p)) 63 { 64 TH_LOG("Failed to set capabilities: %s", strerror(errno)); 65 } 66 EXPECT_NE(-1, cap_free(cap_p)); 67 68 /* Quickly checks that ambient capabilities are cleared. */ 69 EXPECT_NE(-1, cap_get_ambient(caps[0])); 70 } 71 72 /* We cannot put such helpers in a library because of kselftest_harness.h . */ 73 static void __maybe_unused disable_caps(struct __test_metadata *const _metadata) 74 { 75 _init_caps(_metadata, false); 76 } 77 78 static void __maybe_unused drop_caps(struct __test_metadata *const _metadata) 79 { 80 _init_caps(_metadata, true); 81 } 82 83 static void _change_cap(struct __test_metadata *const _metadata, 84 const cap_flag_t flag, const cap_value_t cap, 85 const cap_flag_value_t value) 86 { 87 cap_t cap_p; 88 89 cap_p = cap_get_proc(); 90 EXPECT_NE(NULL, cap_p); 91 EXPECT_NE(-1, cap_set_flag(cap_p, flag, 1, &cap, value)); 92 EXPECT_NE(-1, cap_set_proc(cap_p)) 93 { 94 TH_LOG("Failed to set capability %d: %s", cap, strerror(errno)); 95 } 96 EXPECT_NE(-1, cap_free(cap_p)); 97 } 98 99 static void __maybe_unused set_cap(struct __test_metadata *const _metadata, 100 const cap_value_t cap) 101 { 102 _change_cap(_metadata, CAP_EFFECTIVE, cap, CAP_SET); 103 } 104 105 static void __maybe_unused clear_cap(struct __test_metadata *const _metadata, 106 const cap_value_t cap) 107 { 108 _change_cap(_metadata, CAP_EFFECTIVE, cap, CAP_CLEAR); 109 } 110 111 static void __maybe_unused 112 set_ambient_cap(struct __test_metadata *const _metadata, const cap_value_t cap) 113 { 114 _change_cap(_metadata, CAP_INHERITABLE, cap, CAP_SET); 115 116 EXPECT_NE(-1, cap_set_ambient(cap, CAP_SET)) 117 { 118 TH_LOG("Failed to set ambient capability %d: %s", cap, 119 strerror(errno)); 120 } 121 } 122 123 static void __maybe_unused clear_ambient_cap( 124 struct __test_metadata *const _metadata, const cap_value_t cap) 125 { 126 EXPECT_EQ(1, cap_get_ambient(cap)); 127 _change_cap(_metadata, CAP_INHERITABLE, cap, CAP_CLEAR); 128 EXPECT_EQ(0, cap_get_ambient(cap)); 129 } 130 131 /* Receives an FD from a UNIX socket. Returns the received FD, or -errno. */ 132 static int __maybe_unused recv_fd(int usock) 133 { 134 int fd_rx; 135 union { 136 /* Aligned ancillary data buffer. */ 137 char buf[CMSG_SPACE(sizeof(fd_rx))]; 138 struct cmsghdr _align; 139 } cmsg_rx = {}; 140 char data = '\0'; 141 struct iovec io = { 142 .iov_base = &data, 143 .iov_len = sizeof(data), 144 }; 145 struct msghdr msg = { 146 .msg_iov = &io, 147 .msg_iovlen = 1, 148 .msg_control = &cmsg_rx.buf, 149 .msg_controllen = sizeof(cmsg_rx.buf), 150 }; 151 struct cmsghdr *cmsg; 152 int res; 153 154 res = recvmsg(usock, &msg, MSG_CMSG_CLOEXEC); 155 if (res < 0) 156 return -errno; 157 158 cmsg = CMSG_FIRSTHDR(&msg); 159 if (cmsg->cmsg_len != CMSG_LEN(sizeof(fd_rx))) 160 return -EIO; 161 162 memcpy(&fd_rx, CMSG_DATA(cmsg), sizeof(fd_rx)); 163 return fd_rx; 164 } 165 166 /* Sends an FD on a UNIX socket. Returns 0 on success or -errno. */ 167 static int __maybe_unused send_fd(int usock, int fd_tx) 168 { 169 union { 170 /* Aligned ancillary data buffer. */ 171 char buf[CMSG_SPACE(sizeof(fd_tx))]; 172 struct cmsghdr _align; 173 } cmsg_tx = {}; 174 char data_tx = '.'; 175 struct iovec io = { 176 .iov_base = &data_tx, 177 .iov_len = sizeof(data_tx), 178 }; 179 struct msghdr msg = { 180 .msg_iov = &io, 181 .msg_iovlen = 1, 182 .msg_control = &cmsg_tx.buf, 183 .msg_controllen = sizeof(cmsg_tx.buf), 184 }; 185 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); 186 187 cmsg->cmsg_len = CMSG_LEN(sizeof(fd_tx)); 188 cmsg->cmsg_level = SOL_SOCKET; 189 cmsg->cmsg_type = SCM_RIGHTS; 190 memcpy(CMSG_DATA(cmsg), &fd_tx, sizeof(fd_tx)); 191 192 if (sendmsg(usock, &msg, 0) < 0) 193 return -errno; 194 return 0; 195 } 196 197 static void __maybe_unused 198 enforce_ruleset(struct __test_metadata *const _metadata, const int ruleset_fd) 199 { 200 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); 201 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0)) 202 { 203 TH_LOG("Failed to enforce ruleset: %s", strerror(errno)); 204 } 205 } 206 207 static void __maybe_unused 208 drop_access_rights(struct __test_metadata *const _metadata, 209 const struct landlock_ruleset_attr *const ruleset_attr) 210 { 211 int ruleset_fd; 212 213 ruleset_fd = 214 landlock_create_ruleset(ruleset_attr, sizeof(*ruleset_attr), 0); 215 EXPECT_LE(0, ruleset_fd) 216 { 217 TH_LOG("Failed to create a ruleset: %s", strerror(errno)); 218 } 219 enforce_ruleset(_metadata, ruleset_fd); 220 EXPECT_EQ(0, close(ruleset_fd)); 221 } 222 223 struct protocol_variant { 224 int domain; 225 int type; 226 int protocol; 227 }; 228 229 struct service_fixture { 230 struct protocol_variant protocol; 231 /* port is also stored in ipv4_addr.sin_port or ipv6_addr.sin6_port */ 232 unsigned short port; 233 union { 234 struct sockaddr_in ipv4_addr; 235 struct sockaddr_in6 ipv6_addr; 236 struct { 237 struct sockaddr_un unix_addr; 238 socklen_t unix_addr_len; 239 }; 240 }; 241 }; 242 243 static void __maybe_unused set_unix_address(struct service_fixture *const srv, 244 const unsigned short index) 245 { 246 srv->unix_addr.sun_family = AF_UNIX; 247 sprintf(srv->unix_addr.sun_path, 248 "_selftests-landlock-abstract-unix-tid%d-index%d", sys_gettid(), 249 index); 250 srv->unix_addr_len = SUN_LEN(&srv->unix_addr); 251 srv->unix_addr.sun_path[0] = '\0'; 252 } 253