]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: add BPF.NAME column
authorMasatake YAMATO <yamato@redhat.com>
Tue, 26 Sep 2023 16:12:16 +0000 (01:12 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Sat, 30 Sep 2023 12:16:36 +0000 (21:16 +0900)
An example output:

  $ sudo  ./lsfd -oCOMMAND,PID,ASSOC,TYPE,BPF.NAME,NAME -Q '(TYPE =~ "bpf-*")' -p 1
  COMMAND PID ASSOC     TYPE        BPF.NAME NAME
  systemd   1     9 bpf_link                 anon_inode:bpf_link
  systemd   1    13  bpf-map     cgroup_hash id=391 type=hash-of-maps name=cgroup_hash
  systemd   1    14 bpf-prog restrict_filesy id=8210 type=lsm name=restrict_filesy
  systemd   1    28 bpf-prog      sd_devices id=8298 type=cgroup_device name=sd_devices
  systemd   1    29 bpf-prog      sd_devices id=8299 type=cgroup_device name=sd_devices
  systemd   1    30 bpf-prog      sd_devices id=8300 type=cgroup_device name=sd_devices
  ...

Using memset was suggested by Thomas Weißschuh
<thomas@t-8ch.de>.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
misc-utils/lsfd-unkn.c
misc-utils/lsfd.c
misc-utils/lsfd.h

index 4d68f4010463698fc7ca0c341a6d6131ef8953a0..3b9902f58cd1f473797cd0482f2b7ee0f0634014 100644 (file)
@@ -19,6 +19,9 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/bpf.h>
+#include <stdalign.h>
+#include <sys/syscall.h>
 #include <sys/timerfd.h>
 #include <time.h>
 
@@ -27,6 +30,9 @@
 
 #include "lsfd.h"
 
+#define offsetofend(TYPE, MEMBER)                              \
+       (offsetof(TYPE, MEMBER) + sizeof_member(TYPE, MEMBER))
+
 struct unkn {
        struct file file;
        const struct anon_ops *anon_ops;
@@ -1021,6 +1027,7 @@ static const char *bpf_prog_type_table[] = {
 struct anon_bpf_prog_data {
        int type;
        int id;
+       char name[BPF_OBJ_NAME_LEN + 1];
 };
 
 static bool anon_bpf_prog_probe(const char *str)
@@ -1059,6 +1066,9 @@ static bool anon_bpf_prog_fill_column(struct proc *proc  __attribute__((__unused
                else
                        xasprintf(str, "UNKNOWN(%d)", data->type);
                return true;
+       case COL_BPF_NAME:
+               *str = xstrdup(data->name);
+               return true;
        default:
                return false;
        }
@@ -1076,6 +1086,9 @@ static char *anon_bpf_prog_get_name(struct unkn *unkn)
        else
                xasprintf(&str, "id=%d type=UNKNOWN(%d)", data->id, data->type);
 
+       if (*data->name)
+               xstrfappend(&str, " name=%s", data->name);
+
        return str;
 }
 
@@ -1085,6 +1098,7 @@ static void anon_bpf_prog_init(struct unkn *unkn)
        struct anon_bpf_prog_data *data = xmalloc(sizeof(*data));
        data->type = -1;
        data->id = -1;
+       data->name[0] = '\0';
        unkn->anon_data = data;
 }
 
@@ -1094,6 +1108,33 @@ static void anon_bpf_prog_free(struct unkn *unkn)
        free(data);
 }
 
+static void anon_bpf_prog_get_more_info(struct anon_bpf_prog_data *prog_data)
+{
+       union bpf_attr attr = {
+               .prog_id = (int32_t)prog_data->id,
+               .next_id = 0,
+               .open_flags = 0,
+       };
+       struct bpf_prog_info info = { 0 };
+       union bpf_attr info_attr = {
+               .info.info_len = sizeof(info),
+               .info.info = (uint64_t)(uintptr_t)&info,
+       };
+
+       int bpf_fd = syscall(SYS_bpf, BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
+       if (bpf_fd < 0)
+               return;
+
+       info_attr.info.bpf_fd = bpf_fd;
+       if (syscall(SYS_bpf, BPF_OBJ_GET_INFO_BY_FD, &info_attr, offsetofend(union bpf_attr, info)) == 0) {
+               memcpy(prog_data->name,
+                      info.name,
+                      BPF_OBJ_NAME_LEN);
+               prog_data->name[BPF_OBJ_NAME_LEN] = '\0';
+       }
+       close (bpf_fd);
+}
+
 static int anon_bpf_prog_handle_fdinfo(struct unkn *unkn, const char *key, const char *value)
 {
        if (strcmp(key, "prog_id") == 0) {
@@ -1102,6 +1143,7 @@ static int anon_bpf_prog_handle_fdinfo(struct unkn *unkn, const char *key, const
                if (rc < 0)
                        return 0; /* ignore -- parse failed */
                ((struct anon_bpf_prog_data *)unkn->anon_data)->id = (int)t;
+               anon_bpf_prog_get_more_info((struct anon_bpf_prog_data *)unkn->anon_data);
                return 1;
        }
 
@@ -1169,6 +1211,7 @@ static const char *bpf_map_type_table[] = {
 struct anon_bpf_map_data {
        int type;
        int id;
+       char name[BPF_OBJ_NAME_LEN + 1];
 };
 
 static bool anon_bpf_map_probe(const char *str)
@@ -1207,6 +1250,9 @@ static bool anon_bpf_map_fill_column(struct proc *proc  __attribute__((__unused_
                else
                        xasprintf(str, "UNKNOWN(%d)", data->type);
                return true;
+       case COL_BPF_NAME:
+               *str = xstrdup(data->name);
+               return true;
        default:
                return false;
        }
@@ -1223,6 +1269,10 @@ static char *anon_bpf_map_get_name(struct unkn *unkn)
                xasprintf(&str, "id=%d type=%s", data->id, t);
        else
                xasprintf(&str, "id=%d type=UNKNOWN(%d)", data->id, data->type);
+
+       if (*data->name)
+               xstrfappend(&str, " name=%s", data->name);
+
        return str;
 }
 
@@ -1231,6 +1281,7 @@ static void anon_bpf_map_init(struct unkn *unkn)
        struct anon_bpf_map_data *data = xmalloc(sizeof(*data));
        data->type = -1;
        data->id = -1;
+       data->name[0] = '\0';
        unkn->anon_data = data;
 }
 
@@ -1240,6 +1291,33 @@ static void anon_bpf_map_free(struct unkn *unkn)
        free(data);
 }
 
+static void anon_bpf_map_get_more_info(struct anon_bpf_map_data *map_data)
+{
+       union bpf_attr attr = {
+               .map_id = (int32_t)map_data->id,
+               .next_id = 0,
+               .open_flags = 0,
+       };
+       struct bpf_map_info info = { 0 };
+       union bpf_attr info_attr = {
+               .info.info_len = sizeof(info),
+               .info.info = (uint64_t)(uintptr_t)&info,
+       };
+
+       int bpf_fd = syscall(SYS_bpf, BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
+       if (bpf_fd < 0)
+               return;
+
+       info_attr.info.bpf_fd = bpf_fd;
+       if (syscall(SYS_bpf, BPF_OBJ_GET_INFO_BY_FD, &info_attr, offsetofend(union bpf_attr, info)) == 0) {
+               memcpy(map_data->name,
+                      info.name,
+                      BPF_OBJ_NAME_LEN);
+               map_data->name[BPF_OBJ_NAME_LEN] = '\0';
+       }
+       close (bpf_fd);
+}
+
 static int anon_bpf_map_handle_fdinfo(struct unkn *unkn, const char *key, const char *value)
 {
        if (strcmp(key, "map_id") == 0) {
@@ -1248,6 +1326,7 @@ static int anon_bpf_map_handle_fdinfo(struct unkn *unkn, const char *key, const
                if (rc < 0)
                        return 0; /* ignore -- parse failed */
                ((struct anon_bpf_map_data *)unkn->anon_data)->id = (int)t;
+               anon_bpf_map_get_more_info((struct anon_bpf_map_data *)unkn->anon_data);
                return 1;
        }
 
index d6bd6e971e67bd46a1ab5b6d3e2b120afb66704d..7d1d381fd8dd6cff23f58fa93107e88735d49040 100644 (file)
@@ -137,6 +137,9 @@ static const struct colinfo infos[] = {
        [COL_BPF_MAP_TYPE_RAW]= { "BPF-MAP.TYPE.RAW",
                                   0,   SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
                                   N_("bpf map type (raw)") },
+       [COL_BPF_NAME]         = { "BPF.NAME",
+                                  0,   SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
+                                  N_("bpf object name") },
        [COL_BPF_PROG_ID]      = { "BPF-PROG.ID",
                                   0,   SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
                                   N_("bpf program id associated with the fd") },
index 8cddc59ef25f06449fc3a8387ddf972962b1a1bd..9cf87f8308596d6a3d3b0b58917a8934b607db15 100644 (file)
@@ -46,6 +46,7 @@ enum {
        COL_BPF_MAP_ID,
        COL_BPF_MAP_TYPE,
        COL_BPF_MAP_TYPE_RAW,
+       COL_BPF_NAME,
        COL_BPF_PROG_ID,
        COL_BPF_PROG_TYPE,
        COL_BPF_PROG_TYPE_RAW,