All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline
@ 2014-04-02 18:42 Steven Rostedt
  2014-04-02 18:57 ` Linus Torvalds
                   ` (3 more replies)
  0 siblings, 4 replies; 74+ messages in thread
From: Steven Rostedt @ 2014-04-02 18:42 UTC (permalink / raw)
  To: LKML
  Cc: Linus Torvalds, Andrew Morton, Thomas Gleixner, H. Peter Anvin,
	Borislav Petkov, Ingo Molnar, Mel Gorman, Kay Sievers

It has come to our attention that a system running a specific user
space init program will not boot if you add "debug" to the kernel
command line. What happens is that the user space tool parses the
kernel command line, and if it sees "debug" it will spit out so much
information that the system fails to boot. This basically renders the
"debug" option for the kernel useless.

This bug has been reported to the developers of said tool
here:

  https://bugs.freedesktop.org/show_bug.cgi?id=76935

The response is:

"Generic terms are generic, not the first user owns them."

That is, the "debug" statement on the *kernel* command line is not
owned by the kernel just because it was the first user of it, and
they refuse to fix their bug.

Well, my response is, we OWN the kernel command line, and as such, we
can keep the users from seeing stuff on it if we so choose. And with
that, I propose this patch, which hides "debug" from /proc/cmdline,
such that we don't have to worry about tools parsing for it and causing
hardship for those trying to debug the kernel.

Reported-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c
index cbd82df..fdb75f7 100644
--- a/fs/proc/cmdline.c
+++ b/fs/proc/cmdline.c
@@ -5,7 +5,7 @@
 
 static int cmdline_proc_show(struct seq_file *m, void *v)
 {
-	seq_printf(m, "%s\n", saved_command_line);
+	seq_printf(m, "%s\n", proc_command_line);
 	return 0;
 }
 
diff --git a/include/linux/init.h b/include/linux/init.h
index a3ba270..daf978a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -145,6 +145,7 @@ typedef void (*ctor_fn_t)(void);
 extern int do_one_initcall(initcall_t fn);
 extern char __initdata boot_command_line[];
 extern char *saved_command_line;
+extern char *proc_command_line;
 extern unsigned int reset_devices;
 
 /* used by init/main.c */
diff --git a/init/main.c b/init/main.c
index 9c7fd4c..6c2022f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -121,8 +121,10 @@ void (*__initdata late_time_init)(void);
 
 /* Untouched command line saved by arch-specific code. */
 char __initdata boot_command_line[COMMAND_LINE_SIZE];
-/* Untouched saved command line (eg. for /proc) */
+/* Untouched saved command line */
 char *saved_command_line;
+/* Slightly touched command line (for /proc) */
+char *proc_command_line;
 /* Command line for parameter parsing */
 static char *static_command_line;
 /* Command line for per-initcall parameter parsing */
