From a6cf40a4491954d6f81052f8bbce757f73727f16 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 12 Feb 2019 09:43:24 -0500 Subject: [PATCH] Add namespace contexts 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 instroduced in v3.8.0 in this commit : commit 98f842e675f96ffac96e6c50315790912b2812be Author: Eric W. Biederman Date: Wed Jun 15 10:21:48 2011 -0700 proc: Usable inode numbers for the namespace file descriptors. Assign a unique proc inode to each namespace, and use that inode number to ensure we only allocate at most one proc inode for every namespace in proc. A single proc inode per namespace allows userspace to test to see if two processes are in the same namespace. ... Prior to this there is no unique identifier for a namespace that is available to both the kernel and userspace. Enabling any of these contexts on a kernel that is too old or doesn't have the proper features enabled will fail and return -ENOSYS. Per namespace particularities : - Cgroup - Introduced in 4.6.0 - CONFIG_CGROUPS - IPC - Introduced in 2.6.25 - CONFIG_IPC_NS - MNT - Introduced in 2.6.20 - The mnt_namespace struct is defined in a private header - NET - Introduced in 2.6.24 - CONFIG_NET_NS - PID - Introduced in 2.6.20 - CONFIG_PID_NS - User - Introduced in 2.6.23 - CONFIG_USER_NS - UTS - Introduced in 2.6.19 - CONFIG_UTS_NS Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- Kbuild.common | 5 + Makefile | 26 +++++ instrumentation/events/lttng-module/sched.h | 11 +- lttng-abi.c | 14 +++ lttng-abi.h | 7 ++ lttng-context-cgroup-ns.c | 105 +++++++++++++++++++ lttng-context-ipc-ns.c | 104 +++++++++++++++++++ lttng-context-mnt-ns.c | 105 +++++++++++++++++++ lttng-context-net-ns.c | 104 +++++++++++++++++++ lttng-context-pid-ns.c | 106 ++++++++++++++++++++ lttng-context-user-ns.c | 90 +++++++++++++++++ lttng-context-uts-ns.c | 104 +++++++++++++++++++ lttng-context.c | 28 ++++++ lttng-events.h | 78 ++++++++++++++ wrapper/namespace.h | 21 ++++ 15 files changed, 900 insertions(+), 8 deletions(-) create mode 100644 lttng-context-cgroup-ns.c create mode 100644 lttng-context-ipc-ns.c create mode 100644 lttng-context-mnt-ns.c create mode 100644 lttng-context-net-ns.c create mode 100644 lttng-context-pid-ns.c create mode 100644 lttng-context-user-ns.c create mode 100644 lttng-context-uts-ns.c create mode 100644 wrapper/namespace.h diff --git a/Kbuild.common b/Kbuild.common index c7cbd0b2..e2934e20 100644 --- a/Kbuild.common +++ b/Kbuild.common @@ -71,4 +71,9 @@ ifneq ($(CONFIG_DYNAMIC_FTRACE),) endif endif +mnt_ns_dep = $(srctree)/fs/mount.h +ifeq ($(wildcard $(mnt_ns_dep)),) + ccflags-y += -DLTTNG_MNT_NS_MISSING_HEADER +endif + # vim:syntax=make diff --git a/Makefile b/Makefile index c7b8a417..9b3e6c22 100644 --- a/Makefile +++ b/Makefile @@ -83,6 +83,32 @@ ifneq ($(KERNELRELEASE),) -o \( $(VERSION) -eq 3 -a $(PATCHLEVEL) -ge 15 \) ] ; then \ echo "lttng-tracepoint.o" ; fi;) + lttng-tracer-objs += lttng-context-cgroup-ns.o + + ifneq ($(CONFIG_IPC_NS),) + lttng-tracer-objs += lttng-context-ipc-ns.o + endif + + ifneq ($(wildcard $(mnt_ns_dep)),) + lttng-tracer-objs += lttng-context-mnt-ns.o + endif + + ifneq ($(CONFIG_NET_NS),) + lttng-tracer-objs += lttng-context-net-ns.o + endif + + ifneq ($(CONFIG_PID_NS),) + lttng-tracer-objs += lttng-context-pid-ns.o + endif + + ifneq ($(CONFIG_USER_NS),) + lttng-tracer-objs += lttng-context-user-ns.o + endif + + ifneq ($(CONFIG_UTS_NS),) + lttng-tracer-objs += lttng-context-uts-ns.o + endif + obj-$(CONFIG_LTTNG) += lttng-statedump.o lttng-statedump-objs := lttng-statedump-impl.o wrapper/irqdesc.o \ wrapper/fdtable.o diff --git a/instrumentation/events/lttng-module/sched.h b/instrumentation/events/lttng-module/sched.h index 5b4313a9..0f34ff15 100644 --- a/instrumentation/events/lttng-module/sched.h +++ b/instrumentation/events/lttng-module/sched.h @@ -13,12 +13,7 @@ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) #include #endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)) -#define lttng_proc_inum ns.inum -#else -#define lttng_proc_inum proc_inum -#endif +#include #define LTTNG_MAX_PID_NS_LEVEL 32 @@ -437,7 +432,7 @@ LTTNG_TRACEPOINT_EVENT_CODE(sched_process_fork, pid_ns = task_active_pid_ns(parent); if (pid_ns) parent_ns_inum = - pid_ns->lttng_proc_inum; + pid_ns->lttng_ns_inum; } parent_ns_inum; })) @@ -457,7 +452,7 @@ LTTNG_TRACEPOINT_EVENT_CODE(sched_process_fork, pid_ns = task_active_pid_ns(child); if (pid_ns) child_ns_inum = - pid_ns->lttng_proc_inum; + pid_ns->lttng_ns_inum; } child_ns_inum; })) diff --git a/lttng-abi.c b/lttng-abi.c index 5624b6c4..34dd8f80 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -236,6 +236,20 @@ long lttng_abi_add_context(struct file *file, case LTTNG_KERNEL_CONTEXT_CALLSTACK_KERNEL: case LTTNG_KERNEL_CONTEXT_CALLSTACK_USER: return lttng_add_callstack_to_ctx(ctx, context_param->ctx); + case LTTNG_KERNEL_CONTEXT_CGROUP_NS: + return lttng_add_cgroup_ns_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_IPC_NS: + return lttng_add_ipc_ns_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_MNT_NS: + return lttng_add_mnt_ns_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_NET_NS: + return lttng_add_net_ns_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_PID_NS: + return lttng_add_pid_ns_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_USER_NS: + return lttng_add_user_ns_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_UTS_NS: + return lttng_add_uts_ns_to_ctx(ctx); default: return -EINVAL; } diff --git a/lttng-abi.h b/lttng-abi.h index c292de01..91fe67f7 100644 --- a/lttng-abi.h +++ b/lttng-abi.h @@ -161,6 +161,13 @@ enum lttng_kernel_context_type { LTTNG_KERNEL_CONTEXT_MIGRATABLE = 15, LTTNG_KERNEL_CONTEXT_CALLSTACK_KERNEL = 16, LTTNG_KERNEL_CONTEXT_CALLSTACK_USER = 17, + LTTNG_KERNEL_CONTEXT_CGROUP_NS = 18, + LTTNG_KERNEL_CONTEXT_IPC_NS = 19, + LTTNG_KERNEL_CONTEXT_MNT_NS = 20, + LTTNG_KERNEL_CONTEXT_NET_NS = 21, + LTTNG_KERNEL_CONTEXT_PID_NS = 22, + LTTNG_KERNEL_CONTEXT_USER_NS = 23, + LTTNG_KERNEL_CONTEXT_UTS_NS = 24, }; struct lttng_kernel_perf_counter_ctx { diff --git a/lttng-context-cgroup-ns.c b/lttng-context-cgroup-ns.c new file mode 100644 index 00000000..81486e51 --- /dev/null +++ b/lttng-context-cgroup-ns.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-context-cgroup-ns.c + * + * LTTng cgroup namespace context. + * + * Copyright (C) 2009-2012 Mathieu Desnoyers + * 2019 Michael Jeanson + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CGROUPS) && \ + ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)) || \ + LTTNG_UBUNTU_KERNEL_RANGE(4,4,0,0, 4,5,0,0)) + +static +size_t cgroup_ns_get_size(size_t offset) +{ + size_t size = 0; + + size += lib_ring_buffer_align(offset, lttng_alignof(unsigned int)); + size += sizeof(unsigned int); + return size; +} + +static +void cgroup_ns_record(struct lttng_ctx_field *field, + struct lib_ring_buffer_ctx *ctx, + struct lttng_channel *chan) +{ + unsigned int cgroup_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + cgroup_ns_inum = current->nsproxy->cgroup_ns->lttng_ns_inum; + + lib_ring_buffer_align_ctx(ctx, lttng_alignof(cgroup_ns_inum)); + chan->ops->event_write(ctx, &cgroup_ns_inum, sizeof(cgroup_ns_inum)); +} + +static +void cgroup_ns_get_value(struct lttng_ctx_field *field, + struct lttng_probe_ctx *lttng_probe_ctx, + union lttng_ctx_value *value) +{ + unsigned int cgroup_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + cgroup_ns_inum = current->nsproxy->cgroup_ns->lttng_ns_inum; + + value->s64 = cgroup_ns_inum; +} + +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(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned int); + 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); + wrapper_vmalloc_sync_all(); + return 0; +} +EXPORT_SYMBOL_GPL(lttng_add_cgroup_ns_to_ctx); + +#endif diff --git a/lttng-context-ipc-ns.c b/lttng-context-ipc-ns.c new file mode 100644 index 00000000..78d59660 --- /dev/null +++ b/lttng-context-ipc-ns.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-context-ipc-ns.c + * + * LTTng ipc namespace context. + * + * Copyright (C) 2009-2012 Mathieu Desnoyers + * 2019 Michael Jeanson + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_IPC_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + +static +size_t ipc_ns_get_size(size_t offset) +{ + size_t size = 0; + + size += lib_ring_buffer_align(offset, lttng_alignof(unsigned int)); + size += sizeof(unsigned int); + return size; +} + +static +void ipc_ns_record(struct lttng_ctx_field *field, + struct lib_ring_buffer_ctx *ctx, + struct lttng_channel *chan) +{ + unsigned int ipc_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + ipc_ns_inum = current->nsproxy->ipc_ns->lttng_ns_inum; + + lib_ring_buffer_align_ctx(ctx, lttng_alignof(ipc_ns_inum)); + chan->ops->event_write(ctx, &ipc_ns_inum, sizeof(ipc_ns_inum)); +} + +static +void ipc_ns_get_value(struct lttng_ctx_field *field, + struct lttng_probe_ctx *lttng_probe_ctx, + union lttng_ctx_value *value) +{ + unsigned int ipc_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + ipc_ns_inum = current->nsproxy->ipc_ns->lttng_ns_inum; + + value->s64 = ipc_ns_inum; +} + +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(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned int); + 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); + wrapper_vmalloc_sync_all(); + return 0; +} +EXPORT_SYMBOL_GPL(lttng_add_ipc_ns_to_ctx); + +#endif diff --git a/lttng-context-mnt-ns.c b/lttng-context-mnt-ns.c new file mode 100644 index 00000000..98d5b8e6 --- /dev/null +++ b/lttng-context-mnt-ns.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-context-mnt-ns.c + * + * LTTng mount namespace context. + * + * Copyright (C) 2009-2012 Mathieu Desnoyers + * 2019 Michael Jeanson + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(LTTNG_MNT_NS_MISSING_HEADER) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + +#include <../fs/mount.h> + +static +size_t mnt_ns_get_size(size_t offset) +{ + size_t size = 0; + + size += lib_ring_buffer_align(offset, lttng_alignof(unsigned int)); + size += sizeof(unsigned int); + return size; +} + +static +void mnt_ns_record(struct lttng_ctx_field *field, + struct lib_ring_buffer_ctx *ctx, + struct lttng_channel *chan) +{ + unsigned int mnt_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + mnt_ns_inum = current->nsproxy->mnt_ns->lttng_ns_inum; + + lib_ring_buffer_align_ctx(ctx, lttng_alignof(mnt_ns_inum)); + chan->ops->event_write(ctx, &mnt_ns_inum, sizeof(mnt_ns_inum)); +} + +static +void mnt_ns_get_value(struct lttng_ctx_field *field, + struct lttng_probe_ctx *lttng_probe_ctx, + union lttng_ctx_value *value) +{ + unsigned int mnt_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + mnt_ns_inum = current->nsproxy->mnt_ns->lttng_ns_inum; + + value->s64 = mnt_ns_inum; +} + +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(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned int); + 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); + wrapper_vmalloc_sync_all(); + return 0; +} +EXPORT_SYMBOL_GPL(lttng_add_mnt_ns_to_ctx); + +#endif diff --git a/lttng-context-net-ns.c b/lttng-context-net-ns.c new file mode 100644 index 00000000..24d7ae35 --- /dev/null +++ b/lttng-context-net-ns.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-context-net-ns.c + * + * LTTng net namespace context. + * + * Copyright (C) 2009-2012 Mathieu Desnoyers + * 2019 Michael Jeanson + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_NET_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + +static +size_t net_ns_get_size(size_t offset) +{ + size_t size = 0; + + size += lib_ring_buffer_align(offset, lttng_alignof(unsigned int)); + size += sizeof(unsigned int); + return size; +} + +static +void net_ns_record(struct lttng_ctx_field *field, + struct lib_ring_buffer_ctx *ctx, + struct lttng_channel *chan) +{ + unsigned int net_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + net_ns_inum = current->nsproxy->net_ns->lttng_ns_inum; + + lib_ring_buffer_align_ctx(ctx, lttng_alignof(net_ns_inum)); + chan->ops->event_write(ctx, &net_ns_inum, sizeof(net_ns_inum)); +} + +static +void net_ns_get_value(struct lttng_ctx_field *field, + struct lttng_probe_ctx *lttng_probe_ctx, + union lttng_ctx_value *value) +{ + unsigned int net_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + net_ns_inum = current->nsproxy->net_ns->lttng_ns_inum; + + value->s64 = net_ns_inum; +} + +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(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned int); + 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); + wrapper_vmalloc_sync_all(); + return 0; +} +EXPORT_SYMBOL_GPL(lttng_add_net_ns_to_ctx); + +#endif diff --git a/lttng-context-pid-ns.c b/lttng-context-pid-ns.c new file mode 100644 index 00000000..f039f260 --- /dev/null +++ b/lttng-context-pid-ns.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-context-pid-ns.c + * + * LTTng pid namespace context. + * + * Copyright (C) 2009-2012 Mathieu Desnoyers + * 2019 Michael Jeanson + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_PID_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + +static +size_t pid_ns_get_size(size_t offset) +{ + size_t size = 0; + + size += lib_ring_buffer_align(offset, lttng_alignof(unsigned int)); + size += sizeof(unsigned int); + return size; +} + +static +void pid_ns_record(struct lttng_ctx_field *field, + struct lib_ring_buffer_ctx *ctx, + struct lttng_channel *chan) +{ + struct pid_namespace *ns; + unsigned int pid_ns_inum = 0; + + /* + * The pid namespace is an exception -- it's accessed using + * task_active_pid_ns. The pid namespace in nsproxy is the + * namespace that children will use. + */ + ns = task_active_pid_ns(current); + + if (ns) + pid_ns_inum = ns->lttng_ns_inum; + + lib_ring_buffer_align_ctx(ctx, lttng_alignof(pid_ns_inum)); + chan->ops->event_write(ctx, &pid_ns_inum, sizeof(pid_ns_inum)); +} + +static +void pid_ns_get_value(struct lttng_ctx_field *field, + struct lttng_probe_ctx *lttng_probe_ctx, + union lttng_ctx_value *value) +{ + struct pid_namespace *ns; + unsigned int pid_ns_inum = 0; + + /* + * The pid namespace is an exception -- it's accessed using + * task_active_pid_ns. The pid namespace in nsproxy is the + * namespace that children will use. + */ + ns = task_active_pid_ns(current); + + if (ns) + pid_ns_inum = ns->lttng_ns_inum; + + value->s64 = pid_ns_inum; +} + +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(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned int); + 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); + wrapper_vmalloc_sync_all(); + return 0; +} +EXPORT_SYMBOL_GPL(lttng_add_pid_ns_to_ctx); + +#endif diff --git a/lttng-context-user-ns.c b/lttng-context-user-ns.c new file mode 100644 index 00000000..746e4d9d --- /dev/null +++ b/lttng-context-user-ns.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-context-user-ns.c + * + * LTTng user namespace context. + * + * Copyright (C) 2009-2012 Mathieu Desnoyers + * 2019 Michael Jeanson + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_USER_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + +static +size_t user_ns_get_size(size_t offset) +{ + size_t size = 0; + + size += lib_ring_buffer_align(offset, lttng_alignof(unsigned int)); + size += sizeof(unsigned int); + return size; +} + +static +void user_ns_record(struct lttng_ctx_field *field, + struct lib_ring_buffer_ctx *ctx, + struct lttng_channel *chan) +{ + unsigned int user_ns_inum = 0; + + if (current_user_ns()) + user_ns_inum = current_user_ns()->lttng_ns_inum; + + lib_ring_buffer_align_ctx(ctx, lttng_alignof(user_ns_inum)); + chan->ops->event_write(ctx, &user_ns_inum, sizeof(user_ns_inum)); +} + +static +void user_ns_get_value(struct lttng_ctx_field *field, + struct lttng_probe_ctx *lttng_probe_ctx, + union lttng_ctx_value *value) +{ + unsigned int user_ns_inum = 0; + + if (current_user_ns()) + user_ns_inum = current_user_ns()->lttng_ns_inum; + + value->s64 = user_ns_inum; +} + +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(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned int); + 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); + wrapper_vmalloc_sync_all(); + return 0; +} +EXPORT_SYMBOL_GPL(lttng_add_user_ns_to_ctx); + +#endif diff --git a/lttng-context-uts-ns.c b/lttng-context-uts-ns.c new file mode 100644 index 00000000..7352a3df --- /dev/null +++ b/lttng-context-uts-ns.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-context-uts-ns.c + * + * LTTng uts namespace context. + * + * Copyright (C) 2009-2012 Mathieu Desnoyers + * 2019 Michael Jeanson + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_UTS_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + +static +size_t uts_ns_get_size(size_t offset) +{ + size_t size = 0; + + size += lib_ring_buffer_align(offset, lttng_alignof(unsigned int)); + size += sizeof(unsigned int); + return size; +} + +static +void uts_ns_record(struct lttng_ctx_field *field, + struct lib_ring_buffer_ctx *ctx, + struct lttng_channel *chan) +{ + unsigned int uts_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + uts_ns_inum = current->nsproxy->uts_ns->lttng_ns_inum; + + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uts_ns_inum)); + chan->ops->event_write(ctx, &uts_ns_inum, sizeof(uts_ns_inum)); +} + +static +void uts_ns_get_value(struct lttng_ctx_field *field, + struct lttng_probe_ctx *lttng_probe_ctx, + union lttng_ctx_value *value) +{ + unsigned int uts_ns_inum = 0; + + /* + * nsproxy can be NULL when scheduled out of exit. + * + * As documented in 'linux/nsproxy.h' namespaces access rules, no + * precautions should be taken when accessing the current task's + * namespaces, just dereference the pointers. + */ + if (current->nsproxy) + uts_ns_inum = current->nsproxy->uts_ns->lttng_ns_inum; + + value->s64 = uts_ns_inum; +} + +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(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned int) * CHAR_BIT; + field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned int); + 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); + wrapper_vmalloc_sync_all(); + return 0; +} +EXPORT_SYMBOL_GPL(lttng_add_uts_ns_to_ctx); + +#endif diff --git a/lttng-context.c b/lttng-context.c index 869496d8..eb4534cb 100644 --- a/lttng-context.c +++ b/lttng-context.c @@ -303,6 +303,34 @@ int lttng_context_init(void) if (ret && ret != -ENOSYS) { printk(KERN_WARNING "Cannot add context lttng_add_migratable_to_ctx"); } + ret = lttng_add_cgroup_ns_to_ctx(<tng_static_ctx); + if (ret && ret != -ENOSYS) { + printk(KERN_WARNING "Cannot add context lttng_add_cgroup_ns_to_ctx"); + } + ret = lttng_add_ipc_ns_to_ctx(<tng_static_ctx); + if (ret && ret != -ENOSYS) { + printk(KERN_WARNING "Cannot add context lttng_add_ipc_ns_to_ctx"); + } + ret = lttng_add_mnt_ns_to_ctx(<tng_static_ctx); + if (ret && ret != -ENOSYS) { + printk(KERN_WARNING "Cannot add context lttng_add_mnt_ns_to_ctx"); + } + ret = lttng_add_net_ns_to_ctx(<tng_static_ctx); + if (ret && ret != -ENOSYS) { + printk(KERN_WARNING "Cannot add context lttng_add_net_ns_to_ctx"); + } + ret = lttng_add_pid_ns_to_ctx(<tng_static_ctx); + if (ret && ret != -ENOSYS) { + printk(KERN_WARNING "Cannot add context lttng_add_pid_ns_to_ctx"); + } + ret = lttng_add_user_ns_to_ctx(<tng_static_ctx); + if (ret && ret != -ENOSYS) { + printk(KERN_WARNING "Cannot add context lttng_add_user_ns_to_ctx"); + } + ret = lttng_add_uts_ns_to_ctx(<tng_static_ctx); + if (ret && ret != -ENOSYS) { + printk(KERN_WARNING "Cannot add context lttng_add_uts_ns_to_ctx"); + } /* TODO: perf counters for filtering */ return 0; } diff --git a/lttng-events.h b/lttng-events.h index 8fe36a73..fe6e2849 100644 --- a/lttng-events.h +++ b/lttng-events.h @@ -718,6 +718,84 @@ int lttng_add_migratable_to_ctx(struct lttng_ctx **ctx) int lttng_add_callstack_to_ctx(struct lttng_ctx **ctx, int type); +#if defined(CONFIG_CGROUPS) && \ + ((LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)) || \ + LTTNG_UBUNTU_KERNEL_RANGE(4,4,0,0, 4,5,0,0)) +int lttng_add_cgroup_ns_to_ctx(struct lttng_ctx **ctx); +#else +static inline +int lttng_add_cgroup_ns_to_ctx(struct lttng_ctx **ctx) +{ + return -ENOSYS; +} +#endif + +#if defined(CONFIG_IPC_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) +int lttng_add_ipc_ns_to_ctx(struct lttng_ctx **ctx); +#else +static inline +int lttng_add_ipc_ns_to_ctx(struct lttng_ctx **ctx) +{ + return -ENOSYS; +} +#endif + +#if !defined(LTTNG_MNT_NS_MISSING_HEADER) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) +int lttng_add_mnt_ns_to_ctx(struct lttng_ctx **ctx); +#else +static inline +int lttng_add_mnt_ns_to_ctx(struct lttng_ctx **ctx) +{ + return -ENOSYS; +} +#endif + +#if defined(CONFIG_NET_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) +int lttng_add_net_ns_to_ctx(struct lttng_ctx **ctx); +#else +static inline +int lttng_add_net_ns_to_ctx(struct lttng_ctx **ctx) +{ + return -ENOSYS; +} +#endif + +#if defined(CONFIG_PID_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) +int lttng_add_pid_ns_to_ctx(struct lttng_ctx **ctx); +#else +static inline +int lttng_add_pid_ns_to_ctx(struct lttng_ctx **ctx) +{ + return -ENOSYS; +} +#endif + +#if defined(CONFIG_USER_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) +int lttng_add_user_ns_to_ctx(struct lttng_ctx **ctx); +#else +static inline +int lttng_add_user_ns_to_ctx(struct lttng_ctx **ctx) +{ + return -ENOSYS; +} +#endif + +#if defined(CONFIG_UTS_NS) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) +int lttng_add_uts_ns_to_ctx(struct lttng_ctx **ctx); +#else +static inline +int lttng_add_uts_ns_to_ctx(struct lttng_ctx **ctx) +{ + return -ENOSYS; +} +#endif + #if defined(CONFIG_PERF_EVENTS) int lttng_add_perf_counter_to_ctx(uint32_t type, uint64_t config, diff --git a/wrapper/namespace.h b/wrapper/namespace.h new file mode 100644 index 00000000..36dbf4c0 --- /dev/null +++ b/wrapper/namespace.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * wrapper/namespace.h + * + * Copyright (C) 2011-2012 Mathieu Desnoyers + * 2019 Michael Jeanson + * + */ + +#ifndef _LTTNG_WRAPPER_NAMESPACE_H +#define _LTTNG_WRAPPER_NAMESPACE_H + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)) +#define lttng_ns_inum ns.inum +#else +#define lttng_ns_inum proc_inum +#endif + +#endif /* _LTTNG_WRAPPER_NAMESPACE_H */ -- 2.34.1