Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BPF-CHECKPOINT-COMMIT
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bf4807c89d8f92c47404b1e4eeeefb42259d1b50
27861fc720be2c39b861d8bdfb68287f54de6855
2 changes: 1 addition & 1 deletion CHECKPOINT-COMMIT
Original file line number Diff line number Diff line change
@@ -1 +1 @@
e860a98c8aebd8de82c0ee901acf5a759acd4570
21aeabb68258ce17b91af113a768760b3a491d93
11 changes: 11 additions & 0 deletions bash-completion/bpftool
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,17 @@ _bpftool()
;;
esac
;;
token)
case $command in
show|list)
return 0
;;
*)
[[ $prev == $object ]] && \
COMPREPLY=( $( compgen -W 'help show list' -- "$cur" ) )
;;
esac
;;
esac
} &&
complete -F _bpftool bpftool
Expand Down
64 changes: 64 additions & 0 deletions docs/bpftool-token.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)

================
bpftool-token
================
-------------------------------------------------------------------------------
tool for inspection and simple manipulation of eBPF tokens
-------------------------------------------------------------------------------

:Manual section: 8

.. include:: substitutions.rst

SYNOPSIS
========

**bpftool** [*OPTIONS*] **token** *COMMAND*

*OPTIONS* := { |COMMON_OPTIONS| }

*COMMANDS* := { **show** | **list** | **help** }

TOKEN COMMANDS
===============

| **bpftool** **token** { **show** | **list** }
| **bpftool** **token help**
|

DESCRIPTION
===========
bpftool token { show | list }
List BPF token information for each *bpffs* mount point containing token
information on the system. Information include mount point path, allowed
**bpf**\ () system call commands, maps, programs, and attach types for the
token.

bpftool prog help
Print short help message.

OPTIONS
========
.. include:: common_options.rst

EXAMPLES
========
|
| **# mkdir -p /sys/fs/bpf/token**
| **# mount -t bpf bpffs /sys/fs/bpf/token** \
| **-o delegate_cmds=prog_load:map_create** \
| **-o delegate_progs=kprobe** \
| **-o delegate_attachs=xdp**
| **# bpftool token list**

::

token_info /sys/fs/bpf/token
allowed_cmds:
map_create prog_load
allowed_maps:
allowed_progs:
kprobe
allowed_attachs:
xdp
8 changes: 8 additions & 0 deletions include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ union bpf_iter_link_info {
* * **struct bpf_map_info**
* * **struct bpf_btf_info**
* * **struct bpf_link_info**
* * **struct bpf_token_info**
*
* Return
* Returns zero on success. On error, -1 is returned and *errno*
Expand Down Expand Up @@ -6803,6 +6804,13 @@ struct bpf_link_info {
};
} __attribute__((aligned(8)));

struct bpf_token_info {
__u64 allowed_cmds;
__u64 allowed_maps;
__u64 allowed_progs;
__u64 allowed_attachs;
} __attribute__((aligned(8)));

/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed
* by user and intended to be used by socket (e.g. to bind to, depends on
* attach type).
Expand Down
3 changes: 2 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static int do_help(int argc, char **argv)
" %s batch file FILE\n"
" %s version\n"
"\n"
" OBJECT := { prog | map | link | cgroup | perf | net | feature | btf | gen | struct_ops | iter }\n"
" OBJECT := { prog | map | link | cgroup | perf | net | feature | btf | gen | struct_ops | iter | token }\n"
" " HELP_SPEC_OPTIONS " |\n"
" {-V|--version} }\n"
"",
Expand All @@ -87,6 +87,7 @@ static const struct cmd commands[] = {
{ "gen", do_gen },
{ "struct_ops", do_struct_ops },
{ "iter", do_iter },
{ "token", do_token },
{ "version", do_version },
{ 0 }
};
Expand Down
1 change: 1 addition & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ int do_tracelog(int argc, char **arg) __weak;
int do_feature(int argc, char **argv) __weak;
int do_struct_ops(int argc, char **argv) __weak;
int do_iter(int argc, char **argv) __weak;
int do_token(int argc, char **argv) __weak;

int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
int prog_parse_fd(int *argc, char ***argv);
Expand Down
2 changes: 1 addition & 1 deletion src/prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,