@@ -349,13 +351,44 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { }
  */
 static void __init setup_command_line(char *command_line)
 {
-	saved_command_line =
-		memblock_virt_alloc(strlen(boot_command_line) + 1, 0);
-	initcall_command_line =
-		memblock_virt_alloc(strlen(boot_command_line) + 1, 0);
+	char *str;
+	int len = strlen(boot_command_line);
+
+	saved_command_line = memblock_virt_alloc(len + 1, 0);
+	initcall_command_line = memblock_virt_alloc(len + 1, 0);
 	static_command_line = memblock_virt_alloc(strlen(command_line) + 1, 0);
 	strcpy (saved_command_line, boot_command_line);
 	strcpy (static_command_line, command_line);
+
+	proc_command_line = saved_command_line;
+
+	/*
+	 * To keep user processes from abusing 'debug', we strip it
+	 * from what /proc/cmdline shows.
+	 */
+	str = saved_command_line;
+	do {
+		int index;
+
+		str = strstr(str, "debug");
+		if (!str)
+			break;
+
+		/* Make sure debug is by itself */
+		if ((str != saved_command_line && str[-1] != ' ') ||
+		    (str[5] != '\0' && str[5] != ' ')) {
+			str += 5;
+			continue;
+		}
+
+		/* Remove "debug" from command line */
+		index = str - saved_command_line;
+		proc_command_line = memblock_virt_alloc(len - 4, 0);
+		strncpy(proc_command_line, boot_command_line, index);
+		strncpy(proc_command_line + index,
+			boot_command_line + index + 5, len - (index + 5));
+		break;
+	} while (*str != '\0');
 }
 
 /*

^ permalink raw reply related	[flat|nested] 74+ messages in thread
* Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline
@ 2014-04-23 15:15 Borislav Petkov
  2014-04-23 20:44 ` Borislav Petkov
  0 siblings, 1 reply; 74+ messages in thread
From: Borislav Petkov @ 2014-04-23 15:15 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Jiri Kosina, Andrew Morton, Mateusz Guzik, Greg Kroah-Hartman,
	Steven Rostedt, LKML, Thomas Gleixner, H. Peter Anvin,
	Ingo Molnar, Mel Gorman, Kay Sievers

Hi Linus,

here's some more massaging of your patch. (Btw, let's start a new
thread).

On Wed, Apr 02, 2014 at 06:47:57PM -0700, Linus Torvalds wrote:
> It's definitely not perfect - if we suppress output, and the process
> then closes the file descriptor rather than continuing to write more,
> you won't  get that "suppressed" message. But it's a usable starting
> point for testing and commentary on the actual limits.
> 
> So we should probably add reporting about suppressed messages at file
> close time,

see below.

> and we should tweak the limits (for example, perhaps not limit things
> if the buffers are largely empty - which happens at bootup), but on
> the whole I think this is a reasonable thing to do.

Err, help me out here pls, which buffers? Do you mean we should look at
log_buf's fill level?

> Whether it actually fixes the problem that Borislav had is
> questionable, of course. For all I know, systemd debug mode generates
> so much data in *other* ways and then causes feedback loops with the
> kernel debugging that this patch is totally immaterial, and dmesg was
> never the main issue. But unlike the "hide 'debug' from
> /proc/cmdline", I think this patch at least _conceptually_ makes a lot
> of sense, even if systemd gets fixed, so ...

Ok, here's a dirty hack that issues ratelimit messages at release time.
I probably should wrap it nicely in ratelimit_*() accessors instead
of poking directly at ratelimit_state. Yeah, maybe a ratelimit_exit()
wrapper which does all the fun automatically.

Anyway, with it, it looks like this:

[    3.098474] systemd-fstab-g: 4 callbacks suppressed
[    9.256317] audit_printk_skb: 108 callbacks suppressed
[   31.486281] systemd-journal: 464 callbacks suppressed

In dmesg, it basically shuts up:

...
[    3.603657] systemd-journald[115]: Vacuuming...
[    3.603666] systemd-journald[115]: Vacuuming done, freed 0 bytes
[    3.603759] systemd-journald[115]: Assertion 'dual_timestamp_is_set(&e->timestamp)' failed at src/libsystemd/sd-event/sd-event.c:2204, function sd_event_get_now_monotonic(). Ignoring.
[    3.603759] systemd-journald[115]: Flushing /dev/kmsg...
[    3.603759] systemd-journald[115]: Assertion 'dual_timestamp_is_set(&e->timestamp)' failed at src/libsystemd/sd-event/sd-event.c:2204, function sd_event_get_now_monotonic(). Ignoring.
[    3.603759] systemd-journald[115]: Assertion 'dual_timestamp_is_set(&e->timestamp)' failed at src/libsystemd/sd-event/sd-event.c:2204, function sd_event_get_now_monotonic(). Ignoring.
[    3.603759] systemd-journald[115]: Assertion 'dual_timestamp_is_set(&e->timestamp)' failed at src/libsystemd/sd-event/sd-event.c:2204, function sd_event_get_now_monotonic(). Ignoring.
[    3.640216] BTRFS info (device sda2): disk space caching is enabled
[    3.815059] systemd-udevd[142]: starting version 210

and then on shutdown, when it releases kmsg:

...
[  OK  ] Stopped target Local File Systems (Pre).
         Stopping Remount Root and Kernel File Systems...
[  OK  ] Stopped Remount Root and Kernel File Systems.
[  OK  ] Reached target Shutdown.
Sending SIGTERM to remaining processes...
[   31.486281] systemd-journal: 464 callbacks suppressed
[   32.246116] mtrr: no MTRR for fc000000,400000 found
Sending SIGKILL to remaining processes...
Unmounting file systems.
[   32.356186] BTRFS info (device sda2): disk space caching is enabled
Unmounting /tmp.
[   32.392842] BTRFS info (device sda2): disk space caching is enabled
Unmounting /var/log.
...

Comments?

Thanks.

---
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h
index 0a260d8a18bf..ab8d9fb76789 100644
--- a/include/linux/ratelimit.h
+++ b/include/linux/ratelimit.h
@@ -7,6 +7,8 @@
 #define DEFAULT_RATELIMIT_INTERVAL	(5 * HZ)
 #define DEFAULT_RATELIMIT_BURST		10
 
+#define	RATELIMIT_MSG_ON_RELEASE	BIT(0)
+
 struct ratelimit_state {
 	raw_spinlock_t	lock;		/* protect the state */
 
