aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c154
1 files changed, 89 insertions, 65 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 53d9a9ec88e6..36231525e22f 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -97,7 +97,7 @@ static int console_locked, console_suspended;
97/* 97/*
98 * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars 98 * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
99 * It is also used in interesting ways to provide interlocking in 99 * It is also used in interesting ways to provide interlocking in
100 * release_console_sem(). 100 * console_unlock();.
101 */ 101 */
102static DEFINE_SPINLOCK(logbuf_lock); 102static DEFINE_SPINLOCK(logbuf_lock);
103 103
@@ -262,25 +262,47 @@ int dmesg_restrict = 1;
262int dmesg_restrict; 262int dmesg_restrict;
263#endif 263#endif
264 264
265static int syslog_action_restricted(int type)
266{
267 if (dmesg_restrict)
268 return 1;
269 /* Unless restricted, we allow "read all" and "get buffer size" for everybody */
270 return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER;
271}
272
273static int check_syslog_permissions(int type, bool from_file)
274{
275 /*
276 * If this is from /proc/kmsg and we've already opened it, then we've
277 * already done the capabilities checks at open time.
278 */
279 if (from_file && type != SYSLOG_ACTION_OPEN)
280 return 0;
281
282 if (syslog_action_restricted(type)) {
283 if (capable(CAP_SYSLOG))
284 return 0;
285 /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
286 if (capable(CAP_SYS_ADMIN)) {
287 WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN "
288 "but no CAP_SYSLOG (deprecated).\n");
289 return 0;
290 }
291 return -EPERM;
292 }
293 return 0;
294}
295
265int do_syslog(int type, char __user *buf, int len, bool from_file) 296int do_syslog(int type, char __user *buf, int len, bool from_file)
266{ 297{
267 unsigned i, j, limit, count; 298 unsigned i, j, limit, count;
268 int do_clear = 0; 299 int do_clear = 0;
269 char c; 300 char c;
270 int error = 0; 301 int error;
271 302
272 /* 303 error = check_syslog_permissions(type, from_file);
273 * If this is from /proc/kmsg we only do the capabilities checks 304 if (error)
274 * at open time. 305 goto out;
275 */
276 if (type == SYSLOG_ACTION_OPEN || !from_file) {
277 if (dmesg_restrict && !capable(CAP_SYSLOG))
278 goto warn; /* switch to return -EPERM after 2.6.39 */
279 if ((type != SYSLOG_ACTION_READ_ALL &&
280 type != SYSLOG_ACTION_SIZE_BUFFER) &&
281 !capable(CAP_SYSLOG))
282 goto warn; /* switch to return -EPERM after 2.6.39 */
283 }
284 306
285 error = security_syslog(type); 307 error = security_syslog(type);
286 if (error) 308 if (error)
@@ -423,12 +445,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
423 } 445 }
424out: 446out:
425 return error; 447 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;
432} 448}
433 449
434SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) 450SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
@@ -501,7 +517,7 @@ static void _call_console_drivers(unsigned start,
501/* 517/*
502 * Call the console drivers, asking them to write out 518 * Call the console drivers, asking them to write out
503 * log_buf[start] to log_buf[end - 1]. 519 * log_buf[start] to log_buf[end - 1].
504 * The console_sem must be held. 520 * The console_lock must be held.
505 */ 521 */
506static void call_console_drivers(unsigned start, unsigned end) 522static void call_console_drivers(unsigned start, unsigned end)
507{ 523{
@@ -604,11 +620,11 @@ static int have_callable_console(void)
604 * 620 *
605 * This is printk(). It can be called from any context. We want it to work. 621 * This is printk(). It can be called from any context. We want it to work.
606 * 622 *
607 * We try to grab the console_sem. If we succeed, it's easy - we log the output and 623 * We try to grab the console_lock. If we succeed, it's easy - we log the output and
608 * call the console drivers. If we fail to get the semaphore we place the output 624 * call the console drivers. If we fail to get the semaphore we place the output
609 * into the log buffer and return. The current holder of the console_sem will 625 * into the log buffer and return. The current holder of the console_sem will
610 * notice the new output in release_console_sem() and will send it to the 626 * notice the new output in console_unlock(); and will send it to the
611 * consoles before releasing the semaphore. 627 * consoles before releasing the lock.
612 * 628 *
613 * One effect of this deferred printing is that code which calls printk() and 629 * One effect of this deferred printing is that code which calls printk() and
614 * then changes console_loglevel may break. This is because console_loglevel 630 * then changes console_loglevel may break. This is because console_loglevel
@@ -659,19 +675,19 @@ static inline int can_use_console(unsigned int cpu)
659/* 675/*
660 * Try to get console ownership to actually show the kernel 676 * Try to get console ownership to actually show the kernel
661 * messages from a 'printk'. Return true (and with the 677 * messages from a 'printk'. Return true (and with the
662 * console_semaphore held, and 'console_locked' set) if it 678 * console_lock held, and 'console_locked' set) if it
663 * is successful, false otherwise. 679 * is successful, false otherwise.
664 * 680 *
665 * This gets called with the 'logbuf_lock' spinlock held and 681 * This gets called with the 'logbuf_lock' spinlock held and
666 * interrupts disabled. It should return with 'lockbuf_lock' 682 * interrupts disabled. It should return with 'lockbuf_lock'
667 * released but interrupts still disabled. 683 * released but interrupts still disabled.
668 */ 684 */
669static int acquire_console_semaphore_for_printk(unsigned int cpu) 685static int console_trylock_for_printk(unsigned int cpu)
670 __releases(&logbuf_lock) 686 __releases(&logbuf_lock)
671{ 687{
672 int retval = 0; 688 int retval = 0;
673 689
674 if (!try_acquire_console_sem()) { 690 if (console_trylock()) {
675 retval = 1; 691 retval = 1;
676 692
677 /* 693 /*
@@ -827,12 +843,12 @@ asmlinkage int vprintk(const char *fmt, va_list args)
827 * actual magic (print out buffers, wake up klogd, 843 * actual magic (print out buffers, wake up klogd,
828 * etc). 844 * etc).
829 * 845 *
830 * The acquire_console_semaphore_for_printk() function 846 * The console_trylock_for_printk() function
831 * will release 'logbuf_lock' regardless of whether it 847 * will release 'logbuf_lock' regardless of whether it
832 * actually gets the semaphore or not. 848 * actually gets the semaphore or not.
833 */ 849 */
834 if (acquire_console_semaphore_for_printk(this_cpu)) 850 if (console_trylock_for_printk(this_cpu))
835 release_console_sem(); 851 console_unlock();
836 852
837 lockdep_on(); 853 lockdep_on();
838out_restore_irqs: 854out_restore_irqs:
@@ -993,7 +1009,7 @@ void suspend_console(void)
993 if (!console_suspend_enabled) 1009 if (!console_suspend_enabled)
994 return; 1010 return;
995 printk("Suspending console(s) (use no_console_suspend to debug)\n"); 1011 printk("Suspending console(s) (use no_console_suspend to debug)\n");
996 acquire_console_sem(); 1012 console_lock();
997 console_suspended = 1; 1013 console_suspended = 1;
998 up(&console_sem); 1014 up(&console_sem);
999} 1015}
@@ -1004,7 +1020,7 @@ void resume_console(void)
1004 return; 1020 return;
1005 down(&console_sem); 1021 down(&console_sem);
1006 console_suspended = 0; 1022 console_suspended = 0;
1007 release_console_sem(); 1023 console_unlock();
1008} 1024}
1009 1025
1010/** 1026/**
@@ -1027,21 +1043,21 @@ static int __cpuinit console_cpu_notify(struct notifier_block *self,
1027 case CPU_DYING: 1043 case CPU_DYING:
1028 case CPU_DOWN_FAILED: 1044 case CPU_DOWN_FAILED:
1029 case CPU_UP_CANCELED: 1045 case CPU_UP_CANCELED:
1030 acquire_console_sem(); 1046 console_lock();
1031 release_console_sem(); 1047 console_unlock();
1032 } 1048 }
1033 return NOTIFY_OK; 1049 return NOTIFY_OK;
1034} 1050}
1035 1051
1036/** 1052/**
1037 * acquire_console_sem - lock the console system for exclusive use. 1053 * console_lock - lock the console system for exclusive use.
1038 * 1054 *
1039 * Acquires a semaphore which guarantees that the caller has 1055 * Acquires a lock which guarantees that the caller has
1040 * exclusive access to the console system and the console_drivers list. 1056 * exclusive access to the console system and the console_drivers list.
1041 * 1057 *
1042 * Can sleep, returns nothing. 1058 * Can sleep, returns nothing.
1043 */ 1059 */
1044void acquire_console_sem(void) 1060void console_lock(void)
1045{ 1061{
1046 BUG_ON(in_interrupt()); 1062 BUG_ON(in_interrupt());
1047 down(&console_sem); 1063 down(&console_sem);
@@ -1050,21 +1066,29 @@ void acquire_console_sem(void)
1050 console_locked = 1; 1066 console_locked = 1;
1051 console_may_schedule = 1; 1067 console_may_schedule = 1;
1052} 1068}
1053EXPORT_SYMBOL(acquire_console_sem); 1069EXPORT_SYMBOL(console_lock);
1054 1070
1055int try_acquire_console_sem(void) 1071/**
1072 * console_trylock - try to lock the console system for exclusive use.
1073 *
1074 * Tried to acquire a lock which guarantees that the caller has
1075 * exclusive access to the console system and the console_drivers list.
1076 *
1077 * returns 1 on success, and 0 on failure to acquire the lock.
1078 */
1079int console_trylock(void)
1056{ 1080{
1057 if (down_trylock(&console_sem)) 1081 if (down_trylock(&console_sem))
1058 return -1; 1082 return 0;
1059 if (console_suspended) { 1083 if (console_suspended) {
1060 up(&console_sem); 1084 up(&console_sem);
1061 return -1; 1085 return 0;
1062 } 1086 }
1063 console_locked = 1; 1087 console_locked = 1;
1064 console_may_schedule = 0; 1088 console_may_schedule = 0;
1065 return 0; 1089 return 1;
1066} 1090}
1067EXPORT_SYMBOL(try_acquire_console_sem); 1091EXPORT_SYMBOL(console_trylock);
1068 1092
1069int is_console_locked(void) 1093int is_console_locked(void)
1070{ 1094{
@@ -1095,20 +1119,20 @@ void wake_up_klogd(void)
1095} 1119}
1096 1120
1097/** 1121/**
1098 * release_console_sem - unlock the console system 1122 * console_unlock - unlock the console system
1099 * 1123 *
1100 * Releases the semaphore which the caller holds on the console system 1124 * Releases the console_lock which the caller holds on the console system
1101 * and the console driver list. 1125 * and the console driver list.
1102 * 1126 *
1103 * While the semaphore was held, console output may have been buffered 1127 * While the console_lock was held, console output may have been buffered
1104 * by printk(). If this is the case, release_console_sem() emits 1128 * by printk(). If this is the case, console_unlock(); emits
1105 * the output prior to releasing the semaphore. 1129 * the output prior to releasing the lock.
1106 * 1130 *
1107 * If there is output waiting for klogd, we wake it up. 1131 * If there is output waiting for klogd, we wake it up.
1108 * 1132 *
1109 * release_console_sem() may be called from any context. 1133 * console_unlock(); may be called from any context.
1110 */ 1134 */
1111void release_console_sem(void) 1135void console_unlock(void)
1112{ 1136{
1113 unsigned long flags; 1137 unsigned long flags;
1114 unsigned _con_start, _log_end; 1138 unsigned _con_start, _log_end;
@@ -1141,7 +1165,7 @@ void release_console_sem(void)
1141 if (wake_klogd) 1165 if (wake_klogd)
1142 wake_up_klogd(); 1166 wake_up_klogd();
1143} 1167}
1144EXPORT_SYMBOL(release_console_sem); 1168EXPORT_SYMBOL(console_unlock);
1145 1169
1146/** 1170/**
1147 * console_conditional_schedule - yield the CPU if required 1171 * console_conditional_schedule - yield the CPU if required
@@ -1150,7 +1174,7 @@ EXPORT_SYMBOL(release_console_sem);
1150 * if this CPU should yield the CPU to another task, do 1174 * if this CPU should yield the CPU to another task, do
1151 * so here. 1175 * so here.
1152 * 1176 *
1153 * Must be called within acquire_console_sem(). 1177 * Must be called within console_lock();.
1154 */ 1178 */
1155void __sched console_conditional_schedule(void) 1179void __sched console_conditional_schedule(void)
1156{ 1180{
@@ -1171,14 +1195,14 @@ void console_unblank(void)
1171 if (down_trylock(&console_sem) != 0) 1195 if (down_trylock(&console_sem) != 0)
1172 return; 1196 return;
1173 } else 1197 } else
1174 acquire_console_sem(); 1198 console_lock();
1175 1199
1176 console_locked = 1; 1200 console_locked = 1;
1177 console_may_schedule = 0; 1201 console_may_schedule = 0;
1178 for_each_console(c) 1202 for_each_console(c)
1179 if ((c->flags & CON_ENABLED) && c->unblank) 1203 if ((c->flags & CON_ENABLED) && c->unblank)
1180 c->unblank(); 1204 c->unblank();
1181 release_console_sem(); 1205 console_unlock();
1182} 1206}
1183 1207
1184/* 1208/*
@@ -1189,7 +1213,7 @@ struct tty_driver *console_device(int *index)
1189 struct console *c; 1213 struct console *c;
1190 struct tty_driver *driver = NULL; 1214 struct tty_driver *driver = NULL;
1191 1215
1192 acquire_console_sem(); 1216 console_lock();
1193 for_each_console(c) { 1217 for_each_console(c) {
1194 if (!c->device) 1218 if (!c->device)
1195 continue; 1219 continue;
@@ -1197,7 +1221,7 @@ struct tty_driver *console_device(int *index)
1197 if (driver) 1221 if (driver)
1198 break; 1222 break;
1199 } 1223 }
1200 release_console_sem(); 1224 console_unlock();
1201 return driver; 1225 return driver;
1202} 1226}
1203 1227
@@ -1208,17 +1232,17 @@ struct tty_driver *console_device(int *index)
1208 */ 1232 */
1209void console_stop(struct console *console) 1233void console_stop(struct console *console)
1210{ 1234{
1211 acquire_console_sem(); 1235 console_lock();
1212 console->flags &= ~CON_ENABLED; 1236 console->flags &= ~CON_ENABLED;
1213 release_console_sem(); 1237 console_unlock();
1214} 1238}
1215EXPORT_SYMBOL(console_stop); 1239EXPORT_SYMBOL(console_stop);
1216 1240
1217void console_start(struct console *console) 1241void console_start(struct console *console)
1218{ 1242{
1219 acquire_console_sem(); 1243 console_lock();
1220 console->flags |= CON_ENABLED; 1244 console->flags |= CON_ENABLED;
1221 release_console_sem(); 1245 console_unlock();
1222} 1246}
1223EXPORT_SYMBOL(console_start); 1247EXPORT_SYMBOL(console_start);
1224 1248
@@ -1340,7 +1364,7 @@ void register_console(struct console *newcon)
1340 * Put this console in the list - keep the 1364 * Put this console in the list - keep the
1341 * preferred driver at the head of the list. 1365 * preferred driver at the head of the list.
1342 */ 1366 */
1343 acquire_console_sem(); 1367 console_lock();
1344 if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) { 1368 if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
1345 newcon->next = console_drivers; 1369 newcon->next = console_drivers;
1346 console_drivers = newcon; 1370 console_drivers = newcon;
@@ -1352,14 +1376,14 @@ void register_console(struct console *newcon)
1352 } 1376 }
1353 if (newcon->flags & CON_PRINTBUFFER) { 1377 if (newcon->flags & CON_PRINTBUFFER) {
1354 /* 1378 /*
1355 * release_console_sem() will print out the buffered messages 1379 * console_unlock(); will print out the buffered messages
1356 * for us. 1380 * for us.
1357 */ 1381 */
1358 spin_lock_irqsave(&logbuf_lock, flags); 1382 spin_lock_irqsave(&logbuf_lock, flags);
1359 con_start = log_start; 1383 con_start = log_start;
1360 spin_unlock_irqrestore(&logbuf_lock, flags); 1384 spin_unlock_irqrestore(&logbuf_lock, flags);
1361 } 1385 }
1362 release_console_sem(); 1386 console_unlock();
1363 console_sysfs_notify(); 1387 console_sysfs_notify();
1364 1388
1365 /* 1389 /*
@@ -1396,7 +1420,7 @@ int unregister_console(struct console *console)
1396 return braille_unregister_console(console); 1420 return braille_unregister_console(console);
1397#endif 1421#endif
1398 1422
1399 acquire_console_sem(); 1423 console_lock();
1400 if (console_drivers == console) { 1424 if (console_drivers == console) {
1401 console_drivers=console->next; 1425 console_drivers=console->next;
1402 res = 0; 1426 res = 0;
@@ -1418,7 +1442,7 @@ int unregister_console(struct console *console)
1418 if (console_drivers != NULL && console->flags & CON_CONSDEV) 1442 if (console_drivers != NULL && console->flags & CON_CONSDEV)
1419 console_drivers->flags |= CON_CONSDEV; 1443 console_drivers->flags |= CON_CONSDEV;
1420 1444
1421 release_console_sem(); 1445 console_unlock();
1422 console_sysfs_notify(); 1446 console_sysfs_notify();
1423 return res; 1447 return res;
1424} 1448}