#include <probes/lttng-tracepoint-event.h>
#include <linux/nsproxy.h>
+#include <linux/cgroup.h>
+#include <linux/ipc_namespace.h>
+#include <net/net_namespace.h>
#include <linux/pid_namespace.h>
+#include <linux/user_namespace.h>
+#include <linux/utsname.h>
#include <linux/types.h>
#include <linux/version.h>
+#include <wrapper/namespace.h>
+#include <wrapper/user_namespace.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0))
-#define lttng_proc_inum ns.inum
-#else
-#define lttng_proc_inum proc_inum
+#ifndef LTTNG_MNT_NS_MISSING_HEADER
+# ifndef ONCE_LTTNG_FS_MOUNT_H
+# define ONCE_LTTNG_FS_MOUNT_H
+# include <../fs/mount.h>
+# endif
#endif
LTTNG_TRACEPOINT_EVENT(lttng_statedump_start,
)
)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0))
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_cgroup_ns,
+ TP_PROTO(struct lttng_session *session,
+ struct task_struct *p,
+ struct cgroup_namespace *cgroup_ns),
+ TP_ARGS(session, p, cgroup_ns),
+ TP_FIELDS(
+ ctf_integer(pid_t, tid, p->pid)
+ ctf_integer(unsigned int, ns_inum, cgroup_ns ? cgroup_ns->lttng_ns_inum : 0)
+ )
+)
+#endif
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_ipc_ns,
+ TP_PROTO(struct lttng_session *session,
+ struct task_struct *p,
+ struct ipc_namespace *ipc_ns),
+ TP_ARGS(session, p, ipc_ns),
+ TP_FIELDS(
+ ctf_integer(pid_t, tid, p->pid)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+ ctf_integer(unsigned int, ns_inum, ipc_ns ? ipc_ns->lttng_ns_inum : 0)
+#endif
+ )
+)
+
+#if !defined(LTTNG_MNT_NS_MISSING_HEADER)
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_mnt_ns,
+ TP_PROTO(struct lttng_session *session,
+ struct task_struct *p,
+ struct mnt_namespace *mnt_ns),
+ TP_ARGS(session, p, mnt_ns),
+ TP_FIELDS(
+ ctf_integer(pid_t, tid, p->pid)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+ ctf_integer(unsigned int, ns_inum, mnt_ns ? mnt_ns->lttng_ns_inum : 0)
+#endif
+ )
+)
+#endif
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_net_ns,
+ TP_PROTO(struct lttng_session *session,
+ struct task_struct *p,
+ struct net *net_ns),
+ TP_ARGS(session, p, net_ns),
+ TP_FIELDS(
+ ctf_integer(pid_t, tid, p->pid)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+ ctf_integer(unsigned int, ns_inum, net_ns ? net_ns->lttng_ns_inum : 0)
+#endif
+ )
+)
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_pid_ns,
+ TP_PROTO(struct lttng_session *session,
+ struct task_struct *p,
+ struct pid_namespace *pid_ns),
+ TP_ARGS(session, p, pid_ns),
+ TP_FIELDS(
+ ctf_integer(pid_t, tid, p->pid)
+ ctf_integer(pid_t, vtid, pid_ns ? task_pid_nr_ns(p, pid_ns) : 0)
+ ctf_integer(pid_t, vpid, pid_ns ? task_tgid_nr_ns(p, pid_ns) : 0)
+ ctf_integer(pid_t, vppid,
+ ({
+ struct task_struct *parent;
+ pid_t ret = 0;
+
+ if (pid_ns) {
+ rcu_read_lock();
+ parent = rcu_dereference(p->real_parent);
+ ret = task_tgid_nr_ns(parent, pid_ns);
+ rcu_read_unlock();
+ }
+ ret;
+ }))
+ ctf_integer(int, ns_level, pid_ns ? pid_ns->level : 0)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+ ctf_integer(unsigned int, ns_inum, pid_ns ? pid_ns->lttng_ns_inum : 0)
+#endif
+ )
+)
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_user_ns,
+ TP_PROTO(struct lttng_session *session,
+ struct task_struct *p,
+ struct user_namespace *user_ns),
+ TP_ARGS(session, p, user_ns),
+ TP_FIELDS(
+ ctf_integer(pid_t, tid, p->pid)
+ ctf_integer(uid_t, vuid, user_ns ? lttng_task_vuid(p, user_ns) : 0)
+ ctf_integer(gid_t, vgid, user_ns ? lttng_task_vgid(p, user_ns) : 0)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0))
+ ctf_integer(int, ns_level, user_ns ? user_ns->level : 0)
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+ ctf_integer(unsigned int, ns_inum, user_ns ? user_ns->lttng_ns_inum : 0)
+#endif
+ )
+)
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_uts_ns,
+ TP_PROTO(struct lttng_session *session,
+ struct task_struct *p,
+ struct uts_namespace *uts_ns),
+ TP_ARGS(session, p, uts_ns),
+ TP_FIELDS(
+ ctf_integer(pid_t, tid, p->pid)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+ ctf_integer(unsigned int, ns_inum, uts_ns ? uts_ns->lttng_ns_inum : 0)
+#endif
+ )
+)
+
LTTNG_TRACEPOINT_EVENT(lttng_statedump_file_descriptor,
TP_PROTO(struct lttng_session *session,
struct task_struct *p, int fd, const char *filename,
#include <lttng-tracer.h>
#include <wrapper/irqdesc.h>
#include <wrapper/fdtable.h>
+#include <wrapper/namespace.h>
#include <wrapper/irq.h>
#include <wrapper/tracepoint.h>
#include <wrapper/genhd.h>
DEFINE_TRACE(lttng_statedump_file_descriptor);
DEFINE_TRACE(lttng_statedump_start);
DEFINE_TRACE(lttng_statedump_process_state);
+DEFINE_TRACE(lttng_statedump_process_pid_ns);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0))
+DEFINE_TRACE(lttng_statedump_process_cgroup_ns);
+#endif
+DEFINE_TRACE(lttng_statedump_process_ipc_ns);
+#ifndef LTTNG_MNT_NS_MISSING_HEADER
+DEFINE_TRACE(lttng_statedump_process_mnt_ns);
+#endif
+DEFINE_TRACE(lttng_statedump_process_net_ns);
+DEFINE_TRACE(lttng_statedump_process_user_ns);
+DEFINE_TRACE(lttng_statedump_process_uts_ns);
DEFINE_TRACE(lttng_statedump_network_interface);
#ifdef LTTNG_HAVE_STATEDUMP_CPU_TOPOLOGY
DEFINE_TRACE(lttng_statedump_cpu_topology);
#endif
/*
+ * Statedump the task's namespaces using the proc filesystem inode number as
+ * the unique identifier. The user and pid ns are nested and will be dumped
+ * recursively.
+ *
* Called with task lock held.
*/
static
enum lttng_execution_submode submode,
enum lttng_process_status status)
{
+ struct nsproxy *proxy;
struct pid_namespace *pid_ns;
+ struct user_namespace *user_ns;
+ /*
+ * The pid and user namespaces are special, they are nested and
+ * accessed with specific functions instead of the nsproxy struct
+ * like the other namespaces.
+ */
pid_ns = task_active_pid_ns(p);
do {
trace_lttng_statedump_process_state(session,
p, type, mode, submode, status, pid_ns);
+ trace_lttng_statedump_process_pid_ns(session, p, pid_ns);
pid_ns = pid_ns->parent;
} while (pid_ns);
+
+
+ user_ns = task_cred_xxx(p, user_ns);
+ do {
+ trace_lttng_statedump_process_user_ns(session, p, user_ns);
+ user_ns = user_ns->lttng_user_ns_parent;
+ } while (user_ns);
+
+ /*
+ * Back and forth on locking strategy within Linux upstream for nsproxy.
+ * See Linux upstream commit 728dba3a39c66b3d8ac889ddbe38b5b1c264aec3
+ * "namespaces: Use task_lock and not rcu to protect nsproxy"
+ * for details.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || \
+ LTTNG_UBUNTU_KERNEL_RANGE(3,13,11,36, 3,14,0,0) || \
+ LTTNG_UBUNTU_KERNEL_RANGE(3,16,1,11, 3,17,0,0) || \
+ LTTNG_RHEL_KERNEL_RANGE(3,10,0,229,13,0, 3,11,0,0,0,0))
+ proxy = p->nsproxy;
+#else
+ rcu_read_lock();
+ proxy = task_nsproxy(p);
+#endif
+ if (proxy) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0))
+ trace_lttng_statedump_process_cgroup_ns(session, p, proxy->cgroup_ns);
+#endif
+ trace_lttng_statedump_process_ipc_ns(session, p, proxy->ipc_ns);
+#ifndef LTTNG_MNT_NS_MISSING_HEADER
+ trace_lttng_statedump_process_mnt_ns(session, p, proxy->mnt_ns);
+#endif
+ trace_lttng_statedump_process_net_ns(session, p, proxy->net_ns);
+ trace_lttng_statedump_process_uts_ns(session, p, proxy->uts_ns);
+ }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || \
+ LTTNG_UBUNTU_KERNEL_RANGE(3,13,11,36, 3,14,0,0) || \
+ LTTNG_UBUNTU_KERNEL_RANGE(3,16,1,11, 3,17,0,0) || \
+ LTTNG_RHEL_KERNEL_RANGE(3,10,0,229,13,0, 3,11,0,0,0,0))
+ /* (nothing) */
+#else
+ rcu_read_unlock();
+#endif
}
static
#define lttng_current_vxxgid(xxx) \
(from_kgid_munged(current_user_ns(), current_##xxx()))
+static inline
+uid_t lttng_task_vuid(struct task_struct *p, struct user_namespace *ns)
+{
+ uid_t uid;
+ kuid_t kuid;
+
+ kuid = task_cred_xxx(p, uid);
+ uid = from_kuid_munged(ns, kuid);
+
+ return uid;
+}
+
+static inline
+gid_t lttng_task_vgid(struct task_struct *p, struct user_namespace *ns)
+{
+ gid_t gid;
+ kgid_t kgid;
+
+ kgid = task_cred_xxx(p, gid);
+ gid = from_kgid_munged(ns, kgid);
+
+ return gid;
+}
+
#else
#define lttng_current_xxuid(xxx) (current_##xxx())
#define lttng_current_vxxgid(xxx) \
(user_ns_map_gid(current_user_ns(), current_cred(), current_##xxx()))
+
+static inline
+uid_t lttng_task_vuid(struct task_struct *p, struct user_namespace *ns)
+{
+ uid_t uid;
+
+ /*
+ * __task_cred requires the RCU readlock be held
+ */
+ rcu_read_lock();
+ uid = user_ns_map_uid(ns, __task_cred(p), __task_cred(p)->uid);
+ rcu_read_unlock();
+
+ return uid;
+}
+
+static inline
+gid_t lttng_task_vgid(struct task_struct *p, struct user_namespace *ns)
+{
+ gid_t gid;
+
+ /*
+ * __task_cred requires the RCU readlock be held
+ */
+ rcu_read_lock();
+ gid = user_ns_map_gid(ns, __task_cred(p), __task_cred(p)->gid);
+ rcu_read_unlock();
+
+ return gid;
+}
+
#endif
#define lttng_current_uid() (lttng_current_xxuid(uid))