Add userspace namespace contexts
authorMichael Jeanson <mjeanson@efficios.com>
Tue, 12 Feb 2019 15:38:25 +0000 (10:38 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 18 Oct 2019 15:25:33 +0000 (11:25 -0400)
Add a context for each available kernel namespace which currently are :
cgroup, ipc, mnt, net, pid, user and uts. The id chosen to identify the
namespaces is the inode number of the file representing each one of them
in the proc filesystem.

This was introduced in kernel v3.8.0, if any of these context are
enabled on a system running an older kernel, zero will be returned.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
18 files changed:
doc/man/lttng-ust.3.txt
include/lttng/ust-abi.h
include/lttng/ust-events.h
include/lttng/ust.h
liblttng-ust-fork/ustfork.c
liblttng-ust/Makefile.am
liblttng-ust/lttng-context-cgroup-ns.c [new file with mode: 0644]
liblttng-ust/lttng-context-ipc-ns.c [new file with mode: 0644]
liblttng-ust/lttng-context-mnt-ns.c [new file with mode: 0644]
liblttng-ust/lttng-context-net-ns.c [new file with mode: 0644]
liblttng-ust/lttng-context-pid-ns.c [new file with mode: 0644]
liblttng-ust/lttng-context-user-ns.c [new file with mode: 0644]
liblttng-ust/lttng-context-uts-ns.c [new file with mode: 0644]
liblttng-ust/lttng-context.c
liblttng-ust/lttng-events.c
liblttng-ust/lttng-tracer-core.h
liblttng-ust/lttng-ust-comm.c
liblttng-ust/ns.h [new file with mode: 0644]

index 2a3003a72382a1efb6dcb8e75079db165957fa49..9865547eea36b3b1732408cb6206a6c1b97e01fb 100644 (file)
@@ -790,11 +790,41 @@ Only available on IA-32 and x86-64 architectures.
 
 `vpid`::
     Virtual process ID: process ID as seen from the point of view of
-    the process namespace.
+    the current man:pid_namespaces(7).
 
 `vtid`::
     Virtual thread ID: thread ID as seen from the point of view of
-    the process namespace.
+    the current man:pid_namespaces(7).
+
+The following man:namespaces(7) context fields are supported by LTTng-UST:
+
+`cgroup_ns`::
+    Cgroup root directory namespace: inode number of the current
+    man:cgroup_namespaces(7) in the proc filesystem.
+
+`ipc_ns`::
+    System V IPC, POSIX message queues namespace: inode number of the
+    current IPC namespace in the proc filesystem.
+
+`mnt_ns`::
+    Mount points namespace: inode number of the current Mount namespace
+    in the proc filesystem.
+
+`net_ns`::
+    Network devices, stacks, ports namespace: inode number of the
+    current Network namespace in the proc filesystem.
+
+`pid_ns`::
+    Process IDs namespace: inode number of the current
+    man:pid_namespaces(7) in the proc filesystem.
+
+`user_ns`::
+    User and group IDs namespace: inode number of the current
+    man:user_namespaces(7) in the proc filesystem.
+
+`uts_ns`::
+    Hostname and NIS domain name namespace: inode number of the
+    current UTS namespace in the proc filesystem.
 
 
 [[state-dump]]
index c1e13085bbf44cfa327aeabf5025e0c4f94c0aa6..d299b7deb9b874a0bc5ea2280a3f116c9e53495c 100644 (file)
@@ -145,6 +145,13 @@ enum lttng_ust_context_type {
        LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER   = 5,
        LTTNG_UST_CONTEXT_CPU_ID                = 6,
        LTTNG_UST_CONTEXT_APP_CONTEXT           = 7,
+       LTTNG_UST_CONTEXT_CGROUP_NS             = 8,
+       LTTNG_UST_CONTEXT_IPC_NS                = 9,
+       LTTNG_UST_CONTEXT_MNT_NS                = 10,
+       LTTNG_UST_CONTEXT_NET_NS                = 11,
+       LTTNG_UST_CONTEXT_PID_NS                = 12,
+       LTTNG_UST_CONTEXT_USER_NS               = 13,
+       LTTNG_UST_CONTEXT_UTS_NS                = 14,
 };
 
 struct lttng_ust_perf_counter_ctx {
index fefb8585536c6173e1d624954f58a8fba89421e9..c0ec3860f7dc3b2ec61e7ab33de33e4123b0b2d6 100644 (file)
@@ -679,9 +679,23 @@ int lttng_add_procname_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_ip_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_cpu_id_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_dyntest_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_cgroup_ns_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_ipc_ns_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_mnt_ns_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_net_ns_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_pid_ns_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_user_ns_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_uts_ns_to_ctx(struct lttng_ctx **ctx);
 void lttng_context_vtid_reset(void);
 void lttng_context_vpid_reset(void);
 void lttng_context_procname_reset(void);
+void lttng_context_cgroup_ns_reset(void);
+void lttng_context_ipc_ns_reset(void);
+void lttng_context_mnt_ns_reset(void);
+void lttng_context_net_ns_reset(void);
+void lttng_context_pid_ns_reset(void);
+void lttng_context_user_ns_reset(void);
+void lttng_context_uts_ns_reset(void);
 
 #ifdef LTTNG_UST_HAVE_PERF_EVENT
 int lttng_add_perf_counter_to_ctx(uint32_t type,
index 2779d7a76165b1c73735683bb61c2d74530cb5d7..0b2a8979a3002cca8f89c82052aafdd54e610f0e 100644 (file)
@@ -32,6 +32,8 @@ extern "C" {
 extern void ust_before_fork(sigset_t *save_sigset);
 extern void ust_after_fork_parent(sigset_t *restore_sigset);
 extern void ust_after_fork_child(sigset_t *restore_sigset);
+extern void ust_after_setns(void);
+extern void ust_after_unshare(void);
 
 #ifdef __cplusplus 
 }
index 71c4b86c1189ff7f89e1f7edba541c5d69d98df5..25f9d4cc04c31d2589e36d148684bf61d846c5aa 100644 (file)
@@ -160,6 +160,56 @@ int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...)
        return retval;
 }
 
+int setns(int fd, int nstype)
+{
+       static int (*plibc_func)(int fd, int nstype) = NULL;
+       int retval;
+       int saved_errno;
+
+       if (plibc_func == NULL) {
+               plibc_func = dlsym(RTLD_NEXT, "setns");
+               if (plibc_func == NULL) {
+                       fprintf(stderr, "libustfork: unable to find \"setns\" symbol\n");
+                       errno = ENOSYS;
+                       return -1;
+               }
+       }
+
+       /* Do the real setns */
+       retval = plibc_func(fd, nstype);
+       saved_errno = errno;
+
+       ust_after_setns();
+
+       errno = saved_errno;
+       return retval;
+}
+
+int unshare(int flags)
+{
+       static int (*plibc_func)(int flags) = NULL;
+       int retval;
+       int saved_errno;
+
+       if (plibc_func == NULL) {
+               plibc_func = dlsym(RTLD_NEXT, "unshare");
+               if (plibc_func == NULL) {
+                       fprintf(stderr, "libustfork: unable to find \"unshare\" symbol\n");
+                       errno = ENOSYS;
+                       return -1;
+               }
+       }
+
+       /* Do the real setns */
+       retval = plibc_func(flags);
+       saved_errno = errno;
+
+       ust_after_unshare();
+
+       errno = saved_errno;
+       return retval;
+}
+
 #elif defined (__FreeBSD__)
 
 pid_t rfork(int flags)
index 156552806943705c954031931ea2fd888596079f..1f167218af985bcdf6d71d67e152bd6895fd3ef0 100644 (file)
@@ -33,6 +33,13 @@ liblttng_ust_runtime_la_SOURCES = \
        lttng-context-procname.c \
        lttng-context-ip.c \
        lttng-context-cpu-id.c \
+       lttng-context-cgroup-ns.c \
+       lttng-context-ipc-ns.c \
+       lttng-context-mnt-ns.c \
+       lttng-context-net-ns.c \
+       lttng-context-pid-ns.c \
+       lttng-context-user-ns.c \
+       lttng-context-uts-ns.c \
        lttng-context.c \
        lttng-events.c \
        lttng-filter.c \
@@ -61,7 +68,8 @@ liblttng_ust_runtime_la_SOURCES = \
        lttng-ust-tracelog-provider.h \
        getenv.h \
        string-utils.c \
-       string-utils.h
+       string-utils.h \
+       ns.h
 
 if HAVE_PERF_EVENT
 liblttng_ust_runtime_la_SOURCES += \
diff --git a/liblttng-ust/lttng-context-cgroup-ns.c b/liblttng-ust/lttng-context-cgroup-ns.c
new file mode 100644 (file)
index 0000000..d405315
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * lttng-context-cgroup-ns.c
+ *
+ * LTTng UST cgroup namespace context.
+ *
+ * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *               2019 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+#include <lttng/ust-tid.h>
+#include <urcu/tls-compat.h>
+#include "lttng-tracer-core.h"
+#include "ns.h"
+
+
+/*
+ * We cache the result to ensure we don't stat(2) the proc filesystem on
+ * each event.
+ */
+static DEFINE_URCU_TLS(ino_t, cached_cgroup_ns) = NS_INO_UNINITIALIZED;
+
+static
+ino_t get_cgroup_ns(void)
+{
+       struct stat sb;
+       ino_t cgroup_ns;
+
+       cgroup_ns = CMM_LOAD_SHARED(URCU_TLS(cached_cgroup_ns));
+
+       /*
+        * If the cache is populated, do nothing and return the
+        * cached inode number.
+        */
+       if (caa_likely(cgroup_ns != NS_INO_UNINITIALIZED))
+               return cgroup_ns;
+
+       /*
+        * At this point we have to populate the cache, set the initial
+        * value to NS_INO_UNAVAILABLE (0), if we fail to get the inode
+        * number from the proc filesystem, this is the value we will
+        * cache.
+        */
+       cgroup_ns = NS_INO_UNAVAILABLE;
+
+       /*
+        * /proc/thread-self was introduced in kernel v3.17
+        */
+       if (stat("/proc/thread-self/ns/cgroup", &sb) == 0) {
+               cgroup_ns = sb.st_ino;
+       } else {
+               char proc_ns_path[LTTNG_PROC_NS_PATH_MAX];
+
+               if (snprintf(proc_ns_path, LTTNG_PROC_NS_PATH_MAX,
+                               "/proc/self/task/%d/ns/cgroup",
+                               lttng_gettid()) >= 0) {
+
+                       if (stat(proc_ns_path, &sb) == 0) {
+                               cgroup_ns = sb.st_ino;
+                       }
+               }
+       }
+
+       /*
+        * And finally, store the inode number in the cache.
+        */
+       CMM_STORE_SHARED(URCU_TLS(cached_cgroup_ns), cgroup_ns);
+
+       return cgroup_ns;
+}
+
+/*
+ * The cgroup namespace can change for 3 reasons
+ *  * clone(2) called with CLONE_NEWCGROUP
+ *  * setns(2) called with the fd of a different cgroup ns
+ *  * unshare(2) called with CLONE_NEWCGROUP
+ */
+void lttng_context_cgroup_ns_reset(void)
+{
+       CMM_STORE_SHARED(URCU_TLS(cached_cgroup_ns), NS_INO_UNINITIALIZED);
+}
+
+static
+size_t cgroup_ns_get_size(struct lttng_ctx_field *field, size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(ino_t));
+       size += sizeof(ino_t);
+       return size;
+}
+
+static
+void cgroup_ns_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan)
+{
+       ino_t cgroup_ns;
+
+       cgroup_ns = get_cgroup_ns();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(cgroup_ns));
+       chan->ops->event_write(ctx, &cgroup_ns, sizeof(cgroup_ns));
+}
+
+static
+void cgroup_ns_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value)
+{
+       value->u.s64 = get_cgroup_ns();
+}
+
+int lttng_add_cgroup_ns_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "cgroup_ns")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "cgroup_ns";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(ino_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = cgroup_ns_get_size;
+       field->record = cgroup_ns_record;
+       field->get_value = cgroup_ns_get_value;
+       lttng_context_update(*ctx);
+       return 0;
+}
+
+/*
+ *  * Force a read (imply TLS fixup for dlopen) of TLS variables.
+ *   */
+void lttng_fixup_cgroup_ns_tls(void)
+{
+       asm volatile ("" : : "m" (URCU_TLS(cached_cgroup_ns)));
+}
diff --git a/liblttng-ust/lttng-context-ipc-ns.c b/liblttng-ust/lttng-context-ipc-ns.c
new file mode 100644 (file)
index 0000000..c973dc8
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * lttng-context-ipc-ns.c
+ *
+ * LTTng UST ipc namespace context.
+ *
+ * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *               2019 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+#include <lttng/ust-tid.h>
+#include <urcu/tls-compat.h>
+#include "lttng-tracer-core.h"
+#include "ns.h"
+
+
+/*
+ * We cache the result to ensure we don't stat(2) the proc filesystem on
+ * each event.
+ */
+static DEFINE_URCU_TLS(ino_t, cached_ipc_ns) = NS_INO_UNINITIALIZED;
+
+static
+ino_t get_ipc_ns(void)
+{
+       struct stat sb;
+       ino_t ipc_ns;
+
+       ipc_ns = CMM_LOAD_SHARED(URCU_TLS(cached_ipc_ns));
+
+       /*
+        * If the cache is populated, do nothing and return the
+        * cached inode number.
+        */
+       if (caa_likely(ipc_ns != NS_INO_UNINITIALIZED))
+               return ipc_ns;
+
+       /*
+        * At this point we have to populate the cache, set the initial
+        * value to NS_INO_UNAVAILABLE (0), if we fail to get the inode
+        * number from the proc filesystem, this is the value we will
+        * cache.
+        */
+       ipc_ns = NS_INO_UNAVAILABLE;
+
+       /*
+        * /proc/thread-self was introduced in kernel v3.17
+        */
+       if (stat("/proc/thread-self/ns/ipc", &sb) == 0) {
+               ipc_ns = sb.st_ino;
+       } else {
+               char proc_ns_path[LTTNG_PROC_NS_PATH_MAX];
+
+               if (snprintf(proc_ns_path, LTTNG_PROC_NS_PATH_MAX,
+                               "/proc/self/task/%d/ns/ipc",
+                               lttng_gettid()) >= 0) {
+
+                       if (stat(proc_ns_path, &sb) == 0) {
+                               ipc_ns = sb.st_ino;
+                       }
+               }
+       }
+
+       /*
+        * And finally, store the inode number in the cache.
+        */
+       CMM_STORE_SHARED(URCU_TLS(cached_ipc_ns), ipc_ns);
+
+       return ipc_ns;
+}
+
+/*
+ * The ipc namespace can change for 3 reasons
+ *  * clone(2) called with CLONE_NEWIPC
+ *  * setns(2) called with the fd of a different ipc ns
+ *  * unshare(2) called with CLONE_NEWIPC
+ */
+void lttng_context_ipc_ns_reset(void)
+{
+       CMM_STORE_SHARED(URCU_TLS(cached_ipc_ns), NS_INO_UNINITIALIZED);
+}
+
+static
+size_t ipc_ns_get_size(struct lttng_ctx_field *field, size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(ino_t));
+       size += sizeof(ino_t);
+       return size;
+}
+
+static
+void ipc_ns_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan)
+{
+       ino_t ipc_ns;
+
+       ipc_ns = get_ipc_ns();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(ipc_ns));
+       chan->ops->event_write(ctx, &ipc_ns, sizeof(ipc_ns));
+}
+
+static
+void ipc_ns_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value)
+{
+       value->u.s64 = get_ipc_ns();
+}
+
+int lttng_add_ipc_ns_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "ipc_ns")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "ipc_ns";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(ino_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = ipc_ns_get_size;
+       field->record = ipc_ns_record;
+       field->get_value = ipc_ns_get_value;
+       lttng_context_update(*ctx);
+       return 0;
+}
+
+/*
+ *  * Force a read (imply TLS fixup for dlopen) of TLS variables.
+ *   */
+void lttng_fixup_ipc_ns_tls(void)
+{
+       asm volatile ("" : : "m" (URCU_TLS(cached_ipc_ns)));
+}
diff --git a/liblttng-ust/lttng-context-mnt-ns.c b/liblttng-ust/lttng-context-mnt-ns.c
new file mode 100644 (file)
index 0000000..d54c42a
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * lttng-context-mnt-ns.c
+ *
+ * LTTng UST mnt namespace context.
+ *
+ * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *               2019 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+
+#include "ns.h"
+
+/*
+ * We cache the result to ensure we don't stat(2) the proc filesystem on
+ * each event. The mount namespace is global to the process.
+ */
+static ino_t cached_mnt_ns = NS_INO_UNINITIALIZED;
+
+static
+ino_t get_mnt_ns(void)
+{
+       struct stat sb;
+       ino_t mnt_ns;
+
+       mnt_ns = CMM_LOAD_SHARED(cached_mnt_ns);
+
+       /*
+        * If the cache is populated, do nothing and return the
+        * cached inode number.
+        */
+       if (caa_likely(mnt_ns != NS_INO_UNINITIALIZED))
+               return mnt_ns;
+
+       /*
+        * At this point we have to populate the cache, set the initial
+        * value to NS_INO_UNAVAILABLE (0), if we fail to get the inode
+        * number from the proc filesystem, this is the value we will
+        * cache.
+        */
+       mnt_ns = NS_INO_UNAVAILABLE;
+
+       if (stat("/proc/self/ns/mnt", &sb) == 0) {
+               mnt_ns = sb.st_ino;
+       }
+
+       /*
+        * And finally, store the inode number in the cache.
+        */
+       CMM_STORE_SHARED(cached_mnt_ns, mnt_ns);
+
+       return mnt_ns;
+}
+
+/*
+ * The mnt namespace can change for 3 reasons
+ *  * clone(2) called with CLONE_NEWNS
+ *  * setns(2) called with the fd of a different mnt ns
+ *  * unshare(2) called with CLONE_NEWNS
+ */
+void lttng_context_mnt_ns_reset(void)
+{
+       CMM_STORE_SHARED(cached_mnt_ns, NS_INO_UNINITIALIZED);
+}
+
+static
+size_t mnt_ns_get_size(struct lttng_ctx_field *field, size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(ino_t));
+       size += sizeof(ino_t);
+       return size;
+}
+
+static
+void mnt_ns_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan)
+{
+       ino_t mnt_ns;
+
+       mnt_ns = get_mnt_ns();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(mnt_ns));
+       chan->ops->event_write(ctx, &mnt_ns, sizeof(mnt_ns));
+}
+
+static
+void mnt_ns_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value)
+{
+       value->u.s64 = get_mnt_ns();
+}
+
+int lttng_add_mnt_ns_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "mnt_ns")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "mnt_ns";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(ino_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = mnt_ns_get_size;
+       field->record = mnt_ns_record;
+       field->get_value = mnt_ns_get_value;
+       lttng_context_update(*ctx);
+       return 0;
+}
diff --git a/liblttng-ust/lttng-context-net-ns.c b/liblttng-ust/lttng-context-net-ns.c
new file mode 100644 (file)
index 0000000..9d6ded1
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * lttng-context-net-ns.c
+ *
+ * LTTng UST net namespace context.
+ *
+ * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *               2019 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+#include <lttng/ust-tid.h>
+#include <urcu/tls-compat.h>
+#include "lttng-tracer-core.h"
+#include "ns.h"
+
+
+/*
+ * We cache the result to ensure we don't stat(2) the proc filesystem on
+ * each event.
+ */
+static DEFINE_URCU_TLS(ino_t, cached_net_ns) = NS_INO_UNINITIALIZED;
+
+static
+ino_t get_net_ns(void)
+{
+       struct stat sb;
+       ino_t net_ns;
+
+       net_ns = CMM_LOAD_SHARED(URCU_TLS(cached_net_ns));
+
+       /*
+        * If the cache is populated, do nothing and return the
+        * cached inode number.
+        */
+       if (caa_likely(net_ns != NS_INO_UNINITIALIZED))
+               return net_ns;
+
+       /*
+        * At this point we have to populate the cache, set the initial
+        * value to NS_INO_UNAVAILABLE (0), if we fail to get the inode
+        * number from the proc filesystem, this is the value we will
+        * cache.
+        */
+       net_ns = NS_INO_UNAVAILABLE;
+
+       /*
+        * /proc/thread-self was introduced in kernel v3.17
+        */
+       if (stat("/proc/thread-self/ns/net", &sb) == 0) {
+               net_ns = sb.st_ino;
+       } else {
+               char proc_ns_path[LTTNG_PROC_NS_PATH_MAX];
+
+               if (snprintf(proc_ns_path, LTTNG_PROC_NS_PATH_MAX,
+                               "/proc/self/task/%d/ns/net",
+                               lttng_gettid()) >= 0) {
+
+                       if (stat(proc_ns_path, &sb) == 0) {
+                               net_ns = sb.st_ino;
+                       }
+               }
+       }
+
+       /*
+        * And finally, store the inode number in the cache.
+        */
+       CMM_STORE_SHARED(URCU_TLS(cached_net_ns), net_ns);
+
+       return net_ns;
+}
+
+/*
+ * The net namespace can change for 3 reasons
+ *  * clone(2) called with CLONE_NEWNET
+ *  * setns(2) called with the fd of a different net ns
+ *  * unshare(2) called with CLONE_NEWNET
+ */
+void lttng_context_net_ns_reset(void)
+{
+       CMM_STORE_SHARED(URCU_TLS(cached_net_ns), NS_INO_UNINITIALIZED);
+}
+
+static
+size_t net_ns_get_size(struct lttng_ctx_field *field, size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(ino_t));
+       size += sizeof(ino_t);
+       return size;
+}
+
+static
+void net_ns_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan)
+{
+       ino_t net_ns;
+
+       net_ns = get_net_ns();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(net_ns));
+       chan->ops->event_write(ctx, &net_ns, sizeof(net_ns));
+}
+
+static
+void net_ns_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value)
+{
+       value->u.s64 = get_net_ns();
+}
+
+int lttng_add_net_ns_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "net_ns")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "net_ns";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(ino_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = net_ns_get_size;
+       field->record = net_ns_record;
+       field->get_value = net_ns_get_value;
+       lttng_context_update(*ctx);
+       return 0;
+}
+
+/*
+ *  * Force a read (imply TLS fixup for dlopen) of TLS variables.
+ *   */
+void lttng_fixup_net_ns_tls(void)
+{
+       asm volatile ("" : : "m" (URCU_TLS(cached_net_ns)));
+}
diff --git a/liblttng-ust/lttng-context-pid-ns.c b/liblttng-ust/lttng-context-pid-ns.c
new file mode 100644 (file)
index 0000000..1581fb3
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * lttng-context-pid-ns.c
+ *
+ * LTTng UST pid namespace context.
+ *
+ * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *               2019 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+
+#include "ns.h"
+
+/*
+ * We cache the result to ensure we don't stat(2) the proc filesystem on
+ * each event. The PID namespace is global to the process.
+ */
+static ino_t cached_pid_ns = NS_INO_UNINITIALIZED;
+
+static
+ino_t get_pid_ns(void)
+{
+       struct stat sb;
+       ino_t pid_ns;
+
+       pid_ns = CMM_LOAD_SHARED(cached_pid_ns);
+
+       /*
+        * If the cache is populated, do nothing and return the
+        * cached inode number.
+        */
+       if (caa_likely(pid_ns != NS_INO_UNINITIALIZED))
+               return pid_ns;
+
+       /*
+        * At this point we have to populate the cache, set the initial
+        * value to NS_INO_UNAVAILABLE (0), if we fail to get the inode
+        * number from the proc filesystem, this is the value we will
+        * cache.
+        */
+       pid_ns = NS_INO_UNAVAILABLE;
+
+       if (stat("/proc/self/ns/pid", &sb) == 0) {
+               pid_ns = sb.st_ino;
+       }
+
+       /*
+        * And finally, store the inode number in the cache.
+        */
+       CMM_STORE_SHARED(cached_pid_ns, pid_ns);
+
+       return pid_ns;
+}
+
+/*
+ * A process's PID namespace membership is determined when the process is
+ * created and cannot be changed thereafter.
+ *
+ * The pid namespace can change only on clone(2) / fork(2) :
+ *  - clone(2) with the CLONE_NEWPID flag
+ *  - clone(2) / fork(2) after a call to unshare(2) with the CLONE_NEWPID flag
+ *  - clone(2) / fork(2) after a call to setns(2) with a PID namespace fd
+ */
+void lttng_context_pid_ns_reset(void)
+{
+       CMM_STORE_SHARED(cached_pid_ns, NS_INO_UNINITIALIZED);
+}
+
+static
+size_t pid_ns_get_size(struct lttng_ctx_field *field, size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(ino_t));
+       size += sizeof(ino_t);
+       return size;
+}
+
+static
+void pid_ns_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan)
+{
+       ino_t pid_ns;
+
+       pid_ns = get_pid_ns();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(pid_ns));
+       chan->ops->event_write(ctx, &pid_ns, sizeof(pid_ns));
+}
+
+static
+void pid_ns_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value)
+{
+       value->u.s64 = get_pid_ns();
+}
+
+int lttng_add_pid_ns_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "pid_ns")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "pid_ns";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(ino_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = pid_ns_get_size;
+       field->record = pid_ns_record;
+       field->get_value = pid_ns_get_value;
+       lttng_context_update(*ctx);
+       return 0;
+}
diff --git a/liblttng-ust/lttng-context-user-ns.c b/liblttng-ust/lttng-context-user-ns.c
new file mode 100644 (file)
index 0000000..04b940f
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * lttng-context-user-ns.c
+ *
+ * LTTng UST user namespace context.
+ *
+ * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *               2019 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+
+#include "ns.h"
+
+/*
+ * We cache the result to ensure we don't stat(2) the proc filesystem on
+ * each event. The user namespace is global to the process.
+ */
+static ino_t cached_user_ns = NS_INO_UNINITIALIZED;
+
+static
+ino_t get_user_ns(void)
+{
+       struct stat sb;
+       ino_t user_ns;
+
+       user_ns = CMM_LOAD_SHARED(cached_user_ns);
+
+       /*
+        * If the cache is populated, do nothing and return the
+        * cached inode number.
+        */
+       if (caa_likely(user_ns != NS_INO_UNINITIALIZED))
+               return user_ns;
+
+       /*
+        * At this point we have to populate the cache, set the initial
+        * value to NS_INO_UNAVAILABLE (0), if we fail to get the inode
+        * number from the proc filesystem, this is the value we will
+        * cache.
+        */
+       user_ns = NS_INO_UNAVAILABLE;
+
+       if (stat("/proc/self/ns/user", &sb) == 0) {
+               user_ns = sb.st_ino;
+       }
+
+       /*
+        * And finally, store the inode number in the cache.
+        */
+       CMM_STORE_SHARED(cached_user_ns, user_ns);
+
+       return user_ns;
+}
+
+/*
+ * The user namespace can change for 3 reasons
+ *  * clone(2) called with CLONE_NEWUSER
+ *  * setns(2) called with the fd of a different user ns
+ *  * unshare(2) called with CLONE_NEWUSER
+ */
+void lttng_context_user_ns_reset(void)
+{
+       CMM_STORE_SHARED(cached_user_ns, NS_INO_UNINITIALIZED);
+}
+
+static
+size_t user_ns_get_size(struct lttng_ctx_field *field, size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(ino_t));
+       size += sizeof(ino_t);
+       return size;
+}
+
+static
+void user_ns_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan)
+{
+       ino_t user_ns;
+
+       user_ns = get_user_ns();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(user_ns));
+       chan->ops->event_write(ctx, &user_ns, sizeof(user_ns));
+}
+
+static
+void user_ns_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value)
+{
+       value->u.s64 = get_user_ns();
+}
+
+int lttng_add_user_ns_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "user_ns")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "user_ns";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(ino_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = user_ns_get_size;
+       field->record = user_ns_record;
+       field->get_value = user_ns_get_value;
+       lttng_context_update(*ctx);
+       return 0;
+}
diff --git a/liblttng-ust/lttng-context-uts-ns.c b/liblttng-ust/lttng-context-uts-ns.c
new file mode 100644 (file)
index 0000000..fb2d89f
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * lttng-context-uts-ns.c
+ *
+ * LTTng UST uts namespace context.
+ *
+ * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *               2019 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+#include <lttng/ust-tid.h>
+#include <urcu/tls-compat.h>
+#include "lttng-tracer-core.h"
+#include "ns.h"
+
+
+/*
+ * We cache the result to ensure we don't stat(2) the proc filesystem on
+ * each event.
+ */
+static DEFINE_URCU_TLS(ino_t, cached_uts_ns) = NS_INO_UNINITIALIZED;
+
+static
+ino_t get_uts_ns(void)
+{
+       struct stat sb;
+       ino_t uts_ns;
+
+       uts_ns = CMM_LOAD_SHARED(URCU_TLS(cached_uts_ns));
+
+       /*
+        * If the cache is populated, do nothing and return the
+        * cached inode number.
+        */
+       if (caa_likely(uts_ns != NS_INO_UNINITIALIZED))
+               return uts_ns;
+
+       /*
+        * At this point we have to populate the cache, set the initial
+        * value to NS_INO_UNAVAILABLE (0), if we fail to get the inode
+        * number from the proc filesystem, this is the value we will
+        * cache.
+        */
+       uts_ns = NS_INO_UNAVAILABLE;
+
+       /*
+        * /proc/thread-self was introduced in kernel v3.17
+        */
+       if (stat("/proc/thread-self/ns/uts", &sb) == 0) {
+               uts_ns = sb.st_ino;
+       } else {
+               char proc_ns_path[LTTNG_PROC_NS_PATH_MAX];
+
+               if (snprintf(proc_ns_path, LTTNG_PROC_NS_PATH_MAX,
+                               "/proc/self/task/%d/ns/uts",
+                               lttng_gettid()) >= 0) {
+
+                       if (stat(proc_ns_path, &sb) == 0) {
+                               uts_ns = sb.st_ino;
+                       }
+               }
+       }
+
+       /*
+        * And finally, store the inode number in the cache.
+        */
+       CMM_STORE_SHARED(URCU_TLS(cached_uts_ns), uts_ns);
+
+       return uts_ns;
+}
+
+/*
+ * The uts namespace can change for 3 reasons
+ *  * clone(2) called with CLONE_NEWUTS
+ *  * setns(2) called with the fd of a different uts ns
+ *  * unshare(2) called with CLONE_NEWUTS
+ */
+void lttng_context_uts_ns_reset(void)
+{
+       CMM_STORE_SHARED(URCU_TLS(cached_uts_ns), NS_INO_UNINITIALIZED);
+}
+
+static
+size_t uts_ns_get_size(struct lttng_ctx_field *field, size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(ino_t));
+       size += sizeof(ino_t);
+       return size;
+}
+
+static
+void uts_ns_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan)
+{
+       ino_t uts_ns;
+
+       uts_ns = get_uts_ns();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uts_ns));
+       chan->ops->event_write(ctx, &uts_ns, sizeof(uts_ns));
+}
+
+static
+void uts_ns_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value)
+{
+       value->u.s64 = get_uts_ns();
+}
+
+int lttng_add_uts_ns_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "uts_ns")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "uts_ns";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(ino_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = uts_ns_get_size;
+       field->record = uts_ns_record;
+       field->get_value = uts_ns_get_value;
+       lttng_context_update(*ctx);
+       return 0;
+}
+
+/*
+ *  * Force a read (imply TLS fixup for dlopen) of TLS variables.
+ *   */
+void lttng_fixup_uts_ns_tls(void)
+{
+       asm volatile ("" : : "m" (URCU_TLS(cached_uts_ns)));
+}
index eeaaae4321219af741b83261e59d624ffda233eb..ad6c38f0241486f78392cb82f5348a15d83187a6 100644 (file)
@@ -372,6 +372,41 @@ int lttng_session_context_init(struct lttng_ctx **ctx)
                WARN("Cannot add context lttng_add_cpu_id_to_ctx");
                goto error;
        }
