Merge pull request #31727 from YHNdnzj/homed-followup
data-fd-util: some cleanups
This commit is contained in:
@@ -1140,9 +1140,7 @@ int setenvf(const char *name, bool overwrite, const char *valuef, ...) {
|
||||
return RET_NERRNO(unsetenv(name));
|
||||
|
||||
va_start(ap, valuef);
|
||||
DISABLE_WARNING_FORMAT_NONLITERAL;
|
||||
r = vasprintf(&value, valuef, ap);
|
||||
REENABLE_WARNING;
|
||||
va_end(ap);
|
||||
|
||||
if (r < 0)
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
/* The maximum size of the file we'll read in one go in read_full_file() (64M). */
|
||||
#define READ_FULL_BYTES_MAX (64U*1024U*1024U - 1U)
|
||||
#define READ_FULL_BYTES_MAX (64U * U64_MB - UINT64_C(1))
|
||||
/* Used when a size is specified for read_full_file() with READ_FULL_FILE_UNBASE64 or _UNHEX */
|
||||
#define READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY 3
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
* exponentially in a loop. We use a size limit of 4M-2 because 4M-1 is the maximum buffer that /proc/sys/
|
||||
* allows us to read() (larger reads will fail with ENOMEM), and we want to read one extra byte so that we
|
||||
* can detect EOFs. */
|
||||
#define READ_VIRTUAL_BYTES_MAX (4U*1024U*1024U - 2U)
|
||||
#define READ_VIRTUAL_BYTES_MAX (4U * U64_MB - UINT64_C(2))
|
||||
|
||||
int fdopen_unlocked(int fd, const char *options, FILE **ret) {
|
||||
assert(ret);
|
||||
|
||||
@@ -1444,7 +1444,7 @@ static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *er
|
||||
static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
fd = acquire_data_fd(dump, strlen(dump), 0);
|
||||
fd = acquire_data_fd(dump);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
|
||||
@@ -410,7 +410,7 @@ static int setup_input(
|
||||
case EXEC_INPUT_DATA: {
|
||||
int fd;
|
||||
|
||||
fd = acquire_data_fd(context->stdin_data, context->stdin_data_size, 0);
|
||||
fd = acquire_data_fd_full(context->stdin_data, context->stdin_data_size, /* flags = */ 0);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
|
||||
@@ -1258,7 +1258,7 @@ static int home_start_work(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
stdin_fd = acquire_data_fd(formatted, strlen(formatted), 0);
|
||||
stdin_fd = acquire_data_fd(formatted);
|
||||
if (stdin_fd < 0)
|
||||
return stdin_fd;
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ int home_setup_cifs(
|
||||
pid_t mount_pid;
|
||||
int exit_status;
|
||||
|
||||
passwd_fd = acquire_data_fd(*pw, strlen(*pw), /* flags= */ 0);
|
||||
passwd_fd = acquire_data_fd(*pw);
|
||||
if (passwd_fd < 0)
|
||||
return log_error_errno(passwd_fd, "Failed to create data FD for password: %m");
|
||||
|
||||
@@ -94,7 +94,7 @@ int home_setup_cifs(
|
||||
|
||||
r = setenvf("PASSWD_FD", /* overwrite= */ true, "%d", passwd_fd);
|
||||
if (r < 0) {
|
||||
log_error_errno(errno, "Failed to set $PASSWD_FD: %m");
|
||||
log_error_errno(r, "Failed to set $PASSWD_FD: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ static int bus_method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fd = acquire_data_fd(dump, strlen(dump), 0);
|
||||
fd = acquire_data_fd(dump);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
|
||||
@@ -627,7 +627,7 @@ static int method_dump_memory_state_by_fd(sd_bus_message *message, void *userdat
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fd = acquire_data_fd(dump, dump_size, 0);
|
||||
fd = acquire_data_fd_full(dump, dump_size, /* flags = */ 0);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
|
||||
+20
-20
@@ -20,16 +20,15 @@
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */
|
||||
#define DATA_FD_MEMORY_LIMIT (64U*1024U)
|
||||
#define DATA_FD_MEMORY_LIMIT (64U * U64_KB)
|
||||
|
||||
/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */
|
||||
#define DATA_FD_TMP_LIMIT (1024U*1024U)
|
||||
#define DATA_FD_TMP_LIMIT (1U * U64_MB)
|
||||
|
||||
int acquire_data_fd(const void *data, size_t size, unsigned flags) {
|
||||
_cleanup_close_pair_ int pipefds[2] = EBADF_PAIR;
|
||||
int acquire_data_fd_full(const void *data, size_t size, DataFDFlags flags) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int isz = 0, r;
|
||||
ssize_t n;
|
||||
int r;
|
||||
|
||||
assert(data || size == 0);
|
||||
|
||||
@@ -52,24 +51,25 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags) {
|
||||
* It sucks a bit that depending on the situation we return very different objects here, but that's Linux I
|
||||
* figure. */
|
||||
|
||||
if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0))
|
||||
if (size == SIZE_MAX)
|
||||
size = strlen(data);
|
||||
|
||||
if (size == 0 && !FLAGS_SET(flags, ACQUIRE_NO_DEV_NULL))
|
||||
/* As a special case, return /dev/null if we have been called for an empty data block */
|
||||
return RET_NERRNO(open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY));
|
||||
|
||||
if ((flags & ACQUIRE_NO_MEMFD) == 0) {
|
||||
if (!FLAGS_SET(flags, ACQUIRE_NO_MEMFD)) {
|
||||
fd = memfd_new_and_seal("data-fd", data, size);
|
||||
if (fd < 0) {
|
||||
if (ERRNO_IS_NOT_SUPPORTED(fd))
|
||||
goto try_pipe;
|
||||
|
||||
if (fd < 0 && !ERRNO_IS_NOT_SUPPORTED(fd))
|
||||
return fd;
|
||||
}
|
||||
|
||||
return TAKE_FD(fd);
|
||||
if (fd >= 0)
|
||||
return TAKE_FD(fd);
|
||||
}
|
||||
|
||||
try_pipe:
|
||||
if ((flags & ACQUIRE_NO_PIPE) == 0) {
|
||||
if (!FLAGS_SET(flags, ACQUIRE_NO_PIPE)) {
|
||||
_cleanup_close_pair_ int pipefds[2] = EBADF_PAIR;
|
||||
int isz;
|
||||
|
||||
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||
return -errno;
|
||||
|
||||
@@ -106,7 +106,7 @@ try_pipe:
|
||||
}
|
||||
|
||||
try_dev_shm:
|
||||
if ((flags & ACQUIRE_NO_TMPFILE) == 0) {
|
||||
if (!FLAGS_SET(flags, ACQUIRE_NO_TMPFILE)) {
|
||||
fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500);
|
||||
if (fd < 0)
|
||||
goto try_dev_shm_without_o_tmpfile;
|
||||
@@ -122,7 +122,7 @@ try_dev_shm:
|
||||
}
|
||||
|
||||
try_dev_shm_without_o_tmpfile:
|
||||
if ((flags & ACQUIRE_NO_REGULAR) == 0) {
|
||||
if (!FLAGS_SET(flags, ACQUIRE_NO_REGULAR)) {
|
||||
char pattern[] = "/dev/shm/data-fd-XXXXXX";
|
||||
|
||||
fd = mkostemp_safe(pattern);
|
||||
@@ -179,7 +179,7 @@ int copy_data_fd(int fd) {
|
||||
* that we use the reported regular file size only as a hint, given that there are plenty special files in
|
||||
* /proc and /sys which report a zero file size but can be read from. */
|
||||
|
||||
if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) {
|
||||
if (!S_ISREG(st.st_mode) || (uint64_t) st.st_size < DATA_FD_MEMORY_LIMIT) {
|
||||
|
||||
/* Try a memfd first */
|
||||
copy_fd = memfd_new("data-fd");
|
||||
@@ -252,7 +252,7 @@ int copy_data_fd(int fd) {
|
||||
}
|
||||
|
||||
/* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */
|
||||
if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) &&
|
||||
if ((!S_ISREG(st.st_mode) || (uint64_t) st.st_size < DATA_FD_TMP_LIMIT) &&
|
||||
(DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) {
|
||||
off_t f;
|
||||
|
||||
|
||||
@@ -2,15 +2,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
typedef enum DataFDFlags {
|
||||
ACQUIRE_NO_DEV_NULL = 1 << 0,
|
||||
ACQUIRE_NO_MEMFD = 1 << 1,
|
||||
ACQUIRE_NO_PIPE = 1 << 2,
|
||||
ACQUIRE_NO_TMPFILE = 1 << 3,
|
||||
ACQUIRE_NO_REGULAR = 1 << 4,
|
||||
};
|
||||
} DataFDFlags;
|
||||
|
||||
int acquire_data_fd_full(const void *data, size_t size, DataFDFlags flags);
|
||||
static inline int acquire_data_fd(const void *data) {
|
||||
return acquire_data_fd_full(data, SIZE_MAX, 0);
|
||||
}
|
||||
|
||||
int acquire_data_fd(const void *data, size_t size, unsigned flags);
|
||||
int copy_data_fd(int fd);
|
||||
int memfd_clone_fd(int fd, const char *name, int mode);
|
||||
|
||||
@@ -17,7 +17,7 @@ static void test_acquire_data_fd_one(unsigned flags) {
|
||||
char rbuffer[sizeof(wbuffer)];
|
||||
int fd;
|
||||
|
||||
fd = acquire_data_fd("foo", 3, flags);
|
||||
fd = acquire_data_fd_full("foo", 3, flags);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
zero(rbuffer);
|
||||
@@ -26,7 +26,7 @@ static void test_acquire_data_fd_one(unsigned flags) {
|
||||
|
||||
fd = safe_close(fd);
|
||||
|
||||
fd = acquire_data_fd("", 0, flags);
|
||||
fd = acquire_data_fd_full("", SIZE_MAX, flags);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
zero(rbuffer);
|
||||
@@ -37,7 +37,7 @@ static void test_acquire_data_fd_one(unsigned flags) {
|
||||
|
||||
random_bytes(wbuffer, sizeof(wbuffer));
|
||||
|
||||
fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags);
|
||||
fd = acquire_data_fd_full(wbuffer, sizeof(wbuffer), flags);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
zero(rbuffer);
|
||||
@@ -98,14 +98,14 @@ TEST(copy_data_fd) {
|
||||
fd1 = safe_close(fd1);
|
||||
fd2 = safe_close(fd2);
|
||||
|
||||
fd1 = acquire_data_fd("hallo", 6, 0);
|
||||
fd1 = acquire_data_fd("hallo");
|
||||
assert_se(fd1 >= 0);
|
||||
|
||||
fd2 = copy_data_fd(fd1);
|
||||
assert_se(fd2 >= 0);
|
||||
|
||||
safe_close(fd1);
|
||||
fd1 = acquire_data_fd("hallo", 6, 0);
|
||||
fd1 = acquire_data_fd("hallo");
|
||||
assert_se(fd1 >= 0);
|
||||
|
||||
assert_equal_fd(fd1, fd2);
|
||||
|
||||
@@ -170,7 +170,7 @@ TEST(rearrange_stdio) {
|
||||
assert_se(fd_move_above_stdio(0) == 3);
|
||||
}
|
||||
assert_se(open("/dev/full", O_WRONLY|O_CLOEXEC) == 0);
|
||||
assert_se(acquire_data_fd("foobar", 6, 0) == 2);
|
||||
assert_se(acquire_data_fd("foobar") == 2);
|
||||
|
||||
assert_se(rearrange_stdio(2, 0, 1) >= 0);
|
||||
|
||||
|
||||
@@ -123,8 +123,8 @@ static int method_passfd(Varlink *link, JsonVariant *parameters, VarlinkMethodFl
|
||||
test_fd(yy, "bar", 3);
|
||||
test_fd(zz, "quux", 4);
|
||||
|
||||
_cleanup_close_ int vv = acquire_data_fd("miau", 4, 0);
|
||||
_cleanup_close_ int ww = acquire_data_fd("wuff", 4, 0);
|
||||
_cleanup_close_ int vv = acquire_data_fd("miau");
|
||||
_cleanup_close_ int ww = acquire_data_fd("wuff");
|
||||
|
||||
assert_se(vv >= 0);
|
||||
assert_se(ww >= 0);
|
||||
@@ -275,9 +275,9 @@ static void *thread(void *arg) {
|
||||
assert_se(json_variant_integer(json_variant_by_key(o, "sum")) == 88 + 99);
|
||||
assert_se(!e);
|
||||
|
||||
int fd1 = acquire_data_fd("foo", 3, 0);
|
||||
int fd2 = acquire_data_fd("bar", 3, 0);
|
||||
int fd3 = acquire_data_fd("quux", 4, 0);
|
||||
int fd1 = acquire_data_fd("foo");
|
||||
int fd2 = acquire_data_fd("bar");
|
||||
int fd3 = acquire_data_fd("quux");
|
||||
|
||||
assert_se(fd1 >= 0);
|
||||
assert_se(fd2 >= 0);
|
||||
|
||||
Reference in New Issue
Block a user