summaryrefslogtreecommitdiff
path: root/usr.bin/rsync/receiver.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2019-03-30 07:28:56 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2019-03-30 07:28:56 +0000
commitef4e7de081eb811ef8da1d4b611bb365db8aefed (patch)
tree0b76f2bbce8acce8f72e409d08aa31ffcb0eb2f9 /usr.bin/rsync/receiver.c
parentea1421bad554d57d966e2c52069766450d08d332 (diff)
For now perform utimes, chown, chmod in the same order as cp(1), until
we know later how rsync wants to behave and how it interacts with future option development. This sequence is safest, since it drops setugid bits in case of failure to chown.. ok florian
Diffstat (limited to 'usr.bin/rsync/receiver.c')
-rw-r--r--usr.bin/rsync/receiver.c80
1 files changed, 42 insertions, 38 deletions
diff --git a/usr.bin/rsync/receiver.c b/usr.bin/rsync/receiver.c
index 873c5d2df69..c6d26cb0917 100644
--- a/usr.bin/rsync/receiver.c
+++ b/usr.bin/rsync/receiver.c
@@ -1,4 +1,4 @@
-/* $Id: receiver.c,v 1.21 2019/03/23 16:04:28 deraadt Exp $ */
+/* $Id: receiver.c,v 1.22 2019/03/30 07:28:55 deraadt Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -47,49 +47,52 @@ rsync_set_metadata(struct sess *sess, int newfile,
{
uid_t uid = (uid_t)-1;
gid_t gid = (gid_t)-1;
+ mode_t mode;
struct timespec ts[2];
+ /* Conditionally adjust file modification time. */
+
+ if (sess->opts->preserve_times) {
+ ts[0].tv_nsec = UTIME_NOW;
+ ts[1].tv_sec = f->st.mtime;
+ ts[1].tv_nsec = 0;
+ if (futimens(fd, ts) == -1) {
+ ERR(sess, "%s: futimens", path);
+ return 0;
+ }
+ LOG4(sess, "%s: updated date", f->path);
+ }
+
/*
* Conditionally adjust identifiers.
* If we have an EPERM, report it but continue on: this just
* means that we're mapping into an unknown (or disallowed)
* group identifier.
*/
-
if (getuid() == 0 && sess->opts->preserve_uids)
uid = f->st.uid;
if (sess->opts->preserve_gids)
gid = f->st.gid;
+ mode = f->st.mode;
if (uid != (uid_t)-1 || gid != (gid_t)-1) {
if (fchown(fd, uid, gid) == -1) {
if (errno != EPERM) {
ERR(sess, "%s: fchown", path);
return 0;
}
- WARNX(sess, "%s: identity unknown or not available "
- "to user.group: %u.%u", f->path, uid, gid);
+ if (getuid() == 0)
+ WARNX(sess, "%s: identity unknown or not available "
+ "to user.group: %u.%u", f->path, uid, gid);
} else
LOG4(sess, "%s: updated uid and/or gid", f->path);
- }
-
- /* Conditionally adjust file modification time. */
-
- if (sess->opts->preserve_times) {
- ts[0].tv_nsec = UTIME_NOW;
- ts[1].tv_sec = f->st.mtime;
- ts[1].tv_nsec = 0;
- if (futimens(fd, ts) == -1) {
- ERR(sess, "%s: futimens", path);
- return 0;
- }
- LOG4(sess, "%s: updated date", f->path);
+ mode &= ~(S_ISTXT | S_ISUID | S_ISGID);
}
/* Conditionally adjust file permissions. */
if (newfile || sess->opts->preserve_perms) {
- if (fchmod(fd, f->st.mode) == -1) {
+ if (fchmod(fd, mode) == -1) {
ERR(sess, "%s: fchmod", path);
return 0;
}
@@ -105,51 +108,52 @@ rsync_set_metadata_at(struct sess *sess, int newfile, int rootfd,
{
uid_t uid = (uid_t)-1;
gid_t gid = (gid_t)-1;
+ mode_t mode;
struct timespec ts[2];
+ /* Conditionally adjust file modification time. */
+
+ if (sess->opts->preserve_times) {
+ ts[0].tv_nsec = UTIME_NOW;
+ ts[1].tv_sec = f->st.mtime;
+ ts[1].tv_nsec = 0;
+ if (utimensat(rootfd, path, ts, AT_SYMLINK_NOFOLLOW) == -1) {
+ ERR(sess, "%s: utimensat", path);
+ return 0;
+ }
+ LOG4(sess, "%s: updated date", f->path);
+ }
+
/*
* Conditionally adjust identifiers.
* If we have an EPERM, report it but continue on: this just
* means that we're mapping into an unknown (or disallowed)
* group identifier.
*/
-
if (getuid() == 0 && sess->opts->preserve_uids)
uid = f->st.uid;
if (sess->opts->preserve_gids)
gid = f->st.gid;
+ mode = f->st.mode;
if (uid != (uid_t)-1 || gid != (gid_t)-1) {
- if (fchownat(rootfd, path, uid, gid, AT_SYMLINK_NOFOLLOW) ==
- -1) {
+ if (fchownat(rootfd, path, uid, gid, AT_SYMLINK_NOFOLLOW) == -1) {
if (errno != EPERM) {
ERR(sess, "%s: fchownat", path);
return 0;
}
- WARNX(sess, "%s: identity unknown or not available "
- "to user.group: %u.%u", f->path, uid, gid);
+ if (getuid() == 0)
+ WARNX(sess, "%s: identity unknown or not available "
+ "to user.group: %u.%u", f->path, uid, gid);
} else
LOG4(sess, "%s: updated uid and/or gid", f->path);
- }
-
- /* Conditionally adjust file modification time. */
-
- if (sess->opts->preserve_times) {
- ts[0].tv_nsec = UTIME_NOW;
- ts[1].tv_sec = f->st.mtime;
- ts[1].tv_nsec = 0;
- if (utimensat(rootfd, path, ts, AT_SYMLINK_NOFOLLOW) == -1) {
- ERR(sess, "%s: utimensat", path);
- return 0;
- }
- LOG4(sess, "%s: updated date", f->path);
+ mode &= ~(S_ISTXT | S_ISUID | S_ISGID);
}
/* Conditionally adjust file permissions. */
if (newfile || sess->opts->preserve_perms) {
- if (fchmodat(rootfd, path, f->st.mode, AT_SYMLINK_NOFOLLOW) ==
- -1) {
+ if (fchmodat(rootfd, path, mode, AT_SYMLINK_NOFOLLOW) == -1) {
ERR(sess, "%s: fchmodat", path);
return 0;
}