+       ret = lttng_add_cgroup_ns_to_ctx(ctx);
+       if (ret) {
+               WARN("Cannot add context lttng_add_cgroup_ns_to_ctx");
+               goto error;
+       }
+       ret = lttng_add_ipc_ns_to_ctx(ctx);
+       if (ret) {
+               WARN("Cannot add context lttng_add_ipc_ns_to_ctx");
+               goto error;
+       }
+       ret = lttng_add_mnt_ns_to_ctx(ctx);
+       if (ret) {
+               WARN("Cannot add context lttng_add_mnt_ns_to_ctx");
+               goto error;
+       }
+       ret = lttng_add_net_ns_to_ctx(ctx);
+       if (ret) {
+               WARN("Cannot add context lttng_add_net_ns_to_ctx");
+               goto error;
+       }
+       ret = lttng_add_pid_ns_to_ctx(ctx);
+       if (ret) {
+               WARN("Cannot add context lttng_add_pid_ns_to_ctx");
+               goto error;
+       }
+       ret = lttng_add_user_ns_to_ctx(ctx);
+       if (ret) {
+               WARN("Cannot add context lttng_add_user_ns_to_ctx");
+               goto error;
+       }
+       ret = lttng_add_uts_ns_to_ctx(ctx);
+       if (ret) {
+               WARN("Cannot add context lttng_add_uts_ns_to_ctx");
+               goto error;
+       }
        lttng_context_update(*ctx);
        return 0;
 
