Skip to contentSkip to conversation

namespaces: log namespaces per task

PATCH Superseded Richard Guy Briggs 4 participants 38 messages Oct 6, 2014 – Oct 14, 2014 1 message not in the archive

Subsystems (12)
Networking Documentation VFS MM core +8 more subsystems

v5 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

v5 cover namespaces: log namespaces per task

The purpose is to track namespace instances in use by logged processes from the perspective of init_*_ns by assigning each a per-kernel, per-boot serial number.

1/13 defines a function to generate them and assigns them.

Use a serial number per namespace (unique across one boot of one kernel) instead of the inode number (which is claimed to have had the right to change reserved and is not necessarily unique if there is more than one proc fs). It could be argued that the inode numbers have now become a defacto interface and can't change now, but I'm proposing this approach to see if this helps address some of the objections to the earlier patchset.

2/13 adds access functions to get to the serial numbers in a similar way to inode access for namespace proc operations.

3/13 exposes proc's ns entries structure which lists a number of useful operations per namespace type for other subsystems to use.

4/13 provides an example of usage for audit_log_task_info() which is used by syscall audits, among others. audit_log_task() and audit_common_recv_message() would be other potential use cases.

Proposed output format:
This differs slightly from Aristeu's patch because of the label conflict with "pid=" due to including it in existing records rather than it being a seperate record. It has now returned to being a seperate record. The serial numbers are printed in hex.

	type=NS_INFO msg=audit(1408577535.306:82):  netns=8 utsns=2 ipcns=1 pidns=4 userns=3 mntns=5

5/13 change audit startup from __initcall to subsys_initcall to get it started earlier to be able to receive initial namespace log messages.

6/13 tracks the creation and deletion of of namespaces, listing the type of namespace instance, related namespace id if there is one and the newly minted serial number.

Proposed output format for initial namespace creation:

	type=AUDIT_NS_INIT_UTS msg=audit(1408577534.868:5): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_utsns=0 utsns=2 res=1
	type=AUDIT_NS_INIT_USER msg=audit(1408577534.868:6): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_userns=0 userns=3 res=1
	type=AUDIT_NS_INIT_PID msg=audit(1408577534.868:7): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_pidns=0 pidns=4 res=1
	type=AUDIT_NS_INIT_MNT msg=audit(1408577534.868:8): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_mntns=0 mntns=5 res=1
	type=AUDIT_NS_INIT_IPC msg=audit(1408577534.868:9): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_ipcns=0 ipcns=1 res=1
	type=AUDIT_NS_INIT_NET msg=audit(1408577533.500:10): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_netns=0 netns=7 res=1

And a CLONE action would result in:

	type=type=AUDIT_NS_INIT_NET msg=audit(1408577535.306:81): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 old_netns=7 netns=8 res=1
	type=type=AUDIT_NS_INIT_MNT msg=audit(1408577535.307:83): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 old_mntns=5 mntns=9 res=1

While deleting a namespace would result in:

	type=type=AUDIT_NS_DEL_MNT msg=audit(1408577552.221:85): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 mntns=9 res=1

7/13 accepts a PID from userspace and requests logging an AUDIT_NS_INFO record type (CAP_AUDIT_CONTROL required).

8/13 is a macro for CLONE_NEW_* flags.

9/13 adds auditing on creation of namespace(s) in fork.

10/13 adds auditing a change of namespace on setns.

11/13 attaches a AUDIT_NS_INFO record to AUDIT_VIRT_CONTROL records (CAP_AUDIT_WRITE required).

12/13 implements, as suggested by Serge Hallyn, making these serial numbers available in /proc/self/ns/{ipc,mnt,net,pid,user,uts}_snum. I chose "snum" instead of "seq" for consistency with inum and there are a number of other uses of "seq" in the namespace code.

13/13 Document proc's ns entries structure in Documentation/filesystems/proc.txt

v4 -> v5:
Clean up prototypes for dependencies on CONFIG_NAMESPACES. Add AUDIT_NS_INFO record type to AUDIT_VIRT_CONTROL record. Log AUDIT_NS_INFO with PID.
Move /proc/<pid>/ns_* patches to end of patchset to deprecate them. Log on changing ns (setns).
Log on creating new namespaces when forking.
Added a macro for CLONE_NEW*.

v3 -> v4:
Seperate out the NS_INFO message from the SYSCALL message. Moved audit_log_namespace_info() out of audit_log_task_info(). Use a seperate message type per namespace type for each of INIT/DEL. Make ns= easier to search across NS_INFO and NS_INIT/DEL_XXX msg types. Add /proc/<pid>/ns/ documentation.
Fix dynamic initial ns logging.

v2 -> v3:
Use atomic64_t in ns_serial to simplify it.
Avoid funciton duplication in proc, keying on dentry. Squash down audit patch to avoid rcu sleep issues. Add tracking for creation and deletion of namespace instances.

v1 -> v2:
Avoid rollover by switching from an int to a long long. Change rollover behaviour from simply avoiding zero to raising a BUG. Expose serial numbers in /proc/<pid>/ns/*_snum.
Expose ns_entries and use it in audit.

Notes:
As for CAP_AUDIT_READ, a patchset has been accepted upstream to check capabilities of userspace processes that try to join netlink broadcast groups.

This set does not try to solve the non-init namespace audit messages and auditd problem yet. That will come later, likely with additional auditd instances running in another namespace with a limited ability to influence the master auditd. I echo Eric B's idea that messages destined for different namespaces would have to be tailored for that namespace with references that make sense (such as the right pid number reported to that pid namespace, and not leaking info about parents or peers).

Questions:
Is there a way to link serial numbers of namespaces involved in migration of a container to another kernel? It sounds like what is needed is a part of a mangement application that is able to pull the audit records from constituent hosts to build an audit trail of a container.

What additional events should list this information?

Does this present any problematic information leaks? Only CAP_AUDIT_CONTROL (and now CAP_AUDIT_READ) in init_user_ns can get to this information in the init namespace at the moment from audit. *However*, the addition of the proc/<pid>/ns/*_snum does make it available to other processes now.

Richard Guy Briggs (13):
namespaces: assign each namespace instance a serial number
namespaces: expose namespace instance serial number in
proc_ns_operations
namespaces: expose ns_entries
audit: log namespace serial numbers
audit: initialize at subsystem time rather than device time
audit: log creation and deletion of namespace instances
audit: dump namespace IDs for pid on receipt of AUDIT_NS_INFO
sched: add a macro to ref all CLONE_NEW* flags
fork: audit on creation of new namespace(s)
audit: log on switching namespace (setns)
audit: emit AUDIT_NS_INFO record with AUDIT_VIRT_CONTROL record
namespaces: expose ns instance serial numbers in proc
Documentation: add a section for /proc/<pid>/ns/

 Documentation/filesystems/proc.txt |   16 ++++
 fs/mount.h                         |    1 +
 fs/namespace.c                     |   20 +++++
 fs/proc/namespaces.c               |   35 +++++++--
 include/linux/audit.h              |   20 +++++
 include/linux/ipc_namespace.h      |    1 +
 include/linux/nsproxy.h            |   10 +++
 include/linux/pid_namespace.h      |    1 +
 include/linux/proc_ns.h            |    2 +
 include/linux/user_namespace.h     |    1 +
 include/linux/utsname.h            |    1 +
 include/net/net_namespace.h        |    1 +
 include/uapi/linux/audit.h         |   21 +++++
 include/uapi/linux/sched.h         |    6 ++
 init/version.c                     |    1 +
 ipc/msgutil.c                      |    1 +
 ipc/namespace.c                    |   20 +++++
 kernel/audit.c                     |  143 +++++++++++++++++++++++++++++++++++-
 kernel/auditsc.c                   |    2 +
 kernel/fork.c                      |    3 +
 kernel/nsproxy.c                   |   22 ++++++
 kernel/pid.c                       |    1 +
 kernel/pid_namespace.c             |   19 +++++
 kernel/user.c                      |    1 +
 kernel/user_namespace.c            |   20 +++++
 kernel/utsname.c                   |   21 +++++
 net/core/net_namespace.c           |   27 +++++++-
 security/integrity/ima/ima_api.c   |    2 +
 28 files changed, 408 insertions(+), 11 deletions(-)
#1 lore raw

PATCH v5 1/13 namespaces: assign each namespace instance a serial number

Generate and assign a serial number per namespace instance since boot.

Use a serial number per namespace (unique across one boot of one kernel) instead of the inode number (which is claimed to have had the right to change reserved and is not necessarily unique if there is more than one proc fs) to uniquely identify it per kernel boot.

---
 fs/mount.h                     |    1 +
 fs/namespace.c                 |    1 +
 include/linux/ipc_namespace.h  |    1 +
 include/linux/nsproxy.h        |   10 ++++++++++
 include/linux/pid_namespace.h  |    1 +
 include/linux/user_namespace.h |    1 +
 include/linux/utsname.h        |    1 +
 include/net/net_namespace.h    |    1 +
 init/version.c                 |    1 +
 ipc/msgutil.c                  |    1 +
 ipc/namespace.c                |    2 ++
 kernel/nsproxy.c               |   18 ++++++++++++++++++
 kernel/pid.c                   |    1 +
 kernel/pid_namespace.c         |    2 ++
 kernel/user.c                  |    1 +
 kernel/user_namespace.c        |    2 ++
 kernel/utsname.c               |    2 ++
 net/core/net_namespace.c       |    8 +++++++-
 18 files changed, 54 insertions(+), 1 deletions(-)
fs/mount.h +1 -0
index d55297f..c076f99 100644
@@ -5,6 +5,7 @@
 struct mnt_namespace {
 	atomic_t		count;
 	unsigned int		proc_inum;
+	long long	serial_num;
 	struct mount *	root;
 	struct list_head	list;
 	struct user_namespace	*user_ns;
fs/namespace.c +1 -0
index 182bc41..9af49ff 100644
@@ -2486,6 +2486,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
 		kfree(new_ns);
 		return ERR_PTR(ret);
 	}
+	new_ns->serial_num = ns_serial();
 	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
 	atomic_set(&new_ns->count, 1);
 	new_ns->root = NULL;
include/linux/ipc_namespace.h +1 -0
index 35e7eca..8ccfb2d 100644
@@ -69,6 +69,7 @@ struct ipc_namespace {
 	struct user_namespace *user_ns;
 
 	unsigned int	proc_inum;
+	long long	serial_num;
 };
 
 extern struct ipc_namespace init_ipc_ns;
include/linux/nsproxy.h +10 -0
index b4ec59d..9d627b5 100644
@@ -66,6 +66,16 @@ static inline struct nsproxy *task_nsproxy(struct task_struct *tsk)
 	return rcu_dereference(tsk->nsproxy);
 }
 
+long long ns_serial(void);
+enum {
+	NS_IPC_INIT_SN	= 1,
+	NS_UTS_INIT_SN	= 2,
+	NS_USER_INIT_SN	= 3,
+	NS_PID_INIT_SN	= 4,
+	__NS_MAX_INIT_SN= 5,
+};
+#define NS_DYN_INIT_SN	(__NS_MAX_INIT_SN - 1)
+
 int copy_namespaces(unsigned long flags, struct task_struct *tsk);
 void exit_task_namespaces(struct task_struct *tsk);
 void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
include/linux/pid_namespace.h +1 -0
index 7246ef3..4d8023e 100644
@@ -43,6 +43,7 @@ struct pid_namespace {
 	int hide_pid;
 	int reboot;	/* group exit code if this pidns was rebooted */
 	unsigned int proc_inum;
+	long long	serial_num;
 };
 
 extern struct pid_namespace init_pid_ns;
include/linux/user_namespace.h +1 -0
index 4836ba3..159ac26 100644
@@ -27,6 +27,7 @@ struct user_namespace {
 	kuid_t			owner;
 	kgid_t			group;
 	unsigned int		proc_inum;
+	long long	serial_num;
 
 	/* Register of per-UID persistent keyrings for this namespace */
 #ifdef CONFIG_PERSISTENT_KEYRINGS
include/linux/utsname.h +1 -0
index 239e277..8490197 100644
@@ -24,6 +24,7 @@ struct uts_namespace {
 	struct new_utsname name;
 	struct user_namespace *user_ns;
 	unsigned int proc_inum;
+	long long	serial_num;
 };
 extern struct uts_namespace init_uts_ns;
 
include/net/net_namespace.h +1 -0
index 361d260..5238a06 100644
@@ -61,6 +61,7 @@ struct net {
 	struct user_namespace   *user_ns;	/* Owning user namespace */
 
 	unsigned int		proc_inum;
+	long long	serial_num;
 
 	struct proc_dir_entry 	*proc_net;
 	struct proc_dir_entry 	*proc_net_stat;
init/version.c +1 -0
index 1a4718e..cfdcb85 100644
@@ -36,6 +36,7 @@ struct uts_namespace init_uts_ns = {
 	},
 	.user_ns = &init_user_ns,
 	.proc_inum = PROC_UTS_INIT_INO,
+	.serial_num = NS_UTS_INIT_SN /* ns_serial() */,
 };
 EXPORT_SYMBOL_GPL(init_uts_ns);
 
ipc/msgutil.c +1 -0
index 7e70959..9aa66ae 100644
@@ -32,6 +32,7 @@ struct ipc_namespace init_ipc_ns = {
 	.count		= ATOMIC_INIT(1),
 	.user_ns = &init_user_ns,
 	.proc_inum = PROC_IPC_INIT_INO,
+	.serial_num = NS_IPC_INIT_SN /* ns_serial() */,
 };
 
 atomic_t nr_ipc_ns = ATOMIC_INIT(1);
ipc/namespace.c +2 -0
index 59451c1..76dac5c 100644
@@ -41,6 +41,8 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
 	}
 	atomic_inc(&nr_ipc_ns);
 
+	ns->serial_num = ns_serial();
+
 	sem_init_ns(ns);
 	msg_init_ns(ns);
 	shm_init_ns(ns);
kernel/nsproxy.c +18 -0
index 8e78110..0c2f25e 100644
@@ -41,6 +41,24 @@ struct nsproxy init_nsproxy = {
 #endif
 };
 
+/**
+ * ns_serial - compute a serial number for the namespace
+ *
+ * Compute a serial number for the namespace to uniquely identify it in
+ * audit records.
+ */
+long long ns_serial(void)
+{
+	/* reserved for IPC, UTS, user, PID */
+	static atomic64_t serial = ATOMIC_INIT(NS_DYN_INIT_SN);
+	long long ret;
+
+	ret = atomic64_add_return(1, &serial);
+	BUG_ON(!ret);
+
+	return ret;
+}
+
 static inline struct nsproxy *create_nsproxy(void)
 {
 	struct nsproxy *nsproxy;
kernel/pid.c +1 -0
index 9b9a266..3bf7127 100644
@@ -80,6 +80,7 @@ struct pid_namespace init_pid_ns = {
 	.child_reaper = &init_task,
 	.user_ns = &init_user_ns,
 	.proc_inum = PROC_PID_INIT_INO,
+	.serial_num = NS_PID_INIT_SN /* ns_serial() */,
 };
 EXPORT_SYMBOL_GPL(init_pid_ns);
 
kernel/pid_namespace.c +2 -0
index db95d8e..40a8b36 100644
@@ -109,6 +109,8 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
 	if (err)
 		goto out_free_map;
 
+	ns->serial_num = ns_serial();
+
 	kref_init(&ns->kref);
 	ns->level = level;
 	ns->parent = get_pid_ns(parent_pid_ns);
kernel/user.c +1 -0
index 4efa393..2f597e0 100644
@@ -51,6 +51,7 @@ struct user_namespace init_user_ns = {
 	.owner = GLOBAL_ROOT_UID,
 	.group = GLOBAL_ROOT_GID,
 	.proc_inum = PROC_USER_INIT_INO,
+	.serial_num = NS_USER_INIT_SN /* ns_serial() */,
 #ifdef CONFIG_PERSISTENT_KEYRINGS
 	.persistent_keyring_register_sem =
 	__RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
kernel/user_namespace.c +2 -0
index fcc0256..5c5c399 100644
@@ -92,6 +92,8 @@ int create_user_ns(struct cred *new)
 		return ret;
 	}
 
+	ns->serial_num = ns_serial();
+
 	atomic_set(&ns->count, 1);
 	/* Leave the new->user_ns reference with the new user namespace. */
 	ns->parent = parent_ns;
kernel/utsname.c +2 -0
index fd39312..d0cf7b5 100644
@@ -48,6 +48,8 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
 		return ERR_PTR(err);
 	}
 
