linux_old1/drivers
Tejun Heo 28b0f8a696 tty: make n_tty_read() always abort if hangup is in progress
A tty is hung up by __tty_hangup() setting file->f_op to
hung_up_tty_fops, which is skipped on ttys whose write operation isn't
tty_write().  This means that, for example, /dev/console whose write
op is redirected_tty_write() is never actually marked hung up.

Because n_tty_read() uses the hung up status to decide whether to
abort the waiting readers, the lack of hung-up marking can lead to the
following scenario.

 1. A session contains two processes.  The leader and its child.  The
    child ignores SIGHUP.

 2. The leader exits and starts disassociating from the controlling
    terminal (/dev/console).

 3. __tty_hangup() skips setting f_op to hung_up_tty_fops.

 4. SIGHUP is delivered and ignored.

 5. tty_ldisc_hangup() is invoked.  It wakes up the waits which should
    clear the read lockers of tty->ldisc_sem.

 6. The reader wakes up but because tty_hung_up_p() is false, it
    doesn't abort and goes back to sleep while read-holding
    tty->ldisc_sem.

 7. The leader progresses to tty_ldisc_lock() in tty_ldisc_hangup()
    and is now stuck in D sleep indefinitely waiting for
    tty->ldisc_sem.

The following is Alan's explanation on why some ttys aren't hung up.

 http://lkml.kernel.org/r/20171101170908.6ad08580@alans-desktop

 1. It broke the serial consoles because they would hang up and close
    down the hardware. With tty_port that *should* be fixable properly
    for any cases remaining.

 2. The console layer was (and still is) completely broken and doens't
    refcount properly. So if you turn on console hangups it breaks (as
    indeed does freeing consoles and half a dozen other things).

As neither can be fixed quickly, this patch works around the problem
by introducing a new flag, TTY_HUPPING, which is used solely to tell
n_tty_read() that hang-up is in progress for the console and the
readers should be aborted regardless of the hung-up status of the
device.

The following is a sample hung task warning caused by this issue.

  INFO: task agetty:2662 blocked for more than 120 seconds.
        Not tainted 4.11.3-dbg-tty-lockup-02478-gfd6c7ee-dirty #28
  "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
      0  2662      1 0x00000086
  Call Trace:
   __schedule+0x267/0x890
   schedule+0x36/0x80
   schedule_timeout+0x23c/0x2e0
   ldsem_down_write+0xce/0x1f6
   tty_ldisc_lock+0x16/0x30
   tty_ldisc_hangup+0xb3/0x1b0
   __tty_hangup+0x300/0x410
   disassociate_ctty+0x6c/0x290
   do_exit+0x7ef/0xb00
   do_group_exit+0x3f/0xa0
   get_signal+0x1b3/0x5d0
   do_signal+0x28/0x660
   exit_to_usermode_loop+0x46/0x86
   do_syscall_64+0x9c/0xb0
   entry_SYSCALL64_slow_path+0x25/0x25

The following is the repro.  Run "$PROG /dev/console".  The parent
process hangs in D state.

  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/wait.h>
  #include <sys/ioctl.h>
  #include <fcntl.h>
  #include <unistd.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <errno.h>
  #include <signal.h>
  #include <time.h>
  #include <termios.h>

  int main(int argc, char **argv)
  {
	  struct sigaction sact = { .sa_handler = SIG_IGN };
	  struct timespec ts1s = { .tv_sec = 1 };
	  pid_t pid;
	  int fd;

	  if (argc < 2) {
		  fprintf(stderr, "test-hung-tty /dev/$TTY\n");
		  return 1;
	  }

	  /* fork a child to ensure that it isn't already the session leader */
	  pid = fork();
	  if (pid < 0) {
		  perror("fork");
		  return 1;
	  }

	  if (pid > 0) {
		  /* top parent, wait for everyone */
		  while (waitpid(-1, NULL, 0) >= 0)
			  ;
		  if (errno != ECHILD)
			  perror("waitpid");
		  return 0;
	  }

	  /* new session, start a new session and set the controlling tty */
	  if (setsid() < 0) {
		  perror("setsid");
		  return 1;
	  }

	  fd = open(argv[1], O_RDWR);
	  if (fd < 0) {
		  perror("open");
		  return 1;
	  }

	  if (ioctl(fd, TIOCSCTTY, 1) < 0) {
		  perror("ioctl");
		  return 1;
	  }

	  /* fork a child, sleep a bit and exit */
	  pid = fork();
	  if (pid < 0) {
		  perror("fork");
		  return 1;
	  }

	  if (pid > 0) {
		  nanosleep(&ts1s, NULL);
		  printf("Session leader exiting\n");
		  exit(0);
	  }

	  /*
	   * The child ignores SIGHUP and keeps reading from the controlling
	   * tty.  Because SIGHUP is ignored, the child doesn't get killed on
	   * parent exit and the bug in n_tty makes the read(2) block the
	   * parent's control terminal hangup attempt.  The parent ends up in
	   * D sleep until the child is explicitly killed.
	   */
	  sigaction(SIGHUP, &sact, NULL);
	  printf("Child reading tty\n");
	  while (1) {
		  char buf[1024];

		  if (read(fd, buf, sizeof(buf)) < 0) {
			  perror("read");
			  return 1;
		  }
	  }

	  return 0;
  }

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Alan Cox <alan@llwyncelyn.cymru>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-02-28 13:21:10 +01:00
..
accessibility
acpi Merge branches 'acpi-ec', 'acpi-tables' and 'acpi-doc' 2018-02-15 12:02:42 +01:00
amba
android ANDROID: binder: synchronize_rcu() when using POLLFREE. 2018-02-16 11:16:38 +01:00
ata pci-v4.16-changes 2018-02-06 09:59:40 -08:00
atm atm: he: use 64-bit arithmetic instead of 32-bit 2018-02-08 15:05:16 -05:00
auxdisplay
base ACPI updates for v4.16-rc2 2018-02-15 14:50:32 -08:00
bcma
block Things have been very quiet on the rbd side, as work continues on the 2018-02-08 11:38:59 -08:00
bluetooth vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
bus ARM: SoC driver updates for 4.16 2018-02-01 16:35:31 -08:00
cdrom
char Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2018-02-14 17:02:15 -08:00
clk MIPS changes for 4.16 2018-02-07 11:22:44 -08:00
clocksource treewide/trivial: Remove ';;$' typo noise 2018-02-22 10:59:33 +01:00
connector
cpufreq Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2018-02-14 17:02:15 -08:00
cpuidle powerpc updates for 4.16 2018-02-02 10:01:04 -08:00
crypto Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 2018-02-22 16:38:10 -08:00
dax Merge branch 'for-4.16/dax' into libnvdimm-for-next 2018-02-03 00:26:10 -07:00
dca
devfreq
dio
dma Merge branch 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm 2018-02-02 09:50:51 -08:00
dma-buf vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
edac Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2018-02-14 17:02:15 -08:00
eisa EISA: Delete error message for a failed memory allocation in eisa_probe() 2018-01-23 09:04:10 +01:00
extcon extcon: int3496: process id-pin first so that we start with the right status 2018-02-14 06:37:33 +09:00
firewire vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
firmware 2nd set of arm64 updates for 4.16: 2018-02-08 10:44:25 -08:00
fmc
fpga
fsi
gpio vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
gpu Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2018-02-25 16:27:51 -08:00
hid usb: ldusb: add PIDs for new CASSY devices supported by this driver 2018-02-15 18:44:03 +01:00
hsi vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
hv vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
hwmon Fix bad temperature display on Ryzen/Threadripper 2018-02-15 14:31:28 -08:00
hwspinlock
hwtracing Char/Misc driver patches for 4.16-rc1 2018-02-01 10:31:17 -08:00
i2c i2c: designware: Consider SCL GPIO optional 2018-02-22 12:15:35 +01:00
ide pci-v4.16-changes 2018-02-06 09:59:40 -08:00
idle
iio First round of IIO fixes for the 4.16 cycle. 2018-02-20 10:03:22 +01:00
infiniband RDMA/uverbs: Fix kernel panic while using XRC_TGT QP type 2018-02-21 13:52:19 -05:00
input vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
iommu treewide/trivial: Remove ';;$' typo noise 2018-02-22 10:59:33 +01:00
ipack
irqchip irqchip/bcm: Remove hashed address printing 2018-02-16 14:22:16 +00:00
isdn vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
leds vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
lightnvm
macintosh powerpc/macio: set a proper dma_coherent_mask 2018-02-13 08:58:53 -08:00
mailbox vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
mcb
md treewide/trivial: Remove ';;$' typo noise 2018-02-22 10:59:33 +01:00
media vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
memory ARM: SoC driver updates for 4.16 2018-02-01 16:35:31 -08:00
memstick
message scsi: mptfusion: Add bounds check in mptctl_hp_targetinfo() 2018-01-30 21:32:06 -05:00
mfd vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
misc powerpc fixes for 4.16 #4 2018-02-24 16:05:50 -08:00
mmc mmc: bcm2835: Don't overwrite max frequency unconditionally 2018-02-14 11:30:10 +01:00
mtd mtd: nand: MTD_NAND_MARVELL should depend on HAS_DMA 2018-02-12 10:57:20 +01:00
mux Char/Misc driver patches for 4.16-rc1 2018-02-01 10:31:17 -08:00
net gianfar: simplify FCS handling and fix memory leak 2018-02-23 12:26:36 -05:00
nfc
ntb NTB: ntb_perf: fix cast to restricted __le32 2018-01-28 22:17:24 -05:00
nubus
nvdimm Merge branch 'for-4.16/nfit' into libnvdimm-for-next 2018-02-03 00:26:26 -07:00
nvme nvme-rdma: fix sysfs invoked reset_ctrl error flow 2018-02-14 15:44:22 +02:00
nvmem
of device property: Constify device_get_match_data() 2018-02-12 10:41:11 +01:00
opp opp: cpu: Replace GFP_ATOMIC with GFP_KERNEL in dev_pm_opp_init_cpufreq_table 2018-02-12 15:07:46 +05:30
oprofile
parisc
parport
pci PCI/cxgb4: Extend T3 PCI quirk to T4+ devices 2018-02-16 15:41:53 -05:00
pcmcia Merge branch 'pcmcia' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia 2018-02-08 11:48:49 -08:00
perf arm_pmu: acpi: request IRQs up-front 2018-02-20 11:34:54 +00:00
phy USB/PHY updates for 4.16-rc1 2018-02-01 09:40:49 -08:00
pinctrl This is the bulk of pin control changes for the v4.16 kernel cycle: 2018-02-02 14:22:53 -08:00
platform platform/x86: dell-laptop: Removed duplicates in DMI whitelist 2018-02-15 12:18:33 +02:00
pnp
power power supply and reset changes for the v4.16 series 2018-01-31 12:55:31 -08:00
powercap
pps vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
ps3
ptp vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
pwm
rapidio vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
ras mm/memory_failure: Remove unused trapno from memory_failure 2018-01-23 12:17:42 -06:00
regulator regulator: Fix suspend to idle 2018-01-30 12:25:59 +00:00
remoteproc remoteproc updates for v4.16 2018-02-05 10:07:40 -08:00
reset
rpmsg vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
rtc vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
s390 virtio: bugfixes 2018-02-15 14:29:27 -08:00
sbus pci-v4.16-changes 2018-02-06 09:59:40 -08:00
scsi SCSI fixes on 20180222 2018-02-23 14:09:43 -08:00
sfi
sh cpufreq: Add and use cpufreq_for_each_{valid_,}entry_idx() 2018-02-08 10:21:39 +01:00
siox
slimbus
sn
soc treewide/trivial: Remove ';;$' typo noise 2018-02-22 10:59:33 +01:00
soundwire soundwire: Fix a signedness bug 2018-01-22 16:45:26 +01:00
spi Merge remote-tracking branch 'spi/topic/xilinx' into spi-next 2018-01-26 17:57:34 +00:00
spmi
ssb Merge git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git 2018-02-01 10:37:39 +02:00
staging Staging/IIO fixes for 4.16-rc2 2018-02-22 12:05:43 -08:00
target Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2018-02-09 14:49:46 -08:00
tc
tee
thermal Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux 2018-02-06 15:04:58 -08:00
thunderbolt
tty tty: make n_tty_read() always abort if hangup is in progress 2018-02-28 13:21:10 +01:00
uio vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
usb USB fixes for 4.16-rc3 2018-02-22 12:13:01 -08:00
uwb
vfio vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
vhost vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
video Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2018-02-14 17:02:15 -08:00
virt vfs: do bulk POLL* -> EPOLL* replacement 2018-02-11 14:34:03 -08:00
virtio virtio_pci: don't kfree device on register failure 2018-02-01 16:26:45 +02:00
visorbus
vlynq
vme
w1 Documentation updates for 4.16. New stuff includes refcount_t 2018-01-31 19:25:25 -08:00
watchdog linux-watchdog 4.16-rc1 merge window tag 2018-02-07 11:54:34 -08:00
xen mm, swap, frontswap: fix THP swap if frontswap enabled 2018-02-21 15:35:43 -08:00
zorro
Kconfig Char/Misc driver patches for 4.16-rc1 2018-02-01 10:31:17 -08:00
Makefile pci-v4.16-changes 2018-02-06 09:59:40 -08:00