]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
Add wrapper for write(2)
authorChristian Göttsche <cgzones@googlemail.com>
Tue, 28 Feb 2023 15:35:05 +0000 (16:35 +0100)
committerSerge Hallyn <serge@hallyn.com>
Fri, 4 Aug 2023 22:15:42 +0000 (17:15 -0500)
write(2) may not write the complete given buffer.  Add a wrapper to
avoid short writes.

13 files changed:
lib/Makefile.am
lib/commonio.c
lib/prototypes.h
lib/write_full.c [new file with mode: 0644]
libmisc/copydir.c
libmisc/failure.c
libmisc/idmapping.c
libmisc/log.c
libmisc/utmp.c
src/login.c
src/su.c
src/useradd.c
src/usermod.c

index 5d76205cff8fb7beb52b5c23656c55c0ed431c14..c8d6dd5fbb90fc4867bfee7f061c7cd3cfd44b3b 100644 (file)
@@ -66,7 +66,8 @@ libshadow_la_SOURCES = \
        shadowio.c \
        shadowio.h \
        shadowmem.c \
-       spawn.c
+       spawn.c \
+       write_full.c
 
 if WITH_TCB
 libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h
index 0e66c8ddaaddedaba7451b6715983a9c996f5766..73fdb3a16aa7c74d3b64b39a089ecbe19709271a 100644 (file)
@@ -140,7 +140,7 @@ static int do_lock_file (const char *file, const char *lock, bool log)
        pid = getpid ();
        snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
        len = (ssize_t) strlen (buf) + 1;
