* [PATCH V2 1/6] namespaces: assign each namespace instance a serial number
2014-05-10 0:27 [PATCH V2 0/6] namespaces: log namespaces per task Richard Guy Briggs
@ 2014-05-10 0:27 ` Richard Guy Briggs
2014-05-10 15:01 ` Eric Paris
2014-05-10 0:27 ` [PATCH V2 2/6] audit: log namespace serial numbers Richard Guy Briggs
` (4 subsequent siblings)
5 siblings, 1 reply; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-10 0:27 UTC (permalink / raw)
To: linux-audit, linux-kernel, containers
Cc: Richard Guy Briggs, arozansk, serge, ebiederm, eparis, sgrubb
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.
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
fs/mount.h | 1 +
fs/namespace.c | 1 +
include/linux/ipc_namespace.h | 1 +
include/linux/nsproxy.h | 8 ++++++++
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 | 20 ++++++++++++++++++++
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 | 4 +++-
18 files changed, 50 insertions(+), 1 deletions(-)
diff --git a/fs/mount.h b/fs/mount.h
index b29e42f..3d2f451 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -5,6 +5,7 @@
struct mnt_namespace {
atomic_t count;
unsigned int proc_inum;
+ unsigned long long serial_num;
struct mount * root;
struct list_head list;
struct user_namespace *user_ns;
diff --git a/fs/namespace.c b/fs/namespace.c
index 2ffc5a2..b4a31aa 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2472,6 +2472,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;
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 35e7eca..392e45c 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -69,6 +69,7 @@ struct ipc_namespace {
struct user_namespace *user_ns;
unsigned int proc_inum;
+ unsigned long long serial_num;
};
extern struct ipc_namespace init_ipc_ns;
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index b4ec59d..3329335 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -66,6 +66,14 @@ static inline struct nsproxy *task_nsproxy(struct task_struct *tsk)
return rcu_dereference(tsk->nsproxy);
}
+unsigned 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,
+};
+
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);
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 7246ef3..ad20a38 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -43,6 +43,7 @@ struct pid_namespace {
int hide_pid;
int reboot; /* group exit code if this pidns was rebooted */
unsigned int proc_inum;
+ unsigned long long serial_num;
};
extern struct pid_namespace init_pid_ns;
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 4836ba3..5f18aa0 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -27,6 +27,7 @@ struct user_namespace {
kuid_t owner;
kgid_t group;
unsigned int proc_inum;
+ unsigned long long serial_num;
/* Register of per-UID persistent keyrings for this namespace */
#ifdef CONFIG_PERSISTENT_KEYRINGS
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index 239e277..ad5f9ea 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -24,6 +24,7 @@ struct uts_namespace {
struct new_utsname name;
struct user_namespace *user_ns;
unsigned int proc_inum;
+ unsigned long long serial_num;
};
extern struct uts_namespace init_uts_ns;
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 991dcd9..a8d4bd9 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -59,6 +59,7 @@ struct net {
struct user_namespace *user_ns; /* Owning user namespace */
unsigned int proc_inum;
+ unsigned long long serial_num;
struct proc_dir_entry *proc_net;
struct proc_dir_entry *proc_net_stat;
diff --git a/init/version.c b/init/version.c
index 1a4718e..cfdcb85 100644
--- a/init/version.c
+++ b/init/version.c
@@ -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);
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 7e70959..9aa66ae 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -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);
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 59451c1..76dac5c 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -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);
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 8e78110..f4f1068 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -41,6 +41,26 @@ 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.
+ */
+unsigned long long ns_serial(void)
+{
+ static DEFINE_SPINLOCK(serial_lock);
+ static unsigned long long serial = 4; /* reserved for IPC, UTS, user, PID */
+ unsigned long flags;
+
+ spin_lock_irqsave(&serial_lock, flags);
+ ++serial;
+ spin_unlock_irqrestore(&serial_lock, flags);
+ BUG_ON(!serial);
+
+ return serial;
+}
+
static inline struct nsproxy *create_nsproxy(void)
{
struct nsproxy *nsproxy;
diff --git a/kernel/pid.c b/kernel/pid.c
index 9b9a266..3bf7127 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -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);
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 06c62de..c24f207 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -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);
diff --git a/kernel/user.c b/kernel/user.c
index c006131..fb16754 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -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),
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index dd06439..750241c 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -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;
diff --git a/kernel/utsname.c b/kernel/utsname.c
index fd39312..d0cf7b5 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -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);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 81d3a9a..e0b8528 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -104,8 +104,10 @@ static int ops_init(const struct pernet_operations *ops, struct net *net)
err = 0;
if (ops->init)
err = ops->init(net);
- if (!err)
+ if (!err) {
+ net->serial_num = ns_serial();
return 0;
+ }
cleanup:
kfree(data);
--
1.7.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH V2 1/6] namespaces: assign each namespace instance a serial number
2014-05-10 0:27 ` [PATCH V2 1/6] namespaces: assign each namespace instance a serial number Richard Guy Briggs
@ 2014-05-10 15:01 ` Eric Paris
2014-05-13 14:39 ` Richard Guy Briggs
0 siblings, 1 reply; 16+ messages in thread
From: Eric Paris @ 2014-05-10 15:01 UTC (permalink / raw)
To: Richard Guy Briggs
Cc: linux-audit, linux-kernel, containers, arozansk, serge, ebiederm,
sgrubb
On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
> 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.
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
> +/**
> + * ns_serial - compute a serial number for the namespace
> + *
> + * Compute a serial number for the namespace to uniquely identify it in
> + * audit records.
> + */
> +unsigned long long ns_serial(void)
> +{
> + static DEFINE_SPINLOCK(serial_lock);
> + static unsigned long long serial = 4; /* reserved for IPC, UTS, user, PID */
> + unsigned long flags;
> +
> + spin_lock_irqsave(&serial_lock, flags);
> + ++serial;
> + spin_unlock_irqrestore(&serial_lock, flags);
> + BUG_ON(!serial);
> +
> + return serial;
> +}
> +
> static inline struct nsproxy *create_nsproxy(void)
> {
> struct nsproxy *nsproxy;
atomic64_t instead of doing it yourself?
and why _irqsave() ? Can we seriously create new namespaces in irq
context? If you use the atomic though, you don't have to worry about
it...
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 1/6] namespaces: assign each namespace instance a serial number
2014-05-10 15:01 ` Eric Paris
@ 2014-05-13 14:39 ` Richard Guy Briggs
2014-05-13 15:13 ` Richard Guy Briggs
0 siblings, 1 reply; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-13 14:39 UTC (permalink / raw)
To: Eric Paris
Cc: linux-audit, linux-kernel, containers, arozansk, serge, ebiederm,
sgrubb
On 14/05/10, Eric Paris wrote:
> On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
> > 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.
> >
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
>
> > +/**
> > + * ns_serial - compute a serial number for the namespace
> > + *
> > + * Compute a serial number for the namespace to uniquely identify it in
> > + * audit records.
> > + */
> > +unsigned long long ns_serial(void)
> > +{
> > + static DEFINE_SPINLOCK(serial_lock);
> > + static unsigned long long serial = 4; /* reserved for IPC, UTS, user, PID */
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&serial_lock, flags);
> > + ++serial;
> > + spin_unlock_irqrestore(&serial_lock, flags);
> > + BUG_ON(!serial);
> > +
> > + return serial;
> > +}
> > +
> > static inline struct nsproxy *create_nsproxy(void)
> > {
> > struct nsproxy *nsproxy;
>
> atomic64_t instead of doing it yourself?
I'm willing to switch to atomic64_*. Thanks for pointing out its
existence.
> and why _irqsave() ? Can we seriously create new namespaces in irq
> context? If you use the atomic though, you don't have to worry about
> it...
Agreed. That is unlikely.
- RGB
--
Richard Guy Briggs <rbriggs@redhat.com>
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
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 1/6] namespaces: assign each namespace instance a serial number
2014-05-13 14:39 ` Richard Guy Briggs
@ 2014-05-13 15:13 ` Richard Guy Briggs
2014-05-13 15:30 ` Eric Paris
0 siblings, 1 reply; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-13 15:13 UTC (permalink / raw)
To: Eric Paris
Cc: linux-audit, linux-kernel, containers, arozansk, serge, ebiederm,
sgrubb
On 14/05/13, Richard Guy Briggs wrote:
> On 14/05/10, Eric Paris wrote:
> > On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
> > > 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.
> > >
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> >
> > > +/**
> > > + * ns_serial - compute a serial number for the namespace
> > > + *
> > > + * Compute a serial number for the namespace to uniquely identify it in
> > > + * audit records.
> > > + */
> > > +unsigned long long ns_serial(void)
> > > +{
> > > + static DEFINE_SPINLOCK(serial_lock);
> > > + static unsigned long long serial = 4; /* reserved for IPC, UTS, user, PID */
> > > + unsigned long flags;
> > > +
> > > + spin_lock_irqsave(&serial_lock, flags);
> > > + ++serial;
> > > + spin_unlock_irqrestore(&serial_lock, flags);
> > > + BUG_ON(!serial);
> > > +
> > > + return serial;
> > > +}
> > > +
> > > static inline struct nsproxy *create_nsproxy(void)
> > > {
> > > struct nsproxy *nsproxy;
> >
> > atomic64_t instead of doing it yourself?
>
> I'm willing to switch to atomic64_*. Thanks for pointing out its
> existence.
Same would then go for using atomic_t in audit_serial().
> > and why _irqsave() ? Can we seriously create new namespaces in irq
> > context? If you use the atomic though, you don't have to worry about
> > it...
>
> Agreed. That is unlikely.
>
> - RGB
>
> --
> Richard Guy Briggs <rbriggs@redhat.com>
> 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
- RGB
--
Richard Guy Briggs <rbriggs@redhat.com>
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
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 1/6] namespaces: assign each namespace instance a serial number
2014-05-13 15:13 ` Richard Guy Briggs
@ 2014-05-13 15:30 ` Eric Paris
2014-05-13 18:44 ` Eric Paris
0 siblings, 1 reply; 16+ messages in thread
From: Eric Paris @ 2014-05-13 15:30 UTC (permalink / raw)
To: Richard Guy Briggs
Cc: linux-audit, linux-kernel, containers, arozansk, serge, ebiederm,
sgrubb
On Tue, 2014-05-13 at 11:13 -0400, Richard Guy Briggs wrote:
> On 14/05/13, Richard Guy Briggs wrote:
> > On 14/05/10, Eric Paris wrote:
> > > On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
> > > > 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.
> > > >
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > ---
> > >
> > > > +/**
> > > > + * ns_serial - compute a serial number for the namespace
> > > > + *
> > > > + * Compute a serial number for the namespace to uniquely identify it in
> > > > + * audit records.
> > > > + */
> > > > +unsigned long long ns_serial(void)
> > > > +{
> > > > + static DEFINE_SPINLOCK(serial_lock);
> > > > + static unsigned long long serial = 4; /* reserved for IPC, UTS, user, PID */
> > > > + unsigned long flags;
> > > > +
> > > > + spin_lock_irqsave(&serial_lock, flags);
> > > > + ++serial;
> > > > + spin_unlock_irqrestore(&serial_lock, flags);
> > > > + BUG_ON(!serial);
> > > > +
> > > > + return serial;
> > > > +}
> > > > +
> > > > static inline struct nsproxy *create_nsproxy(void)
> > > > {
> > > > struct nsproxy *nsproxy;
> > >
> > > atomic64_t instead of doing it yourself?
> >
> > I'm willing to switch to atomic64_*. Thanks for pointing out its
> > existence.
>
> Same would then go for using atomic_t in audit_serial().
Yup, moving to an atomic in audit_serial() looks like a good idea to me.
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 1/6] namespaces: assign each namespace instance a serial number
2014-05-13 15:30 ` Eric Paris
@ 2014-05-13 18:44 ` Eric Paris
0 siblings, 0 replies; 16+ messages in thread
From: Eric Paris @ 2014-05-13 18:44 UTC (permalink / raw)
To: Richard Guy Briggs; +Cc: containers, linux-kernel, linux-audit, ebiederm, serge
On Tue, 2014-05-13 at 11:30 -0400, Eric Paris wrote:
> On Tue, 2014-05-13 at 11:13 -0400, Richard Guy Briggs wrote:
> > On 14/05/13, Richard Guy Briggs wrote:
> > > On 14/05/10, Eric Paris wrote:
> > > > On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
> > > > > 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.
> > > > >
> > > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > > ---
> > > >
> > > > > +/**
> > > > > + * ns_serial - compute a serial number for the namespace
> > > > > + *
> > > > > + * Compute a serial number for the namespace to uniquely identify it in
> > > > > + * audit records.
> > > > > + */
> > > > > +unsigned long long ns_serial(void)
> > > > > +{
> > > > > + static DEFINE_SPINLOCK(serial_lock);
> > > > > + static unsigned long long serial = 4; /* reserved for IPC, UTS, user, PID */
> > > > > + unsigned long flags;
> > > > > +
> > > > > + spin_lock_irqsave(&serial_lock, flags);
> > > > > + ++serial;
> > > > > + spin_unlock_irqrestore(&serial_lock, flags);
> > > > > + BUG_ON(!serial);
> > > > > +
> > > > > + return serial;
> > > > > +}
> > > > > +
> > > > > static inline struct nsproxy *create_nsproxy(void)
> > > > > {
> > > > > struct nsproxy *nsproxy;
> > > >
> > > > atomic64_t instead of doing it yourself?
> > >
> > > I'm willing to switch to atomic64_*. Thanks for pointing out its
> > > existence.
> >
> > Same would then go for using atomic_t in audit_serial().
>
> Yup, moving to an atomic in audit_serial() looks like a good idea to me.
Talking with steve on irc, neither of us see a need for the double
increment quirk if the serial wraps back to 0. Nothing wrong with 0, it
is a number.
-Eric
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH V2 2/6] audit: log namespace serial numbers
2014-05-10 0:27 [PATCH V2 0/6] namespaces: log namespaces per task Richard Guy Briggs
2014-05-10 0:27 ` [PATCH V2 1/6] namespaces: assign each namespace instance a serial number Richard Guy Briggs
@ 2014-05-10 0:27 ` Richard Guy Briggs
2014-05-10 15:07 ` Eric Paris
2014-05-10 15:56 ` Eric Paris
2014-05-10 0:27 ` [PATCH V2 3/6] namespaces: expose namespace instance serial number in proc_ns_operations Richard Guy Briggs
` (3 subsequent siblings)
5 siblings, 2 replies; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-10 0:27 UTC (permalink / raw)
To: linux-audit, linux-kernel, containers
Cc: Richard Guy Briggs, arozansk, serge, ebiederm, eparis, sgrubb
Log the namespace serial numbers of a task in audit_log_task_info() 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=SYSCALL msg=audit(1399651071.433:72): arch=c000003e syscall=272 success=yes exit=0 a0=40000000 a1=ffffffffffffffff a2=0 a3=22 items=0 ppid=1 pid=483 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="(t-daemon)" exe="/usr/lib/systemd/systemd" netns=97 utsns=2 ipcns=1 pidns=4 userns=3 mntns=5 subj=system_u:system_r:init_t:s0 key=(null)
The serial numbers are printed in hex.
Suggested-by: Aristeu Rozanski <arozansk@redhat.com>
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
---
include/linux/audit.h | 7 +++++++
kernel/audit.c | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 22cfddb..0ef404a 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -101,6 +101,13 @@ extern int __weak audit_classify_compat_syscall(int abi, unsigned syscall);
struct filename;
extern void audit_log_session_info(struct audit_buffer *ab);
+#ifdef CONFIG_NAMESPACES
+extern void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk);
+#else
+void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
+{
+}
+#endif
#ifdef CONFIG_AUDIT_COMPAT_GENERIC
#define audit_is_compat(arch) (!((arch) & __AUDIT_ARCH_64BIT))
diff --git a/kernel/audit.c b/kernel/audit.c
index 59c0bbe..fe783ad 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -64,7 +64,15 @@
#endif
#include <linux/freezer.h>
#include <linux/tty.h>
+#include <linux/nsproxy.h>
+#include <linux/utsname.h>
+#include <linux/ipc_namespace.h>
+#include "../fs/mount.h"
+#include <linux/mount.h>
+#include <linux/mnt_namespace.h>
#include <linux/pid_namespace.h>
+#include <net/net_namespace.h>
+#include <linux/user_namespace.h>
#include <net/netns/generic.h>
#include "audit.h"
@@ -1617,6 +1625,35 @@ 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_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
+{
+ struct nsproxy *nsproxy;
+
+ rcu_read_lock();
+ nsproxy = task_nsproxy(tsk);
+ if (nsproxy != NULL) {
+ audit_log_format(ab, " mntns=%llx", nsproxy->mnt_ns->serial_num);
+#ifdef CONFIG_NET_NS
+ audit_log_format(ab, " netns=%llx", nsproxy->net_ns->serial_num);
+#endif
+#ifdef CONFIG_UTS_NS
+ audit_log_format(ab, " utsns=%llx", nsproxy->uts_ns->serial_num);
+#endif
+#ifdef CONFIG_IPC_NS
+ audit_log_format(ab, " ipcns=%llx", nsproxy->ipc_ns->serial_num);
+#endif
+ }
+#ifdef CONFIG_PID_NS
+ audit_log_format(ab, " pidns=%llx", task_active_pid_ns(tsk)->serial_num);
+#endif
+#ifdef CONFIG_USER_NS
+ audit_log_format(ab, " userns=%llx", task_cred_xxx(tsk, user_ns)->serial_num);
+#endif
+ rcu_read_unlock();
+}
+#endif /* CONFIG_NAMESPACES */
+
void audit_log_key(struct audit_buffer *ab, char *key)
{
audit_log_format(ab, " key=");
@@ -1861,6 +1898,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
up_read(&mm->mmap_sem);
} else
audit_log_format(ab, " exe=(null)");
+ audit_log_namespace_info(ab, tsk);
audit_log_task_context(ab);
}
EXPORT_SYMBOL(audit_log_task_info);
--
1.7.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH V2 2/6] audit: log namespace serial numbers
2014-05-10 0:27 ` [PATCH V2 2/6] audit: log namespace serial numbers Richard Guy Briggs
@ 2014-05-10 15:07 ` Eric Paris
2014-05-13 14:19 ` Richard Guy Briggs
2014-05-10 15:56 ` Eric Paris
1 sibling, 1 reply; 16+ messages in thread
From: Eric Paris @ 2014-05-10 15:07 UTC (permalink / raw)
To: Richard Guy Briggs
Cc: linux-audit, linux-kernel, containers, arozansk, serge, ebiederm,
sgrubb
On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
> Log the namespace serial numbers of a task in audit_log_task_info() 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=SYSCALL msg=audit(1399651071.433:72): arch=c000003e syscall=272 success=yes exit=0 a0=40000000 a1=ffffffffffffffff a2=0 a3=22 items=0 ppid=1 pid=483 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="(t-daemon)" exe="/usr/lib/systemd/systemd" netns=97 utsns=2 ipcns=1 pidns=4 userns=3 mntns=5 subj=system_u:system_r:init_t:s0 key=(null)
>
> The serial numbers are printed in hex.
>
> Suggested-by: Aristeu Rozanski <arozansk@redhat.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
> ---
> include/linux/audit.h | 7 +++++++
> kernel/audit.c | 38 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 45 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 22cfddb..0ef404a 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -101,6 +101,13 @@ extern int __weak audit_classify_compat_syscall(int abi, unsigned syscall);
> struct filename;
>
> extern void audit_log_session_info(struct audit_buffer *ab);
> +#ifdef CONFIG_NAMESPACES
> +extern void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk);
> +#else
> +void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
> +{
> +}
> +#endif
>
> #ifdef CONFIG_AUDIT_COMPAT_GENERIC
> #define audit_is_compat(arch) (!((arch) & __AUDIT_ARCH_64BIT))
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 59c0bbe..fe783ad 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -64,7 +64,15 @@
> #endif
> #include <linux/freezer.h>
> #include <linux/tty.h>
> +#include <linux/nsproxy.h>
> +#include <linux/utsname.h>
> +#include <linux/ipc_namespace.h>
> +#include "../fs/mount.h"
I don't think such an include is ever a good idea and likely to get us
SHOT by Viro...
Why do we need this include?
> +#include <linux/mount.h>
> +#include <linux/mnt_namespace.h>
> #include <linux/pid_namespace.h>
> +#include <net/net_namespace.h>
> +#include <linux/user_namespace.h>
> #include <net/netns/generic.h>
>
> #include "audit.h"
> @@ -1617,6 +1625,35 @@ 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_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
> +{
> + struct nsproxy *nsproxy;
> +
> + rcu_read_lock();
> + nsproxy = task_nsproxy(tsk);
> + if (nsproxy != NULL) {
> + audit_log_format(ab, " mntns=%llx", nsproxy->mnt_ns->serial_num);
> +#ifdef CONFIG_NET_NS
> + audit_log_format(ab, " netns=%llx", nsproxy->net_ns->serial_num);
> +#endif
> +#ifdef CONFIG_UTS_NS
> + audit_log_format(ab, " utsns=%llx", nsproxy->uts_ns->serial_num);
> +#endif
> +#ifdef CONFIG_IPC_NS
> + audit_log_format(ab, " ipcns=%llx", nsproxy->ipc_ns->serial_num);
> +#endif
> + }
> +#ifdef CONFIG_PID_NS
> + audit_log_format(ab, " pidns=%llx", task_active_pid_ns(tsk)->serial_num);
> +#endif
> +#ifdef CONFIG_USER_NS
> + audit_log_format(ab, " userns=%llx", task_cred_xxx(tsk, user_ns)->serial_num);
> +#endif
> + rcu_read_unlock();
> +}
> +#endif /* CONFIG_NAMESPACES */
> +
> void audit_log_key(struct audit_buffer *ab, char *key)
> {
> audit_log_format(ab, " key=");
> @@ -1861,6 +1898,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
> up_read(&mm->mmap_sem);
> } else
> audit_log_format(ab, " exe=(null)");
> + audit_log_namespace_info(ab, tsk);
> audit_log_task_context(ab);
> }
> EXPORT_SYMBOL(audit_log_task_info);
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 2/6] audit: log namespace serial numbers
2014-05-10 15:07 ` Eric Paris
@ 2014-05-13 14:19 ` Richard Guy Briggs
0 siblings, 0 replies; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-13 14:19 UTC (permalink / raw)
To: Eric Paris
Cc: linux-audit, linux-kernel, containers, arozansk, serge, ebiederm,
sgrubb
On 14/05/10, Eric Paris wrote:
> On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
> > Log the namespace serial numbers of a task in audit_log_task_info() 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=SYSCALL msg=audit(1399651071.433:72): arch=c000003e syscall=272 success=yes exit=0 a0=40000000 a1=ffffffffffffffff a2=0 a3=22 items=0 ppid=1 pid=483 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="(t-daemon)" exe="/usr/lib/systemd/systemd" netns=97 utsns=2 ipcns=1 pidns=4 userns=3 mntns=5 subj=system_u:system_r:init_t:s0 key=(null)
> >
> > The serial numbers are printed in hex.
> >
> > Suggested-by: Aristeu Rozanski <arozansk@redhat.com>
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
> > ---
> > include/linux/audit.h | 7 +++++++
> > kernel/audit.c | 38 ++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 45 insertions(+), 0 deletions(-)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 22cfddb..0ef404a 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -101,6 +101,13 @@ extern int __weak audit_classify_compat_syscall(int abi, unsigned syscall);
> > struct filename;
> >
> > extern void audit_log_session_info(struct audit_buffer *ab);
> > +#ifdef CONFIG_NAMESPACES
> > +extern void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk);
> > +#else
> > +void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
> > +{
> > +}
> > +#endif
> >
> > #ifdef CONFIG_AUDIT_COMPAT_GENERIC
> > #define audit_is_compat(arch) (!((arch) & __AUDIT_ARCH_64BIT))
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index 59c0bbe..fe783ad 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -64,7 +64,15 @@
> > #endif
> > #include <linux/freezer.h>
> > #include <linux/tty.h>
> > +#include <linux/nsproxy.h>
> > +#include <linux/utsname.h>
> > +#include <linux/ipc_namespace.h>
> > +#include "../fs/mount.h"
>
> I don't think such an include is ever a good idea and likely to get us
> SHOT by Viro...
Which is why patch 6 would replace it, but that depends on getting
buy-in to expose ns_entries in patch 5.
> Why do we need this include?
For "struct mnt_namespace", to get access to the serial number.
I agree. It is ugly. In fact, it is the one below that isn't necessary
since it is pulled in by ../fs/mount.h
> > +#include <linux/mount.h>
> > +#include <linux/mnt_namespace.h>
> > #include <linux/pid_namespace.h>
> > +#include <net/net_namespace.h>
> > +#include <linux/user_namespace.h>
> > #include <net/netns/generic.h>
> >
> > #include "audit.h"
> > @@ -1617,6 +1625,35 @@ 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_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
> > +{
> > + struct nsproxy *nsproxy;
> > +
> > + rcu_read_lock();
> > + nsproxy = task_nsproxy(tsk);
> > + if (nsproxy != NULL) {
> > + audit_log_format(ab, " mntns=%llx", nsproxy->mnt_ns->serial_num);
> > +#ifdef CONFIG_NET_NS
> > + audit_log_format(ab, " netns=%llx", nsproxy->net_ns->serial_num);
> > +#endif
> > +#ifdef CONFIG_UTS_NS
> > + audit_log_format(ab, " utsns=%llx", nsproxy->uts_ns->serial_num);
> > +#endif
> > +#ifdef CONFIG_IPC_NS
> > + audit_log_format(ab, " ipcns=%llx", nsproxy->ipc_ns->serial_num);
> > +#endif
> > + }
> > +#ifdef CONFIG_PID_NS
> > + audit_log_format(ab, " pidns=%llx", task_active_pid_ns(tsk)->serial_num);
> > +#endif
> > +#ifdef CONFIG_USER_NS
> > + audit_log_format(ab, " userns=%llx", task_cred_xxx(tsk, user_ns)->serial_num);
> > +#endif
> > + rcu_read_unlock();
> > +}
> > +#endif /* CONFIG_NAMESPACES */
> > +
> > void audit_log_key(struct audit_buffer *ab, char *key)
> > {
> > audit_log_format(ab, " key=");
> > @@ -1861,6 +1898,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
> > up_read(&mm->mmap_sem);
> > } else
> > audit_log_format(ab, " exe=(null)");
> > + audit_log_namespace_info(ab, tsk);
> > audit_log_task_context(ab);
> > }
> > EXPORT_SYMBOL(audit_log_task_info);
>
>
- RGB
--
Richard Guy Briggs <rbriggs@redhat.com>
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V2 2/6] audit: log namespace serial numbers
2014-05-10 0:27 ` [PATCH V2 2/6] audit: log namespace serial numbers Richard Guy Briggs
2014-05-10 15:07 ` Eric Paris
@ 2014-05-10 15:56 ` Eric Paris
2014-05-13 14:28 ` Richard Guy Briggs
1 sibling, 1 reply; 16+ messages in thread
From: Eric Paris @ 2014-05-10 15:56 UTC (permalink / raw)
To: Richard Guy Briggs
Cc: linux-audit, linux-kernel, containers, arozansk, serge, ebiederm,
sgrubb
On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
Not so relevant because you delete all of this code later... But
still...
> +#ifdef CONFIG_NAMESPACES
> +void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
> +{
> + struct nsproxy *nsproxy;
> +
> + rcu_read_lock();
ok, so we are under rcu_read_lock() and cannot sleep
> + nsproxy = task_nsproxy(tsk);
> + if (nsproxy != NULL) {
> + audit_log_format(ab, " mntns=%llx", nsproxy->mnt_ns->serial_num);
But this could do an allocation, are we sure that everything used
GFP_ATOMIC when creating the audit buffer? [hint: it doesn't]
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH V2 2/6] audit: log namespace serial numbers
2014-05-10 15:56 ` Eric Paris
@ 2014-05-13 14:28 ` Richard Guy Briggs
0 siblings, 0 replies; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-13 14:28 UTC (permalink / raw)
To: Eric Paris
Cc: linux-audit, linux-kernel, containers, arozansk, serge, ebiederm,
sgrubb
On 14/05/10, Eric Paris wrote:
> On Fri, 2014-05-09 at 20:27 -0400, Richard Guy Briggs wrote:
>
> Not so relevant because you delete all of this code later... But
> still...
>
> > +#ifdef CONFIG_NAMESPACES
> > +void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
> > +{
> > + struct nsproxy *nsproxy;
> > +
> > + rcu_read_lock();
>
> ok, so we are under rcu_read_lock() and cannot sleep
>
> > + nsproxy = task_nsproxy(tsk);
> > + if (nsproxy != NULL) {
> > + audit_log_format(ab, " mntns=%llx", nsproxy->mnt_ns->serial_num);
>
> But this could do an allocation, are we sure that everything used
> GFP_ATOMIC when creating the audit buffer? [hint: it doesn't]
Ugh, missed that. Even more reason to go with the ns_entries export.
- RGB
--
Richard Guy Briggs <rbriggs@redhat.com>
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH V2 3/6] namespaces: expose namespace instance serial number in proc_ns_operations
2014-05-10 0:27 [PATCH V2 0/6] namespaces: log namespaces per task Richard Guy Briggs
2014-05-10 0:27 ` [PATCH V2 1/6] namespaces: assign each namespace instance a serial number Richard Guy Briggs
2014-05-10 0:27 ` [PATCH V2 2/6] audit: log namespace serial numbers Richard Guy Briggs
@ 2014-05-10 0:27 ` Richard Guy Briggs
2014-05-10 0:27 ` [PATCH V2 4/6] namespaces: expose ns instance serial numbers in proc Richard Guy Briggs
` (2 subsequent siblings)
5 siblings, 0 replies; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-10 0:27 UTC (permalink / raw)
To: linux-audit, linux-kernel, containers
Cc: Richard Guy Briggs, arozansk, serge, ebiederm, eparis, sgrubb
Expose the namespace instance serial number for each namespace type in the proc
namespace operations structure to make it available for the proc filesystem.
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
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(-)
diff --git a/fs/namespace.c b/fs/namespace.c
index b4a31aa..69d269f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3014,6 +3014,12 @@ static unsigned int mntns_inum(void *ns)
return mnt_ns->proc_inum;
}
+static unsigned 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,
@@ -3021,4 +3027,5 @@ const struct proc_ns_operations mntns_operations = {
.put = mntns_put,
.install = mntns_install,
.inum = mntns_inum,
+ .snum = mntns_snum,
};
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
index 34a1e10..aebb3a2 100644
--- a/include/linux/proc_ns.h
+++ b/include/linux/proc_ns.h
@@ -14,6 +14,7 @@ struct proc_ns_operations {
void (*put)(void *ns);
int (*install)(struct nsproxy *nsproxy, void *ns);
unsigned int (*inum)(void *ns);
+ unsigned long long (*snum)(void *ns);
};
struct proc_ns {
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 76dac5c..0669c2d 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -191,6 +191,13 @@ static unsigned int ipcns_inum(void *vp)
return ns->proc_inum;
}
+static unsigned 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,
};
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index c24f207..1dd2eb2 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -368,6 +368,12 @@ static unsigned int pidns_inum(void *ns)
return pid_ns->proc_inum;
}
+static unsigned 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,
@@ -375,6 +381,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)
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 750241c..0b1ba1c 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -890,6 +890,12 @@ static unsigned int userns_inum(void *ns)
return user_ns->proc_inum;
}
+static unsigned 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,
@@ -897,6 +903,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)
diff --git a/kernel/utsname.c b/kernel/utsname.c
index d0cf7b5..c8ca860 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -132,6 +132,13 @@ static unsigned int utsns_inum(void *vp)
return ns->proc_inum;
}
+static unsigned 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,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index e0b8528..e16dc0e 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -667,6 +667,12 @@ static unsigned int netns_inum(void *ns)
return net->proc_inum;
}
+static unsigned 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,
@@ -674,5 +680,6 @@ const struct proc_ns_operations netns_operations = {
.put = netns_put,
.install = netns_install,
.inum = netns_inum,
+ .snum = netns_snum,
};
#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH V2 4/6] namespaces: expose ns instance serial numbers in proc
2014-05-10 0:27 [PATCH V2 0/6] namespaces: log namespaces per task Richard Guy Briggs
` (2 preceding siblings ...)
2014-05-10 0:27 ` [PATCH V2 3/6] namespaces: expose namespace instance serial number in proc_ns_operations Richard Guy Briggs
@ 2014-05-10 0:27 ` Richard Guy Briggs
2014-05-10 0:27 ` [PATCH V2 5/6] namespaces: expose ns_entries Richard Guy Briggs
2014-05-10 0:27 ` [PATCH V2 6/6] audit: convert namespace serial number logging to use proc ns_entries Richard Guy Briggs
5 siblings, 0 replies; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-10 0:27 UTC (permalink / raw)
To: linux-audit, linux-kernel, containers
Cc: Richard Guy Briggs, arozansk, serge, ebiederm, eparis, sgrubb
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.
Suggested-by: Serge E. Hallyn <serge@hallyn.com>
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
Although it works as expected, I'm not that happy with this patch because it
duplicates a lot of code, including minor changes to proc_ns_follow_link(),
proc_ns_readlink(), ns_dname() that will be harder to keep consistent. The
only way I could see to get that information into those functions would be
through dentry. Maybe the information needed is already in there in d_name or
d_iname? Or I could add a flag to d_flags (there are 9 bits unused?) but that
flag isn't useful for any other types of entries, so I'm not so keen to pollute
it.
---
fs/proc/namespaces.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 138 insertions(+), 12 deletions(-)
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 9ae46b8..40bab47 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -42,6 +42,11 @@ static const struct inode_operations ns_inode_operations = {
.setattr = proc_setattr,
};
+enum ns_num {
+ PROC_NS_INUM,
+ PROC_NS_SNUM
+};
+
static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
{
struct inode *inode = dentry->d_inode;
@@ -51,14 +56,28 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
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,
};
+static char *ns_snum_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_snum:[%llx]",
+ ns_ops->name, ns_ops->snum(PROC_I(inode)->ns.ns));
+}
+
+const struct dentry_operations ns_snum_dentry_operations = {
+ .d_delete = always_delete_dentry,
+ .d_dname = ns_snum_dname,
+};
+
static struct dentry *proc_ns_get_dentry(struct super_block *sb,
- struct task_struct *task, const struct proc_ns_operations *ns_ops)
+ struct task_struct *task, const struct proc_ns_operations *ns_ops,
+ enum ns_num ns_num)
{
struct dentry *dentry, *result;
struct inode *inode;
@@ -96,7 +115,10 @@ static struct dentry *proc_ns_get_dentry(struct super_block *sb,
ns_ops->put(ns);
}
- d_set_d_op(dentry, &ns_dentry_operations);
+ if (ns_num == PROC_NS_INUM)
+ d_set_d_op(dentry, &ns_dentry_operations);
+ else if (ns_num == PROC_NS_SNUM)
+ d_set_d_op(dentry, &ns_snum_dentry_operations);
result = d_instantiate_unique(dentry, inode);
if (result) {
dput(dentry);
@@ -122,7 +144,39 @@ static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
if (!ptrace_may_access(task, PTRACE_MODE_READ))
goto out_put_task;
- ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops);
+ ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops, PROC_NS_INUM);
+ if (IS_ERR(ns_path.dentry)) {
+ error = ERR_CAST(ns_path.dentry);
+ goto out_put_task;
+ }
+
+ ns_path.mnt = mntget(nd->path.mnt);
+ nd_jump_link(nd, &ns_path);
+ error = NULL;
+
+out_put_task:
+ put_task_struct(task);
+out:
+ return error;
+}
+
+static void *proc_ns_snum_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ struct inode *inode = dentry->d_inode;
+ struct super_block *sb = inode->i_sb;
+ struct proc_inode *ei = PROC_I(inode);
+ struct task_struct *task;
+ struct path ns_path;
+ void *error = ERR_PTR(-EACCES);
+
+ task = get_proc_task(inode);
+ if (!task)
+ goto out;
+
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
+ goto out_put_task;
+
+ ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops, PROC_NS_SNUM);
if (IS_ERR(ns_path.dentry)) {
error = ERR_CAST(ns_path.dentry);
goto out_put_task;
@@ -181,10 +235,59 @@ static const struct inode_operations proc_ns_link_inode_operations = {
.setattr = proc_setattr,
};
+static int proc_ns_snum_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+{
+ struct inode *inode = dentry->d_inode;
+ struct proc_inode *ei = PROC_I(inode);
+ const struct proc_ns_operations *ns_ops = ei->ns.ns_ops;
+ struct task_struct *task;
+ void *ns;
+ char name[50];
+ int len = -EACCES;
+
+ task = get_proc_task(inode);
+ if (!task)
+ goto out;
+
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
+ goto out_put_task;
+
+ len = -ENOENT;
+ ns = ns_ops->get(task);
+ if (!ns)
+ goto out_put_task;
+
+ snprintf(name, sizeof(name), "%s_snum:[%llx]", ns_ops->name, ns_ops->snum(ns));
+ len = strlen(name);
+
+ if (len > buflen)
+ len = buflen;
+ if (copy_to_user(buffer, name, len))
+ len = -EFAULT;
+
+ ns_ops->put(ns);
+out_put_task:
+ put_task_struct(task);
+out:
+ return len;
+}
+
+static const struct inode_operations proc_ns_snum_link_inode_operations = {
+ .readlink = proc_ns_snum_readlink,
+ .follow_link = proc_ns_snum_follow_link,
+ .setattr = proc_setattr,
+};
+
+struct proc_ns_entry {
+ const struct proc_ns_operations *ns_ops;
+ enum ns_num ns_num;
+};
+
static int proc_ns_instantiate(struct inode *dir,
struct dentry *dentry, struct task_struct *task, const void *ptr)
{
- const struct proc_ns_operations *ns_ops = ptr;
+ const struct proc_ns_entry *ns_entry = ptr;
+ const struct proc_ns_operations *ns_ops = ns_entry->ns_ops;
struct inode *inode;
struct proc_inode *ei;
@@ -194,7 +297,10 @@ static int proc_ns_instantiate(struct inode *dir,
ei = PROC_I(inode);
inode->i_mode = S_IFLNK|S_IRWXUGO;
- inode->i_op = &proc_ns_link_inode_operations;
+ if (ns_entry->ns_num == PROC_NS_INUM)
+ inode->i_op = &proc_ns_link_inode_operations;
+ else if (ns_entry->ns_num == PROC_NS_SNUM)
+ inode->i_op = &proc_ns_snum_link_inode_operations;
ei->ns.ns_ops = ns_ops;
d_set_d_op(dentry, &pid_dentry_operations);
@@ -216,14 +322,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];
+ struct proc_ns_entry ns_entry = { ops, PROC_NS_INUM };
+
if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
- proc_ns_instantiate, task, ops))
+ proc_ns_instantiate, task, &ns_entry))
+ break;
+ ctx->pos++;
+ ns_entry.ns_num = PROC_NS_SNUM;
+ snprintf(name, sizeof(name), "%s_snum", ops->name);
+ if (!proc_fill_cache(file, ctx, name, strlen(name),
+ proc_ns_instantiate, task, &ns_entry))
break;
ctx->pos++;
entry++;
@@ -245,6 +360,7 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
struct task_struct *task = get_proc_task(dir);
const struct proc_ns_operations **entry, **last;
unsigned int len = dentry->d_name.len;
+ struct proc_ns_entry ns_entry;
error = -ENOENT;
@@ -253,15 +369,25 @@ 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)) {
+ ns_entry.ns_ops = *entry;
+ ns_entry.ns_num = PROC_NS_INUM;
+ break;
+ } else if (!memcmp(dentry->d_name.name, name, len)) {
+ ns_entry.ns_ops = *entry;
+ ns_entry.ns_num = PROC_NS_SNUM;
break;
+ }
}
if (entry == last)
goto out;
- error = proc_ns_instantiate(dir, dentry, task, *entry);
+ error = proc_ns_instantiate(dir, dentry, task, &ns_entry);
out:
put_task_struct(task);
out_no_task:
--
1.7.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH V2 5/6] namespaces: expose ns_entries
2014-05-10 0:27 [PATCH V2 0/6] namespaces: log namespaces per task Richard Guy Briggs
` (3 preceding siblings ...)
2014-05-10 0:27 ` [PATCH V2 4/6] namespaces: expose ns instance serial numbers in proc Richard Guy Briggs
@ 2014-05-10 0:27 ` Richard Guy Briggs
2014-05-10 0:27 ` [PATCH V2 6/6] audit: convert namespace serial number logging to use proc ns_entries Richard Guy Briggs
5 siblings, 0 replies; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-10 0:27 UTC (permalink / raw)
To: linux-audit, linux-kernel, containers
Cc: Richard Guy Briggs, arozansk, serge, ebiederm, eparis, sgrubb
Expose ns_entries so subsystems other than proc can use this set of namespace
operations.
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
fs/proc/namespaces.c | 2 +-
include/linux/proc_ns.h | 1 +
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 40bab47..ac5519f 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -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
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
index aebb3a2..02979ab 100644
--- a/include/linux/proc_ns.h
+++ b/include/linux/proc_ns.h
@@ -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
--
1.7.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH V2 6/6] audit: convert namespace serial number logging to use proc ns_entries
2014-05-10 0:27 [PATCH V2 0/6] namespaces: log namespaces per task Richard Guy Briggs
` (4 preceding siblings ...)
2014-05-10 0:27 ` [PATCH V2 5/6] namespaces: expose ns_entries Richard Guy Briggs
@ 2014-05-10 0:27 ` Richard Guy Briggs
5 siblings, 0 replies; 16+ messages in thread
From: Richard Guy Briggs @ 2014-05-10 0:27 UTC (permalink / raw)
To: linux-audit, linux-kernel, containers
Cc: Richard Guy Briggs, arozansk, serge, ebiederm, eparis, sgrubb
Convert audit direct access to namespace serial numbers to insead use the proc
namespace operations structure which lists all namespace types with a
consistent api.
This should eventually squash down to: [audit: log namespace serial numbers]
(which in turn will need to follow [namespaces: expose ns_entries])
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
kernel/audit.c | 43 ++++++++++++-------------------------------
1 files changed, 12 insertions(+), 31 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index fe783ad..6452278 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -64,15 +64,7 @@
#endif
#include <linux/freezer.h>
#include <linux/tty.h>
-#include <linux/nsproxy.h>
-#include <linux/utsname.h>
-#include <linux/ipc_namespace.h>
-#include "../fs/mount.h"
-#include <linux/mount.h>
-#include <linux/mnt_namespace.h>
-#include <linux/pid_namespace.h>
-#include <net/net_namespace.h>
-#include <linux/user_namespace.h>
+#include <linux/proc_ns.h>
#include <net/netns/generic.h>
#include "audit.h"
@@ -1628,29 +1620,18 @@ void audit_log_session_info(struct audit_buffer *ab)
#ifdef CONFIG_NAMESPACES
void audit_log_namespace_info(struct audit_buffer *ab, struct task_struct *tsk)
{
- struct nsproxy *nsproxy;
-
- rcu_read_lock();
- nsproxy = task_nsproxy(tsk);
- if (nsproxy != NULL) {
- audit_log_format(ab, " mntns=%llx", nsproxy->mnt_ns->serial_num);
-#ifdef CONFIG_NET_NS
- audit_log_format(ab, " netns=%llx", nsproxy->net_ns->serial_num);
-#endif
-#ifdef CONFIG_UTS_NS
- audit_log_format(ab, " utsns=%llx", nsproxy->uts_ns->serial_num);
-#endif
-#ifdef CONFIG_IPC_NS
- audit_log_format(ab, " ipcns=%llx", nsproxy->ipc_ns->serial_num);
-#endif
+ const struct proc_ns_operations **entry;
+ bool end = false;
+
+ if (!tsk)
+ return;
+ 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;
}
-#ifdef CONFIG_PID_NS
- audit_log_format(ab, " pidns=%llx", task_active_pid_ns(tsk)->serial_num);
-#endif
-#ifdef CONFIG_USER_NS
- audit_log_format(ab, " userns=%llx", task_cred_xxx(tsk, user_ns)->serial_num);
-#endif
- rcu_read_unlock();
}
#endif /* CONFIG_NAMESPACES */
--
1.7.1
^ permalink raw reply related [flat|nested] 16+ messages in thread