]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
write: use mem2strcpy() for utmp strings
authorKarel Zak <kzak@redhat.com>
Wed, 13 May 2026 09:22:59 +0000 (11:22 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 13 May 2026 09:22:59 +0000 (11:22 +0200)
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>
term-utils/write.c

index c7c6ba4970b35e87bdcdf6f089a7ba8f01cd1e00..e08a5d5fca1e2df190b316b7d5b325239c5ed868 100644 (file)
@@ -183,8 +183,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;
                }
@@ -274,23 +280,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;