+	ns->serial_num = ns_serial();
+
 	down_read(&uts_sem);
 	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
 	ns->user_ns = get_user_ns(user_ns);
net/core/net_namespace.c +7 -1
index 85b6269..3b5cfdb 100644
@@ -384,7 +384,13 @@ EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
 
 static __net_init int net_ns_net_init(struct net *net)
 {
-	return proc_alloc_inum(&net->proc_inum);
+	int ret;
+
+	ret = proc_alloc_inum(&net->proc_inum);
+	if (ret)
+		return ret;
+	net->serial_num = ns_serial();
+	return 0;
 }
 
 static __net_exit void net_ns_net_exit(struct net *net)
Signature · 1 line
1.7.1
#2 lore raw

RE: [PATCH V5 01/13] namespaces: assign each namespace instance a serial number

Quoted 86 lines

-----Original Message-----
From: containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org [mailto:containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org] On Behalf Of Richard Guy
Briggs
Sent: Monday, October 06, 2014 1:08 PM
To: [email protected]; [email protected]; containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc: [email protected]; [email protected]; [email protected]; [email protected]; ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Subject: [PATCH V5 01/13] namespaces: assign each namespace instance a serial
number

Generate and assign a serial number per namespace instance since boot.

Use a serial number per namespace (unique across one boot of one kernel) instead of the inode number (which is claimed to have had the right to change reserved and is not necessarily unique if there is more than one proc fs) to uniquely identify it per kernel boot.

---
 fs/mount.h                     |    1 +
 fs/namespace.c                 |    1 +
 include/linux/ipc_namespace.h  |    1 +
 include/linux/nsproxy.h        |   10 ++++++++++
 include/linux/pid_namespace.h  |    1 +
 include/linux/user_namespace.h |    1 +
 include/linux/utsname.h        |    1 +
 include/net/net_namespace.h    |    1 +
 init/version.c                 |    1 +
 ipc/msgutil.c                  |    1 +
 ipc/namespace.c                |    2 ++
 kernel/nsproxy.c               |   18 ++++++++++++++++++
 kernel/pid.c                   |    1 +
 kernel/pid_namespace.c         |    2 ++
 kernel/user.c                  |    1 +
 kernel/user_namespace.c        |    2 ++
 kernel/utsname.c               |    2 ++
 net/core/net_namespace.c       |    8 +++++++-
 18 files changed, 54 insertions(+), 1 deletions(-)
fs/mount.h +1 -0
index d55297f..c076f99 100644
@@ -5,6 +5,7 @@
 struct mnt_namespace {
 	atomic_t		count;
 	unsigned int		proc_inum;
+	long long	serial_num;
 	struct mount *	root;
 	struct list_head	list;
 	struct user_namespace	*user_ns;
fs/namespace.c +1 -0
index 182bc41..9af49ff 100644
@@ -2486,6 +2486,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct
 user_namespace *user_ns)
 		kfree(new_ns);
 		return ERR_PTR(ret);
 	}
+	new_ns->serial_num = ns_serial();
 	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
 	atomic_set(&new_ns->count, 1);
fs/namespace.c +0 -0
 	new_ns->root = NULL;
include/linux/ipc_namespace.h +1 -0
index 35e7eca..8ccfb2d 100644
@@ -69,6 +69,7 @@ struct ipc_namespace {
 	struct user_namespace *user_ns;
 
 	unsigned int	proc_inum;
+	long long	serial_num;
 };
 
 extern struct ipc_namespace init_ipc_ns;
include/linux/nsproxy.h +0 -0
index b4ec59d..9d627b5 100644
@@ -66,6 +66,16 @@ static inline struct nsproxy *task_nsproxy(struct task_struct
 *tsk)

include/linux/nsproxy.h static inline struct nsproxy *task_nsproxy(struct task_struct · line 76

Quoted 10 lines
include/linux/nsproxy.h +7 -0
 	return rcu_dereference(tsk->nsproxy);
 }
 
+long long ns_serial(void);
+enum {
+	NS_IPC_INIT_SN	= 1,
+	NS_UTS_INIT_SN	= 2,
+	NS_USER_INIT_SN	= 3,
+	NS_PID_INIT_SN	= 4,
+	__NS_MAX_INIT_SN= 5,

You may need a space before '='.

The rest looks good to me.

Thanks,

- Chen

#3 lore raw

Re: [PATCH V5 01/13] namespaces: assign each namespace instance a serial number

Quoted 87 lines · Hanxiao
Quoted 87 lines

-----Original Message-----
From: containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org [mailto:containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org] On Behalf Of Richard Guy
Briggs
Sent: Monday, October 06, 2014 1:08 PM
To: [email protected]; [email protected]; containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc: [email protected]; [email protected]; [email protected]; [email protected]; ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Subject: [PATCH V5 01/13] namespaces: assign each namespace instance a serial
number

Generate and assign a serial number per namespace instance since boot.

Use a serial number per namespace (unique across one boot of one kernel) instead of the inode number (which is claimed to have had the right to change reserved and is not necessarily unique if there is more than one proc fs) to uniquely identify it per kernel boot.

---
 fs/mount.h                     |    1 +
 fs/namespace.c                 |    1 +
 include/linux/ipc_namespace.h  |    1 +
 include/linux/nsproxy.h        |   10 ++++++++++
 include/linux/pid_namespace.h  |    1 +
 include/linux/user_namespace.h |    1 +
 include/linux/utsname.h        |    1 +
 include/net/net_namespace.h    |    1 +
 init/version.c                 |    1 +
 ipc/msgutil.c                  |    1 +
 ipc/namespace.c                |    2 ++
 kernel/nsproxy.c               |   18 ++++++++++++++++++
 kernel/pid.c                   |    1 +
 kernel/pid_namespace.c         |    2 ++
 kernel/user.c                  |    1 +
 kernel/user_namespace.c        |    2 ++
 kernel/utsname.c               |    2 ++
 net/core/net_namespace.c       |    8 +++++++-
 18 files changed, 54 insertions(+), 1 deletions(-)
fs/mount.h +1 -0
index d55297f..c076f99 100644
@@ -5,6 +5,7 @@
 struct mnt_namespace {
 	atomic_t		count;
 	unsigned int		proc_inum;
+	long long	serial_num;
 	struct mount *	root;
 	struct list_head	list;
 	struct user_namespace	*user_ns;
fs/namespace.c +1 -0
index 182bc41..9af49ff 100644
@@ -2486,6 +2486,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct
 user_namespace *user_ns)
 		kfree(new_ns);
 		return ERR_PTR(ret);
 	}
+	new_ns->serial_num = ns_serial();
 	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
 	atomic_set(&new_ns->count, 1);
fs/namespace.c +0 -0
 	new_ns->root = NULL;
include/linux/ipc_namespace.h +1 -0
index 35e7eca..8ccfb2d 100644
@@ -69,6 +69,7 @@ struct ipc_namespace {
 	struct user_namespace *user_ns;
 
 	unsigned int	proc_inum;
+	long long	serial_num;
 };
 
 extern struct ipc_namespace init_ipc_ns;
include/linux/nsproxy.h +0 -0
index b4ec59d..9d627b5 100644
@@ -66,6 +66,16 @@ static inline struct nsproxy *task_nsproxy(struct task_struct
 *tsk)
 	return rcu_dereference(tsk->nsproxy);
 }
 
Quoted 9 lines

include/linux/nsproxy.h static inline struct nsproxy *task_nsproxy(struct task_struct *tsk) · line 75

Quoted 7 lines
include/linux/nsproxy.h +7 -0
+long long ns_serial(void);
+enum {
+	NS_IPC_INIT_SN	= 1,
+	NS_UTS_INIT_SN	= 2,
+	NS_USER_INIT_SN	= 3,
+	NS_PID_INIT_SN	= 4,
+	__NS_MAX_INIT_SN= 5,

You may need a space before '='.

Thanks, cleaned up.

Quoted 5 lines

The rest looks good to me.

Thanks,

- Chen

- RGB

--
Richard Guy Briggs <[email protected]> Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

maintainer Acked-by Serge Hallyn on v5 1/13
#4 lore raw

Re: [PATCH V5 01/13] namespaces: assign each namespace instance a serial number

In reply to Richard Guy Briggs
Quoted 8 lines · Richard Guy Briggs

Generate and assign a serial number per namespace instance since boot.

Use a serial number per namespace (unique across one boot of one kernel) instead of the inode number (which is claimed to have had the right to change reserved and is not necessarily unique if there is more than one proc fs) to uniquely identify it per kernel boot.

Quoted 276 lines
---
 fs/mount.h                     |    1 +
 fs/namespace.c                 |    1 +
 include/linux/ipc_namespace.h  |    1 +
 include/linux/nsproxy.h        |   10 ++++++++++
 include/linux/pid_namespace.h  |    1 +
 include/linux/user_namespace.h |    1 +
 include/linux/utsname.h        |    1 +
 include/net/net_namespace.h    |    1 +
 init/version.c                 |    1 +
 ipc/msgutil.c                  |    1 +
 ipc/namespace.c                |    2 ++
 kernel/nsproxy.c               |   18 ++++++++++++++++++
 kernel/pid.c                   |    1 +
 kernel/pid_namespace.c         |    2 ++
 kernel/user.c                  |    1 +
 kernel/user_namespace.c        |    2 ++
 kernel/utsname.c               |    2 ++
 net/core/net_namespace.c       |    8 +++++++-
 18 files changed, 54 insertions(+), 1 deletions(-)
fs/mount.h +1 -0
index d55297f..c076f99 100644
@@ -5,6 +5,7 @@
 struct mnt_namespace {
 	atomic_t		count;
 	unsigned int		proc_inum;
+	long long	serial_num;
 	struct mount *	root;
 	struct list_head	list;
 	struct user_namespace	*user_ns;
fs/namespace.c +1 -0
index 182bc41..9af49ff 100644
@@ -2486,6 +2486,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
 		kfree(new_ns);
 		return ERR_PTR(ret);
 	}
+	new_ns->serial_num = ns_serial();
 	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
 	atomic_set(&new_ns->count, 1);
 	new_ns->root = NULL;
include/linux/ipc_namespace.h +1 -0
index 35e7eca..8ccfb2d 100644
@@ -69,6 +69,7 @@ struct ipc_namespace {
 	struct user_namespace *user_ns;
 
 	unsigned int	proc_inum;
+	long long	serial_num;
 };
 
 extern struct ipc_namespace init_ipc_ns;
include/linux/nsproxy.h +10 -0
index b4ec59d..9d627b5 100644
@@ -66,6 +66,16 @@ static inline struct nsproxy *task_nsproxy(struct task_struct *tsk)
 	return rcu_dereference(tsk->nsproxy);
 }
 
+long long ns_serial(void);
+enum {
+	NS_IPC_INIT_SN	= 1,
+	NS_UTS_INIT_SN	= 2,
+	NS_USER_INIT_SN	= 3,
+	NS_PID_INIT_SN	= 4,
+	__NS_MAX_INIT_SN= 5,
+};
+#define NS_DYN_INIT_SN	(__NS_MAX_INIT_SN - 1)
+
 int copy_namespaces(unsigned long flags, struct task_struct *tsk);
 void exit_task_namespaces(struct task_struct *tsk);
 void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
include/linux/pid_namespace.h +1 -0
index 7246ef3..4d8023e 100644
@@ -43,6 +43,7 @@ struct pid_namespace {
 	int hide_pid;
 	int reboot;	/* group exit code if this pidns was rebooted */
 	unsigned int proc_inum;
+	long long	serial_num;
 };
 
 extern struct pid_namespace init_pid_ns;
include/linux/user_namespace.h +1 -0
index 4836ba3..159ac26 100644
@@ -27,6 +27,7 @@ struct user_namespace {
 	kuid_t			owner;
 	kgid_t			group;
 	unsigned int		proc_inum;
+	long long	serial_num;
 
 	/* Register of per-UID persistent keyrings for this namespace */
 #ifdef CONFIG_PERSISTENT_KEYRINGS
include/linux/utsname.h +1 -0
index 239e277..8490197 100644
@@ -24,6 +24,7 @@ struct uts_namespace {
 	struct new_utsname name;
 	struct user_namespace *user_ns;
 	unsigned int proc_inum;
+	long long	serial_num;
 };
 extern struct uts_namespace init_uts_ns;
 
include/net/net_namespace.h +1 -0
index 361d260..5238a06 100644
@@ -61,6 +61,7 @@ struct net {
 	struct user_namespace   *user_ns;	/* Owning user namespace */
 
 	unsigned int		proc_inum;
+	long long	serial_num;
 
 	struct proc_dir_entry 	*proc_net;
 	struct proc_dir_entry 	*proc_net_stat;
init/version.c +1 -0
index 1a4718e..cfdcb85 100644
@@ -36,6 +36,7 @@ struct uts_namespace init_uts_ns = {
 	},
 	.user_ns = &init_user_ns,
 	.proc_inum = PROC_UTS_INIT_INO,
+	.serial_num = NS_UTS_INIT_SN /* ns_serial() */,
 };
 EXPORT_SYMBOL_GPL(init_uts_ns);
 
ipc/msgutil.c +1 -0
index 7e70959..9aa66ae 100644
@@ -32,6 +32,7 @@ struct ipc_namespace init_ipc_ns = {
 	.count		= ATOMIC_INIT(1),
 	.user_ns = &init_user_ns,
 	.proc_inum = PROC_IPC_INIT_INO,
+	.serial_num = NS_IPC_INIT_SN /* ns_serial() */,
 };
 
 atomic_t nr_ipc_ns = ATOMIC_INIT(1);
ipc/namespace.c +2 -0
index 59451c1..76dac5c 100644
@@ -41,6 +41,8 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
 	}
 	atomic_inc(&nr_ipc_ns);
 
+	ns->serial_num = ns_serial();
+
 	sem_init_ns(ns);
 	msg_init_ns(ns);
 	shm_init_ns(ns);
kernel/nsproxy.c +18 -0
index 8e78110..0c2f25e 100644
@@ -41,6 +41,24 @@ struct nsproxy init_nsproxy = {
 #endif
 };
 
+/**
+ * ns_serial - compute a serial number for the namespace
+ *
+ * Compute a serial number for the namespace to uniquely identify it in
+ * audit records.
+ */
+long long ns_serial(void)
+{
+	/* reserved for IPC, UTS, user, PID */
+	static atomic64_t serial = ATOMIC_INIT(NS_DYN_INIT_SN);
+	long long ret;
+
+	ret = atomic64_add_return(1, &serial);
+	BUG_ON(!ret);
+
+	return ret;
+}
+
 static inline struct nsproxy *create_nsproxy(void)
 {
 	struct nsproxy *nsproxy;
kernel/pid.c +1 -0
index 9b9a266..3bf7127 100644
@@ -80,6 +80,7 @@ struct pid_namespace init_pid_ns = {
 	.child_reaper = &init_task,
 	.user_ns = &init_user_ns,
 	.proc_inum = PROC_PID_INIT_INO,
+	.serial_num = NS_PID_INIT_SN /* ns_serial() */,
 };
 EXPORT_SYMBOL_GPL(init_pid_ns);
 
kernel/pid_namespace.c +2 -0
index db95d8e..40a8b36 100644
@@ -109,6 +109,8 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
 	if (err)
 		goto out_free_map;
 
+	ns->serial_num = ns_serial();
+
 	kref_init(&ns->kref);
 	ns->level = level;
 	ns->parent = get_pid_ns(parent_pid_ns);
kernel/user.c +1 -0
index 4efa393..2f597e0 100644
@@ -51,6 +51,7 @@ struct user_namespace init_user_ns = {
 	.owner = GLOBAL_ROOT_UID,
 	.group = GLOBAL_ROOT_GID,
 	.proc_inum = PROC_USER_INIT_INO,
+	.serial_num = NS_USER_INIT_SN /* ns_serial() */,
 #ifdef CONFIG_PERSISTENT_KEYRINGS
 	.persistent_keyring_register_sem =
 	__RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
kernel/user_namespace.c +2 -0
index fcc0256..5c5c399 100644
@@ -92,6 +92,8 @@ int create_user_ns(struct cred *new)
 		return ret;
 	}
 
+	ns->serial_num = ns_serial();
+
 	atomic_set(&ns->count, 1);
 	/* Leave the new->user_ns reference with the new user namespace. */
 	ns->parent = parent_ns;
kernel/utsname.c +2 -0
index fd39312..d0cf7b5 100644
@@ -48,6 +48,8 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
 		return ERR_PTR(err);
 	}
 
+	ns->serial_num = ns_serial();
+
 	down_read(&uts_sem);
 	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
 	ns->user_ns = get_user_ns(user_ns);
net/core/net_namespace.c +7 -1
index 85b6269..3b5cfdb 100644
@@ -384,7 +384,13 @@ EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
 
 static __net_init int net_ns_net_init(struct net *net)
 {
-	return proc_alloc_inum(&net->proc_inum);
+	int ret;
+
+	ret = proc_alloc_inum(&net->proc_inum);
+	if (ret)
+		return ret;
+	net->serial_num = ns_serial();
+	return 0;
 }
 
 static __net_exit void net_ns_net_exit(struct net *net)
Signature · 1 line
1.7.1
#5 lore raw

PATCH v5 2/13 namespaces: expose namespace instance serial number in proc_ns_operations

In reply to Richard Guy Briggs

Expose the namespace instance serial number for each namespace type in the proc namespace operations structure to make it available for the proc filesystem.

---
 fs/namespace.c           |    7 +++++++
 include/linux/proc_ns.h  |    1 +
 ipc/namespace.c          |    8 ++++++++
 kernel/pid_namespace.c   |    7 +++++++
 kernel/user_namespace.c  |    7 +++++++
 kernel/utsname.c         |    8 ++++++++
 net/core/net_namespace.c |    7 +++++++
 7 files changed, 45 insertions(+), 0 deletions(-)
fs/namespace.c +7 -0
index 9af49ff..f433f21 100644
@@ -3028,6 +3028,12 @@ static unsigned int mntns_inum(void *ns)
 	return mnt_ns->proc_inum;
 }
 
+static long long mntns_snum(void *ns)
+{
+	struct mnt_namespace *mnt_ns = ns;
+	return mnt_ns->serial_num;
+}
+
 const struct proc_ns_operations mntns_operations = {
 	.name		= "mnt",
 	.type		= CLONE_NEWNS,
@@ -3035,4 +3041,5 @@ const struct proc_ns_operations mntns_operations = {
 	.put		= mntns_put,
 	.install	= mntns_install,
 	.inum		= mntns_inum,
+	.snum		= mntns_snum,
 };
include/linux/proc_ns.h +1 -0
index 34a1e10..aaafe3e 100644
@@ -14,6 +14,7 @@ struct proc_ns_operations {
 	void (*put)(void *ns);
 	int (*install)(struct nsproxy *nsproxy, void *ns);
 	unsigned int (*inum)(void *ns);
+	long long (*snum)(void *ns);
 };
 
 struct proc_ns {
ipc/namespace.c +8 -0
index 76dac5c..36ce7ff 100644
@@ -191,6 +191,13 @@ static unsigned int ipcns_inum(void *vp)
 	return ns->proc_inum;
 }
 
+static long long ipcns_snum(void *vp)
+{
+	struct ipc_namespace *ns = vp;
+
+	return ns->serial_num;
+}
+
 const struct proc_ns_operations ipcns_operations = {
 	.name		= "ipc",
 	.type		= CLONE_NEWIPC,
@@ -198,4 +205,5 @@ const struct proc_ns_operations ipcns_operations = {
 	.put		= ipcns_put,
 	.install	= ipcns_install,
 	.inum		= ipcns_inum,
+	.snum		= ipcns_snum,
 };
kernel/pid_namespace.c +7 -0
index 40a8b36..059b330 100644
@@ -370,6 +370,12 @@ static unsigned int pidns_inum(void *ns)
 	return pid_ns->proc_inum;
 }
 
+static long long pidns_snum(void *ns)
+{
+	struct pid_namespace *pid_ns = ns;
+	return pid_ns->serial_num;
+}
+
 const struct proc_ns_operations pidns_operations = {
 	.name		= "pid",
 	.type		= CLONE_NEWPID,
@@ -377,6 +383,7 @@ const struct proc_ns_operations pidns_operations = {
 	.put		= pidns_put,
 	.install	= pidns_install,
 	.inum		= pidns_inum,
+	.snum		= pidns_snum,
 };
 
 static __init int pid_namespaces_init(void)
kernel/user_namespace.c +7 -0
index 5c5c399..3f04df5 100644
@@ -896,6 +896,12 @@ static unsigned int userns_inum(void *ns)
 	return user_ns->proc_inum;
 }
 
+static long long userns_snum(void *ns)
+{
+	struct user_namespace *user_ns = ns;
+	return user_ns->serial_num;
+}
+
 const struct proc_ns_operations userns_operations = {
 	.name		= "user",
 	.type		= CLONE_NEWUSER,
@@ -903,6 +909,7 @@ const struct proc_ns_operations userns_operations = {
 	.put		= userns_put,
 	.install	= userns_install,
 	.inum		= userns_inum,
+	.snum		= userns_snum,
 };
 
 static __init int user_namespaces_init(void)
kernel/utsname.c +8 -0
index d0cf7b5..ffeac1b 100644
@@ -132,6 +132,13 @@ static unsigned int utsns_inum(void *vp)
 	return ns->proc_inum;
 }
 
+static long long utsns_snum(void *vp)
+{
+	struct uts_namespace *ns = vp;
+
+	return ns->serial_num;
+}
+
 const struct proc_ns_operations utsns_operations = {
 	.name		= "uts",
 	.type		= CLONE_NEWUTS,
@@ -139,4 +146,5 @@ const struct proc_ns_operations utsns_operations = {
 	.put		= utsns_put,
 	.install	= utsns_install,
 	.inum		= utsns_inum,
+	.snum		= utsns_snum,
 };
net/core/net_namespace.c +7 -0
index 3b5cfdb..c402eea 100644
@@ -671,6 +671,12 @@ static unsigned int netns_inum(void *ns)
 	return net->proc_inum;
 }
 
+static long long netns_snum(void *ns)
+{
+	struct net *net = ns;
+	return net->serial_num;
+}
+
 const struct proc_ns_operations netns_operations = {
 	.name		= "net",
 	.type		= CLONE_NEWNET,
@@ -678,5 +684,6 @@ const struct proc_ns_operations netns_operations = {
 	.put		= netns_put,
 	.install	= netns_install,
 	.inum		= netns_inum,
+	.snum		= netns_snum,
 };
 #endif
Signature · 1 line
1.7.1
maintainer Acked-by Serge Hallyn on v5 2/13
#6 lore raw

Re: [PATCH V5 02/13] namespaces: expose namespace instance serial number in proc_ns_operations

Quoted 4 lines · Richard Guy Briggs

Expose the namespace instance serial number for each namespace type in the proc namespace operations structure to make it available for the proc filesystem.

Quoted 169 lines
---
 fs/namespace.c           |    7 +++++++
 include/linux/proc_ns.h  |    1 +
 ipc/namespace.c          |    8 ++++++++
 kernel/pid_namespace.c   |    7 +++++++
 kernel/user_namespace.c  |    7 +++++++
 kernel/utsname.c         |    8 ++++++++
 net/core/net_namespace.c |    7 +++++++
 7 files changed, 45 insertions(+), 0 deletions(-)
fs/namespace.c +7 -0
index 9af49ff..f433f21 100644
@@ -3028,6 +3028,12 @@ static unsigned int mntns_inum(void *ns)
 	return mnt_ns->proc_inum;
 }
 
+static long long mntns_snum(void *ns)
+{
+	struct mnt_namespace *mnt_ns = ns;
+	return mnt_ns->serial_num;
+}
+
 const struct proc_ns_operations mntns_operations = {
 	.name		= "mnt",
 	.type		= CLONE_NEWNS,
@@ -3035,4 +3041,5 @@ const struct proc_ns_operations mntns_operations = {
 	.put		= mntns_put,
 	.install	= mntns_install,
 	.inum		= mntns_inum,
+	.snum		= mntns_snum,
 };
include/linux/proc_ns.h +1 -0
index 34a1e10..aaafe3e 100644
@@ -14,6 +14,7 @@ struct proc_ns_operations {
 	void (*put)(void *ns);
 	int (*install)(struct nsproxy *nsproxy, void *ns);
 	unsigned int (*inum)(void *ns);
+	long long (*snum)(void *ns);
 };
 
 struct proc_ns {
ipc/namespace.c +8 -0
index 76dac5c..36ce7ff 100644
@@ -191,6 +191,13 @@ static unsigned int ipcns_inum(void *vp)
 	return ns->proc_inum;
 }
 
+static long long ipcns_snum(void *vp)
+{
+	struct ipc_namespace *ns = vp;
+
+	return ns->serial_num;
+}
+
 const struct proc_ns_operations ipcns_operations = {
 	.name		= "ipc",
 	.type		= CLONE_NEWIPC,
@@ -198,4 +205,5 @@ const struct proc_ns_operations ipcns_operations = {
 	.put		= ipcns_put,
 	.install	= ipcns_install,
 	.inum		= ipcns_inum,
+	.snum		= ipcns_snum,
 };
kernel/pid_namespace.c +7 -0
index 40a8b36..059b330 100644
@@ -370,6 +370,12 @@ static unsigned int pidns_inum(void *ns)
 	return pid_ns->proc_inum;
 }
 
+static long long pidns_snum(void *ns)
+{
+	struct pid_namespace *pid_ns = ns;
+	return pid_ns->serial_num;
+}
+
 const struct proc_ns_operations pidns_operations = {
 	.name		= "pid",
 	.type		= CLONE_NEWPID,
@@ -377,6 +383,7 @@ const struct proc_ns_operations pidns_operations = {
 	.put		= pidns_put,
 	.install	= pidns_install,
 	.inum		= pidns_inum,
+	.snum		= pidns_snum,
 };
 
 static __init int pid_namespaces_init(void)
kernel/user_namespace.c +7 -0
index 5c5c399..3f04df5 100644
@@ -896,6 +896,12 @@ static unsigned int userns_inum(void *ns)
 	return user_ns->proc_inum;
 }
 
+static long long userns_snum(void *ns)
+{
+	struct user_namespace *user_ns = ns;
+	return user_ns->serial_num;
+}
+
 const struct proc_ns_operations userns_operations = {
 	.name		= "user",
 	.type		= CLONE_NEWUSER,
@@ -903,6 +909,7 @@ const struct proc_ns_operations userns_operations = {
 	.put		= userns_put,
 	.install	= userns_install,
 	.inum		= userns_inum,
+	.snum		= userns_snum,
 };
 
 static __init int user_namespaces_init(void)
kernel/utsname.c +8 -0
index d0cf7b5..ffeac1b 100644
@@ -132,6 +132,13 @@ static unsigned int utsns_inum(void *vp)
 	return ns->proc_inum;
 }
 
+static long long utsns_snum(void *vp)
+{
+	struct uts_namespace *ns = vp;
+
+	return ns->serial_num;
+}
+
 const struct proc_ns_operations utsns_operations = {
 	.name		= "uts",
 	.type		= CLONE_NEWUTS,
@@ -139,4 +146,5 @@ const struct proc_ns_operations utsns_operations = {
 	.put		= utsns_put,
 	.install	= utsns_install,
 	.inum		= utsns_inum,
+	.snum		= utsns_snum,
 };
net/core/net_namespace.c +7 -0
index 3b5cfdb..c402eea 100644
@@ -671,6 +671,12 @@ static unsigned int netns_inum(void *ns)
 	return net->proc_inum;
 }
 
+static long long netns_snum(void *ns)
+{
+	struct net *net = ns;
+	return net->serial_num;
+}
+
 const struct proc_ns_operations netns_operations = {
 	.name		= "net",
 	.type		= CLONE_NEWNET,
@@ -678,5 +684,6 @@ const struct proc_ns_operations netns_operations = {
 	.put		= netns_put,
 	.install	= netns_install,
 	.inum		= netns_inum,
+	.snum		= netns_snum,
 };
 #endif
Signature · 1 line
1.7.1
#7 lore raw

PATCH v5 3/13 namespaces: expose ns_entries

In reply to Richard Guy Briggs

Expose ns_entries so subsystems other than proc can use this set of namespace operations.

---
 fs/proc/namespaces.c    |    2 +-
 include/linux/proc_ns.h |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)
fs/proc/namespaces.c +1 -1
index 8902609..310da74 100644
@@ -15,7 +15,7 @@
 #include "internal.h"
 
 
-static const struct proc_ns_operations *ns_entries[] = {
+const struct proc_ns_operations *ns_entries[] = {
 #ifdef CONFIG_NET_NS
 	&netns_operations,
 #endif
include/linux/proc_ns.h +1 -0
index aaafe3e..f4563db 100644
@@ -28,6 +28,7 @@ extern const struct proc_ns_operations ipcns_operations;
 extern const struct proc_ns_operations pidns_operations;
 extern const struct proc_ns_operations userns_operations;
 extern const struct proc_ns_operations mntns_operations;
+extern const struct proc_ns_operations *ns_entries[];
 
 /*
  * We always define these enumerators
Signature · 1 line
1.7.1
maintainer Acked-by Serge Hallyn on v5 3/13
#8 lore raw

Re: [PATCH V5 03/13] namespaces: expose ns_entries

Quoted 4 lines · Richard Guy Briggs

Expose ns_entries so subsystems other than proc can use this set of namespace operations.

Quoted 32 lines
---
 fs/proc/namespaces.c    |    2 +-
 include/linux/proc_ns.h |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)
fs/proc/namespaces.c +1 -1
index 8902609..310da74 100644
@@ -15,7 +15,7 @@
 #include "internal.h"
 
 
-static const struct proc_ns_operations *ns_entries[] = {
+const struct proc_ns_operations *ns_entries[] = {
 #ifdef CONFIG_NET_NS
 	&netns_operations,
 #endif
include/linux/proc_ns.h +1 -0
index aaafe3e..f4563db 100644
@@ -28,6 +28,7 @@ extern const struct proc_ns_operations ipcns_operations;
 extern const struct proc_ns_operations pidns_operations;
 extern const struct proc_ns_operations userns_operations;
 extern const struct proc_ns_operations mntns_operations;
+extern const struct proc_ns_operations *ns_entries[];
 
 /*
  * We always define these enumerators
Signature · 1 line
1.7.1
#9 lore raw

PATCH v5 4/13 audit: log namespace serial numbers

In reply to Richard Guy Briggs

Log the namespace serial numbers of a task in a new record type (1329) (usually accompanies audit_log_task_info() type=SYSCALL record) which is used by syscall audits, among others..

Idea first presented:

	https://www.redhat.com/archives/linux-audit/2013-March/msg00020.html

Typical output format would look something like:

	type=NS_INFO msg=audit(1408577535.306:82):  netns=8 utsns=2 ipcns=1 pidns=4 userns=3 mntns=5

The serial numbers are printed in hex.

---
 include/linux/audit.h            |    8 ++++++++
 include/uapi/linux/audit.h       |    1 +
 kernel/audit.c                   |   30 ++++++++++++++++++++++++++++++
 kernel/auditsc.c                 |    2 ++
 security/integrity/ima/ima_api.c |    2 ++
 5 files changed, 43 insertions(+), 0 deletions(-)
include/linux/audit.h +8 -0
index 36dffec..7cdebdc 100644
@@ -475,6 +475,12 @@ static inline void	    audit_log_secctx(struct audit_buffer *ab, u32 secid)
 extern int audit_log_task_context(struct audit_buffer *ab);
 extern void audit_log_task_info(struct audit_buffer *ab,
 				struct task_struct *tsk);
+#ifdef CONFIG_NAMESPACES
+extern void		    audit_log_ns_info(struct task_struct *tsk);
+#else
+static inline void	    audit_log_ns_info(struct task_struct *tsk)
+{ }
+#endif
 
 extern int		    audit_update_lsm_rules(void);
 
@@ -531,6 +537,8 @@ static inline int audit_log_task_context(struct audit_buffer *ab)
 static inline void audit_log_task_info(struct audit_buffer *ab,
 				       struct task_struct *tsk)
 { }
+static inline void audit_log_ns_info(struct task_struct *tsk)
+{ }
 #define audit_enabled 0
 #endif /* CONFIG_AUDIT */
 static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
include/uapi/linux/audit.h +1 -0
index 4d100c8..760357e 100644
@@ -110,6 +110,7 @@
 #define AUDIT_SECCOMP		1326	/* Secure Computing event */
 #define AUDIT_PROCTITLE		1327	/* Proctitle emit event */
 #define AUDIT_FEATURE_CHANGE	1328	/* audit log listing feature changes */
+#define AUDIT_NS_INFO		1329	/* Record process namespace IDs */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
kernel/audit.c +30 -0
index 53bb39b..ff1630d 100644
@@ -65,6 +65,7 @@
 #include <linux/freezer.h>
 #include <linux/tty.h>
 #include <linux/pid_namespace.h>
+#include <linux/proc_ns.h>
 #include <net/netns/generic.h>
 
 #include "audit.h"
@@ -743,6 +744,8 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature
 			 audit_feature_names[which], !!old_feature, !!new_feature,
 			 !!old_lock, !!new_lock, res);
 	audit_log_end(ab);
+
+	audit_log_ns_info(current);
 }
 
 static int audit_set_feature(struct sk_buff *skb)
@@ -1651,6 +1654,31 @@ void audit_log_session_info(struct audit_buffer *ab)
 	audit_log_format(ab, " auid=%u ses=%u", auid, sessionid);
 }
 
+#ifdef CONFIG_NAMESPACES
+void audit_log_ns_info(struct task_struct *tsk)
+{
+	const struct proc_ns_operations **entry;
+	bool end = false;
+	struct audit_buffer *ab;
+
+	if (!tsk)
+		return;
+	ab = audit_log_start(tsk->audit_context, GFP_KERNEL,
+			     AUDIT_NS_INFO);
+	if (!ab)
+		return;
+	audit_log_format(ab, " pid=%d", task_pid_nr(tsk));
+	for (entry = ns_entries; !end; entry++) {
+		void *ns = (*entry)->get(tsk);
+		audit_log_format(ab, " %sns=%llx", (*entry)->name,
+				 (*entry)->snum(ns));
+		(*entry)->put(ns);
+		end = (*entry)->type == CLONE_NEWNS;
+	}
+	audit_log_end(ab);
+}
+#endif /* CONFIG_NAMESPACES */
+
 void audit_log_key(struct audit_buffer *ab, char *key)
 {
 	audit_log_format(ab, " key=");
@@ -1922,6 +1950,8 @@ void audit_log_link_denied(const char *operation, struct path *link)
 	audit_log_format(ab, " res=0");
 	audit_log_end(ab);
 
+	audit_log_ns_info(current);
+
 	/* Generate AUDIT_PATH record with object. */
 	name->type = AUDIT_TYPE_NORMAL;
 	audit_copy_inode(name, link->dentry, link->dentry->d_inode);
kernel/auditsc.c +2 -0
index 8933572..d4a23f4 100644
@@ -1376,6 +1376,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 	audit_log_key(ab, context->filterkey);
 	audit_log_end(ab);
 
+	audit_log_ns_info(tsk);
+
 	for (aux = context->aux; aux; aux = aux->next) {
 
 		ab = audit_log_start(context, GFP_KERNEL, aux->type);
security/integrity/ima/ima_api.c +2 -0
index d9cd5ce..58ac695 100644
@@ -323,6 +323,8 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
 	audit_log_task_info(ab, current);
 	audit_log_end(ab);
 
+	audit_log_ns_info(current);
+
 	iint->flags |= IMA_AUDITED;
 }
 
Signature · 1 line
1.7.1
#10 lore raw

PATCH v5 5/13 audit: initialize at subsystem time rather than device time

In reply to Richard Guy Briggs

The audit subsystem should be initialized a bit earlier so that it is in place in time for initial namespace serial number logging.

---
 kernel/audit.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/audit.c +1 -1
index ff1630d..8ff7f28 100644
@@ -1186,7 +1186,7 @@ static int __init audit_init(void)
 
 	return 0;
 }
-__initcall(audit_init);
+subsys_initcall(audit_init);
 
 /* Process kernel command-line parameter at boot time.  audit=0 or audit=1. */
 static int __init audit_enable(char *str)
Signature · 1 line
1.7.1
maintainer Acked-by Serge Hallyn on v5 5/13
#11 lore raw

Re: [PATCH V5 05/13] audit: initialize at subsystem time rather than device time

Quoted 3 lines · Richard Guy Briggs

The audit subsystem should be initialized a bit earlier so that it is in place in time for initial namespace serial number logging.
---

Quoted 18 lines
 kernel/audit.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/audit.c +1 -1
index ff1630d..8ff7f28 100644
@@ -1186,7 +1186,7 @@ static int __init audit_init(void)
 
 	return 0;
 }
