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 \
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
*
* 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.
*/
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:
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)
_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
#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.
*
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;
}
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);
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)
}
}
} else {
- /* PID tracker disabled. */
+ /* ID tracker disabled. */
if (iter >= *pos && iter == 0) {
- return session; /* empty tracker */
+ return id_tracker_p; /* empty tracker */
}
iter++;
}
/* 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)
}
}
} else {
- /* PID tracker disabled. */
+ /* ID tracker disabled. */
if (iter >= *ppos && iter == 0)
- return session; /* empty tracker */
+ return p; /* empty tracker */
iter++;
}
}
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;
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:
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 {
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 */
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);
--- /dev/null
+/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
+ *
+ * lttng-tracker-pid.c
+ *
+ * LTTng Process ID tracking.
+ *
+ * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/seq_file.h>
+#include <linux/stringify.h>
+#include <linux/hash.h>
+#include <linux/rcupdate.h>
+
+#include <wrapper/tracepoint.h>
+#include <wrapper/rcu.h>
+#include <wrapper/list.h>
+#include <lttng-events.h>
+
+/*
+ * 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);
+}
+++ /dev/null
-/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
- *
- * lttng-tracker-pid.c
- *
- * LTTng Process ID tracking.
- *
- * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/seq_file.h>
-#include <linux/stringify.h>
-#include <linux/hash.h>
-#include <linux/rcupdate.h>
-
-#include <wrapper/tracepoint.h>
-#include <wrapper/rcu.h>
-#include <wrapper/list.h>
-#include <lttng-events.h>
-
-/*
- * 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);
-}
#include <linux/rculist.h>
#include <asm/byteorder.h>
#include <linux/swab.h>
+#include <linux/uidgid.h>
#include <probes/lttng.h>
#include <probes/lttng-types.h>
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; \
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; \
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; \
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; \