1*2d812311STao Chen // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2*2d812311STao Chen /* Copyright (C) 2025 Didi Technology Co., Tao Chen */ 3*2d812311STao Chen 4*2d812311STao Chen #ifndef _GNU_SOURCE 5*2d812311STao Chen #define _GNU_SOURCE 6*2d812311STao Chen #endif 7*2d812311STao Chen #include <errno.h> 8*2d812311STao Chen #include <fcntl.h> 9*2d812311STao Chen #include <stdbool.h> 10*2d812311STao Chen #include <stdio.h> 11*2d812311STao Chen #include <stdlib.h> 12*2d812311STao Chen #include <string.h> 13*2d812311STao Chen #include <unistd.h> 14*2d812311STao Chen #include <mntent.h> 15*2d812311STao Chen #include <sys/types.h> 16*2d812311STao Chen #include <sys/stat.h> 17*2d812311STao Chen 18*2d812311STao Chen #include "json_writer.h" 19*2d812311STao Chen #include "main.h" 20*2d812311STao Chen 21*2d812311STao Chen #define MOUNTS_FILE "/proc/mounts" 22*2d812311STao Chen 23*2d812311STao Chen static bool has_delegate_options(const char *mnt_ops) 24*2d812311STao Chen { 25*2d812311STao Chen return strstr(mnt_ops, "delegate_cmds") || 26*2d812311STao Chen strstr(mnt_ops, "delegate_maps") || 27*2d812311STao Chen strstr(mnt_ops, "delegate_progs") || 28*2d812311STao Chen strstr(mnt_ops, "delegate_attachs"); 29*2d812311STao Chen } 30*2d812311STao Chen 31*2d812311STao Chen static char *get_delegate_value(const char *opts, const char *key) 32*2d812311STao Chen { 33*2d812311STao Chen char *token, *rest, *ret = NULL; 34*2d812311STao Chen char *opts_copy = strdup(opts); 35*2d812311STao Chen 36*2d812311STao Chen if (!opts_copy) 37*2d812311STao Chen return NULL; 38*2d812311STao Chen 39*2d812311STao Chen for (token = strtok_r(opts_copy, ",", &rest); token; 40*2d812311STao Chen token = strtok_r(NULL, ",", &rest)) { 41*2d812311STao Chen if (strncmp(token, key, strlen(key)) == 0 && 42*2d812311STao Chen token[strlen(key)] == '=') { 43*2d812311STao Chen ret = token + strlen(key) + 1; 44*2d812311STao Chen break; 45*2d812311STao Chen } 46*2d812311STao Chen } 47*2d812311STao Chen free(opts_copy); 48*2d812311STao Chen 49*2d812311STao Chen return ret; 50*2d812311STao Chen } 51*2d812311STao Chen 52*2d812311STao Chen static void print_items_per_line(const char *input, int items_per_line) 53*2d812311STao Chen { 54*2d812311STao Chen char *str, *rest, *strs; 55*2d812311STao Chen int cnt = 0; 56*2d812311STao Chen 57*2d812311STao Chen if (!input) 58*2d812311STao Chen return; 59*2d812311STao Chen 60*2d812311STao Chen strs = strdup(input); 61*2d812311STao Chen if (!strs) 62*2d812311STao Chen return; 63*2d812311STao Chen 64*2d812311STao Chen for (str = strtok_r(strs, ":", &rest); str; 65*2d812311STao Chen str = strtok_r(NULL, ":", &rest)) { 66*2d812311STao Chen if (cnt % items_per_line == 0) 67*2d812311STao Chen printf("\n\t "); 68*2d812311STao Chen 69*2d812311STao Chen printf("%-20s", str); 70*2d812311STao Chen cnt++; 71*2d812311STao Chen } 72*2d812311STao Chen 73*2d812311STao Chen free(strs); 74*2d812311STao Chen } 75*2d812311STao Chen 76*2d812311STao Chen #define ITEMS_PER_LINE 4 77*2d812311STao Chen static void show_token_info_plain(struct mntent *mntent) 78*2d812311STao Chen { 79*2d812311STao Chen char *value; 80*2d812311STao Chen 81*2d812311STao Chen printf("token_info %s", mntent->mnt_dir); 82*2d812311STao Chen 83*2d812311STao Chen printf("\n\tallowed_cmds:"); 84*2d812311STao Chen value = get_delegate_value(mntent->mnt_opts, "delegate_cmds"); 85*2d812311STao Chen print_items_per_line(value, ITEMS_PER_LINE); 86*2d812311STao Chen 87*2d812311STao Chen printf("\n\tallowed_maps:"); 88*2d812311STao Chen value = get_delegate_value(mntent->mnt_opts, "delegate_maps"); 89*2d812311STao Chen print_items_per_line(value, ITEMS_PER_LINE); 90*2d812311STao Chen 91*2d812311STao Chen printf("\n\tallowed_progs:"); 92*2d812311STao Chen value = get_delegate_value(mntent->mnt_opts, "delegate_progs"); 93*2d812311STao Chen print_items_per_line(value, ITEMS_PER_LINE); 94*2d812311STao Chen 95*2d812311STao Chen printf("\n\tallowed_attachs:"); 96*2d812311STao Chen value = get_delegate_value(mntent->mnt_opts, "delegate_attachs"); 97*2d812311STao Chen print_items_per_line(value, ITEMS_PER_LINE); 98*2d812311STao Chen printf("\n"); 99*2d812311STao Chen } 100*2d812311STao Chen 101*2d812311STao Chen static void split_json_array_str(const char *input) 102*2d812311STao Chen { 103*2d812311STao Chen char *str, *rest, *strs; 104*2d812311STao Chen 105*2d812311STao Chen if (!input) { 106*2d812311STao Chen jsonw_start_array(json_wtr); 107*2d812311STao Chen jsonw_end_array(json_wtr); 108*2d812311STao Chen return; 109*2d812311STao Chen } 110*2d812311STao Chen 111*2d812311STao Chen strs = strdup(input); 112*2d812311STao Chen if (!strs) 113*2d812311STao Chen return; 114*2d812311STao Chen 115*2d812311STao Chen jsonw_start_array(json_wtr); 116*2d812311STao Chen for (str = strtok_r(strs, ":", &rest); str; 117*2d812311STao Chen str = strtok_r(NULL, ":", &rest)) { 118*2d812311STao Chen jsonw_string(json_wtr, str); 119*2d812311STao Chen } 120*2d812311STao Chen jsonw_end_array(json_wtr); 121*2d812311STao Chen 122*2d812311STao Chen free(strs); 123*2d812311STao Chen } 124*2d812311STao Chen 125*2d812311STao Chen static void show_token_info_json(struct mntent *mntent) 126*2d812311STao Chen { 127*2d812311STao Chen char *value; 128*2d812311STao Chen 129*2d812311STao Chen jsonw_start_object(json_wtr); 130*2d812311STao Chen 131*2d812311STao Chen jsonw_string_field(json_wtr, "token_info", mntent->mnt_dir); 132*2d812311STao Chen 133*2d812311STao Chen jsonw_name(json_wtr, "allowed_cmds"); 134*2d812311STao Chen value = get_delegate_value(mntent->mnt_opts, "delegate_cmds"); 135*2d812311STao Chen split_json_array_str(value); 136*2d812311STao Chen 137*2d812311STao Chen jsonw_name(json_wtr, "allowed_maps"); 138*2d812311STao Chen value = get_delegate_value(mntent->mnt_opts, "delegate_maps"); 139*2d812311STao Chen split_json_array_str(value); 140*2d812311STao Chen 141*2d812311STao Chen jsonw_name(json_wtr, "allowed_progs"); 142*2d812311STao Chen value = get_delegate_value(mntent->mnt_opts, "delegate_progs"); 143*2d812311STao Chen split_json_array_str(value); 144*2d812311STao Chen 145*2d812311STao Chen jsonw_name(json_wtr, "allowed_attachs"); 146*2d812311STao Chen value = get_delegate_value(mntent->mnt_opts, "delegate_attachs"); 147*2d812311STao Chen split_json_array_str(value); 148*2d812311STao Chen 149*2d812311STao Chen jsonw_end_object(json_wtr); 150*2d812311STao Chen } 151*2d812311STao Chen 152*2d812311STao Chen static int __show_token_info(struct mntent *mntent) 153*2d812311STao Chen { 154*2d812311STao Chen if (json_output) 155*2d812311STao Chen show_token_info_json(mntent); 156*2d812311STao Chen else 157*2d812311STao Chen show_token_info_plain(mntent); 158*2d812311STao Chen 159*2d812311STao Chen return 0; 160*2d812311STao Chen } 161*2d812311STao Chen 162*2d812311STao Chen static int show_token_info(void) 163*2d812311STao Chen { 164*2d812311STao Chen FILE *fp; 165*2d812311STao Chen struct mntent *ent; 166*2d812311STao Chen 167*2d812311STao Chen fp = setmntent(MOUNTS_FILE, "r"); 168*2d812311STao Chen if (!fp) { 169*2d812311STao Chen p_err("Failed to open: %s", MOUNTS_FILE); 170*2d812311STao Chen return -1; 171*2d812311STao Chen } 172*2d812311STao Chen 173*2d812311STao Chen if (json_output) 174*2d812311STao Chen jsonw_start_array(json_wtr); 175*2d812311STao Chen 176*2d812311STao Chen while ((ent = getmntent(fp)) != NULL) { 177*2d812311STao Chen if (strncmp(ent->mnt_type, "bpf", 3) == 0) { 178*2d812311STao Chen if (has_delegate_options(ent->mnt_opts)) 179*2d812311STao Chen __show_token_info(ent); 180*2d812311STao Chen } 181*2d812311STao Chen } 182*2d812311STao Chen 183*2d812311STao Chen if (json_output) 184*2d812311STao Chen jsonw_end_array(json_wtr); 185*2d812311STao Chen 186*2d812311STao Chen endmntent(fp); 187*2d812311STao Chen 188*2d812311STao Chen return 0; 189*2d812311STao Chen } 190*2d812311STao Chen 191*2d812311STao Chen static int do_show(int argc, char **argv) 192*2d812311STao Chen { 193*2d812311STao Chen if (argc) 194*2d812311STao Chen return BAD_ARG(); 195*2d812311STao Chen 196*2d812311STao Chen return show_token_info(); 197*2d812311STao Chen } 198*2d812311STao Chen 199*2d812311STao Chen static int do_help(int argc, char **argv) 200*2d812311STao Chen { 201*2d812311STao Chen if (json_output) { 202*2d812311STao Chen jsonw_null(json_wtr); 203*2d812311STao Chen return 0; 204*2d812311STao Chen } 205*2d812311STao Chen 206*2d812311STao Chen fprintf(stderr, 207*2d812311STao Chen "Usage: %1$s %2$s { show | list }\n" 208*2d812311STao Chen " %1$s %2$s help\n" 209*2d812311STao Chen "\n" 210*2d812311STao Chen "", 211*2d812311STao Chen bin_name, argv[-2]); 212*2d812311STao Chen return 0; 213*2d812311STao Chen } 214*2d812311STao Chen 215*2d812311STao Chen static const struct cmd cmds[] = { 216*2d812311STao Chen { "show", do_show }, 217*2d812311STao Chen { "list", do_show }, 218*2d812311STao Chen { "help", do_help }, 219*2d812311STao Chen { 0 } 220*2d812311STao Chen }; 221*2d812311STao Chen 222*2d812311STao Chen int do_token(int argc, char **argv) 223*2d812311STao Chen { 224*2d812311STao Chen return cmd_select(cmds, argc, argv, do_help); 225*2d812311STao Chen } 226