diff options
Diffstat (limited to 'kernel/printk.c')
-rw-r--r-- | kernel/printk.c | 52 |
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 | */ |
54 | void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) | 49 | void 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 | } |
429 | out: | 424 | out: |
430 | return error; | 425 | return error; |
426 | warn: | ||
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 | ||
433 | SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) | 434 | SYSCALL_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 | } |
1422 | EXPORT_SYMBOL(unregister_console); | 1425 | EXPORT_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 | } |
1534 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); | 1538 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); |
1535 | 1539 | ||
1536 | static const char * const kmsg_reasons[] = { | ||
1537 | [KMSG_DUMP_OOPS] = "oops", | ||
1538 | [KMSG_DUMP_PANIC] = "panic", | ||
1539 | [KMSG_DUMP_KEXEC] = "kexec", | ||
1540 | }; | ||
1541 | |||
1542 | static 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 |