-__initcall(audit_init);
+subsys_initcall(audit_init);
 
 /* Process kernel command-line parameter at boot time.  audit=0 or audit=1. */
 static int __init audit_enable(char *str)
Signature · 1 line
1.7.1

A message that is not in the archive (sent off-list or not yet received): [email protected]

#13 lore raw

PATCH v5 5/13 audit: initialize at subsystem time rather than device time

The audit subsystem should be initialized a bit earlier so that it is in place in time for initial namespace serial number logging.

---
 kernel/audit.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/audit.c +1 -1
index ff1630d..8ff7f28 100644
@@ -1186,7 +1186,7 @@ static int __init audit_init(void)
 
 	return 0;
 }
-__initcall(audit_init);
+subsys_initcall(audit_init);
 
 /* Process kernel command-line parameter at boot time.  audit=0 or audit=1. */
 static int __init audit_enable(char *str)
Signature · 1 line
1.7.1
#14 lore raw

PATCH v5 9/13 fork: audit on creation of new namespace(s)

In reply to a message not in the archive

When clone(2) is called to fork a new process creating one or more namespaces, audit the event to tie the new pid with the namespace IDs.

Signed-off-by Richard Guy Briggs
---
 kernel/fork.c    |    3 +++
 kernel/nsproxy.c |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
kernel/fork.c +3 -0
index 6a13c46..a7fe4d5 100644
@@ -1624,6 +1624,9 @@ long do_fork(unsigned long clone_flags,
 			get_task_struct(p);
 		}
 
+		if (unlikely(clone_flags & CLONE_NEW_MASK)) {
+			audit_log_ns_info(p);
+		}
 		wake_up_new_task(p);
 
 		/* forking complete and child started to run, tell ptracer */
kernel/nsproxy.c +1 -0
index 0c2f25e..2cdc16b 100644
@@ -25,6 +25,7 @@
 #include <linux/proc_ns.h>
 #include <linux/file.h>
 #include <linux/syscalls.h>
+#include <linux/audit.h>
 
 static struct kmem_cache *nsproxy_cachep;
 
Signature · 1 line
1.7.1
#15 lore raw

PATCH v5 10/13 audit: log on switching namespace (setns)

In reply to a message not in the archive

Added six new audit message types, AUDIT_NS_SET_* and function audit_log_ns_set() to log a switch of namespace.

---
 include/linux/audit.h      |    4 +++
 include/uapi/linux/audit.h |    6 +++++
 kernel/audit.c             |   46 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/nsproxy.c           |    3 ++
 4 files changed, 59 insertions(+), 0 deletions(-)
include/linux/audit.h +4 -0
index 1474334..9de9b25 100644
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <uapi/linux/audit.h>
+#include <linux/proc_ns.h>
 
 struct audit_sig_info {
 	uid_t		uid;
@@ -484,6 +485,7 @@ static inline void	    audit_log_ns_info(struct task_struct *tsk)
 extern int		    audit_log_ns_init(int type, long long old_snum,
 					      long long snum);
 extern int		    audit_log_ns_del(int type, long long snum);
+extern void		    audit_log_ns_set(const struct proc_ns_operations *ops, void *ns);
 
 extern int		    audit_update_lsm_rules(void);
 
@@ -547,6 +549,8 @@ static inline int audit_log_ns_init(int type, long long old_snum,
 { }
 static inline int audit_log_ns_del(int type, long long snum)
 { }
+static inline void audit_log_ns_set(const struct proc_ns_operations *ops, void *ns)
+{ }
 #define audit_enabled 0
 #endif /* CONFIG_AUDIT */
 static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
include/uapi/linux/audit.h +6 -0
index 1acfea7..7ec7209 100644
@@ -123,6 +123,12 @@
 #define AUDIT_NS_DEL_USER	1339	/* Record USER namespace instance deletion */
 #define AUDIT_NS_DEL_PID	1340	/* Record PID namespace instance deletion */
 #define AUDIT_NS_DEL_NET	1341	/* Record NET namespace instance deletion */
+#define AUDIT_NS_SET_MNT	1342	/* Record mount namespace instance deletion */
+#define AUDIT_NS_SET_UTS	1343	/* Record UTS namespace instance deletion */
+#define AUDIT_NS_SET_IPC	1344	/* Record IPC namespace instance deletion */
+#define AUDIT_NS_SET_USER	1345	/* Record USER namespace instance deletion */
+#define AUDIT_NS_SET_PID	1346	/* Record PID namespace instance deletion */
+#define AUDIT_NS_SET_NET	1347	/* Record NET namespace instance deletion */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
kernel/audit.c +46 -0

52 lines not on this page · raw message

kernel/nsproxy.c +3 -0
index 2cdc16b..e37409a 100644
@@ -275,6 +275,9 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
 		goto out;
 	}
 	switch_task_namespaces(tsk, new_nsproxy);
+
+	audit_log_ns_set(ops, ei->ns);
+
 out:
 	fput(file);
 	return err;
Signature · 1 line
1.7.1
#16 lore raw

PATCH v5 11/13 audit: emit AUDIT_NS_INFO record with AUDIT_VIRT_CONTROL record

In reply to a message not in the archive
---
 include/uapi/linux/audit.h |    2 ++
 kernel/audit.c             |    2 ++
 2 files changed, 4 insertions(+), 0 deletions(-)
include/uapi/linux/audit.h +2 -0
index 7ec7209..beb23f7 100644
@@ -163,6 +163,8 @@
 
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
+#define AUDIT_VIRT_CONTROL	2500	/* Start, Pause, Stop VM */
+
 /* Rule flags */
 #define AUDIT_FILTER_USER	0x00	/* Apply rule to user-generated messages */
 #define AUDIT_FILTER_TASK	0x01	/* Apply rule at task creation (not syscall) */
kernel/audit.c +2 -0
index 84590d1..5404c24 100644
@@ -941,6 +941,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 			}
 			audit_set_portid(ab, NETLINK_CB(skb).portid);
 			audit_log_end(ab);
+			if (msg_type == AUDIT_VIRT_CONTROL)
+				audit_log_ns_info(NULL);
 			mutex_lock(&audit_cmd_mutex);
 		}
 		break;
Signature · 1 line
1.7.1
#17 lore raw

PATCH v5 12/13 namespaces: expose ns instance serial numbers in proc

In reply to a message not in the archive

Expose the namespace instace serial numbers in the proc filesystem at /proc/<pid>/ns/<ns>_snum. The link text gives the serial number in hex.

"snum" was chosen instead of "seq" for consistency with inum and there are a number of other uses of "seq" in the namespace code.

---
 fs/proc/namespaces.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)
fs/proc/namespaces.c +25 -8
index 310da74..29c3909 100644
@@ -47,12 +47,15 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
 	struct inode *inode = dentry->d_inode;
 	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns.ns_ops;
 
-	return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
-		ns_ops->name, inode->i_ino);
+	if (strstr(dentry->d_iname, "_snum"))
+		return dynamic_dname(dentry, buffer, buflen, "%s_snum:[%llx]",
+			ns_ops->name, ns_ops->snum(PROC_I(inode)->ns.ns));
+	else
+		return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
+			ns_ops->name, inode->i_ino);
 }
 
-const struct dentry_operations ns_dentry_operations =
-{
+const struct dentry_operations ns_dentry_operations = {
 	.d_delete	= always_delete_dentry,
 	.d_dname	= ns_dname,
 };
@@ -160,7 +163,10 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl
 	if (!ns)
 		goto out_put_task;
 
-	snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
+	if (strstr(dentry->d_iname, "_snum"))
+		snprintf(name, sizeof(name), "%s_snum:[%llx]", ns_ops->name, ns_ops->snum(ns));
+	else
+		snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
 	res = readlink_copy(buffer, buflen, name);
 	ns_ops->put(ns);
 out_put_task:
@@ -210,16 +216,23 @@ static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
 
 	if (!dir_emit_dots(file, ctx))
 		goto out;
-	if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
+	if (ctx->pos >= 2 + 2 * ARRAY_SIZE(ns_entries))
 		goto out;
 	entry = ns_entries + (ctx->pos - 2);
 	last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
 	while (entry <= last) {
 		const struct proc_ns_operations *ops = *entry;
+		char name[50];
+
 		if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
 				     proc_ns_instantiate, task, ops))
 			break;
 		ctx->pos++;
+		snprintf(name, sizeof(name), "%s_snum", ops->name);
+		if (!proc_fill_cache(file, ctx, name, strlen(name),
+				     proc_ns_instantiate, task, ops))
+			break;
+		ctx->pos++;
 		entry++;
 	}
 out:
@@ -247,9 +260,13 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 
 	last = &ns_entries[ARRAY_SIZE(ns_entries)];
 	for (entry = ns_entries; entry < last; entry++) {
-		if (strlen((*entry)->name) != len)
+		char name[50];
+
+		snprintf(name, sizeof(name), "%s_snum", (*entry)->name);
+		if (strlen((*entry)->name) != len && strlen(name) != len)
 			continue;
-		if (!memcmp(dentry->d_name.name, (*entry)->name, len))
+		if (!memcmp(dentry->d_name.name, (*entry)->name, len)
+		    || !memcmp(dentry->d_name.name, name, len))
 			break;
 	}
 	if (entry == last)
Signature · 1 line
1.7.1
#18 lore raw

PATCH v5 13/13 Documentation: add a section for /proc/<pid>/ns/

In reply to a message not in the archive
---
 Documentation/filesystems/proc.txt |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
Documentation/filesystems/proc.txt +16 -0
index ddc531a..c4bfd6f 100644
@@ -42,6 +42,7 @@ Table of Contents
   3.6	/proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
   3.7   /proc/<pid>/task/<tid>/children - Information about task children
   3.8   /proc/<pid>/fdinfo/<fd> - Information about opened file
+  3.9   /proc/<pid>/ns/<ns>{,_snum} - Information about process namespaces
 
   4	Configuring procfs
   4.1	Mount options
@@ -1744,6 +1745,21 @@ pair provide additional information particular to the objects they represent.
 	optional and may be omitted if no marks created yet.
 
 
+3.9	/proc/<pid>/ns/<nstype>{,_snum} - Information about process namespaces
+--------------------------------------------------------------------------
+These files provides information about the namespaces within which the process
+is contained.  The files named only with the namespace type <nstype> contain a
+link that lists the containing namespace' inode number in its proc filesystem.
+The files with suffix _snum contain a link that lists the containing
+namespace' instance serial number, unique per kernel since boot.  The
+namespace types are self-describing.
+
+The output format of the inode links is:
+	<nstype>:[<inode_number>]
+The output format of the serial number links is:
+	<nstype>_snum:[<serial_number>]
+
+
 ------------------------------------------------------------------------------
 Configuring procfs
 ------------------------------------------------------------------------------
Signature · 1 line
1.7.1
#19 lore raw

PATCH v5 6/13 audit: log creation and deletion of namespace instances

In reply to Richard Guy Briggs

Log the creation and deletion of namespace instances in all 6 types of namespaces.

Twelve new audit message types have been introduced:

AUDIT_NS_INIT_MNT       1330    /* Record mount namespace instance creation */
AUDIT_NS_INIT_UTS       1331    /* Record UTS namespace instance creation */
AUDIT_NS_INIT_IPC       1332    /* Record IPC namespace instance creation */
AUDIT_NS_INIT_USER      1333    /* Record USER namespace instance creation */
AUDIT_NS_INIT_PID       1334    /* Record PID namespace instance creation */
AUDIT_NS_INIT_NET       1335    /* Record NET namespace instance creation */
AUDIT_NS_DEL_MNT        1336    /* Record mount namespace instance deletion */
AUDIT_NS_DEL_UTS        1337    /* Record UTS namespace instance deletion */
AUDIT_NS_DEL_IPC        1338    /* Record IPC namespace instance deletion */
AUDIT_NS_DEL_USER       1339    /* Record USER namespace instance deletion */
AUDIT_NS_DEL_PID        1340    /* Record PID namespace instance deletion */
AUDIT_NS_DEL_NET        1341    /* Record NET namespace instance deletion */