-       if (write (fd, buf, (size_t) len) != len) {
+       if (write_full (fd, buf, (size_t) len) != len) {
                if (log) {
                        (void) fprintf (shadow_logfd,
                                        "%s: %s file write error: %s\n",
index a1338341077102ede0bc1d20d86e696261c09b3d..d20abf3e39e1e7971f7b5b9dfc33f11d7525167b 100644 (file)
@@ -526,6 +526,9 @@ extern unsigned long active_sessions_count(const char *name,
 /* valid.c */
 extern bool valid (const char *, const struct passwd *);
 
+/* write_full.c */
+extern ssize_t write_full(int fd, const void *buf, size_t count);
+
 /* xgetpwnam.c */
 extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *);
 /* xprefix_getpwnam.c */
diff --git a/lib/write_full.c b/lib/write_full.c
new file mode 100644 (file)
index 0000000..cde52fb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * SPDX-FileCopyrightText:  2023, Christian Göttsche <cgzones@googlemail.com>
+ *
+ * SPDX-License-Identifier:  BSD-3-Clause
+ */
+
+
+#include <config.h>
+
+#ident "$Id$"
+
+#include "prototypes.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+
+/*
+ * write_full - write entire buffer
+ *
+ * Write up to count bytes from the buffer starting at buf to the
+ * file referred to by the file descriptor fd.
+ * Retry in case of a short write.
+ *
+ * Returns the number of bytes written on success, -1 on error.
+ */
+ssize_t write_full(int fd, const void *buf, size_t count) {
+       ssize_t written = 0;
+
+       while (count > 0) {
+               ssize_t res;
+
+               res = write(fd, buf, count);
+               if (res < 0) {
+                       if (errno == EINTR) {
+                               continue;
+                       }
+
+                       return res;
+               }
+
+               if (res == 0) {
+                       break;
+               }
+
+               written += res;
+               buf = (const unsigned char*)buf + res;
+               count -= res;
+       }
+
+       return written;
+}
index d04ddc59999a0e366807493be758524e4fa36945..cc1a30d29707563bf21f5c49cb7d75d9e41e7939 100644 (file)
@@ -740,42 +740,6 @@ static int copy_special (const struct path_info *src, const struct path_info *ds
        return err;
 }
 
-/*
- * full_write - write entire buffer
- *
- * Write up to count bytes from the buffer starting at buf to the
- * file referred to by the file descriptor fd.
- * Retry in case of a short write.
- *
- * Returns the number of bytes written on success, -1 on error.
- */
-static ssize_t full_write(int fd, const void *buf, size_t count) {
-       ssize_t written = 0;
-
-       while (count > 0) {
-               ssize_t res;
-
-               res = write(fd, buf, count);
-               if (res < 0) {
-                       if (errno == EINTR) {
-                               continue;
-                       }
-
-                       return res;
-               }
-
-               if (res == 0) {
-                       break;
-               }
-
-               written += res;
-               buf = (const unsigned char*)buf + res;
-               count -= res;
-       }
-
-       return written;
-}
-
 /*
  * copy_file - copy a file
  *
@@ -852,7 +816,7 @@ static int copy_file (const struct path_info *src, const struct path_info *dst,
                        break;
                }
 
-               if (full_write (ofd, buf, cnt) < 0) {
+               if (write_full (ofd, buf, cnt) < 0) {
                        (void) close (ofd);
                        (void) close (ifd);
                        return -1;
index df8614a24191f13f406110cecf750c2d1ce3174b..6fc575c12336c2844abdf038c21f6b94e08b4901 100644 (file)
@@ -17,6 +17,7 @@
 #include "defines.h"
 #include "faillog.h"
 #include "failure.h"
+#include "prototypes.h"
 #define        YEAR    (365L*DAY)
 /*
  * failure - make failure entry
@@ -85,7 +86,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
         */
 
        if (   (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
-           || (write (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)
+           || (write_full (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)
            || (close (fd) != 0)) {
                SYSLOG ((LOG_WARN,
                         "Can't write faillog entry for UID %lu in %s.",
@@ -184,7 +185,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
                fail.fail_cnt = 0;
 
                if (   (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
-                   || (write (fd, &fail, sizeof fail) != (ssize_t) sizeof fail)
+                   || (write_full (fd, &fail, sizeof fail) != (ssize_t) sizeof fail)
                    || (close (fd) != 0)) {
                        SYSLOG ((LOG_WARN,
                                 "Can't reset faillog entry for UID %lu in %s.",
index 46bb814d5df107a2b4d7126f503271f1365ffafc..ae8c4b93a7064e0d8434a217d8817a988ba89dd5 100644 (file)
@@ -215,7 +215,7 @@ void write_mapping(int proc_dir_fd, int ranges, const struct map_range *mappings
                        log_get_progname(), map_file, strerror(errno));
                exit(EXIT_FAILURE);
        }
-       if (write(fd, buf, pos - buf) != (pos - buf)) {
+       if (write_full(fd, buf, pos - buf) != (pos - buf)) {
                fprintf(log_get_logfd(), _("%s: write to %s failed: %s\n"),
                        log_get_progname(), map_file, strerror(errno));
                exit(EXIT_FAILURE);
index ab94f330cc7b958ab0fc986958739767c0619ae0..cc38d6dc5fbe506520c769fca2c7e8f42a9026e8 100644 (file)
@@ -82,7 +82,7 @@ void dolastlog (
        strncpy (newlog.ll_host, host, sizeof (newlog.ll_host) - 1);
 #endif
        if (   (lseek (fd, offset, SEEK_SET) != offset)
-           || (write (fd, &newlog, sizeof newlog) != (ssize_t) sizeof newlog)
+           || (write_full (fd, &newlog, sizeof newlog) != (ssize_t) sizeof newlog)
            || (close (fd) != 0)) {
                SYSLOG ((LOG_WARN,
                         "Can't write lastlog entry for UID %lu in %s.",
index e5e79cffcf2eee5ddb57baafa06b536e7971bceb..7c7da6971ab5c884579ebb039ae5f844cae88746 100644 (file)
@@ -97,7 +97,7 @@ static void failtmp (const char *username, const struct utmp *failent)
         * Append the new failure record and close the log file.
         */
 
-       if (   (write (fd, failent, sizeof *failent) != (ssize_t) sizeof *failent)
+       if (   (write_full (fd, failent, sizeof *failent) != (ssize_t) sizeof *failent)
            || (close (fd) != 0)) {
                SYSLOG ((LOG_WARN,
                         "Can't append failure of user %s to %s.",
@@ -194,7 +194,7 @@ static void updwtmp (const char *filename, const struct utmp *ut)
 
        fd = open (filename, O_APPEND | O_WRONLY, 0);
        if (fd >= 0) {
-               write (fd, ut, sizeof (*ut));
+               write_full (fd, ut, sizeof (*ut));
                close (fd);
        }
 }
index b712cf445e806eef20acec42fead92c6685e1a8d..b5562923a12734b627a34b9c1461e6a680b61c07 100644 (file)
@@ -400,7 +400,7 @@ static void exit_handler (unused int sig)
 
 static void alarm_handler (unused int sig)
 {
-       write (STDERR_FILENO, tmsg, strlen (tmsg));
+       write_full (STDERR_FILENO, tmsg, strlen (tmsg));
        signal(SIGALRM, exit_handler);
        alarm(2);
 }
index 628ef4e4c4a475f739305f663b0decb7205ef692..84b9246892c32cc71b38703119200f2db404c051 100644 (file)
--- a/src/su.c
+++ b/src/su.c
@@ -164,9 +164,9 @@ static void kill_child (int unused(s))
 {
        if (0 != pid_child) {
                (void) kill (-pid_child, SIGKILL);
-               (void) write (STDERR_FILENO, kill_msg, strlen (kill_msg));
+               (void) write_full (STDERR_FILENO, kill_msg, strlen (kill_msg));
        } else {
-               (void) write (STDERR_FILENO, wait_msg, strlen (wait_msg));
+               (void) write_full (STDERR_FILENO, wait_msg, strlen (wait_msg));
        }
        _exit (255);
 }
index d6766426be5e340d00eb8e0ab93f45d7382e26ad..5b601e01823fe2b8bfbe8576cc7402a5dd2db3fa 100644 (file)
@@ -2067,7 +2067,7 @@ static void faillog_reset (uid_t uid)
                return;
        }
        if (   (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
-           || (write (fd, &fl, sizeof (fl)) != (ssize_t) sizeof (fl))
+           || (write_full (fd, &fl, sizeof (fl)) != (ssize_t) sizeof (fl))
            || (fsync (fd) != 0)) {
                fprintf (stderr,
                         _("%s: failed to reset the faillog entry of UID %lu: %s\n"),
@@ -2112,7 +2112,7 @@ static void lastlog_reset (uid_t uid)
                return;
        }
        if (   (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
-           || (write (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll))
+           || (write_full (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll))
            || (fsync (fd) != 0)) {
                fprintf (stderr,
                         _("%s: failed to reset the lastlog entry of UID %lu: %s\n"),
index bf01881ac912f3993d0a339a4cc0cba3c4f04acb..9e8968025b4deefbc3a936bb99f2b605beac5256 100644 (file)
@@ -1941,7 +1941,7 @@ static void update_lastlog (void)
            && (read (fd, &ll, sizeof ll) == (ssize_t) sizeof ll)) {
                /* Copy the old entry to its new location */
                if (   (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
-                   || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
+                   || (write_full (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
                    || (fsync (fd) != 0)) {
                        fprintf (stderr,
                                 _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
@@ -1957,7 +1957,7 @@ static void update_lastlog (void)
                        /* Reset the new uid's lastlog entry */
                        memzero (&ll, sizeof (ll));
                        if (   (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
-                           || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
+                           || (write_full (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
                            || (fsync (fd) != 0)) {
                                fprintf (stderr,
                                         _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
@@ -2001,7 +2001,7 @@ static void update_faillog (void)
            && (read (fd, &fl, sizeof fl) == (ssize_t) sizeof fl)) {
                /* Copy the old entry to its new location */
                if (   (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
-                   || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)
+                   || (write_full (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)
                    || (fsync (fd) != 0)) {
                        fprintf (stderr,
                                 _("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"),
@@ -2017,7 +2017,7 @@ static void update_faillog (void)
                        /* Reset the new uid's faillog entry */
                        memzero (&fl, sizeof (fl));
                        if (   (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
-                           || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)) {
+                           || (write_full (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)) {
                                fprintf (stderr,
                                         _("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"),
                                         Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno));