Skip to contentSkip to conversation

RFC: Containerized syslog (Take II)

PATCH In review Jean-Marc Pigeon 2 participants 3 messages Feb 16, 2010 – Feb 17, 2010 2 messages not in the archive

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

PATCH 1/1 RFC: Containerized syslog (Take II)

Containerized syslog is now part of nsproxy. A new flag CLONE_SYSLOG allow to unshare syslog area.
Main containerized syslog purpose is to allow full container not to leak or compromise hosts syslog data.

---
 include/linux/init_task.h      |    2 +
 include/linux/nsproxy.h        |    2 +
 include/linux/sched.h          |    1 +
 include/linux/syslog.h         |    9 ++--
 include/linux/user_namespace.h |    1 -
 kernel/fork.c                  |    2 +-
 kernel/nsproxy.c               |   18 +++++++-
 kernel/printk.c                |   14 +++---
 kernel/syslog.c                |   84 ++++++++++++++++++++++++++++++++--------
 kernel/user.c                  |    3 -
 kernel/user_namespace.c        |    5 --
 11 files changed, 101 insertions(+), 40 deletions(-)
include/linux/init_task.h +2 -0
index abec69b..30b479e 100644
@@ -11,6 +11,7 @@
 #include <linux/user_namespace.h>
 #include <linux/securebits.h>
 #include <net/net_namespace.h>
+#include <linux/syslog.h>
 
 extern struct files_struct init_files;
 extern struct fs_struct init_fs;
@@ -37,6 +38,7 @@ extern struct nsproxy init_nsproxy;
 	.count		= ATOMIC_INIT(1),				\
 	.uts_ns		= &init_uts_ns,					\
 	.mnt_ns		= NULL,						\
+	.syslog_ns	= &init_kernel_syslog_ns,			\
 	INIT_NET_NS(net_ns)                                             \
 	INIT_IPC_NS(ipc_ns)						\
 }
include/linux/nsproxy.h +2 -0
index 7b370c7..852fed3 100644
@@ -3,6 +3,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/sched.h>
+#include <linux/syslog.h>
 
 struct mnt_namespace;
 struct uts_namespace;
@@ -29,6 +30,7 @@ struct nsproxy {
 	struct mnt_namespace *mnt_ns;
 	struct pid_namespace *pid_ns;
 	struct net 	     *net_ns;
+	struct syslog_ns     *syslog_ns;
 };
 extern struct nsproxy init_nsproxy;
 
include/linux/sched.h +1 -0
index 78efe7c..659cc81 100644
@@ -9,6 +9,7 @@
 #define CLONE_FS	0x00000200	/* set if fs info shared between processes */
 #define CLONE_FILES	0x00000400	/* set if open files shared between processes */
 #define CLONE_SIGHAND	0x00000800	/* set if signal handlers and blocked signals shared */
+#define CLONE_SYSLOG	0x00001000	/* set if we need private syslog (/proc/kmsg)	*/
 #define CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
 #define CLONE_VFORK	0x00004000	/* set if the parent wants the child to wake it up on mm_release */
 #define CLONE_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
include/linux/syslog.h +5 -4
index 98c6898..cdbebee 100644
@@ -3,6 +3,7 @@
 #include	<linux/spinlock_types.h>
 
 struct syslog_ns {
+	struct kref kref;	/*syslog_ns reference count & control			*/
         wait_queue_head_t wait;
 	spinlock_t logbuf_lock;	/* access conflict locker				*/
         unsigned log_start;	/* Index into log_buf: next char to be read by syslog() */
@@ -22,8 +23,8 @@ extern struct syslog_ns init_kernel_syslog_ns;
  * Syslog API
  *
  */
-extern struct syslog_ns *syslog_malloc(unsigned container_buf_len);
-extern struct syslog_ns *syslog_realloc(struct syslog_ns *syslog_ns, unsigned container_buf_len);
-extern struct syslog_ns *syslog_free(struct syslog_ns *syslog);
-extern struct syslog_ns *syslog_get_current(void);
+extern struct syslog_ns *realloc_syslog_ns(struct syslog_ns *syslog_ns, unsigned container_buf_len);
+extern struct syslog_ns *copy_syslog_ns(unsigned long flags,struct syslog_ns *current_syslog_ns);
+extern struct syslog_ns *release_syslog_ns(struct syslog_ns *current_syslog_ns);
+extern struct syslog_ns *get_current_syslog_ns(void);
 #endif /* _LINUX_SYSLOG_H */
include/linux/user_namespace.h +0 -1
index 3d0c73e..cc4f453 100644
@@ -14,7 +14,6 @@ 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;
kernel/fork.c +1 -1
index f88bd98..38c8d8c 100644
@@ -1647,7 +1647,7 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 	err = -EINVAL;
 	if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
 				CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
-				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
+				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET|CLONE_SYSLOG))
 		goto bad_unshare_out;
 
 	/*
kernel/nsproxy.c +15 -3
index 09b4ff9..ff968db 100644
@@ -44,6 +44,8 @@ static inline struct nsproxy *create_nsproxy(void)
 static struct nsproxy *create_new_namespaces(unsigned long flags,
 			struct task_struct *tsk, struct fs_struct *new_fs)
 {
+#define	CONTAINER_BUF_LEN	4096	/*should be enough for container syslog	*/
+
 	struct nsproxy *new_nsp;
 	int err;
 