index 7aa288c75210d1da75d84cfef08f82cdbcc292bf..855f8d8739d1ff0ecb07d6779957c4f11153f9db 100644 (file)
@@ -1112,6 +1112,20 @@ int lttng_attach_context(struct lttng_ust_context *context_param,
        case LTTNG_UST_CONTEXT_APP_CONTEXT:
                return lttng_ust_add_app_context_to_ctx_rcu(uargs->app_context.ctxname,
                        ctx);
+       case LTTNG_UST_CONTEXT_CGROUP_NS:
+               return lttng_add_cgroup_ns_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_IPC_NS:
+               return lttng_add_ipc_ns_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_MNT_NS:
+               return lttng_add_mnt_ns_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_NET_NS:
+               return lttng_add_net_ns_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_PID_NS:
+               return lttng_add_pid_ns_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_USER_NS:
+               return lttng_add_user_ns_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_UTS_NS:
+               return lttng_add_uts_ns_to_ctx(ctx);
        default:
                return -EINVAL;
        }
index f750f4b01e89a32e7c2237da8847e1c9e42ce98f..52315a8de001227fecd02ae50749581b9a16edf9 100644 (file)
 #include <lttng/ringbuffer-config.h>
 #include <usterr-signal-safe.h>
 
+/*
+ * The longuest possible namespace proc path is with the cgroup ns
+ * and the maximum theoretical linux pid of 536870912 :
+ *
+ *  /proc/self/task/536870912/ns/cgroup
+ */
+#define LTTNG_PROC_NS_PATH_MAX 40
+
 struct lttng_session;
 struct lttng_channel;
 struct lttng_event;
