@@ -390,8 +390,12 @@ DEFINE_RAW_SPINLOCK(logbuf_lock);
390390 printk_safe_exit_irqrestore(flags); \
391391 } while (0)
392392
393+ /* syslog_lock protects syslog_* variables and write access to clear_seq. */
394+ static DEFINE_RAW_SPINLOCK (syslog_lock );
395+
393396#ifdef CONFIG_PRINTK
394397DECLARE_WAIT_QUEUE_HEAD (log_wait );
398+ /* All 3 protected by @syslog_lock. */
395399/* the next printk record to read by syslog(READ) or /proc/kmsg */
396400static u64 syslog_seq ;
397401static size_t syslog_partial ;
@@ -410,7 +414,7 @@ struct latched_seq {
410414/*
411415 * The next printk record to read after the last 'clear' command. There are
412416 * two copies (updated with seqcount_latch) so that reads can locklessly
413- * access a valid value. Writers are synchronized by @logbuf_lock .
417+ * access a valid value. Writers are synchronized by @syslog_lock .
414418 */
415419static struct latched_seq clear_seq = {
416420 .latch = SEQCNT_LATCH_ZERO (clear_seq .latch ),
@@ -470,7 +474,7 @@ bool printk_percpu_data_ready(void)
470474 return __printk_percpu_data_ready ;
471475}
472476
473- /* Must be called under logbuf_lock . */
477+ /* Must be called under syslog_lock . */
474478static void latched_seq_write (struct latched_seq * ls , u64 val )
475479{
476480 raw_write_seqcount_latch (& ls -> latch );
@@ -1529,7 +1533,9 @@ static int syslog_print(char __user *buf, int size)
15291533 size_t skip ;
15301534
15311535 logbuf_lock_irq ();
1536+ raw_spin_lock (& syslog_lock );
15321537 if (!prb_read_valid (prb , syslog_seq , & r )) {
1538+ raw_spin_unlock (& syslog_lock );
15331539 logbuf_unlock_irq ();
15341540 break ;
15351541 }
@@ -1559,6 +1565,7 @@ static int syslog_print(char __user *buf, int size)
15591565 syslog_partial += n ;
15601566 } else
15611567 n = 0 ;
1568+ raw_spin_unlock (& syslog_lock );
15621569 logbuf_unlock_irq ();
15631570
15641571 if (!n )
@@ -1625,8 +1632,11 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
16251632 break ;
16261633 }
16271634
1628- if (clear )
1635+ if (clear ) {
1636+ raw_spin_lock (& syslog_lock );
16291637 latched_seq_write (& clear_seq , seq );
1638+ raw_spin_unlock (& syslog_lock );
1639+ }
16301640 logbuf_unlock_irq ();
16311641
16321642 kfree (text );
@@ -1636,10 +1646,24 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
16361646static void syslog_clear (void )
16371647{
16381648 logbuf_lock_irq ();
1649+ raw_spin_lock (& syslog_lock );
16391650 latched_seq_write (& clear_seq , prb_next_seq (prb ));
1651+ raw_spin_unlock (& syslog_lock );
16401652 logbuf_unlock_irq ();
16411653}
16421654
1655+ /* Return a consistent copy of @syslog_seq. */
1656+ static u64 read_syslog_seq_irq (void )
1657+ {
1658+ u64 seq ;
1659+
1660+ raw_spin_lock_irq (& syslog_lock );
1661+ seq = syslog_seq ;
1662+ raw_spin_unlock_irq (& syslog_lock );
1663+
1664+ return seq ;
1665+ }
1666+
16431667int do_syslog (int type , char __user * buf , int len , int source )
16441668{
16451669 struct printk_info info ;
@@ -1663,8 +1687,9 @@ int do_syslog(int type, char __user *buf, int len, int source)
16631687 return 0 ;
16641688 if (!access_ok (buf , len ))
16651689 return - EFAULT ;
1690+
16661691 error = wait_event_interruptible (log_wait ,
1667- prb_read_valid (prb , syslog_seq , NULL ));
1692+ prb_read_valid (prb , read_syslog_seq_irq () , NULL ));
16681693 if (error )
16691694 return error ;
16701695 error = syslog_print (buf , len );
@@ -1713,8 +1738,10 @@ int do_syslog(int type, char __user *buf, int len, int source)
17131738 /* Number of chars in the log buffer */
17141739 case SYSLOG_ACTION_SIZE_UNREAD :
17151740 logbuf_lock_irq ();
1741+ raw_spin_lock (& syslog_lock );
17161742 if (!prb_read_valid_info (prb , syslog_seq , & info , NULL )) {
17171743 /* No unread messages. */
1744+ raw_spin_unlock (& syslog_lock );
17181745 logbuf_unlock_irq ();
17191746 return 0 ;
17201747 }
@@ -1743,6 +1770,7 @@ int do_syslog(int type, char __user *buf, int len, int source)
17431770 }
17441771 error -= syslog_partial ;
17451772 }
1773+ raw_spin_unlock (& syslog_lock );
17461774 logbuf_unlock_irq ();
17471775 break ;
17481776 /* Size of the log buffer */
@@ -2992,7 +3020,12 @@ void register_console(struct console *newcon)
29923020 */
29933021 exclusive_console = newcon ;
29943022 exclusive_console_stop_seq = console_seq ;
3023+
3024+ /* Get a consistent copy of @syslog_seq. */
3025+ raw_spin_lock (& syslog_lock );
29953026 console_seq = syslog_seq ;
3027+ raw_spin_unlock (& syslog_lock );
3028+
29963029 logbuf_unlock_irqrestore (flags );
29973030 }
29983031 console_unlock ();
0 commit comments