@@ -80,9 +82,17 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
 		err = PTR_ERR(new_nsp->net_ns);
 		goto out_net;
 	}
-
+	new_nsp->syslog_ns = copy_syslog_ns(flags, tsk->nsproxy->syslog_ns);
+	if (IS_ERR(new_nsp->syslog_ns)) {
+		err = PTR_ERR(new_nsp->syslog_ns);
+		goto out_syslog;
+	}
+	
 	return new_nsp;
 
+out_syslog:
+	if (new_nsp->net_ns) 
+		put_net(new_nsp->net_ns);
 out_net:
 	if (new_nsp->pid_ns)
 		put_pid_ns(new_nsp->pid_ns);
@@ -116,7 +126,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 	get_nsproxy(old_ns);
 
 	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-				CLONE_NEWPID | CLONE_NEWNET)))
+				CLONE_NEWPID | CLONE_NEWNET | CLONE_SYSLOG)))
 		return 0;
 
 	if (!capable(CAP_SYS_ADMIN)) {
@@ -151,6 +161,8 @@ out:
 
 void free_nsproxy(struct nsproxy *ns)
 {
+	if (ns->syslog_ns)
+		ns->syslog_ns=release_syslog_ns(ns->syslog_ns);
 	if (ns->mnt_ns)
 		put_mnt_ns(ns->mnt_ns);
 	if (ns->uts_ns)
@@ -173,7 +185,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
 	int err = 0;
 
 	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-			       CLONE_NEWNET)))
+			       CLONE_NEWNET | CLONE_SYSLOG )))
 		return 0;
 
 	if (!capable(CAP_SYS_ADMIN))
kernel/printk.c +7 -7
index fd0a05c..3c7f213 100644
@@ -148,7 +148,7 @@ static int saved_console_loglevel = -1;
  */
 void log_buf_kexec_setup(void)
 {
-	struct syslog_ns *syslog_ns = syslog_get_current();
+	struct syslog_ns *syslog_ns = get_current_syslog_ns();
 
 	VMCOREINFO_SYMBOL(sys_log_buf);
 	VMCOREINFO_SYMBOL(sys_log_end);
@@ -163,7 +163,7 @@ static int __init log_buf_len_setup(char *str)
 
 	if (size) {
 		size = roundup_pow_of_two(size);
-		(void) syslog_realloc(&init_kernel_syslog_ns,size);
+		(void) realloc_syslog_ns(&init_kernel_syslog_ns,size);
 	}
 	return 1;
 }
@@ -244,7 +244,7 @@ int do_syslog(int type, char __user *buf, int len)
 	int do_clear = 0;
 	char c;
 	int error = 0;
-	struct syslog_ns *syslog_ns = syslog_get_current();
+	struct syslog_ns *syslog_ns = get_current_syslog_ns();
 
 	error = security_syslog(type);
 	if (error)