@@ -44,6 +52,10 @@ void ust_unlock(void);
 void lttng_fixup_event_tls(void);
 void lttng_fixup_vtid_tls(void);
 void lttng_fixup_procname_tls(void);
+void lttng_fixup_cgroup_ns_tls(void);
+void lttng_fixup_ipc_ns_tls(void);
+void lttng_fixup_net_ns_tls(void);
+void lttng_fixup_uts_ns_tls(void);
 
 const char *lttng_ust_obj_get_name(int id);
 
index b067b3da1bbc9b71084b121c46a7a530976db041..5a2aacdf32d6513348465bdedf0cbfc398b372be 100644 (file)
@@ -425,6 +425,10 @@ void lttng_ust_fixup_tls(void)
        lttng_fixup_ust_mutex_nest_tls();
        lttng_ust_fixup_perf_counter_tls();
        lttng_ust_fixup_fd_tracker_tls();
+       lttng_fixup_cgroup_ns_tls();
+       lttng_fixup_ipc_ns_tls();
+       lttng_fixup_net_ns_tls();
+       lttng_fixup_uts_ns_tls();
 }
 
 int lttng_get_notify_socket(void *owner)
@@ -2034,6 +2038,18 @@ void __attribute__((destructor)) lttng_ust_exit(void)
        lttng_ust_cleanup(1);
 }
 
