mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-09-21 01:34:54 -04:00
syscall: do_mknod_at must mkfifoat for an operator-path FIFO on non-Linux
The operator_path_resolve branch of do_mknod_at() called mknodat() and returned its result directly, without the FIFO/socket fallback that the bare-path do_mknod() and the secure-relpath branch below it both have. mknodat() can make a FIFO only on Linux; on the BSDs/macOS/Solaris it fails with EINVAL, so creating a special file under an operator-supplied path -- e.g. backing up a FIFO into a --backup-dir -- failed there. Retry race-safely with mkfifoat() on the held parent dirfd, and fail a nested socket closed (EOPNOTSUPP) exactly as the secure-relpath path does.
This commit is contained in:
1 parent
4da4a7ce1e
commit
ea7fc12b9c
1 file changed
+13
@@ -1055,6 +1055,19 @@ int do_mknod_at(const char *pathname, mode_t mode, dev_t dev)
|
||||
if (dfd < 0)
|
||||
return -1;
|
||||
ret = mknodat(dfd, bname, mode, dev);
|
||||
if (ret < 0) {
|
||||
/* mknodat() can't make a FIFO/socket on the BSDs/macOS/
|
||||
* Solaris (EINVAL); retry race-safely on the held dirfd,
|
||||
* mirroring the secure-relpath path below. Without this a
|
||||
* FIFO backup to an operator --backup-dir fails there. */
|
||||
#ifdef HAVE_MKFIFOAT
|
||||
if (S_ISFIFO(mode))
|
||||
ret = mkfifoat(dfd, bname, mode);
|
||||
else
|
||||
#endif
|
||||
if (S_ISSOCK(mode))
|
||||
errno = EOPNOTSUPP; /* no dirfd-relative socket bind */
|
||||
}
|
||||
e = errno;
|
||||
close(dfd);
|
||||
errno = e;
|
||||
|
||||
Reference in new issue
Block a user