@@ -638,7 +638,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 {
 	int printed_len = 0;
 	int current_log_level = default_message_loglevel;
-	struct syslog_ns *syslog_ns = syslog_get_current();
+	struct syslog_ns *syslog_ns = get_current_syslog_ns();
 	unsigned long flags;
 	int this_cpu;
 	char *p;
@@ -1012,7 +1012,7 @@ void release_console_sem(void)
 		unsigned long flags;
 		unsigned _con_start, _log_end;
 		unsigned wake_klogd = 0;
-		struct syslog_ns *syslog_ns = syslog_get_current();
+		struct syslog_ns *syslog_ns = get_current_syslog_ns();
 
 		for ( ; ; ) {
 			spin_lock_irqsave(&sys_log_lock, flags);
@@ -1252,7 +1252,7 @@ void register_console(struct console *newcon)
 		 * for us.
 		 */
 
-		struct syslog_ns *syslog_ns = syslog_get_current();
+		struct syslog_ns *syslog_ns = get_current_syslog_ns();
 
 		spin_lock_irqsave(&sys_log_lock, flags);
 		sys_log_con_start = sys_log_start;
@@ -1462,7 +1462,7 @@ void kmsg_dump(enum kmsg_dump_reason reason)
 	const char *s1, *s2;
 	unsigned long l1, l2;
 	unsigned long flags;
-	struct syslog_ns *syslog_ns = syslog_get_current();
+	struct syslog_ns *syslog_ns = get_current_syslog_ns();
 
 	/* Theoretically, the log could move on after we do this, but
 	   there's not a lot we can do about that. The new messages
kernel/syslog.c +68 -16

155 lines not on this page · raw message

kernel/user.c +0 -3
index cb2d4ba..d9bea1f 100644
@@ -23,9 +23,6 @@ struct user_namespace init_user_ns = {
 	.kref = {
 		.refcount	= ATOMIC_INIT(2),
 	},
-#ifdef CONFIG_PRINTK
-	.syslog = &init_kernel_syslog_ns,
-#endif
 	.creator = &root_user
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
kernel/user_namespace.c +0 -5
index 9d8014f..db72d1b 100644
@@ -38,11 +38,6 @@ int create_user_ns(struct cred *new)
 		INIT_HLIST_HEAD(ns->uidhash_table + n);
 
 	
-	ns->syslog = syslog_malloc(CONTAINER_BUF_LEN);
-        if (!ns->syslog) {
-                kfree(ns);
-                return -ENOMEM;
-        }
 	/* Alloc new root user.  */
 	root_user = alloc_uid(ns, 0);
 	if (!root_user) {
Signature · 1 line
1.6.6

A message that is not in the archive (sent off-list or not yet received): 201002161520.o1GFKC6Q013851-X4ZF2iejbABnc3BsFfMrZw@public.gmane.org

#2 lore raw
Quoted 6 lines · Jean-Marc Pigeon

Containerized syslog is now part of nsproxy. A new flag CLONE_SYSLOG allow to unshare syslog area.
Main containerized syslog purpose is to allow full container not to leak or compromise hosts syslog data.

Hi Jean-Marc,

I think this last point deserves significant elaboration. What
does it mean to "not leak or compromise hosts syslog data"? Is it possible to guarantee that we don't leak or is this just a best-effort sort of thing? My hunch is it's the latter. You really must respond to Eric's question of why this is useful. I know it might seem obvious to you but it's not actualy clear. I've found that carefuly explaining my reasoning when it seemed obvious often uncovers hidden assumptions I made and may even suggest problems and/or alternate approaches.

Kernel patch guidelines suggests you should split the patch up so it's one change at a time. One possible way to divide this into a series of patches is:

patch to add krefs
patch to move syslog_ns from user_namespace to nsproxy patch to rename syslog_current_ns() (or whatever) patch to rename X to Y

(There may be better ways to break up the patches -- these just came to mind)

But the krefs patch probably deals with correctness so it should eventually be merged with the first patch (for clean bisectability). The name changes are nice right now, but should also be merged since introducing new code only to change the names later is often pointless. So you're left with:

<modified original patch>
patch to move syslog_ns from user_namespace to nsproxy
...

Each of these patches should have a clear description of why it's
necessary/good -- not just "this patch adds krefs" for example. What problem does adding the krefs solve?

Quoted 13 lines
include/linux/init_task.h +1 -0
index abec69b..30b479e 100644
@@ -11,6 +11,7 @@
 #include <linux/user_namespace.h>
 #include <linux/securebits.h>
 #include <net/net_namespace.h>
+#include <linux/syslog.h>
 
 extern struct files_struct init_files;
 extern struct fs_struct init_fs;

include/linux/init_task.h extern struct nsproxy init_nsproxy; · line 41

Quoted 4 lines
include/linux/init_task.h +1 -0
@@ -37,6 +38,7 @@ extern struct nsproxy init_nsproxy;
 	.count		= ATOMIC_INIT(1),				\
 	.uts_ns		= &init_uts_ns,					\
 	.mnt_ns		= NULL,						\
+	.syslog_ns	= &init_kernel_syslog_ns,			\

s/_kernel_//

(We know it's kernel code..)

<snip>

include/linux/sched.h line 12

Quoted 9 lines
include/linux/sched.h +1 -0
index 78efe7c..659cc81 100644
@@ -9,6 +9,7 @@
 #define CLONE_FS	0x00000200	/* set if fs info shared between processes */
 #define CLONE_FILES	0x00000400	/* set if open files shared between processes */
 #define CLONE_SIGHAND	0x00000800	/* set if signal handlers and blocked signals shared */
+#define CLONE_SYSLOG	0x00001000	/* set if we need private syslog (/proc/kmsg)	*/

Check with Suka on this one -- I seem to recall specific unused CLONE_ flags are, unfortunately, reserved. Otherwise yes, this is the right place and what Serge suggested.

<snip>

Quoted 17 lines
include/linux/user_namespace.h +0 -1
index 3d0c73e..cc4f453 100644
@@ -14,7 +14,6 @@ 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;
kernel/fork.c +0 -0
index f88bd98..38c8d8c 100644

kernel/fork.c SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) · line 1650

Quoted 5 lines
kernel/fork.c +1 -1
@@ -1647,7 +1647,7 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 	err = -EINVAL;
 	if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
 				CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
-				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
+				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET|CLONE_SYSLOG))

You shouldn't be able to unshare syslog -- I think it's a security concern. I think just keeping CLONE_SYSLOG out of this set is sufficient for sys_unshare. There's a corresponding check in clone/clone2/eclone which would be similar to how CLONE_NEWPID is privileged.

Quoted 45 lines
kernel/fork.c +0 -0
 		goto bad_unshare_out;
 
 	/*
kernel/nsproxy.c +12 -2
index 09b4ff9..ff968db 100644
@@ -44,6 +44,8 @@ static inline struct nsproxy *create_nsproxy(void)
 static struct nsproxy *create_new_namespaces(unsigned long flags,
 			struct task_struct *tsk, struct fs_struct *new_fs)
 {
+#define	CONTAINER_BUF_LEN	4096	/*should be enough for container syslog	*/
+
 	struct nsproxy *new_nsp;
 	int err;
 
@@ -80,9 +82,17 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
 		err = PTR_ERR(new_nsp->net_ns);
 		goto out_net;
 	}
