aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c52
1 files changed, 19 insertions, 33 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index ab3ffc5b3b64..53d9a9ec88e6 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -39,16 +39,11 @@
39#include <linux/syslog.h> 39#include <linux/syslog.h>
40#include <linux/cpu.h> 40#include <linux/cpu.h>
41#include <linux/notifier.h> 41#include <linux/notifier.h>
42#include <linux/rculist.h>
42 43
43#include <asm/uaccess.h> 44#include <asm/uaccess.h>
44 45
45/* 46/*
46 * for_each_console() allows you to iterate on each console
47 */
48#define for_each_console(con) \
49 for (con = console_drivers; con != NULL; con = con->next)
50
51/*
52 * Architectures can override it: 47 * Architectures can override it:
53 */ 48 */
54void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) 49void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
@@ -279,12 +274,12 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
279 * at open time. 274 * at open time.
280 */ 275 */
281 if (type == SYSLOG_ACTION_OPEN || !from_file) { 276 if (type == SYSLOG_ACTION_OPEN || !from_file) {
282 if (dmesg_restrict && !capable(CAP_SYS_ADMIN)) 277 if (dmesg_restrict && !capable(CAP_SYSLOG))
283 return -EPERM; 278 goto warn; /* switch to return -EPERM after 2.6.39 */
284 if ((type != SYSLOG_ACTION_READ_ALL && 279 if ((type != SYSLOG_ACTION_READ_ALL &&
285 type != SYSLOG_ACTION_SIZE_BUFFER) && 280 type != SYSLOG_ACTION_SIZE_BUFFER) &&
286 !capable(CAP_SYS_ADMIN)) 281 !capable(CAP_SYSLOG))
287 return -EPERM; 282 goto warn; /* switch to return -EPERM after 2.6.39 */
288 } 283 }
289 284
290 error = security_syslog(type); 285 error = security_syslog(type);
@@ -428,6 +423,12 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
428 } 423 }
429out: 424out:
430 return error; 425 return error;
426warn:
427 /* remove after 2.6.39 */
428 if (capable(CAP_SYS_ADMIN))
429 WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN "
430 "but no CAP_SYSLOG (deprecated and denied).\n");
431 return -EPERM;
431} 432}
432 433
433SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) 434SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
@@ -1359,6 +1360,7 @@ void register_console(struct console *newcon)
1359 spin_unlock_irqrestore(&logbuf_lock, flags); 1360 spin_unlock_irqrestore(&logbuf_lock, flags);
1360 } 1361 }
1361 release_console_sem(); 1362 release_console_sem();
1363 console_sysfs_notify();
1362 1364
1363 /* 1365 /*
1364 * By unregistering the bootconsoles after we enable the real console 1366 * By unregistering the bootconsoles after we enable the real console
@@ -1417,6 +1419,7 @@ int unregister_console(struct console *console)
1417 console_drivers->flags |= CON_CONSDEV; 1419 console_drivers->flags |= CON_CONSDEV;
1418 1420
1419 release_console_sem(); 1421 release_console_sem();
1422 console_sysfs_notify();
1420 return res; 1423 return res;
1421} 1424}
1422EXPORT_SYMBOL(unregister_console); 1425EXPORT_SYMBOL(unregister_console);
@@ -1500,7 +1503,7 @@ int kmsg_dump_register(struct kmsg_dumper *dumper)
1500 /* Don't allow registering multiple times */ 1503 /* Don't allow registering multiple times */
1501 if (!dumper->registered) { 1504 if (!dumper->registered) {
1502 dumper->registered = 1; 1505 dumper->registered = 1;
1503 list_add_tail(&dumper->list, &dump_list); 1506 list_add_tail_rcu(&dumper->list, &dump_list);
1504 err = 0; 1507 err = 0;
1505 } 1508 }
1506 spin_unlock_irqrestore(&dump_list_lock, flags); 1509 spin_unlock_irqrestore(&dump_list_lock, flags);
@@ -1524,29 +1527,16 @@ int kmsg_dump_unregister(struct kmsg_dumper *dumper)
1524 spin_lock_irqsave(&dump_list_lock, flags); 1527 spin_lock_irqsave(&dump_list_lock, flags);
1525 if (dumper->registered) { 1528 if (dumper->registered) {
1526 dumper->registered = 0; 1529 dumper->registered = 0;
1527 list_del(&dumper->list); 1530 list_del_rcu(&dumper->list);
1528 err = 0; 1531 err = 0;
1529 } 1532 }
1530 spin_unlock_irqrestore(&dump_list_lock, flags); 1533 spin_unlock_irqrestore(&dump_list_lock, flags);
1534 synchronize_rcu();
1531 1535
1532 return err; 1536 return err;
1533} 1537}
1534EXPORT_SYMBOL_GPL(kmsg_dump_unregister); 1538EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
1535 1539
1536static const char * const kmsg_reasons[] = {
1537 [KMSG_DUMP_OOPS] = "oops",
1538 [KMSG_DUMP_PANIC] = "panic",
1539 [KMSG_DUMP_KEXEC] = "kexec",
1540};
1541
1542static const char *kmsg_to_str(enum kmsg_dump_reason reason)
1543{
1544 if (reason >= ARRAY_SIZE(kmsg_reasons) || reason < 0)
1545 return "unknown";
1546
1547 return kmsg_reasons[reason];
1548}
1549
1550/** 1540/**
1551 * kmsg_dump - dump kernel log to kernel message dumpers. 1541 * kmsg_dump - dump kernel log to kernel message dumpers.
1552 * @reason: the reason (oops, panic etc) for dumping 1542 * @reason: the reason (oops, panic etc) for dumping
@@ -1585,13 +1575,9 @@ void kmsg_dump(enum kmsg_dump_reason reason)
1585 l2 = chars; 1575 l2 = chars;
1586 } 1576 }
1587 1577
1588 if (!spin_trylock_irqsave(&dump_list_lock, flags)) { 1578 rcu_read_lock();
1589 printk(KERN_ERR "dump_kmsg: dump list lock is held during %s, skipping dump\n", 1579 list_for_each_entry_rcu(dumper, &dump_list, list)
1590 kmsg_to_str(reason));
1591 return;
1592 }
1593 list_for_each_entry(dumper, &dump_list, list)
1594 dumper->dump(dumper, reason, s1, l1, s2, l2); 1580 dumper->dump(dumper, reason, s1, l1, s2, l2);
1595 spin_unlock_irqrestore(&dump_list_lock, flags); 1581 rcu_read_unlock();
1596} 1582}
1597#endif 1583#endif