As suggested by Eric Paris, there are 12 message types, one for each of creation and deletion, one for each type of namespace so that text searches are easier in conjunction with the AUDIT_NS_INFO message type, being able to search for all records such as "netns=7 " and to avoid fields disappearing per message type to make ausearch more efficient.

A typical startup would look roughly like:

	type=AUDIT_NS_INIT_UTS msg=audit(1408577534.868:5): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_utsns=0 utsns=2 res=1
	type=AUDIT_NS_INIT_USER msg=audit(1408577534.868:6): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_userns=0 userns=3 res=1
	type=AUDIT_NS_INIT_PID msg=audit(1408577534.868:7): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_pidns=0 pidns=4 res=1
	type=AUDIT_NS_INIT_MNT msg=audit(1408577534.868:8): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_mntns=0 mntns=5 res=1
	type=AUDIT_NS_INIT_IPC msg=audit(1408577534.868:9): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_ipcns=0 ipcns=1 res=1
	type=AUDIT_NS_INIT_NET msg=audit(1408577533.500:10): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_netns=0 netns=7 res=1

And a CLONE action would result in:

	type=type=AUDIT_NS_INIT_NET msg=audit(1408577535.306:81): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 old_netns=7 netns=8 res=1
	type=type=AUDIT_NS_INIT_MNT msg=audit(1408577535.307:83): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 old_mntns=5 mntns=9 res=1

While deleting a namespace would result in:

	type=type=AUDIT_NS_DEL_MNT msg=audit(1408577552.221:85): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 mntns=9 res=1

If non-zero, old_snum lists the namespace from which it was cloned.

---
 fs/namespace.c             |   12 ++++++++++
 include/linux/audit.h      |    8 +++++++
 include/uapi/linux/audit.h |   12 ++++++++++
 ipc/namespace.c            |   10 +++++++++
 kernel/audit.c             |   49 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/pid_namespace.c     |   10 +++++++++
 kernel/user_namespace.c    |   11 +++++++++
 kernel/utsname.c           |   11 +++++++++
 net/core/net_namespace.c   |   12 ++++++++++
 9 files changed, 135 insertions(+), 0 deletions(-)
fs/namespace.c +12 -0
index f433f21..cb05b3d 100644
@@ -24,6 +24,7 @@
 #include <linux/proc_ns.h>
 #include <linux/magic.h>
 #include <linux/bootmem.h>
+#include <linux/audit.h>
 #include "pnode.h"
 #include "internal.h"
 
@@ -2459,6 +2460,7 @@ dput_out:
 
 static void free_mnt_ns(struct mnt_namespace *ns)
 {
+	audit_log_ns_del(AUDIT_NS_DEL_MNT, ns->serial_num);
 	proc_free_inum(ns->proc_inum);
 	put_user_ns(ns->user_ns);
 	kfree(ns);
@@ -2519,6 +2521,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
 	new_ns = alloc_mnt_ns(user_ns);
 	if (IS_ERR(new_ns))
 		return new_ns;
+	audit_log_ns_init(AUDIT_NS_INIT_MNT, ns->serial_num, new_ns->serial_num);
 
 	namespace_lock();
 	/* First pass: copy the tree topology */
@@ -2831,6 +2834,15 @@ static void __init init_mount_tree(void)
 	set_fs_root(current->fs, &root);
 }
 
+/* log the serial number of init mnt namespace after audit service starts */
+static int __init mnt_ns_init_log(void)
+{
+	struct mnt_namespace *init_mnt_ns = init_task.nsproxy->mnt_ns;
+	audit_log_ns_init(AUDIT_NS_INIT_MNT, 0, init_mnt_ns->serial_num);
+	return 0;
+}
+late_initcall(mnt_ns_init_log);
+
 void __init mnt_init(void)
 {
 	unsigned u;
include/linux/audit.h +8 -0
index 7cdebdc..1474334 100644
@@ -481,6 +481,9 @@ extern void		    audit_log_ns_info(struct task_struct *tsk);
 static inline void	    audit_log_ns_info(struct task_struct *tsk)
 { }
 #endif
+extern int		    audit_log_ns_init(int type, long long old_snum,
+					      long long snum);
+extern int		    audit_log_ns_del(int type, long long snum);
 
 extern int		    audit_update_lsm_rules(void);
 
@@ -539,6 +542,11 @@ static inline void audit_log_task_info(struct audit_buffer *ab,
 { }
 static inline void audit_log_ns_info(struct task_struct *tsk)
 { }
+static inline int audit_log_ns_init(int type, long long old_snum,
+				    long long snum)
+{ }
+static inline int audit_log_ns_del(int type, long long snum)
+{ }
 #define audit_enabled 0
 #endif /* CONFIG_AUDIT */
 static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
include/uapi/linux/audit.h +12 -0
index 760357e..1acfea7 100644
@@ -111,6 +111,18 @@
 #define AUDIT_PROCTITLE		1327	/* Proctitle emit event */
 #define AUDIT_FEATURE_CHANGE	1328	/* audit log listing feature changes */
 #define AUDIT_NS_INFO		1329	/* Record process namespace IDs */
+#define AUDIT_NS_INIT_MNT	1330	/* Record mount namespace instance creation */
+#define AUDIT_NS_INIT_UTS	1331	/* Record UTS namespace instance creation */
+#define AUDIT_NS_INIT_IPC	1332	/* Record IPC namespace instance creation */
+#define AUDIT_NS_INIT_USER	1333	/* Record USER namespace instance creation */
+#define AUDIT_NS_INIT_PID	1334	/* Record PID namespace instance creation */
+#define AUDIT_NS_INIT_NET	1335	/* Record NET namespace instance creation */
+#define AUDIT_NS_DEL_MNT	1336	/* Record mount namespace instance deletion */
+#define AUDIT_NS_DEL_UTS	1337	/* Record UTS namespace instance deletion */
+#define AUDIT_NS_DEL_IPC	1338	/* Record IPC namespace instance deletion */
+#define AUDIT_NS_DEL_USER	1339	/* Record USER namespace instance deletion */
+#define AUDIT_NS_DEL_PID	1340	/* Record PID namespace instance deletion */
+#define AUDIT_NS_DEL_NET	1341	/* Record NET namespace instance deletion */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
ipc/namespace.c +10 -0
index 36ce7ff..538c4b9 100644
@@ -13,6 +13,7 @@
 #include <linux/mount.h>
 #include <linux/user_namespace.h>
 #include <linux/proc_ns.h>
+#include <linux/audit.h>
 
 #include "util.h"
 
@@ -42,6 +43,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
 	atomic_inc(&nr_ipc_ns);
 
 	ns->serial_num = ns_serial();
+	audit_log_ns_init(AUDIT_NS_INIT_IPC, old_ns->serial_num, ns->serial_num);
 
 	sem_init_ns(ns);
 	msg_init_ns(ns);
@@ -121,6 +123,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
 	 */
 	ipcns_notify(IPCNS_REMOVED);
 	put_user_ns(ns->user_ns);
+	audit_log_ns_del(AUDIT_NS_DEL_IPC, ns->serial_num);
 	proc_free_inum(ns->proc_inum);
 	kfree(ns);
 }
@@ -207,3 +210,10 @@ const struct proc_ns_operations ipcns_operations = {
 	.inum		= ipcns_inum,
 	.snum		= ipcns_snum,
 };
+
+static int __init ipc_namespaces_init(void)
+{
+	return audit_log_ns_init(AUDIT_NS_INIT_IPC, 0, init_ipc_ns.serial_num);
+}
+
+late_initcall(ipc_namespaces_init);
kernel/audit.c +49 -0

55 lines not on this page · raw message

kernel/pid_namespace.c +10 -0
index 059b330..7da351a 100644
@@ -18,6 +18,7 @@
 #include <linux/proc_ns.h>
 #include <linux/reboot.h>
 #include <linux/export.h>
+#include <linux/audit.h>
 
 struct pid_cache {
 	int nr_ids;
@@ -110,6 +111,8 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
 		goto out_free_map;
 
 	ns->serial_num = ns_serial();
+	audit_log_ns_init(AUDIT_NS_INIT_PID, parent_pid_ns->serial_num,
+			  ns->serial_num);
 
 	kref_init(&ns->kref);
 	ns->level = level;
@@ -144,6 +147,7 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
 {
 	int i;
 
+	audit_log_ns_del(AUDIT_NS_DEL_PID, ns->serial_num);
 	proc_free_inum(ns->proc_inum);
 	for (i = 0; i < PIDMAP_ENTRIES; i++)
 		kfree(ns->pidmap[i].page);
@@ -397,3 +401,9 @@ static __init int pid_namespaces_init(void)
 }
 
 __initcall(pid_namespaces_init);
+
+static __init int pid_namespaces_late_init(void)
+{
+	return audit_log_ns_init(AUDIT_NS_INIT_PID, 0, init_pid_ns.serial_num);
+}
+late_initcall(pid_namespaces_late_init);
kernel/user_namespace.c +11 -0
index 3f04df5..24497a0 100644
@@ -22,6 +22,7 @@
 #include <linux/ctype.h>
 #include <linux/projid.h>
 #include <linux/fs_struct.h>
+#include <linux/audit.h>
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 
@@ -93,6 +94,8 @@ int create_user_ns(struct cred *new)
 	}
 
 	ns->serial_num = ns_serial();
+	audit_log_ns_init(AUDIT_NS_INIT_USER, parent_ns->serial_num,
+			  ns->serial_num);
 
 	atomic_set(&ns->count, 1);
 	/* Leave the new->user_ns reference with the new user namespace. */
@@ -138,6 +141,7 @@ void free_user_ns(struct user_namespace *ns)
 #ifdef CONFIG_PERSISTENT_KEYRINGS
 		key_put(ns->persistent_keyring_register);
 #endif
+		audit_log_ns_del(AUDIT_NS_DEL_USER, ns->serial_num);
 		proc_free_inum(ns->proc_inum);
 		kmem_cache_free(user_ns_cachep, ns);
 		ns = parent;
@@ -918,3 +922,10 @@ static __init int user_namespaces_init(void)
 	return 0;
 }
 subsys_initcall(user_namespaces_init);
+
+static __init int user_namespaces_late_init(void)
+{
+	return audit_log_ns_init(AUDIT_NS_INIT_USER, 0,
+				 init_user_ns.serial_num);
+}
+late_initcall(user_namespaces_late_init);
kernel/utsname.c +11 -0
index ffeac1b..05ecc2d 100644
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/user_namespace.h>
 #include <linux/proc_ns.h>
+#include <linux/audit.h>
 
 static struct uts_namespace *create_uts_ns(void)
 {
@@ -49,6 +50,7 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
 	}
 
 	ns->serial_num = ns_serial();
+	audit_log_ns_init(AUDIT_NS_INIT_UTS, old_ns->serial_num, ns->serial_num);
 
 	down_read(&uts_sem);
 	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
@@ -86,6 +88,7 @@ void free_uts_ns(struct kref *kref)
 
 	ns = container_of(kref, struct uts_namespace, kref);
 	put_user_ns(ns->user_ns);
+	audit_log_ns_del(AUDIT_NS_DEL_UTS, ns->serial_num);
 	proc_free_inum(ns->proc_inum);
 	kfree(ns);
 }
@@ -148,3 +151,11 @@ const struct proc_ns_operations utsns_operations = {
 	.inum		= utsns_inum,
 	.snum		= utsns_snum,
 };
+
+static int __init uts_namespaces_init(void)
+{
+	return audit_log_ns_init(AUDIT_NS_INIT_UTS, 0,
+				 init_uts_ns.serial_num);
+}
+
+late_initcall(uts_namespaces_init);
net/core/net_namespace.c +12 -0
index c402eea..295ecc3 100644
@@ -17,6 +17,7 @@
 #include <linux/user_namespace.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
+#include <linux/audit.h>
 
 /*
  *	Our network namespace constructor/destructor lists
@@ -253,6 +254,8 @@ struct net *copy_net_ns(unsigned long flags,
 	mutex_lock(&net_mutex);
 	rv = setup_net(net, user_ns);
 	if (rv == 0) {
+		audit_log_ns_init(AUDIT_NS_INIT_NET, old_net->serial_num,
+				  net->serial_num);
 		rtnl_lock();
 		list_add_tail_rcu(&net->list, &net_namespace_list);
 		rtnl_unlock();
@@ -395,6 +398,7 @@ static __net_init int net_ns_net_init(struct net *net)
 
 static __net_exit void net_ns_net_exit(struct net *net)
 {
+	audit_log_ns_del(AUDIT_NS_DEL_NET, net->serial_num);
 	proc_free_inum(net->proc_inum);
 }
 
@@ -441,6 +445,14 @@ static int __init net_ns_init(void)
 
 pure_initcall(net_ns_init);
 
+/* log the serial number of init_net namespace after audit service starts */
+static int __init net_ns_init_log(void)
+{
+	audit_log_ns_init(AUDIT_NS_INIT_NET, 0, init_net.serial_num);
+	return 0;
+}
+late_initcall(net_ns_init_log);
+
 #ifdef CONFIG_NET_NS
 static int __register_pernet_operations(struct list_head *list,
 					struct pernet_operations *ops)
Signature · 1 line
1.7.1
maintainer Acked-by Serge Hallyn on v5 6/13
#20 lore raw

Re: [PATCH V5 06/13] audit: log creation and deletion of namespace instances

Quoted 36 lines · Richard Guy Briggs

Log the creation and deletion of namespace instances in all 6 types of namespaces.

Twelve new audit message types have been introduced:

AUDIT_NS_INIT_MNT       1330    /* Record mount namespace instance creation */
AUDIT_NS_INIT_UTS       1331    /* Record UTS namespace instance creation */
AUDIT_NS_INIT_IPC       1332    /* Record IPC namespace instance creation */
AUDIT_NS_INIT_USER      1333    /* Record USER namespace instance creation */
AUDIT_NS_INIT_PID       1334    /* Record PID namespace instance creation */
AUDIT_NS_INIT_NET       1335    /* Record NET namespace instance creation */
AUDIT_NS_DEL_MNT        1336    /* Record mount namespace instance deletion */
AUDIT_NS_DEL_UTS        1337    /* Record UTS namespace instance deletion */
AUDIT_NS_DEL_IPC        1338    /* Record IPC namespace instance deletion */
AUDIT_NS_DEL_USER       1339    /* Record USER namespace instance deletion */
AUDIT_NS_DEL_PID        1340    /* Record PID namespace instance deletion */
AUDIT_NS_DEL_NET        1341    /* Record NET namespace instance deletion */

As suggested by Eric Paris, there are 12 message types, one for each of creation and deletion, one for each type of namespace so that text searches are easier in conjunction with the AUDIT_NS_INFO message type, being able to search for all records such as "netns=7 " and to avoid fields disappearing per message type to make ausearch more efficient.

A typical startup would look roughly like:

	type=AUDIT_NS_INIT_UTS msg=audit(1408577534.868:5): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_utsns=0 utsns=2 res=1
	type=AUDIT_NS_INIT_USER msg=audit(1408577534.868:6): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_userns=0 userns=3 res=1
	type=AUDIT_NS_INIT_PID msg=audit(1408577534.868:7): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_pidns=0 pidns=4 res=1
	type=AUDIT_NS_INIT_MNT msg=audit(1408577534.868:8): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_mntns=0 mntns=5 res=1
	type=AUDIT_NS_INIT_IPC msg=audit(1408577534.868:9): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_ipcns=0 ipcns=1 res=1
	type=AUDIT_NS_INIT_NET msg=audit(1408577533.500:10): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel old_netns=0 netns=7 res=1

And a CLONE action would result in:

	type=type=AUDIT_NS_INIT_NET msg=audit(1408577535.306:81): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 old_netns=7 netns=8 res=1
	type=type=AUDIT_NS_INIT_MNT msg=audit(1408577535.307:83): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 old_mntns=5 mntns=9 res=1
Quoted 6 lines

While deleting a namespace would result in:

	type=type=AUDIT_NS_DEL_MNT msg=audit(1408577552.221:85): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 mntns=9 res=1