@@ -15,6 +17,7 @@ struct ratelimit_state {
 	int		printed;
 	int		missed;
 	unsigned long	begin;
+	unsigned long	flags;
 };
 
 #define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init)		\
@@ -28,12 +31,11 @@ struct ratelimit_state {
 static inline void ratelimit_state_init(struct ratelimit_state *rs,
 					int interval, int burst)
 {
+	memset(rs, 0, sizeof(*rs));
+
 	raw_spin_lock_init(&rs->lock);
 	rs->interval = interval;
 	rs->burst = burst;
-	rs->printed = 0;
-	rs->missed = 0;
-	rs->begin = 0;
 }
 
 extern struct ratelimit_state printk_ratelimit_state;
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 5b5fdd8eeb75..18cfa5f5b058 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -450,6 +450,7 @@ struct devkmsg_user {
 	u64 seq;
 	u32 idx;
 	enum log_flags prev;
+	struct ratelimit_state rs;
 	struct mutex lock;
 	char buf[8192];
 };
@@ -461,11 +462,15 @@ static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv,
 	int i;
 	int level = default_message_loglevel;
 	int facility = 1;	/* LOG_USER */
+	struct file *file = iocb->ki_filp;
+	struct devkmsg_user *user = file->private_data;
 	size_t len = iov_length(iv, count);
 	ssize_t ret = len;
 
-	if (len > LOG_LINE_MAX)
+	if (!user || len > LOG_LINE_MAX)
 		return -EINVAL;
+	if (!___ratelimit(&user->rs, current->comm))
+		return ret;
 	buf = kmalloc(len+1, GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;
@@ -696,21 +701,25 @@ static unsigned int devkmsg_poll(struct file *file, poll_table *wait)
 static int devkmsg_open(struct inode *inode, struct file *file)
 {
 	struct devkmsg_user *user;
-	int err;
-
-	/* write-only does not need any file context */
-	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
-		return 0;
 
-	err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL,
-				       SYSLOG_FROM_READER);
-	if (err)
-		return err;
+	/* write-only does not need to check read permissions */
+	if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+		int err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL,
+					       SYSLOG_FROM_READER);
+		if (err)
+			return err;
+	}
 
 	user = kmalloc(sizeof(struct devkmsg_user), GFP_KERNEL);
 	if (!user)
 		return -ENOMEM;
 