-
+	new_nsp->syslog_ns = copy_syslog_ns(flags, tsk->nsproxy->syslog_ns);
+	if (IS_ERR(new_nsp->syslog_ns)) {
+		err = PTR_ERR(new_nsp->syslog_ns);
+		goto out_syslog;
+	}
+	
 	return new_nsp;
 
+out_syslog:
+	if (new_nsp->net_ns) 
+		put_net(new_nsp->net_ns);
 out_net:
 	if (new_nsp->pid_ns)
 		put_pid_ns(new_nsp->pid_ns);
@@ -116,7 +126,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 	get_nsproxy(old_ns);
 
 	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-				CLONE_NEWPID | CLONE_NEWNET)))
+				CLONE_NEWPID | CLONE_NEWNET | CLONE_SYSLOG)))
 		return 0;
 
 	if (!capable(CAP_SYS_ADMIN)) {

kernel/nsproxy.c out: · line 165

Quoted 5 lines
kernel/nsproxy.c +2 -0
@@ -151,6 +161,8 @@ out:
 
 void free_nsproxy(struct nsproxy *ns)
 {
+	if (ns->syslog_ns)
+		ns->syslog_ns=release_syslog_ns(ns->syslog_ns);

style: space around the assignment operator.
See the kernel Documentation on contributing patches and the style of kernel code -- those are our standards too. scripts/checkpatch.pl will also find many of these things for you.

kernel/nsproxy.c int unshare_nsproxy_namespaces(unsigned long unshare_flags, · line 188

Quoted 9 lines
kernel/nsproxy.c +1 -1
 	if (ns->mnt_ns)
 		put_mnt_ns(ns->mnt_ns);
 	if (ns->uts_ns)
@@ -173,7 +185,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
 	int err = 0;
 
 	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-			       CLONE_NEWNET)))
+			       CLONE_NEWNET | CLONE_SYSLOG )))

You shouldn't be able to unshare syslog. It should require using a privileged clone() call like CLONE_NEWPID. So CLONE_SYSLOG doesn't belong here I think.