If non-zero, old_snum lists the namespace from which it was cloned.

Two suggestions below though

Quoted 150 lines
---
 fs/namespace.c             |   12 ++++++++++
 include/linux/audit.h      |    8 +++++++
 include/uapi/linux/audit.h |   12 ++++++++++
 ipc/namespace.c            |   10 +++++++++
 kernel/audit.c             |   49 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/pid_namespace.c     |   10 +++++++++
 kernel/user_namespace.c    |   11 +++++++++
 kernel/utsname.c           |   11 +++++++++
 net/core/net_namespace.c   |   12 ++++++++++
 9 files changed, 135 insertions(+), 0 deletions(-)
fs/namespace.c +12 -0
index f433f21..cb05b3d 100644
@@ -24,6 +24,7 @@
 #include <linux/proc_ns.h>
 #include <linux/magic.h>
 #include <linux/bootmem.h>
+#include <linux/audit.h>
 #include "pnode.h"
 #include "internal.h"
 
@@ -2459,6 +2460,7 @@ dput_out:
 
 static void free_mnt_ns(struct mnt_namespace *ns)
 {
+	audit_log_ns_del(AUDIT_NS_DEL_MNT, ns->serial_num);
 	proc_free_inum(ns->proc_inum);
 	put_user_ns(ns->user_ns);
 	kfree(ns);
@@ -2519,6 +2521,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
 	new_ns = alloc_mnt_ns(user_ns);
 	if (IS_ERR(new_ns))
 		return new_ns;
+	audit_log_ns_init(AUDIT_NS_INIT_MNT, ns->serial_num, new_ns->serial_num);
 
 	namespace_lock();
 	/* First pass: copy the tree topology */
@@ -2831,6 +2834,15 @@ static void __init init_mount_tree(void)
 	set_fs_root(current->fs, &root);
 }
 
+/* log the serial number of init mnt namespace after audit service starts */
+static int __init mnt_ns_init_log(void)
+{
+	struct mnt_namespace *init_mnt_ns = init_task.nsproxy->mnt_ns;
+	audit_log_ns_init(AUDIT_NS_INIT_MNT, 0, init_mnt_ns->serial_num);
+	return 0;
+}
+late_initcall(mnt_ns_init_log);
+
 void __init mnt_init(void)
 {
 	unsigned u;
include/linux/audit.h +8 -0
index 7cdebdc..1474334 100644
@@ -481,6 +481,9 @@ extern void		    audit_log_ns_info(struct task_struct *tsk);
 static inline void	    audit_log_ns_info(struct task_struct *tsk)
 { }
 #endif
+extern int		    audit_log_ns_init(int type, long long old_snum,
+					      long long snum);
+extern int		    audit_log_ns_del(int type, long long snum);
 
 extern int		    audit_update_lsm_rules(void);
 
@@ -539,6 +542,11 @@ static inline void audit_log_task_info(struct audit_buffer *ab,
 { }
 static inline void audit_log_ns_info(struct task_struct *tsk)
 { }
+static inline int audit_log_ns_init(int type, long long old_snum,
+				    long long snum)
+{ }
+static inline int audit_log_ns_del(int type, long long snum)
+{ }
 #define audit_enabled 0
 #endif /* CONFIG_AUDIT */
 static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
include/uapi/linux/audit.h +12 -0
index 760357e..1acfea7 100644
@@ -111,6 +111,18 @@
 #define AUDIT_PROCTITLE		1327	/* Proctitle emit event */
 #define AUDIT_FEATURE_CHANGE	1328	/* audit log listing feature changes */
 #define AUDIT_NS_INFO		1329	/* Record process namespace IDs */
+#define AUDIT_NS_INIT_MNT	1330	/* Record mount namespace instance creation */
+#define AUDIT_NS_INIT_UTS	1331	/* Record UTS namespace instance creation */
+#define AUDIT_NS_INIT_IPC	1332	/* Record IPC namespace instance creation */
+#define AUDIT_NS_INIT_USER	1333	/* Record USER namespace instance creation */
+#define AUDIT_NS_INIT_PID	1334	/* Record PID namespace instance creation */
+#define AUDIT_NS_INIT_NET	1335	/* Record NET namespace instance creation */
+#define AUDIT_NS_DEL_MNT	1336	/* Record mount namespace instance deletion */
+#define AUDIT_NS_DEL_UTS	1337	/* Record UTS namespace instance deletion */
+#define AUDIT_NS_DEL_IPC	1338	/* Record IPC namespace instance deletion */
+#define AUDIT_NS_DEL_USER	1339	/* Record USER namespace instance deletion */
+#define AUDIT_NS_DEL_PID	1340	/* Record PID namespace instance deletion */
+#define AUDIT_NS_DEL_NET	1341	/* Record NET namespace instance deletion */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
ipc/namespace.c +10 -0
index 36ce7ff..538c4b9 100644
@@ -13,6 +13,7 @@
 #include <linux/mount.h>
 #include <linux/user_namespace.h>
 #include <linux/proc_ns.h>
+#include <linux/audit.h>
 
 #include "util.h"
 
@@ -42,6 +43,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
 	atomic_inc(&nr_ipc_ns);
 
 	ns->serial_num = ns_serial();
+	audit_log_ns_init(AUDIT_NS_INIT_IPC, old_ns->serial_num, ns->serial_num);
 
 	sem_init_ns(ns);
 	msg_init_ns(ns);
@@ -121,6 +123,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
 	 */
 	ipcns_notify(IPCNS_REMOVED);
 	put_user_ns(ns->user_ns);
+	audit_log_ns_del(AUDIT_NS_DEL_IPC, ns->serial_num);
 	proc_free_inum(ns->proc_inum);
 	kfree(ns);
 }
@@ -207,3 +210,10 @@ const struct proc_ns_operations ipcns_operations = {
 	.inum		= ipcns_inum,
 	.snum		= ipcns_snum,
 };
+
+static int __init ipc_namespaces_init(void)
+{
+	return audit_log_ns_init(AUDIT_NS_INIT_IPC, 0, init_ipc_ns.serial_num);
+}
+
+late_initcall(ipc_namespaces_init);
kernel/audit.c +0 -0
index 8ff7f28..a17a09f 100644
@@ -1960,6 +1960,55 @@ out:
 	kfree(name);

kernel/audit.c out: · line 1970

Quoted 10 lines
kernel/audit.c +8 -0
 }
 
+#ifdef CONFIG_NAMESPACES
+static char* ns_name[] = {
+	"mnt",
+	"uts",
+	"ipc",
+	"user",
+	"pid",
+	"net",

Comment here that the order corresponds to the AUDIT_NS_INIT_MNT.. #defines order, and maybe even move this next to those.

Quoted 4 lines
kernel/audit.c +4 -0
+};
+
+/**
+ * audit_log_ns_init - report a namespace instance creation

kernel/audit.c out: · line 1984

Quoted 10 lines
kernel/audit.c +10 -0
+ * @type: type of audit namespace instance created message
+ * @old_snum: the serial number of the cloned namespace instance
+ * @snum: the serial number of the new namespace instance
+ */
+int audit_log_ns_init(int type, long long old_snum, long long snum)
+{
+	struct audit_buffer *ab;
+	char* audit_ns_name = ns_name[type - AUDIT_NS_INIT_MNT];
+
+	if (type < AUDIT_NS_INIT_MNT || type > AUDIT_NS_INIT_NET)

probably worth defining an AUDIT_NS_INIT_FIRST and AUDIT_NS_INIT_LAST in audit.h which can be updated at the source defines.

Quoted 195 lines
kernel/audit.c +27 -0
+		return 0;
+	audit_log_common_recv_msg(&ab, type);
+	audit_log_format(ab, " old_%sns=%llx %sns=%llx res=1",
+			 audit_ns_name, old_snum, audit_ns_name, snum);
+	audit_log_end(ab);
+	return 0;
+}
+
+/**
+ * audit_log_ns_del - report a namespace instance deleted
+ * @type: type of audit namespace instance deleted message
+ * @snum: the serial number of the namespace instance
+ */
+int audit_log_ns_del(int type, long long snum)
+{
+	struct audit_buffer *ab;
+	char* audit_ns_name = ns_name[type - AUDIT_NS_DEL_MNT];
+
+	if (type < AUDIT_NS_DEL_MNT || type > AUDIT_NS_DEL_NET)
+		return 0;
+	audit_log_common_recv_msg(&ab, type);
+	audit_log_format(ab, " %ssn=%llx res=1", audit_ns_name, snum);
+	audit_log_end(ab);
+	return 0;
+}
+#endif /* CONFIG_NAMESPACES */
+
 /**
  * audit_log_end - end one audit record
  * @ab: the audit_buffer
kernel/pid_namespace.c +10 -0
index 059b330..7da351a 100644
@@ -18,6 +18,7 @@
 #include <linux/proc_ns.h>
 #include <linux/reboot.h>
 #include <linux/export.h>
+#include <linux/audit.h>
 
 struct pid_cache {
 	int nr_ids;
@@ -110,6 +111,8 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
 		goto out_free_map;
 
 	ns->serial_num = ns_serial();
+	audit_log_ns_init(AUDIT_NS_INIT_PID, parent_pid_ns->serial_num,
+			  ns->serial_num);
 
 	kref_init(&ns->kref);
 	ns->level = level;
@@ -144,6 +147,7 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
 {
 	int i;
 
+	audit_log_ns_del(AUDIT_NS_DEL_PID, ns->serial_num);
 	proc_free_inum(ns->proc_inum);
 	for (i = 0; i < PIDMAP_ENTRIES; i++)
 		kfree(ns->pidmap[i].page);
@@ -397,3 +401,9 @@ static __init int pid_namespaces_init(void)
 }
 
 __initcall(pid_namespaces_init);
+
+static __init int pid_namespaces_late_init(void)
+{
+	return audit_log_ns_init(AUDIT_NS_INIT_PID, 0, init_pid_ns.serial_num);
+}
+late_initcall(pid_namespaces_late_init);
kernel/user_namespace.c +11 -0
index 3f04df5..24497a0 100644
@@ -22,6 +22,7 @@
 #include <linux/ctype.h>
 #include <linux/projid.h>
 #include <linux/fs_struct.h>
+#include <linux/audit.h>
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 
@@ -93,6 +94,8 @@ int create_user_ns(struct cred *new)
 	}
 
 	ns->serial_num = ns_serial();
+	audit_log_ns_init(AUDIT_NS_INIT_USER, parent_ns->serial_num,
+			  ns->serial_num);
 
 	atomic_set(&ns->count, 1);
 	/* Leave the new->user_ns reference with the new user namespace. */
@@ -138,6 +141,7 @@ void free_user_ns(struct user_namespace *ns)
 #ifdef CONFIG_PERSISTENT_KEYRINGS
 		key_put(ns->persistent_keyring_register);
 #endif
+		audit_log_ns_del(AUDIT_NS_DEL_USER, ns->serial_num);
 		proc_free_inum(ns->proc_inum);
 		kmem_cache_free(user_ns_cachep, ns);
 		ns = parent;
@@ -918,3 +922,10 @@ static __init int user_namespaces_init(void)
 	return 0;
 }
 subsys_initcall(user_namespaces_init);
+
+static __init int user_namespaces_late_init(void)
+{
+	return audit_log_ns_init(AUDIT_NS_INIT_USER, 0,
+				 init_user_ns.serial_num);
+}
+late_initcall(user_namespaces_late_init);
kernel/utsname.c +11 -0
index ffeac1b..05ecc2d 100644
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/user_namespace.h>
 #include <linux/proc_ns.h>
+#include <linux/audit.h>
 
 static struct uts_namespace *create_uts_ns(void)
 {
@@ -49,6 +50,7 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
 	}
 
 	ns->serial_num = ns_serial();
+	audit_log_ns_init(AUDIT_NS_INIT_UTS, old_ns->serial_num, ns->serial_num);
 
 	down_read(&uts_sem);
 	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
@@ -86,6 +88,7 @@ void free_uts_ns(struct kref *kref)
 
 	ns = container_of(kref, struct uts_namespace, kref);
 	put_user_ns(ns->user_ns);
+	audit_log_ns_del(AUDIT_NS_DEL_UTS, ns->serial_num);
 	proc_free_inum(ns->proc_inum);
 	kfree(ns);
 }
@@ -148,3 +151,11 @@ const struct proc_ns_operations utsns_operations = {
 	.inum		= utsns_inum,
 	.snum		= utsns_snum,
 };
+
+static int __init uts_namespaces_init(void)
+{
+	return audit_log_ns_init(AUDIT_NS_INIT_UTS, 0,
+				 init_uts_ns.serial_num);
+}
+
+late_initcall(uts_namespaces_init);
net/core/net_namespace.c +12 -0
index c402eea..295ecc3 100644
@@ -17,6 +17,7 @@
 #include <linux/user_namespace.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
+#include <linux/audit.h>
 
 /*
  *	Our network namespace constructor/destructor lists
@@ -253,6 +254,8 @@ struct net *copy_net_ns(unsigned long flags,
 	mutex_lock(&net_mutex);
 	rv = setup_net(net, user_ns);
 	if (rv == 0) {
+		audit_log_ns_init(AUDIT_NS_INIT_NET, old_net->serial_num,
+				  net->serial_num);
 		rtnl_lock();
 		list_add_tail_rcu(&net->list, &net_namespace_list);
 		rtnl_unlock();
@@ -395,6 +398,7 @@ static __net_init int net_ns_net_init(struct net *net)
 
 static __net_exit void net_ns_net_exit(struct net *net)
 {
+	audit_log_ns_del(AUDIT_NS_DEL_NET, net->serial_num);
 	proc_free_inum(net->proc_inum);
 }
 
@@ -441,6 +445,14 @@ static int __init net_ns_init(void)
 
 pure_initcall(net_ns_init);
 
+/* log the serial number of init_net namespace after audit service starts */
+static int __init net_ns_init_log(void)
+{
+	audit_log_ns_init(AUDIT_NS_INIT_NET, 0, init_net.serial_num);
+	return 0;
+}
+late_initcall(net_ns_init_log);
+
 #ifdef CONFIG_NET_NS
 static int __register_pernet_operations(struct list_head *list,
 					struct pernet_operations *ops)
Signature · 1 line
1.7.1
#21 lore raw

PATCH v5 7/13 audit: dump namespace IDs for pid on receipt of AUDIT_NS_INFO

In reply to Richard Guy Briggs

When a task with CAP_AUDIT_CONTROL sends a NETLINK_AUDIT message of type AUDIT_NS_INFO with a PID of interest, dump the namespace IDs of that task to the audit log.

---
 kernel/audit.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
kernel/audit.c +14 -0
index a17a09f..cc63445 100644
@@ -671,6 +671,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
 	case AUDIT_TTY_SET:
 	case AUDIT_TRIM:
 	case AUDIT_MAKE_EQUIV:
+	case AUDIT_NS_INFO:
 		/* Only support auditd and auditctl in initial pid namespace
 		 * for now. */
 		if ((task_active_pid_ns(current) != &init_pid_ns))
@@ -1068,6 +1069,19 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		audit_log_end(ab);
 		break;
 	}
+	case AUDIT_NS_INFO:
+#ifdef CONFIG_NAMESPACES
+	{
+		struct task_struct *tsk;
+
+		rcu_read_lock();
+		tsk = find_task_by_vpid(*(pid_t *)data);
+		rcu_read_unlock();
+		audit_log_ns_info(tsk);
+	}
+#else /* CONFIG_NAMESPACES */
+		err = -EOPNOTSUPP;
+#endif /* CONFIG_NAMESPACES */
 	default:
 		err = -EINVAL;
 		break;
Signature · 1 line
1.7.1
maintainer Acked-by Serge Hallyn on v5 7/13
#22 lore raw

Re: [PATCH V5 07/13] audit: dump namespace IDs for pid on receipt of AUDIT_NS_INFO

Quoted 4 lines · Richard Guy Briggs

When a task with CAP_AUDIT_CONTROL sends a NETLINK_AUDIT message of type AUDIT_NS_INFO with a PID of interest, dump the namespace IDs of that task to the audit log.
---

Quoted 37 lines
 kernel/audit.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
kernel/audit.c +14 -0
index a17a09f..cc63445 100644
@@ -671,6 +671,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
 	case AUDIT_TTY_SET:
 	case AUDIT_TRIM:
 	case AUDIT_MAKE_EQUIV:
