tree-wide: use pwrite_full() for positioned writes
Several places write a buffer at an offset with a single pwrite() or pwritev(), and fail if the call writes less than the whole buffer. The lock file of a dynamic user is then truncated to the bytes written, so it keeps a cut-off user name. memfd_new_and_seal() fails for data larger than one write() call accepts, which is about 2 GiB on Linux. The other callers return -EIO, and lose the error that another write would report, such as ENOSPC. Use pwrite_full(), which keeps writing until the whole buffer is written or a write fails. The lock file of a dynamic user is written from two buffers and uses pwritev_full() instead. repart writes the verity signature with lseek() and loop_write(). It uses pwrite_full() as well, which does not move the file offset. (cherry picked from commit 2fd17cb9eaca00a4dcb9af85a1f485e6d04bda04)
This commit is contained in:
committed by
Luca Boccassi
parent
8b9fb1bbec
commit
ef565d78af
@@ -7,6 +7,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "io-util.h"
|
||||
#include "memfd-util.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
@@ -132,11 +133,9 @@ int memfd_new_and_seal(const char *name, const void *data, size_t sz) {
|
||||
return fd;
|
||||
|
||||
if (sz > 0) {
|
||||
ssize_t n = pwrite(fd, data, sz, 0);
|
||||
if (n < 0)
|
||||
return -errno;
|
||||
if ((size_t) n != sz)
|
||||
return -EIO;
|
||||
r = pwrite_full(fd, data, sz, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = memfd_set_sealed(fd);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "fileio.h"
|
||||
#include "format-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "io-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "lock-util.h"
|
||||
#include "manager.h"
|
||||
@@ -186,7 +187,7 @@ static int pick_uid(char **suggested_paths, const char *name, uid_t *ret_uid) {
|
||||
char lock_path[STRLEN("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1];
|
||||
_cleanup_close_ int lock_fd = -EBADF;
|
||||
uid_t candidate;
|
||||
ssize_t l;
|
||||
uint64_t written;
|
||||
|
||||
if (--n_tries <= 0) /* Give up retrying eventually */
|
||||
return -EBUSY;
|
||||
@@ -268,18 +269,17 @@ static int pick_uid(char **suggested_paths, const char *name, uid_t *ret_uid) {
|
||||
}
|
||||
|
||||
/* Let's store the user name in the lock file, so that we can use it for looking up the username for a UID */
|
||||
l = pwritev(lock_fd,
|
||||
(struct iovec[2]) {
|
||||
IOVEC_MAKE_STRING(name),
|
||||
IOVEC_MAKE((char[1]) { '\n' }, 1),
|
||||
}, 2, 0);
|
||||
if (l < 0) {
|
||||
r = -errno;
|
||||
r = pwritev_full(lock_fd,
|
||||
(struct iovec[2]) {
|
||||
IOVEC_MAKE_STRING(name),
|
||||
IOVEC_MAKE((char[1]) { '\n' }, 1),
|
||||
}, 2, 0, &written);
|
||||
if (r < 0) {
|
||||
(void) unlink(lock_path);
|
||||
return r;
|
||||
}
|
||||
|
||||
(void) ftruncate(lock_fd, l);
|
||||
(void) ftruncate(lock_fd, written);
|
||||
|
||||
*ret_uid = candidate;
|
||||
return TAKE_FD(lock_fd);
|
||||
|
||||
+7
-10
@@ -5,6 +5,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "compress.h"
|
||||
#include "copy.h"
|
||||
#include "io-util.h"
|
||||
#include "qcow2-util.h"
|
||||
#include "sparse-endian.h"
|
||||
|
||||
@@ -80,11 +81,9 @@ static int copy_cluster(
|
||||
if ((uint64_t) l != cluster_size)
|
||||
return -EIO;
|
||||
|
||||
l = pwrite(dfd, buffer, cluster_size, doffset);
|
||||
if (l < 0)
|
||||
return -errno;
|
||||
if ((uint64_t) l != cluster_size)
|
||||
return -EIO;
|
||||
r = pwrite_full(dfd, buffer, cluster_size, doffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -122,11 +121,9 @@ static int decompress_cluster(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
l = pwrite(dfd, buffer2, cluster_size, doffset);
|
||||
if (l < 0)
|
||||
return -errno;
|
||||
if ((uint64_t) l != cluster_size)
|
||||
return -EIO;
|
||||
r = pwrite_full(dfd, buffer2, cluster_size, doffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "id128-util.h"
|
||||
#include "io-util.h"
|
||||
#include "journal-authenticate-internal.h"
|
||||
#include "journal-def.h"
|
||||
#include "journal-file.h"
|
||||
@@ -392,7 +393,6 @@ static int journal_file_init_header(
|
||||
JournalFileFlags file_flags,
|
||||
JournalFile *template) {
|
||||
|
||||
ssize_t k;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
@@ -429,13 +429,7 @@ static int journal_file_init_header(
|
||||
} else
|
||||
h.seqnum_id = h.file_id;
|
||||
|
||||
k = pwrite(f->fd, &h, sizeof(h), 0);
|
||||
if (k < 0)
|
||||
return -errno;
|
||||
if (k != sizeof(h))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
return pwrite_full(f->fd, &h, sizeof(h), 0);
|
||||
}
|
||||
|
||||
static int journal_file_refresh_header(JournalFile *f) {
|
||||
|
||||
+22
-29
@@ -6311,10 +6311,7 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to pad string to %s", FORMAT_BYTES(p->new_size));
|
||||
|
||||
if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
|
||||
return log_error_errno(errno, "Failed to seek to partition %s offset: %m", strna(hint));
|
||||
|
||||
r = loop_write(whole_fd, text, p->new_size);
|
||||
r = pwrite_full(whole_fd, text, p->new_size, p->offset);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write verity signature to partition %s: %m", strna(hint));
|
||||
|
||||
@@ -8383,16 +8380,16 @@ static int write_primary_descriptor(
|
||||
iso9660_datetime_zero(&desc.volume_expiration_date);
|
||||
iso9660_datetime_zero(&desc.volume_effective_date);
|
||||
|
||||
ssize_t s = pwrite(fd, &desc, sizeof(desc), ISO9660_PRIMARY_DESCRIPTOR*ISO9660_BLOCK_SIZE);
|
||||
if (s < 0)
|
||||
return log_error_errno(errno, "Failed to write ISO9660 primary descriptor: %m");
|
||||
if (s != sizeof(desc))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to fully write ISO9660 primary descriptor");
|
||||
r = pwrite_full(fd, &desc, sizeof(desc), ISO9660_PRIMARY_DESCRIPTOR*ISO9660_BLOCK_SIZE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write ISO9660 primary descriptor: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_eltorito_descriptor(int fd, uint32_t catalog_sector) {
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
struct iso9660_eltorito_descriptor desc = {
|
||||
@@ -8407,16 +8404,16 @@ static int write_eltorito_descriptor(int fd, uint32_t catalog_sector) {
|
||||
|
||||
strncpy(desc.boot_system_identifier, "EL TORITO SPECIFICATION", sizeof(desc.boot_system_identifier));
|
||||
|
||||
ssize_t s = pwrite(fd, &desc, sizeof(desc), ISO9660_ELTORITO_DESCRIPTOR*ISO9660_BLOCK_SIZE);
|
||||
if (s < 0)
|
||||
return log_error_errno(errno, "Failed to write ISO9660 El-Torito descriptor: %m");
|
||||
if (s != sizeof(desc))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to fully write ISO9660 El-Torito descriptor");
|
||||
r = pwrite_full(fd, &desc, sizeof(desc), ISO9660_ELTORITO_DESCRIPTOR*ISO9660_BLOCK_SIZE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write ISO9660 El-Torito descriptor: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_terminal_descriptor(int fd) {
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
struct iso9660_terminal_descriptor desc = {
|
||||
@@ -8428,11 +8425,9 @@ static int write_terminal_descriptor(int fd) {
|
||||
|
||||
iso9660_set_const_string(desc.header.identifier, sizeof(desc.header.identifier), "CD001", /* allow_a_chars= */ true);
|
||||
|
||||
ssize_t s = pwrite(fd, &desc, sizeof(desc), ISO9660_TERMINAL_DESCRIPTOR*ISO9660_BLOCK_SIZE);
|
||||
if (s < 0)
|
||||
return log_error_errno(errno, "Failed to write ISO9660 terminal descriptor: %m");
|
||||
if (s != sizeof(desc))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to fully write ISO9660 terminal descriptor");
|
||||
r = pwrite_full(fd, &desc, sizeof(desc), ISO9660_TERMINAL_DESCRIPTOR*ISO9660_BLOCK_SIZE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write ISO9660 terminal descriptor: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -8450,6 +8445,8 @@ static uint16_t calculate_validation_entry_checksum(const void *p, size_t size)
|
||||
}
|
||||
|
||||
static int write_boot_catalog(int fd, uint32_t load_block) {
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
struct el_torito_validation_entry ve = {
|
||||
@@ -8485,11 +8482,9 @@ static int write_boot_catalog(int fd, uint32_t load_block) {
|
||||
p = mempcpy(p, &sh, sizeof(sh));
|
||||
assert((size_t) (p - sector) <= sizeof(sector));
|
||||
|
||||
ssize_t s = pwrite(fd, §or, sizeof(sector), ISO9660_BOOT_CATALOG*ISO9660_BLOCK_SIZE);
|
||||
if (s < 0)
|
||||
return log_error_errno(errno, "Failed to write El-Torito boot catalog: %m");
|
||||
if (s != sizeof(sector))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to fully write El-Torito boot catalog");
|
||||
r = pwrite_full(fd, §or, sizeof(sector), ISO9660_BOOT_CATALOG*ISO9660_BLOCK_SIZE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write El-Torito boot catalog: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -8548,11 +8543,9 @@ static int write_directories(
|
||||
p = mempcpy(p, &parent, sizeof(parent));
|
||||
assert((size_t) (p - sector) <= sizeof(sector));
|
||||
|
||||
ssize_t s = pwrite(fd, §or, sizeof(sector), ISO9660_ROOT_DIRECTORY*ISO9660_BLOCK_SIZE);
|
||||
if (s < 0)
|
||||
return log_error_errno(errno, "Failed to write ISO9660 root directory: %m");
|
||||
if (s != sizeof(sector))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to fully write ISO9660 root directory");
|
||||
r = pwrite_full(fd, §or, sizeof(sector), ISO9660_ROOT_DIRECTORY*ISO9660_BLOCK_SIZE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write ISO9660 root directory: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user