From owner-svn-src-head@freebsd.org Wed Jan 18 18:16:58 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id ECEF1CB6EBC; Wed, 18 Jan 2017 18:16:58 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C50711640; Wed, 18 Jan 2017 18:16:58 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v0IIGvVF067927; Wed, 18 Jan 2017 18:16:57 GMT (envelope-from cem@FreeBSD.org) Received: (from cem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v0IIGvfW067921; Wed, 18 Jan 2017 18:16:57 GMT (envelope-from cem@FreeBSD.org) Message-Id: <201701181816.v0IIGvfW067921@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: cem set sender to cem@FreeBSD.org using -f From: "Conrad E. Meyer" Date: Wed, 18 Jan 2017 18:16:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r312393 - in head: sbin/restore sys/sys sys/ufs/ufs X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 Jan 2017 18:16:59 -0000 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 -#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