+static
+void ust_context_ns_reset(void)
+{
+       lttng_context_pid_ns_reset();
+       lttng_context_cgroup_ns_reset();
+       lttng_context_ipc_ns_reset();
+       lttng_context_mnt_ns_reset();
+       lttng_context_net_ns_reset();
+       lttng_context_user_ns_reset();
+       lttng_context_uts_ns_reset();
+}
+
 /*
  * We exclude the worker threads across fork and clone (except
  * CLONE_VM), because these system calls only keep the forking thread
@@ -2116,6 +2132,7 @@ void ust_after_fork_child(sigset_t *restore_sigset)
        lttng_context_vpid_reset();
        lttng_context_vtid_reset();
        lttng_context_procname_reset();
+       ust_context_ns_reset();
        DBG("process %d", getpid());
        /* Release urcu mutexes */
        urcu_bp_after_fork_child();
@@ -2125,6 +2142,16 @@ void ust_after_fork_child(sigset_t *restore_sigset)
        lttng_ust_init();
 }
 
+void ust_after_setns(void)
+{
+       ust_context_ns_reset();
+}
+
+void ust_after_unshare(void)
+{
+       ust_context_ns_reset();
+}
+
 void lttng_ust_sockinfo_session_enabled(void *owner)
 {
        struct sock_info *sock_info = owner;
diff --git a/liblttng-ust/ns.h b/liblttng-ust/ns.h
new file mode 100644 (file)
index 0000000..4793f3e
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _LTTNG_NS_H
+#define _LTTNG_NS_H
+
+/*
+ * Copyright (c) 2019 - Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+/*
+ * The lowest valid inode number that can be allocated in the proc filesystem
+ * is 0xF0000000. Any number below can be used internally as an error code.
+ *
+ * Zero is used in the kernel as an error code, it's the value we will return
+ * when we fail to read the proper inode number.
+ *
+ * One is used internally to identify an uninitialized cache entry, it should
+ * never be returned.
+ */
+
+enum ns_ino_state {
+       NS_INO_UNAVAILABLE      = 0x0,
+       NS_INO_UNINITIALIZED    = 0x1,
+       NS_INO_MIN              = 0xF0000000,
+};
+
+#endif /* _LTTNG_NS_H */
This page took 0.041717 seconds and 4 git commands to generate.