On 2021/04/07 22:48, Greg Kroah-Hartman wrote:
>> By the way, as soon as applying this patch, I guess that syzkaller starts
>> generating hung task reports because /dev/ttyprintk can trivially trigger
>> flood of
>>
>>   tty_warn(tty, "%s: tty->count = 1 port count = %d\n", __func__,
>>            port->count);
>>
>> message, and adding
>>
>>   if (strcmp(tty_driver_name(tty), "ttyprintk"))
> 
> Odd, how can ttyprintk() generate that mess?

So far three tests and results:

  https://groups.google.com/g/syzkaller-bugs/c/yRLYijD2tbw/m/WifLgadvAAAJ
  https://groups.google.com/g/syzkaller-bugs/c/yRLYijD2tbw/m/w2_MiMmAAAAJ
  https://groups.google.com/g/syzkaller-bugs/c/yRLYijD2tbw/m/hfsQqSOPAAAJ

Patch https://syzkaller.appspot.com/x/patch.diff?x=145e4c9ad00000 generated
console output https://syzkaller.appspot.com/x/log.txt?x=162f9fced00000 .

Patch https://syzkaller.appspot.com/x/patch.diff?x=14839931d00000 did not
flood the console output enough to fire khungtaskd.

Maybe it is because /dev/ttyprintk can be opened/closed by multiple processes
without serialization?

Running

  for i in $(seq 1 100); do sleep 1 > /dev/ttyprintk & done

results in

  tty_port_close_start: tty->count = 1 port count = 100

. If tty_port_open() from tpk_open() can do

  spin_lock_irq(&port->lock);
  ++port->count;
  spin_unlock_irq(&port->lock);

when tty_port_close_start() from tty_port_close() from tpk_close() is doing

  spin_lock_irqsave(&port->lock, flags);
  if (tty->count == 1 && port->count != 1) {
    tty_warn(tty, "%s: tty->count = 1 port count = %d\n", __func__,
             port->count);
    port->count = 1;
  }
  if (--port->count < 0) {
    tty_warn(tty, "%s: bad port count (%d)\n", __func__,
             port->count);
    port->count = 0;
  }

  if (port->count) {
    spin_unlock_irqrestore(&port->lock, flags);
    return 0;
  }
  spin_unlock_irqrestore(&port->lock, flags);

, what prevents port->count from getting larger than 1 ?

Reply via email to