Last active
July 16, 2025 18:07
-
-
Save teknoraver/92f27cbc456e4ab4a508943eb93958b8 to your computer and use it in GitHub Desktop.
Sample tool to create a BPF token
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* run as: | |
* gcc -O2 -Wall bpf_token.c -o bpf_token -lbpf | |
* sudo strace -f -e fsopen,fsconfig,fspick,fsmount,move_mount,unshare,bpf ./bpf_token | |
*/ | |
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <sys/socket.h> | |
#include <sched.h> | |
#include <sys/syscall.h> | |
#include <sys/mount.h> | |
#include <sys/stat.h> | |
#include <bpf/bpf.h> | |
#define pexit(msg) do { perror(msg); exit(1); } while (0) | |
#define BPFFS_MOUNT "/sys/fs/bpf" | |
static int sendfd(int sockfd, int fd) | |
{ | |
struct cmsghdr *cmsg; | |
int err; | |
union { | |
char buf[CMSG_SPACE(sizeof(fd))]; | |
struct cmsghdr align; | |
} u; | |
struct msghdr msg = { | |
.msg_control = u.buf, | |
.msg_controllen = sizeof(u.buf), | |
}; | |
cmsg = CMSG_FIRSTHDR(&msg); | |
cmsg->cmsg_level = SOL_SOCKET; | |
cmsg->cmsg_type = SCM_RIGHTS; | |
cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); | |
memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); | |
err = sendmsg(sockfd, &msg, 0); | |
if (err < 0) | |
err = -errno; | |
if (err != msg.msg_iovlen) { | |
perror("sendmsg"); | |
return -EINVAL; | |
} | |
return 0; | |
} | |
static int recvfd(int sockfd) | |
{ | |
struct cmsghdr *cmsg; | |
int err; | |
int fd; | |
union { | |
char buf[CMSG_SPACE(sizeof(fd))]; | |
struct cmsghdr align; | |
} u; | |
struct msghdr msg = { | |
.msg_control = u.buf, | |
.msg_controllen = sizeof(u.buf), | |
}; | |
err = recvmsg(sockfd, &msg, 0); | |
if (err < 0) | |
return -errno; | |
cmsg = CMSG_FIRSTHDR(&msg); | |
if (!cmsg || | |
cmsg->cmsg_len != CMSG_LEN(sizeof(fd)) || | |
cmsg->cmsg_level != SOL_SOCKET || | |
cmsg->cmsg_type != SCM_RIGHTS) | |
return -EINVAL; | |
memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); | |
return fd; | |
} | |
void parent(int sock_fd) | |
{ | |
int fs_fd, mnt_fd, bpffs_fd, token_fd; | |
int r; | |
if (unshare(CLONE_NEWUSER) < 0) | |
pexit("unshare"); | |
if (unshare(CLONE_NEWNS) < 0) | |
pexit("unshare"); | |
r = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0); | |
if (r < 0) | |
pexit("mount"); | |
fs_fd = fsopen("bpf", FSOPEN_CLOEXEC); | |
if (fs_fd < 0) | |
pexit("fsopen"); | |
r = sendfd(sock_fd, fs_fd); | |
if (r < 0) | |
pexit("sendfd"); | |
close(fs_fd); | |
fs_fd = recvfd(sock_fd); | |
if (fs_fd < 0) | |
pexit("recvfd"); | |
mnt_fd = fsmount(fs_fd, 0, 0); | |
if (mnt_fd < 0) | |
pexit("fsmount"); | |
close(fs_fd); | |
mkdir(BPFFS_MOUNT, 0755); | |
r = move_mount(mnt_fd, "", AT_FDCWD, BPFFS_MOUNT, MOVE_MOUNT_F_EMPTY_PATH); | |
if (r < 0) | |
pexit("move_mount"); | |
bpffs_fd = openat(mnt_fd, ".", O_RDONLY); | |
if (bpffs_fd < 0) | |
pexit("openat"); | |
token_fd = bpf_token_create(bpffs_fd, NULL); | |
if (token_fd < 0) | |
pexit("bpf_token_create"); | |
printf("BPF token fd: %d\n", token_fd); | |
} | |
void child(int sock_fd) | |
{ | |
int fs_fd; | |
int r; | |
fs_fd = recvfd(sock_fd); | |
if (fs_fd < 0) | |
pexit("recvfd"); | |
r = fsconfig(fs_fd, FSCONFIG_SET_STRING, "delegate_cmds", "any", 0); | |
if (r < 0) | |
pexit("fsconfig"); | |
r = fsconfig(fs_fd, FSCONFIG_SET_STRING, "delegate_maps", "any", 0); | |
if (r < 0) | |
pexit("fsconfig"); | |
r = fsconfig(fs_fd, FSCONFIG_SET_STRING, "delegate_progs", "any", 0); | |
if (r < 0) | |
pexit("fsconfig"); | |
r = fsconfig(fs_fd, FSCONFIG_SET_STRING, "delegate_attachs", "any", 0); | |
if (r < 0) | |
pexit("fsconfig"); | |
r = fsconfig(fs_fd, FSCONFIG_CMD_CREATE, NULL, NULL, 0); | |
if (r < 0) | |
pexit("fsconfig"); | |
r = sendfd(sock_fd, fs_fd); | |
if (r < 0) | |
pexit("sendfd"); | |
exit(0); | |
} | |
int main(void) | |
{ | |
int token_fds[2]; | |
int r; | |
r = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, token_fds); | |
if (r < 0) | |
pexit("socketpair"); | |
if (fork()) | |
parent(token_fds[0]); | |
else | |
child(token_fds[1]); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment