1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * linux/drivers/net/netconsole.c
4 *
5 * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com>
6 *
7 * This file contains the implementation of an IRQ-safe, crash-safe
8 * kernel console implementation that outputs kernel messages to the
9 * network.
10 *
11 * Modification history:
12 *
13 * 2001-09-17 started by Ingo Molnar.
14 * 2003-08-11 2.6 port by Matt Mackall
15 * simplified options
16 * generic card hooks
17 * works non-modular
18 * 2003-09-07 rewritten with netpoll api
19 */
20
21 /****************************************************************
22 *
23 ****************************************************************/
24
25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27 #include <linux/mm.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 #include <linux/console.h>
32 #include <linux/moduleparam.h>
33 #include <linux/kernel.h>
34 #include <linux/string.h>
35 #include <linux/netpoll.h>
36 #include <linux/inet.h>
37 #include <linux/configfs.h>
38 #include <linux/etherdevice.h>
39 #include <linux/u64_stats_sync.h>
40 #include <linux/utsname.h>
41 #include <linux/rtnetlink.h>
42
43 MODULE_AUTHOR("Matt Mackall <mpm@selenic.com>");
44 MODULE_DESCRIPTION("Console driver for network interfaces");
45 MODULE_LICENSE("GPL");
46
47 #define MAX_PARAM_LENGTH 256
48 #define MAX_EXTRADATA_ENTRY_LEN 256
49 #define MAX_EXTRADATA_VALUE_LEN 200
50 /* The number 3 comes from userdata entry format characters (' ', '=', '\n') */
51 #define MAX_EXTRADATA_NAME_LEN (MAX_EXTRADATA_ENTRY_LEN - \
52 MAX_EXTRADATA_VALUE_LEN - 3)
53 #define MAX_EXTRADATA_ITEMS 16
54 #define MAX_PRINT_CHUNK 1000
55
56 static char config[MAX_PARAM_LENGTH];
57 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
58 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
59
60 static bool oops_only;
61 module_param(oops_only, bool, 0600);
62 MODULE_PARM_DESC(oops_only, "Only log oops messages");
63
64 #define NETCONSOLE_PARAM_TARGET_PREFIX "cmdline"
65
66 #ifndef MODULE
option_setup(char * opt)67 static int __init option_setup(char *opt)
68 {
69 strscpy(config, opt, MAX_PARAM_LENGTH);
70 return 1;
71 }
72 __setup("netconsole=", option_setup);
73 #endif /* MODULE */
74
75 /* Linked list of all configured targets */
76 static LIST_HEAD(target_list);
77 /* target_cleanup_list is used to track targets that need to be cleaned outside
78 * of target_list_lock. It should be cleaned in the same function it is
79 * populated.
80 */
81 static LIST_HEAD(target_cleanup_list);
82
83 /* This needs to be a spinlock because write_msg() cannot sleep */
84 static DEFINE_SPINLOCK(target_list_lock);
85 /* This needs to be a mutex because netpoll_cleanup might sleep */
86 static DEFINE_MUTEX(target_cleanup_list_lock);
87
88 /*
89 * Console driver for extended netconsoles. Registered on the first use to
90 * avoid unnecessarily enabling ext message formatting.
91 */
92 static struct console netconsole_ext;
93
94 struct netconsole_target_stats {
95 u64_stats_t xmit_drop_count;
96 u64_stats_t enomem_count;
97 struct u64_stats_sync syncp;
98 };
99
100 /* Features enabled in sysdata. Contrary to userdata, this data is populated by
101 * the kernel. The fields are designed as bitwise flags, allowing multiple
102 * features to be set in sysdata_fields.
103 */
104 enum sysdata_feature {
105 /* Populate the CPU that sends the message */
106 SYSDATA_CPU_NR = BIT(0),
107 /* Populate the task name (as in current->comm) in sysdata */
108 SYSDATA_TASKNAME = BIT(1),
109 /* Kernel release/version as part of sysdata */
110 SYSDATA_RELEASE = BIT(2),
111 };
112
113 /**
114 * struct netconsole_target - Represents a configured netconsole target.
115 * @list: Links this target into the target_list.
116 * @group: Links us into the configfs subsystem hierarchy.
117 * @userdata_group: Links to the userdata configfs hierarchy
118 * @extradata_complete: Cached, formatted string of append
119 * @userdata_length: String length of usedata in extradata_complete.
120 * @sysdata_fields: Sysdata features enabled.
121 * @stats: Packet send stats for the target. Used for debugging.
122 * @enabled: On / off knob to enable / disable target.
123 * Visible from userspace (read-write).
124 * We maintain a strict 1:1 correspondence between this and
125 * whether the corresponding netpoll is active or inactive.
126 * Also, other parameters of a target may be modified at
127 * runtime only when it is disabled (enabled == 0).
128 * @extended: Denotes whether console is extended or not.
129 * @release: Denotes whether kernel release version should be prepended
130 * to the message. Depends on extended console.
131 * @np: The netpoll structure for this target.
132 * Contains the other userspace visible parameters:
133 * dev_name (read-write)
134 * local_port (read-write)
135 * remote_port (read-write)
136 * local_ip (read-write)
137 * remote_ip (read-write)
138 * local_mac (read-only)
139 * remote_mac (read-write)
140 * @buf: The buffer used to send the full msg to the network stack
141 */
142 struct netconsole_target {
143 struct list_head list;
144 #ifdef CONFIG_NETCONSOLE_DYNAMIC
145 struct config_group group;
146 struct config_group userdata_group;
147 char extradata_complete[MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS];
148 size_t userdata_length;
149 /* bit-wise with sysdata_feature bits */
150 u32 sysdata_fields;
151 #endif
152 struct netconsole_target_stats stats;
153 bool enabled;
154 bool extended;
155 bool release;
156 struct netpoll np;
157 /* protected by target_list_lock */
158 char buf[MAX_PRINT_CHUNK];
159 };
160
161 #ifdef CONFIG_NETCONSOLE_DYNAMIC
162
163 static struct configfs_subsystem netconsole_subsys;
164 static DEFINE_MUTEX(dynamic_netconsole_mutex);
165
dynamic_netconsole_init(void)166 static int __init dynamic_netconsole_init(void)
167 {
168 config_group_init(&netconsole_subsys.su_group);
169 mutex_init(&netconsole_subsys.su_mutex);
170 return configfs_register_subsystem(&netconsole_subsys);
171 }
172
dynamic_netconsole_exit(void)173 static void __exit dynamic_netconsole_exit(void)
174 {
175 configfs_unregister_subsystem(&netconsole_subsys);
176 }
177
178 /*
179 * Targets that were created by parsing the boot/module option string
180 * do not exist in the configfs hierarchy (and have NULL names) and will
181 * never go away, so make these a no-op for them.
182 */
netconsole_target_get(struct netconsole_target * nt)183 static void netconsole_target_get(struct netconsole_target *nt)
184 {
185 if (config_item_name(&nt->group.cg_item))
186 config_group_get(&nt->group);
187 }
188
netconsole_target_put(struct netconsole_target * nt)189 static void netconsole_target_put(struct netconsole_target *nt)
190 {
191 if (config_item_name(&nt->group.cg_item))
192 config_group_put(&nt->group);
193 }
194
195 #else /* !CONFIG_NETCONSOLE_DYNAMIC */
196
dynamic_netconsole_init(void)197 static int __init dynamic_netconsole_init(void)
198 {
199 return 0;
200 }
201
dynamic_netconsole_exit(void)202 static void __exit dynamic_netconsole_exit(void)
203 {
204 }
205
206 /*
207 * No danger of targets going away from under us when dynamic
208 * reconfigurability is off.
209 */
netconsole_target_get(struct netconsole_target * nt)210 static void netconsole_target_get(struct netconsole_target *nt)
211 {
212 }
213
netconsole_target_put(struct netconsole_target * nt)214 static void netconsole_target_put(struct netconsole_target *nt)
215 {
216 }
217
populate_configfs_item(struct netconsole_target * nt,int cmdline_count)218 static void populate_configfs_item(struct netconsole_target *nt,
219 int cmdline_count)
220 {
221 }
222 #endif /* CONFIG_NETCONSOLE_DYNAMIC */
223
224 /* Allocate and initialize with defaults.
225 * Note that these targets get their config_item fields zeroed-out.
226 */
alloc_and_init(void)227 static struct netconsole_target *alloc_and_init(void)
228 {
229 struct netconsole_target *nt;
230
231 nt = kzalloc(sizeof(*nt), GFP_KERNEL);
232 if (!nt)
233 return nt;
234
235 if (IS_ENABLED(CONFIG_NETCONSOLE_EXTENDED_LOG))
236 nt->extended = true;
237 if (IS_ENABLED(CONFIG_NETCONSOLE_PREPEND_RELEASE))
238 nt->release = true;
239
240 nt->np.name = "netconsole";
241 strscpy(nt->np.dev_name, "eth0", IFNAMSIZ);
242 nt->np.local_port = 6665;
243 nt->np.remote_port = 6666;
244 eth_broadcast_addr(nt->np.remote_mac);
245
246 return nt;
247 }
248
249 /* Clean up every target in the cleanup_list and move the clean targets back to
250 * the main target_list.
251 */
netconsole_process_cleanups_core(void)252 static void netconsole_process_cleanups_core(void)
253 {
254 struct netconsole_target *nt, *tmp;
255 unsigned long flags;
256
257 /* The cleanup needs RTNL locked */
258 ASSERT_RTNL();
259
260 mutex_lock(&target_cleanup_list_lock);
261 list_for_each_entry_safe(nt, tmp, &target_cleanup_list, list) {
262 /* all entries in the cleanup_list needs to be disabled */
263 WARN_ON_ONCE(nt->enabled);
264 do_netpoll_cleanup(&nt->np);
265 /* moved the cleaned target to target_list. Need to hold both
266 * locks
267 */
268 spin_lock_irqsave(&target_list_lock, flags);
269 list_move(&nt->list, &target_list);
270 spin_unlock_irqrestore(&target_list_lock, flags);
271 }
272 WARN_ON_ONCE(!list_empty(&target_cleanup_list));
273 mutex_unlock(&target_cleanup_list_lock);
274 }
275
276 #ifdef CONFIG_NETCONSOLE_DYNAMIC
277
278 /*
279 * Our subsystem hierarchy is:
280 *
281 * /sys/kernel/config/netconsole/
282 * |
283 * <target>/
284 * | enabled
285 * | release
286 * | dev_name
287 * | local_port
288 * | remote_port
289 * | local_ip
290 * | remote_ip
291 * | local_mac
292 * | remote_mac
293 * | transmit_errors
294 * | userdata/
295 * | <key>/
296 * | value
297 * | ...
298 * |
299 * <target>/...
300 */
301
to_target(struct config_item * item)302 static struct netconsole_target *to_target(struct config_item *item)
303 {
304 struct config_group *cfg_group;
305
306 cfg_group = to_config_group(item);
307 if (!cfg_group)
308 return NULL;
309 return container_of(to_config_group(item),
310 struct netconsole_target, group);
311 }
312
313 /* Do the list cleanup with the rtnl lock hold. rtnl lock is necessary because
314 * netdev might be cleaned-up by calling __netpoll_cleanup(),
315 */
netconsole_process_cleanups(void)316 static void netconsole_process_cleanups(void)
317 {
318 /* rtnl lock is called here, because it has precedence over
319 * target_cleanup_list_lock mutex and target_cleanup_list
320 */
321 rtnl_lock();
322 netconsole_process_cleanups_core();
323 rtnl_unlock();
324 }
325
326 /* Get rid of possible trailing newline, returning the new length */
trim_newline(char * s,size_t maxlen)327 static void trim_newline(char *s, size_t maxlen)
328 {
329 size_t len;
330
331 len = strnlen(s, maxlen);
332 if (s[len - 1] == '\n')
333 s[len - 1] = '\0';
334 }
335
336 /*
337 * Attribute operations for netconsole_target.
338 */
339
enabled_show(struct config_item * item,char * buf)340 static ssize_t enabled_show(struct config_item *item, char *buf)
341 {
342 return sysfs_emit(buf, "%d\n", to_target(item)->enabled);
343 }
344
extended_show(struct config_item * item,char * buf)345 static ssize_t extended_show(struct config_item *item, char *buf)
346 {
347 return sysfs_emit(buf, "%d\n", to_target(item)->extended);
348 }
349
release_show(struct config_item * item,char * buf)350 static ssize_t release_show(struct config_item *item, char *buf)
351 {
352 return sysfs_emit(buf, "%d\n", to_target(item)->release);
353 }
354
dev_name_show(struct config_item * item,char * buf)355 static ssize_t dev_name_show(struct config_item *item, char *buf)
356 {
357 return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name);
358 }
359
local_port_show(struct config_item * item,char * buf)360 static ssize_t local_port_show(struct config_item *item, char *buf)
361 {
362 return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port);
363 }
364
remote_port_show(struct config_item * item,char * buf)365 static ssize_t remote_port_show(struct config_item *item, char *buf)
366 {
367 return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port);
368 }
369
local_ip_show(struct config_item * item,char * buf)370 static ssize_t local_ip_show(struct config_item *item, char *buf)
371 {
372 struct netconsole_target *nt = to_target(item);
373
374 if (nt->np.ipv6)
375 return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6);
376 else
377 return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip);
378 }
379
remote_ip_show(struct config_item * item,char * buf)380 static ssize_t remote_ip_show(struct config_item *item, char *buf)
381 {
382 struct netconsole_target *nt = to_target(item);
383
384 if (nt->np.ipv6)
385 return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6);
386 else
387 return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip);
388 }
389
local_mac_show(struct config_item * item,char * buf)390 static ssize_t local_mac_show(struct config_item *item, char *buf)
391 {
392 struct net_device *dev = to_target(item)->np.dev;
393 static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
394
395 return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast);
396 }
397
remote_mac_show(struct config_item * item,char * buf)398 static ssize_t remote_mac_show(struct config_item *item, char *buf)
399 {
400 return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac);
401 }
402
transmit_errors_show(struct config_item * item,char * buf)403 static ssize_t transmit_errors_show(struct config_item *item, char *buf)
404 {
405 struct netconsole_target *nt = to_target(item);
406 u64 xmit_drop_count, enomem_count;
407 unsigned int start;
408
409 do {
410 start = u64_stats_fetch_begin(&nt->stats.syncp);
411 xmit_drop_count = u64_stats_read(&nt->stats.xmit_drop_count);
412 enomem_count = u64_stats_read(&nt->stats.enomem_count);
413 } while (u64_stats_fetch_retry(&nt->stats.syncp, start));
414
415 return sysfs_emit(buf, "%llu\n", xmit_drop_count + enomem_count);
416 }
417
418 /* configfs helper to display if cpu_nr sysdata feature is enabled */
sysdata_cpu_nr_enabled_show(struct config_item * item,char * buf)419 static ssize_t sysdata_cpu_nr_enabled_show(struct config_item *item, char *buf)
420 {
421 struct netconsole_target *nt = to_target(item->ci_parent);
422 bool cpu_nr_enabled;
423
424 mutex_lock(&dynamic_netconsole_mutex);
425 cpu_nr_enabled = !!(nt->sysdata_fields & SYSDATA_CPU_NR);
426 mutex_unlock(&dynamic_netconsole_mutex);
427
428 return sysfs_emit(buf, "%d\n", cpu_nr_enabled);
429 }
430
431 /* configfs helper to display if taskname sysdata feature is enabled */
sysdata_taskname_enabled_show(struct config_item * item,char * buf)432 static ssize_t sysdata_taskname_enabled_show(struct config_item *item,
433 char *buf)
434 {
435 struct netconsole_target *nt = to_target(item->ci_parent);
436 bool taskname_enabled;
437
438 mutex_lock(&dynamic_netconsole_mutex);
439 taskname_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
440 mutex_unlock(&dynamic_netconsole_mutex);
441
442 return sysfs_emit(buf, "%d\n", taskname_enabled);
443 }
444
sysdata_release_enabled_show(struct config_item * item,char * buf)445 static ssize_t sysdata_release_enabled_show(struct config_item *item,
446 char *buf)
447 {
448 struct netconsole_target *nt = to_target(item->ci_parent);
449 bool release_enabled;
450
451 mutex_lock(&dynamic_netconsole_mutex);
452 release_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
453 mutex_unlock(&dynamic_netconsole_mutex);
454
455 return sysfs_emit(buf, "%d\n", release_enabled);
456 }
457
458 /*
459 * This one is special -- targets created through the configfs interface
460 * are not enabled (and the corresponding netpoll activated) by default.
461 * The user is expected to set the desired parameters first (which
462 * would enable him to dynamically add new netpoll targets for new
463 * network interfaces as and when they come up).
464 */
enabled_store(struct config_item * item,const char * buf,size_t count)465 static ssize_t enabled_store(struct config_item *item,
466 const char *buf, size_t count)
467 {
468 struct netconsole_target *nt = to_target(item);
469 unsigned long flags;
470 bool enabled;
471 ssize_t ret;
472
473 mutex_lock(&dynamic_netconsole_mutex);
474 ret = kstrtobool(buf, &enabled);
475 if (ret)
476 goto out_unlock;
477
478 ret = -EINVAL;
479 if (enabled == nt->enabled) {
480 pr_info("network logging has already %s\n",
481 nt->enabled ? "started" : "stopped");
482 goto out_unlock;
483 }
484
485 if (enabled) { /* true */
486 if (nt->release && !nt->extended) {
487 pr_err("Not enabling netconsole. Release feature requires extended log message");
488 goto out_unlock;
489 }
490
491 if (nt->extended && !console_is_registered(&netconsole_ext))
492 register_console(&netconsole_ext);
493
494 /*
495 * Skip netpoll_parse_options() -- all the attributes are
496 * already configured via configfs. Just print them out.
497 */
498 netpoll_print_options(&nt->np);
499
500 ret = netpoll_setup(&nt->np);
501 if (ret)
502 goto out_unlock;
503
504 nt->enabled = true;
505 pr_info("network logging started\n");
506 } else { /* false */
507 /* We need to disable the netconsole before cleaning it up
508 * otherwise we might end up in write_msg() with
509 * nt->np.dev == NULL and nt->enabled == true
510 */
511 mutex_lock(&target_cleanup_list_lock);
512 spin_lock_irqsave(&target_list_lock, flags);
513 nt->enabled = false;
514 /* Remove the target from the list, while holding
515 * target_list_lock
516 */
517 list_move(&nt->list, &target_cleanup_list);
518 spin_unlock_irqrestore(&target_list_lock, flags);
519 mutex_unlock(&target_cleanup_list_lock);
520 }
521
522 ret = strnlen(buf, count);
523 /* Deferred cleanup */
524 netconsole_process_cleanups();
525 out_unlock:
526 mutex_unlock(&dynamic_netconsole_mutex);
527 return ret;
528 }
529
release_store(struct config_item * item,const char * buf,size_t count)530 static ssize_t release_store(struct config_item *item, const char *buf,
531 size_t count)
532 {
533 struct netconsole_target *nt = to_target(item);
534 bool release;
535 ssize_t ret;
536
537 mutex_lock(&dynamic_netconsole_mutex);
538 if (nt->enabled) {
539 pr_err("target (%s) is enabled, disable to update parameters\n",
540 config_item_name(&nt->group.cg_item));
541 ret = -EINVAL;
542 goto out_unlock;
543 }
544
545 ret = kstrtobool(buf, &release);
546 if (ret)
547 goto out_unlock;
548
549 nt->release = release;
550
551 ret = strnlen(buf, count);
552 out_unlock:
553 mutex_unlock(&dynamic_netconsole_mutex);
554 return ret;
555 }
556
extended_store(struct config_item * item,const char * buf,size_t count)557 static ssize_t extended_store(struct config_item *item, const char *buf,
558 size_t count)
559 {
560 struct netconsole_target *nt = to_target(item);
561 bool extended;
562 ssize_t ret;
563
564 mutex_lock(&dynamic_netconsole_mutex);
565 if (nt->enabled) {
566 pr_err("target (%s) is enabled, disable to update parameters\n",
567 config_item_name(&nt->group.cg_item));
568 ret = -EINVAL;
569 goto out_unlock;
570 }
571
572 ret = kstrtobool(buf, &extended);
573 if (ret)
574 goto out_unlock;
575
576 nt->extended = extended;
577 ret = strnlen(buf, count);
578 out_unlock:
579 mutex_unlock(&dynamic_netconsole_mutex);
580 return ret;
581 }
582
dev_name_store(struct config_item * item,const char * buf,size_t count)583 static ssize_t dev_name_store(struct config_item *item, const char *buf,
584 size_t count)
585 {
586 struct netconsole_target *nt = to_target(item);
587
588 mutex_lock(&dynamic_netconsole_mutex);
589 if (nt->enabled) {
590 pr_err("target (%s) is enabled, disable to update parameters\n",
591 config_item_name(&nt->group.cg_item));
592 mutex_unlock(&dynamic_netconsole_mutex);
593 return -EINVAL;
594 }
595
596 strscpy(nt->np.dev_name, buf, IFNAMSIZ);
597 trim_newline(nt->np.dev_name, IFNAMSIZ);
598
599 mutex_unlock(&dynamic_netconsole_mutex);
600 return strnlen(buf, count);
601 }
602
local_port_store(struct config_item * item,const char * buf,size_t count)603 static ssize_t local_port_store(struct config_item *item, const char *buf,
604 size_t count)
605 {
606 struct netconsole_target *nt = to_target(item);
607 ssize_t ret = -EINVAL;
608
609 mutex_lock(&dynamic_netconsole_mutex);
610 if (nt->enabled) {
611 pr_err("target (%s) is enabled, disable to update parameters\n",
612 config_item_name(&nt->group.cg_item));
613 goto out_unlock;
614 }
615
616 ret = kstrtou16(buf, 10, &nt->np.local_port);
617 if (ret < 0)
618 goto out_unlock;
619 ret = strnlen(buf, count);
620 out_unlock:
621 mutex_unlock(&dynamic_netconsole_mutex);
622 return ret;
623 }
624
remote_port_store(struct config_item * item,const char * buf,size_t count)625 static ssize_t remote_port_store(struct config_item *item,
626 const char *buf, size_t count)
627 {
628 struct netconsole_target *nt = to_target(item);
629 ssize_t ret = -EINVAL;
630
631 mutex_lock(&dynamic_netconsole_mutex);
632 if (nt->enabled) {
633 pr_err("target (%s) is enabled, disable to update parameters\n",
634 config_item_name(&nt->group.cg_item));
635 goto out_unlock;
636 }
637
638 ret = kstrtou16(buf, 10, &nt->np.remote_port);
639 if (ret < 0)
640 goto out_unlock;
641 ret = strnlen(buf, count);
642 out_unlock:
643 mutex_unlock(&dynamic_netconsole_mutex);
644 return ret;
645 }
646
local_ip_store(struct config_item * item,const char * buf,size_t count)647 static ssize_t local_ip_store(struct config_item *item, const char *buf,
648 size_t count)
649 {
650 struct netconsole_target *nt = to_target(item);
651 ssize_t ret = -EINVAL;
652
653 mutex_lock(&dynamic_netconsole_mutex);
654 if (nt->enabled) {
655 pr_err("target (%s) is enabled, disable to update parameters\n",
656 config_item_name(&nt->group.cg_item));
657 goto out_unlock;
658 }
659
660 if (strnchr(buf, count, ':')) {
661 const char *end;
662
663 if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {
664 if (*end && *end != '\n') {
665 pr_err("invalid IPv6 address at: <%c>\n", *end);
666 goto out_unlock;
667 }
668 nt->np.ipv6 = true;
669 } else
670 goto out_unlock;
671 } else {
672 if (!nt->np.ipv6)
673 nt->np.local_ip.ip = in_aton(buf);
674 else
675 goto out_unlock;
676 }
677
678 ret = strnlen(buf, count);
679 out_unlock:
680 mutex_unlock(&dynamic_netconsole_mutex);
681 return ret;
682 }
683
remote_ip_store(struct config_item * item,const char * buf,size_t count)684 static ssize_t remote_ip_store(struct config_item *item, const char *buf,
685 size_t count)
686 {
687 struct netconsole_target *nt = to_target(item);
688 ssize_t ret = -EINVAL;
689
690 mutex_lock(&dynamic_netconsole_mutex);
691 if (nt->enabled) {
692 pr_err("target (%s) is enabled, disable to update parameters\n",
693 config_item_name(&nt->group.cg_item));
694 goto out_unlock;
695 }
696
697 if (strnchr(buf, count, ':')) {
698 const char *end;
699
700 if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {
701 if (*end && *end != '\n') {
702 pr_err("invalid IPv6 address at: <%c>\n", *end);
703 goto out_unlock;
704 }
705 nt->np.ipv6 = true;
706 } else
707 goto out_unlock;
708 } else {
709 if (!nt->np.ipv6)
710 nt->np.remote_ip.ip = in_aton(buf);
711 else
712 goto out_unlock;
713 }
714
715 ret = strnlen(buf, count);
716 out_unlock:
717 mutex_unlock(&dynamic_netconsole_mutex);
718 return ret;
719 }
720
721 /* Count number of entries we have in extradata.
722 * This is important because the extradata_complete only supports
723 * MAX_EXTRADATA_ITEMS entries. Before enabling any new {user,sys}data
724 * feature, number of entries needs to checked for available space.
725 */
count_extradata_entries(struct netconsole_target * nt)726 static size_t count_extradata_entries(struct netconsole_target *nt)
727 {
728 size_t entries;
729
730 /* Userdata entries */
731 entries = list_count_nodes(&nt->userdata_group.cg_children);
732 /* Plus sysdata entries */
733 if (nt->sysdata_fields & SYSDATA_CPU_NR)
734 entries += 1;
735 if (nt->sysdata_fields & SYSDATA_TASKNAME)
736 entries += 1;
737 if (nt->sysdata_fields & SYSDATA_RELEASE)
738 entries += 1;
739
740 return entries;
741 }
742
remote_mac_store(struct config_item * item,const char * buf,size_t count)743 static ssize_t remote_mac_store(struct config_item *item, const char *buf,
744 size_t count)
745 {
746 struct netconsole_target *nt = to_target(item);
747 u8 remote_mac[ETH_ALEN];
748 ssize_t ret = -EINVAL;
749
750 mutex_lock(&dynamic_netconsole_mutex);
751 if (nt->enabled) {
752 pr_err("target (%s) is enabled, disable to update parameters\n",
753 config_item_name(&nt->group.cg_item));
754 goto out_unlock;
755 }
756
757 if (!mac_pton(buf, remote_mac))
758 goto out_unlock;
759 if (buf[MAC_ADDR_STR_LEN] && buf[MAC_ADDR_STR_LEN] != '\n')
760 goto out_unlock;
761 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
762
763 ret = strnlen(buf, count);
764 out_unlock:
765 mutex_unlock(&dynamic_netconsole_mutex);
766 return ret;
767 }
768
769 struct userdatum {
770 struct config_item item;
771 char value[MAX_EXTRADATA_VALUE_LEN];
772 };
773
to_userdatum(struct config_item * item)774 static struct userdatum *to_userdatum(struct config_item *item)
775 {
776 return container_of(item, struct userdatum, item);
777 }
778
779 struct userdata {
780 struct config_group group;
781 };
782
to_userdata(struct config_item * item)783 static struct userdata *to_userdata(struct config_item *item)
784 {
785 return container_of(to_config_group(item), struct userdata, group);
786 }
787
userdata_to_target(struct userdata * ud)788 static struct netconsole_target *userdata_to_target(struct userdata *ud)
789 {
790 struct config_group *netconsole_group;
791
792 netconsole_group = to_config_group(ud->group.cg_item.ci_parent);
793 return to_target(&netconsole_group->cg_item);
794 }
795
userdatum_value_show(struct config_item * item,char * buf)796 static ssize_t userdatum_value_show(struct config_item *item, char *buf)
797 {
798 return sysfs_emit(buf, "%s\n", &(to_userdatum(item)->value[0]));
799 }
800
update_userdata(struct netconsole_target * nt)801 static void update_userdata(struct netconsole_target *nt)
802 {
803 int complete_idx = 0, child_count = 0;
804 struct list_head *entry;
805
806 /* Clear the current string in case the last userdatum was deleted */
807 nt->userdata_length = 0;
808 nt->extradata_complete[0] = 0;
809
810 list_for_each(entry, &nt->userdata_group.cg_children) {
811 struct userdatum *udm_item;
812 struct config_item *item;
813
814 if (WARN_ON_ONCE(child_count >= MAX_EXTRADATA_ITEMS))
815 break;
816 child_count++;
817
818 item = container_of(entry, struct config_item, ci_entry);
819 udm_item = to_userdatum(item);
820
821 /* Skip userdata with no value set */
822 if (strnlen(udm_item->value, MAX_EXTRADATA_VALUE_LEN) == 0)
823 continue;
824
825 /* This doesn't overflow extradata_complete since it will write
826 * one entry length (1/MAX_EXTRADATA_ITEMS long), entry count is
827 * checked to not exceed MAX items with child_count above
828 */
829 complete_idx += scnprintf(&nt->extradata_complete[complete_idx],
830 MAX_EXTRADATA_ENTRY_LEN, " %s=%s\n",
831 item->ci_name, udm_item->value);
832 }
833 nt->userdata_length = strnlen(nt->extradata_complete,
834 sizeof(nt->extradata_complete));
835 }
836
userdatum_value_store(struct config_item * item,const char * buf,size_t count)837 static ssize_t userdatum_value_store(struct config_item *item, const char *buf,
838 size_t count)
839 {
840 struct userdatum *udm = to_userdatum(item);
841 struct netconsole_target *nt;
842 struct userdata *ud;
843 ssize_t ret;
844
845 if (count > MAX_EXTRADATA_VALUE_LEN)
846 return -EMSGSIZE;
847
848 mutex_lock(&dynamic_netconsole_mutex);
849
850 ret = strscpy(udm->value, buf, sizeof(udm->value));
851 if (ret < 0)
852 goto out_unlock;
853 trim_newline(udm->value, sizeof(udm->value));
854
855 ud = to_userdata(item->ci_parent);
856 nt = userdata_to_target(ud);
857 update_userdata(nt);
858 ret = count;
859 out_unlock:
860 mutex_unlock(&dynamic_netconsole_mutex);
861 return ret;
862 }
863
864 /* disable_sysdata_feature - Disable sysdata feature and clean sysdata
865 * @nt: target that is disabling the feature
866 * @feature: feature being disabled
867 */
disable_sysdata_feature(struct netconsole_target * nt,enum sysdata_feature feature)868 static void disable_sysdata_feature(struct netconsole_target *nt,
869 enum sysdata_feature feature)
870 {
871 nt->sysdata_fields &= ~feature;
872 nt->extradata_complete[nt->userdata_length] = 0;
873 }
874
sysdata_release_enabled_store(struct config_item * item,const char * buf,size_t count)875 static ssize_t sysdata_release_enabled_store(struct config_item *item,
876 const char *buf, size_t count)
877 {
878 struct netconsole_target *nt = to_target(item->ci_parent);
879 bool release_enabled, curr;
880 ssize_t ret;
881
882 ret = kstrtobool(buf, &release_enabled);
883 if (ret)
884 return ret;
885
886 mutex_lock(&dynamic_netconsole_mutex);
887 curr = !!(nt->sysdata_fields & SYSDATA_RELEASE);
888 if (release_enabled == curr)
889 goto unlock_ok;
890
891 if (release_enabled &&
892 count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
893 ret = -ENOSPC;
894 goto unlock;
895 }
896
897 if (release_enabled)
898 nt->sysdata_fields |= SYSDATA_RELEASE;
899 else
900 disable_sysdata_feature(nt, SYSDATA_RELEASE);
901
902 unlock_ok:
903 ret = strnlen(buf, count);
904 unlock:
905 mutex_unlock(&dynamic_netconsole_mutex);
906 return ret;
907 }
908
sysdata_taskname_enabled_store(struct config_item * item,const char * buf,size_t count)909 static ssize_t sysdata_taskname_enabled_store(struct config_item *item,
910 const char *buf, size_t count)
911 {
912 struct netconsole_target *nt = to_target(item->ci_parent);
913 bool taskname_enabled, curr;
914 ssize_t ret;
915
916 ret = kstrtobool(buf, &taskname_enabled);
917 if (ret)
918 return ret;
919
920 mutex_lock(&dynamic_netconsole_mutex);
921 curr = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
922 if (taskname_enabled == curr)
923 goto unlock_ok;
924
925 if (taskname_enabled &&
926 count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
927 ret = -ENOSPC;
928 goto unlock;
929 }
930
931 if (taskname_enabled)
932 nt->sysdata_fields |= SYSDATA_TASKNAME;
933 else
934 disable_sysdata_feature(nt, SYSDATA_TASKNAME);
935
936 unlock_ok:
937 ret = strnlen(buf, count);
938 unlock:
939 mutex_unlock(&dynamic_netconsole_mutex);
940 return ret;
941 }
942
943 /* configfs helper to sysdata cpu_nr feature */
sysdata_cpu_nr_enabled_store(struct config_item * item,const char * buf,size_t count)944 static ssize_t sysdata_cpu_nr_enabled_store(struct config_item *item,
945 const char *buf, size_t count)
946 {
947 struct netconsole_target *nt = to_target(item->ci_parent);
948 bool cpu_nr_enabled, curr;
949 ssize_t ret;
950
951 ret = kstrtobool(buf, &cpu_nr_enabled);
952 if (ret)
953 return ret;
954
955 mutex_lock(&dynamic_netconsole_mutex);
956 curr = !!(nt->sysdata_fields & SYSDATA_CPU_NR);
957 if (cpu_nr_enabled == curr)
958 /* no change requested */
959 goto unlock_ok;
960
961 if (cpu_nr_enabled &&
962 count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
963 /* user wants the new feature, but there is no space in the
964 * buffer.
965 */
966 ret = -ENOSPC;
967 goto unlock;
968 }
969
970 if (cpu_nr_enabled)
971 nt->sysdata_fields |= SYSDATA_CPU_NR;
972 else
973 /* This is special because extradata_complete might have
974 * remaining data from previous sysdata, and it needs to be
975 * cleaned.
976 */
977 disable_sysdata_feature(nt, SYSDATA_CPU_NR);
978
979 unlock_ok:
980 ret = strnlen(buf, count);
981 unlock:
982 mutex_unlock(&dynamic_netconsole_mutex);
983 return ret;
984 }
985
986 CONFIGFS_ATTR(userdatum_, value);
987 CONFIGFS_ATTR(sysdata_, cpu_nr_enabled);
988 CONFIGFS_ATTR(sysdata_, taskname_enabled);
989 CONFIGFS_ATTR(sysdata_, release_enabled);
990
991 static struct configfs_attribute *userdatum_attrs[] = {
992 &userdatum_attr_value,
993 NULL,
994 };
995
userdatum_release(struct config_item * item)996 static void userdatum_release(struct config_item *item)
997 {
998 kfree(to_userdatum(item));
999 }
1000
1001 static struct configfs_item_operations userdatum_ops = {
1002 .release = userdatum_release,
1003 };
1004
1005 static const struct config_item_type userdatum_type = {
1006 .ct_item_ops = &userdatum_ops,
1007 .ct_attrs = userdatum_attrs,
1008 .ct_owner = THIS_MODULE,
1009 };
1010
userdatum_make_item(struct config_group * group,const char * name)1011 static struct config_item *userdatum_make_item(struct config_group *group,
1012 const char *name)
1013 {
1014 struct netconsole_target *nt;
1015 struct userdatum *udm;
1016 struct userdata *ud;
1017
1018 if (strlen(name) > MAX_EXTRADATA_NAME_LEN)
1019 return ERR_PTR(-ENAMETOOLONG);
1020
1021 ud = to_userdata(&group->cg_item);
1022 nt = userdata_to_target(ud);
1023 if (count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS)
1024 return ERR_PTR(-ENOSPC);
1025
1026 udm = kzalloc(sizeof(*udm), GFP_KERNEL);
1027 if (!udm)
1028 return ERR_PTR(-ENOMEM);
1029
1030 config_item_init_type_name(&udm->item, name, &userdatum_type);
1031 return &udm->item;
1032 }
1033
userdatum_drop(struct config_group * group,struct config_item * item)1034 static void userdatum_drop(struct config_group *group, struct config_item *item)
1035 {
1036 struct netconsole_target *nt;
1037 struct userdata *ud;
1038
1039 ud = to_userdata(&group->cg_item);
1040 nt = userdata_to_target(ud);
1041
1042 mutex_lock(&dynamic_netconsole_mutex);
1043 update_userdata(nt);
1044 config_item_put(item);
1045 mutex_unlock(&dynamic_netconsole_mutex);
1046 }
1047
1048 static struct configfs_attribute *userdata_attrs[] = {
1049 &sysdata_attr_cpu_nr_enabled,
1050 &sysdata_attr_taskname_enabled,
1051 &sysdata_attr_release_enabled,
1052 NULL,
1053 };
1054
1055 static struct configfs_group_operations userdata_ops = {
1056 .make_item = userdatum_make_item,
1057 .drop_item = userdatum_drop,
1058 };
1059
1060 static const struct config_item_type userdata_type = {
1061 .ct_item_ops = &userdatum_ops,
1062 .ct_group_ops = &userdata_ops,
1063 .ct_attrs = userdata_attrs,
1064 .ct_owner = THIS_MODULE,
1065 };
1066
1067 CONFIGFS_ATTR(, enabled);
1068 CONFIGFS_ATTR(, extended);
1069 CONFIGFS_ATTR(, dev_name);
1070 CONFIGFS_ATTR(, local_port);
1071 CONFIGFS_ATTR(, remote_port);
1072 CONFIGFS_ATTR(, local_ip);
1073 CONFIGFS_ATTR(, remote_ip);
1074 CONFIGFS_ATTR_RO(, local_mac);
1075 CONFIGFS_ATTR(, remote_mac);
1076 CONFIGFS_ATTR(, release);
1077 CONFIGFS_ATTR_RO(, transmit_errors);
1078
1079 static struct configfs_attribute *netconsole_target_attrs[] = {
1080 &attr_enabled,
1081 &attr_extended,
1082 &attr_release,
1083 &attr_dev_name,
1084 &attr_local_port,
1085 &attr_remote_port,
1086 &attr_local_ip,
1087 &attr_remote_ip,
1088 &attr_local_mac,
1089 &attr_remote_mac,
1090 &attr_transmit_errors,
1091 NULL,
1092 };
1093
1094 /*
1095 * Item operations and type for netconsole_target.
1096 */
1097
netconsole_target_release(struct config_item * item)1098 static void netconsole_target_release(struct config_item *item)
1099 {
1100 kfree(to_target(item));
1101 }
1102
1103 static struct configfs_item_operations netconsole_target_item_ops = {
1104 .release = netconsole_target_release,
1105 };
1106
1107 static const struct config_item_type netconsole_target_type = {
1108 .ct_attrs = netconsole_target_attrs,
1109 .ct_item_ops = &netconsole_target_item_ops,
1110 .ct_owner = THIS_MODULE,
1111 };
1112
init_target_config_group(struct netconsole_target * nt,const char * name)1113 static void init_target_config_group(struct netconsole_target *nt,
1114 const char *name)
1115 {
1116 config_group_init_type_name(&nt->group, name, &netconsole_target_type);
1117 config_group_init_type_name(&nt->userdata_group, "userdata",
1118 &userdata_type);
1119 configfs_add_default_group(&nt->userdata_group, &nt->group);
1120 }
1121
find_cmdline_target(const char * name)1122 static struct netconsole_target *find_cmdline_target(const char *name)
1123 {
1124 struct netconsole_target *nt, *ret = NULL;
1125 unsigned long flags;
1126
1127 spin_lock_irqsave(&target_list_lock, flags);
1128 list_for_each_entry(nt, &target_list, list) {
1129 if (!strcmp(nt->group.cg_item.ci_name, name)) {
1130 ret = nt;
1131 break;
1132 }
1133 }
1134 spin_unlock_irqrestore(&target_list_lock, flags);
1135
1136 return ret;
1137 }
1138
1139 /*
1140 * Group operations and type for netconsole_subsys.
1141 */
1142
make_netconsole_target(struct config_group * group,const char * name)1143 static struct config_group *make_netconsole_target(struct config_group *group,
1144 const char *name)
1145 {
1146 struct netconsole_target *nt;
1147 unsigned long flags;
1148
1149 /* Checking if a target by this name was created at boot time. If so,
1150 * attach a configfs entry to that target. This enables dynamic
1151 * control.
1152 */
1153 if (!strncmp(name, NETCONSOLE_PARAM_TARGET_PREFIX,
1154 strlen(NETCONSOLE_PARAM_TARGET_PREFIX))) {
1155 nt = find_cmdline_target(name);
1156 if (nt) {
1157 init_target_config_group(nt, name);
1158 return &nt->group;
1159 }
1160 }
1161
1162 nt = alloc_and_init();
1163 if (!nt)
1164 return ERR_PTR(-ENOMEM);
1165
1166 /* Initialize the config_group member */
1167 init_target_config_group(nt, name);
1168
1169 /* Adding, but it is disabled */
1170 spin_lock_irqsave(&target_list_lock, flags);
1171 list_add(&nt->list, &target_list);
1172 spin_unlock_irqrestore(&target_list_lock, flags);
1173
1174 return &nt->group;
1175 }
1176
drop_netconsole_target(struct config_group * group,struct config_item * item)1177 static void drop_netconsole_target(struct config_group *group,
1178 struct config_item *item)
1179 {
1180 unsigned long flags;
1181 struct netconsole_target *nt = to_target(item);
1182
1183 spin_lock_irqsave(&target_list_lock, flags);
1184 list_del(&nt->list);
1185 spin_unlock_irqrestore(&target_list_lock, flags);
1186
1187 /*
1188 * The target may have never been enabled, or was manually disabled
1189 * before being removed so netpoll may have already been cleaned up.
1190 */
1191 if (nt->enabled)
1192 netpoll_cleanup(&nt->np);
1193
1194 config_item_put(&nt->group.cg_item);
1195 }
1196
1197 static struct configfs_group_operations netconsole_subsys_group_ops = {
1198 .make_group = make_netconsole_target,
1199 .drop_item = drop_netconsole_target,
1200 };
1201
1202 static const struct config_item_type netconsole_subsys_type = {
1203 .ct_group_ops = &netconsole_subsys_group_ops,
1204 .ct_owner = THIS_MODULE,
1205 };
1206
1207 /* The netconsole configfs subsystem */
1208 static struct configfs_subsystem netconsole_subsys = {
1209 .su_group = {
1210 .cg_item = {
1211 .ci_namebuf = "netconsole",
1212 .ci_type = &netconsole_subsys_type,
1213 },
1214 },
1215 };
1216
populate_configfs_item(struct netconsole_target * nt,int cmdline_count)1217 static void populate_configfs_item(struct netconsole_target *nt,
1218 int cmdline_count)
1219 {
1220 char target_name[16];
1221
1222 snprintf(target_name, sizeof(target_name), "%s%d",
1223 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1224 init_target_config_group(nt, target_name);
1225 }
1226
sysdata_append_cpu_nr(struct netconsole_target * nt,int offset)1227 static int sysdata_append_cpu_nr(struct netconsole_target *nt, int offset)
1228 {
1229 /* Append cpu=%d at extradata_complete after userdata str */
1230 return scnprintf(&nt->extradata_complete[offset],
1231 MAX_EXTRADATA_ENTRY_LEN, " cpu=%u\n",
1232 raw_smp_processor_id());
1233 }
1234
sysdata_append_taskname(struct netconsole_target * nt,int offset)1235 static int sysdata_append_taskname(struct netconsole_target *nt, int offset)
1236 {
1237 return scnprintf(&nt->extradata_complete[offset],
1238 MAX_EXTRADATA_ENTRY_LEN, " taskname=%s\n",
1239 current->comm);
1240 }
1241
sysdata_append_release(struct netconsole_target * nt,int offset)1242 static int sysdata_append_release(struct netconsole_target *nt, int offset)
1243 {
1244 return scnprintf(&nt->extradata_complete[offset],
1245 MAX_EXTRADATA_ENTRY_LEN, " release=%s\n",
1246 init_utsname()->release);
1247 }
1248
1249 /*
1250 * prepare_extradata - append sysdata at extradata_complete in runtime
1251 * @nt: target to send message to
1252 */
prepare_extradata(struct netconsole_target * nt)1253 static int prepare_extradata(struct netconsole_target *nt)
1254 {
1255 int extradata_len;
1256
1257 /* userdata was appended when configfs write helper was called
1258 * by update_userdata().
1259 */
1260 extradata_len = nt->userdata_length;
1261
1262 if (!nt->sysdata_fields)
1263 goto out;
1264
1265 if (nt->sysdata_fields & SYSDATA_CPU_NR)
1266 extradata_len += sysdata_append_cpu_nr(nt, extradata_len);
1267 if (nt->sysdata_fields & SYSDATA_TASKNAME)
1268 extradata_len += sysdata_append_taskname(nt, extradata_len);
1269 if (nt->sysdata_fields & SYSDATA_RELEASE)
1270 extradata_len += sysdata_append_release(nt, extradata_len);
1271
1272 WARN_ON_ONCE(extradata_len >
1273 MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS);
1274
1275 out:
1276 return extradata_len;
1277 }
1278 #else /* CONFIG_NETCONSOLE_DYNAMIC not set */
prepare_extradata(struct netconsole_target * nt)1279 static int prepare_extradata(struct netconsole_target *nt)
1280 {
1281 return 0;
1282 }
1283 #endif /* CONFIG_NETCONSOLE_DYNAMIC */
1284
1285 /* Handle network interface device notifications */
netconsole_netdev_event(struct notifier_block * this,unsigned long event,void * ptr)1286 static int netconsole_netdev_event(struct notifier_block *this,
1287 unsigned long event, void *ptr)
1288 {
1289 unsigned long flags;
1290 struct netconsole_target *nt, *tmp;
1291 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1292 bool stopped = false;
1293
1294 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
1295 event == NETDEV_RELEASE || event == NETDEV_JOIN))
1296 goto done;
1297
1298 mutex_lock(&target_cleanup_list_lock);
1299 spin_lock_irqsave(&target_list_lock, flags);
1300 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1301 netconsole_target_get(nt);
1302 if (nt->np.dev == dev) {
1303 switch (event) {
1304 case NETDEV_CHANGENAME:
1305 strscpy(nt->np.dev_name, dev->name, IFNAMSIZ);
1306 break;
1307 case NETDEV_RELEASE:
1308 case NETDEV_JOIN:
1309 case NETDEV_UNREGISTER:
1310 nt->enabled = false;
1311 list_move(&nt->list, &target_cleanup_list);
1312 stopped = true;
1313 }
1314 }
1315 netconsole_target_put(nt);
1316 }
1317 spin_unlock_irqrestore(&target_list_lock, flags);
1318 mutex_unlock(&target_cleanup_list_lock);
1319
1320 if (stopped) {
1321 const char *msg = "had an event";
1322
1323 switch (event) {
1324 case NETDEV_UNREGISTER:
1325 msg = "unregistered";
1326 break;
1327 case NETDEV_RELEASE:
1328 msg = "released slaves";
1329 break;
1330 case NETDEV_JOIN:
1331 msg = "is joining a master device";
1332 break;
1333 }
1334 pr_info("network logging stopped on interface %s as it %s\n",
1335 dev->name, msg);
1336 }
1337
1338 /* Process target_cleanup_list entries. By the end, target_cleanup_list
1339 * should be empty
1340 */
1341 netconsole_process_cleanups_core();
1342
1343 done:
1344 return NOTIFY_DONE;
1345 }
1346
1347 static struct notifier_block netconsole_netdev_notifier = {
1348 .notifier_call = netconsole_netdev_event,
1349 };
1350
1351 /**
1352 * send_udp - Wrapper for netpoll_send_udp that counts errors
1353 * @nt: target to send message to
1354 * @msg: message to send
1355 * @len: length of message
1356 *
1357 * Calls netpoll_send_udp and classifies the return value. If an error
1358 * occurred it increments statistics in nt->stats accordingly.
1359 * Only calls netpoll_send_udp if CONFIG_NETCONSOLE_DYNAMIC is disabled.
1360 */
send_udp(struct netconsole_target * nt,const char * msg,int len)1361 static void send_udp(struct netconsole_target *nt, const char *msg, int len)
1362 {
1363 int result = netpoll_send_udp(&nt->np, msg, len);
1364
1365 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC)) {
1366 if (result == NET_XMIT_DROP) {
1367 u64_stats_update_begin(&nt->stats.syncp);
1368 u64_stats_inc(&nt->stats.xmit_drop_count);
1369 u64_stats_update_end(&nt->stats.syncp);
1370 } else if (result == -ENOMEM) {
1371 u64_stats_update_begin(&nt->stats.syncp);
1372 u64_stats_inc(&nt->stats.enomem_count);
1373 u64_stats_update_end(&nt->stats.syncp);
1374 }
1375 }
1376 }
1377
send_msg_no_fragmentation(struct netconsole_target * nt,const char * msg,int msg_len,int release_len)1378 static void send_msg_no_fragmentation(struct netconsole_target *nt,
1379 const char *msg,
1380 int msg_len,
1381 int release_len)
1382 {
1383 const char *extradata = NULL;
1384 const char *release;
1385
1386 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1387 extradata = nt->extradata_complete;
1388 #endif
1389
1390 if (release_len) {
1391 release = init_utsname()->release;
1392
1393 scnprintf(nt->buf, MAX_PRINT_CHUNK, "%s,%s", release, msg);
1394 msg_len += release_len;
1395 } else {
1396 memcpy(nt->buf, msg, msg_len);
1397 }
1398
1399 if (extradata)
1400 msg_len += scnprintf(&nt->buf[msg_len],
1401 MAX_PRINT_CHUNK - msg_len,
1402 "%s", extradata);
1403
1404 send_udp(nt, nt->buf, msg_len);
1405 }
1406
append_release(char * buf)1407 static void append_release(char *buf)
1408 {
1409 const char *release;
1410
1411 release = init_utsname()->release;
1412 scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release);
1413 }
1414
send_fragmented_body(struct netconsole_target * nt,const char * msgbody,int header_len,int msgbody_len,int extradata_len)1415 static void send_fragmented_body(struct netconsole_target *nt,
1416 const char *msgbody, int header_len,
1417 int msgbody_len, int extradata_len)
1418 {
1419 int sent_extradata, preceding_bytes;
1420 const char *extradata = NULL;
1421 int body_len, offset = 0;
1422
1423 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1424 extradata = nt->extradata_complete;
1425 #endif
1426
1427 /* body_len represents the number of bytes that will be sent. This is
1428 * bigger than MAX_PRINT_CHUNK, thus, it will be split in multiple
1429 * packets
1430 */
1431 body_len = msgbody_len + extradata_len;
1432
1433 /* In each iteration of the while loop below, we send a packet
1434 * containing the header and a portion of the body. The body is
1435 * composed of two parts: msgbody and extradata. We keep track of how
1436 * many bytes have been sent so far using the offset variable, which
1437 * ranges from 0 to the total length of the body.
1438 */
1439 while (offset < body_len) {
1440 int this_header = header_len;
1441 bool msgbody_written = false;
1442 int this_offset = 0;
1443 int this_chunk = 0;
1444
1445 this_header += scnprintf(nt->buf + this_header,
1446 MAX_PRINT_CHUNK - this_header,
1447 ",ncfrag=%d/%d;", offset,
1448 body_len);
1449
1450 /* Not all msgbody data has been written yet */
1451 if (offset < msgbody_len) {
1452 this_chunk = min(msgbody_len - offset,
1453 MAX_PRINT_CHUNK - this_header);
1454 if (WARN_ON_ONCE(this_chunk <= 0))
1455 return;
1456 memcpy(nt->buf + this_header, msgbody + offset,
1457 this_chunk);
1458 this_offset += this_chunk;
1459 }
1460
1461 /* msgbody was finally written, either in the previous
1462 * messages and/or in the current buf. Time to write
1463 * the extradata.
1464 */
1465 msgbody_written |= offset + this_offset >= msgbody_len;
1466
1467 /* Msg body is fully written and there is pending extradata to
1468 * write, append extradata in this chunk
1469 */
1470 if (msgbody_written && offset + this_offset < body_len) {
1471 /* Track how much user data was already sent. First
1472 * time here, sent_userdata is zero
1473 */
1474 sent_extradata = (offset + this_offset) - msgbody_len;
1475 /* offset of bytes used in current buf */
1476 preceding_bytes = this_chunk + this_header;
1477
1478 if (WARN_ON_ONCE(sent_extradata < 0))
1479 return;
1480
1481 this_chunk = min(extradata_len - sent_extradata,
1482 MAX_PRINT_CHUNK - preceding_bytes);
1483 if (WARN_ON_ONCE(this_chunk < 0))
1484 /* this_chunk could be zero if all the previous
1485 * message used all the buffer. This is not a
1486 * problem, extradata will be sent in the next
1487 * iteration
1488 */
1489 return;
1490
1491 memcpy(nt->buf + this_header + this_offset,
1492 extradata + sent_extradata,
1493 this_chunk);
1494 this_offset += this_chunk;
1495 }
1496
1497 send_udp(nt, nt->buf, this_header + this_offset);
1498 offset += this_offset;
1499 }
1500 }
1501
send_msg_fragmented(struct netconsole_target * nt,const char * msg,int msg_len,int release_len,int extradata_len)1502 static void send_msg_fragmented(struct netconsole_target *nt,
1503 const char *msg,
1504 int msg_len,
1505 int release_len,
1506 int extradata_len)
1507 {
1508 int header_len, msgbody_len;
1509 const char *msgbody;
1510
1511 /* need to insert extra header fields, detect header and msgbody */
1512 msgbody = memchr(msg, ';', msg_len);
1513 if (WARN_ON_ONCE(!msgbody))
1514 return;
1515
1516 header_len = msgbody - msg;
1517 msgbody_len = msg_len - header_len - 1;
1518 msgbody++;
1519
1520 /*
1521 * Transfer multiple chunks with the following extra header.
1522 * "ncfrag=<byte-offset>/<total-bytes>"
1523 */
1524 if (release_len)
1525 append_release(nt->buf);
1526
1527 /* Copy the header into the buffer */
1528 memcpy(nt->buf + release_len, msg, header_len);
1529 header_len += release_len;
1530
1531 /* for now on, the header will be persisted, and the msgbody
1532 * will be replaced
1533 */
1534 send_fragmented_body(nt, msgbody, header_len, msgbody_len,
1535 extradata_len);
1536 }
1537
1538 /**
1539 * send_ext_msg_udp - send extended log message to target
1540 * @nt: target to send message to
1541 * @msg: extended log message to send
1542 * @msg_len: length of message
1543 *
1544 * Transfer extended log @msg to @nt. If @msg is longer than
1545 * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
1546 * ncfrag header field added to identify them.
1547 */
send_ext_msg_udp(struct netconsole_target * nt,const char * msg,int msg_len)1548 static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
1549 int msg_len)
1550 {
1551 int release_len = 0;
1552 int extradata_len;
1553
1554 extradata_len = prepare_extradata(nt);
1555
1556 if (nt->release)
1557 release_len = strlen(init_utsname()->release) + 1;
1558
1559 if (msg_len + release_len + extradata_len <= MAX_PRINT_CHUNK)
1560 return send_msg_no_fragmentation(nt, msg, msg_len, release_len);
1561
1562 return send_msg_fragmented(nt, msg, msg_len, release_len,
1563 extradata_len);
1564 }
1565
write_ext_msg(struct console * con,const char * msg,unsigned int len)1566 static void write_ext_msg(struct console *con, const char *msg,
1567 unsigned int len)
1568 {
1569 struct netconsole_target *nt;
1570 unsigned long flags;
1571
1572 if ((oops_only && !oops_in_progress) || list_empty(&target_list))
1573 return;
1574
1575 spin_lock_irqsave(&target_list_lock, flags);
1576 list_for_each_entry(nt, &target_list, list)
1577 if (nt->extended && nt->enabled && netif_running(nt->np.dev))
1578 send_ext_msg_udp(nt, msg, len);
1579 spin_unlock_irqrestore(&target_list_lock, flags);
1580 }
1581
write_msg(struct console * con,const char * msg,unsigned int len)1582 static void write_msg(struct console *con, const char *msg, unsigned int len)
1583 {
1584 int frag, left;
1585 unsigned long flags;
1586 struct netconsole_target *nt;
1587 const char *tmp;
1588
1589 if (oops_only && !oops_in_progress)
1590 return;
1591 /* Avoid taking lock and disabling interrupts unnecessarily */
1592 if (list_empty(&target_list))
1593 return;
1594
1595 spin_lock_irqsave(&target_list_lock, flags);
1596 list_for_each_entry(nt, &target_list, list) {
1597 if (!nt->extended && nt->enabled && netif_running(nt->np.dev)) {
1598 /*
1599 * We nest this inside the for-each-target loop above
1600 * so that we're able to get as much logging out to
1601 * at least one target if we die inside here, instead
1602 * of unnecessarily keeping all targets in lock-step.
1603 */
1604 tmp = msg;
1605 for (left = len; left;) {
1606 frag = min(left, MAX_PRINT_CHUNK);
1607 send_udp(nt, tmp, frag);
1608 tmp += frag;
1609 left -= frag;
1610 }
1611 }
1612 }
1613 spin_unlock_irqrestore(&target_list_lock, flags);
1614 }
1615
1616 /* Allocate new target (from boot/module param) and setup netpoll for it */
alloc_param_target(char * target_config,int cmdline_count)1617 static struct netconsole_target *alloc_param_target(char *target_config,
1618 int cmdline_count)
1619 {
1620 struct netconsole_target *nt;
1621 int err;
1622
1623 nt = alloc_and_init();
1624 if (!nt) {
1625 err = -ENOMEM;
1626 goto fail;
1627 }
1628
1629 if (*target_config == '+') {
1630 nt->extended = true;
1631 target_config++;
1632 }
1633
1634 if (*target_config == 'r') {
1635 if (!nt->extended) {
1636 pr_err("Netconsole configuration error. Release feature requires extended log message");
1637 err = -EINVAL;
1638 goto fail;
1639 }
1640 nt->release = true;
1641 target_config++;
1642 }
1643
1644 /* Parse parameters and setup netpoll */
1645 err = netpoll_parse_options(&nt->np, target_config);
1646 if (err)
1647 goto fail;
1648
1649 err = netpoll_setup(&nt->np);
1650 if (err) {
1651 pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n",
1652 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1653 if (!IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1654 /* only fail if dynamic reconfiguration is set,
1655 * otherwise, keep the target in the list, but disabled.
1656 */
1657 goto fail;
1658 } else {
1659 nt->enabled = true;
1660 }
1661 populate_configfs_item(nt, cmdline_count);
1662
1663 return nt;
1664
1665 fail:
1666 kfree(nt);
1667 return ERR_PTR(err);
1668 }
1669
1670 /* Cleanup netpoll for given target (from boot/module param) and free it */
free_param_target(struct netconsole_target * nt)1671 static void free_param_target(struct netconsole_target *nt)
1672 {
1673 netpoll_cleanup(&nt->np);
1674 kfree(nt);
1675 }
1676
1677 static struct console netconsole_ext = {
1678 .name = "netcon_ext",
1679 .flags = CON_ENABLED | CON_EXTENDED,
1680 .write = write_ext_msg,
1681 };
1682
1683 static struct console netconsole = {
1684 .name = "netcon",
1685 .flags = CON_ENABLED,
1686 .write = write_msg,
1687 };
1688
init_netconsole(void)1689 static int __init init_netconsole(void)
1690 {
1691 int err;
1692 struct netconsole_target *nt, *tmp;
1693 unsigned int count = 0;
1694 bool extended = false;
1695 unsigned long flags;
1696 char *target_config;
1697 char *input = config;
1698
1699 if (strnlen(input, MAX_PARAM_LENGTH)) {
1700 while ((target_config = strsep(&input, ";"))) {
1701 nt = alloc_param_target(target_config, count);
1702 if (IS_ERR(nt)) {
1703 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1704 continue;
1705 err = PTR_ERR(nt);
1706 goto fail;
1707 }
1708 /* Dump existing printks when we register */
1709 if (nt->extended) {
1710 extended = true;
1711 netconsole_ext.flags |= CON_PRINTBUFFER;
1712 } else {
1713 netconsole.flags |= CON_PRINTBUFFER;
1714 }
1715
1716 spin_lock_irqsave(&target_list_lock, flags);
1717 list_add(&nt->list, &target_list);
1718 spin_unlock_irqrestore(&target_list_lock, flags);
1719 count++;
1720 }
1721 }
1722
1723 err = register_netdevice_notifier(&netconsole_netdev_notifier);
1724 if (err)
1725 goto fail;
1726
1727 err = dynamic_netconsole_init();
1728 if (err)
1729 goto undonotifier;
1730
1731 if (extended)
1732 register_console(&netconsole_ext);
1733 register_console(&netconsole);
1734 pr_info("network logging started\n");
1735
1736 return err;
1737
1738 undonotifier:
1739 unregister_netdevice_notifier(&netconsole_netdev_notifier);
1740
1741 fail:
1742 pr_err("cleaning up\n");
1743
1744 /*
1745 * Remove all targets and destroy them (only targets created
1746 * from the boot/module option exist here). Skipping the list
1747 * lock is safe here, and netpoll_cleanup() will sleep.
1748 */
1749 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1750 list_del(&nt->list);
1751 free_param_target(nt);
1752 }
1753
1754 return err;
1755 }
1756
cleanup_netconsole(void)1757 static void __exit cleanup_netconsole(void)
1758 {
1759 struct netconsole_target *nt, *tmp;
1760
1761 if (console_is_registered(&netconsole_ext))
1762 unregister_console(&netconsole_ext);
1763 unregister_console(&netconsole);
1764 dynamic_netconsole_exit();
1765 unregister_netdevice_notifier(&netconsole_netdev_notifier);
1766
1767 /*
1768 * Targets created via configfs pin references on our module
1769 * and would first be rmdir(2)'ed from userspace. We reach
1770 * here only when they are already destroyed, and only those
1771 * created from the boot/module option are left, so remove and
1772 * destroy them. Skipping the list lock is safe here, and
1773 * netpoll_cleanup() will sleep.
1774 */
1775 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1776 list_del(&nt->list);
1777 free_param_target(nt);
1778 }
1779 }
1780
1781 /*
1782 * Use late_initcall to ensure netconsole is
1783 * initialized after network device driver if built-in.
1784 *
1785 * late_initcall() and module_init() are identical if built as module.
1786 */
1787 late_initcall(init_netconsole);
1788 module_exit(cleanup_netconsole);
1789