From 1d4ef93a75bc51ae49b7effd934548105da3ccaf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Jun 2026 17:03:19 +1000 Subject: [PATCH] util1: set_times_at() + make_path parent chain via do_mkdir_at() set_times_at() is the held-dirfd form of set_times() (utimensat tier; returns -2 where the active tier has no dfd form so the caller falls back). make_path() now creates its parent chain through do_mkdir_at(), which resolves the parent via the secure resolver, closing the --relative implied-parent symlink escape once the gate covers the receiver. (cherry picked from commit 5ccb76b08b5fec9aac88772a192478231b4b159a) --- util1.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/util1.c b/util1.c index 7a1f24b5..70a247ca 100644 --- a/util1.c +++ b/util1.c @@ -180,6 +180,25 @@ int set_times(const char *fname, STRUCT_STAT *stp) return 0; } +/* Held-dirfd variant of set_times(): set `name`'s times relative to dir fd + * `dfd`. Returns 0/-1 like set_times(), or -2 when this platform's active + * time-setting tier has no dfd-relative form (caller falls back to + * set_times(fname, stp)). Only the utimensat tier has an at-on-dfd form. */ +int set_times_at(int dfd, const char *name, STRUCT_STAT *stp) +{ +#if defined HAVE_UTIMENSAT && !defined HAVE_SETATTRLIST + int r = do_utimensat_atfd(dfd, name, stp); + if (r == 0) + return 0; + if (errno == ENOSYS) + return -2; + return -1; +#else + (void)dfd; (void)name; (void)stp; + return -2; +#endif +} + /* Create any necessary directories in fname. Any missing directories are * created with default permissions. Returns < 0 on error, or the number * of directories created. */ @@ -214,7 +233,7 @@ int make_path(char *fname, int flags) else errno = ENOTDIR; } - } else if (do_mkdir(fname, ACCESSPERMS) == 0) { + } else if (do_mkdir_at(fname, ACCESSPERMS) == 0) { ret++; break; } @@ -253,7 +272,7 @@ int make_path(char *fname, int flags) p += strlen(p); if (ret < 0) /* Skip mkdir on error, but keep restoring the path. */ continue; - if (do_mkdir(fname, ACCESSPERMS) < 0) + if (do_mkdir_at(fname, ACCESSPERMS) < 0) ret = -ret - 1; else ret++;