aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Rostedt (Google) <rostedt@goodmis.org>2022-04-20 11:26:36 -0400
committerSteven Rostedt (Google) <rostedt@goodmis.org>2022-04-26 20:50:18 -0400
commitbcfcb50e4e8fa4ca73da600b215c35b8af3e8692 (patch)
treeba57978a9ec4bb3643c3e430549c4e02d3b42777
parentb94ae17125adaa7c22346e5c000e9c2e903a53b8 (diff)
downloadtrace-cmd-bcfcb50e4e8fa4ca73da600b215c35b8af3e8692.tar.gz
trace-cmd agent: Have -N take a host name
For security reasons, it is not safe to let a trace-cmd agent connect to *any* host. Have the -N option take a host name and only connect to that host. It still gives full control to any process on that host, but at least the agent is not fully open to *any* machine. Link: https://lore.kernel.org/linux-trace-devel/20220420152637.13105-11-rostedt@goodmis.org Link: https://lore.kernel.org/linux-trace-devel/20220417211315.1049221-2-rostedt@goodmis.org Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-rw-r--r--tracecmd/include/trace-local.h7
-rw-r--r--tracecmd/trace-agent.c34
-rw-r--r--tracecmd/trace-listen.c55
-rw-r--r--tracecmd/trace-record.c13
4 files changed, 97 insertions, 12 deletions
diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h
index 8c595957..e3fec131 100644
--- a/tracecmd/include/trace-local.h
+++ b/tracecmd/include/trace-local.h
@@ -122,7 +122,7 @@ void trace_convert(int argc, char **argv);
int trace_record_agent(struct tracecmd_msg_handle *msg_handle,
int cpus, int *fds,
int argc, char **argv, bool use_fifos,
- unsigned long long trace_id);
+ unsigned long long trace_id, const char *host);
struct hook_list;
@@ -267,6 +267,7 @@ struct buffer_instance {
struct tracecmd_msg_handle *msg_handle;
struct tracecmd_output *network_handle;
+ const char *host;
struct pid_addr_maps *pid_maps;
@@ -309,9 +310,13 @@ extern struct buffer_instance *first_instance;
#define START_PORT_SEARCH 1500
#define MAX_PORT_SEARCH 6000
+struct sockaddr_storage;
+
int trace_net_make(int port, enum port_type type);
int trace_net_search(int start_port, int *sfd, enum port_type type);
int trace_net_print_connection(int fd);
+bool trace_net_cmp_connection(struct sockaddr_storage *addr, const char *name);
+bool trace_net_cmp_connection_fd(int fd, const char *name);
struct buffer_instance *allocate_instance(const char *name);
void add_instance(struct buffer_instance *instance, int cpu_count);
diff --git a/tracecmd/trace-agent.c b/tracecmd/trace-agent.c
index 59cecae7..f0723a66 100644
--- a/tracecmd/trace-agent.c
+++ b/tracecmd/trace-agent.c
@@ -62,7 +62,8 @@ static void make_net(int nr, int *fds, unsigned int *ports)
}
}
-static void make_sockets(int nr, int *fds, unsigned int *ports, bool network)
+static void make_sockets(int nr, int *fds, unsigned int *ports,
+ const char * network)
{
if (network)
return make_net(nr, fds, ports);
@@ -109,7 +110,7 @@ static char *get_clock(int argc, char **argv)
return NULL;
}
-static void trace_print_connection(int fd, bool network)
+static void trace_print_connection(int fd, const char *network)
{
int ret;
@@ -121,7 +122,7 @@ static void trace_print_connection(int fd, bool network)
tracecmd_debug("Could not print connection fd:%d\n", fd);
}
-static void agent_handle(int sd, int nr_cpus, int page_size, bool network)
+static void agent_handle(int sd, int nr_cpus, int page_size, const char *network)
{
struct tracecmd_tsync_protos *tsync_protos = NULL;
struct tracecmd_time_sync *tsync = NULL;
@@ -203,7 +204,7 @@ static void agent_handle(int sd, int nr_cpus, int page_size, bool network)
die("Failed to send trace response");
trace_record_agent(msg_handle, nr_cpus, fds, argc, argv,
- use_fifos, trace_id);
+ use_fifos, trace_id, network);
if (tsync) {
tracecmd_tsync_with_host_stop(tsync);
@@ -248,14 +249,23 @@ static pid_t do_fork()
return fork();
}
-static void agent_serve(unsigned int port, bool do_daemon, bool network)
+static void agent_serve(unsigned int port, bool do_daemon, const char *network)
{
+ struct sockaddr_storage net_addr;
+ struct sockaddr *addr = NULL;
+ socklen_t *addr_len_p = NULL;
+ socklen_t addr_len = sizeof(net_addr);
int sd, cd, nr_cpus;
unsigned int cid;
pid_t pid;
signal(SIGCHLD, handle_sigchld);
+ if (network) {
+ addr = (struct sockaddr *)&net_addr;
+ addr_len_p = &addr_len;
+ }
+
nr_cpus = tracecmd_count_cpus();
page_size = getpagesize();
@@ -279,7 +289,7 @@ static void agent_serve(unsigned int port, bool do_daemon, bool network)
die("daemon");
for (;;) {
- cd = accept(sd, NULL, NULL);
+ cd = accept(sd, addr, addr_len_p);
if (cd < 0) {
if (errno == EINTR)
continue;
@@ -288,6 +298,12 @@ static void agent_serve(unsigned int port, bool do_daemon, bool network)
if (tracecmd_get_debug())
trace_print_connection(cd, network);
+ if (network && !trace_net_cmp_connection(&net_addr, network)) {
+ dprint("Client does not match '%s'\n", network);
+ close(cd);
+ continue;
+ }
+
if (handler_pid)
goto busy;
@@ -314,7 +330,7 @@ void trace_agent(int argc, char **argv)
{
bool do_daemon = false;
unsigned int port = TRACE_AGENT_DEFAULT_PORT;
- bool network = false;
+ const char *network = NULL;
if (argc < 2)
usage(argv);
@@ -332,7 +348,7 @@ void trace_agent(int argc, char **argv)
{NULL, 0, NULL, 0}
};
- c = getopt_long(argc-1, argv+1, "+hp:DN",
+ c = getopt_long(argc-1, argv+1, "+hp:DN:",
long_options, &option_index);
if (c == -1)
break;
@@ -341,7 +357,7 @@ void trace_agent(int argc, char **argv)
usage(argv);
break;
case 'N':
- network = true;
+ network = optarg;
break;
case 'p':
port = atoi(optarg);
diff --git a/tracecmd/trace-listen.c b/tracecmd/trace-listen.c
index b7be761d..86d2b9e9 100644
--- a/tracecmd/trace-listen.c
+++ b/tracecmd/trace-listen.c
@@ -756,6 +756,61 @@ static int do_fork(int cfd)
return 0;
}
+bool trace_net_cmp_connection(struct sockaddr_storage *addr, const char *name)
+{
+ char host[NI_MAXHOST], nhost[NI_MAXHOST];
+ char service[NI_MAXSERV];
+ socklen_t addr_len = sizeof(*addr);
+ struct addrinfo *result, *rp;
+ struct addrinfo hints;
+ bool found = false;
+ int s;
+
+ if (getnameinfo((struct sockaddr *)addr, addr_len,
+ host, NI_MAXHOST,
+ service, NI_MAXSERV, NI_NUMERICSERV))
+ return -1;
+
+ if (strcmp(host, name) == 0)
+ return true;
+
+ /* Check other IPs that name could be for */
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ /* Check other IPs that name could be for */
+ s = getaddrinfo(name, NULL, &hints, &result);
+ if (s != 0)
+ return false;
+
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ if (getnameinfo(rp->ai_addr, rp->ai_addrlen,
+ nhost, NI_MAXHOST,
+ service, NI_MAXSERV, NI_NUMERICSERV))
+ continue;
+ if (strcmp(host, nhost) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ freeaddrinfo(result);
+ return found;
+}
+
+bool trace_net_cmp_connection_fd(int fd, const char *name)
+{
+ struct sockaddr_storage addr;
+ socklen_t addr_len = sizeof(addr);
+
+ if (getpeername(fd, (struct sockaddr *)&addr, &addr_len))
+ return false;
+
+ return trace_net_cmp_connection(&addr, name);
+};
+
int trace_net_print_connection(int fd)
{
char host[NI_MAXHOST], service[NI_MAXSERV];
diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c
index 9c930920..27c4e7ba 100644
--- a/tracecmd/trace-record.c
+++ b/tracecmd/trace-record.c
@@ -3426,8 +3426,16 @@ static int create_recorder(struct buffer_instance *instance, int cpu,
if (is_agent(instance)) {
if (instance->use_fifos)
fd = instance->fds[cpu];
- else
+ else {
+ again:
fd = do_accept(instance->fds[cpu]);
+ if (instance->host &&
+ !trace_net_cmp_connection_fd(fd, instance->host)) {
+ dprint("Client does not match '%s' for cpu:%d\n",
+ instance->host, cpu);
+ goto again;
+ }
+ }
} else {
fd = connect_port(host, instance->client_ports[cpu],
instance->port_type);
@@ -7275,7 +7283,7 @@ int trace_record_agent(struct tracecmd_msg_handle *msg_handle,
int cpus, int *fds,
int argc, char **argv,
bool use_fifos,
- unsigned long long trace_id)
+ unsigned long long trace_id, const char *host)
{
struct common_record_context ctx;
char **argv_plus;
@@ -7304,6 +7312,7 @@ int trace_record_agent(struct tracecmd_msg_handle *msg_handle,
ctx.instance->use_fifos = use_fifos;
ctx.instance->flags |= BUFFER_FL_AGENT;
ctx.instance->msg_handle = msg_handle;
+ ctx.instance->host = host;
msg_handle->version = V3_PROTOCOL;
top_instance.trace_id = trace_id;
record_trace(argc, argv, &ctx);