+	case AUDIT_NS_INFO:
 		/* Only support auditd and auditctl in initial pid namespace
 		 * for now. */
 		if ((task_active_pid_ns(current) != &init_pid_ns))
@@ -1068,6 +1069,19 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		audit_log_end(ab);
 		break;
 	}
+	case AUDIT_NS_INFO:
+#ifdef CONFIG_NAMESPACES
+	{
+		struct task_struct *tsk;
+
+		rcu_read_lock();
+		tsk = find_task_by_vpid(*(pid_t *)data);
+		rcu_read_unlock();
+		audit_log_ns_info(tsk);
+	}
+#else /* CONFIG_NAMESPACES */
+		err = -EOPNOTSUPP;
+#endif /* CONFIG_NAMESPACES */
 	default:
 		err = -EINVAL;
 		break;
Signature · 1 line
1.7.1
#23 lore raw

PATCH v5 8/13 sched: add a macro to ref all CLONE_NEW* flags

In reply to Richard Guy Briggs
---
 include/uapi/linux/sched.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
include/uapi/linux/sched.h +6 -0
index 34f9d73..5aceba2 100644
@@ -28,6 +28,12 @@
 #define CLONE_NEWUSER		0x10000000	/* New user namespace */
 #define CLONE_NEWPID		0x20000000	/* New pid namespace */
 #define CLONE_NEWNET		0x40000000	/* New network namespace */
+#define CLONE_NEW_MASK	( CLONE_NEWNS \
+			| CLONE_NEWUTS \
+			| CLONE_NEWIPC \
+			| CLONE_NEWUSER \
+			| CLONE_NEWPID \
+			| CLONE_NEWNET)	/* mask of all namespace type flags */
 #define CLONE_IO		0x80000000	/* Clone io context */
 
 /*
Signature · 1 line
1.7.1
#24 lore raw

RE: [PATCH V5 08/13] sched: add a macro to ref all CLONE_NEW* flags

Quoted 23 lines

-----Original Message-----
From: containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org [mailto:containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org] On Behalf Of Richard Guy
Briggs
Sent: Monday, October 06, 2014 1:09 PM
To: [email protected]; [email protected]; containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc: [email protected]; [email protected]; [email protected]; [email protected]; ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Subject: [PATCH V5 08/13] sched: add a macro to ref all CLONE_NEW* flags

---
 include/uapi/linux/sched.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
include/uapi/linux/sched.h +0 -0
index 34f9d73..5aceba2 100644
@@ -28,6 +28,12 @@
 #define CLONE_NEWUSER		0x10000000	/* New user namespace */

include/uapi/linux/sched.h line 38

Quoted 10 lines
include/uapi/linux/sched.h +6 -0
 #define CLONE_NEWPID		0x20000000	/* New pid namespace */
 #define CLONE_NEWNET		0x40000000	/* New network namespace */
+#define CLONE_NEW_MASK	( CLONE_NEWNS \
+			| CLONE_NEWUTS \
+			| CLONE_NEWIPC \
+			| CLONE_NEWUSER \
+			| CLONE_NEWPID \
+			| CLONE_NEWNET)	/* mask of all namespace type flags */
 #define CLONE_IO		0x80000000	/* Clone io context */
 

The name 'CLONE_NEW_MASK' may confuse readers.
How about something like CLONE_NEW_MASK_ALL?

Thanks,
- Chen

#25 lore raw

Re: [PATCH V5 08/13] sched: add a macro to ref all CLONE_NEW* flags

Quoted 27 lines · Hanxiao
Quoted 27 lines

-----Original Message-----
From: containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org [mailto:containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org] On Behalf Of Richard Guy
Briggs
Sent: Monday, October 06, 2014 1:09 PM
To: [email protected]; [email protected]; containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc: [email protected]; [email protected]; [email protected]; [email protected]; ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Subject: [PATCH V5 08/13] sched: add a macro to ref all CLONE_NEW* flags

---
 include/uapi/linux/sched.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
include/uapi/linux/sched.h +2 -0
index 34f9d73..5aceba2 100644
@@ -28,6 +28,12 @@
 #define CLONE_NEWUSER		0x10000000	/* New user namespace */
 #define CLONE_NEWPID		0x20000000	/* New pid namespace */
 #define CLONE_NEWNET		0x40000000	/* New network namespace */
+#define CLONE_NEW_MASK	( CLONE_NEWNS \
+			| CLONE_NEWUTS \
Quoted 8 lines

include/uapi/linux/sched.h line 37

Quoted 5 lines
include/uapi/linux/sched.h +4 -0
+			| CLONE_NEWIPC \
+			| CLONE_NEWUSER \
+			| CLONE_NEWPID \
+			| CLONE_NEWNET)	/* mask of all namespace type flags */
 #define CLONE_IO		0x80000000	/* Clone io context */

The name 'CLONE_NEW_MASK' may confuse readers.
How about something like CLONE_NEW_MASK_ALL?

Fair enough. Changed.

Quoted 2 lines

Thanks,
- Chen

- RGB

--
Richard Guy Briggs <[email protected]> Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

maintainer Acked-by Serge Hallyn on v5 8/13
#26 lore raw

Re: [PATCH V5 08/13] sched: add a macro to ref all CLONE_NEW* flags

In reply to Richard Guy Briggs
Quoted 1 line · Richard Guy Briggs

---

Quoted 22 lines
 include/uapi/linux/sched.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
include/uapi/linux/sched.h +6 -0
index 34f9d73..5aceba2 100644
@@ -28,6 +28,12 @@
 #define CLONE_NEWUSER		0x10000000	/* New user namespace */
 #define CLONE_NEWPID		0x20000000	/* New pid namespace */
 #define CLONE_NEWNET		0x40000000	/* New network namespace */
+#define CLONE_NEW_MASK	( CLONE_NEWNS \
+			| CLONE_NEWUTS \
+			| CLONE_NEWIPC \
+			| CLONE_NEWUSER \
+			| CLONE_NEWPID \
+			| CLONE_NEWNET)	/* mask of all namespace type flags */
 #define CLONE_IO		0x80000000	/* Clone io context */
 
 /*
Signature · 1 line
1.7.1
#27 lore raw

PATCH v5 9/13 fork: audit on creation of new namespace(s)

In reply to Richard Guy Briggs

When clone(2) is called to fork a new process creating one or more namespaces, audit the event to tie the new pid with the namespace IDs.

Signed-off-by Richard Guy Briggs
---
 kernel/fork.c    |    3 +++
 kernel/nsproxy.c |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
kernel/fork.c +3 -0
index 6a13c46..a7fe4d5 100644
@@ -1624,6 +1624,9 @@ long do_fork(unsigned long clone_flags,
 			get_task_struct(p);
 		}
 
+		if (unlikely(clone_flags & CLONE_NEW_MASK)) {
+			audit_log_ns_info(p);
+		}
 		wake_up_new_task(p);
 
 		/* forking complete and child started to run, tell ptracer */
kernel/nsproxy.c +1 -0
index 0c2f25e..2cdc16b 100644
@@ -25,6 +25,7 @@
 #include <linux/proc_ns.h>
 #include <linux/file.h>
 #include <linux/syscalls.h>
+#include <linux/audit.h>
 
 static struct kmem_cache *nsproxy_cachep;
 
Signature · 1 line
1.7.1
maintainer Acked-by Serge Hallyn on v5 9/13
#28 lore raw

Re: [PATCH V5 09/13] fork: audit on creation of new namespace(s)

Quoted 4 lines · Richard Guy Briggs

When clone(2) is called to fork a new process creating one or more namespaces, audit the event to tie the new pid with the namespace IDs.

Signed-off-by Richard Guy Briggs
Quoted 33 lines
---
 kernel/fork.c    |    3 +++
 kernel/nsproxy.c |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
kernel/fork.c +3 -0
index 6a13c46..a7fe4d5 100644
@@ -1624,6 +1624,9 @@ long do_fork(unsigned long clone_flags,
 			get_task_struct(p);
 		}
 
+		if (unlikely(clone_flags & CLONE_NEW_MASK)) {
+			audit_log_ns_info(p);
+		}
 		wake_up_new_task(p);
 
 		/* forking complete and child started to run, tell ptracer */
kernel/nsproxy.c +1 -0
index 0c2f25e..2cdc16b 100644
@@ -25,6 +25,7 @@
 #include <linux/proc_ns.h>
 #include <linux/file.h>
 #include <linux/syscalls.h>
+#include <linux/audit.h>
 
 static struct kmem_cache *nsproxy_cachep;
 
Signature · 1 line
1.7.1
#29 lore raw

PATCH v5 10/13 audit: log on switching namespace (setns)

In reply to Richard Guy Briggs

Added six new audit message types, AUDIT_NS_SET_* and function audit_log_ns_set() to log a switch of namespace.

---
 include/linux/audit.h      |    4 +++
 include/uapi/linux/audit.h |    6 +++++
 kernel/audit.c             |   46 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/nsproxy.c           |    3 ++
 4 files changed, 59 insertions(+), 0 deletions(-)
include/linux/audit.h +4 -0
index 1474334..9de9b25 100644
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <uapi/linux/audit.h>
+#include <linux/proc_ns.h>
 
 struct audit_sig_info {
 	uid_t		uid;
@@ -484,6 +485,7 @@ static inline void	    audit_log_ns_info(struct task_struct *tsk)
 extern int		    audit_log_ns_init(int type, long long old_snum,
 					      long long snum);
 extern int		    audit_log_ns_del(int type, long long snum);
+extern void		    audit_log_ns_set(const struct proc_ns_operations *ops, void *ns);
 
 extern int		    audit_update_lsm_rules(void);
 
@@ -547,6 +549,8 @@ static inline int audit_log_ns_init(int type, long long old_snum,
 { }
 static inline int audit_log_ns_del(int type, long long snum)
 { }
+static inline void audit_log_ns_set(const struct proc_ns_operations *ops, void *ns)
+{ }
 #define audit_enabled 0
 #endif /* CONFIG_AUDIT */
 static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
include/uapi/linux/audit.h +6 -0
index 1acfea7..7ec7209 100644
@@ -123,6 +123,12 @@
 #define AUDIT_NS_DEL_USER	1339	/* Record USER namespace instance deletion */
 #define AUDIT_NS_DEL_PID	1340	/* Record PID namespace instance deletion */
 #define AUDIT_NS_DEL_NET	1341	/* Record NET namespace instance deletion */
+#define AUDIT_NS_SET_MNT	1342	/* Record mount namespace instance deletion */
+#define AUDIT_NS_SET_UTS	1343	/* Record UTS namespace instance deletion */
+#define AUDIT_NS_SET_IPC	1344	/* Record IPC namespace instance deletion */
+#define AUDIT_NS_SET_USER	1345	/* Record USER namespace instance deletion */
+#define AUDIT_NS_SET_PID	1346	/* Record PID namespace instance deletion */
+#define AUDIT_NS_SET_NET	1347	/* Record NET namespace instance deletion */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
kernel/audit.c +46 -0

52 lines not on this page · raw message

kernel/nsproxy.c +3 -0
index 2cdc16b..e37409a 100644
@@ -275,6 +275,9 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
 		goto out;
 	}
 	switch_task_namespaces(tsk, new_nsproxy);
+
+	audit_log_ns_set(ops, ei->ns);
+
 out:
 	fput(file);
 	return err;
Signature · 1 line
1.7.1
maintainer
#30 lore raw

Re: [PATCH V5 10/13] audit: log on switching namespace (setns)

Quoted 91 lines · Richard Guy Briggs

Added six new audit message types, AUDIT_NS_SET_* and function audit_log_ns_set() to log a switch of namespace.

---
 include/linux/audit.h      |    4 +++
 include/uapi/linux/audit.h |    6 +++++
 kernel/audit.c             |   46 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/nsproxy.c           |    3 ++
 4 files changed, 59 insertions(+), 0 deletions(-)
include/linux/audit.h +4 -0
index 1474334..9de9b25 100644
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <uapi/linux/audit.h>
+#include <linux/proc_ns.h>
 
 struct audit_sig_info {
 	uid_t		uid;
@@ -484,6 +485,7 @@ static inline void	    audit_log_ns_info(struct task_struct *tsk)
 extern int		    audit_log_ns_init(int type, long long old_snum,
 					      long long snum);
 extern int		    audit_log_ns_del(int type, long long snum);
+extern void		    audit_log_ns_set(const struct proc_ns_operations *ops, void *ns);
 
 extern int		    audit_update_lsm_rules(void);
 
@@ -547,6 +549,8 @@ static inline int audit_log_ns_init(int type, long long old_snum,
 { }
 static inline int audit_log_ns_del(int type, long long snum)
 { }
+static inline void audit_log_ns_set(const struct proc_ns_operations *ops, void *ns)
+{ }
 #define audit_enabled 0
 #endif /* CONFIG_AUDIT */
 static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
include/uapi/linux/audit.h +6 -0
index 1acfea7..7ec7209 100644
@@ -123,6 +123,12 @@
 #define AUDIT_NS_DEL_USER	1339	/* Record USER namespace instance deletion */
 #define AUDIT_NS_DEL_PID	1340	/* Record PID namespace instance deletion */
 #define AUDIT_NS_DEL_NET	1341	/* Record NET namespace instance deletion */
+#define AUDIT_NS_SET_MNT	1342	/* Record mount namespace instance deletion */
+#define AUDIT_NS_SET_UTS	1343	/* Record UTS namespace instance deletion */
+#define AUDIT_NS_SET_IPC	1344	/* Record IPC namespace instance deletion */
+#define AUDIT_NS_SET_USER	1345	/* Record USER namespace instance deletion */
+#define AUDIT_NS_SET_PID	1346	/* Record PID namespace instance deletion */
+#define AUDIT_NS_SET_NET	1347	/* Record NET namespace instance deletion */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
kernel/audit.c +26 -0
index cc63445..84590d1 100644
@@ -2021,6 +2021,52 @@ int audit_log_ns_del(int type, long long snum)
 	audit_log_end(ab);
 	return 0;
 }
+
+/**
+ * audit_log_ns_set - report a namespace set change
+ * @ops: the ops structure for the namespace to be changed
+ * @ns: the new namespace
+ */
+void audit_log_ns_set(const struct proc_ns_operations *ops, void *ns)
+{
+	struct audit_buffer *ab;
+	void *old_ns;
+	int msg_type;
+
+	switch (ops->type) {
+	case CLONE_NEWNS:
+		msg_type = AUDIT_NS_SET_MNT;
+		break;
+	case CLONE_NEWUTS:
+		msg_type = AUDIT_NS_SET_UTS;
+		break;
+	case CLONE_NEWIPC:
+		msg_type = AUDIT_NS_SET_IPC;
+		break;
+	case CLONE_NEWUSER:
+		msg_type = AUDIT_NS_SET_USER;
+		break;
+	case CLONE_NEWPID:

kernel/audit.c int audit_log_ns_del(int type, long long snum) · line 2059

Quoted 10 lines
kernel/audit.c +10 -0
+		msg_type = AUDIT_NS_SET_PID;
+		break;
+	case CLONE_NEWNET:
+		msg_type = AUDIT_NS_SET_NET;
+		break;
+	default:
+		return;
+	}
+	//ab = audit_log_start(tsk->audit_context, GFP_KERNEL, msg_type);
+	//audit_log_format(ab, " pid=%d", current->pid);

Are these commented lines an accident, a 'TODO', or something else?

Quoted 29 lines
kernel/audit.c +10 -0
+	audit_log_common_recv_msg(&ab, ops->type);
+	if (!ab)
+		return;
+ 	old_ns = ops->get(current);
+	audit_log_format(ab, " old-%ssn=%llx %ssn=%llx",
+			 ops->name, ops->snum(old_ns),
+			 ops->name, ops->snum(ns));
+	ops->put(old_ns);
+	audit_log_end(ab);
+}
 #endif /* CONFIG_NAMESPACES */
 
 /**
kernel/nsproxy.c +3 -0
index 2cdc16b..e37409a 100644
@@ -275,6 +275,9 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
 		goto out;
 	}
 	switch_task_namespaces(tsk, new_nsproxy);
+
+	audit_log_ns_set(ops, ei->ns);
+
 out:
 	fput(file);
 	return err;
Signature · 1 line
1.7.1
#31 lore raw

PATCH v5 11/13 audit: emit AUDIT_NS_INFO record with AUDIT_VIRT_CONTROL record

In reply to Richard Guy Briggs
---
 include/uapi/linux/audit.h |    2 ++
 kernel/audit.c             |    2 ++
 2 files changed, 4 insertions(+), 0 deletions(-)
include/uapi/linux/audit.h +2 -0
index 7ec7209..beb23f7 100644
@@ -163,6 +163,8 @@
 
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
+#define AUDIT_VIRT_CONTROL	2500	/* Start, Pause, Stop VM */
+
 /* Rule flags */
 #define AUDIT_FILTER_USER	0x00	/* Apply rule to user-generated messages */
 #define AUDIT_FILTER_TASK	0x01	/* Apply rule at task creation (not syscall) */
kernel/audit.c +2 -0
index 84590d1..5404c24 100644
@@ -941,6 +941,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 			}
 			audit_set_portid(ab, NETLINK_CB(skb).portid);
 			audit_log_end(ab);
+			if (msg_type == AUDIT_VIRT_CONTROL)
+				audit_log_ns_info(NULL);
 			mutex_lock(&audit_cmd_mutex);
 		}
 		break;
