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