Skip to content

Commit 360c11e

Browse files
msekletargregkh
authored andcommitted
tty: tty_io: update timestamps on all device nodes
User space applications watch for timestamp changes on character device files in order to determine idle time of a given terminal session. For example, "w" program uses this information to populate the IDLE column of its output [1]. Similarly, systemd-logind has optional feature where it uses atime of the tty character device to determine if there was activity on the terminal associated with the logind's session object. If there was no activity for a configured period of time then logind will terminate such session [2]. Now, usually (e.g. bash running on the terminal) the use of the terminal will update timestamps (atime and mtime) on the corresponding terminal character device. However, if access to the terminal, e.g. /dev/pts/0, is performed through magic character device /dev/tty then such access obviously changes the state of the terminal, however timestamps on the device that correspond to the terminal (/dev/pts/0) are not updated. This patch makes sure that we update timestamps on *all* character devices that correspond to the given tty, because outside observers (w, systemd-logind) are maybe checking these timestamps. Obviously, they can not check timestamps on /dev/tty as that has per-process meaning. [1] https://gitlab.com/procps-ng/procps/-/blob/v4.0.0/w.c#L286 [2] https://github.com/systemd/systemd/blob/v252/NEWS#L477 Signed-off-by: Michal Sekletar <msekleta@redhat.com> Message-ID: <20230613172107.78138-1-msekleta@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4903fde commit 360c11e

1 file changed

Lines changed: 20 additions & 11 deletions

File tree

drivers/tty/tty_io.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#include <linux/compat.h>
102102
#include <linux/uaccess.h>
103103
#include <linux/termios_internal.h>
104+
#include <linux/fs.h>
104105

105106
#include <linux/kbd_kern.h>
106107
#include <linux/vt_kern.h>
@@ -811,18 +812,26 @@ void start_tty(struct tty_struct *tty)
811812
}
812813
EXPORT_SYMBOL(start_tty);
813814

814-
static void tty_update_time(struct timespec64 *time)
815+
static void tty_update_time(struct tty_struct *tty, bool mtime)
815816
{
816817
time64_t sec = ktime_get_real_seconds();
818+
struct tty_file_private *priv;
817819

818-
/*
819-
* We only care if the two values differ in anything other than the
820-
* lower three bits (i.e every 8 seconds). If so, then we can update
821-
* the time of the tty device, otherwise it could be construded as a
822-
* security leak to let userspace know the exact timing of the tty.
823-
*/
824-
if ((sec ^ time->tv_sec) & ~7)
825-
time->tv_sec = sec;
820+
spin_lock(&tty->files_lock);
821+
list_for_each_entry(priv, &tty->tty_files, list) {
822+
struct inode *inode = file_inode(priv->file);
823+
struct timespec64 *time = mtime ? &inode->i_mtime : &inode->i_atime;
824+
825+
/*
826+
* We only care if the two values differ in anything other than the
827+
* lower three bits (i.e every 8 seconds). If so, then we can update
828+
* the time of the tty device, otherwise it could be construded as a
829+
* security leak to let userspace know the exact timing of the tty.
830+
*/
831+
if ((sec ^ time->tv_sec) & ~7)
832+
time->tv_sec = sec;
833+
}
834+
spin_unlock(&tty->files_lock);
826835
}
827836

828837
/*
@@ -928,7 +937,7 @@ static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to)
928937
tty_ldisc_deref(ld);
929938

930939
if (i > 0)
931-
tty_update_time(&inode->i_atime);
940+
tty_update_time(tty, false);
932941

933942
return i;
934943
}
@@ -1036,7 +1045,7 @@ static inline ssize_t do_tty_write(
10361045
cond_resched();
10371046
}
10381047
if (written) {
1039-
tty_update_time(&file_inode(file)->i_mtime);
1048+
tty_update_time(tty, true);
10401049
ret = written;
10411050
}
10421051
out:

0 commit comments

Comments
 (0)