lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 23 Dec 2014 22:27:38 +0100
From:	Bruno Prémont <bonbons@...ux-vserver.org>
To:	dwalker@...o99.com, Matt Mackall <mpm@...enic.com>,
	Satyam Sharma <satyam.sharma@...il.com>,
	Cong Wang <xiyou.wangcong@...il.com>
Cc:	linux-kernel@...r.kernel.org,
	Andrew Morton <akpm@...ux-foundation.org>,
	Joe Perches <joe@...ches.com>
Subject: [PATCH 2/3] netconsole: make loglevel configurable per target

Switch to registering a new console for each target so that loglevel
based message filtering can be set individually for each target.

This adds a new loglevel= option to netconsole module parameter and also
add a configfs file to configure the loglevel.

The loglevel conf be adjusted at any time for synamic netconsole
consoles.

Signed-off-by: Bruno Prémont <bonbons@...ux-vserver.org>
---
Note: only configuration via configfs has been runtime-tested.

 Documentation/networking/netconsole.txt |  11 ++-
 drivers/net/netconsole.c                | 114 +++++++++++++++++++++++---------
 2 files changed, 94 insertions(+), 31 deletions(-)

diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt
index a5d574a..c1df516 100644
--- a/Documentation/networking/netconsole.txt
+++ b/Documentation/networking/netconsole.txt
@@ -24,7 +24,7 @@ Sender and receiver configuration:
 It takes a string configuration parameter "netconsole" in the
 following format:
 
- netconsole=[src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr]
+ netconsole=[src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr][,loglevel=level]
 
    where
         src-port      source for UDP packets (defaults to 6665)
@@ -33,6 +33,9 @@ following format:
         tgt-port      port for logging agent (6666)
         tgt-ip        IP address for logging agent
         tgt-macaddr   ethernet MAC address for logging agent (broadcast)
+        level         limit messages printed to those whose loglevel is
+                      smaller that value, range is 1 to 8
+                      If missing, loglevel limit as set via syslog(1) applies
 
 Examples:
 
@@ -114,11 +117,16 @@ The interface exposes these parameters of a netconsole target to userspace:
 	remote_ip	Remote agent's IP address		(read-write)
 	local_mac	Local interface's MAC address		(read-only)
 	remote_mac	Remote agent's MAC address		(read-write)
+	loglevel        Console loglevel filter                 (read-write)
 
 The "enabled" attribute is also used to control whether the parameters of
 a target can be updated or not -- you can modify the parameters of only
 disabled targets (i.e. if "enabled" is 0).
 
+The "loglevel" parameter can be set at any time. When set to "0" it will
+read back as empty string and global loglevel filter applies. Otherwise
+specified loglevel filter applies.
+
 To update a target's parameters:
 
  cat enabled				# check if enabled is 1
@@ -164,6 +172,7 @@ priority messages to the console. You can change this at runtime using:
 
  dmesg -n 8
 
+or by specifying netconsole loglevel parameter
 or by specifying "debug" on the kernel command line at boot, to send
 all kernel messages to the console. A specific value for this parameter
 can also be set using the "loglevel" kernel boot option. See the
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index ba2f5e7..a96cd8e 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -103,10 +103,12 @@ struct netconsole_target {
 #ifdef	CONFIG_NETCONSOLE_DYNAMIC
 	struct config_item	item;
 #endif
+	struct console		console;
 	int			enabled;
 	struct mutex		mutex;
 	struct netpoll		np;
 };
+static void write_msg(struct console *con, const char *msg, unsigned int len);
 
 #ifdef	CONFIG_NETCONSOLE_DYNAMIC
 
