Add wrapper for write(2)
write(2) may not write the complete given buffer. Add a wrapper to avoid short writes.
This commit is contained in:
committed by
Serge Hallyn
parent
d63f3a0c0a
commit
969549fdf0
+2
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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",
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
+1
-37
@@ -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;
|
||||
|
||||
+3
-2
@@ -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.",
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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.",
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -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"),
|
||||
|
||||
+4
-4
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user