Skip to content

Commit f8ac924

Browse files
committed
tty: tty_io: update timestamps on all device nodes
jira LE-3201 Rebuild_History Non-Buildable kernel-rt-4.18.0-553.27.1.rt7.368.el8_10 commit-author Michal Sekletar <msekleta@redhat.com> commit 360c11e Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-rt-4.18.0-553.27.1.rt7.368.el8_10/360c11e2.failed 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> (cherry picked from commit 360c11e) Signed-off-by: Jonathan Maple <jmaple@ciq.com> # Conflicts: # drivers/tty/tty_io.c
1 parent 9d58ba2 commit f8ac924

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
tty: tty_io: update timestamps on all device nodes
2+
3+
jira LE-3201
4+
Rebuild_History Non-Buildable kernel-rt-4.18.0-553.27.1.rt7.368.el8_10
5+
commit-author Michal Sekletar <msekleta@redhat.com>
6+
commit 360c11e2258ce4269441a5ab6d43d0b202f4261b
7+
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
8+
Will be included in final tarball splat. Ref for failed cherry-pick at:
9+
ciq/ciq_backports/kernel-rt-4.18.0-553.27.1.rt7.368.el8_10/360c11e2.failed
10+
11+
User space applications watch for timestamp changes on character device
12+
files in order to determine idle time of a given terminal session. For
13+
example, "w" program uses this information to populate the IDLE column
14+
of its output [1]. Similarly, systemd-logind has optional feature where
15+
it uses atime of the tty character device to determine if there was
16+
activity on the terminal associated with the logind's session object. If
17+
there was no activity for a configured period of time then logind will
18+
terminate such session [2].
19+
20+
Now, usually (e.g. bash running on the terminal) the use of the terminal
21+
will update timestamps (atime and mtime) on the corresponding terminal
22+
character device. However, if access to the terminal, e.g. /dev/pts/0,
23+
is performed through magic character device /dev/tty then such access
24+
obviously changes the state of the terminal, however timestamps on the
25+
device that correspond to the terminal (/dev/pts/0) are not updated.
26+
27+
This patch makes sure that we update timestamps on *all* character
28+
devices that correspond to the given tty, because outside observers (w,
29+
systemd-logind) are maybe checking these timestamps. Obviously, they can
30+
not check timestamps on /dev/tty as that has per-process meaning.
31+
32+
[1] https://gitlab.com/procps-ng/procps/-/blob/v4.0.0/w.c#L286
33+
[2] https://github.com/systemd/systemd/blob/v252/NEWS#L477
34+
35+
Signed-off-by: Michal Sekletar <msekleta@redhat.com>
36+
Message-ID: <20230613172107.78138-1-msekleta@redhat.com>
37+
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
38+
(cherry picked from commit 360c11e2258ce4269441a5ab6d43d0b202f4261b)
39+
Signed-off-by: Jonathan Maple <jmaple@ciq.com>
40+
41+
# Conflicts:
42+
# drivers/tty/tty_io.c
43+
diff --cc drivers/tty/tty_io.c
44+
index 7cb9fc7e0eb4,a505d2c49110..000000000000
45+
--- a/drivers/tty/tty_io.c
46+
+++ b/drivers/tty/tty_io.c
47+
@@@ -97,8 -98,10 +97,13 @@@
48+
#include <linux/seq_file.h>
49+
#include <linux/serial.h>
50+
#include <linux/ratelimit.h>
51+
-#include <linux/compat.h>
52+
+
53+
#include <linux/uaccess.h>
54+
++<<<<<<< HEAD
55+
++=======
56+
+ #include <linux/termios_internal.h>
57+
+ #include <linux/fs.h>
58+
++>>>>>>> 360c11e2258c (tty: tty_io: update timestamps on all device nodes)
59+
60+
#include <linux/kbd_kern.h>
61+
#include <linux/vt_kern.h>
62+
@@@ -816,39 -812,110 +821,47 @@@ void start_tty(struct tty_struct *tty
63+
}
64+
EXPORT_SYMBOL(start_tty);
65+
66+
- static void tty_update_time(struct timespec64 *time)
67+
+ static void tty_update_time(struct tty_struct *tty, bool mtime)
68+
{
69+
time64_t sec = ktime_get_real_seconds();
70+
+ struct tty_file_private *priv;
71+
72+
- /*
73+
- * We only care if the two values differ in anything other than the
74+
- * lower three bits (i.e every 8 seconds). If so, then we can update
75+
- * the time of the tty device, otherwise it could be construded as a
76+
- * security leak to let userspace know the exact timing of the tty.
77+
- */
78+
- if ((sec ^ time->tv_sec) & ~7)
79+
- time->tv_sec = sec;
80+
+ spin_lock(&tty->files_lock);
81+
+ list_for_each_entry(priv, &tty->tty_files, list) {
82+
+ struct inode *inode = file_inode(priv->file);
83+
+ struct timespec64 *time = mtime ? &inode->i_mtime : &inode->i_atime;
84+
+
85+
+ /*
86+
+ * We only care if the two values differ in anything other than the
87+
+ * lower three bits (i.e every 8 seconds). If so, then we can update
88+
+ * the time of the tty device, otherwise it could be construded as a
89+
+ * security leak to let userspace know the exact timing of the tty.
90+
+ */
91+
+ if ((sec ^ time->tv_sec) & ~7)
92+
+ time->tv_sec = sec;
93+
+ }
94+
+ spin_unlock(&tty->files_lock);
95+
}
96+
97+
-/*
98+
- * Iterate on the ldisc ->read() function until we've gotten all
99+
- * the data the ldisc has for us.
100+
- *
101+
- * The "cookie" is something that the ldisc read function can fill
102+
- * in to let us know that there is more data to be had.
103+
- *
104+
- * We promise to continue to call the ldisc until it stops returning
105+
- * data or clears the cookie. The cookie may be something that the
106+
- * ldisc maintains state for and needs to free.
107+
- */
108+
-static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty,
109+
- struct file *file, struct iov_iter *to)
110+
-{
111+
- int retval = 0;
112+
- void *cookie = NULL;
113+
- unsigned long offset = 0;
114+
- char kernel_buf[64];
115+
- size_t count = iov_iter_count(to);
116+
-
117+
- do {
118+
- int size, copied;
119+
-
120+
- size = count > sizeof(kernel_buf) ? sizeof(kernel_buf) : count;
121+
- size = ld->ops->read(tty, file, kernel_buf, size, &cookie, offset);
122+
- if (!size)
123+
- break;
124+
-
125+
- if (size < 0) {
126+
- /* Did we have an earlier error (ie -EFAULT)? */
127+
- if (retval)
128+
- break;
129+
- retval = size;
130+
-
131+
- /*
132+
- * -EOVERFLOW means we didn't have enough space
133+
- * for a whole packet, and we shouldn't return
134+
- * a partial result.
135+
- */
136+
- if (retval == -EOVERFLOW)
137+
- offset = 0;
138+
- break;
139+
- }
140+
-
141+
- copied = copy_to_iter(kernel_buf, size, to);
142+
- offset += copied;
143+
- count -= copied;
144+
-
145+
- /*
146+
- * If the user copy failed, we still need to do another ->read()
147+
- * call if we had a cookie to let the ldisc clear up.
148+
- *
149+
- * But make sure size is zeroed.
150+
- */
151+
- if (unlikely(copied != size)) {
152+
- count = 0;
153+
- retval = -EFAULT;
154+
- }
155+
- } while (cookie);
156+
-
157+
- /* We always clear tty buffer in case they contained passwords */
158+
- memzero_explicit(kernel_buf, sizeof(kernel_buf));
159+
- return offset ? offset : retval;
160+
-}
161+
-
162+
-
163+
/**
164+
- * tty_read - read method for tty device files
165+
- * @iocb: kernel I/O control block
166+
- * @to: destination for the data read
167+
+ * tty_read - read method for tty device files
168+
+ * @file: pointer to tty file
169+
+ * @buf: user buffer
170+
+ * @count: size of user buffer
171+
+ * @ppos: unused
172+
*
173+
- * Perform the read system call function on this terminal device. Checks
174+
- * for hung up devices before calling the line discipline method.
175+
+ * Perform the read system call function on this terminal device. Checks
176+
+ * for hung up devices before calling the line discipline method.
177+
*
178+
- * Locking:
179+
- * Locks the line discipline internally while needed. Multiple read calls
180+
- * may be outstanding in parallel.
181+
+ * Locking:
182+
+ * Locks the line discipline internally while needed. Multiple
183+
+ * read calls may be outstanding in parallel.
184+
*/
185+
-static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to)
186+
+
187+
+static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
188+
+ loff_t *ppos)
189+
{
190+
int i;
191+
- struct file *file = iocb->ki_filp;
192+
struct inode *inode = file_inode(file);
193+
struct tty_struct *tty = file_tty(file);
194+
struct tty_ldisc *ld;
195+
* Unmerged path drivers/tty/tty_io.c

0 commit comments

Comments
 (0)