X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=liblttng-ust-ctl%2Fustctl.c;h=65e95cf43adbae8bf3cec03bee211a050815fd77;hb=refs%2Fheads%2Fsow-2020-0002-rev2;hp=07267aed122ff469591b3062f628d5ecbfbbe89a;hpb=8406222c45d29b23064d688e33be84894a51baac;p=deliverable%2Flttng-ust.git diff --git a/liblttng-ust-ctl/ustctl.c b/liblttng-ust-ctl/ustctl.c index 07267aed..65e95cf4 100644 --- a/liblttng-ust-ctl/ustctl.c +++ b/liblttng-ust-ctl/ustctl.c @@ -1,25 +1,16 @@ /* - * Copyright (C) 2011 - Julien Desfossez - * Copyright (C) 2011-2013 - Mathieu Desnoyers + * SPDX-License-Identifier: GPL-2.0-only * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License only. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Copyright (C) 2011 Julien Desfossez + * Copyright (C) 2011-2013 Mathieu Desnoyers */ #include #include #include #include +#include +#include #include #include @@ -36,6 +27,7 @@ #include "../liblttng-ust/lttng-rb-clients.h" #include "../liblttng-ust/clock.h" #include "../liblttng-ust/getenv.h" +#include "../liblttng-ust/lttng-tracer-core.h" #include "../libcounter/shm.h" #include "../libcounter/smp.h" @@ -78,6 +70,7 @@ struct ustctl_counter_attr { uint32_t nr_dimensions; int64_t global_sum_step; struct ustctl_counter_dimension dimensions[USTCTL_COUNTER_ATTR_DIMENSION_MAX]; + bool coalesce_hits; }; /* @@ -99,9 +92,13 @@ extern void lttng_ring_buffer_client_overwrite_rt_exit(void); extern void lttng_ring_buffer_client_discard_exit(void); extern void lttng_ring_buffer_client_discard_rt_exit(void); extern void lttng_ring_buffer_metadata_client_exit(void); +LTTNG_HIDDEN extern void lttng_counter_client_percpu_32_modular_init(void); +LTTNG_HIDDEN extern void lttng_counter_client_percpu_32_modular_exit(void); +LTTNG_HIDDEN extern void lttng_counter_client_percpu_64_modular_init(void); +LTTNG_HIDDEN extern void lttng_counter_client_percpu_64_modular_exit(void); int ustctl_release_handle(int sock, int handle) @@ -163,6 +160,7 @@ int ustctl_release_object(int sock, struct lttng_ust_object_data *data) case LTTNG_UST_OBJECT_TYPE_CONTEXT: case LTTNG_UST_OBJECT_TYPE_EVENT_NOTIFIER_GROUP: case LTTNG_UST_OBJECT_TYPE_EVENT_NOTIFIER: + case LTTNG_UST_OBJECT_TYPE_COUNTER_EVENT: break; case LTTNG_UST_OBJECT_TYPE_COUNTER: free(data->u.counter.data); @@ -579,7 +577,7 @@ int ustctl_create_event_notifier(int sock, struct lttng_ust_event_notifier *even lum.cmd = LTTNG_UST_EVENT_NOTIFIER_CREATE; lum.u.event_notifier.len = sizeof(*event_notifier); - ret = ustcomm_send_app_cmd(sock, &lum, &lur); + ret = ustcomm_send_app_msg(sock, &lum); if (ret) { free(event_notifier_data); return ret; @@ -587,11 +585,17 @@ int ustctl_create_event_notifier(int sock, struct lttng_ust_event_notifier *even /* Send struct lttng_ust_event_notifier */ len = ustcomm_send_unix_sock(sock, event_notifier, sizeof(*event_notifier)); if (len != sizeof(*event_notifier)) { + free(event_notifier_data); if (len < 0) return len; else return -EIO; } + ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); + if (ret) { + free(event_notifier_data); + return ret; + } event_notifier_data->handle = lur.ret_val; DBG("received event_notifier handle %u", event_notifier_data->handle); *_event_notifier_data = event_notifier_data; @@ -2012,6 +2016,105 @@ int ustctl_has_perf_counters(void) #endif +#ifdef __linux__ +/* + * Override application pid/uid/gid with unix socket credentials. If + * the application announced a pid matching our view, it means it is + * within the same pid namespace, so expose the ppid provided by the + * application. + */ +static +int get_cred(int sock, + const struct ustctl_reg_msg *reg_msg, + uint32_t *pid, + uint32_t *ppid, + uint32_t *uid, + uint32_t *gid) +{ + struct ucred ucred; + socklen_t ucred_len = sizeof(struct ucred); + int ret; + + ret = getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &ucred_len); + if (ret) { + return -LTTNG_UST_ERR_PEERCRED; + } + DBG("Unix socket peercred [ pid: %u, uid: %u, gid: %u ], " + "application registered claiming [ pid: %u, ppid: %u, uid: %u, gid: %u ]", + ucred.pid, ucred.uid, ucred.gid, + reg_msg->pid, reg_msg->ppid, reg_msg->uid, reg_msg->gid); + if (!ucred.pid) { + ERR("Unix socket credential pid=0. Refusing application in distinct, non-nested pid namespace."); + return -LTTNG_UST_ERR_PEERCRED_PID; + } + *pid = ucred.pid; + *uid = ucred.uid; + *gid = ucred.gid; + if (ucred.pid == reg_msg->pid) { + *ppid = reg_msg->ppid; + } else { + *ppid = 0; + } + return 0; +} +#elif defined(__FreeBSD__) +#include +#include + +/* + * Override application uid/gid with unix socket credentials. Use the + * first group of the cr_groups. + * Use the pid and ppid provided by the application on registration. + */ +static +int get_cred(int sock, + const struct ustctl_reg_msg *reg_msg, + uint32_t *pid, + uint32_t *ppid, + uint32_t *uid, + uint32_t *gid) +{ + struct xucred xucred; + socklen_t xucred_len = sizeof(struct xucred); + int ret; + + ret = getsockopt(sock, SOL_SOCKET, LOCAL_PEERCRED, &xucred, &xucred_len); + if (ret) { + return -LTTNG_UST_ERR_PEERCRED; + } + if (xucred.cr_version != XUCRED_VERSION || xucred.cr_ngroups < 1) { + return -LTTNG_UST_ERR_PEERCRED; + } + DBG("Unix socket peercred [ uid: %u, gid: %u ], " + "application registered claiming [ pid: %d, ppid: %d, uid: %u, gid: %u ]", + xucred.cr_uid, xucred.cr_groups[0], + reg_msg->pid, reg_msg->ppid, reg_msg->uid, reg_msg->gid); + *pid = reg_msg->pid; + *ppid = reg_msg->ppid; + *uid = xucred.cr_uid; + *gid = xucred.cr_groups[0]; + return 0; +} +#else +#warning "Using insecure fallback: trusting user id provided by registered applications. Please consider implementing use of unix socket credentials on your platform." +static +int get_cred(int sock, + const struct ustctl_reg_msg *reg_msg, + uint32_t *pid, + uint32_t *ppid, + uint32_t *uid, + uint32_t *gid) +{ + DBG("Application registered claiming [ pid: %u, ppid: %d, uid: %u, gid: %u ]", + reg_msg->pid, reg_msg->ppid, reg_msg->uid, reg_msg->gid); + *pid = reg_msg->pid; + *ppid = reg_msg->ppid; + *uid = reg_msg->uid; + *gid = reg_msg->gid; + return 0; +} +#endif + /* * Returns 0 on success, negative error value on error. */ @@ -2062,10 +2165,6 @@ int ustctl_recv_reg_msg(int sock, } *major = reg_msg.major; *minor = reg_msg.minor; - *pid = reg_msg.pid; - *ppid = reg_msg.ppid; - *uid = reg_msg.uid; - *gid = reg_msg.gid; *bits_per_long = reg_msg.bits_per_long; *uint8_t_alignment = reg_msg.uint8_t_alignment; *uint16_t_alignment = reg_msg.uint16_t_alignment; @@ -2077,8 +2176,7 @@ int ustctl_recv_reg_msg(int sock, reg_msg.major > LTTNG_UST_ABI_MAJOR_VERSION) { return -LTTNG_UST_ERR_UNSUP_MAJOR; } - - return 0; + return get_cred(sock, ®_msg, pid, ppid, uid, gid); } int ustctl_recv_notify(int sock, enum ustctl_notify_cmd *notify_cmd) @@ -2120,7 +2218,8 @@ int ustctl_recv_register_event(int sock, char **signature, size_t *nr_fields, struct ustctl_field **fields, - char **model_emf_uri) + char **model_emf_uri, + uint64_t *user_token) { ssize_t len; struct ustcomm_notify_event_msg msg; @@ -2143,6 +2242,7 @@ int ustctl_recv_register_event(int sock, *loglevel = msg.loglevel; signature_len = msg.signature_len; fields_len = msg.fields_len; + *user_token = msg.user_token; if (fields_len % sizeof(*a_fields) != 0) { return -EINVAL; @@ -2234,7 +2334,8 @@ signature_error: * Returns 0 on success, negative error value on error. */ int ustctl_reply_register_event(int sock, - uint32_t id, + uint32_t event_id, + uint64_t counter_index, int ret_code) { ssize_t len; @@ -2246,7 +2347,8 @@ int ustctl_reply_register_event(int sock, memset(&reply, 0, sizeof(reply)); reply.header.notify_cmd = USTCTL_NOTIFY_CMD_EVENT; reply.r.ret_code = ret_code; - reply.r.event_id = id; + reply.r.event_id = event_id; + reply.r.counter_index = counter_index; len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply)); if (len > 0 && len != sizeof(reply)) return -EIO; @@ -2471,13 +2573,14 @@ struct ustctl_daemon_counter * const int *counter_cpu_fds, enum ustctl_counter_bitness bitness, enum ustctl_counter_arithmetic arithmetic, - uint32_t alloc_flags) + uint32_t alloc_flags, + bool coalesce_hits) { const char *transport_name; struct ustctl_daemon_counter *counter; struct lttng_counter_transport *transport; - struct lttng_counter_dimension ust_dim[LTTNG_COUNTER_DIMENSION_MAX]; - size_t i; + struct lttng_ust_counter_dimension ust_dim[LTTNG_COUNTER_DIMENSION_MAX]; + size_t counter_len[LTTNG_COUNTER_DIMENSION_MAX], i; if (nr_dimensions > LTTNG_COUNTER_DIMENSION_MAX) return NULL; @@ -2527,6 +2630,14 @@ struct ustctl_daemon_counter * return NULL; } + for (i = 0; i < nr_dimensions; i++) { + if (dimensions[i].has_underflow) + return NULL; + if (dimensions[i].has_overflow) + return NULL; + counter_len[i] = ust_dim[i].size = dimensions[i].size; + } + counter = zmalloc(sizeof(*counter)); if (!counter) return NULL; @@ -2537,18 +2648,13 @@ struct ustctl_daemon_counter * counter->attr->arithmetic = arithmetic; counter->attr->nr_dimensions = nr_dimensions; counter->attr->global_sum_step = global_sum_step; + counter->attr->coalesce_hits = coalesce_hits; + for (i = 0; i < nr_dimensions; i++) counter->attr->dimensions[i] = dimensions[i]; - for (i = 0; i < nr_dimensions; i++) { - ust_dim[i].size = dimensions[i].size; - ust_dim[i].underflow_index = dimensions[i].underflow_index; - ust_dim[i].overflow_index = dimensions[i].overflow_index; - ust_dim[i].has_underflow = dimensions[i].has_underflow; - ust_dim[i].has_overflow = dimensions[i].has_overflow; - } counter->counter = transport->ops.counter_create(nr_dimensions, - ust_dim, global_sum_step, global_counter_fd, + counter_len, global_sum_step, global_counter_fd, nr_counter_cpu_fds, counter_cpu_fds, true); if (!counter->counter) goto free_attr; @@ -2592,6 +2698,7 @@ int ustctl_create_counter_data(struct ustctl_daemon_counter *counter, } counter_conf.number_dimensions = counter->attr->nr_dimensions; counter_conf.global_sum_step = counter->attr->global_sum_step; + counter_conf.coalesce_hits = counter->attr->coalesce_hits; for (i = 0; i < counter->attr->nr_dimensions; i++) { counter_conf.dimensions[i].size = counter->attr->dimensions[i].size; counter_conf.dimensions[i].underflow_index = counter->attr->dimensions[i].underflow_index; @@ -2798,6 +2905,53 @@ int ustctl_send_counter_cpu_data_to_ust(int sock, return ret; } +int ustctl_counter_create_event(int sock, + struct lttng_ust_counter_event *counter_event, + struct lttng_ust_object_data *counter_data, + struct lttng_ust_object_data **_counter_event_data) +{ + struct ustcomm_ust_msg lum; + struct ustcomm_ust_reply lur; + struct lttng_ust_object_data *counter_event_data; + ssize_t len; + int ret; + + if (!counter_data || !_counter_event_data) + return -EINVAL; + + counter_event_data = zmalloc(sizeof(*counter_event_data)); + if (!counter_event_data) + return -ENOMEM; + counter_event_data->type = LTTNG_UST_OBJECT_TYPE_COUNTER_EVENT; + memset(&lum, 0, sizeof(lum)); + lum.handle = counter_data->handle; + lum.cmd = LTTNG_UST_COUNTER_EVENT; + lum.u.counter_event.len = sizeof(*counter_event); + ret = ustcomm_send_app_msg(sock, &lum); + if (ret) { + free(counter_event_data); + return ret; + } + /* Send struct lttng_ust_counter_event */ + len = ustcomm_send_unix_sock(sock, counter_event, sizeof(*counter_event)); + if (len != sizeof(*counter_event)) { + free(counter_event_data); + if (len < 0) + return len; + else + return -EIO; + } + ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); + if (ret) { + free(counter_event_data); + return ret; + } + counter_event_data->handle = lur.ret_val; + DBG("received counter event handle %u", counter_event_data->handle); + *_counter_event_data = counter_event_data; + return 0; +} + int ustctl_counter_read(struct ustctl_daemon_counter *counter, const size_t *dimension_indexes, int cpu, int64_t *value,