if (mode == DUMP_JITED) {
if (info->jited_prog_len == 0 || !info->jited_prog_insns) {
p_info("no instructions returned");
p_err("error retrieving jit dump: no instructions returned or kernel.kptr_restrict set?");
return -1;
}
buf = u64_to_ptr(info->jited_prog_insns);
Expand Down
225 changes: 225 additions & 0 deletions src/token.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2025 Didi Technology Co., Tao Chen */

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <mntent.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "json_writer.h"
#include "main.h"

#define MOUNTS_FILE "/proc/mounts"

static bool has_delegate_options(const char *mnt_ops)
{
return strstr(mnt_ops, "delegate_cmds") ||
strstr(mnt_ops, "delegate_maps") ||
strstr(mnt_ops, "delegate_progs") ||
strstr(mnt_ops, "delegate_attachs");
}

static char *get_delegate_value(const char *opts, const char *key)
{
char *token, *rest, *ret = NULL;
char *opts_copy = strdup(opts);

if (!opts_copy)
return NULL;

for (token = strtok_r(opts_copy, ",", &rest); token;
token = strtok_r(NULL, ",", &rest)) {
if (strncmp(token, key, strlen(key)) == 0 &&
token[strlen(key)] == '=') {
ret = token + strlen(key) + 1;
break;
}
}
free(opts_copy);

return ret;
}

static void print_items_per_line(const char *input, int items_per_line)
{
char *str, *rest, *strs;
int cnt = 0;

if (!input)
return;

strs = strdup(input);
if (!strs)
return;

for (str = strtok_r(strs, ":", &rest); str;
str = strtok_r(NULL, ":", &rest)) {
if (cnt % items_per_line == 0)
printf("\n\t ");

printf("%-20s", str);
cnt++;
}

free(strs);
}

#define ITEMS_PER_LINE 4
static void show_token_info_plain(struct mntent *mntent)
{
char *value;

printf("token_info %s", mntent->mnt_dir);

printf("\n\tallowed_cmds:");
value = get_delegate_value(mntent->mnt_opts, "delegate_cmds");
print_items_per_line(value, ITEMS_PER_LINE);

printf("\n\tallowed_maps:");
value = get_delegate_value(mntent->mnt_opts, "delegate_maps");
print_items_per_line(value, ITEMS_PER_LINE);

printf("\n\tallowed_progs:");
value = get_delegate_value(mntent->mnt_opts, "delegate_progs");
print_items_per_line(value, ITEMS_PER_LINE);

printf("\n\tallowed_attachs:");
value = get_delegate_value(mntent->mnt_opts, "delegate_attachs");
print_items_per_line(value, ITEMS_PER_LINE);
printf("\n");
}

static void split_json_array_str(const char *input)
{
char *str, *rest, *strs;

if (!input) {
jsonw_start_array(json_wtr);
jsonw_end_array(json_wtr);
return;
}

strs = strdup(input);
if (!strs)
return;

jsonw_start_array(json_wtr);
for (str = strtok_r(strs, ":", &rest); str;
str = strtok_r(NULL, ":", &rest)) {
jsonw_string(json_wtr, str);
}
jsonw_end_array(json_wtr);

free(strs);
}

static void show_token_info_json(struct mntent *mntent)
{
char *value;

jsonw_start_object(json_wtr);

jsonw_string_field(json_wtr, "token_info", mntent->mnt_dir);

jsonw_name(json_wtr, "allowed_cmds");
value = get_delegate_value(mntent->mnt_opts, "delegate_cmds");
split_json_array_str(value);

jsonw_name(json_wtr, "allowed_maps");
value = get_delegate_value(mntent->mnt_opts, "delegate_maps");
split_json_array_str(value);

jsonw_name(json_wtr, "allowed_progs");
value = get_delegate_value(mntent->mnt_opts, "delegate_progs");
split_json_array_str(value);

jsonw_name(json_wtr, "allowed_attachs");
value = get_delegate_value(mntent->mnt_opts, "delegate_attachs");
split_json_array_str(value);

jsonw_end_object(json_wtr);
}

static int __show_token_info(struct mntent *mntent)
{
if (json_output)
show_token_info_json(mntent);
else
show_token_info_plain(mntent);

return 0;
}

static int show_token_info(void)
{
FILE *fp;
struct mntent *ent;

fp = setmntent(MOUNTS_FILE, "r");
if (!fp) {
p_err("Failed to open: %s", MOUNTS_FILE);
return -1;
}

if (json_output)
jsonw_start_array(json_wtr);

while ((ent = getmntent(fp)) != NULL) {
if (strncmp(ent->mnt_type, "bpf", 3) == 0) {
if (has_delegate_options(ent->mnt_opts))
__show_token_info(ent);
}
}

if (json_output)
jsonw_end_array(json_wtr);

endmntent(fp);

return 0;
}

static int do_show(int argc, char **argv)
{
if (argc)
return BAD_ARG();

return show_token_info();
}

static int do_help(int argc, char **argv)
{
if (json_output) {
jsonw_null(json_wtr);
return 0;
}

fprintf(stderr,
"Usage: %1$s %2$s { show | list }\n"
" %1$s %2$s help\n"
"\n"
"",
bin_name, argv[-2]);
return 0;
}

static const struct cmd cmds[] = {
{ "show", do_show },
{ "list", do_show },
{ "help", do_help },
{ 0 }
};

int do_token(int argc, char **argv)
{
return cmd_select(cmds, argc, argv, do_help);
}
Loading