Skip to contentSkip to conversation

syslog ns proof of concept

RFC PATCH In review Serge Hallyn 3 participants 5 messages Nov 17, 2012 – Nov 19, 2012 3 messages not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 syslog ns proof of concept

Introduce a system log namespace. The syslog ns is tied to a user namespace. You must create a new user namespace before you can create a new sylog ns. The syslog ns is created through a new command (11) to the __NR_syslog system call.

Once a task enters a new syslog ns, it's "dmesg", "dmesg -c" and /dev/kmsg actions affect only itself, so that user-created syslog messages no longer are confusingly combined in the host's syslog. "printk" itself always goes to the initial syslog_ns, and consoles belong only to the initial syslog_ns. However printks relating to a specific network namespace, for instance, can now be targeted to the syslog ns for the user ns which owns the network ns, aiding in debugging in a container.

This patch is on top of the user namespace enhanced kernel at
git://kernel.ubuntu.com/serge/quantal-userns. It is good enough to compile with stock ubuntu kernel options, boot, launch other syslog namespaces and exercise them. It will need help before it will compile with funky options like CONFIG_PRINTK=n. This is only being sent out to get feedback on the general idea.

Comments greatly appreciated.

(See https://wiki.ubuntu.com/LxcSyslogNs for background).

---
 fs/proc/kmsg.c                 |   12 +-
 include/linux/printk.h         |    1 -
 include/linux/syslog.h         |   70 +++++-
 include/linux/user_namespace.h |    1 +
 kernel/printk.c                |  530 +++++++++++++++++++++++-----------------
 kernel/sysctl.c                |    3 +-
 kernel/user.c                  |    3 +
 kernel/user_namespace.c        |    3 +
 8 files changed, 392 insertions(+), 231 deletions(-)
fs/proc/kmsg.c +7 -5
index bd4b5a7..3ba594c 100644
@@ -13,6 +13,8 @@
 #include <linux/proc_fs.h>
 #include <linux/fs.h>
 #include <linux/syslog.h>
+#include <linux/cred.h>
+#include <linux/user_namespace.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -21,12 +23,12 @@ extern wait_queue_head_t log_wait;
 
 static int kmsg_open(struct inode * inode, struct file * file)
 {
-	return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_FILE);
+	return do_syslog(file->f_cred->user_ns->syslog_ns, SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_FILE);
 }
 
 static int kmsg_release(struct inode * inode, struct file * file)
 {
-	(void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_FILE);
+	(void) do_syslog(file->f_cred->user_ns->syslog_ns, SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_FILE);
 	return 0;
 }
 
