write: always use utmp as fallback, use mem2strcpy() for utmp strings

Resolves: RHEL-157244
This commit is contained in:
Karel Zak 2026-05-25 12:07:57 +02:00
parent c20fcabde0
commit 6d7cc5a29a
3 changed files with 199 additions and 0 deletions

View File

@ -0,0 +1,122 @@
From 1a06fc9c79b27fb842f000d26b1122d63411c5d9 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 13 May 2026 11:13:03 +0200
Subject: [PATCH 22/23] write: always use utmp as fallback
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The systemd session list may not cover all terminals (e.g., screen,
tmux, or old-style logins). Remove the "if systemd else utmp" pattern
and always fall through to utmp when the target user or tty is not
found in systemd sessions.
Also make sd_get_sessions() and sd_session_get_username() failures
non-fatal — silently fall through to utmp instead of calling errx().
Addresses: https://redhat.atlassian.net/browse/RHEL-157244
Signed-off-by: Karel Zak <kzak@redhat.com>
(cherry picked from commit 3d84e9af768f904660d962720c4c03735e86472b)
---
term-utils/write.c | 50 +++++++++++++++++++++++-----------------------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/term-utils/write.c b/term-utils/write.c
index 3784f0300..fb19e35f4 100644
--- a/term-utils/write.c
+++ b/term-utils/write.c
@@ -140,17 +140,16 @@ static int check_utmp(const struct write_control *ctl)
if (sd_booted() > 0) {
char **sessions_list;
int sessions = sd_get_sessions(&sessions_list);
+
if (sessions < 0)
- errx(EXIT_FAILURE, _("error getting sessions: %s"),
- strerror(-sessions));
+ goto utmp;
for (int i = 0; i < sessions; i++) {
char *name, *tty;
- int r;
- if ((r = sd_session_get_username(sessions_list[i], &name)) < 0)
- errx(EXIT_FAILURE, _("get user name failed: %s"), strerror (-r));
+ if (sd_session_get_username(sessions_list[i], &name) < 0)
+ continue;
if (sd_session_get_tty(sessions_list[i], &tty) < 0) {
free(name);
continue;
@@ -169,23 +168,24 @@ static int check_utmp(const struct write_control *ctl)
for (int i = 0; i < sessions; i++)
free(sessions_list[i]);
free(sessions_list);
- } else {
-#endif
- utmpxname(_PATH_UTMP);
- setutxent();
- while ((u = getutxent())) {
- if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) == 0 &&
- strncmp(ctl->dst_tty_name, u->ut_line, sizeof(u->ut_line)) == 0) {
- res = 0;
- break;
- }
- }
-
- endutxent();
-#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
+ if (res == 0)
+ return res;
}
+utmp:
#endif
+ utmpxname(_PATH_UTMP);
+ setutxent();
+
+ while ((u = getutxent())) {
+ if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) == 0 &&
+ strncmp(ctl->dst_tty_name, u->ut_line, sizeof(u->ut_line)) == 0) {
+ res = 0;
+ break;
+ }
+ }
+
+ endutxent();
return res;
}
@@ -211,16 +211,15 @@ static void search_utmp(struct write_control *ctl)
char path[256];
char **sessions_list;
int sessions = sd_get_sessions(&sessions_list);
+
if (sessions < 0)
- errx(EXIT_FAILURE, _("error getting sessions: %s"),
- strerror(-sessions));
+ goto utmp;
for (int i = 0; i < sessions; i++) {
char *name, *tty;
- int r;
- if ((r = sd_session_get_username(sessions_list[i], &name)) < 0)
- errx(EXIT_FAILURE, _("get user name failed: %s"), strerror (-r));
+ if (sd_session_get_username(sessions_list[i], &name) < 0)
+ continue;
if (strcmp(ctl->dst_login, name) != 0) {
free(name);
@@ -266,7 +265,8 @@ static void search_utmp(struct write_control *ctl)
for (int i = 0; i < sessions; i++)
free(sessions_list[i]);
free(sessions_list);
- } else
+ }
+utmp:
#endif
{
char path[sizeof(u->ut_line) + 6];
--
2.52.0

View File

@ -0,0 +1,74 @@
From dca96d57504b09c2abfca844689e521d44dcde23 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 13 May 2026 11:22:59 +0200
Subject: [PATCH 23/23] write: use mem2strcpy() for utmp strings
The utmp fields ut_user and ut_line are fixed-size buffers not
guaranteed to be null-terminated. Using strncmp(), snprintf() or
memcmp() directly on these fields can read beyond the buffer content.
Use mem2strcpy() to safely copy utmp fields into properly terminated
local buffers before any string operations.
Signed-off-by: Karel Zak <kzak@redhat.com>
(cherry picked from commit 2483e99e14a1ed24129e5255804a679c56493c25)
---
term-utils/write.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/term-utils/write.c b/term-utils/write.c
index fb19e35f4..ae550e268 100644
--- a/term-utils/write.c
+++ b/term-utils/write.c
@@ -178,8 +178,14 @@ utmp:
setutxent();
while ((u = getutxent())) {
- if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) == 0 &&
- strncmp(ctl->dst_tty_name, u->ut_line, sizeof(u->ut_line)) == 0) {
+ char user[sizeof(u->ut_user) + 1];
+ char line[sizeof(u->ut_line) + 1];
+
+ mem2strcpy(user, u->ut_user, sizeof(u->ut_user), sizeof(user));
+ mem2strcpy(line, u->ut_line, sizeof(u->ut_line), sizeof(line));
+
+ if (strcmp(ctl->dst_login, user) == 0 &&
+ strcmp(ctl->dst_tty_name, line) == 0) {
res = 0;
break;
}
@@ -269,23 +275,28 @@ static void search_utmp(struct write_control *ctl)
utmp:
#endif
{
+ char user[sizeof(u->ut_user) + 1];
+ char line[sizeof(u->ut_line) + 1];
char path[sizeof(u->ut_line) + 6];
utmpxname(_PATH_UTMP);
setutxent();
while ((u = getutxent())) {
- if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) != 0)
+ mem2strcpy(user, u->ut_user, sizeof(u->ut_user), sizeof(user));
+ mem2strcpy(line, u->ut_line, sizeof(u->ut_line), sizeof(line));
+
+ if (strcmp(ctl->dst_login, user) != 0)
continue;
num_ttys++;
- snprintf(path, sizeof(path), "/dev/%s", u->ut_line);
+ snprintf(path, sizeof(path), "/dev/%s", line);
if (check_tty(path, &tty_writeable, &tty_atime, 0))
/* bad term? skip */
continue;
if (ctl->src_uid && !tty_writeable)
/* skip ttys with msgs off */
continue;
- if (memcmp(u->ut_line, ctl->src_tty_name, strlen(ctl->src_tty_name) + 1) == 0) {
+ if (strcmp(line, ctl->src_tty_name) == 0) {
user_is_me = 1;
/* don't write to yourself */
continue;
--
2.52.0

View File

@ -146,6 +146,9 @@ Patch20: 0020-login-utils-fix-setpwnam-buffer-use-CVE-2025-14104.patch
###
# RHEL-148508 - sys-utils/lscpu: Change object type to SCOLS_JSON_STRING if data ==
Patch21: 0021-sys-utils-lscpu-Change-object-type-to-SCOLS_JSON_STR.patch
# RHEL-157244 - write: always use utmp as fallback
Patch22: 0022-write-always-use-utmp-as-fallback.patch
Patch23: 0023-write-use-mem2strcpy-for-utmp-strings.patch
%description