From: Mathieu Desnoyers Date: Tue, 17 Dec 2019 15:17:01 +0000 (-0500) Subject: ID tracker: implement vpid/uid/vuid/gid/vgid trackers X-Git-Tag: v2.12.0-pre~4 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=d1f652f8d4f6d1de8f6d32ae8711d6469c38892c;p=lttng-modules.git ID tracker: implement vpid/uid/vuid/gid/vgid trackers Co-developed-by: Jonathan Rajotte Signed-off-by: Jonathan Rajotte Signed-off-by: Mathieu Desnoyers --- diff --git a/Makefile b/Makefile index 709b5dc0..4a6ddbc5 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ ifneq ($(KERNELRELEASE),) lttng-context-hostname.o wrapper/random.o \ probes/lttng.o wrapper/trace-clock.o \ wrapper/page_alloc.o \ - lttng-tracker-pid.o \ + lttng-tracker-id.o \ lttng-filter.o lttng-filter-interpreter.o \ lttng-filter-specialize.o \ lttng-filter-validator.o \ diff --git a/lttng-abi.c b/lttng-abi.c index 5c6f384d..4df3d673 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -525,6 +525,27 @@ int lttng_abi_session_set_creation_time(struct lttng_session *session, return 0; } +static +enum tracker_type get_tracker_type(struct lttng_kernel_tracker_args *tracker) +{ + switch (tracker->type) { + case LTTNG_KERNEL_TRACKER_PID: + return TRACKER_PID; + case LTTNG_KERNEL_TRACKER_VPID: + return TRACKER_VPID; + case LTTNG_KERNEL_TRACKER_UID: + return TRACKER_UID; + case LTTNG_KERNEL_TRACKER_VUID: + return TRACKER_VUID; + case LTTNG_KERNEL_TRACKER_GID: + return TRACKER_GID; + case LTTNG_KERNEL_TRACKER_VGID: + return TRACKER_VGID; + default: + return TRACKER_UNKNOWN; + } +} + /** * lttng_session_ioctl - lttng session fd ioctl * @@ -542,9 +563,13 @@ int lttng_abi_session_set_creation_time(struct lttng_session *session, * LTTNG_KERNEL_METADATA * Returns a LTTng metadata file descriptor * LTTNG_KERNEL_SESSION_TRACK_PID - * Add PID to session tracker + * Add PID to session PID tracker * LTTNG_KERNEL_SESSION_UNTRACK_PID - * Remove PID from session tracker + * Remove PID from session PID tracker + * LTTNG_KERNEL_SESSION_TRACK_ID + * Add ID to tracker + * LTTNG_KERNEL_SESSION_UNTRACK_ID + * Remove ID from tracker * * The returned channel will be deleted when its file descriptor is closed. */ @@ -617,11 +642,54 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) METADATA_CHANNEL); } case LTTNG_KERNEL_SESSION_TRACK_PID: - return lttng_session_track_pid(session, (int) arg); + return lttng_session_track_id(session, TRACKER_PID, (int) arg); case LTTNG_KERNEL_SESSION_UNTRACK_PID: - return lttng_session_untrack_pid(session, (int) arg); + return lttng_session_untrack_id(session, TRACKER_PID, (int) arg); + case LTTNG_KERNEL_SESSION_TRACK_ID: + { + struct lttng_kernel_tracker_args tracker; + enum tracker_type tracker_type; + + if (copy_from_user(&tracker, + (struct lttng_kernel_tracker_args __user *) arg, + sizeof(struct lttng_kernel_tracker_args))) + return -EFAULT; + tracker_type = get_tracker_type(&tracker); + if (tracker_type == TRACKER_UNKNOWN) + return -EINVAL; + return lttng_session_track_id(session, tracker_type, tracker.id); + } + case LTTNG_KERNEL_SESSION_UNTRACK_ID: + { + struct lttng_kernel_tracker_args tracker; + enum tracker_type tracker_type; + + if (copy_from_user(&tracker, + (struct lttng_kernel_tracker_args __user *) arg, + sizeof(struct lttng_kernel_tracker_args))) + return -EFAULT; + tracker_type = get_tracker_type(&tracker); + if (tracker_type == TRACKER_UNKNOWN) + return -EINVAL; + return lttng_session_untrack_id(session, tracker_type, + tracker.id); + } case LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS: - return lttng_session_list_tracker_pids(session); + return lttng_session_list_tracker_ids(session, TRACKER_PID); + case LTTNG_KERNEL_SESSION_LIST_TRACKER_IDS: + { + struct lttng_kernel_tracker_args tracker; + enum tracker_type tracker_type; + + if (copy_from_user(&tracker, + (struct lttng_kernel_tracker_args __user *) arg, + sizeof(struct lttng_kernel_tracker_args))) + return -EFAULT; + tracker_type = get_tracker_type(&tracker); + if (tracker_type == TRACKER_UNKNOWN) + return -EINVAL; + return lttng_session_list_tracker_ids(session, tracker_type); + } case LTTNG_KERNEL_SESSION_METADATA_REGEN: return lttng_session_metadata_regenerate(session); case LTTNG_KERNEL_SESSION_STATEDUMP: diff --git a/lttng-abi.h b/lttng-abi.h index 9d345f4a..5c5d8256 100644 --- a/lttng-abi.h +++ b/lttng-abi.h @@ -208,6 +208,22 @@ struct lttng_kernel_filter_bytecode { char data[0]; } __attribute__((packed)); +enum lttng_kernel_tracker_type { + LTTNG_KERNEL_TRACKER_UNKNOWN = -1, + + LTTNG_KERNEL_TRACKER_PID = 0, + LTTNG_KERNEL_TRACKER_VPID = 1, + LTTNG_KERNEL_TRACKER_UID = 2, + LTTNG_KERNEL_TRACKER_VUID = 3, + LTTNG_KERNEL_TRACKER_GID = 4, + LTTNG_KERNEL_TRACKER_VGID = 5, +}; + +struct lttng_kernel_tracker_args { + enum lttng_kernel_tracker_type type; + int32_t id; +}; + /* LTTng file descriptor ioctl */ /* lttng-abi-old.h reserve 0x40, 0x41, 0x42, 0x43, and 0x44. */ #define LTTNG_KERNEL_SESSION _IO(0xF6, 0x45) @@ -233,6 +249,7 @@ struct lttng_kernel_filter_bytecode { _IOR(0xF6, 0x58, int32_t) #define LTTNG_KERNEL_SESSION_UNTRACK_PID \ _IOR(0xF6, 0x59, int32_t) + /* * ioctl 0x58 and 0x59 are duplicated here. It works, since _IOR vs _IO * are generating two different ioctl numbers, but this was not done on @@ -270,6 +287,14 @@ struct lttng_kernel_filter_bytecode { #define LTTNG_KERNEL_FILTER _IO(0xF6, 0x90) #define LTTNG_KERNEL_ADD_CALLSITE _IO(0xF6, 0x91) +/* Session FD ioctl (continued) */ +#define LTTNG_KERNEL_SESSION_LIST_TRACKER_IDS \ + _IOR(0xF6, 0xA0, struct lttng_kernel_tracker_args) +#define LTTNG_KERNEL_SESSION_TRACK_ID \ + _IOR(0xF6, 0xA1, struct lttng_kernel_tracker_args) +#define LTTNG_KERNEL_SESSION_UNTRACK_ID \ + _IOR(0xF6, 0xA2, struct lttng_kernel_tracker_args) + /* * LTTng-specific ioctls for the lib ringbuffer. * diff --git a/lttng-events.c b/lttng-events.c index 4588153b..1ccbffd6 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -149,6 +149,18 @@ struct lttng_session *lttng_session_create(void) for (i = 0; i < LTTNG_EVENT_HT_SIZE; i++) INIT_HLIST_HEAD(&session->events_ht.table[i]); list_add(&session->list, &sessions); + session->pid_tracker.session = session; + session->pid_tracker.tracker_type = TRACKER_PID; + session->vpid_tracker.session = session; + session->vpid_tracker.tracker_type = TRACKER_VPID; + session->uid_tracker.session = session; + session->uid_tracker.tracker_type = TRACKER_UID; + session->vuid_tracker.session = session; + session->vuid_tracker.tracker_type = TRACKER_VUID; + session->gid_tracker.session = session; + session->gid_tracker.tracker_type = TRACKER_GID; + session->vgid_tracker.session = session; + session->vgid_tracker.tracker_type = TRACKER_VGID; mutex_unlock(&sessions_mutex); return session; @@ -199,8 +211,12 @@ void lttng_session_destroy(struct lttng_session *session) } list_for_each_entry(metadata_stream, &session->metadata_cache->metadata_stream, list) _lttng_metadata_channel_hangup(metadata_stream); - if (session->pid_tracker) - lttng_pid_tracker_destroy(session->pid_tracker); + lttng_id_tracker_destroy(&session->pid_tracker, false); + lttng_id_tracker_destroy(&session->vpid_tracker, false); + lttng_id_tracker_destroy(&session->uid_tracker, false); + lttng_id_tracker_destroy(&session->vuid_tracker, false); + lttng_id_tracker_destroy(&session->gid_tracker, false); + lttng_id_tracker_destroy(&session->vgid_tracker, false); kref_put(&session->metadata_cache->refcount, metadata_cache_destroy); list_del(&session->list); mutex_unlock(&sessions_mutex); @@ -930,91 +946,85 @@ void _lttng_event_destroy(struct lttng_event *event) kmem_cache_free(event_cache, event); } -int lttng_session_track_pid(struct lttng_session *session, int pid) +struct lttng_id_tracker *get_tracker(struct lttng_session *session, + enum tracker_type tracker_type) +{ + switch (tracker_type) { + case TRACKER_PID: + return &session->pid_tracker; + case TRACKER_VPID: + return &session->vpid_tracker; + case TRACKER_UID: + return &session->uid_tracker; + case TRACKER_VUID: + return &session->vuid_tracker; + case TRACKER_GID: + return &session->gid_tracker; + case TRACKER_VGID: + return &session->vgid_tracker; + default: + WARN_ON_ONCE(1); + return NULL; + } +} + +int lttng_session_track_id(struct lttng_session *session, + enum tracker_type tracker_type, int id) { + struct lttng_id_tracker *tracker; int ret; - if (pid < -1) + tracker = get_tracker(session, tracker_type); + if (!tracker) + return -EINVAL; + if (id < -1) return -EINVAL; mutex_lock(&sessions_mutex); - if (pid == -1) { - /* track all pids: destroy tracker. */ - if (session->pid_tracker) { - struct lttng_pid_tracker *lpf; - - lpf = session->pid_tracker; - rcu_assign_pointer(session->pid_tracker, NULL); - synchronize_trace(); - lttng_pid_tracker_destroy(lpf); - } + if (id == -1) { + /* track all ids: destroy tracker. */ + lttng_id_tracker_destroy(tracker, true); ret = 0; } else { - if (!session->pid_tracker) { - struct lttng_pid_tracker *lpf; - - lpf = lttng_pid_tracker_create(); - if (!lpf) { - ret = -ENOMEM; - goto unlock; - } - ret = lttng_pid_tracker_add(lpf, pid); - rcu_assign_pointer(session->pid_tracker, lpf); - } else { - ret = lttng_pid_tracker_add(session->pid_tracker, pid); - } + ret = lttng_id_tracker_add(tracker, id); } -unlock: mutex_unlock(&sessions_mutex); return ret; } -int lttng_session_untrack_pid(struct lttng_session *session, int pid) +int lttng_session_untrack_id(struct lttng_session *session, + enum tracker_type tracker_type, int id) { + struct lttng_id_tracker *tracker; int ret; - if (pid < -1) + tracker = get_tracker(session, tracker_type); + if (!tracker) + return -EINVAL; + if (id < -1) return -EINVAL; mutex_lock(&sessions_mutex); - if (pid == -1) { - /* untrack all pids: replace by empty tracker. */ - struct lttng_pid_tracker *old_lpf = session->pid_tracker; - struct lttng_pid_tracker *lpf; - - lpf = lttng_pid_tracker_create(); - if (!lpf) { - ret = -ENOMEM; - goto unlock; - } - rcu_assign_pointer(session->pid_tracker, lpf); - synchronize_trace(); - if (old_lpf) - lttng_pid_tracker_destroy(old_lpf); - ret = 0; + if (id == -1) { + /* untrack all ids: replace by empty tracker. */ + ret = lttng_id_tracker_empty_set(tracker); } else { - if (!session->pid_tracker) { - ret = -ENOENT; - goto unlock; - } - ret = lttng_pid_tracker_del(session->pid_tracker, pid); + ret = lttng_id_tracker_del(tracker, id); } -unlock: mutex_unlock(&sessions_mutex); return ret; } static -void *pid_list_start(struct seq_file *m, loff_t *pos) +void *id_list_start(struct seq_file *m, loff_t *pos) { - struct lttng_session *session = m->private; - struct lttng_pid_tracker *lpf; - struct lttng_pid_hash_node *e; + struct lttng_id_tracker *id_tracker = m->private; + struct lttng_id_tracker_rcu *id_tracker_p = id_tracker->p; + struct lttng_id_hash_node *e; int iter = 0, i; mutex_lock(&sessions_mutex); - lpf = session->pid_tracker; - if (lpf) { - for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) { - struct hlist_head *head = &lpf->pid_hash[i]; + if (id_tracker_p) { + for (i = 0; i < LTTNG_ID_TABLE_SIZE; i++) { + struct hlist_head *head = &id_tracker_p->id_hash[i]; lttng_hlist_for_each_entry(e, head, hlist) { if (iter++ >= *pos) @@ -1022,9 +1032,9 @@ void *pid_list_start(struct seq_file *m, loff_t *pos) } } } else { - /* PID tracker disabled. */ + /* ID tracker disabled. */ if (iter >= *pos && iter == 0) { - return session; /* empty tracker */ + return id_tracker_p; /* empty tracker */ } iter++; } @@ -1034,18 +1044,17 @@ void *pid_list_start(struct seq_file *m, loff_t *pos) /* Called with sessions_mutex held. */ static -void *pid_list_next(struct seq_file *m, void *p, loff_t *ppos) +void *id_list_next(struct seq_file *m, void *p, loff_t *ppos) { - struct lttng_session *session = m->private; - struct lttng_pid_tracker *lpf; - struct lttng_pid_hash_node *e; + struct lttng_id_tracker *id_tracker = m->private; + struct lttng_id_tracker_rcu *id_tracker_p = id_tracker->p; + struct lttng_id_hash_node *e; int iter = 0, i; (*ppos)++; - lpf = session->pid_tracker; - if (lpf) { - for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) { - struct hlist_head *head = &lpf->pid_hash[i]; + if (id_tracker_p) { + for (i = 0; i < LTTNG_ID_TABLE_SIZE; i++) { + struct hlist_head *head = &id_tracker_p->id_hash[i]; lttng_hlist_for_each_entry(e, head, hlist) { if (iter++ >= *ppos) @@ -1053,9 +1062,9 @@ void *pid_list_next(struct seq_file *m, void *p, loff_t *ppos) } } } else { - /* PID tracker disabled. */ + /* ID tracker disabled. */ if (iter >= *ppos && iter == 0) - return session; /* empty tracker */ + return p; /* empty tracker */ iter++; } @@ -1064,67 +1073,91 @@ void *pid_list_next(struct seq_file *m, void *p, loff_t *ppos) } static -void pid_list_stop(struct seq_file *m, void *p) +void id_list_stop(struct seq_file *m, void *p) { mutex_unlock(&sessions_mutex); } static -int pid_list_show(struct seq_file *m, void *p) +int id_list_show(struct seq_file *m, void *p) { - int pid; + struct lttng_id_tracker *id_tracker = m->private; + struct lttng_id_tracker_rcu *id_tracker_p = id_tracker->p; + int id; - if (p == m->private) { + if (p == id_tracker_p) { /* Tracker disabled. */ - pid = -1; + id = -1; } else { - const struct lttng_pid_hash_node *e = p; + const struct lttng_id_hash_node *e = p; - pid = lttng_pid_tracker_get_node_pid(e); + id = lttng_id_tracker_get_node_id(e); + } + switch (id_tracker->tracker_type) { + case TRACKER_PID: + seq_printf(m, "process { pid = %d; };\n", id); + break; + case TRACKER_VPID: + seq_printf(m, "process { vpid = %d; };\n", id); + break; + case TRACKER_UID: + seq_printf(m, "user { uid = %d; };\n", id); + break; + case TRACKER_VUID: + seq_printf(m, "user { vuid = %d; };\n", id); + break; + case TRACKER_GID: + seq_printf(m, "group { gid = %d; };\n", id); + break; + case TRACKER_VGID: + seq_printf(m, "group { vgid = %d; };\n", id); + break; + default: + seq_printf(m, "UNKNOWN { field = %d };\n", id); } - seq_printf(m, "process { pid = %d; };\n", pid); return 0; } static -const struct seq_operations lttng_tracker_pids_list_seq_ops = { - .start = pid_list_start, - .next = pid_list_next, - .stop = pid_list_stop, - .show = pid_list_show, +const struct seq_operations lttng_tracker_ids_list_seq_ops = { + .start = id_list_start, + .next = id_list_next, + .stop = id_list_stop, + .show = id_list_show, }; static -int lttng_tracker_pids_list_open(struct inode *inode, struct file *file) +int lttng_tracker_ids_list_open(struct inode *inode, struct file *file) { - return seq_open(file, <tng_tracker_pids_list_seq_ops); + return seq_open(file, <tng_tracker_ids_list_seq_ops); } static -int lttng_tracker_pids_list_release(struct inode *inode, struct file *file) +int lttng_tracker_ids_list_release(struct inode *inode, struct file *file) { struct seq_file *m = file->private_data; - struct lttng_session *session = m->private; + struct lttng_id_tracker *id_tracker = m->private; int ret; - WARN_ON_ONCE(!session); + WARN_ON_ONCE(!id_tracker); ret = seq_release(inode, file); - if (!ret && session) - fput(session->file); + if (!ret) + fput(id_tracker->session->file); return ret; } -const struct file_operations lttng_tracker_pids_list_fops = { +const struct file_operations lttng_tracker_ids_list_fops = { .owner = THIS_MODULE, - .open = lttng_tracker_pids_list_open, + .open = lttng_tracker_ids_list_open, .read = seq_read, .llseek = seq_lseek, - .release = lttng_tracker_pids_list_release, + .release = lttng_tracker_ids_list_release, }; -int lttng_session_list_tracker_pids(struct lttng_session *session) +int lttng_session_list_tracker_ids(struct lttng_session *session, + enum tracker_type tracker_type) { - struct file *tracker_pids_list_file; + struct file *tracker_ids_list_file; struct seq_file *m; int file_fd, ret; @@ -1134,30 +1167,32 @@ int lttng_session_list_tracker_pids(struct lttng_session *session) goto fd_error; } - tracker_pids_list_file = anon_inode_getfile("[lttng_tracker_pids_list]", - <tng_tracker_pids_list_fops, + tracker_ids_list_file = anon_inode_getfile("[lttng_tracker_ids_list]", + <tng_tracker_ids_list_fops, NULL, O_RDWR); - if (IS_ERR(tracker_pids_list_file)) { - ret = PTR_ERR(tracker_pids_list_file); + if (IS_ERR(tracker_ids_list_file)) { + ret = PTR_ERR(tracker_ids_list_file); goto file_error; } if (!atomic_long_add_unless(&session->file->f_count, 1, LONG_MAX)) { ret = -EOVERFLOW; goto refcount_error; } - ret = lttng_tracker_pids_list_fops.open(NULL, tracker_pids_list_file); + ret = lttng_tracker_ids_list_fops.open(NULL, tracker_ids_list_file); if (ret < 0) goto open_error; - m = tracker_pids_list_file->private_data; - m->private = session; - fd_install(file_fd, tracker_pids_list_file); + m = tracker_ids_list_file->private_data; + + m->private = get_tracker(session, tracker_type); + BUG_ON(!m->private); + fd_install(file_fd, tracker_ids_list_file); return file_fd; open_error: atomic_long_dec(&session->file->f_count); refcount_error: - fput(tracker_pids_list_file); + fput(tracker_ids_list_file); file_error: put_unused_fd(file_fd); fd_error: diff --git a/lttng-events.h b/lttng-events.h index cdb520e8..78b427a3 100644 --- a/lttng-events.h +++ b/lttng-events.h @@ -489,19 +489,36 @@ struct lttng_dynamic_len_stack { DECLARE_PER_CPU(struct lttng_dynamic_len_stack, lttng_dynamic_len_stack); /* - * struct lttng_pid_tracker declared in header due to deferencing of *v + * struct lttng_id_tracker declared in header due to deferencing of *v * in RCU_INITIALIZER(v). */ -#define LTTNG_PID_HASH_BITS 6 -#define LTTNG_PID_TABLE_SIZE (1 << LTTNG_PID_HASH_BITS) +#define LTTNG_ID_HASH_BITS 6 +#define LTTNG_ID_TABLE_SIZE (1 << LTTNG_ID_HASH_BITS) -struct lttng_pid_tracker { - struct hlist_head pid_hash[LTTNG_PID_TABLE_SIZE]; +enum tracker_type { + TRACKER_PID, + TRACKER_VPID, + TRACKER_UID, + TRACKER_VUID, + TRACKER_GID, + TRACKER_VGID, + + TRACKER_UNKNOWN, +}; + +struct lttng_id_tracker_rcu { + struct hlist_head id_hash[LTTNG_ID_TABLE_SIZE]; +}; + +struct lttng_id_tracker { + struct lttng_session *session; + enum tracker_type tracker_type; + struct lttng_id_tracker_rcu *p; /* RCU dereferenced. */ }; -struct lttng_pid_hash_node { +struct lttng_id_hash_node { struct hlist_node hlist; - int pid; + int id; }; struct lttng_session { @@ -514,7 +531,12 @@ struct lttng_session { unsigned int free_chan_id; /* Next chan ID to allocate */ uuid_le uuid; /* Trace session unique ID */ struct lttng_metadata_cache *metadata_cache; - struct lttng_pid_tracker *pid_tracker; + struct lttng_id_tracker pid_tracker; + struct lttng_id_tracker vpid_tracker; + struct lttng_id_tracker uid_tracker; + struct lttng_id_tracker vuid_tracker; + struct lttng_id_tracker gid_tracker; + struct lttng_id_tracker vgid_tracker; unsigned int metadata_dumped:1, tstate:1; /* Transient enable state */ /* List of enablers */ @@ -611,17 +633,20 @@ void lttng_probes_exit(void); int lttng_metadata_output_channel(struct lttng_metadata_stream *stream, struct channel *chan); -int lttng_pid_tracker_get_node_pid(const struct lttng_pid_hash_node *node); -struct lttng_pid_tracker *lttng_pid_tracker_create(void); -void lttng_pid_tracker_destroy(struct lttng_pid_tracker *lpf); -bool lttng_pid_tracker_lookup(struct lttng_pid_tracker *lpf, int pid); -int lttng_pid_tracker_add(struct lttng_pid_tracker *lpf, int pid); -int lttng_pid_tracker_del(struct lttng_pid_tracker *lpf, int pid); +int lttng_id_tracker_get_node_id(const struct lttng_id_hash_node *node); +int lttng_id_tracker_empty_set(struct lttng_id_tracker *lf); +void lttng_id_tracker_destroy(struct lttng_id_tracker *lf, bool rcu); +bool lttng_id_tracker_lookup(struct lttng_id_tracker_rcu *p, int id); +int lttng_id_tracker_add(struct lttng_id_tracker *lf, int id); +int lttng_id_tracker_del(struct lttng_id_tracker *lf, int id); -int lttng_session_track_pid(struct lttng_session *session, int pid); -int lttng_session_untrack_pid(struct lttng_session *session, int pid); +int lttng_session_track_id(struct lttng_session *session, + enum tracker_type tracker_type, int id); +int lttng_session_untrack_id(struct lttng_session *session, + enum tracker_type tracker_type, int id); -int lttng_session_list_tracker_pids(struct lttng_session *session); +int lttng_session_list_tracker_ids(struct lttng_session *session, + enum tracker_type tracker_type); void lttng_clock_ref(void); void lttng_clock_unref(void); diff --git a/lttng-tracker-id.c b/lttng-tracker-id.c new file mode 100644 index 00000000..9a4b98b2 --- /dev/null +++ b/lttng-tracker-id.c @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-tracker-pid.c + * + * LTTng Process ID tracking. + * + * Copyright (C) 2014 Mathieu Desnoyers + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Hash table is allocated and freed when there are no possible + * concurrent lookups (ensured by the alloc/free caller). However, + * there can be concurrent RCU lookups vs add/del operations. + * + * Concurrent updates of the PID hash table are forbidden: the caller + * must ensure mutual exclusion. This is currently done by holding the + * sessions_mutex across calls to create, destroy, add, and del + * functions of this API. + */ +int lttng_id_tracker_get_node_id(const struct lttng_id_hash_node *node) +{ + return node->id; +} + +/* + * Lookup performed from RCU read-side critical section (RCU sched), + * protected by preemption off at the tracepoint call site. + * Return true if found, false if not found. + */ +bool lttng_id_tracker_lookup(struct lttng_id_tracker_rcu *p, int id) +{ + struct hlist_head *head; + struct lttng_id_hash_node *e; + uint32_t hash = hash_32(id, 32); + + head = &p->id_hash[hash & (LTTNG_ID_TABLE_SIZE - 1)]; + lttng_hlist_for_each_entry_rcu(e, head, hlist) { + if (id == e->id) + return true; /* Found */ + } + return false; +} +EXPORT_SYMBOL_GPL(lttng_id_tracker_lookup); + +static struct lttng_id_tracker_rcu *lttng_id_tracker_rcu_create(void) +{ + struct lttng_id_tracker_rcu *tracker; + + tracker = kzalloc(sizeof(struct lttng_id_tracker_rcu), GFP_KERNEL); + if (!tracker) + return NULL; + return tracker; +} + +/* + * Tracker add and del operations support concurrent RCU lookups. + */ +int lttng_id_tracker_add(struct lttng_id_tracker *lf, int id) +{ + struct hlist_head *head; + struct lttng_id_hash_node *e; + struct lttng_id_tracker_rcu *p = lf->p; + uint32_t hash = hash_32(id, 32); + bool allocated = false; + + if (!p) { + p = lttng_id_tracker_rcu_create(); + if (!p) + return -ENOMEM; + allocated = true; + } + head = &p->id_hash[hash & (LTTNG_ID_TABLE_SIZE - 1)]; + lttng_hlist_for_each_entry(e, head, hlist) { + if (id == e->id) + return -EEXIST; + } + e = kmalloc(sizeof(struct lttng_id_hash_node), GFP_KERNEL); + if (!e) + return -ENOMEM; + e->id = id; + hlist_add_head_rcu(&e->hlist, head); + if (allocated) { + rcu_assign_pointer(lf->p, p); + } + return 0; +} + +static +void id_tracker_del_node_rcu(struct lttng_id_hash_node *e) +{ + hlist_del_rcu(&e->hlist); + /* + * We choose to use a heavyweight synchronize on removal here, + * since removal of an ID from the tracker mask is a rare + * operation, and we don't want to use more cache lines than + * what we really need when doing the ID lookups, so we don't + * want to afford adding a rcu_head field to those pid hash + * node. + */ + synchronize_trace(); + kfree(e); +} + +/* + * This removal is only used on destroy, so it does not need to support + * concurrent RCU lookups. + */ +static +void id_tracker_del_node(struct lttng_id_hash_node *e) +{ + hlist_del(&e->hlist); + kfree(e); +} + +int lttng_id_tracker_del(struct lttng_id_tracker *lf, int id) +{ + struct hlist_head *head; + struct lttng_id_hash_node *e; + struct lttng_id_tracker_rcu *p = lf->p; + uint32_t hash = hash_32(id, 32); + + if (!p) + return -ENOENT; + head = &p->id_hash[hash & (LTTNG_ID_TABLE_SIZE - 1)]; + /* + * No need of _safe iteration, because we stop traversal as soon + * as we remove the entry. + */ + lttng_hlist_for_each_entry(e, head, hlist) { + if (id == e->id) { + id_tracker_del_node_rcu(e); + return 0; + } + } + return -ENOENT; /* Not found */ +} + +static void lttng_id_tracker_rcu_destroy(struct lttng_id_tracker_rcu *p) +{ + int i; + + if (!p) + return; + for (i = 0; i < LTTNG_ID_TABLE_SIZE; i++) { + struct hlist_head *head = &p->id_hash[i]; + struct lttng_id_hash_node *e; + struct hlist_node *tmp; + + lttng_hlist_for_each_entry_safe(e, tmp, head, hlist) + id_tracker_del_node(e); + } + kfree(p); +} + +int lttng_id_tracker_empty_set(struct lttng_id_tracker *lf) +{ + struct lttng_id_tracker_rcu *p, *oldp; + + p = lttng_id_tracker_rcu_create(); + if (!p) + return -ENOMEM; + oldp = lf->p; + rcu_assign_pointer(lf->p, p); + synchronize_trace(); + lttng_id_tracker_rcu_destroy(oldp); + return 0; +} + +void lttng_id_tracker_destroy(struct lttng_id_tracker *lf, bool rcu) +{ + struct lttng_id_tracker_rcu *p = lf->p; + + if (!lf->p) + return; + rcu_assign_pointer(lf->p, NULL); + if (rcu) + synchronize_trace(); + lttng_id_tracker_rcu_destroy(p); +} diff --git a/lttng-tracker-pid.c b/lttng-tracker-pid.c deleted file mode 100644 index 747aec20..00000000 --- a/lttng-tracker-pid.c +++ /dev/null @@ -1,145 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) - * - * lttng-tracker-pid.c - * - * LTTng Process ID tracking. - * - * Copyright (C) 2014 Mathieu Desnoyers - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Hash table is allocated and freed when there are no possible - * concurrent lookups (ensured by the alloc/free caller). However, - * there can be concurrent RCU lookups vs add/del operations. - * - * Concurrent updates of the PID hash table are forbidden: the caller - * must ensure mutual exclusion. This is currently done by holding the - * sessions_mutex across calls to create, destroy, add, and del - * functions of this API. - */ -int lttng_pid_tracker_get_node_pid(const struct lttng_pid_hash_node *node) -{ - return node->pid; -} - -/* - * Lookup performed from RCU read-side critical section (RCU sched), - * protected by preemption off at the tracepoint call site. - * Return 1 if found, 0 if not found. - */ -bool lttng_pid_tracker_lookup(struct lttng_pid_tracker *lpf, int pid) -{ - struct hlist_head *head; - struct lttng_pid_hash_node *e; - uint32_t hash = hash_32(pid, 32); - - head = &lpf->pid_hash[hash & (LTTNG_PID_TABLE_SIZE - 1)]; - lttng_hlist_for_each_entry_rcu(e, head, hlist) { - if (pid == e->pid) - return 1; /* Found */ - } - return 0; -} -EXPORT_SYMBOL_GPL(lttng_pid_tracker_lookup); - -/* - * Tracker add and del operations support concurrent RCU lookups. - */ -int lttng_pid_tracker_add(struct lttng_pid_tracker *lpf, int pid) -{ - struct hlist_head *head; - struct lttng_pid_hash_node *e; - uint32_t hash = hash_32(pid, 32); - - head = &lpf->pid_hash[hash & (LTTNG_PID_TABLE_SIZE - 1)]; - lttng_hlist_for_each_entry(e, head, hlist) { - if (pid == e->pid) - return -EEXIST; - } - e = kmalloc(sizeof(struct lttng_pid_hash_node), GFP_KERNEL); - if (!e) - return -ENOMEM; - e->pid = pid; - hlist_add_head_rcu(&e->hlist, head); - return 0; -} - -static -void pid_tracker_del_node_rcu(struct lttng_pid_hash_node *e) -{ - hlist_del_rcu(&e->hlist); - /* - * We choose to use a heavyweight synchronize on removal here, - * since removal of a PID from the tracker mask is a rare - * operation, and we don't want to use more cache lines than - * what we really need when doing the PID lookups, so we don't - * want to afford adding a rcu_head field to those pid hash - * node. - */ - synchronize_trace(); - kfree(e); -} - -/* - * This removal is only used on destroy, so it does not need to support - * concurrent RCU lookups. - */ -static -void pid_tracker_del_node(struct lttng_pid_hash_node *e) -{ - hlist_del(&e->hlist); - kfree(e); -} - -int lttng_pid_tracker_del(struct lttng_pid_tracker *lpf, int pid) -{ - struct hlist_head *head; - struct lttng_pid_hash_node *e; - uint32_t hash = hash_32(pid, 32); - - head = &lpf->pid_hash[hash & (LTTNG_PID_TABLE_SIZE - 1)]; - /* - * No need of _safe iteration, because we stop traversal as soon - * as we remove the entry. - */ - lttng_hlist_for_each_entry(e, head, hlist) { - if (pid == e->pid) { - pid_tracker_del_node_rcu(e); - return 0; - } - } - return -ENOENT; /* Not found */ -} - -struct lttng_pid_tracker *lttng_pid_tracker_create(void) -{ - return kzalloc(sizeof(struct lttng_pid_tracker), GFP_KERNEL); -} - -void lttng_pid_tracker_destroy(struct lttng_pid_tracker *lpf) -{ - int i; - - for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) { - struct hlist_head *head = &lpf->pid_hash[i]; - struct lttng_pid_hash_node *e; - struct hlist_node *tmp; - - lttng_hlist_for_each_entry_safe(e, tmp, head, hlist) - pid_tracker_del_node(e); - } - kfree(lpf); -} diff --git a/probes/lttng-tracepoint-event-impl.h b/probes/lttng-tracepoint-event-impl.h index 3fe9d995..39454fb3 100644 --- a/probes/lttng-tracepoint-event-impl.h +++ b/probes/lttng-tracepoint-event-impl.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -1127,7 +1128,7 @@ static void __event_probe__##_name(void *__data, _proto) \ struct probe_local_vars __tp_locvar; \ struct probe_local_vars *tp_locvar __attribute__((unused)) = \ &__tp_locvar; \ - struct lttng_pid_tracker *__lpf; \ + struct lttng_id_tracker_rcu *__lf; \ \ if (!_TP_SESSION_CHECK(session, __session)) \ return; \ @@ -1137,8 +1138,27 @@ static void __event_probe__##_name(void *__data, _proto) \ return; \ if (unlikely(!READ_ONCE(__event->enabled))) \ return; \ - __lpf = lttng_rcu_dereference(__session->pid_tracker); \ - if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->tgid))) \ + __lf = lttng_rcu_dereference(__session->pid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, current->tgid))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vpid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, task_tgid_vnr(current)))) \ + return; \ + __lf = lttng_rcu_dereference(__session->uid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kuid(&init_user_ns, current_uid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vuid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kuid(current_user_ns(), current_uid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->gid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kgid(&init_user_ns, current_gid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vgid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kgid(current_user_ns(), current_gid())))) \ return; \ __orig_dynamic_len_offset = this_cpu_ptr(<tng_dynamic_len_stack)->offset; \ __dynamic_len_idx = __orig_dynamic_len_offset; \ @@ -1201,7 +1221,7 @@ static void __event_probe__##_name(void *__data) \ struct probe_local_vars __tp_locvar; \ struct probe_local_vars *tp_locvar __attribute__((unused)) = \ &__tp_locvar; \ - struct lttng_pid_tracker *__lpf; \ + struct lttng_id_tracker_rcu *__lf; \ \ if (!_TP_SESSION_CHECK(session, __session)) \ return; \ @@ -1211,8 +1231,27 @@ static void __event_probe__##_name(void *__data) \ return; \ if (unlikely(!READ_ONCE(__event->enabled))) \ return; \ - __lpf = lttng_rcu_dereference(__session->pid_tracker); \ - if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->tgid))) \ + __lf = lttng_rcu_dereference(__session->pid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, current->tgid))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vpid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, task_tgid_vnr(current)))) \ + return; \ + __lf = lttng_rcu_dereference(__session->uid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kuid(&init_user_ns, current_uid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vuid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kuid(current_user_ns(), current_uid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->gid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kgid(&init_user_ns, current_gid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vgid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kgid(current_user_ns(), current_gid())))) \ return; \ __orig_dynamic_len_offset = this_cpu_ptr(<tng_dynamic_len_stack)->offset; \ __dynamic_len_idx = __orig_dynamic_len_offset; \