write: always use utmp as fallback, use mem2strcpy() for utmp strings
Resolves: RHEL-157244
This commit is contained in:
parent
c20fcabde0
commit
6d7cc5a29a
122
0022-write-always-use-utmp-as-fallback.patch
Normal file
122
0022-write-always-use-utmp-as-fallback.patch
Normal 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
|
||||
|
||||
74
0023-write-use-mem2strcpy-for-utmp-strings.patch
Normal file
74
0023-write-use-mem2strcpy-for-utmp-strings.patch
Normal 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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user