+	/* Configurable? */
+	ratelimit_state_init(&user->rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
+
+	/* We'll say something at release time. */
+	user->rs.flags |= RATELIMIT_MSG_ON_RELEASE;
+
 	mutex_init(&user->lock);
 
 	raw_spin_lock_irq(&logbuf_lock);
@@ -729,6 +738,10 @@ static int devkmsg_release(struct inode *inode, struct file *file)
 	if (!user)
 		return 0;
 
+	if (user->rs.missed)
+		pr_warning("%s: %d callbacks suppressed\n",
+			   current->comm, user->rs.missed);
+
 	mutex_destroy(&user->lock);
 	kfree(user);
 	return 0;
diff --git a/lib/ratelimit.c b/lib/ratelimit.c
index 40e03ea2a967..97b461a9fd52 100644
--- a/lib/ratelimit.c
+++ b/lib/ratelimit.c
@@ -46,12 +46,13 @@ int ___ratelimit(struct ratelimit_state *rs, const char *func)
 		rs->begin = jiffies;
 
 	if (time_is_before_jiffies(rs->begin + rs->interval)) {
-		if (rs->missed)
+		if (rs->missed && !(rs->flags & RATELIMIT_MSG_ON_RELEASE))
 			printk(KERN_WARNING "%s: %d callbacks suppressed\n",
 				func, rs->missed);
 		rs->begin   = 0;
 		rs->printed = 0;
-		rs->missed  = 0;
+		if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE))
+			rs->missed  = 0;
 	}
 	if (rs->burst && rs->burst > rs->printed) {
 		rs->printed++;

-- 
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

^ permalink raw reply related	[flat|nested] 74+ messages in thread

end of thread, other threads:[~2014-05-21  2:58 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-02 18:42 [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline Steven Rostedt
2014-04-02 18:57 ` Linus Torvalds
2014-04-02 19:04 ` Andrew Morton
2014-04-02 19:05   ` Borislav Petkov
2014-04-02 19:08   ` Randy Dunlap
2014-04-02 19:50   ` Thomas Gleixner
2014-04-02 20:05     ` Richard Weinberger
2014-04-02 20:43       ` Thomas Gleixner
2014-04-02 22:18   ` Greg KH
2014-04-02 19:08 ` Borislav Petkov
2014-04-02 19:33   ` Steven Rostedt
2014-04-02 22:12 ` Mateusz Guzik
2014-04-02 22:30   ` David Daney
2014-04-02 22:37   ` Greg KH
2014-04-02 23:13   ` Linus Torvalds
2014-04-02 23:23     ` Jiri Kosina
2014-04-02 23:28       ` Andrew Morton
2014-04-02 23:42         ` Linus Torvalds
2014-04-02 23:47           ` Jiri Kosina
2014-04-02 23:52             ` Linus Torvalds
2014-04-02 23:57               ` Jiri Kosina
2014-04-03  1:38               ` Steven Rostedt
2014-04-03  1:47               ` Linus Torvalds
2014-04-03  9:03                 ` Borislav Petkov
2014-04-03 10:43                 ` Joerg Roedel
2014-04-03 17:05                   ` Theodore Ts'o
2014-04-03 17:09                     ` H. Peter Anvin
2014-04-03 17:18                       ` Theodore Ts'o
2014-04-03 19:19                         ` H. Peter Anvin
2014-04-04 18:21                     ` Andy Lutomirski
2014-04-04 18:32                       ` Linus Torvalds
2014-04-04 18:57                         ` Andy Lutomirski
2014-04-04 19:09                           ` Linus Torvalds
2014-04-04 21:17                         ` John Stoffel
2014-04-04 23:17                           ` Greg Kroah-Hartman
2014-04-05 14:37                             ` John Stoffel
2014-04-05 23:23                             ` Theodore Ts'o
2014-04-04 18:42                       ` Linus Torvalds
2014-04-04 18:51                         ` Andrew Morton
2014-04-04 18:57                           ` Linus Torvalds
2014-04-06 20:49                             ` David Timothy Strauss
2014-05-06  9:38                               ` Felipe Contreras
2014-04-04 19:44                           ` Steven Rostedt
2014-04-04 20:17                             ` Theodore Ts'o
2014-04-04 22:45                               ` Alexei Starovoitov
2014-04-04 22:48                                 ` Linus Torvalds
2014-04-04 19:00                         ` Andy Lutomirski
2014-04-03 11:23                 ` Borislav Petkov
2014-04-03 11:38                   ` Ingo Molnar
2014-04-15  7:26                 ` Borislav Petkov
2014-04-03 10:34               ` Måns Rullgård
2014-04-03 11:03                 ` Borislav Petkov
2014-04-06 17:19                   ` One Thousand Gnomes
2014-05-06  9:47                   ` Felipe Contreras
2014-04-02 23:47           ` Joe Perches
2014-04-02 23:31       ` Linus Torvalds
2014-04-03 11:25       ` Måns Rullgård
2014-04-03 15:17         ` Tim Bird
2014-04-03 18:06           ` Greg Kroah-Hartman
2014-05-06  9:35             ` Felipe Contreras
2014-04-07  4:54     ` Rusty Russell
2014-05-02 22:34       ` Andrew Morton
2014-05-05  2:17         ` Rusty Russell
2014-05-05 13:15           ` Randy Dunlap
2014-05-06  0:57             ` Rusty Russell
2014-05-19  8:06               ` Diego Viola
2014-05-19  8:11                 ` Diego Viola
2014-05-19 14:40                   ` Randy Dunlap
2014-05-20  1:26                     ` Rusty Russell
2014-05-20  6:26                       ` Diego Viola
2014-05-21  1:52                         ` Rusty Russell
2014-04-03  0:49   ` Steven Rostedt
2014-04-23 15:15 Borislav Petkov
2014-04-23 20:44 ` Borislav Petkov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.