Quoted 17 lines
kernel/nsproxy.c +0 -0
 		return 0;
 
 	if (!capable(CAP_SYS_ADMIN))
kernel/printk.c +1 -1
index fd0a05c..3c7f213 100644
@@ -148,7 +148,7 @@ static int saved_console_loglevel = -1;
  */
 void log_buf_kexec_setup(void)
 {
-	struct syslog_ns *syslog_ns = syslog_get_current();
+	struct syslog_ns *syslog_ns = get_current_syslog_ns();
 
 	VMCOREINFO_SYMBOL(sys_log_buf);
 	VMCOREINFO_SYMBOL(sys_log_end);

kernel/printk.c static int __init log_buf_len_setup(char *str) · line 166

Quoted 5 lines
kernel/printk.c +1 -1
@@ -163,7 +163,7 @@ static int __init log_buf_len_setup(char *str)
 
 	if (size) {
 		size = roundup_pow_of_two(size);
-		(void) syslog_realloc(&init_kernel_syslog_ns,size);
+		(void) realloc_syslog_ns(&init_kernel_syslog_ns,size);

style: The namechange looks fine. The (void) cast does not.

Quoted 22 lines
kernel/printk.c +2 -2
 	}
 	return 1;
 }
@@ -244,7 +244,7 @@ int do_syslog(int type, char __user *buf, int len)
 	int do_clear = 0;
 	char c;
 	int error = 0;
-	struct syslog_ns *syslog_ns = syslog_get_current();
+	struct syslog_ns *syslog_ns = get_current_syslog_ns();
 
 	error = security_syslog(type);
 	if (error)
