s390/3270: hangup the 3270 tty after a disconnect
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 2 May 2016 13:09:01 +0000 (15:09 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 10 May 2016 11:24:47 +0000 (13:24 +0200)
The disconnect and later reconnect of a 3270 terminal does not do
a tty hangup. The current session is resumed which is a security
issue.

Do a tty hangup after a unit check has been received.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/char/tty3270.c

index 402eff3c1634710b90f7c9acf0ac9c08b1890d97..0a9f219fdc7c6252f68cb29a5e913826cecd2b62 100644 (file)
@@ -92,6 +92,7 @@ struct tty3270 {
        unsigned char inattr;           /* Visible/invisible input. */
        int throttle, attn;             /* tty throttle/unthrottle. */
        struct tasklet_struct readlet;  /* Tasklet to issue read request. */
+       struct tasklet_struct hanglet;  /* Tasklet to hang up the tty. */
        struct kbd_data *kbd;           /* key_maps stuff. */
 
        /* Escape sequence parsing. */
@@ -645,6 +646,16 @@ tty3270_issue_read(struct tty3270 *tp, int lock)
        }
 }
 
+/*
+ * Hang up the tty
+ */
+static void
+tty3270_hangup_tasklet(struct tty3270 *tp)
+{
+       tty_port_tty_hangup(&tp->port, true);
+       raw3270_put_view(&tp->view);
+}
+
 /*
  * Switch to the tty view.
  */
@@ -678,11 +689,14 @@ tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
        }
 
        if (rq) {
-               if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
+               if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
                        rq->rc = -EIO;
-               else
+                       raw3270_get_view(&tp->view);
+                       tasklet_schedule(&tp->hanglet);
+               } else {
                        /* Normal end. Copy residual count. */
                        rq->rescnt = irb->scsw.cmd.count;
+               }
        } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
                /* Interrupt without an outstanding request -> update all */
                tp->update_flags = TTY_UPDATE_ALL;
@@ -739,6 +753,9 @@ tty3270_alloc_view(void)
        tasklet_init(&tp->readlet,
                     (void (*)(unsigned long)) tty3270_read_tasklet,
                     (unsigned long) tp->read);
+       tasklet_init(&tp->hanglet,
+                    (void (*)(unsigned long)) tty3270_hangup_tasklet,
+                    (unsigned long) tp);
        INIT_WORK(&tp->resize_work, tty3270_resize_work);
 
        return tp;
@@ -1812,7 +1829,22 @@ tty3270_unthrottle(struct tty_struct * tty)
 static void
 tty3270_hangup(struct tty_struct *tty)
 {
-       // FIXME: implement
+       struct tty3270 *tp;
+
+       tp = tty->driver_data;
+       if (!tp)
+               return;
+       spin_lock_bh(&tp->view.lock);
+       tp->cx = tp->saved_cx = 0;
+       tp->cy = tp->saved_cy = 0;
+       tp->highlight = tp->saved_highlight = TAX_RESET;
+       tp->f_color = tp->saved_f_color = TAC_RESET;
+       tty3270_blank_screen(tp);
+       while (tp->nr_lines < tp->view.rows - 2)
+               tty3270_blank_line(tp);
+       tp->update_flags = TTY_UPDATE_ALL;
+       spin_unlock_bh(&tp->view.lock);
+       tty3270_set_timer(tp, 1);
 }
 
 static void