@@ -171,6 +173,7 @@ static struct netconsole_target *alloc_param_target(char *target_config)
 {
 	int err = -ENOMEM;
 	struct netconsole_target *nt;
+	char *loglevel;
 
 	/*
 	 * Allocate and initialize with defaults.
@@ -186,8 +189,26 @@ static struct netconsole_target *alloc_param_target(char *target_config)
 	nt->np.remote_port = 6666;
 	mutex_init(&nt->mutex);
 	memset(nt->np.remote_mac, 0xff, ETH_ALEN);
+	snprintf(nt->console.name, sizeof(nt->console.name), "netcon");
+	/* Dump existing printks when we register */
+	nt->console.flags = CON_ENABLED | CON_PRINTBUFFER;
+	nt->console.write = write_msg;
 
 	/* Parse parameters and setup netpoll */
+	loglevel = strstr(target_config, ",loglevel=");
+	if (loglevel) {
+		int level;
+		err = kstrtoint(loglevel+10, 10, &level);
+		if (err < 0)
+			goto fail;
+		if (level < 1 || level > 8) {
+			err = -EINVAL;
+			goto fail;
+		}
+		nt->console.loglevel = level;
+		nt->console.flags |= CON_LOGLEVEL;
+		*loglevel = '\0';
+	}
 	err = netpoll_parse_options(&nt->np, target_config);
 	if (err)
 		goto fail;
@@ -228,6 +249,7 @@ static void free_param_target(struct netconsole_target *nt)
  *				|	remote_ip
  *				|	local_mac
  *				|	remote_mac
+ *				|	loglevel
  *				|
  *				<target>/...
  */
@@ -301,6 +323,14 @@ static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
 	return snprintf(buf, PAGE_SIZE, "%pM\n", nt->np.remote_mac);
 }
 
+static ssize_t show_loglevel(struct netconsole_target *nt, char *buf)
+{
+	if (nt->console.flags & CON_LOGLEVEL)
+		return snprintf(buf, PAGE_SIZE, "%u\n", nt->console.loglevel);
+	else
+		return snprintf(buf, PAGE_SIZE, "\n");
+}
+
 /*
  * This one is special -- targets created through the configfs interface
  * are not enabled (and the corresponding netpoll activated) by default.
@@ -338,6 +368,8 @@ static ssize_t store_enabled(struct netconsole_target *nt,
 		if (err)
 			return err;
 
+		nt->enabled = 1;
+		register_console(&nt->console);
 		pr_info("netconsole: network logging started\n");
 	} else {	/* 0 */
 		/* We need to disable the netconsole before cleaning it up
@@ -347,11 +379,11 @@ static ssize_t store_enabled(struct netconsole_target *nt,
 		spin_lock_irqsave(&target_list_lock, flags);
 		nt->enabled = 0;
 		spin_unlock_irqrestore(&target_list_lock, flags);
+		unregister_console(&nt->console);
 		netpoll_cleanup(&nt->np);
+		nt->console.flags = nt->console.flags & ~CON_PRINTBUFFER;
 	}
 
-	nt->enabled = enabled;
-
 	return strnlen(buf, count);
 }
 
@@ -494,6 +526,27 @@ static ssize_t store_remote_mac(struct netconsole_target *nt,
 	return strnlen(buf, count);
 }
 
+static ssize_t store_loglevel(struct netconsole_target *nt,
+				 const char *buf,
+				 size_t count)
+{
+	int rv, level;
+
+	rv = kstrtoint(buf, 10, &level);
+	if (rv < 0)
+		return rv;
+	if (level < 0 || level > 8)
+		return -EINVAL;
+
+	if (level > 0) {
+		nt->console.loglevel = level;
+		nt->console.flags |= CON_LOGLEVEL;
+	} else
+		nt->console.flags &= ~CON_LOGLEVEL;
+
+	return strnlen(buf, count);
+}
+
 /*
  * Attribute definitions for netconsole_target.
  */
@@ -514,6 +567,7 @@ NETCONSOLE_TARGET_ATTR_RW(local_ip);
 NETCONSOLE_TARGET_ATTR_RW(remote_ip);
 NETCONSOLE_TARGET_ATTR_RO(local_mac);
 NETCONSOLE_TARGET_ATTR_RW(remote_mac);
