~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/landlock/common.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php