@@ -34,15 +36,15 @@ static ssize_t kmsg_read(struct file *file, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	if ((file->f_flags & O_NONBLOCK) &&
-	    !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
+	    !do_syslog(file->f_cred->user_ns->syslog_ns, SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
 		return -EAGAIN;
-	return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_FILE);
+	return do_syslog(file->f_cred->user_ns->syslog_ns, SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_FILE);
 }
 
 static unsigned int kmsg_poll(struct file *file, poll_table *wait)
 {
 	poll_wait(file, &log_wait, wait);
-	if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
+	if (do_syslog(file->f_cred->user_ns->syslog_ns, SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
 		return POLLIN | POLLRDNORM;
 	return 0;
 }
include/linux/printk.h +0 -1
index 9afc01e..70f8380 100644
@@ -134,7 +134,6 @@ extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
 				   unsigned int interval_msec);
 
 extern int printk_delay_msec;
-extern int dmesg_restrict;
 extern int kptr_restrict;
 
 void log_buf_kexec_setup(void);
include/linux/syslog.h +69 -1

78 lines not on this page · raw message

include/linux/user_namespace.h +1 -0
index b9bd2e6..8aebb8b 100644
@@ -26,6 +26,7 @@ struct user_namespace {
 	kuid_t			owner;
 	kgid_t			group;
 	unsigned int		proc_inum;
+	struct syslog_ns	*syslog_ns;
 };
 
 extern struct user_namespace init_user_ns;
kernel/printk.c +307 -223

1,117 lines not on this page · raw message

kernel/sysctl.c +2 -1
index 26f65ea..3d5f19f 100644
@@ -61,6 +61,7 @@
 #include <linux/kmod.h>
 #include <linux/capability.h>
 #include <linux/binfmts.h>
+#include <linux/syslog.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
@@ -712,7 +713,7 @@ static struct ctl_table kern_table[] = {
 	},
 	{
 		.procname	= "dmesg_restrict",
-		.data		= &dmesg_restrict,
+		.data		= &init_syslog_ns.dmesg_restrict,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_minmax_sysadmin,
kernel/user.c +3 -0
index 33acb5e..bd176cc 100644
@@ -18,6 +18,8 @@
 #include <linux/user_namespace.h>
 #include <linux/proc_fs.h>
 
+struct syslog_ns;
+extern struct syslog_ns init_syslog_ns;
 /*
  * userns count is 1 for root user, 1 for init_uts_ns,
  * and 1 for... ?
@@ -53,6 +55,7 @@ struct user_namespace init_user_ns = {
 	.owner = GLOBAL_ROOT_UID,
 	.group = GLOBAL_ROOT_GID,
 	.proc_inum = PROC_USER_INIT_INO,
+	.syslog_ns = &init_syslog_ns,
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
 
kernel/user_namespace.c +3 -0
index dafa125..f62c8a9 100644
@@ -21,6 +21,7 @@
 #include <linux/uaccess.h>
 #include <linux/ctype.h>
 #include <linux/projid.h>
+#include <linux/syslog.h>
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 
@@ -84,6 +85,7 @@ int create_user_ns(struct cred *new)
 	ns->owner = owner;
 	ns->group = group;
 
+	ns->syslog_ns = get_syslog_ns(parent_ns->syslog_ns);
 
 	/* Leave the new user namespace reference ns on new */
 	set_cred_user_ns(new, ns);
@@ -111,6 +113,7 @@ void free_user_ns(struct kref *kref)
 	struct user_namespace *parent, *ns =
 		container_of(kref, struct user_namespace, kref);
 
+	put_syslog_ns(ns->syslog_ns);
 	parent = ns->parent;
 	proc_free_inum(ns->proc_inum);
 	kmem_cache_free(user_ns_cachep, ns);
Signature · 1 line
1.7.10.4
#1 lore raw
Quoted 21 lines · Serge Hallyn

Introduce a system log namespace. The syslog ns is tied to a user namespace. You must create a new user namespace before you can create a new sylog ns. The syslog ns is created through a new command (11) to the __NR_syslog system call.

Once a task enters a new syslog ns, it's "dmesg", "dmesg -c" and /dev/kmsg actions affect only itself, so that user-created syslog messages no longer are confusingly combined in the host's syslog. "printk" itself always goes to the initial syslog_ns, and consoles belong only to the initial syslog_ns. However printks relating to a specific network namespace, for instance, can now be targeted to the syslog ns for the user ns which owns the network ns, aiding in debugging in a container.

This patch is on top of the user namespace enhanced kernel at
git://kernel.ubuntu.com/serge/quantal-userns. It is good enough to compile with stock ubuntu kernel options, boot, launch other syslog namespaces and exercise them. It will need help before it will compile with funky options like CONFIG_PRINTK=n. This is only being sent out to get feedback on the general idea.

Quoted 3 lines

Comments greatly appreciated.

(See https://wiki.ubuntu.com/LxcSyslogNs for background).

Overall I would say the goal sounds well thought out.

I am not a fan of how this ties into the user namespace. I would prefer closer or looser ties. The recursive reference count loop where a userns refers to a syslogns and that syslogns refers to the same userns is unpleasant.

The important case as I understand it is to handle injection of messages into dmesg by userspace?

I would really like to see how messages from networking devices and netfilter would be handled. Right now one of the ugliest bits of lowering the permissions in the network namespace is what do about the commands that set the message loglevel.

In general unless we can safely and sanely direct kernel messages into this new dmesg I don't actually see the point of having another ring buffer in the kernel. If the only success is userspace having the syslog facility simply be unavailable seems more palatable.

Eric

A message that is not in the archive (sent off-list or not yet received): 87haoo3opt.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]

#3 lore raw
Quoted 25 lines · Eric W. Biederman
Quoted 23 lines · Serge Hallyn

Introduce a system log namespace. The syslog ns is tied to a user namespace. You must create a new user namespace before you can create a new sylog ns. The syslog ns is created through a new command (11) to the __NR_syslog system call.

Once a task enters a new syslog ns, it's "dmesg", "dmesg -c" and /dev/kmsg actions affect only itself, so that user-created syslog messages no longer are confusingly combined in the host's syslog. "printk" itself always goes to the initial syslog_ns, and consoles belong only to the initial syslog_ns. However printks relating to a specific network namespace, for instance, can now be targeted to the syslog ns for the user ns which owns the network ns, aiding in debugging in a container.

This patch is on top of the user namespace enhanced kernel at
git://kernel.ubuntu.com/serge/quantal-userns. It is good enough to compile with stock ubuntu kernel options, boot, launch other syslog namespaces and exercise them. It will need help before it will compile with funky options like CONFIG_PRINTK=n. This is only being sent out to get feedback on the general idea.

Comments greatly appreciated.

Quoted 8 lines
Quoted 1 line

(See https://wiki.ubuntu.com/LxcSyslogNs for background).

Overall I would say the goal sounds well thought out.

I am not a fan of how this ties into the user namespace. I would prefer closer or looser ties. The recursive reference count loop where a userns refers to a syslogns and that syslogns refers to the same userns is unpleasant.

We could make the nsproxy point to the syslog_ns, but this seemed simpler. Note that the syslog_ns does not need to pin the user_ns, since by design the user_ns owning a syslog_ns can't go away if the syslog_ns is still alive.

But yes, the question of "what should point to the syslog_ns" is what has kept a syslog_ns from being seriously proposed since february 2010 :)

Hm, wait. A nagging feeling made me look back, and I see that I do in fact pin the user_ns from the syslog_ns. I didn't mean to (and I don't release it :) and we don't need to. When a syslog_ns is created, it can only be inherited by child user_ns's, and its owner, the parent user_ns, can never go away until the child user_ns's go away.

Quoted 2 lines

The important case as I understand it is to handle injection of messages into dmesg by userspace?

1. injection of messages into dmesg by userspace, 2. clearing of messages by userspace, but also 3. allowing appropriate kernel printks to be targeted to containers.

Quoted 2 lines

I would really like to see how messages from networking devices and netfilter would be handled. Right now one of the ugliest bits of

It would simply replace a

	printk(KERN_NOTICE "doing something\n");
with
	nsprintk(net->user_ns->syslog_ns, KERN_NOTICE "doing something\n");

I'm not yet clear on whether we'd want nsprintk to print to both the init_syslog_ns (with a ns prefix) and the child ns.

Quoted 2 lines

lowering the permissions in the network namespace is what do about the commands that set the message loglevel.

Here I'm not sure what you mean.

Quoted 4 lines

In general unless we can safely and sanely direct kernel messages into this new dmesg I don't actually see the point of having another ring buffer in the kernel. If the only success is userspace having the syslog facility simply be unavailable seems more palatable.

No I didn't do any in this patch, but directing kernel messages into the new dmesg was definately a goal and should be trivial now.

-serge

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

#5 lore raw
Quoted 40 lines · Serge E. Hallyn
Quoted 25 lines · Eric W. Biederman
Quoted 23 lines · Serge Hallyn

Introduce a system log namespace. The syslog ns is tied to a user namespace. You must create a new user namespace before you can create a new sylog ns. The syslog ns is created through a new command (11) to the __NR_syslog system call.

Once a task enters a new syslog ns, it's "dmesg", "dmesg -c" and /dev/kmsg actions affect only itself, so that user-created syslog messages no longer are confusingly combined in the host's syslog. "printk" itself always goes to the initial syslog_ns, and consoles belong only to the initial syslog_ns. However printks relating to a specific network namespace, for instance, can now be targeted to the syslog ns for the user ns which owns the network ns, aiding in debugging in a container.

This patch is on top of the user namespace enhanced kernel at
git://kernel.ubuntu.com/serge/quantal-userns. It is good enough to compile with stock ubuntu kernel options, boot, launch other syslog namespaces and exercise them. It will need help before it will compile with funky options like CONFIG_PRINTK=n. This is only being sent out to get feedback on the general idea.

Comments greatly appreciated.

Quoted 8 lines
Quoted 1 line

(See https://wiki.ubuntu.com/LxcSyslogNs for background).

Overall I would say the goal sounds well thought out.

I am not a fan of how this ties into the user namespace. I would prefer closer or looser ties. The recursive reference count loop where a userns refers to a syslogns and that syslogns refers to the same userns is unpleasant.

We could make the nsproxy point to the syslog_ns, but this seemed simpler. Note that the syslog_ns does not need to pin the user_ns, since by design the user_ns owning a syslog_ns can't go away if the syslog_ns is still alive.

Quoted 8 lines

But yes, the question of "what should point to the syslog_ns" is what has kept a syslog_ns from being seriously proposed since february 2010 :)

Hm, wait. A nagging feeling made me look back, and I see that I do in fact pin the user_ns from the syslog_ns. I didn't mean to (and I don't release it :) and we don't need to. When a syslog_ns is created, it can only be inherited by child user_ns's, and its owner, the parent user_ns, can never go away until the child user_ns's go away.

There is an argument to be made that syslog messages are the kind of security identifiers like uid, gids, and keys that should be part of a user namespace. I'm not fully convinced but there are some DOS attacks that would naturally prevent.

Quoted 10 lines
Quoted 2 lines

The important case as I understand it is to handle injection of messages into dmesg by userspace?

1. injection of messages into dmesg by userspace, 2. clearing of messages by userspace, but also 3. allowing appropriate kernel printks to be targeted to containers.

Quoted 2 lines

I would really like to see how messages from networking devices and netfilter would be handled. Right now one of the ugliest bits of

Quoted 7 lines

It would simply replace a

	printk(KERN_NOTICE "doing something\n");
with
	nsprintk(net->user_ns->syslog_ns, KERN_NOTICE "doing something\n");

I'm not yet clear on whether we'd want nsprintk to print to both the init_syslog_ns (with a ns prefix) and the child ns.

There are some specialized forms of printk like dev_printk and in particular netdev_printk that it would be very interesting if they did the work behind the scenes. So that you could code the obvious thing and it would do the right thing automatically.

Quoted 4 lines
Quoted 2 lines

lowering the permissions in the network namespace is what do about the commands that set the message loglevel.

Here I'm not sure what you mean.

There is a possible DOS attack that by turning on debug messages in a user namespace you can overwhelm syslog.

Quoted 7 lines
Quoted 4 lines

In general unless we can safely and sanely direct kernel messages into this new dmesg I don't actually see the point of having another ring buffer in the kernel. If the only success is userspace having the syslog facility simply be unavailable seems more palatable.

No I didn't do any in this patch, but directing kernel messages into the new dmesg was definately a goal and should be trivial now.

Getting the semantics of which kernel messages should be directed at the new ring buffer and what that means seems to me to be a key factor in seeing how practical this is. Otherwise this seems to call out for a change in userspace.

Certainly inside a user namespace now you can't destructively touch the kernel's syslog at all.

Eric

A message that is not in the archive (sent off-list or not yet received): 87pq3c223i.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]

