Another reason this is bogus, confirmed by Jean-Marc's testing:
printk is called too often without valid 'current', i.e. when
network packets arrive and are processed. So we should send output
of sys_syslog() to current's ring buffer, all printks to the
init_syslog_ns, and then we can use ns_printk(syslog_ns, fmt, ...)
for targeted printks.
And, as discussed on irc, we'll make syslog_ns a full namespace
in its own right, use the last remaining clone flag (if there is
one) or build on top of eclone(). It'd be nicer to have a 'real'
clone flag so we can also unshare(CLONE_NEWLOG).
-serge
Quoting Serge E. Hallyn (se...@us.ibm.com):
Provide each user namespace with its own syslog ringbuffer.
So you can do
ns_exec -cU /bin/bash
dmesg
and see nothing. Root in a container (with private user namespace)
cannot clear the host's ring buffer.
Since containers do not have a notion of consoles at present,
only the initial user namespace deals with console output or
with the console-related syslog commands.
This opens the door to targetting printk at certain syslog
namespaces. It's not safe to be applied - it's a quick-n-dirty
hack and won't even compile for CONFIG_PRINTK=n. Also I've not decided
what to do about duplication of printks to init_user_ns so for
now emit_one_char always duplicates to inti_user_ns. We probably
want to be smarter about this and output a prefix indicating the
target.
But I figured discussions about the API would be more meaningful
with a testable patch.
---
fs/proc/kmsg.c |5 +-
include/linux/user_namespace.h |2 +
kernel/printk.c| 225
++--
kernel/user.c |4 +
kernel/user_namespace.c| 13 +++
5 files changed, 168 insertions(+), 81 deletions(-)
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 7ca7834..2746b70 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -12,11 +12,12 @@
#include linux/poll.h
#include linux/proc_fs.h
#include linux/fs.h
+#include linux/syslog.h
#include asm/uaccess.h
#include asm/io.h
-extern wait_queue_head_t log_wait;
+extern struct syslog_ns init_syslog_ns;
extern int do_syslog(int type, char __user *bug, int count);
@@ -41,7 +42,7 @@ static ssize_t kmsg_read(struct file *file, char __user
*buf,
static unsigned int kmsg_poll(struct file *file, poll_table *wait)
{
- poll_wait(file, log_wait, wait);
+ poll_wait(file, init_syslog_ns.wait, wait);
if (do_syslog(9, NULL, 0))
return POLLIN | POLLRDNORM;
return 0;
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index cc4f453..3926c89 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -5,6 +5,7 @@
#include linux/nsproxy.h
#include linux/sched.h
#include linux/err.h
+#include linux/syslog.h
#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
#define UIDHASH_SZ (1 UIDHASH_BITS)
@@ -14,6 +15,7 @@ struct user_namespace {
struct hlist_head uidhash_table[UIDHASH_SZ];
struct user_struct *creator;
struct work_struct destroyer;
+ struct syslog_ns*syslog;
};
extern struct user_namespace init_user_ns;
diff --git a/kernel/printk.c b/kernel/printk.c
index 1751c45..5b93447 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -35,9 +35,18 @@
#include linux/kexec.h
#include linux/ratelimit.h
#include linux/kmsg_dump.h
+#include linux/user_namespace.h
#include asm/uaccess.h
+struct syslog_ns init_syslog_ns;
+#define g_log_wait (init_syslog_ns.wait)
+#define g_log_start (init_syslog_ns.start)
+#define g_log_end (init_syslog_ns.end)
+#define g_log_buf_len (init_syslog_ns.buf_len)
+#define g_logged_chars (init_syslog_ns.logged_chars)
+#define g_log_buf (init_syslog_ns.buf)
+
/*
* for_each_console() allows you to iterate on each console
*/
@@ -52,6 +61,7 @@ void asmlinkage __attribute__((weak)) early_printk(const
char *fmt, ...)
}
#define __LOG_BUF_LEN(1 CONFIG_LOG_BUF_SHIFT)
+#define CONTAINER_BUF_LEN 4096
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
@@ -60,8 +70,6 @@ void asmlinkage __attribute__((weak)) early_printk(const
char *fmt, ...)
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG
*/
-DECLARE_WAIT_QUEUE_HEAD(log_wait);
-
int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */
DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
@@ -98,22 +106,20 @@ EXPORT_SYMBOL_GPL(console_drivers);
static int console_locked, console_suspended;
/*
- * logbuf_lock protects log_buf, log_start, log_end, con_start and
logged_chars
+ * logbuf_lock protects g_log_buf, g_log_start, g_log_end,