From eaebc33220b6cd81e1cb31d2b81244b6b15b8185 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 3 Nov 2025 21:59:34 +0100 Subject: [PATCH 1/3] fileio: mask off O_NOFOLLOW in xfopenat_regular() for fd_reopen() in a similar fashion as xopenat_full() --- src/basic/fileio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index a493384c52..a3860abefb 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1011,7 +1011,7 @@ static int xfopenat_regular(int dir_fd, const char *path, const char *mode, int assert(mode); assert(ret); - if (dir_fd == AT_FDCWD && open_flags == 0 && path) + if (dir_fd == AT_FDCWD && path && open_flags == 0) f = fopen(path, mode); else { _cleanup_close_ int fd = -EBADF; @@ -1029,7 +1029,7 @@ static int xfopenat_regular(int dir_fd, const char *path, const char *mode, int if (dir_fd == AT_FDCWD) return -EBADF; - fd = fd_reopen(dir_fd, mode_flags | open_flags); + fd = fd_reopen(dir_fd, (mode_flags | open_flags) & ~O_NOFOLLOW); if (fd < 0) return fd; } From 89b9a68e5fe56b863e01e6f39102d9ca0a54a88e Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 3 Nov 2025 22:06:53 +0100 Subject: [PATCH 2/3] sd-json: accept NULL path in sd_json_parse_file_at() too --- src/libsystemd/sd-json/sd-json.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index 776df25b8e..c2da6bca07 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -3453,10 +3453,8 @@ _public_ int sd_json_parse_file_at( if (f) r = read_full_stream(f, &text, NULL); - else if (path) - r = read_full_file_full(dir_fd, path, UINT64_MAX, SIZE_MAX, 0, NULL, &text, NULL); else - return -EINVAL; + r = read_full_file_full(dir_fd, path, UINT64_MAX, SIZE_MAX, 0, NULL, &text, NULL); if (r < 0) return r; From d98c783516edf0a108d1048387b15ebe5e9469f5 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 3 Nov 2025 22:16:46 +0100 Subject: [PATCH 3/3] sysupdated: port to sd_json_parse_file_at() --- src/sysupdate/sysupdated.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/sysupdate/sysupdated.c b/src/sysupdate/sysupdated.c index 1ade24b374..ac0e6f8e81 100644 --- a/src/sysupdate/sysupdated.c +++ b/src/sysupdate/sysupdated.c @@ -221,10 +221,8 @@ static int job_new(JobType type, Target *t, sd_bus_message *msg, JobComplete com } static int job_parse_child_output(int _fd, sd_json_variant **ret) { + _cleanup_close_ int fd = ASSERT_FD(_fd); /* Take ownership of the passed fd */ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; - /* Take ownership of the passed fd */ - _cleanup_close_ int fd = _fd; - _cleanup_fclose_ FILE *f = NULL; struct stat st; int r; @@ -240,16 +238,10 @@ static int job_parse_child_output(int _fd, sd_json_variant **ret) { return 0; } - if (lseek(fd, SEEK_SET, 0) == (off_t) -1) - return log_debug_errno(errno, "Failed to seek to beginning of memfd: %m"); - - f = take_fdopen(&fd, "r"); - if (!f) - return log_debug_errno(errno, "Failed to reopen memfd: %m"); - - r = sd_json_parse_file(f, "stdout", 0, &v, NULL, NULL); + r = sd_json_parse_file_at(/* f = */ NULL, fd, /* path = */ NULL, /* flags = */ 0, + &v, /* reterr_line = */ NULL, /* reterr_column = */ NULL); if (r < 0) - return log_debug_errno(r, "Failed to parse JSON: %m"); + return log_debug_errno(r, "Failed to parse child output as JSON: %m"); *ret = TAKE_PTR(v); return 0;