+NETCONSOLE_TARGET_ATTR_RW(loglevel);
 
 static struct configfs_attribute *netconsole_target_attrs[] = {
 	&netconsole_target_enabled.attr,
@@ -524,6 +578,7 @@ static struct configfs_attribute *netconsole_target_attrs[] = {
 	&netconsole_target_remote_ip.attr,
 	&netconsole_target_local_mac.attr,
 	&netconsole_target_remote_mac.attr,
+	&netconsole_target_loglevel.attr,
 	NULL,
 };
 
@@ -605,6 +660,10 @@ static struct config_item *make_netconsole_target(struct config_group *group,
 	nt->np.remote_port = 6666;
 	mutex_init(&nt->mutex);
 	memset(nt->np.remote_mac, 0xff, ETH_ALEN);
+	snprintf(nt->console.name, sizeof(nt->console.name), "netcon-%s", name);
+	nt->console.flags = CON_ENABLED;
+	nt->console.write = write_msg;
+	nt->console.loglevel = 0;
 
 	/* Initialize the config_item member */
 	config_item_init_type_name(&nt->item, name, &netconsole_target_type);
@@ -626,6 +685,7 @@ static void drop_netconsole_target(struct config_group *group,
 	spin_lock_irqsave(&target_list_lock, flags);
 	list_del(&nt->list);
 	spin_unlock_irqrestore(&target_list_lock, flags);
+	unregister_console(&nt->console);
 
 	/*
 	 * The target may have never been enabled, or was manually disabled
@@ -732,7 +792,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
 {
 	int frag, left;
 	unsigned long flags;
-	struct netconsole_target *nt;
+	struct netconsole_target *nt = container_of(con, struct netconsole_target, console);
 	const char *tmp;
 
 	if (oops_only && !oops_in_progress)
@@ -742,34 +802,26 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
 		return;
 
 	spin_lock_irqsave(&target_list_lock, flags);
-	list_for_each_entry(nt, &target_list, list) {
-		netconsole_target_get(nt);
-		if (nt->enabled && netif_running(nt->np.dev)) {
-			/*
-			 * We nest this inside the for-each-target loop above
-			 * so that we're able to get as much logging out to
-			 * at least one target if we die inside here, instead
-			 * of unnecessarily keeping all targets in lock-step.
-			 */
-			tmp = msg;
-			for (left = len; left;) {
-				frag = min(left, MAX_PRINT_CHUNK);
-				netpoll_send_udp(&nt->np, tmp, frag);
-				tmp += frag;
-				left -= frag;
-			}
+	netconsole_target_get(nt);
+	if (nt->enabled && netif_running(nt->np.dev)) {
+		/*
+		 * We nest this inside the for-each-target loop above
+		 * so that we're able to get as much logging out to
+		 * at least one target if we die inside here, instead
+		 * of unnecessarily keeping all targets in lock-step.
+		 */
+		tmp = msg;
+		for (left = len; left;) {
+			frag = min(left, MAX_PRINT_CHUNK);
+			netpoll_send_udp(&nt->np, tmp, frag);
+			tmp += frag;
+			left -= frag;
 		}
-		netconsole_target_put(nt);
 	}
+	netconsole_target_put(nt);
 	spin_unlock_irqrestore(&target_list_lock, flags);
 }
 
-static struct console netconsole = {
-	.name	= "netcon",
-	.flags	= CON_ENABLED,
-	.write	= write_msg,
-};
-
 static int __init init_netconsole(void)
 {
 	int err;
@@ -785,8 +837,6 @@ static int __init init_netconsole(void)
 				err = PTR_ERR(nt);
 				goto fail;
 			}
-			/* Dump existing printks when we register */
-			netconsole.flags |= CON_PRINTBUFFER;
 
 			spin_lock_irqsave(&target_list_lock, flags);
 			list_add(&nt->list, &target_list);
@@ -802,7 +852,9 @@ static int __init init_netconsole(void)
 	if (err)
 		goto undonotifier;
 
-	register_console(&netconsole);
+	list_for_each_entry_safe(nt, tmp, &target_list, list) {
+		register_console(&nt->console);
+	}
 	pr_info("network logging started\n");
 
 	return err;
@@ -830,7 +882,9 @@ static void __exit cleanup_netconsole(void)
 {
 	struct netconsole_target *nt, *tmp;
 
-	unregister_console(&netconsole);
+	list_for_each_entry_safe(nt, tmp, &target_list, list) {
+		unregister_console(&nt->console);
+	}
 	dynamic_netconsole_exit();
 	unregister_netdevice_notifier(&netconsole_netdev_notifier);
 
-- 
2.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