svn commit: r312393 - in head: sbin/restore sys/sys sys/ufs/ufs
Conrad E. Meyer
cem at FreeBSD.org
Wed Jan 18 18:16:59 UTC 2017
Author: cem
Date: Wed Jan 18 18:16:57 2017
New Revision: 312393
URL: https://svnweb.freebsd.org/changeset/base/312393
Log:
restore(8): Handle extended attribute names correctly
UFS2 extended attribute names are not NUL-terminated. Handle
appropriately.
Correct the EXTATTR_BASE_LENGTH() macro, which handled ea_namelength ==
one (mod eight) extended attributes incorrectly.
PR: 216127
Reported by: dewayne at heuristicsystems.com.au
Reviewed by: kib@
Sponsored by: Dell EMC Isilon
Differential Revision: https://reviews.freebsd.org/D9208
Modified:
head/sbin/restore/dirs.c
head/sbin/restore/extern.h
head/sbin/restore/tape.c
head/sys/sys/extattr.h
head/sys/ufs/ufs/extattr.h
Modified: head/sbin/restore/dirs.c
==============================================================================
--- head/sbin/restore/dirs.c Wed Jan 18 18:14:50 2017 (r312392)
+++ head/sbin/restore/dirs.c Wed Jan 18 18:16:57 2017 (r312393)
@@ -645,7 +645,7 @@ setdirmodes(int flags)
if (!Nflag) {
if (node.extsize > 0) {
if (bufsize >= node.extsize) {
- set_extattr_file(cp, buf, node.extsize);
+ set_extattr(-1, cp, buf, node.extsize, SXA_FILE);
} else {
fprintf(stderr, "Cannot restore %s%s\n",
"extended attributes for ", cp);
Modified: head/sbin/restore/extern.h
==============================================================================
--- head/sbin/restore/extern.h Wed Jan 18 18:14:50 2017 (r312392)
+++ head/sbin/restore/extern.h Wed Jan 18 18:16:57 2017 (r312393)
@@ -87,7 +87,12 @@ struct direct *rst_readdir(RST_DIR *);
void rst_closedir(void *);
void runcmdshell(void);
char *savename(char *);
-void set_extattr_file(char *, void *, int);
+enum set_extattr_mode {
+ SXA_FILE,
+ SXA_LINK,
+ SXA_FD,
+};
+void set_extattr(int, char *, void *, int, enum set_extattr_mode);
void setdirmodes(int);
void setinput(char *, int);
void setup(void);
Modified: head/sbin/restore/tape.c
==============================================================================
--- head/sbin/restore/tape.c Wed Jan 18 18:14:50 2017 (r312392)
+++ head/sbin/restore/tape.c Wed Jan 18 18:16:57 2017 (r312393)
@@ -105,8 +105,6 @@ static void findinode(struct s_spcl *);
static void findtapeblksize(void);
static char *setupextattr(int);
static void xtrattr(char *, size_t);
-static void set_extattr_link(char *, void *, int);
-static void set_extattr_fd(int, char *, void *, int);
static void skiphole(void (*)(char *, size_t), size_t *);
static int gethead(struct s_spcl *);
static void readtape(char *);
@@ -627,7 +625,7 @@ extractfile(char *name)
}
if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
if (extsize > 0)
- set_extattr_link(name, buf, extsize);
+ set_extattr(-1, name, buf, extsize, SXA_LINK);
(void) lchown(name, uid, gid);
(void) lchmod(name, mode);
(void) utimensat(AT_FDCWD, name, ctimep,
@@ -658,7 +656,7 @@ extractfile(char *name)
} else {
buf = setupextattr(extsize);
getfile(xtrnull, xtrattr, xtrnull);
- set_extattr_file(name, buf, extsize);
+ set_extattr(-1, name, buf, extsize, SXA_FILE);
}
(void) chown(name, uid, gid);
(void) chmod(name, mode);
@@ -688,7 +686,7 @@ extractfile(char *name)
} else {
buf = setupextattr(extsize);
getfile(xtrnull, xtrattr, xtrnull);
- set_extattr_file(name, buf, extsize);
+ set_extattr(-1, name, buf, extsize, SXA_FILE);
}
(void) chown(name, uid, gid);
(void) chmod(name, mode);
@@ -715,7 +713,7 @@ extractfile(char *name)
buf = setupextattr(extsize);
getfile(xtrfile, xtrattr, xtrskip);
if (extsize > 0)
- set_extattr_fd(ofile, name, buf, extsize);
+ set_extattr(ofile, name, buf, extsize, SXA_FD);
(void) fchown(ofile, uid, gid);
(void) fchmod(ofile, mode);
(void) futimens(ofile, ctimep);
@@ -728,12 +726,16 @@ extractfile(char *name)
}
/*
- * Set attributes for a file.
+ * Set attributes on a file descriptor, link, or file.
*/
void
-set_extattr_file(char *name, void *buf, int size)
+set_extattr(int fd, char *name, void *buf, int size, enum set_extattr_mode mode)
{
struct extattr *eap, *eaend;
+ const char *method;
+ ssize_t res;
+ int error;
+ char eaname[EXTATTR_MAXNAMELEN + 1];
vprintf(stdout, "Set attributes for %s:", name);
eaend = buf + size;
@@ -748,77 +750,34 @@ set_extattr_file(char *name, void *buf,
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
continue;
- vprintf(stdout, "\n\t%s, (%d bytes), %*s",
+ snprintf(eaname, sizeof(eaname), "%.*s",
+ (int)eap->ea_namelength, eap->ea_name);
+ vprintf(stdout, "\n\t%s, (%d bytes), %s",
namespace_names[eap->ea_namespace], eap->ea_length,
- eap->ea_namelength, eap->ea_name);
+ eaname);
/*
* First we try the general attribute setting interface.
* However, some attributes can only be set by root or
* by using special interfaces (for example, ACLs).
*/
- if (extattr_set_file(name, eap->ea_namespace, eap->ea_name,
- EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
- dprintf(stdout, " (set using extattr_set_file)");
- continue;
- }
- /*
- * If the general interface refuses to set the attribute,
- * then we try all the specialized interfaces that we
- * know about.
- */
- if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
- !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
- if (acl_set_file(name, ACL_TYPE_ACCESS,
- EXTATTR_CONTENT(eap)) != -1) {
- dprintf(stdout, " (set using acl_set_file)");
- continue;
- }
- }
- if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
- !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
- if (acl_set_file(name, ACL_TYPE_DEFAULT,
- EXTATTR_CONTENT(eap)) != -1) {
- dprintf(stdout, " (set using acl_set_file)");
- continue;
- }
- }
- vprintf(stdout, " (unable to set)");
- }
- vprintf(stdout, "\n");
-}
-
-/*
- * Set attributes for a symbolic link.
- */
-static void
-set_extattr_link(char *name, void *buf, int size)
-{
- struct extattr *eap, *eaend;
-
- vprintf(stdout, "Set attributes for %s:", name);
- eaend = buf + size;
- for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
- /*
- * Make sure this entry is complete.
- */
- if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
- dprintf(stdout, "\n\t%scorrupted",
- eap == buf ? "" : "remainder ");
- break;
+ if (mode == SXA_FD) {
+ res = extattr_set_fd(fd, eap->ea_namespace,
+ eaname, EXTATTR_CONTENT(eap),
+ EXTATTR_CONTENT_SIZE(eap));
+ method = "extattr_set_fd";
+ } else if (mode == SXA_LINK) {
+ res = extattr_set_link(name, eap->ea_namespace,
+ eaname, EXTATTR_CONTENT(eap),
+ EXTATTR_CONTENT_SIZE(eap));
+ method = "extattr_set_link";
+ } else if (mode == SXA_FILE) {
+ res = extattr_set_file(name, eap->ea_namespace,
+ eaname, EXTATTR_CONTENT(eap),
+ EXTATTR_CONTENT_SIZE(eap));
+ method = "extattr_set_file";
}
- if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
- continue;
- vprintf(stdout, "\n\t%s, (%d bytes), %*s",
- namespace_names[eap->ea_namespace], eap->ea_length,
- eap->ea_namelength, eap->ea_name);
- /*
- * First we try the general attribute setting interface.
- * However, some attributes can only be set by root or
- * by using special interfaces (for example, ACLs).
- */
- if (extattr_set_link(name, eap->ea_namespace, eap->ea_name,
- EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
- dprintf(stdout, " (set using extattr_set_link)");
+ if (res != -1) {
+ dprintf(stdout, " (set using %s)", method);
continue;
}
/*
@@ -827,77 +786,37 @@ set_extattr_link(char *name, void *buf,
* know about.
*/
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
- !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
- if (acl_set_link_np(name, ACL_TYPE_ACCESS,
- EXTATTR_CONTENT(eap)) != -1) {
- dprintf(stdout, " (set using acl_set_link_np)");
- continue;
+ strcmp(eaname, POSIX1E_ACL_ACCESS_EXTATTR_NAME) == 0) {
+ if (mode == SXA_FD) {
+ error = acl_set_fd(fd, EXTATTR_CONTENT(eap));
+ method = "acl_set_fd";
+ } else if (mode == SXA_LINK) {
+ error = acl_set_link_np(name, ACL_TYPE_ACCESS,
+ EXTATTR_CONTENT(eap));
+ method = "acl_set_link_np";
+ } else if (mode == SXA_FILE) {
+ error = acl_set_file(name, ACL_TYPE_ACCESS,
+ EXTATTR_CONTENT(eap));
+ method = "acl_set_file";
}
- }
- if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
- !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
- if (acl_set_link_np(name, ACL_TYPE_DEFAULT,
- EXTATTR_CONTENT(eap)) != -1) {
- dprintf(stdout, " (set using acl_set_link_np)");
+ if (error != -1) {
+ dprintf(stdout, " (set using %s)", method);
continue;
}
}
- vprintf(stdout, " (unable to set)");
- }
- vprintf(stdout, "\n");
-}
-
-/*
- * Set attributes on a file descriptor.
- */
-static void
-set_extattr_fd(int fd, char *name, void *buf, int size)
-{
- struct extattr *eap, *eaend;
-
- vprintf(stdout, "Set attributes for %s:", name);
- eaend = buf + size;
- for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
- /*
- * Make sure this entry is complete.
- */
- if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
- dprintf(stdout, "\n\t%scorrupted",
- eap == buf ? "" : "remainder ");
- break;
- }
- if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
- continue;
- vprintf(stdout, "\n\t%s, (%d bytes), %*s",
- namespace_names[eap->ea_namespace], eap->ea_length,
- eap->ea_namelength, eap->ea_name);
- /*
- * First we try the general attribute setting interface.
- * However, some attributes can only be set by root or
- * by using special interfaces (for example, ACLs).
- */
- if (extattr_set_fd(fd, eap->ea_namespace, eap->ea_name,
- EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
- dprintf(stdout, " (set using extattr_set_fd)");
- continue;
- }
- /*
- * If the general interface refuses to set the attribute,
- * then we try all the specialized interfaces that we
- * know about.
- */
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
- !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
- if (acl_set_fd(fd, EXTATTR_CONTENT(eap)) != -1) {
- dprintf(stdout, " (set using acl_set_fd)");
- continue;
+ strcmp(eaname, POSIX1E_ACL_DEFAULT_EXTATTR_NAME) == 0) {
+ if (mode == SXA_LINK) {
+ error = acl_set_link_np(name, ACL_TYPE_DEFAULT,
+ EXTATTR_CONTENT(eap));
+ method = "acl_set_link_np";
+ } else {
+ error = acl_set_file(name, ACL_TYPE_DEFAULT,
+ EXTATTR_CONTENT(eap));
+ method = "acl_set_file";
}
- }
- if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
- !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
- if (acl_set_file(name, ACL_TYPE_DEFAULT,
- EXTATTR_CONTENT(eap)) != -1) {
- dprintf(stdout, " (set using acl_set_file)");
+ if (error != -1) {
+ dprintf(stdout, " (set using %s)", method);
continue;
}
}
Modified: head/sys/sys/extattr.h
==============================================================================
--- head/sys/sys/extattr.h Wed Jan 18 18:14:50 2017 (r312392)
+++ head/sys/sys/extattr.h Wed Jan 18 18:16:57 2017 (r312393)
@@ -57,10 +57,11 @@
EXTATTR_NAMESPACE_USER_STRING, \
EXTATTR_NAMESPACE_SYSTEM_STRING }
+#define EXTATTR_MAXNAMELEN NAME_MAX
+
#ifdef _KERNEL
#include <sys/types.h>
-#define EXTATTR_MAXNAMELEN NAME_MAX
struct thread;
struct ucred;
struct vnode;
Modified: head/sys/ufs/ufs/extattr.h
==============================================================================
--- head/sys/ufs/ufs/extattr.h Wed Jan 18 18:14:50 2017 (r312392)
+++ head/sys/ufs/ufs/extattr.h Wed Jan 18 18:16:57 2017 (r312393)
@@ -93,12 +93,14 @@ struct extattr {
* content referenced by eap.
*/
#define EXTATTR_NEXT(eap) \
- ((struct extattr *)(((void *)(eap)) + (eap)->ea_length))
-#define EXTATTR_CONTENT(eap) (((void *)(eap)) + EXTATTR_BASE_LENGTH(eap))
+ ((struct extattr *)(((u_char *)(eap)) + (eap)->ea_length))
+#define EXTATTR_CONTENT(eap) \
+ (void *)(((u_char *)(eap)) + EXTATTR_BASE_LENGTH(eap))
#define EXTATTR_CONTENT_SIZE(eap) \
((eap)->ea_length - EXTATTR_BASE_LENGTH(eap) - (eap)->ea_contentpadlen)
+/* -1 below compensates for ea_name[1] */
#define EXTATTR_BASE_LENGTH(eap) \
- ((sizeof(struct extattr) + (eap)->ea_namelength + 7) & ~7)
+ roundup2((sizeof(struct extattr) - 1 + (eap)->ea_namelength), 8)
#ifdef _KERNEL
More information about the svn-src-head
mailing list