mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 04:04:43 +01:00
With "bpftool prog tracelog", bpftool prints messages from the trace pipe. To do so, it first needs to find the tracefs mount point to open the pipe. Bpftool looks at a few "default" locations, including /sys/kernel/debug/tracing and /sys/kernel/tracing. Some of these locations, namely /tracing and /trace, are not standard. They are in the list because some users used to hardcode the tracing directory to short names; but we have no compelling reason to look at these locations. If we fail to find the tracefs at the default locations, we have an additional step to find it by parsing /proc/mounts anyway, so it's safe to remove these entries from the list of default locations to check. Additionally, Alexei reports that looking for the tracefs at /sys/kernel/debug/tracing may automatically mount the file system under that location, and generate a kernel log message telling that auto-mounting there is deprecated. To avoid this message, let's swap the order for checking the potential mount points: try /sys/kernel/tracing first, which should be the standard location nowadays. The kernel log message may still appear if the tracefs is not mounted on /sys/kernel/tracing when we run bpftool. Reported-by: Alexei Starovoitov <ast@kernel.org> Closes: https://lore.kernel.org/r/CAADnVQLcMi5YQhZKsU4z3S2uVUAGu_62C33G2Zx_ruG3uXa-Ug@mail.gmail.com/ Signed-off-by: Quentin Monnet <qmo@kernel.org> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/r/20250915134209.36568-1-qmo@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
159 lines
3.2 KiB
C
159 lines
3.2 KiB
C
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
|
/* Copyright (c) 2015-2017 Daniel Borkmann */
|
|
/* Copyright (c) 2018 Netronome Systems, Inc. */
|
|
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <linux/magic.h>
|
|
#include <fcntl.h>
|
|
#include <sys/vfs.h>
|
|
|
|
#include "main.h"
|
|
|
|
#ifndef TRACEFS_MAGIC
|
|
# define TRACEFS_MAGIC 0x74726163
|
|
#endif
|
|
|
|
#define _textify(x) #x
|
|
#define textify(x) _textify(x)
|
|
|
|
FILE *trace_pipe_fd;
|
|
char *buff;
|
|
|
|
static int validate_tracefs_mnt(const char *mnt, unsigned long magic)
|
|
{
|
|
struct statfs st_fs;
|
|
|
|
if (statfs(mnt, &st_fs) < 0)
|
|
return -ENOENT;
|
|
if ((unsigned long)st_fs.f_type != magic)
|
|
return -ENOENT;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static bool
|
|
find_tracefs_mnt_single(unsigned long magic, char *mnt, const char *mntpt)
|
|
{
|
|
size_t src_len;
|
|
|
|
if (validate_tracefs_mnt(mntpt, magic))
|
|
return false;
|
|
|
|
src_len = strlen(mntpt);
|
|
if (src_len + 1 >= PATH_MAX) {
|
|
p_err("tracefs mount point name too long");
|
|
return false;
|
|
}
|
|
|
|
strcpy(mnt, mntpt);
|
|
return true;
|
|
}
|
|
|
|
static bool get_tracefs_pipe(char *mnt)
|
|
{
|
|
static const char * const known_mnts[] = {
|
|
"/sys/kernel/tracing",
|
|
"/sys/kernel/debug/tracing",
|
|
};
|
|
const char *pipe_name = "/trace_pipe";
|
|
const char *fstype = "tracefs";
|
|
char type[100], format[32];
|
|
const char * const *ptr;
|
|
bool found = false;
|
|
FILE *fp;
|
|
|
|
for (ptr = known_mnts; ptr < known_mnts + ARRAY_SIZE(known_mnts); ptr++)
|
|
if (find_tracefs_mnt_single(TRACEFS_MAGIC, mnt, *ptr))
|
|
goto exit_found;
|
|
|
|
fp = fopen("/proc/mounts", "r");
|
|
if (!fp)
|
|
return false;
|
|
|
|
/* Allow room for NULL terminating byte and pipe file name */
|
|
snprintf(format, sizeof(format), "%%*s %%%zus %%99s %%*s %%*d %%*d\\n",
|
|
PATH_MAX - strlen(pipe_name) - 1);
|
|
while (fscanf(fp, format, mnt, type) == 2)
|
|
if (strcmp(type, fstype) == 0) {
|
|
found = true;
|
|
break;
|
|
}
|
|
fclose(fp);
|
|
|
|
/* The string from fscanf() might be truncated, check mnt is valid */
|
|
if (found && validate_tracefs_mnt(mnt, TRACEFS_MAGIC))
|
|
goto exit_found;
|
|
|
|
if (block_mount)
|
|
return false;
|
|
|
|
p_info("could not find tracefs, attempting to mount it now");
|
|
strcpy(mnt, known_mnts[0]);
|
|
if (mount_tracefs(mnt))
|
|
return false;
|
|
|
|
exit_found:
|
|
strcat(mnt, pipe_name);
|
|
return true;
|
|
}
|
|
|
|
static void exit_tracelog(int signum)
|
|
{
|
|
fclose(trace_pipe_fd);
|
|
free(buff);
|
|
|
|
if (json_output) {
|
|
jsonw_end_array(json_wtr);
|
|
jsonw_destroy(&json_wtr);
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
int do_tracelog(int argc, char **argv)
|
|
{
|
|
const struct sigaction act = {
|
|
.sa_handler = exit_tracelog
|
|
};
|
|
char trace_pipe[PATH_MAX];
|
|
size_t buff_len = 0;
|
|
|
|
if (json_output)
|
|
jsonw_start_array(json_wtr);
|
|
|
|
if (!get_tracefs_pipe(trace_pipe))
|
|
return -1;
|
|
|
|
trace_pipe_fd = fopen(trace_pipe, "r");
|
|
if (!trace_pipe_fd) {
|
|
p_err("could not open trace pipe: %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
sigaction(SIGHUP, &act, NULL);
|
|
sigaction(SIGINT, &act, NULL);
|
|
sigaction(SIGTERM, &act, NULL);
|
|
while (1) {
|
|
ssize_t ret;
|
|
|
|
ret = getline(&buff, &buff_len, trace_pipe_fd);
|
|
if (ret <= 0) {
|
|
p_err("failed to read content from trace pipe: %s",
|
|
strerror(errno));
|
|
break;
|
|
}
|
|
if (json_output)
|
|
jsonw_string(json_wtr, buff);
|
|
else
|
|
printf("%s", buff);
|
|
}
|
|
|
|
fclose(trace_pipe_fd);
|
|
free(buff);
|
|
return -1;
|
|
}
|