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/hex.h>
40 #include <linux/u64_stats_sync.h>
41 #include <linux/utsname.h>
42 #include <linux/rtnetlink.h>
43 #include <linux/workqueue.h>
44
45 MODULE_AUTHOR("Matt Mackall <mpm@selenic.com>");
46 MODULE_DESCRIPTION("Console driver for network interfaces");
47 MODULE_LICENSE("GPL");
48
49 #define MAX_PARAM_LENGTH 256
50 #define MAX_EXTRADATA_ENTRY_LEN 256
51 #define MAX_EXTRADATA_VALUE_LEN 200
52 /* The number 3 comes from userdata entry format characters (' ', '=', '\n') */
53 #define MAX_EXTRADATA_NAME_LEN (MAX_EXTRADATA_ENTRY_LEN - \
54 MAX_EXTRADATA_VALUE_LEN - 3)
55 #define MAX_USERDATA_ITEMS 256
56 #define MAX_PRINT_CHUNK 1000
57
58 static char config[MAX_PARAM_LENGTH];
59 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
60 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
61
62 static bool oops_only;
63 module_param(oops_only, bool, 0600);
64 MODULE_PARM_DESC(oops_only, "Only log oops messages");
65
66 #define NETCONSOLE_PARAM_TARGET_PREFIX "cmdline"
67
68 #ifndef MODULE
option_setup(char * opt)69 static int __init option_setup(char *opt)
70 {
71 strscpy(config, opt, MAX_PARAM_LENGTH);
72 return 1;
73 }
74 __setup("netconsole=", option_setup);
75 #endif /* MODULE */
76
77 /* Linked list of all configured targets */
78 static LIST_HEAD(target_list);
79 /* target_cleanup_list is used to track targets that need to be cleaned outside
80 * of target_list_lock. It should be cleaned in the same function it is
81 * populated.
82 */
83 static LIST_HEAD(target_cleanup_list);
84
85 /* This needs to be a spinlock because write_msg() cannot sleep */
86 static DEFINE_SPINLOCK(target_list_lock);
87 /* This needs to be a mutex because netpoll_cleanup might sleep */
88 static DEFINE_MUTEX(target_cleanup_list_lock);
89
90 static struct workqueue_struct *netconsole_wq;
91
92 /*
93 * Console driver for netconsoles. Register only consoles that have
94 * an associated target of the same type.
95 */
96 static struct console netconsole_ext, netconsole;
97
98 struct netconsole_target_stats {
99 u64_stats_t xmit_drop_count;
100 u64_stats_t enomem_count;
101 struct u64_stats_sync syncp;
102 };
103
104 enum console_type {
105 CONS_BASIC = BIT(0),
106 CONS_EXTENDED = BIT(1),
107 };
108
109 /* Features enabled in sysdata. Contrary to userdata, this data is populated by
110 * the kernel. The fields are designed as bitwise flags, allowing multiple
111 * features to be set in sysdata_fields.
112 */
113 enum sysdata_feature {
114 /* Populate the CPU that sends the message */
115 SYSDATA_CPU_NR = BIT(0),
116 /* Populate the task name (as in current->comm) in sysdata */
117 SYSDATA_TASKNAME = BIT(1),
118 /* Kernel release/version as part of sysdata */
119 SYSDATA_RELEASE = BIT(2),
120 /* Include a per-target message ID as part of sysdata */
121 SYSDATA_MSGID = BIT(3),
122 /* Sentinel: highest bit position */
123 MAX_SYSDATA_ITEMS = 4,
124 };
125
126 enum target_state {
127 STATE_DISABLED,
128 STATE_ENABLED,
129 STATE_DEACTIVATED,
130 };
131
132 /**
133 * struct netconsole_target - Represents a configured netconsole target.
134 * @list: Links this target into the target_list.
135 * @group: Links us into the configfs subsystem hierarchy.
136 * @userdata_group: Links to the userdata configfs hierarchy
137 * @userdata: Cached, formatted string of append
138 * @userdata_length: String length of userdata.
139 * @sysdata: Cached, formatted string of append
140 * @sysdata_fields: Sysdata features enabled.
141 * @msgcounter: Message sent counter.
142 * @stats: Packet send stats for the target. Used for debugging.
143 * @state: State of the target.
144 * Visible from userspace (read-write).
145 * From a userspace perspective, the target is either enabled or
146 * disabled. Internally, although both STATE_DISABLED and
147 * STATE_DEACTIVATED correspond to inactive targets, the latter is
148 * due to automatic interface state changes and will try
149 * recover automatically, if the interface comes back
150 * online.
151 * Also, other parameters of a target may be modified at
152 * runtime only when it is disabled (state != STATE_ENABLED).
153 * @extended: Denotes whether console is extended or not.
154 * @release: Denotes whether kernel release version should be prepended
155 * to the message. Depends on extended console.
156 * @np: The netpoll structure for this target.
157 * Contains the other userspace visible parameters:
158 * dev_name (read-write)
159 * local_port (read-write)
160 * remote_port (read-write)
161 * local_ip (read-write)
162 * remote_ip (read-write)
163 * local_mac (read-only)
164 * remote_mac (read-write)
165 * @buf: The buffer used to send the full msg to the network stack
166 * @resume_wq: Workqueue to resume deactivated target
167 */
168 struct netconsole_target {
169 struct list_head list;
170 #ifdef CONFIG_NETCONSOLE_DYNAMIC
171 struct config_group group;
172 struct config_group userdata_group;
173 char *userdata;
174 size_t userdata_length;
175 char sysdata[MAX_EXTRADATA_ENTRY_LEN * MAX_SYSDATA_ITEMS];
176
177 /* bit-wise with sysdata_feature bits */
178 u32 sysdata_fields;
179 /* protected by target_list_lock */
180 u32 msgcounter;
181 #endif
182 struct netconsole_target_stats stats;
183 enum target_state state;
184 bool extended;
185 bool release;
186 struct netpoll np;
187 /* protected by target_list_lock */
188 char buf[MAX_PRINT_CHUNK];
189 struct work_struct resume_wq;
190 };
191
192 #ifdef CONFIG_NETCONSOLE_DYNAMIC
193
194 static struct configfs_subsystem netconsole_subsys;
195 static DEFINE_MUTEX(dynamic_netconsole_mutex);
196
dynamic_netconsole_init(void)197 static int __init dynamic_netconsole_init(void)
198 {
199 config_group_init(&netconsole_subsys.su_group);
200 mutex_init(&netconsole_subsys.su_mutex);
201 return configfs_register_subsystem(&netconsole_subsys);
202 }
203
dynamic_netconsole_exit(void)204 static void __exit dynamic_netconsole_exit(void)
205 {
206 configfs_unregister_subsystem(&netconsole_subsys);
207 }
208
209 /*
210 * Targets that were created by parsing the boot/module option string
211 * do not exist in the configfs hierarchy (and have NULL names) and will
212 * never go away, so make these a no-op for them.
213 */
netconsole_target_get(struct netconsole_target * nt)214 static void netconsole_target_get(struct netconsole_target *nt)
215 {
216 if (config_item_name(&nt->group.cg_item))
217 config_group_get(&nt->group);
218 }
219
netconsole_target_put(struct netconsole_target * nt)220 static void netconsole_target_put(struct netconsole_target *nt)
221 {
222 if (config_item_name(&nt->group.cg_item))
223 config_group_put(&nt->group);
224 }
225
dynamic_netconsole_mutex_lock(void)226 static void dynamic_netconsole_mutex_lock(void)
227 {
228 mutex_lock(&dynamic_netconsole_mutex);
229 }
230
dynamic_netconsole_mutex_unlock(void)231 static void dynamic_netconsole_mutex_unlock(void)
232 {
233 mutex_unlock(&dynamic_netconsole_mutex);
234 }
235
236 #else /* !CONFIG_NETCONSOLE_DYNAMIC */
237
dynamic_netconsole_init(void)238 static int __init dynamic_netconsole_init(void)
239 {
240 return 0;
241 }
242
dynamic_netconsole_exit(void)243 static void __exit dynamic_netconsole_exit(void)
244 {
245 }
246
247 /*
248 * No danger of targets going away from under us when dynamic
249 * reconfigurability is off.
250 */
netconsole_target_get(struct netconsole_target * nt)251 static void netconsole_target_get(struct netconsole_target *nt)
252 {
253 }
254
netconsole_target_put(struct netconsole_target * nt)255 static void netconsole_target_put(struct netconsole_target *nt)
256 {
257 }
258
populate_configfs_item(struct netconsole_target * nt,int cmdline_count)259 static void populate_configfs_item(struct netconsole_target *nt,
260 int cmdline_count)
261 {
262 }
263
dynamic_netconsole_mutex_lock(void)264 static void dynamic_netconsole_mutex_lock(void)
265 {
266 }
267
dynamic_netconsole_mutex_unlock(void)268 static void dynamic_netconsole_mutex_unlock(void)
269 {
270 }
271
272 #endif /* CONFIG_NETCONSOLE_DYNAMIC */
273
274 /* Check if the target was bound by mac address. */
bound_by_mac(struct netconsole_target * nt)275 static bool bound_by_mac(struct netconsole_target *nt)
276 {
277 return is_valid_ether_addr(nt->np.dev_mac);
278 }
279
280 /* Attempts to resume logging to a deactivated target. */
resume_target(struct netconsole_target * nt)281 static void resume_target(struct netconsole_target *nt)
282 {
283 if (netpoll_setup(&nt->np)) {
284 /* netpoll fails setup once, do not try again. */
285 nt->state = STATE_DISABLED;
286 return;
287 }
288
289 nt->state = STATE_ENABLED;
290 pr_info("network logging resumed on interface %s\n", nt->np.dev_name);
291 }
292
293 /* Checks if a deactivated target matches a device. */
deactivated_target_match(struct netconsole_target * nt,struct net_device * ndev)294 static bool deactivated_target_match(struct netconsole_target *nt,
295 struct net_device *ndev)
296 {
297 if (nt->state != STATE_DEACTIVATED)
298 return false;
299
300 if (bound_by_mac(nt))
301 return !memcmp(nt->np.dev_mac, ndev->dev_addr, ETH_ALEN);
302 return !strncmp(nt->np.dev_name, ndev->name, IFNAMSIZ);
303 }
304
305 /* Process work scheduled for target resume. */
process_resume_target(struct work_struct * work)306 static void process_resume_target(struct work_struct *work)
307 {
308 struct netconsole_target *nt;
309 unsigned long flags;
310
311 nt = container_of(work, struct netconsole_target, resume_wq);
312
313 dynamic_netconsole_mutex_lock();
314
315 spin_lock_irqsave(&target_list_lock, flags);
316 /* Check if target is still deactivated as it may have been disabled
317 * while resume was being scheduled.
318 */
319 if (nt->state != STATE_DEACTIVATED) {
320 spin_unlock_irqrestore(&target_list_lock, flags);
321 goto out_unlock;
322 }
323
324 /* resume_target is IRQ unsafe, remove target from
325 * target_list in order to resume it with IRQ enabled.
326 */
327 list_del_init(&nt->list);
328 spin_unlock_irqrestore(&target_list_lock, flags);
329
330 resume_target(nt);
331
332 /* At this point the target is either enabled or disabled and
333 * was cleaned up before getting deactivated. Either way, add it
334 * back to target list.
335 */
336 spin_lock_irqsave(&target_list_lock, flags);
337 list_add(&nt->list, &target_list);
338 spin_unlock_irqrestore(&target_list_lock, flags);
339
340 out_unlock:
341 dynamic_netconsole_mutex_unlock();
342 }
343
344 /* Allocate and initialize with defaults.
345 * Note that these targets get their config_item fields zeroed-out.
346 */
alloc_and_init(void)347 static struct netconsole_target *alloc_and_init(void)
348 {
349 struct netconsole_target *nt;
350
351 nt = kzalloc_obj(*nt);
352 if (!nt)
353 return nt;
354
355 if (IS_ENABLED(CONFIG_NETCONSOLE_EXTENDED_LOG))
356 nt->extended = true;
357 if (IS_ENABLED(CONFIG_NETCONSOLE_PREPEND_RELEASE))
358 nt->release = true;
359
360 nt->np.name = "netconsole";
361 strscpy(nt->np.dev_name, "eth0", IFNAMSIZ);
362 nt->np.local_port = 6665;
363 nt->np.remote_port = 6666;
364 eth_broadcast_addr(nt->np.remote_mac);
365 nt->state = STATE_DISABLED;
366 INIT_WORK(&nt->resume_wq, process_resume_target);
367
368 return nt;
369 }
370
371 /* Clean up every target in the cleanup_list and move the clean targets back to
372 * the main target_list.
373 */
netconsole_process_cleanups_core(void)374 static void netconsole_process_cleanups_core(void)
375 {
376 struct netconsole_target *nt, *tmp;
377 unsigned long flags;
378
379 /* The cleanup needs RTNL locked */
380 ASSERT_RTNL();
381
382 mutex_lock(&target_cleanup_list_lock);
383 list_for_each_entry_safe(nt, tmp, &target_cleanup_list, list) {
384 /* all entries in the cleanup_list needs to be disabled */
385 WARN_ON_ONCE(nt->state == STATE_ENABLED);
386 do_netpoll_cleanup(&nt->np);
387 if (bound_by_mac(nt))
388 memset(&nt->np.dev_name, 0, IFNAMSIZ);
389 /* moved the cleaned target to target_list. Need to hold both
390 * locks
391 */
392 spin_lock_irqsave(&target_list_lock, flags);
393 list_move(&nt->list, &target_list);
394 spin_unlock_irqrestore(&target_list_lock, flags);
395 }
396 WARN_ON_ONCE(!list_empty(&target_cleanup_list));
397 mutex_unlock(&target_cleanup_list_lock);
398 }
399
netconsole_print_banner(struct netpoll * np)400 static void netconsole_print_banner(struct netpoll *np)
401 {
402 np_info(np, "local port %d\n", np->local_port);
403 if (np->ipv6)
404 np_info(np, "local IPv6 address %pI6c\n", &np->local_ip.in6);
405 else
406 np_info(np, "local IPv4 address %pI4\n", &np->local_ip.ip);
407 np_info(np, "interface name '%s'\n", np->dev_name);
408 np_info(np, "local ethernet address '%pM'\n", np->dev_mac);
409 np_info(np, "remote port %d\n", np->remote_port);
410 if (np->ipv6)
411 np_info(np, "remote IPv6 address %pI6c\n", &np->remote_ip.in6);
412 else
413 np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.ip);
414 np_info(np, "remote ethernet address %pM\n", np->remote_mac);
415 }
416
417 /* Parse the string and populate the `inet_addr` union. Return 0 if IPv4 is
418 * populated, 1 if IPv6 is populated, and -1 upon failure.
419 */
netpoll_parse_ip_addr(const char * str,union inet_addr * addr)420 static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr)
421 {
422 const char *end = NULL;
423 int len;
424
425 len = strlen(str);
426 if (!len)
427 return -1;
428
429 if (str[len - 1] == '\n')
430 len -= 1;
431
432 if (in4_pton(str, len, (void *)addr, -1, &end) > 0 &&
433 (!end || *end == 0 || *end == '\n'))
434 return 0;
435
436 if (IS_ENABLED(CONFIG_IPV6) &&
437 in6_pton(str, len, (void *)addr, -1, &end) > 0 &&
438 (!end || *end == 0 || *end == '\n'))
439 return 1;
440
441 return -1;
442 }
443
444 #ifdef CONFIG_NETCONSOLE_DYNAMIC
445
446 /*
447 * Our subsystem hierarchy is:
448 *
449 * /sys/kernel/config/netconsole/
450 * |
451 * <target>/
452 * | enabled
453 * | release
454 * | dev_name
455 * | local_port
456 * | remote_port
457 * | local_ip
458 * | remote_ip
459 * | local_mac
460 * | remote_mac
461 * | transmit_errors
462 * | userdata/
463 * | <key>/
464 * | value
465 * | ...
466 * |
467 * <target>/...
468 */
469
to_target(struct config_item * item)470 static struct netconsole_target *to_target(struct config_item *item)
471 {
472 struct config_group *cfg_group;
473
474 cfg_group = to_config_group(item);
475 if (!cfg_group)
476 return NULL;
477 return container_of(to_config_group(item),
478 struct netconsole_target, group);
479 }
480
481 /* Do the list cleanup with the rtnl lock hold. rtnl lock is necessary because
482 * netdev might be cleaned-up by calling __netpoll_cleanup(),
483 */
netconsole_process_cleanups(void)484 static void netconsole_process_cleanups(void)
485 {
486 /* rtnl lock is called here, because it has precedence over
487 * target_cleanup_list_lock mutex and target_cleanup_list
488 */
489 rtnl_lock();
490 netconsole_process_cleanups_core();
491 rtnl_unlock();
492 }
493
494 /* Get rid of possible trailing newline, returning the new length */
trim_newline(char * s,size_t maxlen)495 static void trim_newline(char *s, size_t maxlen)
496 {
497 size_t len;
498
499 len = strnlen(s, maxlen);
500 if (!len)
501 return;
502 if (s[len - 1] == '\n')
503 s[len - 1] = '\0';
504 }
505
506 /*
507 * Attribute operations for netconsole_target.
508 */
509
enabled_show(struct config_item * item,char * buf)510 static ssize_t enabled_show(struct config_item *item, char *buf)
511 {
512 return sysfs_emit(buf, "%d\n", to_target(item)->state == STATE_ENABLED);
513 }
514
extended_show(struct config_item * item,char * buf)515 static ssize_t extended_show(struct config_item *item, char *buf)
516 {
517 return sysfs_emit(buf, "%d\n", to_target(item)->extended);
518 }
519
release_show(struct config_item * item,char * buf)520 static ssize_t release_show(struct config_item *item, char *buf)
521 {
522 return sysfs_emit(buf, "%d\n", to_target(item)->release);
523 }
524
dev_name_show(struct config_item * item,char * buf)525 static ssize_t dev_name_show(struct config_item *item, char *buf)
526 {
527 return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name);
528 }
529
local_port_show(struct config_item * item,char * buf)530 static ssize_t local_port_show(struct config_item *item, char *buf)
531 {
532 return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port);
533 }
534
remote_port_show(struct config_item * item,char * buf)535 static ssize_t remote_port_show(struct config_item *item, char *buf)
536 {
537 return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port);
538 }
539
local_ip_show(struct config_item * item,char * buf)540 static ssize_t local_ip_show(struct config_item *item, char *buf)
541 {
542 struct netconsole_target *nt = to_target(item);
543
544 if (nt->np.ipv6)
545 return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6);
546 else
547 return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip);
548 }
549
remote_ip_show(struct config_item * item,char * buf)550 static ssize_t remote_ip_show(struct config_item *item, char *buf)
551 {
552 struct netconsole_target *nt = to_target(item);
553
554 if (nt->np.ipv6)
555 return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6);
556 else
557 return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip);
558 }
559
local_mac_show(struct config_item * item,char * buf)560 static ssize_t local_mac_show(struct config_item *item, char *buf)
561 {
562 struct net_device *dev = to_target(item)->np.dev;
563 static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
564
565 return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast);
566 }
567
remote_mac_show(struct config_item * item,char * buf)568 static ssize_t remote_mac_show(struct config_item *item, char *buf)
569 {
570 return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac);
571 }
572
transmit_errors_show(struct config_item * item,char * buf)573 static ssize_t transmit_errors_show(struct config_item *item, char *buf)
574 {
575 struct netconsole_target *nt = to_target(item);
576 u64 xmit_drop_count, enomem_count;
577 unsigned int start;
578
579 do {
580 start = u64_stats_fetch_begin(&nt->stats.syncp);
581 xmit_drop_count = u64_stats_read(&nt->stats.xmit_drop_count);
582 enomem_count = u64_stats_read(&nt->stats.enomem_count);
583 } while (u64_stats_fetch_retry(&nt->stats.syncp, start));
584
585 return sysfs_emit(buf, "%llu\n", xmit_drop_count + enomem_count);
586 }
587
588 /* configfs helper to display if cpu_nr sysdata feature is enabled */
sysdata_cpu_nr_enabled_show(struct config_item * item,char * buf)589 static ssize_t sysdata_cpu_nr_enabled_show(struct config_item *item, char *buf)
590 {
591 struct netconsole_target *nt = to_target(item->ci_parent);
592 bool cpu_nr_enabled;
593
594 dynamic_netconsole_mutex_lock();
595 cpu_nr_enabled = !!(nt->sysdata_fields & SYSDATA_CPU_NR);
596 dynamic_netconsole_mutex_unlock();
597
598 return sysfs_emit(buf, "%d\n", cpu_nr_enabled);
599 }
600
601 /* configfs helper to display if taskname sysdata feature is enabled */
sysdata_taskname_enabled_show(struct config_item * item,char * buf)602 static ssize_t sysdata_taskname_enabled_show(struct config_item *item,
603 char *buf)
604 {
605 struct netconsole_target *nt = to_target(item->ci_parent);
606 bool taskname_enabled;
607
608 dynamic_netconsole_mutex_lock();
609 taskname_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
610 dynamic_netconsole_mutex_unlock();
611
612 return sysfs_emit(buf, "%d\n", taskname_enabled);
613 }
614
sysdata_release_enabled_show(struct config_item * item,char * buf)615 static ssize_t sysdata_release_enabled_show(struct config_item *item,
616 char *buf)
617 {
618 struct netconsole_target *nt = to_target(item->ci_parent);
619 bool release_enabled;
620
621 dynamic_netconsole_mutex_lock();
622 release_enabled = !!(nt->sysdata_fields & SYSDATA_RELEASE);
623 dynamic_netconsole_mutex_unlock();
624
625 return sysfs_emit(buf, "%d\n", release_enabled);
626 }
627
628 /* Iterate in the list of target, and make sure we don't have any console
629 * register without targets of the same type
630 */
unregister_netcons_consoles(void)631 static void unregister_netcons_consoles(void)
632 {
633 struct netconsole_target *nt;
634 u32 console_type_needed = 0;
635 unsigned long flags;
636
637 spin_lock_irqsave(&target_list_lock, flags);
638 list_for_each_entry(nt, &target_list, list) {
639 if (nt->extended)
640 console_type_needed |= CONS_EXTENDED;
641 else
642 console_type_needed |= CONS_BASIC;
643 }
644 spin_unlock_irqrestore(&target_list_lock, flags);
645
646 if (!(console_type_needed & CONS_EXTENDED) &&
647 console_is_registered(&netconsole_ext))
648 unregister_console(&netconsole_ext);
649
650 if (!(console_type_needed & CONS_BASIC) &&
651 console_is_registered(&netconsole))
652 unregister_console(&netconsole);
653 }
654
sysdata_msgid_enabled_show(struct config_item * item,char * buf)655 static ssize_t sysdata_msgid_enabled_show(struct config_item *item,
656 char *buf)
657 {
658 struct netconsole_target *nt = to_target(item->ci_parent);
659 bool msgid_enabled;
660
661 dynamic_netconsole_mutex_lock();
662 msgid_enabled = !!(nt->sysdata_fields & SYSDATA_MSGID);
663 dynamic_netconsole_mutex_unlock();
664
665 return sysfs_emit(buf, "%d\n", msgid_enabled);
666 }
667
668 /*
669 * This one is special -- targets created through the configfs interface
670 * are not enabled (and the corresponding netpoll activated) by default.
671 * The user is expected to set the desired parameters first (which
672 * would enable him to dynamically add new netpoll targets for new
673 * network interfaces as and when they come up).
674 */
enabled_store(struct config_item * item,const char * buf,size_t count)675 static ssize_t enabled_store(struct config_item *item,
676 const char *buf, size_t count)
677 {
678 struct netconsole_target *nt = to_target(item);
679 bool enabled, current_enabled;
680 unsigned long flags;
681 ssize_t ret;
682
683 dynamic_netconsole_mutex_lock();
684 ret = kstrtobool(buf, &enabled);
685 if (ret)
686 goto out_unlock;
687
688 /* When the user explicitly enables or disables a target that is
689 * currently deactivated, reset its state to disabled. The DEACTIVATED
690 * state only tracks interface-driven deactivation and should _not_
691 * persist when the user manually changes the target's enabled state.
692 */
693 if (nt->state == STATE_DEACTIVATED)
694 nt->state = STATE_DISABLED;
695
696 ret = -EINVAL;
697 current_enabled = nt->state == STATE_ENABLED;
698 if (enabled == current_enabled) {
699 pr_info("network logging has already %s\n",
700 current_enabled ? "started" : "stopped");
701 goto out_unlock;
702 }
703
704 if (enabled) { /* true */
705 if (nt->release && !nt->extended) {
706 pr_err("Not enabling netconsole. Release feature requires extended log message");
707 goto out_unlock;
708 }
709
710 if (nt->extended && !console_is_registered(&netconsole_ext)) {
711 netconsole_ext.flags |= CON_ENABLED;
712 register_console(&netconsole_ext);
713 }
714
715 /* User might be enabling the basic format target for the very
716 * first time, make sure the console is registered.
717 */
718 if (!nt->extended && !console_is_registered(&netconsole)) {
719 netconsole.flags |= CON_ENABLED;
720 register_console(&netconsole);
721 }
722
723 /*
724 * Skip netconsole_parser_cmdline() -- all the attributes are
725 * already configured via configfs. Just print them out.
726 */
727 netconsole_print_banner(&nt->np);
728
729 ret = netpoll_setup(&nt->np);
730 if (ret)
731 goto out_unlock;
732
733 nt->state = STATE_ENABLED;
734 pr_info("network logging started\n");
735 } else { /* false */
736 /* We need to disable the netconsole before cleaning it up
737 * otherwise we might end up in write_msg() with
738 * nt->np.dev == NULL and nt->state == STATE_ENABLED
739 */
740 mutex_lock(&target_cleanup_list_lock);
741 spin_lock_irqsave(&target_list_lock, flags);
742 nt->state = STATE_DISABLED;
743 /* Remove the target from the list, while holding
744 * target_list_lock
745 */
746 list_move(&nt->list, &target_cleanup_list);
747 spin_unlock_irqrestore(&target_list_lock, flags);
748 mutex_unlock(&target_cleanup_list_lock);
749 /* Unregister consoles, whose the last target of that type got
750 * disabled.
751 */
752 unregister_netcons_consoles();
753 }
754
755 ret = count;
756 /* Deferred cleanup */
757 netconsole_process_cleanups();
758 out_unlock:
759 dynamic_netconsole_mutex_unlock();
760 return ret;
761 }
762
release_store(struct config_item * item,const char * buf,size_t count)763 static ssize_t release_store(struct config_item *item, const char *buf,
764 size_t count)
765 {
766 struct netconsole_target *nt = to_target(item);
767 bool release;
768 ssize_t ret;
769
770 dynamic_netconsole_mutex_lock();
771 if (nt->state == STATE_ENABLED) {
772 pr_err("target (%s) is enabled, disable to update parameters\n",
773 config_item_name(&nt->group.cg_item));
774 ret = -EINVAL;
775 goto out_unlock;
776 }
777
778 ret = kstrtobool(buf, &release);
779 if (ret)
780 goto out_unlock;
781
782 nt->release = release;
783
784 ret = count;
785 out_unlock:
786 dynamic_netconsole_mutex_unlock();
787 return ret;
788 }
789
extended_store(struct config_item * item,const char * buf,size_t count)790 static ssize_t extended_store(struct config_item *item, const char *buf,
791 size_t count)
792 {
793 struct netconsole_target *nt = to_target(item);
794 bool extended;
795 ssize_t ret;
796
797 dynamic_netconsole_mutex_lock();
798 if (nt->state == STATE_ENABLED) {
799 pr_err("target (%s) is enabled, disable to update parameters\n",
800 config_item_name(&nt->group.cg_item));
801 ret = -EINVAL;
802 goto out_unlock;
803 }
804
805 ret = kstrtobool(buf, &extended);
806 if (ret)
807 goto out_unlock;
808
809 nt->extended = extended;
810 ret = count;
811 out_unlock:
812 dynamic_netconsole_mutex_unlock();
813 return ret;
814 }
815
dev_name_store(struct config_item * item,const char * buf,size_t count)816 static ssize_t dev_name_store(struct config_item *item, const char *buf,
817 size_t count)
818 {
819 struct netconsole_target *nt = to_target(item);
820 size_t len = count;
821
822 /* Account for a trailing newline appended by tools like echo */
823 if (len && buf[len - 1] == '\n')
824 len--;
825 if (len >= IFNAMSIZ)
826 return -ENAMETOOLONG;
827
828 dynamic_netconsole_mutex_lock();
829 if (nt->state == STATE_ENABLED) {
830 pr_err("target (%s) is enabled, disable to update parameters\n",
831 config_item_name(&nt->group.cg_item));
832 dynamic_netconsole_mutex_unlock();
833 return -EINVAL;
834 }
835
836 strscpy(nt->np.dev_name, buf, IFNAMSIZ);
837 trim_newline(nt->np.dev_name, IFNAMSIZ);
838
839 dynamic_netconsole_mutex_unlock();
840 return count;
841 }
842
local_port_store(struct config_item * item,const char * buf,size_t count)843 static ssize_t local_port_store(struct config_item *item, const char *buf,
844 size_t count)
845 {
846 struct netconsole_target *nt = to_target(item);
847 ssize_t ret = -EINVAL;
848
849 dynamic_netconsole_mutex_lock();
850 if (nt->state == STATE_ENABLED) {
851 pr_err("target (%s) is enabled, disable to update parameters\n",
852 config_item_name(&nt->group.cg_item));
853 goto out_unlock;
854 }
855
856 ret = kstrtou16(buf, 10, &nt->np.local_port);
857 if (ret < 0)
858 goto out_unlock;
859 ret = count;
860 out_unlock:
861 dynamic_netconsole_mutex_unlock();
862 return ret;
863 }
864
remote_port_store(struct config_item * item,const char * buf,size_t count)865 static ssize_t remote_port_store(struct config_item *item,
866 const char *buf, size_t count)
867 {
868 struct netconsole_target *nt = to_target(item);
869 ssize_t ret = -EINVAL;
870
871 dynamic_netconsole_mutex_lock();
872 if (nt->state == STATE_ENABLED) {
873 pr_err("target (%s) is enabled, disable to update parameters\n",
874 config_item_name(&nt->group.cg_item));
875 goto out_unlock;
876 }
877
878 ret = kstrtou16(buf, 10, &nt->np.remote_port);
879 if (ret < 0)
880 goto out_unlock;
881 ret = count;
882 out_unlock:
883 dynamic_netconsole_mutex_unlock();
884 return ret;
885 }
886
local_ip_store(struct config_item * item,const char * buf,size_t count)887 static ssize_t local_ip_store(struct config_item *item, const char *buf,
888 size_t count)
889 {
890 struct netconsole_target *nt = to_target(item);
891 ssize_t ret = -EINVAL;
892 int ipv6;
893
894 dynamic_netconsole_mutex_lock();
895 if (nt->state == STATE_ENABLED) {
896 pr_err("target (%s) is enabled, disable to update parameters\n",
897 config_item_name(&nt->group.cg_item));
898 goto out_unlock;
899 }
900
901 ipv6 = netpoll_parse_ip_addr(buf, &nt->np.local_ip);
902 if (ipv6 == -1)
903 goto out_unlock;
904 nt->np.ipv6 = !!ipv6;
905
906 ret = count;
907 out_unlock:
908 dynamic_netconsole_mutex_unlock();
909 return ret;
910 }
911
remote_ip_store(struct config_item * item,const char * buf,size_t count)912 static ssize_t remote_ip_store(struct config_item *item, const char *buf,
913 size_t count)
914 {
915 struct netconsole_target *nt = to_target(item);
916 ssize_t ret = -EINVAL;
917 int ipv6;
918
919 dynamic_netconsole_mutex_lock();
920 if (nt->state == STATE_ENABLED) {
921 pr_err("target (%s) is enabled, disable to update parameters\n",
922 config_item_name(&nt->group.cg_item));
923 goto out_unlock;
924 }
925
926 ipv6 = netpoll_parse_ip_addr(buf, &nt->np.remote_ip);
927 if (ipv6 == -1)
928 goto out_unlock;
929 nt->np.ipv6 = !!ipv6;
930
931 ret = count;
932 out_unlock:
933 dynamic_netconsole_mutex_unlock();
934 return ret;
935 }
936
937 /* Count number of entries we have in userdata.
938 * This is important because userdata only supports MAX_USERDATA_ITEMS
939 * entries. Before enabling any new userdata feature, number of entries needs
940 * to checked for available space.
941 */
count_userdata_entries(struct netconsole_target * nt)942 static size_t count_userdata_entries(struct netconsole_target *nt)
943 {
944 return list_count_nodes(&nt->userdata_group.cg_children);
945 }
946
remote_mac_store(struct config_item * item,const char * buf,size_t count)947 static ssize_t remote_mac_store(struct config_item *item, const char *buf,
948 size_t count)
949 {
950 struct netconsole_target *nt = to_target(item);
951 u8 remote_mac[ETH_ALEN];
952 ssize_t ret = -EINVAL;
953
954 dynamic_netconsole_mutex_lock();
955 if (nt->state == STATE_ENABLED) {
956 pr_err("target (%s) is enabled, disable to update parameters\n",
957 config_item_name(&nt->group.cg_item));
958 goto out_unlock;
959 }
960
961 if (!mac_pton(buf, remote_mac))
962 goto out_unlock;
963 if (buf[MAC_ADDR_STR_LEN] && buf[MAC_ADDR_STR_LEN] != '\n')
964 goto out_unlock;
965 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
966
967 ret = count;
968 out_unlock:
969 dynamic_netconsole_mutex_unlock();
970 return ret;
971 }
972
973 struct userdatum {
974 struct config_item item;
975 char value[MAX_EXTRADATA_VALUE_LEN];
976 };
977
to_userdatum(struct config_item * item)978 static struct userdatum *to_userdatum(struct config_item *item)
979 {
980 return container_of(item, struct userdatum, item);
981 }
982
983 struct userdata {
984 struct config_group group;
985 };
986
to_userdata(struct config_item * item)987 static struct userdata *to_userdata(struct config_item *item)
988 {
989 return container_of(to_config_group(item), struct userdata, group);
990 }
991
userdata_to_target(struct userdata * ud)992 static struct netconsole_target *userdata_to_target(struct userdata *ud)
993 {
994 struct config_group *netconsole_group;
995
996 netconsole_group = to_config_group(ud->group.cg_item.ci_parent);
997 return to_target(&netconsole_group->cg_item);
998 }
999
userdatum_value_show(struct config_item * item,char * buf)1000 static ssize_t userdatum_value_show(struct config_item *item, char *buf)
1001 {
1002 return sysfs_emit(buf, "%s\n", &(to_userdatum(item)->value[0]));
1003 }
1004
1005 /* Navigate configfs and calculate the lentgh of the formatted string
1006 * representing userdata.
1007 * Must be called holding netconsole_subsys.su_mutex
1008 */
calc_userdata_len(struct netconsole_target * nt)1009 static int calc_userdata_len(struct netconsole_target *nt)
1010 {
1011 struct userdatum *udm_item;
1012 struct config_item *item;
1013 struct list_head *entry;
1014 int len = 0;
1015
1016 list_for_each(entry, &nt->userdata_group.cg_children) {
1017 item = container_of(entry, struct config_item, ci_entry);
1018 udm_item = to_userdatum(item);
1019 /* Skip userdata with no value set */
1020 if (udm_item->value[0]) {
1021 len += snprintf(NULL, 0, " %s=%s\n", item->ci_name,
1022 udm_item->value);
1023 }
1024 }
1025 return len;
1026 }
1027
update_userdata(struct netconsole_target * nt)1028 static int update_userdata(struct netconsole_target *nt)
1029 {
1030 struct userdatum *udm_item;
1031 struct config_item *item;
1032 struct list_head *entry;
1033 char *old_buf = NULL;
1034 char *new_buf = NULL;
1035 unsigned long flags;
1036 int offset = 0;
1037 int len;
1038
1039 /* Calculate required buffer size */
1040 len = calc_userdata_len(nt);
1041
1042 if (WARN_ON_ONCE(len > MAX_EXTRADATA_ENTRY_LEN * MAX_USERDATA_ITEMS))
1043 return -ENOSPC;
1044
1045 /* Allocate new buffer */
1046 if (len) {
1047 new_buf = kmalloc(len + 1, GFP_KERNEL);
1048 if (!new_buf)
1049 return -ENOMEM;
1050 }
1051
1052 /* Write userdata to new buffer */
1053 list_for_each(entry, &nt->userdata_group.cg_children) {
1054 item = container_of(entry, struct config_item, ci_entry);
1055 udm_item = to_userdatum(item);
1056 /* Skip userdata with no value set */
1057 if (udm_item->value[0]) {
1058 offset += scnprintf(&new_buf[offset], len + 1 - offset,
1059 " %s=%s\n", item->ci_name,
1060 udm_item->value);
1061 }
1062 }
1063
1064 WARN_ON_ONCE(offset != len);
1065
1066 /* Switch to new buffer and free old buffer */
1067 spin_lock_irqsave(&target_list_lock, flags);
1068 old_buf = nt->userdata;
1069 nt->userdata = new_buf;
1070 nt->userdata_length = offset;
1071 spin_unlock_irqrestore(&target_list_lock, flags);
1072
1073 kfree(old_buf);
1074
1075 return 0;
1076 }
1077
userdatum_value_store(struct config_item * item,const char * buf,size_t count)1078 static ssize_t userdatum_value_store(struct config_item *item, const char *buf,
1079 size_t count)
1080 {
1081 struct userdatum *udm = to_userdatum(item);
1082 char old_value[MAX_EXTRADATA_VALUE_LEN];
1083 struct netconsole_target *nt;
1084 struct userdata *ud;
1085 ssize_t ret;
1086
1087 if (count >= MAX_EXTRADATA_VALUE_LEN)
1088 return -EMSGSIZE;
1089
1090 mutex_lock(&netconsole_subsys.su_mutex);
1091 dynamic_netconsole_mutex_lock();
1092 /* Snapshot for rollback if update_userdata() fails below */
1093 strscpy(old_value, udm->value, sizeof(old_value));
1094 /* count is bounded above, so strscpy() cannot truncate here */
1095 strscpy(udm->value, buf, sizeof(udm->value));
1096 trim_newline(udm->value, sizeof(udm->value));
1097
1098 ud = to_userdata(item->ci_parent);
1099 nt = userdata_to_target(ud);
1100 ret = update_userdata(nt);
1101 if (ret < 0) {
1102 /* Restore the previous value so it matches the live payload */
1103 strscpy(udm->value, old_value, sizeof(udm->value));
1104 goto out_unlock;
1105 }
1106 ret = count;
1107 out_unlock:
1108 dynamic_netconsole_mutex_unlock();
1109 mutex_unlock(&netconsole_subsys.su_mutex);
1110 return ret;
1111 }
1112
1113 /* disable_sysdata_feature - Disable sysdata feature and clean sysdata
1114 * @nt: target that is disabling the feature
1115 * @feature: feature being disabled
1116 */
disable_sysdata_feature(struct netconsole_target * nt,enum sysdata_feature feature)1117 static void disable_sysdata_feature(struct netconsole_target *nt,
1118 enum sysdata_feature feature)
1119 {
1120 nt->sysdata_fields &= ~feature;
1121 nt->sysdata[0] = 0;
1122 }
1123
sysdata_msgid_enabled_store(struct config_item * item,const char * buf,size_t count)1124 static ssize_t sysdata_msgid_enabled_store(struct config_item *item,
1125 const char *buf, size_t count)
1126 {
1127 struct netconsole_target *nt = to_target(item->ci_parent);
1128 bool msgid_enabled, curr;
1129 ssize_t ret;
1130
1131 ret = kstrtobool(buf, &msgid_enabled);
1132 if (ret)
1133 return ret;
1134
1135 mutex_lock(&netconsole_subsys.su_mutex);
1136 dynamic_netconsole_mutex_lock();
1137 curr = !!(nt->sysdata_fields & SYSDATA_MSGID);
1138 if (msgid_enabled == curr)
1139 goto unlock_ok;
1140
1141 if (msgid_enabled)
1142 nt->sysdata_fields |= SYSDATA_MSGID;
1143 else
1144 disable_sysdata_feature(nt, SYSDATA_MSGID);
1145
1146 unlock_ok:
1147 ret = count;
1148 dynamic_netconsole_mutex_unlock();
1149 mutex_unlock(&netconsole_subsys.su_mutex);
1150 return ret;
1151 }
1152
sysdata_release_enabled_store(struct config_item * item,const char * buf,size_t count)1153 static ssize_t sysdata_release_enabled_store(struct config_item *item,
1154 const char *buf, size_t count)
1155 {
1156 struct netconsole_target *nt = to_target(item->ci_parent);
1157 bool release_enabled, curr;
1158 ssize_t ret;
1159
1160 ret = kstrtobool(buf, &release_enabled);
1161 if (ret)
1162 return ret;
1163
1164 mutex_lock(&netconsole_subsys.su_mutex);
1165 dynamic_netconsole_mutex_lock();
1166 curr = !!(nt->sysdata_fields & SYSDATA_RELEASE);
1167 if (release_enabled == curr)
1168 goto unlock_ok;
1169
1170 if (release_enabled)
1171 nt->sysdata_fields |= SYSDATA_RELEASE;
1172 else
1173 disable_sysdata_feature(nt, SYSDATA_RELEASE);
1174
1175 unlock_ok:
1176 ret = count;
1177 dynamic_netconsole_mutex_unlock();
1178 mutex_unlock(&netconsole_subsys.su_mutex);
1179 return ret;
1180 }
1181
sysdata_taskname_enabled_store(struct config_item * item,const char * buf,size_t count)1182 static ssize_t sysdata_taskname_enabled_store(struct config_item *item,
1183 const char *buf, size_t count)
1184 {
1185 struct netconsole_target *nt = to_target(item->ci_parent);
1186 bool taskname_enabled, curr;
1187 ssize_t ret;
1188
1189 ret = kstrtobool(buf, &taskname_enabled);
1190 if (ret)
1191 return ret;
1192
1193 mutex_lock(&netconsole_subsys.su_mutex);
1194 dynamic_netconsole_mutex_lock();
1195 curr = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
1196 if (taskname_enabled == curr)
1197 goto unlock_ok;
1198
1199 if (taskname_enabled)
1200 nt->sysdata_fields |= SYSDATA_TASKNAME;
1201 else
1202 disable_sysdata_feature(nt, SYSDATA_TASKNAME);
1203
1204 unlock_ok:
1205 ret = count;
1206 dynamic_netconsole_mutex_unlock();
1207 mutex_unlock(&netconsole_subsys.su_mutex);
1208 return ret;
1209 }
1210
1211 /* configfs helper to sysdata cpu_nr feature */
sysdata_cpu_nr_enabled_store(struct config_item * item,const char * buf,size_t count)1212 static ssize_t sysdata_cpu_nr_enabled_store(struct config_item *item,
1213 const char *buf, size_t count)
1214 {
1215 struct netconsole_target *nt = to_target(item->ci_parent);
1216 bool cpu_nr_enabled, curr;
1217 ssize_t ret;
1218
1219 ret = kstrtobool(buf, &cpu_nr_enabled);
1220 if (ret)
1221 return ret;
1222
1223 mutex_lock(&netconsole_subsys.su_mutex);
1224 dynamic_netconsole_mutex_lock();
1225 curr = !!(nt->sysdata_fields & SYSDATA_CPU_NR);
1226 if (cpu_nr_enabled == curr)
1227 /* no change requested */
1228 goto unlock_ok;
1229
1230 if (cpu_nr_enabled)
1231 nt->sysdata_fields |= SYSDATA_CPU_NR;
1232 else
1233 /* This is special because sysdata might have remaining data
1234 * from previous sysdata, and it needs to be cleaned.
1235 */
1236 disable_sysdata_feature(nt, SYSDATA_CPU_NR);
1237
1238 unlock_ok:
1239 ret = count;
1240 dynamic_netconsole_mutex_unlock();
1241 mutex_unlock(&netconsole_subsys.su_mutex);
1242 return ret;
1243 }
1244
1245 CONFIGFS_ATTR(userdatum_, value);
1246 CONFIGFS_ATTR(sysdata_, cpu_nr_enabled);
1247 CONFIGFS_ATTR(sysdata_, taskname_enabled);
1248 CONFIGFS_ATTR(sysdata_, release_enabled);
1249 CONFIGFS_ATTR(sysdata_, msgid_enabled);
1250
1251 static struct configfs_attribute *userdatum_attrs[] = {
1252 &userdatum_attr_value,
1253 NULL,
1254 };
1255
userdatum_release(struct config_item * item)1256 static void userdatum_release(struct config_item *item)
1257 {
1258 kfree(to_userdatum(item));
1259 }
1260
1261 static struct configfs_item_operations userdatum_ops = {
1262 .release = userdatum_release,
1263 };
1264
1265 static const struct config_item_type userdatum_type = {
1266 .ct_item_ops = &userdatum_ops,
1267 .ct_attrs = userdatum_attrs,
1268 .ct_owner = THIS_MODULE,
1269 };
1270
userdatum_make_item(struct config_group * group,const char * name)1271 static struct config_item *userdatum_make_item(struct config_group *group,
1272 const char *name)
1273 {
1274 struct netconsole_target *nt;
1275 struct userdatum *udm;
1276 struct userdata *ud;
1277
1278 if (strlen(name) > MAX_EXTRADATA_NAME_LEN)
1279 return ERR_PTR(-ENAMETOOLONG);
1280
1281 ud = to_userdata(&group->cg_item);
1282 nt = userdata_to_target(ud);
1283 if (count_userdata_entries(nt) >= MAX_USERDATA_ITEMS)
1284 return ERR_PTR(-ENOSPC);
1285
1286 udm = kzalloc_obj(*udm);
1287 if (!udm)
1288 return ERR_PTR(-ENOMEM);
1289
1290 config_item_init_type_name(&udm->item, name, &userdatum_type);
1291 return &udm->item;
1292 }
1293
userdatum_drop(struct config_group * group,struct config_item * item)1294 static void userdatum_drop(struct config_group *group, struct config_item *item)
1295 {
1296 struct netconsole_target *nt;
1297 struct userdata *ud;
1298
1299 ud = to_userdata(&group->cg_item);
1300 nt = userdata_to_target(ud);
1301
1302 dynamic_netconsole_mutex_lock();
1303 update_userdata(nt);
1304 config_item_put(item);
1305 dynamic_netconsole_mutex_unlock();
1306 }
1307
1308 static struct configfs_attribute *userdata_attrs[] = {
1309 &sysdata_attr_cpu_nr_enabled,
1310 &sysdata_attr_taskname_enabled,
1311 &sysdata_attr_release_enabled,
1312 &sysdata_attr_msgid_enabled,
1313 NULL,
1314 };
1315
1316 static struct configfs_group_operations userdata_ops = {
1317 .make_item = userdatum_make_item,
1318 .drop_item = userdatum_drop,
1319 };
1320
1321 static const struct config_item_type userdata_type = {
1322 .ct_item_ops = &userdatum_ops,
1323 .ct_group_ops = &userdata_ops,
1324 .ct_attrs = userdata_attrs,
1325 .ct_owner = THIS_MODULE,
1326 };
1327
1328 CONFIGFS_ATTR(, enabled);
1329 CONFIGFS_ATTR(, extended);
1330 CONFIGFS_ATTR(, dev_name);
1331 CONFIGFS_ATTR(, local_port);
1332 CONFIGFS_ATTR(, remote_port);
1333 CONFIGFS_ATTR(, local_ip);
1334 CONFIGFS_ATTR(, remote_ip);
1335 CONFIGFS_ATTR_RO(, local_mac);
1336 CONFIGFS_ATTR(, remote_mac);
1337 CONFIGFS_ATTR(, release);
1338 CONFIGFS_ATTR_RO(, transmit_errors);
1339
1340 static struct configfs_attribute *netconsole_target_attrs[] = {
1341 &attr_enabled,
1342 &attr_extended,
1343 &attr_release,
1344 &attr_dev_name,
1345 &attr_local_port,
1346 &attr_remote_port,
1347 &attr_local_ip,
1348 &attr_remote_ip,
1349 &attr_local_mac,
1350 &attr_remote_mac,
1351 &attr_transmit_errors,
1352 NULL,
1353 };
1354
1355 /*
1356 * Item operations and type for netconsole_target.
1357 */
1358
netconsole_target_release(struct config_item * item)1359 static void netconsole_target_release(struct config_item *item)
1360 {
1361 struct netconsole_target *nt = to_target(item);
1362
1363 kfree(nt->userdata);
1364 kfree(nt);
1365 }
1366
1367 static struct configfs_item_operations netconsole_target_item_ops = {
1368 .release = netconsole_target_release,
1369 };
1370
1371 static const struct config_item_type netconsole_target_type = {
1372 .ct_attrs = netconsole_target_attrs,
1373 .ct_item_ops = &netconsole_target_item_ops,
1374 .ct_owner = THIS_MODULE,
1375 };
1376
init_target_config_group(struct netconsole_target * nt,const char * name)1377 static void init_target_config_group(struct netconsole_target *nt,
1378 const char *name)
1379 {
1380 config_group_init_type_name(&nt->group, name, &netconsole_target_type);
1381 config_group_init_type_name(&nt->userdata_group, "userdata",
1382 &userdata_type);
1383 configfs_add_default_group(&nt->userdata_group, &nt->group);
1384 }
1385
find_cmdline_target(const char * name)1386 static struct netconsole_target *find_cmdline_target(const char *name)
1387 {
1388 struct netconsole_target *nt, *ret = NULL;
1389 unsigned long flags;
1390
1391 spin_lock_irqsave(&target_list_lock, flags);
1392 list_for_each_entry(nt, &target_list, list) {
1393 if (!strcmp(nt->group.cg_item.ci_name, name)) {
1394 ret = nt;
1395 break;
1396 }
1397 }
1398 spin_unlock_irqrestore(&target_list_lock, flags);
1399
1400 return ret;
1401 }
1402
1403 /*
1404 * Group operations and type for netconsole_subsys.
1405 */
1406
make_netconsole_target(struct config_group * group,const char * name)1407 static struct config_group *make_netconsole_target(struct config_group *group,
1408 const char *name)
1409 {
1410 struct netconsole_target *nt;
1411 unsigned long flags;
1412
1413 /* Checking if a target by this name was created at boot time. If so,
1414 * attach a configfs entry to that target. This enables dynamic
1415 * control.
1416 */
1417 if (!strncmp(name, NETCONSOLE_PARAM_TARGET_PREFIX,
1418 strlen(NETCONSOLE_PARAM_TARGET_PREFIX))) {
1419 nt = find_cmdline_target(name);
1420 if (nt) {
1421 init_target_config_group(nt, name);
1422 return &nt->group;
1423 }
1424 }
1425
1426 nt = alloc_and_init();
1427 if (!nt)
1428 return ERR_PTR(-ENOMEM);
1429
1430 /* Initialize the config_group member */
1431 init_target_config_group(nt, name);
1432
1433 /* Adding, but it is disabled */
1434 spin_lock_irqsave(&target_list_lock, flags);
1435 list_add(&nt->list, &target_list);
1436 spin_unlock_irqrestore(&target_list_lock, flags);
1437
1438 return &nt->group;
1439 }
1440
drop_netconsole_target(struct config_group * group,struct config_item * item)1441 static void drop_netconsole_target(struct config_group *group,
1442 struct config_item *item)
1443 {
1444 struct netconsole_target *nt = to_target(item);
1445 unsigned long flags;
1446
1447 dynamic_netconsole_mutex_lock();
1448
1449 spin_lock_irqsave(&target_list_lock, flags);
1450 /* Disable deactivated target to prevent races between resume attempt
1451 * and target removal.
1452 */
1453 if (nt->state == STATE_DEACTIVATED)
1454 nt->state = STATE_DISABLED;
1455 list_del(&nt->list);
1456 spin_unlock_irqrestore(&target_list_lock, flags);
1457
1458 dynamic_netconsole_mutex_unlock();
1459
1460 /* Now that the target has been marked disabled no further work
1461 * can be scheduled. Existing work will skip as targets are not
1462 * deactivated anymore. Cancel any scheduled resume and wait for
1463 * completion.
1464 */
1465 cancel_work_sync(&nt->resume_wq);
1466
1467 /*
1468 * The target may have never been enabled, or was manually disabled
1469 * before being removed so netpoll may have already been cleaned up.
1470 */
1471 if (nt->state == STATE_ENABLED)
1472 netpoll_cleanup(&nt->np);
1473
1474 config_item_put(&nt->group.cg_item);
1475 }
1476
1477 static struct configfs_group_operations netconsole_subsys_group_ops = {
1478 .make_group = make_netconsole_target,
1479 .drop_item = drop_netconsole_target,
1480 };
1481
1482 static const struct config_item_type netconsole_subsys_type = {
1483 .ct_group_ops = &netconsole_subsys_group_ops,
1484 .ct_owner = THIS_MODULE,
1485 };
1486
1487 /* The netconsole configfs subsystem */
1488 static struct configfs_subsystem netconsole_subsys = {
1489 .su_group = {
1490 .cg_item = {
1491 .ci_namebuf = "netconsole",
1492 .ci_type = &netconsole_subsys_type,
1493 },
1494 },
1495 };
1496
populate_configfs_item(struct netconsole_target * nt,int cmdline_count)1497 static void populate_configfs_item(struct netconsole_target *nt,
1498 int cmdline_count)
1499 {
1500 char target_name[16];
1501
1502 snprintf(target_name, sizeof(target_name), "%s%d",
1503 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1504 init_target_config_group(nt, target_name);
1505 }
1506
sysdata_append_cpu_nr(struct netconsole_target * nt,int offset,struct nbcon_write_context * wctxt)1507 static int sysdata_append_cpu_nr(struct netconsole_target *nt, int offset,
1508 struct nbcon_write_context *wctxt)
1509 {
1510 return scnprintf(&nt->sysdata[offset],
1511 MAX_EXTRADATA_ENTRY_LEN, " cpu=%u\n",
1512 wctxt->cpu);
1513 }
1514
sysdata_append_taskname(struct netconsole_target * nt,int offset,struct nbcon_write_context * wctxt)1515 static int sysdata_append_taskname(struct netconsole_target *nt, int offset,
1516 struct nbcon_write_context *wctxt)
1517 {
1518 return scnprintf(&nt->sysdata[offset],
1519 MAX_EXTRADATA_ENTRY_LEN, " taskname=%s\n",
1520 wctxt->comm);
1521 }
1522
sysdata_append_release(struct netconsole_target * nt,int offset)1523 static int sysdata_append_release(struct netconsole_target *nt, int offset)
1524 {
1525 return scnprintf(&nt->sysdata[offset],
1526 MAX_EXTRADATA_ENTRY_LEN, " release=%s\n",
1527 init_utsname()->release);
1528 }
1529
sysdata_append_msgid(struct netconsole_target * nt,int offset)1530 static int sysdata_append_msgid(struct netconsole_target *nt, int offset)
1531 {
1532 wrapping_assign_add(nt->msgcounter, 1);
1533 return scnprintf(&nt->sysdata[offset],
1534 MAX_EXTRADATA_ENTRY_LEN, " msgid=%u\n",
1535 nt->msgcounter);
1536 }
1537
1538 /*
1539 * prepare_sysdata - append sysdata in runtime
1540 * @nt: target to send message to
1541 * @wctxt: nbcon write context containing message metadata
1542 */
prepare_sysdata(struct netconsole_target * nt,struct nbcon_write_context * wctxt)1543 static int prepare_sysdata(struct netconsole_target *nt,
1544 struct nbcon_write_context *wctxt)
1545 {
1546 int sysdata_len = 0;
1547
1548 if (!nt->sysdata_fields)
1549 goto out;
1550
1551 if (nt->sysdata_fields & SYSDATA_CPU_NR)
1552 sysdata_len += sysdata_append_cpu_nr(nt, sysdata_len, wctxt);
1553 if (nt->sysdata_fields & SYSDATA_TASKNAME)
1554 sysdata_len += sysdata_append_taskname(nt, sysdata_len, wctxt);
1555 if (nt->sysdata_fields & SYSDATA_RELEASE)
1556 sysdata_len += sysdata_append_release(nt, sysdata_len);
1557 if (nt->sysdata_fields & SYSDATA_MSGID)
1558 sysdata_len += sysdata_append_msgid(nt, sysdata_len);
1559
1560 WARN_ON_ONCE(sysdata_len >
1561 MAX_EXTRADATA_ENTRY_LEN * MAX_SYSDATA_ITEMS);
1562
1563 out:
1564 return sysdata_len;
1565 }
1566 #endif /* CONFIG_NETCONSOLE_DYNAMIC */
1567
1568 /* Handle network interface device notifications */
netconsole_netdev_event(struct notifier_block * this,unsigned long event,void * ptr)1569 static int netconsole_netdev_event(struct notifier_block *this,
1570 unsigned long event, void *ptr)
1571 {
1572 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1573 struct netconsole_target *nt, *tmp;
1574 bool stopped = false;
1575 unsigned long flags;
1576
1577 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
1578 event == NETDEV_RELEASE || event == NETDEV_JOIN ||
1579 event == NETDEV_REGISTER))
1580 goto done;
1581
1582 mutex_lock(&target_cleanup_list_lock);
1583 spin_lock_irqsave(&target_list_lock, flags);
1584 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1585 netconsole_target_get(nt);
1586 if (nt->np.dev == dev) {
1587 switch (event) {
1588 case NETDEV_CHANGENAME:
1589 strscpy(nt->np.dev_name, dev->name, IFNAMSIZ);
1590 break;
1591 case NETDEV_RELEASE:
1592 case NETDEV_JOIN:
1593 /* transition target to DISABLED instead of
1594 * DEACTIVATED when (de)enslaving devices as
1595 * their targets should not be automatically
1596 * resumed when the interface is brought up.
1597 */
1598 nt->state = STATE_DISABLED;
1599 list_move(&nt->list, &target_cleanup_list);
1600 stopped = true;
1601 break;
1602 case NETDEV_UNREGISTER:
1603 nt->state = STATE_DEACTIVATED;
1604 list_move(&nt->list, &target_cleanup_list);
1605 stopped = true;
1606 }
1607 }
1608 if ((event == NETDEV_REGISTER || event == NETDEV_CHANGENAME) &&
1609 deactivated_target_match(nt, dev))
1610 /* Schedule resume on a workqueue as it will attempt
1611 * to UP the device, which can't be done as part of this
1612 * notifier.
1613 */
1614 queue_work(netconsole_wq, &nt->resume_wq);
1615 netconsole_target_put(nt);
1616 }
1617 spin_unlock_irqrestore(&target_list_lock, flags);
1618 mutex_unlock(&target_cleanup_list_lock);
1619
1620 if (stopped) {
1621 const char *msg = "had an event";
1622
1623 switch (event) {
1624 case NETDEV_UNREGISTER:
1625 msg = "unregistered";
1626 break;
1627 case NETDEV_RELEASE:
1628 msg = "released slaves";
1629 break;
1630 case NETDEV_JOIN:
1631 msg = "is joining a master device";
1632 break;
1633 }
1634 pr_info("network logging stopped on interface %s as it %s\n",
1635 dev->name, msg);
1636 }
1637
1638 /* Process target_cleanup_list entries. By the end, target_cleanup_list
1639 * should be empty
1640 */
1641 netconsole_process_cleanups_core();
1642
1643 done:
1644 return NOTIFY_DONE;
1645 }
1646
1647 static struct notifier_block netconsole_netdev_notifier = {
1648 .notifier_call = netconsole_netdev_event,
1649 };
1650
1651 /**
1652 * send_udp - Wrapper for netpoll_send_udp that counts errors
1653 * @nt: target to send message to
1654 * @msg: message to send
1655 * @len: length of message
1656 *
1657 * Calls netpoll_send_udp and classifies the return value. If an error
1658 * occurred it increments statistics in nt->stats accordingly.
1659 * Only calls netpoll_send_udp if CONFIG_NETCONSOLE_DYNAMIC is disabled.
1660 */
send_udp(struct netconsole_target * nt,const char * msg,int len)1661 static void send_udp(struct netconsole_target *nt, const char *msg, int len)
1662 {
1663 int result = netpoll_send_udp(&nt->np, msg, len);
1664
1665 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC)) {
1666 if (result == NET_XMIT_DROP) {
1667 u64_stats_update_begin(&nt->stats.syncp);
1668 u64_stats_inc(&nt->stats.xmit_drop_count);
1669 u64_stats_update_end(&nt->stats.syncp);
1670 } else if (result == -ENOMEM) {
1671 u64_stats_update_begin(&nt->stats.syncp);
1672 u64_stats_inc(&nt->stats.enomem_count);
1673 u64_stats_update_end(&nt->stats.syncp);
1674 }
1675 }
1676 }
1677
send_msg_no_fragmentation(struct netconsole_target * nt,const char * msg,int msg_len,int release_len)1678 static void send_msg_no_fragmentation(struct netconsole_target *nt,
1679 const char *msg,
1680 int msg_len,
1681 int release_len)
1682 {
1683 const char *userdata = NULL;
1684 const char *sysdata = NULL;
1685 const char *release;
1686
1687 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1688 userdata = nt->userdata;
1689 sysdata = nt->sysdata;
1690 #endif
1691
1692 if (release_len) {
1693 release = init_utsname()->release;
1694
1695 scnprintf(nt->buf, MAX_PRINT_CHUNK, "%s,%.*s", release,
1696 msg_len, msg);
1697 msg_len += release_len;
1698 } else {
1699 memcpy(nt->buf, msg, msg_len);
1700 }
1701
1702 if (userdata)
1703 msg_len += scnprintf(&nt->buf[msg_len],
1704 MAX_PRINT_CHUNK - msg_len, "%s",
1705 userdata);
1706
1707 if (sysdata)
1708 msg_len += scnprintf(&nt->buf[msg_len],
1709 MAX_PRINT_CHUNK - msg_len, "%s",
1710 sysdata);
1711
1712 send_udp(nt, nt->buf, msg_len);
1713 }
1714
append_release(char * buf)1715 static void append_release(char *buf)
1716 {
1717 const char *release;
1718
1719 release = init_utsname()->release;
1720 scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release);
1721 }
1722
send_fragmented_body(struct netconsole_target * nt,const char * msgbody_ptr,int header_len,int msgbody_len,int sysdata_len)1723 static void send_fragmented_body(struct netconsole_target *nt,
1724 const char *msgbody_ptr, int header_len,
1725 int msgbody_len, int sysdata_len)
1726 {
1727 const char *userdata_ptr = NULL;
1728 const char *sysdata_ptr = NULL;
1729 int data_len, data_sent = 0;
1730 int userdata_offset = 0;
1731 int sysdata_offset = 0;
1732 int msgbody_offset = 0;
1733 int userdata_len = 0;
1734
1735 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1736 userdata_ptr = nt->userdata;
1737 sysdata_ptr = nt->sysdata;
1738 userdata_len = nt->userdata_length;
1739 #endif
1740 if (WARN_ON_ONCE(!userdata_ptr && userdata_len != 0))
1741 return;
1742
1743 if (WARN_ON_ONCE(!sysdata_ptr && sysdata_len != 0))
1744 return;
1745
1746 /* data_len represents the number of bytes that will be sent. This is
1747 * bigger than MAX_PRINT_CHUNK, thus, it will be split in multiple
1748 * packets
1749 */
1750 data_len = msgbody_len + userdata_len + sysdata_len;
1751
1752 /* In each iteration of the while loop below, we send a packet
1753 * containing the header and a portion of the data. The data is
1754 * composed of three parts: msgbody, userdata, and sysdata.
1755 * We keep track of how many bytes have been sent from each part using
1756 * the *_offset variables.
1757 * We keep track of how many bytes have been sent overall using the
1758 * data_sent variable, which ranges from 0 to the total bytes to be
1759 * sent.
1760 */
1761 while (data_sent < data_len) {
1762 int userdata_left = userdata_len - userdata_offset;
1763 int sysdata_left = sysdata_len - sysdata_offset;
1764 int msgbody_left = msgbody_len - msgbody_offset;
1765 int buf_offset = 0;
1766 int this_chunk = 0;
1767
1768 /* header is already populated in nt->buf, just append to it */
1769 buf_offset = header_len;
1770
1771 buf_offset += scnprintf(nt->buf + buf_offset,
1772 MAX_PRINT_CHUNK - buf_offset,
1773 ",ncfrag=%d/%d;", data_sent,
1774 data_len);
1775
1776 /* append msgbody first */
1777 this_chunk = min(msgbody_left, MAX_PRINT_CHUNK - buf_offset);
1778 memcpy(nt->buf + buf_offset, msgbody_ptr + msgbody_offset,
1779 this_chunk);
1780 msgbody_offset += this_chunk;
1781 buf_offset += this_chunk;
1782 data_sent += this_chunk;
1783
1784 /* after msgbody, append userdata */
1785 if (userdata_ptr && userdata_left) {
1786 this_chunk = min(userdata_left,
1787 MAX_PRINT_CHUNK - buf_offset);
1788 memcpy(nt->buf + buf_offset,
1789 userdata_ptr + userdata_offset, this_chunk);
1790 userdata_offset += this_chunk;
1791 buf_offset += this_chunk;
1792 data_sent += this_chunk;
1793 }
1794
1795 /* after userdata, append sysdata */
1796 if (sysdata_ptr && sysdata_left) {
1797 this_chunk = min(sysdata_left,
1798 MAX_PRINT_CHUNK - buf_offset);
1799 memcpy(nt->buf + buf_offset,
1800 sysdata_ptr + sysdata_offset, this_chunk);
1801 sysdata_offset += this_chunk;
1802 buf_offset += this_chunk;
1803 data_sent += this_chunk;
1804 }
1805
1806 /* if all is good, send the packet out */
1807 if (WARN_ON_ONCE(data_sent > data_len))
1808 return;
1809
1810 send_udp(nt, nt->buf, buf_offset);
1811 }
1812 }
1813
send_msg_fragmented(struct netconsole_target * nt,const char * msg,int msg_len,int release_len,int sysdata_len)1814 static void send_msg_fragmented(struct netconsole_target *nt,
1815 const char *msg,
1816 int msg_len,
1817 int release_len,
1818 int sysdata_len)
1819 {
1820 int header_len, msgbody_len;
1821 const char *msgbody;
1822
1823 /* need to insert extra header fields, detect header and msgbody */
1824 msgbody = memchr(msg, ';', msg_len);
1825 if (WARN_ON_ONCE(!msgbody))
1826 return;
1827
1828 header_len = msgbody - msg;
1829 msgbody_len = msg_len - header_len - 1;
1830 msgbody++;
1831
1832 /*
1833 * Transfer multiple chunks with the following extra header.
1834 * "ncfrag=<byte-offset>/<total-bytes>"
1835 */
1836 if (release_len)
1837 append_release(nt->buf);
1838
1839 /* Copy the header into the buffer */
1840 memcpy(nt->buf + release_len, msg, header_len);
1841 header_len += release_len;
1842
1843 /* for now on, the header will be persisted, and the msgbody
1844 * will be replaced
1845 */
1846 send_fragmented_body(nt, msgbody, header_len, msgbody_len,
1847 sysdata_len);
1848 }
1849
1850 /**
1851 * send_ext_msg_udp - send extended log message to target
1852 * @nt: target to send message to
1853 * @wctxt: nbcon write context containing message and metadata
1854 *
1855 * Transfer extended log message to @nt. If message is longer than
1856 * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
1857 * ncfrag header field added to identify them.
1858 */
send_ext_msg_udp(struct netconsole_target * nt,struct nbcon_write_context * wctxt)1859 static void send_ext_msg_udp(struct netconsole_target *nt,
1860 struct nbcon_write_context *wctxt)
1861 {
1862 int userdata_len = 0;
1863 int release_len = 0;
1864 int sysdata_len = 0;
1865 int len;
1866
1867 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1868 sysdata_len = prepare_sysdata(nt, wctxt);
1869 userdata_len = nt->userdata_length;
1870 #endif
1871 if (nt->release)
1872 release_len = strlen(init_utsname()->release) + 1;
1873
1874 len = wctxt->len + release_len + sysdata_len + userdata_len;
1875 if (len <= MAX_PRINT_CHUNK)
1876 return send_msg_no_fragmentation(nt, wctxt->outbuf,
1877 wctxt->len, release_len);
1878
1879 return send_msg_fragmented(nt, wctxt->outbuf, wctxt->len, release_len,
1880 sysdata_len);
1881 }
1882
send_msg_udp(struct netconsole_target * nt,const char * msg,unsigned int len)1883 static void send_msg_udp(struct netconsole_target *nt, const char *msg,
1884 unsigned int len)
1885 {
1886 const char *tmp = msg;
1887 int frag, left = len;
1888
1889 while (left > 0) {
1890 frag = min(left, MAX_PRINT_CHUNK);
1891 send_udp(nt, tmp, frag);
1892 tmp += frag;
1893 left -= frag;
1894 }
1895 }
1896
1897 /**
1898 * netconsole_write - Generic function to send a msg to all targets
1899 * @wctxt: nbcon write context
1900 * @extended: "true" for extended console mode
1901 *
1902 * Given an nbcon write context, send the message to the netconsole targets
1903 */
netconsole_write(struct nbcon_write_context * wctxt,bool extended)1904 static void netconsole_write(struct nbcon_write_context *wctxt, bool extended)
1905 {
1906 struct netconsole_target *nt;
1907
1908 if (oops_only && !oops_in_progress)
1909 return;
1910
1911 list_for_each_entry(nt, &target_list, list) {
1912 if (nt->extended != extended || nt->state != STATE_ENABLED ||
1913 !netif_running(nt->np.dev))
1914 continue;
1915
1916 /* If nbcon_enter_unsafe() fails, just return given netconsole
1917 * lost the ownership, and iterating over the targets will not
1918 * be able to re-acquire.
1919 */
1920 if (!nbcon_enter_unsafe(wctxt))
1921 return;
1922
1923 if (extended)
1924 send_ext_msg_udp(nt, wctxt);
1925 else
1926 send_msg_udp(nt, wctxt->outbuf, wctxt->len);
1927
1928 nbcon_exit_unsafe(wctxt);
1929 }
1930 }
1931
netconsole_write_ext(struct console * con __always_unused,struct nbcon_write_context * wctxt)1932 static void netconsole_write_ext(struct console *con __always_unused,
1933 struct nbcon_write_context *wctxt)
1934 {
1935 netconsole_write(wctxt, true);
1936 }
1937
netconsole_write_basic(struct console * con __always_unused,struct nbcon_write_context * wctxt)1938 static void netconsole_write_basic(struct console *con __always_unused,
1939 struct nbcon_write_context *wctxt)
1940 {
1941 netconsole_write(wctxt, false);
1942 }
1943
netconsole_device_lock(struct console * con __always_unused,unsigned long * flags)1944 static void netconsole_device_lock(struct console *con __always_unused,
1945 unsigned long *flags)
1946 __acquires(&target_list_lock)
1947 {
1948 spin_lock_irqsave(&target_list_lock, *flags);
1949 }
1950
netconsole_device_unlock(struct console * con __always_unused,unsigned long flags)1951 static void netconsole_device_unlock(struct console *con __always_unused,
1952 unsigned long flags)
1953 __releases(&target_list_lock)
1954 {
1955 spin_unlock_irqrestore(&target_list_lock, flags);
1956 }
1957
netconsole_parser_cmdline(struct netpoll * np,char * opt)1958 static int netconsole_parser_cmdline(struct netpoll *np, char *opt)
1959 {
1960 bool ipversion_set = false;
1961 char *cur = opt;
1962 char *delim;
1963 int ipv6;
1964
1965 if (*cur != '@') {
1966 delim = strchr(cur, '@');
1967 if (!delim)
1968 goto parse_failed;
1969 *delim = 0;
1970 if (kstrtou16(cur, 10, &np->local_port))
1971 goto parse_failed;
1972 cur = delim;
1973 }
1974 cur++;
1975
1976 if (*cur != '/') {
1977 ipversion_set = true;
1978 delim = strchr(cur, '/');
1979 if (!delim)
1980 goto parse_failed;
1981 *delim = 0;
1982 ipv6 = netpoll_parse_ip_addr(cur, &np->local_ip);
1983 if (ipv6 < 0)
1984 goto parse_failed;
1985 else
1986 np->ipv6 = (bool)ipv6;
1987 cur = delim;
1988 }
1989 cur++;
1990
1991 if (*cur != ',') {
1992 /* parse out dev_name or dev_mac */
1993 delim = strchr(cur, ',');
1994 if (!delim)
1995 goto parse_failed;
1996 *delim = 0;
1997
1998 np->dev_name[0] = '\0';
1999 eth_broadcast_addr(np->dev_mac);
2000 if (!strchr(cur, ':'))
2001 strscpy(np->dev_name, cur, sizeof(np->dev_name));
2002 else if (!mac_pton(cur, np->dev_mac))
2003 goto parse_failed;
2004
2005 cur = delim;
2006 }
2007 cur++;
2008
2009 if (*cur != '@') {
2010 /* dst port */
2011 delim = strchr(cur, '@');
2012 if (!delim)
2013 goto parse_failed;
2014 *delim = 0;
2015 if (*cur == ' ' || *cur == '\t')
2016 np_info(np, "warning: whitespace is not allowed\n");
2017 if (kstrtou16(cur, 10, &np->remote_port))
2018 goto parse_failed;
2019 cur = delim;
2020 }
2021 cur++;
2022
2023 /* dst ip */
2024 delim = strchr(cur, '/');
2025 if (!delim)
2026 goto parse_failed;
2027 *delim = 0;
2028 ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip);
2029 if (ipv6 < 0)
2030 goto parse_failed;
2031 else if (ipversion_set && np->ipv6 != (bool)ipv6)
2032 goto parse_failed;
2033 else
2034 np->ipv6 = (bool)ipv6;
2035 cur = delim + 1;
2036
2037 if (*cur != 0) {
2038 /* MAC address */
2039 if (!mac_pton(cur, np->remote_mac))
2040 goto parse_failed;
2041 }
2042
2043 netconsole_print_banner(np);
2044
2045 return 0;
2046
2047 parse_failed:
2048 np_info(np, "couldn't parse config at '%s'!\n", cur);
2049 return -1;
2050 }
2051
2052 /* Allocate new target (from boot/module param) and setup netpoll for it */
alloc_param_target(char * target_config,int cmdline_count)2053 static struct netconsole_target *alloc_param_target(char *target_config,
2054 int cmdline_count)
2055 {
2056 struct netconsole_target *nt;
2057 int err;
2058
2059 nt = alloc_and_init();
2060 if (!nt) {
2061 err = -ENOMEM;
2062 goto fail;
2063 }
2064
2065 if (*target_config == '+') {
2066 nt->extended = true;
2067 target_config++;
2068 }
2069
2070 if (*target_config == 'r') {
2071 if (!nt->extended) {
2072 pr_err("Netconsole configuration error. Release feature requires extended log message");
2073 err = -EINVAL;
2074 goto fail;
2075 }
2076 nt->release = true;
2077 target_config++;
2078 }
2079
2080 /* Parse parameters and setup netpoll */
2081 err = netconsole_parser_cmdline(&nt->np, target_config);
2082 if (err)
2083 goto fail;
2084
2085 err = netpoll_setup(&nt->np);
2086 if (err) {
2087 pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n",
2088 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
2089 if (!IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
2090 /* only fail if dynamic reconfiguration is set,
2091 * otherwise, keep the target in the list, but disabled.
2092 */
2093 goto fail;
2094 } else {
2095 nt->state = STATE_ENABLED;
2096 }
2097 populate_configfs_item(nt, cmdline_count);
2098
2099 return nt;
2100
2101 fail:
2102 kfree(nt);
2103 return ERR_PTR(err);
2104 }
2105
2106 /* Cleanup netpoll for given target (from boot/module param) and free it */
free_param_target(struct netconsole_target * nt)2107 static void free_param_target(struct netconsole_target *nt)
2108 {
2109 cancel_work_sync(&nt->resume_wq);
2110 netpoll_cleanup(&nt->np);
2111 #ifdef CONFIG_NETCONSOLE_DYNAMIC
2112 kfree(nt->userdata);
2113 #endif
2114 kfree(nt);
2115 }
2116
2117 static struct console netconsole_ext = {
2118 .name = "netcon_ext",
2119 .flags = CON_ENABLED | CON_EXTENDED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE,
2120 .write_thread = netconsole_write_ext,
2121 .write_atomic = netconsole_write_ext,
2122 .device_lock = netconsole_device_lock,
2123 .device_unlock = netconsole_device_unlock,
2124 };
2125
2126 static struct console netconsole = {
2127 .name = "netcon",
2128 .flags = CON_ENABLED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE,
2129 .write_thread = netconsole_write_basic,
2130 .write_atomic = netconsole_write_basic,
2131 .device_lock = netconsole_device_lock,
2132 .device_unlock = netconsole_device_unlock,
2133 };
2134
init_netconsole(void)2135 static int __init init_netconsole(void)
2136 {
2137 int err;
2138 struct netconsole_target *nt, *tmp;
2139 u32 console_type_needed = 0;
2140 unsigned int count = 0;
2141 unsigned long flags;
2142 char *target_config;
2143 char *input = config;
2144
2145 if (strnlen(input, MAX_PARAM_LENGTH)) {
2146 while ((target_config = strsep(&input, ";"))) {
2147 nt = alloc_param_target(target_config, count);
2148 if (IS_ERR(nt)) {
2149 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
2150 continue;
2151 err = PTR_ERR(nt);
2152 goto fail;
2153 }
2154 /* Dump existing printks when we register */
2155 if (nt->extended) {
2156 console_type_needed |= CONS_EXTENDED;
2157 netconsole_ext.flags |= CON_PRINTBUFFER;
2158 } else {
2159 console_type_needed |= CONS_BASIC;
2160 netconsole.flags |= CON_PRINTBUFFER;
2161 }
2162
2163 spin_lock_irqsave(&target_list_lock, flags);
2164 list_add(&nt->list, &target_list);
2165 spin_unlock_irqrestore(&target_list_lock, flags);
2166 count++;
2167 }
2168 }
2169
2170 netconsole_wq = alloc_workqueue("netconsole", WQ_UNBOUND, 0);
2171 if (!netconsole_wq) {
2172 err = -ENOMEM;
2173 goto fail;
2174 }
2175
2176 err = register_netdevice_notifier(&netconsole_netdev_notifier);
2177 if (err)
2178 goto fail;
2179
2180 err = dynamic_netconsole_init();
2181 if (err)
2182 goto undonotifier;
2183
2184 if (console_type_needed & CONS_EXTENDED)
2185 register_console(&netconsole_ext);
2186 if (console_type_needed & CONS_BASIC)
2187 register_console(&netconsole);
2188 pr_info("network logging started\n");
2189
2190 return err;
2191
2192 undonotifier:
2193 unregister_netdevice_notifier(&netconsole_netdev_notifier);
2194
2195 fail:
2196 pr_err("cleaning up\n");
2197
2198 if (netconsole_wq)
2199 flush_workqueue(netconsole_wq);
2200 /*
2201 * Remove all targets and destroy them (only targets created
2202 * from the boot/module option exist here). Skipping the list
2203 * lock is safe here, and netpoll_cleanup() will sleep.
2204 */
2205 list_for_each_entry_safe(nt, tmp, &target_list, list) {
2206 list_del(&nt->list);
2207 free_param_target(nt);
2208 }
2209
2210 if (netconsole_wq)
2211 destroy_workqueue(netconsole_wq);
2212
2213 return err;
2214 }
2215
cleanup_netconsole(void)2216 static void __exit cleanup_netconsole(void)
2217 {
2218 struct netconsole_target *nt, *tmp;
2219
2220 if (console_is_registered(&netconsole_ext))
2221 unregister_console(&netconsole_ext);
2222 if (console_is_registered(&netconsole))
2223 unregister_console(&netconsole);
2224 dynamic_netconsole_exit();
2225 unregister_netdevice_notifier(&netconsole_netdev_notifier);
2226 flush_workqueue(netconsole_wq);
2227
2228 /*
2229 * Targets created via configfs pin references on our module
2230 * and would first be rmdir(2)'ed from userspace. We reach
2231 * here only when they are already destroyed, and only those
2232 * created from the boot/module option are left, so remove and
2233 * destroy them. Skipping the list lock is safe here, and
2234 * netpoll_cleanup() will sleep.
2235 */
2236 list_for_each_entry_safe(nt, tmp, &target_list, list) {
2237 list_del(&nt->list);
2238 free_param_target(nt);
2239 }
2240
2241 destroy_workqueue(netconsole_wq);
2242 }
2243
2244 /*
2245 * Use late_initcall to ensure netconsole is
2246 * initialized after network device driver if built-in.
2247 *
2248 * late_initcall() and module_init() are identical if built as module.
2249 */
2250 late_initcall(init_netconsole);
2251 module_exit(cleanup_netconsole);
2252