镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ CHECK_SYMLINKS = testsuite/chown-fake_test.py testsuite/devices-fake_test.py \
# Objects for CHECK_PROGS to clean
CHECK_OBJS=tls.o testrun.o getgroups.o getfsdev.o t_stub.o t_unsafe.o t_chmod_secure.o t_rename_secure.o t_symlink_secure.o t_secure_relpath.o t_acl.o t_hashtable_overflow.o t_iwildmatch.o t_clean_fname.o t_safe_arg.o trimslash.o wildtest.o
# Compile-only feature-shape checks.
CHECK_COMPILE_OBJS=syscall-no-at-fdcwd.o syscall-no-o-directory.o \
authenticate-no-o-cloexec.o rsync-no-o-cloexec.o clientserver-no-o-directory.o \
flist-no-o-directory.o generator-no-o-directory.o sender-no-o-directory.o \
lib/acl-no-o-directory.o
CHECK_COMPILE_OBJS=syscall-no-at-fdcwd.o access-no-inet6.o

# note that the -I. is needed to handle config.h when using VPATH
Expand All @@ -85,6 +89,37 @@ syscall-no-at-fdcwd.o: syscall.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_AT_FDCWD -c $(srcdir)/syscall.c -o $@

syscall-no-o-directory.o: syscall.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_O_DIRECTORY -c $(srcdir)/syscall.c -o $@

authenticate-no-o-cloexec.o: authenticate.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_O_CLOEXEC -c $(srcdir)/authenticate.c -o $@

rsync-no-o-cloexec.o: rsync.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_O_CLOEXEC -c $(srcdir)/rsync.c -o $@

clientserver-no-o-directory.o: clientserver.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_O_DIRECTORY -c $(srcdir)/clientserver.c -o $@

flist-no-o-directory.o: flist.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_O_DIRECTORY -c $(srcdir)/flist.c -o $@

generator-no-o-directory.o: generator.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_O_DIRECTORY -c $(srcdir)/generator.c -o $@

sender-no-o-directory.o: sender.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_O_DIRECTORY -c $(srcdir)/sender.c -o $@

lib/acl-no-o-directory.o: lib/acl.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_O_DIRECTORY -c $(srcdir)/lib/acl.c -o $@
access-no-inet6.o: access.c $(HEADERS)
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) \
-DRSYNC_TEST_NO_INET6 -c $(srcdir)/access.c -o $@
Expand Down
7 changes: 0 additions & 7 deletions authenticate.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,6 @@
#include "itypes.h"
#include "ifuncs.h"

/* O_CLOEXEC is absent on some still-supported targets. The random-source fd
* is read and closed synchronously, so the established zero-value fallback is
* sufficient without adding a configure dependency. */
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif

extern int read_only;
extern char *password_file;
extern struct name_num_obj valid_auth_checksums;
Expand Down
27 changes: 26 additions & 1 deletion clientserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,13 @@ static void create_pid_file(void)
const char *slash = strrchr(pid_file, '/');
char dirbuf[MAXPATHLEN];
const char *dir = ".";
int dir_flags = O_RDONLY;
#ifdef O_DIRECTORY
dir_flags |= O_DIRECTORY;
#elif defined O_NONBLOCK
/* Avoid blocking on a non-directory special file before fstat below. */
dir_flags |= O_NONBLOCK;
#endif
if (slash) {
size_t dlen = slash == pid_file ? 1 : (size_t)(slash - pid_file);
if (dlen >= sizeof dirbuf) {
Expand All @@ -1627,7 +1634,25 @@ static void create_pid_file(void)
dir = dirbuf;
base = slash + 1;
}
if ((pdfd = do_open(dir, O_RDONLY|O_DIRECTORY, 0)) < 0) {
pdfd = do_open(dir, dir_flags, 0);
#ifndef O_DIRECTORY
if (pdfd >= 0) {
STRUCT_STAT dir_st;
int save_errno;
if (do_fstat(pdfd, &dir_st) < 0)
save_errno = errno;
else if (!S_ISDIR(dir_st.st_mode))
save_errno = ENOTDIR;
else
save_errno = 0;
if (save_errno) {
close(pdfd);
pdfd = -1;
errno = save_errno;
}
}
#endif
if (pdfd < 0) {
rsyserr(FLOG, errno, "failed to open pid-file directory \"%s\"", dir);
exit_cleanup(RERR_FILEIO);
}
Expand Down
19 changes: 14 additions & 5 deletions flist.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ int open_sender_source_path(const char *path, int flags, int *matched)
errno = saved_errno;
return fd;
#else
(void)path;
(void)flags;
*matched = 0;
errno = ENOSYS;
return -1;
Expand Down Expand Up @@ -2259,14 +2261,21 @@ static void interpret_stat_error(const char *fname, int is_dir)
static DIR *secure_opendir(const char *fbuf)
{
int dfd, fl, matched;
int dir_flags = O_RDONLY;
DIR *d;

#ifdef O_DIRECTORY
dir_flags |= O_DIRECTORY;
#elif defined O_NONBLOCK
/* Avoid blocking on a raced special file before fdopendir validates it. */
dir_flags |= O_NONBLOCK;
#endif
if (filesfrom_owner_walk_active()) {
/* The source base is operator-selected, while each list entry may not
* be. Follow only trusted-owned symlinks while opening the directory. */
dfd = open_no_attacker_symlinks(fbuf, O_RDONLY | O_DIRECTORY, 0);
dfd = open_no_attacker_symlinks(fbuf, dir_flags, 0);
} else if (!am_daemon && am_sender
&& (dfd = open_sender_source_path(fbuf, O_RDONLY | O_DIRECTORY, &matched), matched)) {
&& (dfd = open_sender_source_path(fbuf, dir_flags, &matched), matched)) {
/* The command-line directory is the operator-selected transfer root.
* Follow that root, then keep every recursive scan beneath its held fd. */
} else if (am_daemon && (!am_chrooted || module_dirlen)
Expand Down Expand Up @@ -2295,18 +2304,18 @@ static DIR *secure_opendir(const char *fbuf)
return NULL;
}
dfd = secure_relative_open_at(module_dirfd, *modrel ? modrel : ".",
O_RDONLY | O_DIRECTORY, 0);
dir_flags, 0);
} else if (*fbuf == '/') {
/* An absolute scan path (an absolute --relative / --files-from name, or a
* "/" transfer root): anchor at "/" -- operator-named, trusted. */
const char *relp = fbuf;
while (*relp == '/')
relp++;
dfd = secure_relative_open("/", relp, O_RDONLY | O_DIRECTORY, 0);
dfd = secure_relative_open("/", relp, dir_flags, 0);
} else {
/* Non-daemon (or chrooted) sender: confine beneath the cwd the sender
* chdir'd into (the transfer root). */
dfd = secure_relative_open(NULL, fbuf, O_RDONLY | O_DIRECTORY, 0);
dfd = secure_relative_open(NULL, fbuf, dir_flags, 0);
}

if (dfd < 0)
Expand Down
4 changes: 2 additions & 2 deletions generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,9 +999,9 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru
static int basis_link_stat(const char *path, STRUCT_STAT *stp)
{
extern int am_chrooted;
extern int operator_path_resolve;
extern unsigned int module_dirlen;
#if defined AT_FDCWD && defined O_NOFOLLOW && defined O_DIRECTORY
extern int operator_path_resolve;
/* The basis dir (--link-dest/--compare-dest/--copy-dest) is an operator-
* supplied path. For a non-daemon receiver, resolve it with the ownership
* walk: a symlink component owned by uid 0 or the euid (the operator's own
Expand Down Expand Up @@ -1603,7 +1603,7 @@ static int gen_entry_copy_xattrs(const char *src, const char *fname, struct file
* relative basis goes through the RESOLVE_BENEATH resolver; an absolute one
* through the operator ownership walk. Refuse (don't path-read) when we are
* meant to confine but can't pin; a non-hardened receiver path-reads (sfd<0). */
#if defined AT_FDCWD && defined O_NOFOLLOW
#if defined AT_FDCWD && defined O_NOFOLLOW && defined O_DIRECTORY
if (secure_relpath_active() && src && *src && !symlink_optout_allowed()) {
int odir = 0;
#ifdef O_DIRECTORY
Expand Down
7 changes: 6 additions & 1 deletion lib/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,10 +402,15 @@ int xacl_del_default_at(int dirfd, const char *leaf)
* work race-safely via the /proc compat on a pre-6.13 kernel. */
static int proc_self_fd_usable(void)
{
int dfd = open(".", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
int open_flags = O_RDONLY | O_CLOEXEC;
int dfd;
char p[64];
int usable = 0;

#ifdef O_DIRECTORY
open_flags |= O_DIRECTORY;
#endif
dfd = open(".", open_flags);
if (dfd < 0)
return 0;
if (snprintf(p, sizeof p, "/proc/self/fd/%d/.", dfd) < (int)sizeof p) {
Expand Down
15 changes: 15 additions & 0 deletions rsync.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,21 @@ enum delret {
#endif
#endif

/* O_CLOEXEC is absent on some still-supported targets. Defining it to zero
* preserves the open flags there; the test macro exercises that fallback on
* build hosts that provide O_CLOEXEC. */
#ifdef RSYNC_TEST_NO_O_CLOEXEC
#undef O_CLOEXEC
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif

/* Exercise the O_DIRECTORY portability path on build hosts that provide it. */
#ifdef RSYNC_TEST_NO_O_DIRECTORY
#undef O_DIRECTORY
#endif

#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
Expand Down
2 changes: 1 addition & 1 deletion sender.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static const char *orig_subdir(const char *path)

static int secure_sender_parent_fd(struct file_struct *file, const char *fname, const char **bname_p)
{
#ifdef AT_FDCWD
#if defined AT_FDCWD && defined O_NOFOLLOW && defined O_DIRECTORY
const char *path, *slash, *relp, *bslash, *fslash;
char secure_path[MAXPATHLEN];
int dfd, fl, slen;
Expand Down
12 changes: 2 additions & 10 deletions syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -424,11 +424,6 @@ static int ona_open_absolute_root(char *remaining, char *abspath, size_t abspath
static int ona_open(const char *path, int flags, mode_t mode, char *out_abs, size_t out_cap)
{
#if defined AT_FDCWD && defined O_NOFOLLOW && defined O_DIRECTORY
/* O_CLOEXEC predates some still-supported targets; mirror rand_bytes()'s
* fallback in syscall.c so a build without it still compiles. */
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
const int dir_traverse_flags = directory_traverse_flags() | O_CLOEXEC;
if (!path || !*path) {
errno = EINVAL;
Expand Down Expand Up @@ -3525,15 +3520,12 @@ int secure_relative_dirfd_at_beneath(int anchor_fd, const char *relpath)
directory_traverse_flags(), 0, 1);
}

#if defined O_NOFOLLOW && defined O_DIRECTORY && defined AT_FDCWD
#if defined O_NOFOLLOW && defined AT_FDCWD
/* Fill buf with len random bytes. Prefers /dev/urandom for cryptographic
* quality; falls back to rand() if /dev/urandom cannot be opened or read
* (e.g. inside a chroot or container without /dev populated). */
static void rand_bytes(unsigned char *buf, size_t len)
{
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
ssize_t n = read(fd, buf, len);
Expand All @@ -3555,7 +3547,7 @@ static void rand_bytes(unsigned char *buf, size_t len)
* This is the create loop shared with secure_mkstemp(). */
int do_mkstemp_atfd(int dfd, char *filename, mode_t perms)
{
#ifdef AT_FDCWD
#if defined O_NOFOLLOW && defined AT_FDCWD
static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
size_t filename_len = strlen(filename);
char *suffix;
Expand Down
82 changes: 0 additions & 82 deletions testsuite/authenticate-no-ocloexec-build-regression_test.py

This file was deleted.

Loading