Signature · 1 line
1.7.1
maintainer
#32 lore raw

Re: [PATCH V5 11/13] audit: emit AUDIT_NS_INFO record with AUDIT_VIRT_CONTROL record

Quoted 24 lines · Richard Guy Briggs
---
 include/uapi/linux/audit.h |    2 ++
 kernel/audit.c             |    2 ++
 2 files changed, 4 insertions(+), 0 deletions(-)
include/uapi/linux/audit.h +2 -0
index 7ec7209..beb23f7 100644
@@ -163,6 +163,8 @@
 
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
+#define AUDIT_VIRT_CONTROL	2500	/* Start, Pause, Stop VM */
+
 /* Rule flags */
 #define AUDIT_FILTER_USER	0x00	/* Apply rule to user-generated messages */
 #define AUDIT_FILTER_TASK	0x01	/* Apply rule at task creation (not syscall) */
kernel/audit.c +0 -0
index 84590d1..5404c24 100644

kernel/audit.c static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) · line 945

Quoted 5 lines
kernel/audit.c +2 -0
@@ -941,6 +941,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 			}
 			audit_set_portid(ab, NETLINK_CB(skb).portid);
 			audit_log_end(ab);
+			if (msg_type == AUDIT_VIRT_CONTROL)
+				audit_log_ns_info(NULL);

AFAICT your patchset leaves audit_log_ns_info() immediately returning if arg1 is NULL. Is handling that coming later? Why not leave this until that patch comes?

Quoted 5 lines
kernel/audit.c +0 -0
 			mutex_lock(&audit_cmd_mutex);
 		}
 		break;
Signature · 1 line
1.7.1
#33 lore raw

PATCH v5 12/13 namespaces: expose ns instance serial numbers in proc

In reply to Richard Guy Briggs

Expose the namespace instace serial numbers in the proc filesystem at /proc/<pid>/ns/<ns>_snum. The link text gives the serial number in hex.

"snum" was chosen instead of "seq" for consistency with inum and there are a number of other uses of "seq" in the namespace code.

---
 fs/proc/namespaces.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)
fs/proc/namespaces.c +25 -8
index 310da74..29c3909 100644
@@ -47,12 +47,15 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
 	struct inode *inode = dentry->d_inode;
 	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns.ns_ops;
 
-	return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
-		ns_ops->name, inode->i_ino);
+	if (strstr(dentry->d_iname, "_snum"))
+		return dynamic_dname(dentry, buffer, buflen, "%s_snum:[%llx]",
+			ns_ops->name, ns_ops->snum(PROC_I(inode)->ns.ns));
+	else
+		return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
+			ns_ops->name, inode->i_ino);
 }
 
-const struct dentry_operations ns_dentry_operations =
-{
+const struct dentry_operations ns_dentry_operations = {
 	.d_delete	= always_delete_dentry,
 	.d_dname	= ns_dname,
 };
@@ -160,7 +163,10 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl
 	if (!ns)
 		goto out_put_task;
 
-	snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
+	if (strstr(dentry->d_iname, "_snum"))
+		snprintf(name, sizeof(name), "%s_snum:[%llx]", ns_ops->name, ns_ops->snum(ns));
+	else
+		snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
 	res = readlink_copy(buffer, buflen, name);
 	ns_ops->put(ns);
 out_put_task:
@@ -210,16 +216,23 @@ static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
 
 	if (!dir_emit_dots(file, ctx))
 		goto out;
-	if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
+	if (ctx->pos >= 2 + 2 * ARRAY_SIZE(ns_entries))
 		goto out;
 	entry = ns_entries + (ctx->pos - 2);
 	last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
 	while (entry <= last) {
 		const struct proc_ns_operations *ops = *entry;
+		char name[50];
+
 		if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
 				     proc_ns_instantiate, task, ops))
 			break;
 		ctx->pos++;
+		snprintf(name, sizeof(name), "%s_snum", ops->name);
+		if (!proc_fill_cache(file, ctx, name, strlen(name),
+				     proc_ns_instantiate, task, ops))
+			break;
+		ctx->pos++;
 		entry++;
 	}
 out:
@@ -247,9 +260,13 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 
 	last = &ns_entries[ARRAY_SIZE(ns_entries)];
 	for (entry = ns_entries; entry < last; entry++) {
-		if (strlen((*entry)->name) != len)
+		char name[50];
+
+		snprintf(name, sizeof(name), "%s_snum", (*entry)->name);
+		if (strlen((*entry)->name) != len && strlen(name) != len)
 			continue;
-		if (!memcmp(dentry->d_name.name, (*entry)->name, len))
+		if (!memcmp(dentry->d_name.name, (*entry)->name, len)
+		    || !memcmp(dentry->d_name.name, name, len))
 			break;
 	}
 	if (entry == last)
Signature · 1 line
1.7.1
maintainer Acked-by Serge Hallyn on v5 12/13
#34 lore raw

Re: [PATCH V5 12/13] namespaces: expose ns instance serial numbers in proc

Quoted 1 line · Richard Guy Briggs

Expose the namespace instace serial numbers in the proc filesystem at

(s/stac/stanc/)

Quoted 6 lines

/proc/<pid>/ns/<ns>_snum. The link text gives the serial number in hex.

"snum" was chosen instead of "seq" for consistency with inum and there are a number of other uses of "seq" in the namespace code.

Quoted 84 lines
---
 fs/proc/namespaces.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)
fs/proc/namespaces.c +25 -8
index 310da74..29c3909 100644
@@ -47,12 +47,15 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
 	struct inode *inode = dentry->d_inode;
 	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns.ns_ops;
 
-	return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
-		ns_ops->name, inode->i_ino);
+	if (strstr(dentry->d_iname, "_snum"))
+		return dynamic_dname(dentry, buffer, buflen, "%s_snum:[%llx]",
+			ns_ops->name, ns_ops->snum(PROC_I(inode)->ns.ns));
+	else
+		return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
+			ns_ops->name, inode->i_ino);
 }
 
-const struct dentry_operations ns_dentry_operations =
-{
+const struct dentry_operations ns_dentry_operations = {
 	.d_delete	= always_delete_dentry,
 	.d_dname	= ns_dname,
 };
@@ -160,7 +163,10 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl
 	if (!ns)
 		goto out_put_task;
 
-	snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
+	if (strstr(dentry->d_iname, "_snum"))
+		snprintf(name, sizeof(name), "%s_snum:[%llx]", ns_ops->name, ns_ops->snum(ns));
+	else
+		snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
 	res = readlink_copy(buffer, buflen, name);
 	ns_ops->put(ns);
 out_put_task:
@@ -210,16 +216,23 @@ static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
 
 	if (!dir_emit_dots(file, ctx))
 		goto out;
-	if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
+	if (ctx->pos >= 2 + 2 * ARRAY_SIZE(ns_entries))
 		goto out;
 	entry = ns_entries + (ctx->pos - 2);
 	last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
 	while (entry <= last) {
 		const struct proc_ns_operations *ops = *entry;
+		char name[50];
+
 		if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
 				     proc_ns_instantiate, task, ops))
 			break;
 		ctx->pos++;
+		snprintf(name, sizeof(name), "%s_snum", ops->name);
+		if (!proc_fill_cache(file, ctx, name, strlen(name),
+				     proc_ns_instantiate, task, ops))
+			break;
+		ctx->pos++;
 		entry++;
 	}
 out:
@@ -247,9 +260,13 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 
 	last = &ns_entries[ARRAY_SIZE(ns_entries)];
 	for (entry = ns_entries; entry < last; entry++) {
-		if (strlen((*entry)->name) != len)
+		char name[50];
+
+		snprintf(name, sizeof(name), "%s_snum", (*entry)->name);
+		if (strlen((*entry)->name) != len && strlen(name) != len)
 			continue;
-		if (!memcmp(dentry->d_name.name, (*entry)->name, len))
+		if (!memcmp(dentry->d_name.name, (*entry)->name, len)
+		    || !memcmp(dentry->d_name.name, name, len))
 			break;
 	}
 	if (entry == last)
Signature · 1 line
1.7.1
#35 lore raw

PATCH v5 13/13 Documentation: add a section for /proc/<pid>/ns/

In reply to Richard Guy Briggs
---
 Documentation/filesystems/proc.txt |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
Documentation/filesystems/proc.txt +16 -0
index ddc531a..c4bfd6f 100644
@@ -42,6 +42,7 @@ Table of Contents
   3.6	/proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
   3.7   /proc/<pid>/task/<tid>/children - Information about task children
   3.8   /proc/<pid>/fdinfo/<fd> - Information about opened file
+  3.9   /proc/<pid>/ns/<ns>{,_snum} - Information about process namespaces
 
   4	Configuring procfs
   4.1	Mount options
@@ -1744,6 +1745,21 @@ pair provide additional information particular to the objects they represent.
 	optional and may be omitted if no marks created yet.
 
 
+3.9	/proc/<pid>/ns/<nstype>{,_snum} - Information about process namespaces
+--------------------------------------------------------------------------
+These files provides information about the namespaces within which the process
+is contained.  The files named only with the namespace type <nstype> contain a
+link that lists the containing namespace' inode number in its proc filesystem.
+The files with suffix _snum contain a link that lists the containing
+namespace' instance serial number, unique per kernel since boot.  The
+namespace types are self-describing.
+
+The output format of the inode links is:
+	<nstype>:[<inode_number>]
+The output format of the serial number links is:
+	<nstype>_snum:[<serial_number>]
+
+
 ------------------------------------------------------------------------------
 Configuring procfs
 ------------------------------------------------------------------------------
Signature · 1 line
1.7.1
maintainer Acked-by Serge Hallyn on v5 13/13
#36 lore raw

Re: [PATCH V5 13/13] Documentation: add a section for /proc/<pid>/ns/

Quoted 1 line · Richard Guy Briggs

---

(some nitpicking below)

Thanks, Richard. IMO this patchset is great at the moment. Now if I checkpoint a container, migrate it to another machine, and restart it there, the serial numbers will no longer match, but as the creations are all logged, userspace can track the changed snum, so I don't believe that is a problem. (Pretty sure we've discussed that before, mostly mentioning it here to think through it myself)

Quoted 16 lines
 Documentation/filesystems/proc.txt |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
Documentation/filesystems/proc.txt +1 -0
index ddc531a..c4bfd6f 100644
@@ -42,6 +42,7 @@ Table of Contents
   3.6	/proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
   3.7   /proc/<pid>/task/<tid>/children - Information about task children
   3.8   /proc/<pid>/fdinfo/<fd> - Information about opened file
+  3.9   /proc/<pid>/ns/<ns>{,_snum} - Information about process namespaces
 
   4	Configuring procfs
   4.1	Mount options

Documentation/filesystems/proc.txt pair provide additional information particular to the objects they represent. · line 1750

Quoted 6 lines
Documentation/filesystems/proc.txt +3 -0
@@ -1744,6 +1745,21 @@ pair provide additional information particular to the objects they represent.
 	optional and may be omitted if no marks created yet.
 
 
+3.9	/proc/<pid>/ns/<nstype>{,_snum} - Information about process namespaces
+--------------------------------------------------------------------------
+These files provides information about the namespaces within which the process

s/provides/provide/

Documentation/filesystems/proc.txt pair provide additional information particular to the objects they represent. · line 1752

Quoted 2 lines
Documentation/filesystems/proc.txt +2 -0
+is contained.  The files named only with the namespace type <nstype> contain a
+link that lists the containing namespace' inode number in its proc filesystem.

s/'/'s/

... Maybe add "And which can be used with setns(2)."

Documentation/filesystems/proc.txt pair provide additional information particular to the objects they represent. · line 1754

Quoted 2 lines
Documentation/filesystems/proc.txt +2 -0
+The files with suffix _snum contain a link that lists the containing
+namespace' instance serial number, unique per kernel since boot.  The

s/'/'s/

Quoted 13 lines
Documentation/filesystems/proc.txt +8 -0
+namespace types are self-describing.
+
+The output format of the inode links is:
+	<nstype>:[<inode_number>]
+The output format of the serial number links is:
+	<nstype>_snum:[<serial_number>]
+
+
 ------------------------------------------------------------------------------
 Configuring procfs
 ------------------------------------------------------------------------------
Signature · 1 line
1.7.1
#37 lore raw

Re: [PATCH V5 13/13] Documentation: add a section for /proc/<pid>/ns/

Quoted 5 lines · Serge E. Hallyn
Quoted 1 line · Richard Guy Briggs

---

Quoted 8 lines

(some nitpicking below)

Thanks, Richard. IMO this patchset is great at the moment. Now if I checkpoint a container, migrate it to another machine, and restart it there, the serial numbers will no longer match, but as the creations are all logged, userspace can track the changed snum, so I don't believe that is a problem. (Pretty sure we've discussed that before, mostly mentioning it here to think through it myself)

In fact, these last two are included for completeness, but deprecated, since as has been pointed out it is visible from inside the container. I am expecting to drop the last two patches since the necessary information is available to the audit logs in previous patches, which can be made available to docker or other container supervisor.

Quoted 37 lines
Quoted 16 lines
 Documentation/filesystems/proc.txt |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
Documentation/filesystems/proc.txt +1 -0
index ddc531a..c4bfd6f 100644
@@ -42,6 +42,7 @@ Table of Contents
   3.6	/proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
   3.7   /proc/<pid>/task/<tid>/children - Information about task children
   3.8   /proc/<pid>/fdinfo/<fd> - Information about opened file
+  3.9   /proc/<pid>/ns/<ns>{,_snum} - Information about process namespaces
 
   4	Configuring procfs
   4.1	Mount options

Documentation/filesystems/proc.txt pair provide additional information particular to the objects they represent. · line 1750

Quoted 6 lines
Documentation/filesystems/proc.txt +3 -0
@@ -1744,6 +1745,21 @@ pair provide additional information particular to the objects they represent.
 	optional and may be omitted if no marks created yet.
 
 
+3.9	/proc/<pid>/ns/<nstype>{,_snum} - Information about process namespaces
+--------------------------------------------------------------------------
+These files provides information about the namespaces within which the process

s/provides/provide/

Documentation/filesystems/proc.txt pair provide additional information particular to the objects they represent. · line 1752

Quoted 2 lines
Documentation/filesystems/proc.txt +2 -0
+is contained.  The files named only with the namespace type <nstype> contain a
+link that lists the containing namespace' inode number in its proc filesystem.

s/'/'s/

... Maybe add "And which can be used with setns(2)."

Documentation/filesystems/proc.txt pair provide additional information particular to the objects they represent. · line 1754

Quoted 2 lines
Documentation/filesystems/proc.txt +2 -0
+The files with suffix _snum contain a link that lists the containing
+namespace' instance serial number, unique per kernel since boot.  The

s/'/'s/

Quoted 13 lines
Quoted 13 lines
Documentation/filesystems/proc.txt +8 -0
+namespace types are self-describing.
+
+The output format of the inode links is:
+	<nstype>:[<inode_number>]
+The output format of the serial number links is:
+	<nstype>_snum:[<serial_number>]
+
+
 ------------------------------------------------------------------------------
 Configuring procfs
 ------------------------------------------------------------------------------
Signature · 1 line
1.7.1

- RGB

--
Richard Guy Briggs <[email protected]> Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545