Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3#define _GNU_SOURCE
4#include <bpf/btf.h>
5#include <fcntl.h>
6#include <sched.h>
7#include <signal.h>
8#include <unistd.h>
9#include <linux/filter.h>
10#include <linux/unistd.h>
11#include <linux/mount.h>
12#include <sys/socket.h>
13#include <sys/stat.h>
14#include <sys/syscall.h>
15#include <sys/un.h>
16
17#include "bpf_util.h"
18#include "cap_helpers.h"
19#include "sysctl_helpers.h"
20#include "test_progs.h"
21#include "trace_helpers.h"
22
23#include "priv_map.skel.h"
24#include "priv_prog.skel.h"
25#include "dummy_st_ops_success.skel.h"
26#include "token_kallsyms.skel.h"
27#include "token_lsm.skel.h"
28#include "priv_freplace_prog.skel.h"
29
30static inline int sys_mount(const char *dev_name, const char *dir_name,
31 const char *type, unsigned long flags,
32 const void *data)
33{
34 return syscall(__NR_mount, dev_name, dir_name, type, flags, data);
35}
36
37static inline int sys_fsopen(const char *fsname, unsigned flags)
38{
39 return syscall(__NR_fsopen, fsname, flags);
40}
41
42static inline int sys_fspick(int dfd, const char *path, unsigned flags)
43{
44 return syscall(__NR_fspick, dfd, path, flags);
45}
46
47static inline int sys_fsconfig(int fs_fd, unsigned cmd, const char *key, const void *val, int aux)
48{
49 return syscall(__NR_fsconfig, fs_fd, cmd, key, val, aux);
50}
51
52static inline int sys_fsmount(int fs_fd, unsigned flags, unsigned ms_flags)
53{
54 return syscall(__NR_fsmount, fs_fd, flags, ms_flags);
55}
56
57static inline int sys_move_mount(int from_dfd, const char *from_path,
58 int to_dfd, const char *to_path,
59 unsigned flags)
60{
61 return syscall(__NR_move_mount, from_dfd, from_path, to_dfd, to_path, flags);
62}
63
64static int drop_priv_caps(__u64 *old_caps)
65{
66 return cap_disable_effective((1ULL << CAP_BPF) |
67 (1ULL << CAP_PERFMON) |
68 (1ULL << CAP_NET_ADMIN) |
69 (1ULL << CAP_SYS_ADMIN), old_caps);
70}
71
72static int restore_priv_caps(__u64 old_caps)
73{
74 return cap_enable_effective(old_caps, NULL);
75}
76
77static int set_delegate_mask(int fs_fd, const char *key, __u64 mask, const char *mask_str)
78{
79 char buf[32];
80 int err;
81
82 if (!mask_str) {
83 if (mask == ~0ULL) {
84 mask_str = "any";
85 } else {
86 snprintf(buf, sizeof(buf), "0x%llx", (unsigned long long)mask);
87 mask_str = buf;
88 }
89 }
90
91 err = sys_fsconfig(fs_fd, FSCONFIG_SET_STRING, key,
92 mask_str, 0);
93 if (err < 0)
94 err = -errno;
95 return err;
96}
97
98#define zclose(fd) do { if (fd >= 0) close(fd); fd = -1; } while (0)
99
100struct bpffs_opts {
101 __u64 cmds;
102 __u64 maps;
103 __u64 progs;
104 __u64 attachs;
105 const char *cmds_str;
106 const char *maps_str;
107 const char *progs_str;
108 const char *attachs_str;
109};
110
111static int create_bpffs_fd(void)
112{
113 int fs_fd;
114
115 /* create VFS context */
116 fs_fd = sys_fsopen("bpf", 0);
117 ASSERT_GE(fs_fd, 0, "fs_fd");
118
119 return fs_fd;
120}
121
122static int materialize_bpffs_fd(int fs_fd, struct bpffs_opts *opts)
123{
124 int err;
125
126 /* set up token delegation mount options */
127 err = set_delegate_mask(fs_fd, "delegate_cmds", opts->cmds, opts->cmds_str);
128 if (!ASSERT_OK(err, "fs_cfg_cmds"))
129 return err;
130 err = set_delegate_mask(fs_fd, "delegate_maps", opts->maps, opts->maps_str);
131 if (!ASSERT_OK(err, "fs_cfg_maps"))
132 return err;
133 err = set_delegate_mask(fs_fd, "delegate_progs", opts->progs, opts->progs_str);
134 if (!ASSERT_OK(err, "fs_cfg_progs"))
135 return err;
136 err = set_delegate_mask(fs_fd, "delegate_attachs", opts->attachs, opts->attachs_str);
137 if (!ASSERT_OK(err, "fs_cfg_attachs"))
138 return err;
139
140 /* instantiate FS object */
141 err = sys_fsconfig(fs_fd, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
142 if (err < 0)
143 return -errno;
144
145 return 0;
146}
147
148/* send FD over Unix domain (AF_UNIX) socket */
149static int sendfd(int sockfd, int fd)
150{
151 struct msghdr msg = {};
152 struct cmsghdr *cmsg;
153 int fds[1] = { fd }, err;
154 char iobuf[1];
155 struct iovec io = {
156 .iov_base = iobuf,
157 .iov_len = sizeof(iobuf),
158 };
159 union {
160 char buf[CMSG_SPACE(sizeof(fds))];
161 struct cmsghdr align;
162 } u;
163
164 msg.msg_iov = &io;
165 msg.msg_iovlen = 1;
166 msg.msg_control = u.buf;
167 msg.msg_controllen = sizeof(u.buf);
168 cmsg = CMSG_FIRSTHDR(&msg);
169 cmsg->cmsg_level = SOL_SOCKET;
170 cmsg->cmsg_type = SCM_RIGHTS;
171 cmsg->cmsg_len = CMSG_LEN(sizeof(fds));
172 memcpy(CMSG_DATA(cmsg), fds, sizeof(fds));
173
174 err = sendmsg(sockfd, &msg, 0);
175 if (err < 0)
176 err = -errno;
177 if (!ASSERT_EQ(err, 1, "sendmsg"))
178 return -EINVAL;
179
180 return 0;
181}
182
183/* receive FD over Unix domain (AF_UNIX) socket */
184static int recvfd(int sockfd, int *fd)
185{
186 struct msghdr msg = {};
187 struct cmsghdr *cmsg;
188 int fds[1], err;
189 char iobuf[1];
190 struct iovec io = {
191 .iov_base = iobuf,
192 .iov_len = sizeof(iobuf),
193 };
194 union {
195 char buf[CMSG_SPACE(sizeof(fds))];
196 struct cmsghdr align;
197 } u;
198
199 msg.msg_iov = &io;
200 msg.msg_iovlen = 1;
201 msg.msg_control = u.buf;
202 msg.msg_controllen = sizeof(u.buf);
203
204 err = recvmsg(sockfd, &msg, 0);
205 if (err < 0)
206 err = -errno;
207 if (!ASSERT_EQ(err, 1, "recvmsg"))
208 return -EINVAL;
209
210 cmsg = CMSG_FIRSTHDR(&msg);
211 if (!ASSERT_OK_PTR(cmsg, "cmsg_null") ||
212 !ASSERT_EQ(cmsg->cmsg_len, CMSG_LEN(sizeof(fds)), "cmsg_len") ||
213 !ASSERT_EQ(cmsg->cmsg_level, SOL_SOCKET, "cmsg_level") ||
214 !ASSERT_EQ(cmsg->cmsg_type, SCM_RIGHTS, "cmsg_type"))
215 return -EINVAL;
216
217 memcpy(fds, CMSG_DATA(cmsg), sizeof(fds));
218 *fd = fds[0];
219
220 return 0;
221}
222
223static ssize_t write_nointr(int fd, const void *buf, size_t count)
224{
225 ssize_t ret;
226
227 do {
228 ret = write(fd, buf, count);
229 } while (ret < 0 && errno == EINTR);
230
231 return ret;
232}
233
234static int write_file(const char *path, const void *buf, size_t count)
235{
236 int fd;
237 ssize_t ret;
238
239 fd = open(path, O_WRONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW);
240 if (fd < 0)
241 return -1;
242
243 ret = write_nointr(fd, buf, count);
244 close(fd);
245 if (ret < 0 || (size_t)ret != count)
246 return -1;
247
248 return 0;
249}
250
251static int create_and_enter_userns(void)
252{
253 uid_t uid;
254 gid_t gid;
255 char map[100];
256
257 uid = getuid();
258 gid = getgid();
259
260 if (unshare(CLONE_NEWUSER))
261 return -1;
262
263 if (write_file("/proc/self/setgroups", "deny", sizeof("deny") - 1) &&
264 errno != ENOENT)
265 return -1;
266
267 snprintf(map, sizeof(map), "0 %d 1", uid);
268 if (write_file("/proc/self/uid_map", map, strlen(map)))
269 return -1;
270
271
272 snprintf(map, sizeof(map), "0 %d 1", gid);
273 if (write_file("/proc/self/gid_map", map, strlen(map)))
274 return -1;
275
276 if (setgid(0))
277 return -1;
278
279 if (setuid(0))
280 return -1;
281
282 return 0;
283}
284
285typedef int (*child_callback_fn)(int bpffs_fd, struct token_lsm *lsm_skel);
286
287static void child(int sock_fd, struct bpffs_opts *opts, child_callback_fn callback)
288{
289 int mnt_fd = -1, fs_fd = -1, err = 0, bpffs_fd = -1, token_fd = -1;
290 struct token_lsm *lsm_skel = NULL;
291 char one;
292
293 /* load and attach LSM "policy" before we go into unpriv userns */
294 lsm_skel = token_lsm__open_and_load();
295 if (!ASSERT_OK_PTR(lsm_skel, "lsm_skel_load")) {
296 err = -EINVAL;
297 goto cleanup;
298 }
299 lsm_skel->bss->my_pid = getpid();
300 err = token_lsm__attach(lsm_skel);
301 if (!ASSERT_OK(err, "lsm_skel_attach"))
302 goto cleanup;
303
304 /* setup userns with root mappings */
305 err = create_and_enter_userns();
306 if (!ASSERT_OK(err, "create_and_enter_userns"))
307 goto cleanup;
308
309 /* setup mountns to allow creating BPF FS (fsopen("bpf")) from unpriv process */
310 err = unshare(CLONE_NEWNS);
311 if (!ASSERT_OK(err, "create_mountns"))
312 goto cleanup;
313
314 err = sys_mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
315 if (!ASSERT_OK(err, "remount_root"))
316 goto cleanup;
317
318 fs_fd = create_bpffs_fd();
319 if (!ASSERT_GE(fs_fd, 0, "create_bpffs_fd")) {
320 err = -EINVAL;
321 goto cleanup;
322 }
323
324 /* ensure unprivileged child cannot set delegation options */
325 err = set_delegate_mask(fs_fd, "delegate_cmds", 0x1, NULL);
326 ASSERT_EQ(err, -EPERM, "delegate_cmd_eperm");
327 err = set_delegate_mask(fs_fd, "delegate_maps", 0x1, NULL);
328 ASSERT_EQ(err, -EPERM, "delegate_maps_eperm");
329 err = set_delegate_mask(fs_fd, "delegate_progs", 0x1, NULL);
330 ASSERT_EQ(err, -EPERM, "delegate_progs_eperm");
331 err = set_delegate_mask(fs_fd, "delegate_attachs", 0x1, NULL);
332 ASSERT_EQ(err, -EPERM, "delegate_attachs_eperm");
333
334 /* pass BPF FS context object to parent */
335 err = sendfd(sock_fd, fs_fd);
336 if (!ASSERT_OK(err, "send_fs_fd"))
337 goto cleanup;
338
339 /* wait that the parent reads the fd, does the fsconfig() calls
340 * and send us a signal that it is done
341 */
342 err = read(sock_fd, &one, sizeof(one));
343 if (!ASSERT_GE(err, 0, "read_one"))
344 goto cleanup;
345
346 /* avoid mucking around with mount namespaces and mounting at
347 * well-known path, just create O_PATH fd for detached mount
348 */
349 mnt_fd = sys_fsmount(fs_fd, 0, 0);
350 if (!ASSERT_OK_FD(mnt_fd, "mnt_fd"))
351 goto cleanup;
352
353 /* try to fspick() BPF FS and try to add some delegation options */
354 fs_fd = sys_fspick(mnt_fd, "", FSPICK_EMPTY_PATH);
355 if (!ASSERT_GE(fs_fd, 0, "bpffs_fspick")) {
356 err = -EINVAL;
357 goto cleanup;
358 }
359
360 /* ensure unprivileged child cannot reconfigure to set delegation options */
361 err = set_delegate_mask(fs_fd, "delegate_cmds", 0, "any");
362 if (!ASSERT_EQ(err, -EPERM, "delegate_cmd_eperm_reconfig")) {
363 err = -EINVAL;
364 goto cleanup;
365 }
366 err = set_delegate_mask(fs_fd, "delegate_maps", 0, "any");
367 if (!ASSERT_EQ(err, -EPERM, "delegate_maps_eperm_reconfig")) {
368 err = -EINVAL;
369 goto cleanup;
370 }
371 err = set_delegate_mask(fs_fd, "delegate_progs", 0, "any");
372 if (!ASSERT_EQ(err, -EPERM, "delegate_progs_eperm_reconfig")) {
373 err = -EINVAL;
374 goto cleanup;
375 }
376 err = set_delegate_mask(fs_fd, "delegate_attachs", 0, "any");
377 if (!ASSERT_EQ(err, -EPERM, "delegate_attachs_eperm_reconfig")) {
378 err = -EINVAL;
379 goto cleanup;
380 }
381 zclose(fs_fd);
382
383 bpffs_fd = openat(mnt_fd, ".", 0, O_RDWR);
384 if (!ASSERT_GE(bpffs_fd, 0, "bpffs_open")) {
385 err = -EINVAL;
386 goto cleanup;
387 }
388
389 /* create BPF token FD and pass it to parent for some extra checks */
390 token_fd = bpf_token_create(bpffs_fd, NULL);
391 if (!ASSERT_GT(token_fd, 0, "child_token_create")) {
392 err = -EINVAL;
393 goto cleanup;
394 }
395 err = sendfd(sock_fd, token_fd);
396 if (!ASSERT_OK(err, "send_token_fd"))
397 goto cleanup;
398 zclose(token_fd);
399
400 /* do custom test logic with customly set up BPF FS instance */
401 err = callback(bpffs_fd, lsm_skel);
402 if (!ASSERT_OK(err, "test_callback"))
403 goto cleanup;
404
405 err = 0;
406cleanup:
407 zclose(sock_fd);
408 zclose(mnt_fd);
409 zclose(fs_fd);
410 zclose(bpffs_fd);
411 zclose(token_fd);
412
413 lsm_skel->bss->my_pid = 0;
414 token_lsm__destroy(lsm_skel);
415
416 exit(-err);
417}
418
419static int wait_for_pid(pid_t pid)
420{
421 int status, ret;
422
423again:
424 ret = waitpid(pid, &status, 0);
425 if (ret == -1) {
426 if (errno == EINTR)
427 goto again;
428
429 return -1;
430 }
431
432 if (!WIFEXITED(status))
433 return -1;
434
435 return WEXITSTATUS(status);
436}
437
438static void parent(int child_pid, struct bpffs_opts *bpffs_opts, int sock_fd)
439{
440 int fs_fd = -1, token_fd = -1, err;
441 char one = 1;
442
443 err = recvfd(sock_fd, &fs_fd);
444 if (!ASSERT_OK(err, "recv_bpffs_fd"))
445 goto cleanup;
446
447 err = materialize_bpffs_fd(fs_fd, bpffs_opts);
448 if (!ASSERT_GE(err, 0, "materialize_bpffs_fd")) {
449 err = -EINVAL;
450 goto cleanup;
451 }
452
453 /* notify the child that we did the fsconfig() calls and it can proceed. */
454 err = write(sock_fd, &one, sizeof(one));
455 if (!ASSERT_EQ(err, sizeof(one), "send_one"))
456 goto cleanup;
457 zclose(fs_fd);
458
459 /* receive BPF token FD back from child for some extra tests */
460 err = recvfd(sock_fd, &token_fd);
461 if (!ASSERT_OK(err, "recv_token_fd"))
462 goto cleanup;
463
464 err = wait_for_pid(child_pid);
465 ASSERT_OK(err, "waitpid_child");
466
467cleanup:
468 zclose(sock_fd);
469 zclose(fs_fd);
470 zclose(token_fd);
471
472 if (child_pid > 0)
473 (void)kill(child_pid, SIGKILL);
474}
475
476static void subtest_userns(struct bpffs_opts *bpffs_opts,
477 child_callback_fn child_cb)
478{
479 int sock_fds[2] = { -1, -1 };
480 int child_pid = 0, err;
481
482 err = socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds);
483 if (!ASSERT_OK(err, "socketpair"))
484 goto cleanup;
485
486 child_pid = fork();
487 if (!ASSERT_GE(child_pid, 0, "fork"))
488 goto cleanup;
489
490 if (child_pid == 0) {
491 zclose(sock_fds[0]);
492 return child(sock_fds[1], bpffs_opts, child_cb);
493
494 } else {
495 zclose(sock_fds[1]);
496 return parent(child_pid, bpffs_opts, sock_fds[0]);
497 }
498
499cleanup:
500 zclose(sock_fds[0]);
501 zclose(sock_fds[1]);
502 if (child_pid > 0)
503 (void)kill(child_pid, SIGKILL);
504}
505
506static int userns_map_create(int mnt_fd, struct token_lsm *lsm_skel)
507{
508 LIBBPF_OPTS(bpf_map_create_opts, map_opts);
509 int err, token_fd = -1, map_fd = -1;
510 __u64 old_caps = 0;
511
512 /* create BPF token from BPF FS mount */
513 token_fd = bpf_token_create(mnt_fd, NULL);
514 if (!ASSERT_GT(token_fd, 0, "token_create")) {
515 err = -EINVAL;
516 goto cleanup;
517 }
518
519 /* while inside non-init userns, we need both a BPF token *and*
520 * CAP_BPF inside current userns to create privileged map; let's test
521 * that neither BPF token alone nor namespaced CAP_BPF is sufficient
522 */
523 err = drop_priv_caps(&old_caps);
524 if (!ASSERT_OK(err, "drop_caps"))
525 goto cleanup;
526
527 /* no token, no CAP_BPF -> fail */
528 map_opts.map_flags = 0;
529 map_opts.token_fd = 0;
530 map_fd = bpf_map_create(BPF_MAP_TYPE_STACK, "wo_token_wo_bpf", 0, 8, 1, &map_opts);
531 if (!ASSERT_LT(map_fd, 0, "stack_map_wo_token_wo_cap_bpf_should_fail")) {
532 err = -EINVAL;
533 goto cleanup;
534 }
535
536 /* token without CAP_BPF -> fail */
537 map_opts.map_flags = BPF_F_TOKEN_FD;
538 map_opts.token_fd = token_fd;
539 map_fd = bpf_map_create(BPF_MAP_TYPE_STACK, "w_token_wo_bpf", 0, 8, 1, &map_opts);
540 if (!ASSERT_LT(map_fd, 0, "stack_map_w_token_wo_cap_bpf_should_fail")) {
541 err = -EINVAL;
542 goto cleanup;
543 }
544
545 /* get back effective local CAP_BPF (and CAP_SYS_ADMIN) */
546 err = restore_priv_caps(old_caps);
547 if (!ASSERT_OK(err, "restore_caps"))
548 goto cleanup;
549
550 /* CAP_BPF without token -> fail */
551 map_opts.map_flags = 0;
552 map_opts.token_fd = 0;
553 map_fd = bpf_map_create(BPF_MAP_TYPE_STACK, "wo_token_w_bpf", 0, 8, 1, &map_opts);
554 if (!ASSERT_LT(map_fd, 0, "stack_map_wo_token_w_cap_bpf_should_fail")) {
555 err = -EINVAL;
556 goto cleanup;
557 }
558
559 /* finally, namespaced CAP_BPF + token -> success */
560 map_opts.map_flags = BPF_F_TOKEN_FD;
561 map_opts.token_fd = token_fd;
562 map_fd = bpf_map_create(BPF_MAP_TYPE_STACK, "w_token_w_bpf", 0, 8, 1, &map_opts);
563 if (!ASSERT_GT(map_fd, 0, "stack_map_w_token_w_cap_bpf")) {
564 err = -EINVAL;
565 goto cleanup;
566 }
567
568cleanup:
569 zclose(token_fd);
570 zclose(map_fd);
571 return err;
572}
573
574static int userns_btf_load(int mnt_fd, struct token_lsm *lsm_skel)
575{
576 LIBBPF_OPTS(bpf_btf_load_opts, btf_opts);
577 int err, token_fd = -1, btf_fd = -1;
578 const void *raw_btf_data;
579 struct btf *btf = NULL;
580 __u32 raw_btf_size;
581 __u64 old_caps = 0;
582
583 /* create BPF token from BPF FS mount */
584 token_fd = bpf_token_create(mnt_fd, NULL);
585 if (!ASSERT_GT(token_fd, 0, "token_create")) {
586 err = -EINVAL;
587 goto cleanup;
588 }
589
590 /* while inside non-init userns, we need both a BPF token *and*
591 * CAP_BPF inside current userns to create privileged map; let's test
592 * that neither BPF token alone nor namespaced CAP_BPF is sufficient
593 */
594 err = drop_priv_caps(&old_caps);
595 if (!ASSERT_OK(err, "drop_caps"))
596 goto cleanup;
597
598 /* setup a trivial BTF data to load to the kernel */
599 btf = btf__new_empty();
600 if (!ASSERT_OK_PTR(btf, "empty_btf"))
601 goto cleanup;
602
603 ASSERT_GT(btf__add_int(btf, "int", 4, 0), 0, "int_type");
604
605 raw_btf_data = btf__raw_data(btf, &raw_btf_size);
606 if (!ASSERT_OK_PTR(raw_btf_data, "raw_btf_data"))
607 goto cleanup;
608
609 /* no token + no CAP_BPF -> failure */
610 btf_opts.btf_flags = 0;
611 btf_opts.token_fd = 0;
612 btf_fd = bpf_btf_load(raw_btf_data, raw_btf_size, &btf_opts);
613 if (!ASSERT_LT(btf_fd, 0, "no_token_no_cap_should_fail"))
614 goto cleanup;
615
616 /* token + no CAP_BPF -> failure */
617 btf_opts.btf_flags = BPF_F_TOKEN_FD;
618 btf_opts.token_fd = token_fd;
619 btf_fd = bpf_btf_load(raw_btf_data, raw_btf_size, &btf_opts);
620 if (!ASSERT_LT(btf_fd, 0, "token_no_cap_should_fail"))
621 goto cleanup;
622
623 /* get back effective local CAP_BPF (and CAP_SYS_ADMIN) */
624 err = restore_priv_caps(old_caps);
625 if (!ASSERT_OK(err, "restore_caps"))
626 goto cleanup;
627
628 /* token + CAP_BPF -> success */
629 btf_opts.btf_flags = BPF_F_TOKEN_FD;
630 btf_opts.token_fd = token_fd;
631 btf_fd = bpf_btf_load(raw_btf_data, raw_btf_size, &btf_opts);
632 if (!ASSERT_GT(btf_fd, 0, "token_and_cap_success"))
633 goto cleanup;
634
635 err = 0;
636cleanup:
637 btf__free(btf);
638 zclose(btf_fd);
639 zclose(token_fd);
640 return err;
641}
642
643static int userns_prog_load(int mnt_fd, struct token_lsm *lsm_skel)
644{
645 LIBBPF_OPTS(bpf_prog_load_opts, prog_opts);
646 int err, token_fd = -1, prog_fd = -1;
647 struct bpf_insn insns[] = {
648 /* bpf_jiffies64() requires CAP_BPF */
649 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
650 /* bpf_get_current_task() requires CAP_PERFMON */
651 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_current_task),
652 /* r0 = 0; exit; */
653 BPF_MOV64_IMM(BPF_REG_0, 0),
654 BPF_EXIT_INSN(),
655 };
656 size_t insn_cnt = ARRAY_SIZE(insns);
657 __u64 old_caps = 0;
658
659 /* create BPF token from BPF FS mount */
660 token_fd = bpf_token_create(mnt_fd, NULL);
661 if (!ASSERT_GT(token_fd, 0, "token_create")) {
662 err = -EINVAL;
663 goto cleanup;
664 }
665
666 /* validate we can successfully load BPF program with token; this
667 * being XDP program (CAP_NET_ADMIN) using bpf_jiffies64() (CAP_BPF)
668 * and bpf_get_current_task() (CAP_PERFMON) helpers validates we have
669 * BPF token wired properly in a bunch of places in the kernel
670 */
671 prog_opts.prog_flags = BPF_F_TOKEN_FD;
672 prog_opts.token_fd = token_fd;
673 prog_opts.expected_attach_type = BPF_XDP;
674 prog_fd = bpf_prog_load(BPF_PROG_TYPE_XDP, "token_prog", "GPL",
675 insns, insn_cnt, &prog_opts);
676 if (!ASSERT_GT(prog_fd, 0, "prog_fd")) {
677 err = -EPERM;
678 goto cleanup;
679 }
680
681 /* no token + caps -> failure */
682 prog_opts.prog_flags = 0;
683 prog_opts.token_fd = 0;
684 prog_fd = bpf_prog_load(BPF_PROG_TYPE_XDP, "token_prog", "GPL",
685 insns, insn_cnt, &prog_opts);
686 if (!ASSERT_EQ(prog_fd, -EPERM, "prog_fd_eperm")) {
687 err = -EPERM;
688 goto cleanup;
689 }
690
691 err = drop_priv_caps(&old_caps);
692 if (!ASSERT_OK(err, "drop_caps"))
693 goto cleanup;
694
695 /* no caps + token -> failure */
696 prog_opts.prog_flags = BPF_F_TOKEN_FD;
697 prog_opts.token_fd = token_fd;
698 prog_fd = bpf_prog_load(BPF_PROG_TYPE_XDP, "token_prog", "GPL",
699 insns, insn_cnt, &prog_opts);
700 if (!ASSERT_EQ(prog_fd, -EPERM, "prog_fd_eperm")) {
701 err = -EPERM;
702 goto cleanup;
703 }
704
705 /* no caps + no token -> definitely a failure */
706 prog_opts.prog_flags = 0;
707 prog_opts.token_fd = 0;
708 prog_fd = bpf_prog_load(BPF_PROG_TYPE_XDP, "token_prog", "GPL",
709 insns, insn_cnt, &prog_opts);
710 if (!ASSERT_EQ(prog_fd, -EPERM, "prog_fd_eperm")) {
711 err = -EPERM;
712 goto cleanup;
713 }
714
715 err = 0;
716cleanup:
717 zclose(prog_fd);
718 zclose(token_fd);
719 return err;
720}
721
722static int userns_obj_priv_map(int mnt_fd, struct token_lsm *lsm_skel)
723{
724 LIBBPF_OPTS(bpf_object_open_opts, opts);
725 char buf[256];
726 struct priv_map *skel;
727 int err;
728
729 skel = priv_map__open_and_load();
730 if (!ASSERT_ERR_PTR(skel, "obj_tokenless_load")) {
731 priv_map__destroy(skel);
732 return -EINVAL;
733 }
734
735 /* use bpf_token_path to provide BPF FS path */
736 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", mnt_fd);
737 opts.bpf_token_path = buf;
738 skel = priv_map__open_opts(&opts);
739 if (!ASSERT_OK_PTR(skel, "obj_token_path_open"))
740 return -EINVAL;
741
742 err = priv_map__load(skel);
743 priv_map__destroy(skel);
744 if (!ASSERT_OK(err, "obj_token_path_load"))
745 return -EINVAL;
746
747 return 0;
748}
749
750static int userns_obj_priv_prog(int mnt_fd, struct token_lsm *lsm_skel)
751{
752 LIBBPF_OPTS(bpf_object_open_opts, opts);
753 char buf[256];
754 struct priv_prog *skel;
755 int err;
756
757 skel = priv_prog__open_and_load();
758 if (!ASSERT_ERR_PTR(skel, "obj_tokenless_load")) {
759 priv_prog__destroy(skel);
760 return -EINVAL;
761 }
762
763 /* use bpf_token_path to provide BPF FS path */
764 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", mnt_fd);
765 opts.bpf_token_path = buf;
766 skel = priv_prog__open_opts(&opts);
767 if (!ASSERT_OK_PTR(skel, "obj_token_path_open"))
768 return -EINVAL;
769 err = priv_prog__load(skel);
770 priv_prog__destroy(skel);
771 if (!ASSERT_OK(err, "obj_token_path_load"))
772 return -EINVAL;
773
774 /* provide BPF token, but reject bpf_token_capable() with LSM */
775 lsm_skel->bss->reject_capable = true;
776 lsm_skel->bss->reject_cmd = false;
777 skel = priv_prog__open_opts(&opts);
778 if (!ASSERT_OK_PTR(skel, "obj_token_lsm_reject_cap_open"))
779 return -EINVAL;
780 err = priv_prog__load(skel);
781 priv_prog__destroy(skel);
782 if (!ASSERT_ERR(err, "obj_token_lsm_reject_cap_load"))
783 return -EINVAL;
784
785 /* provide BPF token, but reject bpf_token_cmd() with LSM */
786 lsm_skel->bss->reject_capable = false;
787 lsm_skel->bss->reject_cmd = true;
788 skel = priv_prog__open_opts(&opts);
789 if (!ASSERT_OK_PTR(skel, "obj_token_lsm_reject_cmd_open"))
790 return -EINVAL;
791 err = priv_prog__load(skel);
792 priv_prog__destroy(skel);
793 if (!ASSERT_ERR(err, "obj_token_lsm_reject_cmd_load"))
794 return -EINVAL;
795
796 return 0;
797}
798
799static int userns_obj_priv_freplace_setup(int mnt_fd, struct priv_freplace_prog **fr_skel,
800 struct priv_prog **skel, int *tgt_fd)
801{
802 LIBBPF_OPTS(bpf_object_open_opts, opts);
803 int err;
804 char buf[256];
805
806 /* use bpf_token_path to provide BPF FS path */
807 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", mnt_fd);
808 opts.bpf_token_path = buf;
809 *skel = priv_prog__open_opts(&opts);
810 if (!ASSERT_OK_PTR(*skel, "priv_prog__open_opts"))
811 return -EINVAL;
812 err = priv_prog__load(*skel);
813 if (!ASSERT_OK(err, "priv_prog__load"))
814 return -EINVAL;
815
816 *fr_skel = priv_freplace_prog__open_opts(&opts);
817 if (!ASSERT_OK_PTR(*skel, "priv_freplace_prog__open_opts"))
818 return -EINVAL;
819
820 *tgt_fd = bpf_program__fd((*skel)->progs.xdp_prog1);
821 return 0;
822}
823
824/* Verify that freplace works from user namespace, because bpf token is loaded
825 * in bpf_object__prepare
826 */
827static int userns_obj_priv_freplace_prog(int mnt_fd, struct token_lsm *lsm_skel)
828{
829 struct priv_freplace_prog *fr_skel = NULL;
830 struct priv_prog *skel = NULL;
831 int err, tgt_fd;
832
833 err = userns_obj_priv_freplace_setup(mnt_fd, &fr_skel, &skel, &tgt_fd);
834 if (!ASSERT_OK(err, "setup"))
835 goto out;
836
837 err = bpf_object__prepare(fr_skel->obj);
838 if (!ASSERT_OK(err, "freplace__prepare"))
839 goto out;
840
841 err = bpf_program__set_attach_target(fr_skel->progs.new_xdp_prog2, tgt_fd, "xdp_prog1");
842 if (!ASSERT_OK(err, "set_attach_target"))
843 goto out;
844
845 err = priv_freplace_prog__load(fr_skel);
846 ASSERT_OK(err, "priv_freplace_prog__load");
847
848out:
849 priv_freplace_prog__destroy(fr_skel);
850 priv_prog__destroy(skel);
851 return err;
852}
853
854/* Verify that replace fails to set attach target from user namespace without bpf token */
855static int userns_obj_priv_freplace_prog_fail(int mnt_fd, struct token_lsm *lsm_skel)
856{
857 struct priv_freplace_prog *fr_skel = NULL;
858 struct priv_prog *skel = NULL;
859 int err, tgt_fd;
860
861 err = userns_obj_priv_freplace_setup(mnt_fd, &fr_skel, &skel, &tgt_fd);
862 if (!ASSERT_OK(err, "setup"))
863 goto out;
864
865 err = bpf_program__set_attach_target(fr_skel->progs.new_xdp_prog2, tgt_fd, "xdp_prog1");
866 if (ASSERT_ERR(err, "attach fails"))
867 err = 0;
868 else
869 err = -EINVAL;
870
871out:
872 priv_freplace_prog__destroy(fr_skel);
873 priv_prog__destroy(skel);
874 return err;
875}
876
877/* this test is called with BPF FS that doesn't delegate BPF_BTF_LOAD command,
878 * which should cause struct_ops application to fail, as BTF won't be uploaded
879 * into the kernel, even if STRUCT_OPS programs themselves are allowed
880 */
881static int validate_struct_ops_load(int mnt_fd, bool expect_success)
882{
883 LIBBPF_OPTS(bpf_object_open_opts, opts);
884 char buf[256];
885 struct dummy_st_ops_success *skel;
886 int err;
887
888 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", mnt_fd);
889 opts.bpf_token_path = buf;
890 skel = dummy_st_ops_success__open_opts(&opts);
891 if (!ASSERT_OK_PTR(skel, "obj_token_path_open"))
892 return -EINVAL;
893
894 err = dummy_st_ops_success__load(skel);
895 dummy_st_ops_success__destroy(skel);
896 if (expect_success) {
897 if (!ASSERT_OK(err, "obj_token_path_load"))
898 return -EINVAL;
899 } else /* expect failure */ {
900 if (!ASSERT_ERR(err, "obj_token_path_load"))
901 return -EINVAL;
902 }
903
904 return 0;
905}
906
907static int userns_obj_priv_btf_fail(int mnt_fd, struct token_lsm *lsm_skel)
908{
909 return validate_struct_ops_load(mnt_fd, false /* should fail */);
910}
911
912static int userns_obj_priv_btf_success(int mnt_fd, struct token_lsm *lsm_skel)
913{
914 return validate_struct_ops_load(mnt_fd, true /* should succeed */);
915}
916
917static const char *token_bpffs_custom_dir()
918{
919 return getenv("BPF_SELFTESTS_BPF_TOKEN_DIR") ?: "/tmp/bpf-token-fs";
920}
921
922#define TOKEN_ENVVAR "LIBBPF_BPF_TOKEN_PATH"
923
924static int userns_obj_priv_implicit_token(int mnt_fd, struct token_lsm *lsm_skel)
925{
926 LIBBPF_OPTS(bpf_object_open_opts, opts);
927 struct dummy_st_ops_success *skel;
928 int err;
929
930 /* before we mount BPF FS with token delegation, struct_ops skeleton
931 * should fail to load
932 */
933 skel = dummy_st_ops_success__open_and_load();
934 if (!ASSERT_ERR_PTR(skel, "obj_tokenless_load")) {
935 dummy_st_ops_success__destroy(skel);
936 return -EINVAL;
937 }
938
939 /* mount custom BPF FS over /sys/fs/bpf so that libbpf can create BPF
940 * token automatically and implicitly
941 */
942 err = sys_move_mount(mnt_fd, "", AT_FDCWD, "/sys/fs/bpf", MOVE_MOUNT_F_EMPTY_PATH);
943 if (!ASSERT_OK(err, "move_mount_bpffs"))
944 return -EINVAL;
945
946 /* disable implicit BPF token creation by setting
947 * LIBBPF_BPF_TOKEN_PATH envvar to empty value, load should fail
948 */
949 err = setenv(TOKEN_ENVVAR, "", 1 /*overwrite*/);
950 if (!ASSERT_OK(err, "setenv_token_path"))
951 return -EINVAL;
952 skel = dummy_st_ops_success__open_and_load();
953 if (!ASSERT_ERR_PTR(skel, "obj_token_envvar_disabled_load")) {
954 unsetenv(TOKEN_ENVVAR);
955 dummy_st_ops_success__destroy(skel);
956 return -EINVAL;
957 }
958 unsetenv(TOKEN_ENVVAR);
959
960 /* now the same struct_ops skeleton should succeed thanks to libbpf
961 * creating BPF token from /sys/fs/bpf mount point
962 */
963 skel = dummy_st_ops_success__open_and_load();
964 if (!ASSERT_OK_PTR(skel, "obj_implicit_token_load"))
965 return -EINVAL;
966
967 dummy_st_ops_success__destroy(skel);
968
969 /* now disable implicit token through empty bpf_token_path, should fail */
970 opts.bpf_token_path = "";
971 skel = dummy_st_ops_success__open_opts(&opts);
972 if (!ASSERT_OK_PTR(skel, "obj_empty_token_path_open"))
973 return -EINVAL;
974
975 err = dummy_st_ops_success__load(skel);
976 dummy_st_ops_success__destroy(skel);
977 if (!ASSERT_ERR(err, "obj_empty_token_path_load"))
978 return -EINVAL;
979
980 return 0;
981}
982
983static int userns_obj_priv_implicit_token_envvar(int mnt_fd, struct token_lsm *lsm_skel)
984{
985 const char *custom_dir = token_bpffs_custom_dir();
986 LIBBPF_OPTS(bpf_object_open_opts, opts);
987 struct dummy_st_ops_success *skel;
988 int err;
989
990 /* before we mount BPF FS with token delegation, struct_ops skeleton
991 * should fail to load
992 */
993 skel = dummy_st_ops_success__open_and_load();
994 if (!ASSERT_ERR_PTR(skel, "obj_tokenless_load")) {
995 dummy_st_ops_success__destroy(skel);
996 return -EINVAL;
997 }
998
999 /* mount custom BPF FS over custom location, so libbpf can't create
1000 * BPF token implicitly, unless pointed to it through
1001 * LIBBPF_BPF_TOKEN_PATH envvar
1002 */
1003 rmdir(custom_dir);
1004 if (!ASSERT_OK(mkdir(custom_dir, 0777), "mkdir_bpffs_custom"))
1005 goto err_out;
1006 err = sys_move_mount(mnt_fd, "", AT_FDCWD, custom_dir, MOVE_MOUNT_F_EMPTY_PATH);
1007 if (!ASSERT_OK(err, "move_mount_bpffs"))
1008 goto err_out;
1009
1010 /* even though we have BPF FS with delegation, it's not at default
1011 * /sys/fs/bpf location, so we still fail to load until envvar is set up
1012 */
1013 skel = dummy_st_ops_success__open_and_load();
1014 if (!ASSERT_ERR_PTR(skel, "obj_tokenless_load2")) {
1015 dummy_st_ops_success__destroy(skel);
1016 goto err_out;
1017 }
1018
1019 err = setenv(TOKEN_ENVVAR, custom_dir, 1 /*overwrite*/);
1020 if (!ASSERT_OK(err, "setenv_token_path"))
1021 goto err_out;
1022
1023 /* now the same struct_ops skeleton should succeed thanks to libbpf
1024 * creating BPF token from custom mount point
1025 */
1026 skel = dummy_st_ops_success__open_and_load();
1027 if (!ASSERT_OK_PTR(skel, "obj_implicit_token_load"))
1028 goto err_out;
1029
1030 dummy_st_ops_success__destroy(skel);
1031
1032 /* now disable implicit token through empty bpf_token_path, envvar
1033 * will be ignored, should fail
1034 */
1035 opts.bpf_token_path = "";
1036 skel = dummy_st_ops_success__open_opts(&opts);
1037 if (!ASSERT_OK_PTR(skel, "obj_empty_token_path_open"))
1038 goto err_out;
1039
1040 err = dummy_st_ops_success__load(skel);
1041 dummy_st_ops_success__destroy(skel);
1042 if (!ASSERT_ERR(err, "obj_empty_token_path_load"))
1043 goto err_out;
1044
1045 rmdir(custom_dir);
1046 unsetenv(TOKEN_ENVVAR);
1047 return 0;
1048err_out:
1049 rmdir(custom_dir);
1050 unsetenv(TOKEN_ENVVAR);
1051 return -EINVAL;
1052}
1053
1054static bool kallsyms_has_bpf_func(struct ksyms *ksyms, const char *func_name)
1055{
1056 char name[256];
1057 int i;
1058
1059 for (i = 0; i < ksyms->sym_cnt; i++) {
1060 if (sscanf(ksyms->syms[i].name, "bpf_prog_%*[^_]_%255s", name) == 1 &&
1061 strcmp(name, func_name) == 0)
1062 return true;
1063 }
1064 return false;
1065}
1066
1067static int userns_obj_priv_prog_kallsyms(int mnt_fd, struct token_lsm *lsm_skel)
1068{
1069 const char *func_names[] = { "xdp_main", "token_ksym_subprog" };
1070 LIBBPF_OPTS(bpf_object_open_opts, opts);
1071 struct token_kallsyms *skel;
1072 struct ksyms *ksyms = NULL;
1073 char buf[256];
1074 int i, err;
1075
1076 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", mnt_fd);
1077 opts.bpf_token_path = buf;
1078 skel = token_kallsyms__open_opts(&opts);
1079 if (!ASSERT_OK_PTR(skel, "token_kallsyms__open_opts"))
1080 return -EINVAL;
1081
1082 err = token_kallsyms__load(skel);
1083 if (!ASSERT_OK(err, "token_kallsyms__load"))
1084 goto cleanup;
1085
1086 ksyms = load_kallsyms_local();
1087 if (!ASSERT_OK_PTR(ksyms, "load_kallsyms_local")) {
1088 err = -EINVAL;
1089 goto cleanup;
1090 }
1091
1092 for (i = 0; i < ARRAY_SIZE(func_names); i++) {
1093 if (!ASSERT_TRUE(kallsyms_has_bpf_func(ksyms, func_names[i]),
1094 func_names[i])) {
1095 err = -EINVAL;
1096 break;
1097 }
1098 }
1099
1100cleanup:
1101 free_kallsyms_local(ksyms);
1102 token_kallsyms__destroy(skel);
1103 return err;
1104}
1105
1106#define bit(n) (1ULL << (n))
1107
1108static int userns_bpf_token_info(int mnt_fd, struct token_lsm *lsm_skel)
1109{
1110 int err, token_fd = -1;
1111 struct bpf_token_info info;
1112 u32 len = sizeof(struct bpf_token_info);
1113
1114 /* create BPF token from BPF FS mount */
1115 token_fd = bpf_token_create(mnt_fd, NULL);
1116 if (!ASSERT_GT(token_fd, 0, "token_create")) {
1117 err = -EINVAL;
1118 goto cleanup;
1119 }
1120
1121 memset(&info, 0, len);
1122 err = bpf_obj_get_info_by_fd(token_fd, &info, &len);
1123 if (!ASSERT_ERR(err, "bpf_obj_get_token_info"))
1124 goto cleanup;
1125 if (!ASSERT_EQ(info.allowed_cmds, bit(BPF_MAP_CREATE), "token_info_cmds_map_create")) {
1126 err = -EINVAL;
1127 goto cleanup;
1128 }
1129 if (!ASSERT_EQ(info.allowed_progs, bit(BPF_PROG_TYPE_XDP), "token_info_progs_xdp")) {
1130 err = -EINVAL;
1131 goto cleanup;
1132 }
1133
1134 /* The BPF_PROG_TYPE_EXT is not set in token */
1135 if (ASSERT_EQ(info.allowed_progs, bit(BPF_PROG_TYPE_EXT), "token_info_progs_ext"))
1136 err = -EINVAL;
1137
1138cleanup:
1139 zclose(token_fd);
1140 return err;
1141}
1142
1143void serial_test_token(void)
1144{
1145 if (test__start_subtest("map_token")) {
1146 struct bpffs_opts opts = {
1147 .cmds_str = "map_create",
1148 .maps_str = "stack",
1149 };
1150
1151 subtest_userns(&opts, userns_map_create);
1152 }
1153 if (test__start_subtest("btf_token")) {
1154 struct bpffs_opts opts = {
1155 .cmds = 1ULL << BPF_BTF_LOAD,
1156 };
1157
1158 subtest_userns(&opts, userns_btf_load);
1159 }
1160 if (test__start_subtest("prog_token")) {
1161 struct bpffs_opts opts = {
1162 .cmds_str = "PROG_LOAD",
1163 .progs_str = "XDP",
1164 .attachs_str = "xdp",
1165 };
1166
1167 subtest_userns(&opts, userns_prog_load);
1168 }
1169 if (test__start_subtest("obj_priv_map")) {
1170 struct bpffs_opts opts = {
1171 .cmds = bit(BPF_MAP_CREATE),
1172 .maps = bit(BPF_MAP_TYPE_QUEUE),
1173 };
1174
1175 subtest_userns(&opts, userns_obj_priv_map);
1176 }
1177 if (test__start_subtest("obj_priv_prog")) {
1178 struct bpffs_opts opts = {
1179 .cmds = bit(BPF_PROG_LOAD),
1180 .progs = bit(BPF_PROG_TYPE_XDP),
1181 .attachs = ~0ULL,
1182 };
1183
1184 subtest_userns(&opts, userns_obj_priv_prog);
1185 }
1186 if (test__start_subtest("obj_priv_freplace_prog")) {
1187 struct bpffs_opts opts = {
1188 .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) | bit(BPF_BTF_GET_FD_BY_ID),
1189 .progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP),
1190 .attachs = ~0ULL,
1191 };
1192 subtest_userns(&opts, userns_obj_priv_freplace_prog);
1193 }
1194 if (test__start_subtest("obj_priv_freplace_prog_fail")) {
1195 struct bpffs_opts opts = {
1196 .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) | bit(BPF_BTF_GET_FD_BY_ID),
1197 .progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP),
1198 .attachs = ~0ULL,
1199 };
1200 subtest_userns(&opts, userns_obj_priv_freplace_prog_fail);
1201 }
1202 if (test__start_subtest("obj_priv_btf_fail")) {
1203 struct bpffs_opts opts = {
1204 /* disallow BTF loading */
1205 .cmds = bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
1206 .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
1207 .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
1208 .attachs = ~0ULL,
1209 };
1210
1211 subtest_userns(&opts, userns_obj_priv_btf_fail);
1212 }
1213 if (test__start_subtest("obj_priv_btf_success")) {
1214 struct bpffs_opts opts = {
1215 /* allow BTF loading */
1216 .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
1217 .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
1218 .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
1219 .attachs = ~0ULL,
1220 };
1221
1222 subtest_userns(&opts, userns_obj_priv_btf_success);
1223 }
1224 if (test__start_subtest("obj_priv_implicit_token")) {
1225 struct bpffs_opts opts = {
1226 /* allow BTF loading */
1227 .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
1228 .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
1229 .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
1230 .attachs = ~0ULL,
1231 };
1232
1233 subtest_userns(&opts, userns_obj_priv_implicit_token);
1234 }
1235 if (test__start_subtest("obj_priv_implicit_token_envvar")) {
1236 struct bpffs_opts opts = {
1237 /* allow BTF loading */
1238 .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
1239 .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
1240 .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
1241 .attachs = ~0ULL,
1242 };
1243
1244 subtest_userns(&opts, userns_obj_priv_implicit_token_envvar);
1245 }
1246 if (test__start_subtest("bpf_token_info")) {
1247 struct bpffs_opts opts = {
1248 .cmds = bit(BPF_MAP_CREATE),
1249 .progs = bit(BPF_PROG_TYPE_XDP),
1250 .attachs = ~0ULL,
1251 };
1252
1253 subtest_userns(&opts, userns_bpf_token_info);
1254 }
1255 if (test__start_subtest("obj_priv_prog_kallsyms")) {
1256 char perf_paranoid_orig[32] = {};
1257 char kptr_restrict_orig[32] = {};
1258 struct bpffs_opts opts = {
1259 .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD),
1260 .progs = bit(BPF_PROG_TYPE_XDP),
1261 .attachs = ~0ULL,
1262 };
1263
1264 if (sysctl_set_or_fail("/proc/sys/kernel/perf_event_paranoid", perf_paranoid_orig, "0"))
1265 goto cleanup;
1266 if (sysctl_set_or_fail("/proc/sys/kernel/kptr_restrict", kptr_restrict_orig, "0"))
1267 goto cleanup;
1268
1269 subtest_userns(&opts, userns_obj_priv_prog_kallsyms);
1270
1271cleanup:
1272 if (perf_paranoid_orig[0])
1273 sysctl_set_or_fail("/proc/sys/kernel/perf_event_paranoid", NULL, perf_paranoid_orig);
1274 if (kptr_restrict_orig[0])
1275 sysctl_set_or_fail("/proc/sys/kernel/kptr_restrict", NULL, kptr_restrict_orig);
1276 }
1277}