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 5ccb76b08b)
This commit is contained in:
Andrew Tridgell committed 2026-06-13 06:04:47 +10:00
1 parent a60e5c2d31
commit 1d4ef93a75
1 file changed
+21 -2
+21 -2
View File
@@ -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++;