From: Dave Chinner <david@fromorbit.com>
To: xfs@oss.sgi.com
Subject: [PATCH] restore: don't trash file capabilities
Date: Wed, 5 Feb 2014 12:48:38 +1100 [thread overview]
Message-ID: <1391564918-25524-1-git-send-email-david@fromorbit.com> (raw)
From: Dave Chinner <dchinner@redhat.com>
xfsrestore fails to restore file capabilities correctly because it
sets the owner on the file after it has restored the capability
attributes. This results in the kernel stripping the capabilities
when changing the owner of the file and hence the restored file is
not complete.
Fix this by changing the owner of the file when it is created rather
than after it has been fully restored. This ensures we don't kill
the caps as they are restored after the owner it appropriately set.
This fixes the xfs/296 failure.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
restore/content.c | 116 ++++++++++++++++++++++++++++++++++++------------------
1 file changed, 77 insertions(+), 39 deletions(-)
diff --git a/restore/content.c b/restore/content.c
index 54d933c..b655ed1 100644
--- a/restore/content.c
+++ b/restore/content.c
@@ -362,6 +362,15 @@ struct stream_context {
char sc_path[2 * MAXPATHLEN];
intgen_t sc_fd;
intgen_t sc_hsmflags;
+
+ /*
+ * we have to set the owner before we set extended attributes otherwise
+ * capabilities will not be restored correctly as setting the owner with
+ * fchmod will strip the capability attribute from the file. Hence we
+ * need to do this before restoring xattrs and record it so we don't do
+ * it again on completion of file restoration.
+ */
+ bool_t sc_ownerset;
};
typedef struct stream_context stream_context_t;
@@ -3429,6 +3438,8 @@ applynondirdump( drive_t *drivep,
memset(&strctxp->sc_bstat, 0, sizeof(bstat_t));
strctxp->sc_path[0] = '\0';
strctxp->sc_fd = -1;
+ strctxp->sc_ownerset = BOOL_FALSE;
+
for ( ; ; ) {
drive_ops_t *dop = drivep->d_opsp;
@@ -3455,6 +3466,7 @@ applynondirdump( drive_t *drivep,
memcpy(&strctxp->sc_bstat, bstatp, sizeof(bstat_t));
strctxp->sc_path[0] = '\0';
strctxp->sc_fd = -1;
+ strctxp->sc_ownerset = BOOL_FALSE;
rv = restore_file( drivep, fhdrp, ehcs, ahcs, path1, path2 );
@@ -7351,6 +7363,61 @@ restore_file_cb( void *cp, bool_t linkpr, char *path1, char *path2 )
}
}
+/*
+ * Set the file owner and strip suid/sgid if necessary. On failure, it will
+ * close the file descriptor, unlink the file and return -1. On success,
+ * it will mark the stream contexts as having set the owner and return 0.
+ */
+static int
+set_file_owner(
+ char *path,
+ intgen_t *fdp,
+ stream_context_t *strcxtp)
+{
+ bstat_t *bstatp = &strcxtp->sc_bstat;
+ mode_t mode = (mode_t)bstatp->bs_mode;
+ int rval;
+
+ rval = fchown(*fdp, (uid_t)bstatp->bs_uid, (gid_t)bstatp->bs_gid );
+ if (!rval)
+ goto done;
+
+ mlog(MLOG_VERBOSE | MLOG_WARNING,
+ _("chown (uid=%u, gid=%u) %s failed: %s\n"),
+ bstatp->bs_uid, bstatp->bs_gid, path, strerror(errno));
+
+ if (mode & S_ISUID) {
+ mlog(MLOG_VERBOSE | MLOG_WARNING,
+ _("stripping setuid bit on %s since chown failed\n"),
+ path);
+ mode &= ~S_ISUID;
+ }
+
+ if ((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) {
+ mlog(MLOG_VERBOSE | MLOG_WARNING,
+ _("stripping setgid bit on %s since chown failed\n"),
+ path);
+ mode &= ~S_ISGID;
+ }
+
+ if (mode == (mode_t)bstatp->bs_mode)
+ goto done;
+
+ rval = fchmod(*fdp, mode);
+ if (rval) {
+ mlog(MLOG_VERBOSE | MLOG_ERROR,
+ _("unable to strip setuid/setgid on %s, unlinking file.\n"),
+ path);
+ unlink(path);
+ close(*fdp);
+ *fdp = -1;
+ return -1;
+ }
+done:
+ strcxtp->sc_ownerset = BOOL_TRUE;
+ return 0;
+}
+
/* called to begin a regular file. if no path given, or if just toc,
* don't actually write, just read. also get into that situation if
* cannot prepare destination. fd == -1 signifies no write. *statp
@@ -7442,6 +7509,12 @@ restore_reg( drive_t *drivep,
}
}
+ if (strctxp->sc_ownerset == BOOL_FALSE && persp->a.ownerpr) {
+ rval = set_file_owner(path, fdp, strctxp);
+ if (rval)
+ return BOOL_TRUE;
+ }
+
if ( persp->a.dstdirisxfspr ) {
/* set the extended inode flags, except those which must
@@ -7623,45 +7696,10 @@ restore_complete_reg(stream_context_t *strcxtp)
/* set the owner and group (if enabled)
*/
- if ( persp->a.ownerpr ) {
- rval = fchown( fd,
- ( uid_t )bstatp->bs_uid,
- ( gid_t )bstatp->bs_gid );
- if ( rval ) {
- mode_t mode = (mode_t)bstatp->bs_mode;
-
- mlog( MLOG_VERBOSE | MLOG_WARNING,
- _("chown (uid=%u, gid=%u) %s failed: %s\n"),
- bstatp->bs_uid,
- bstatp->bs_gid,
- path,
- strerror( errno ));
-
- if ( mode & S_ISUID ) {
- mlog( MLOG_VERBOSE | MLOG_WARNING,
- _("stripping setuid bit on %s "
- "since chown failed\n"),
- path );
- mode &= ~S_ISUID;
- }
- if ( (mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP) ) {
- mlog( MLOG_VERBOSE | MLOG_WARNING,
- _("stripping setgid bit on %s "
- "since chown failed\n"),
- path );
- mode &= ~S_ISGID;
- }
- if ( mode != (mode_t)bstatp->bs_mode ) {
- rval = fchmod( fd, mode );
- if ( rval ) {
- mlog( MLOG_VERBOSE | MLOG_ERROR,
- _("unable to strip setuid/setgid "
- "on %s, unlinking file.\n"),
- path );
- unlink( path );
- }
- }
- }
+ if (strcxtp->sc_ownerset == BOOL_FALSE && persp->a.ownerpr) {
+ rval = set_file_owner(path, &fd, strcxtp);
+ if (rval)
+ return BOOL_TRUE;
}
/* set the permissions/mode
--
1.8.4.rc3
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next reply other threads:[~2014-02-05 1:49 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-05 1:48 Dave Chinner [this message]
2014-02-05 14:12 ` [PATCH] restore: don't trash file capabilities Brian Foster
2014-02-05 21:54 ` Dave Chinner
2014-02-05 23:13 ` Brian Foster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1391564918-25524-1-git-send-email-david@fromorbit.com \
--to=david@fromorbit.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox