1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Landlock test helpers
5 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
6 * Copyright © 2019-2020 ANSSI
7 * Copyright © 2021 Microsoft Corporation
10 #include <arpa/inet.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>
22 #include "../kselftest_harness.h"
26 #ifndef __maybe_unused
27 #define __maybe_unused __attribute__((__unused__))
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)
33 #ifndef landlock_create_ruleset
35 landlock_create_ruleset(const struct landlock_ruleset_attr
*const attr
,
36 const size_t size
, const __u32 flags
)
38 return syscall(__NR_landlock_create_ruleset
, attr
, size
, flags
);
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
,
48 return syscall(__NR_landlock_add_rule
, ruleset_fd
, rule_type
, rule_attr
,
53 #ifndef landlock_restrict_self
54 static inline int landlock_restrict_self(const int ruleset_fd
,
57 return syscall(__NR_landlock_restrict_self
, ruleset_fd
, flags
);
61 static void _init_caps(struct __test_metadata
*const _metadata
, bool drop_all
)
64 /* Only these three capabilities are useful for the tests. */
65 const cap_value_t caps
[] = {
66 /* clang-format off */
75 const unsigned int noroot
= SECBIT_NOROOT
| SECBIT_NOROOT_LOCKED
;
77 if ((cap_get_secbits() & noroot
) != noroot
)
78 EXPECT_EQ(0, cap_set_secbits(noroot
));
80 cap_p
= cap_get_proc();
81 EXPECT_NE(NULL
, cap_p
);
82 EXPECT_NE(-1, cap_clear(cap_p
));
84 EXPECT_NE(-1, cap_set_flag(cap_p
, CAP_PERMITTED
,
85 ARRAY_SIZE(caps
), caps
, CAP_SET
));
88 /* Automatically resets ambient capabilities. */
89 EXPECT_NE(-1, cap_set_proc(cap_p
))
91 TH_LOG("Failed to set capabilities: %s", strerror(errno
));
93 EXPECT_NE(-1, cap_free(cap_p
));
95 /* Quickly checks that ambient capabilities are cleared. */
96 EXPECT_NE(-1, cap_get_ambient(caps
[0]));
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
)
102 _init_caps(_metadata
, false);
105 static void __maybe_unused
drop_caps(struct __test_metadata
*const _metadata
)
107 _init_caps(_metadata
, true);
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
)
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
))
121 TH_LOG("Failed to set capability %d: %s", cap
, strerror(errno
));
123 EXPECT_NE(-1, cap_free(cap_p
));
126 static void __maybe_unused
set_cap(struct __test_metadata
*const _metadata
,
127 const cap_value_t cap
)
129 _change_cap(_metadata
, CAP_EFFECTIVE
, cap
, CAP_SET
);
132 static void __maybe_unused
clear_cap(struct __test_metadata
*const _metadata
,
133 const cap_value_t cap
)
135 _change_cap(_metadata
, CAP_EFFECTIVE
, cap
, CAP_CLEAR
);
138 static void __maybe_unused
139 set_ambient_cap(struct __test_metadata
*const _metadata
, const cap_value_t cap
)
141 _change_cap(_metadata
, CAP_INHERITABLE
, cap
, CAP_SET
);
143 EXPECT_NE(-1, cap_set_ambient(cap
, CAP_SET
))
145 TH_LOG("Failed to set ambient capability %d: %s", cap
,
150 static void __maybe_unused
clear_ambient_cap(
151 struct __test_metadata
*const _metadata
, const cap_value_t cap
)
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
));
158 /* Receives an FD from a UNIX socket. Returns the received FD, or -errno. */
159 static int __maybe_unused
recv_fd(int usock
)
163 /* Aligned ancillary data buffer. */
164 char buf
[CMSG_SPACE(sizeof(fd_rx
))];
165 struct cmsghdr _align
;
170 .iov_len
= sizeof(data
),
172 struct msghdr msg
= {
175 .msg_control
= &cmsg_rx
.buf
,
176 .msg_controllen
= sizeof(cmsg_rx
.buf
),
178 struct cmsghdr
*cmsg
;
181 res
= recvmsg(usock
, &msg
, MSG_CMSG_CLOEXEC
);
185 cmsg
= CMSG_FIRSTHDR(&msg
);
186 if (cmsg
->cmsg_len
!= CMSG_LEN(sizeof(fd_rx
)))
189 memcpy(&fd_rx
, CMSG_DATA(cmsg
), sizeof(fd_rx
));
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
)
197 /* Aligned ancillary data buffer. */
198 char buf
[CMSG_SPACE(sizeof(fd_tx
))];
199 struct cmsghdr _align
;
203 .iov_base
= &data_tx
,
204 .iov_len
= sizeof(data_tx
),
206 struct msghdr msg
= {
209 .msg_control
= &cmsg_tx
.buf
,
210 .msg_controllen
= sizeof(cmsg_tx
.buf
),
212 struct cmsghdr
*cmsg
= CMSG_FIRSTHDR(&msg
);
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
));
219 if (sendmsg(usock
, &msg
, 0) < 0)
224 static void __maybe_unused
225 enforce_ruleset(struct __test_metadata
*const _metadata
, const int ruleset_fd
)
227 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS
, 1, 0, 0, 0));
228 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd
, 0))
230 TH_LOG("Failed to enforce ruleset: %s", strerror(errno
));
234 struct protocol_variant
{
239 struct service_fixture
{
240 struct protocol_variant protocol
;
241 /* port is also stored in ipv4_addr.sin_port or ipv6_addr.sin6_port */
244 struct sockaddr_in ipv4_addr
;
245 struct sockaddr_in6 ipv6_addr
;
247 struct sockaddr_un unix_addr
;
248 socklen_t unix_addr_len
;
253 static pid_t __maybe_unused
sys_gettid(void)
255 return syscall(__NR_gettid
);
258 static void __maybe_unused
set_unix_address(struct service_fixture
*const srv
,
259 const unsigned short index
)
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(),
265 srv
->unix_addr_len
= SUN_LEN(&srv
->unix_addr
);
266 srv
->unix_addr
.sun_path
[0] = '\0';