#7 lore raw
Quoted 51 lines · Eric W. Biederman
Quoted 40 lines · Serge E. Hallyn
Quoted 25 lines · Eric W. Biederman
Quoted 23 lines · Serge Hallyn

Introduce a system log namespace. The syslog ns is tied to a user namespace. You must create a new user namespace before you can create a new sylog ns. The syslog ns is created through a new command (11) to the __NR_syslog system call.

Once a task enters a new syslog ns, it's "dmesg", "dmesg -c" and /dev/kmsg actions affect only itself, so that user-created syslog messages no longer are confusingly combined in the host's syslog. "printk" itself always goes to the initial syslog_ns, and consoles belong only to the initial syslog_ns. However printks relating to a specific network namespace, for instance, can now be targeted to the syslog ns for the user ns which owns the network ns, aiding in debugging in a container.

This patch is on top of the user namespace enhanced kernel at
git://kernel.ubuntu.com/serge/quantal-userns. It is good enough to compile with stock ubuntu kernel options, boot, launch other syslog namespaces and exercise them. It will need help before it will compile with funky options like CONFIG_PRINTK=n. This is only being sent out to get feedback on the general idea.

Comments greatly appreciated.

Quoted 8 lines
Quoted 1 line

(See https://wiki.ubuntu.com/LxcSyslogNs for background).

Overall I would say the goal sounds well thought out.

I am not a fan of how this ties into the user namespace. I would prefer closer or looser ties. The recursive reference count loop where a userns refers to a syslogns and that syslogns refers to the same userns is unpleasant.

We could make the nsproxy point to the syslog_ns, but this seemed simpler. Note that the syslog_ns does not need to pin the user_ns, since by design the user_ns owning a syslog_ns can't go away if the syslog_ns is still alive.

Quoted 8 lines

But yes, the question of "what should point to the syslog_ns" is what has kept a syslog_ns from being seriously proposed since february 2010 :)

Hm, wait. A nagging feeling made me look back, and I see that I do in fact pin the user_ns from the syslog_ns. I didn't mean to (and I don't release it :) and we don't need to. When a syslog_ns is created, it can only be inherited by child user_ns's, and its owner, the parent user_ns, can never go away until the child user_ns's go away.

Quoted 4 lines

There is an argument to be made that syslog messages are the kind of security identifiers like uid, gids, and keys that should be part of a user namespace. I'm not fully convinced but there are some DOS attacks that would naturally prevent.

I can't really think of a good case for not putting the syslogns straight into the userns (i.e. not having a separate syslogns), so I'd say let's go that route.

There is a big locking bug (besides syslog_ns pinning user_ns) in my patch - something needs to be done with struct cont, which pins the syslog_ns. So either when a user_ns is freed we need to flush struct cont if it is pinning this user_ns, or the struct cont should explicitly pin the user_ns.

Quoted 15 lines
Quoted 15 lines
Quoted 2 lines

The important case as I understand it is to handle injection of messages into dmesg by userspace?

1. injection of messages into dmesg by userspace, 2. clearing of messages by userspace, but also 3. allowing appropriate kernel printks to be targeted to containers.

Quoted 2 lines

I would really like to see how messages from networking devices and netfilter would be handled. Right now one of the ugliest bits of

It would simply replace a

	printk(KERN_NOTICE "doing something\n");
with
	nsprintk(net->user_ns->syslog_ns, KERN_NOTICE "doing something\n");
Quoted 7 lines
Quoted 2 lines

I'm not yet clear on whether we'd want nsprintk to print to both the init_syslog_ns (with a ns prefix) and the child ns.

There are some specialized forms of printk like dev_printk and in particular netdev_printk that it would be very interesting if they did the work behind the scenes. So that you could code the obvious thing and it would do the right thing automatically.

Agreed.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

lowering the permissions in the network namespace is what do about the commands that set the message loglevel.

Here I'm not sure what you mean.

There is a possible DOS attack that by turning on debug messages in a user namespace you can overwhelm syslog.

Oh, I see.

Quoted 5 lines
Quoted 5 lines
Quoted 4 lines

In general unless we can safely and sanely direct kernel messages into this new dmesg I don't actually see the point of having another ring buffer in the kernel. If the only success is userspace having the syslog facility simply be unavailable seems more palatable.

Quoted 7 lines
Quoted 2 lines

No I didn't do any in this patch, but directing kernel messages into the new dmesg was definately a goal and should be trivial now.

Getting the semantics of which kernel messages should be directed at the new ring buffer and what that means seems to me to be a key factor in seeing how practical this is. Otherwise this seems to call out for a change in userspace.

Ok, I was hoping that once there was a trivial to use nsprintk the appopriate users would be converted by others :), but I can take a look at converting compelling users before I resend.

Quoted 2 lines

Certainly inside a user namespace now you can't destructively touch the kernel's syslog at all.

That should be true, yes.

thanks,
-serge