Skip to content

Commit

Permalink
Merge pull request #1656 from giuseppe/safe-partial-writes
Browse files Browse the repository at this point in the history
utils: fix partial writes with write_file_at_with_flags
  • Loading branch information
giuseppe authored Feb 3, 2025
2 parents 7a53b08 + f1ef3bb commit 73d52bd
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 27 deletions.
1 change: 0 additions & 1 deletion src/libcrun/handlers/krun.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,6 @@ static int
libkrun_load (void **cookie, libcrun_error_t *err)
{
struct krun_config *kconf;
void *handle;
const char *libkrun_so = "libkrun.so.1";
const char *libkrun_sev_so = "libkrun-sev.so.1";

Expand Down
31 changes: 9 additions & 22 deletions src/libcrun/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,37 +121,24 @@ xasprintf (char **str, const char *fmt, ...)
int
write_file_at_with_flags (int dirfd, int flags, mode_t mode, const char *name, const void *data, size_t len, libcrun_error_t *err)
{
cleanup_close int fd = openat (dirfd, name, O_CLOEXEC | O_WRONLY | flags, mode);
cleanup_close int fd = -1;
size_t remaining;
int ret = 0;

fd = openat (dirfd, name, O_CLOEXEC | O_WRONLY | flags, mode);
if (UNLIKELY (fd < 0))
return crun_make_error (err, errno, "opening file `%s` for writing", name);

if (len)
for (remaining = len; remaining > 0;)
{
ret = TEMP_FAILURE_RETRY (write (fd, data, len));
ret = TEMP_FAILURE_RETRY (write (fd, data + len - remaining, remaining));
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "writing file `%s`", name);
}

return ret;
}

int
write_file_at (int dirfd, const char *name, const void *data, size_t len, libcrun_error_t *err)
{
return write_file_at_with_flags (dirfd, O_CLOEXEC | O_CREAT | O_TRUNC, 0700, name, data, len, err);
}

int
write_file_with_flags (const char *name, int flags, const void *data, size_t len, libcrun_error_t *err)
{
return write_file_at_with_flags (AT_FDCWD, flags, 0700, name, data, len, err);
}
remaining -= (size_t) ret;
}

int
write_file (const char *name, const void *data, size_t len, libcrun_error_t *err)
{
return write_file_with_flags (name, O_CREAT | O_TRUNC, data, len, err);
return (len > INT_MAX) ? INT_MAX : (int) len;
}

int
Expand Down
23 changes: 19 additions & 4 deletions src/libcrun/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <dirent.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <ocispec/runtime_spec_schema_config_schema.h>
#include <sys/wait.h>
#include "container.h"
Expand Down Expand Up @@ -55,6 +56,8 @@
#define LIKELY(x) __builtin_expect ((x), 1)
#define UNLIKELY(x) __builtin_expect ((x), 0)

#define WRITE_FILE_DEFAULT_FLAGS (O_CLOEXEC | O_CREAT | O_TRUNC)

__attribute__ ((malloc)) static inline void *
xmalloc (size_t size)
{
Expand Down Expand Up @@ -257,13 +260,25 @@ int xasprintf (char **str, const char *fmt, ...) __attribute__ ((format (printf,

int crun_path_exists (const char *path, libcrun_error_t *err);

int write_file_with_flags (const char *name, int flags, const void *data, size_t len, libcrun_error_t *err);
int write_file_at_with_flags (int dirfd, int flags, mode_t mode, const char *name, const void *data, size_t len, libcrun_error_t *err);

int write_file (const char *name, const void *data, size_t len, libcrun_error_t *err);
static inline int
write_file_with_flags (const char *name, int flags, const void *data, size_t len, libcrun_error_t *err)
{
return write_file_at_with_flags (AT_FDCWD, flags, 0700, name, data, len, err);
}

int write_file_at (int dirfd, const char *name, const void *data, size_t len, libcrun_error_t *err);
static inline int
write_file (const char *name, const void *data, size_t len, libcrun_error_t *err)
{
return write_file_with_flags (name, WRITE_FILE_DEFAULT_FLAGS, data, len, err);
}

int write_file_at_with_flags (int dirfd, int flags, mode_t mode, const char *name, const void *data, size_t len, libcrun_error_t *err);
static inline int
write_file_at (int dirfd, const char *name, const void *data, size_t len, libcrun_error_t *err)
{
return write_file_at_with_flags (dirfd, WRITE_FILE_DEFAULT_FLAGS, 0700, name, data, len, err);
}

int crun_ensure_directory (const char *path, int mode, bool nofollow, libcrun_error_t *err);

Expand Down

0 comments on commit 73d52bd

Please sign in to comment.