@@ -638,7 +638,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 {
 	int printed_len = 0;
 	int current_log_level = default_message_loglevel;
-	struct syslog_ns *syslog_ns = syslog_get_current();
+	struct syslog_ns *syslog_ns = get_current_syslog_ns();
 	unsigned long flags;
 	int this_cpu;
 	char *p;

kernel/printk.c void release_console_sem(void) · line 1015

Quoted 5 lines
kernel/printk.c +1 -1
@@ -1012,7 +1012,7 @@ void release_console_sem(void)
 		unsigned long flags;
 		unsigned _con_start, _log_end;
 		unsigned wake_klogd = 0;
-		struct syslog_ns *syslog_ns = syslog_get_current();
+		struct syslog_ns *syslog_ns = get_current_syslog_ns();

In kernel code, especially namespaces, "get" implies taking an extra reference. So get_current_syslog_ns() needs a different name. I'd name it like the pid
namespace: anything without _ns on the end uses "current".

kernel/printk.c void register_console(struct console *newcon) · line 1255

Quoted 9 lines
kernel/printk.c +1 -1
 		for ( ; ; ) {
 			spin_lock_irqsave(&sys_log_lock, flags);
@@ -1252,7 +1252,7 @@ void register_console(struct console *newcon)
 		 * for us.
 		 */
 
-		struct syslog_ns *syslog_ns = syslog_get_current();
+		struct syslog_ns *syslog_ns = get_current_syslog_ns();

I don't think current necessarily has the relevant syslog_ns here. Current will probably be the tasks involved in device coldplugging -- not the tasks that will be using the console for output. Console/tty code is especially tricky as I recall. This needs more review from someone more familiar with that area I think.

Quoted 19 lines
kernel/printk.c +1 -1
 		spin_lock_irqsave(&sys_log_lock, flags);
 		sys_log_con_start = sys_log_start;
@@ -1462,7 +1462,7 @@ void kmsg_dump(enum kmsg_dump_reason reason)
 	const char *s1, *s2;
 	unsigned long l1, l2;
 	unsigned long flags;
-	struct syslog_ns *syslog_ns = syslog_get_current();
+	struct syslog_ns *syslog_ns = get_current_syslog_ns();
 
 	/* Theoretically, the log could move on after we do this, but
 	   there's not a lot we can do about that. The new messages
kernel/syslog.c +0 -0
index 69d30a9..0088a85 100644
@@ -22,35 +22,66 @@
  *
  */

kernel/syslog.c line 33

Quoted 10 lines
kernel/syslog.c +3 -0
 
+#include <linux/module.h>
 #include <linux/bootmem.h>
 #include <linux/slab.h>
 #include <linux/cred.h>
+#include <linux/kref.h>
 #include <linux/user_namespace.h>
 #include <linux/syslog.h>
 
+#ifdef CONFIG_PRINTK

Shouldn't syslog.c only be compiled if CONFIG_PRINTK is defined? That's a patch to the kernel/Makefile:

obj-$(CONFIG_PRINTK) += syslog.o

Then I think you can avoid this #ifdef entirely.

kernel/syslog.c line 37

Quoted 7 lines
kernel/syslog.c +0 -2
 /*
  * Static memory definition, used to assign a syslog
  * to the kernel itself
  *
  */
-
-#ifdef CONFIG_PRINTK

I suppose. Again, not a substantial change. To me the comment is unnecessary. This init_foo_ns pattern is quite recognizable to anyone familiar with how things are initialized in the kernel.

Quoted 16 lines
kernel/syslog.c +6 -0
 #define __LOG_BUF_LEN   (1 << CONFIG_LOG_BUF_SHIFT)
 
 static char __log_buf[__LOG_BUF_LEN];
 
 struct syslog_ns init_kernel_syslog_ns = {
+	.kref = {
+		.refcount	= ATOMIC_INIT(2),
+	},
         .wait = __WAIT_QUEUE_HEAD_INITIALIZER(init_kernel_syslog_ns.wait),
         .buf_len = __LOG_BUF_LEN,
         .buf = __log_buf
 };
+EXPORT_SYMBOL_GPL(init_kernel_syslog_ns);
 #endif
+/*
+ * Procedure to free all ressources tied to syslog

kernel/syslog.c line 64

Quoted 10 lines
kernel/syslog.c +10 -0
+ *
+ */
+struct syslog_ns *syslog_free(struct syslog_ns *syslog)
+
+{
+	if (syslog != (struct syslog_ns *)0) {
+		(void) kfree(syslog->buf);
+		(void) kfree(syslog);
+		syslog = (struct syslog_ns *)0;
+		}

Ugh. Please run your stuff through checkpatch before the next posting.

Quoted 11 lines
kernel/syslog.c +9 -0
+	return syslog;
+}
 
 /*
+ * Procedure to interface kref _put with syslog_free
+ *
+ */
+static void syslog_out(struct kref *kref)
+
+{
+	struct syslog_ns *sl;

kernel/syslog.c line 84

Quoted 10 lines
kernel/syslog.c +6 -1
+
+	sl=container_of(kref, struct syslog_ns, kref);	
+	sl=syslog_free(sl);
+}
+/*
  * Procedure to assign memory for syslog area
  *
  */
-struct syslog_ns * syslog_malloc(unsigned container_buf_len)
+static struct syslog_ns * malloc_syslog_ns(unsigned container_buf_len)

For namespaces we've been using "create" rather than foo_[m]alloc. create_pid_namespace, create_user_ns, create_uts_ns, etc.

Quoted 13 lines
kernel/syslog.c +2 -0
 {
 	struct syslog_ns *ns;
 
@@ -61,6 +92,8 @@ struct syslog_ns * syslog_malloc(unsigned container_buf_len)
 	if (!ns)
 		return ERR_PTR(-ENOMEM);
 
+	(void) kref_init(&(ns->kref));
+
 	ns->buf_len = container_buf_len;
 	ns->buf = kzalloc(container_buf_len, GFP_KERNEL);
 	if (!ns->buf) {

kernel/syslog.c struct syslog_ns * syslog_malloc(unsigned container_buf_len) · line 113

Quoted 5 lines
kernel/syslog.c +1 -1
@@ -77,7 +110,7 @@ struct syslog_ns * syslog_malloc(unsigned container_buf_len)
  * If syslog_ns is NULL, assign a brand new syslog_ns
  *
  */
-struct syslog_ns * syslog_realloc(struct syslog_ns *syslog_ns, unsigned container_buf_len)
+struct syslog_ns * realloc_syslog_ns(struct syslog_ns *syslog_ns, unsigned container_buf_len)

Does this change the syslog_ns pointer, or just the buffer size? If the latter then resize might be a better word.

Quoted 58 lines
kernel/syslog.c +27 -9
 {
 	if ((syslog_ns == &init_kernel_syslog_ns ) && (container_buf_len > syslog_ns->buf_len)) {
@@ -102,7 +135,7 @@ struct syslog_ns * syslog_realloc(struct syslog_ns *syslog_ns, unsigned containe
 			(void) free_bootmem((unsigned long)old_buf, old_buf_len);
 		}
 	if (!syslog_ns)
-		return syslog_malloc(container_buf_len);
+		return malloc_syslog_ns(container_buf_len);
 	if (syslog_ns->buf_len > container_buf_len) {
 		(void) printk(KERN_WARNING "log_buf_len: Not allowed to decrease syslog buffer\n");
 		return ERR_PTR(-EINVAL);
@@ -126,32 +159,51 @@ struct syslog_ns * syslog_realloc(struct syslog_ns *syslog_ns, unsigned containe
 	(void) printk(KERN_NOTICE "log_buf_len: %u\n", syslog_ns->buf_len);
 	return syslog_ns;
 }
+
 /*
- * Procedure to free all ressources tied to syslog
+ * Procedure to use current syslog unless a CLONE_SYSLOG is set
+ * such a new syslog area is defined and used
  *
  */
-struct syslog_ns *syslog_free(struct syslog_ns *syslog)
+struct syslog_ns *copy_syslog_ns(unsigned long flags,struct syslog_ns *current_syslog_ns)
 
 {
-	if (syslog != (struct syslog_ns *)0) {
-		(void) kfree(syslog->buf);
-		(void) kfree(syslog);
-		syslog = (struct syslog_ns *)0;
-		}
-	return syslog;
+#define	CONTAINER_BUF_LEN	4096	/*should be enough for container syslog	*/
+
+	BUG_ON(!current_syslog_ns);
+	if ((flags & CLONE_SYSLOG) == 0) /*incrementing usage reference count	*/
+		(void) kref_get(&(current_syslog_ns->kref));
+	else
+		current_syslog_ns=malloc_syslog_ns(CONTAINER_BUF_LEN);
+	return current_syslog_ns;
+	
+}
+
+/*
+ * Procedure to decrement syslog usage count and free memory
+ * if syslog usage count reach zero.
+ *
+ */
+struct syslog_ns *release_syslog_ns(struct syslog_ns *current_syslog_ns)
+
+{
+	if (kref_put(&(current_syslog_ns->kref), syslog_out)==0)
+	   current_syslog_ns=(struct syslog_ns *)0;
+	return current_syslog_ns;
 }
 
 /*

kernel/syslog.c struct syslog_ns * syslog_realloc(struct syslog_ns *syslog_ns, unsigned containe · line 203

Quoted 10 lines
kernel/syslog.c +3 -2
- * Procedure to get the current syslog area linked to a container (by CLONE_USER)
+ * Procedure to get the current syslog area linked to a container (by CLONE_SYSLOG)
  * if trouble, pin down the problem before it propagate.
  *
  */
-struct syslog_ns *syslog_get_current(void) 
+struct syslog_ns *get_current_syslog_ns(void) 
 
 {
+

Whitespace changes mixed with other changes are also frowned upon. This one is totally unnecessary.

So please read up on kernel style and patch submission. Please use checkpatch.pl Please break up your patch where it's logical to do so.

Cheers,
-Matt Helsley

A message that is not in the archive (sent off-list or not yet received): 20100216235909.GB3604-52DBMbEzqgQ/wnmkkaCWp/[email protected]

#4 lore raw

Bonjour Matt,

Thanks for comments. your time is really appreciated.

Quoted 8 lines · Matt Helsley

I think this last point deserves significant elaboration. What
does it mean to "not leak or compromise hosts syslog data"? Is it possible to guarantee that we don't leak or is this just a best-effort sort of thing? My hunch is it's the latter. You really must respond to Eric's question of why this is useful. I know it might seem obvious to you but it's not actualy clear. I've found that carefuly explaining my reasoning when it seemed obvious often uncovers hidden assumptions I made and may even suggest problems and/or alternate approaches.

You are right, I'll try to give a better rational when posting patches next time.

Quoted 11 lines

Kernel patch guidelines suggests you should split the patch up so it's one change at a time. One possible way to divide this into a series of patches is:

patch to add krefs
patch to move syslog_ns from user_namespace to nsproxy patch to rename syslog_current_ns() (or whatever) patch to rename X to Y

(There may be better ways to break up the patches -- these just came to mind)

In this case I disagree.
First patch posted is patch to previous (working set) to try to follow Serge suggestion, I should have send both part instead only the last one (not very confortable yet with git).

Patch proposed is a complet set needed to reach a working stage, there is nothing achieved if cut patch in slice, nobody can say it is (not)working without the full patch set...

Quoted 5 lines

Check with Suka on this one -- I seem to recall specific unused CLONE_ flags are, unfortunately, reserved. Otherwise yes, this is the right place and what Serge suggested.

	This very CLONE_SYSLOG 0x0001000 flag was suggested by Serge
	too.
Quoted 1 line

[...]

Quoted 5 lines

You shouldn't be able to unshare syslog -- I think it's a security concern. I think just keeping CLONE_SYSLOG out of this set is sufficient for sys_unshare. There's a corresponding check in clone/clone2/eclone which would be similar to how CLONE_NEWPID is privileged.

We must be able to unshare syslog, this the whole point of the exercice. (to make sure about understanding, unshare means "I, process xyz, want to replace current syslog buffer with
my own".

My personal feeling it shouldn't be a CLONE_SYSLOG, but rather going with a more generic as CLONE_NEWPID.

[...]

Quoted 6 lines

kernel/nsproxy.c out: · line 165

Quoted 1 line
kernel/nsproxy.c +1 -0
+		ns->syslog_ns=release_syslog_ns(ns->syslog_ns);

style: space around the assignment operator.
See the kernel Documentation on contributing patches and the style of kernel code -- those are our standards too. scripts/checkpatch.pl will also find many of these things for you.

Tried to keep local standard, seems my personal way to write code find their way....
Thanks for the pointer scripts/checkpatch.pl

[..[ CLONE_NEWNET | CLONE_SYSLOG )))

Quoted 3 lines

You shouldn't be able to unshare syslog. It should require using a privileged clone() call like CLONE_NEWPID. So CLONE_SYSLOG doesn't belong here I think.

If you mean we shouldn't be able to unshare syslog in specific, but link unsharing to another CLONE flag I agree. NEWPID seems to be an excellent candidate....
But question... what is the best way to reach consensus on this project??? seems everybody is not in pace with the other.

Quoted 4 lines

In kernel code, especially namespaces, "get" implies taking an extra reference. So get_current_syslog_ns() needs a different name. I'd name it like the pid
namespace: anything without _ns on the end uses "current".

OK, point taken about "get", I'll check about pid_namespace.

Quoted 4 lines

obj-$(CONFIG_PRINTK) += syslog.o

Then I think you can avoid this #ifdef entirely.

Interesting, I was not satisfied with my #ifdef, that should clean the code, Thanks.

Quoted 12 lines

kernel/syslog.c line 37

Quoted 8 lines

/*
* Static memory definition, used to assign a syslog
* to the kernel itself
*
*/

kernel/syslog.c +0 -2
-
-#ifdef CONFIG_PRINTK

I suppose. Again, not a substantial change. To me the comment is unnecessary. This init_foo_ns pattern is quite recognizable to anyone familiar with how things are initialized in the kernel.

Well, just notice, for a guy looking at the kernel, I won't call it "cristal clear" (I know it is now an old code), a little bit of help is not that bad. I understand it is not good to write 100 lines of explanation for 10 lines of code, but data pointer are not that bad.
syslog need to be unshared is crystal clear for VZ real user, but you need some data pointer to figure it out (no offense :-}}}).

Quoted 5 lines

kernel/syslog.c line 84

Quoted 2 lines
kernel/syslog.c +1 -1
-struct syslog_ns * syslog_malloc(unsigned container_buf_len)
+static struct syslog_ns * malloc_syslog_ns(unsigned container_buf_len)

For namespaces we've been using "create" rather than foo_[m]alloc. create_pid_namespace, create_user_ns, create_uts_ns, etc.

My understanding of "create" it doesn't assign memory space each time....syslog_malloc does and I was keeping myself here to the malloc standard library routine. (and malloc_syslog_ns is static, which should give me
a little bit of freedom).

{..]

Quoted 4 lines
Quoted 1 line

+struct syslog_ns * realloc_syslog_ns(struct syslog_ns *syslog_ns, unsigned container_buf_len)

Does this change the syslog_ns pointer, or just the buffer size? If the latter then resize might be a better word.

good idea.

Signature · 14 lines
A bientôt
==========================================================================
Jean-Marc Pigeon                                   Internet: [email protected]
SAFE Inc.                                          Phone: (514) 493-4280
                                                   Fax:   (514) 493-1946
        Clement, 'a kiss solution' to get rid of SPAM (at last)
           Clement' Home base <"http://www.clement.safe.ca">
==========================================================================


_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers