diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/cpio/cpio.c | 69 | ||||
-rw-r--r-- | usr/src/cmd/mv/mv.c | 40 | ||||
-rw-r--r-- | usr/src/cmd/tar/tar.c | 104 | ||||
-rw-r--r-- | usr/src/lib/libsec/common/aclutils.c | 27 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_dir.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_vnops.c | 49 |
6 files changed, 213 insertions, 80 deletions
diff --git a/usr/src/cmd/cpio/cpio.c b/usr/src/cmd/cpio/cpio.c index 88026ab580..6f8e97a199 100644 --- a/usr/src/cmd/cpio/cpio.c +++ b/usr/src/cmd/cpio/cpio.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -117,6 +117,8 @@ typedef ulong_t u_off_t; #define ASC_OFFSET_MAX 0XFFFFFFFF /* 8 hexadecimal digits */ #define BIN_OFFSET_MAX LONG_MAX /* signed long max value */ +#define POSIXMODES 07777 + static char aclchar = ' '; static struct Lnk *add_lnk(struct Lnk **); @@ -3574,7 +3576,6 @@ gethdr(void) if (Hdr_type != USTAR && Hdr_type != TAR) { Gen.g_mode = Gen.g_mode & (~_XATTR_CPIO_MODE); Gen.g_mode |= attrmode(xattrp->h_typeflag); - } else if (Hdr_type == USTAR || Hdr_type == TAR) { Thdr_p->tbuf.t_typeflag = xattrp->h_typeflag; } @@ -5754,7 +5755,7 @@ write_hdr(int secflag, off_t len) */ if (G_p->g_attrnam_p != (char *)NULL && Hdr_type != USTAR && Hdr_type != TAR) { - mode = (G_p->g_mode & S_IAMB) | _XATTR_CPIO_MODE; + mode = (G_p->g_mode & POSIXMODES) | _XATTR_CPIO_MODE; } else { mode = G_p->g_mode; } @@ -7429,6 +7430,8 @@ retry_attrdir_open(char *name) struct timeval times[2]; mode_t newmode; struct stat parentstat; + acl_t *aclp = NULL; + int error; /* * We couldn't get to attrdir. See if its @@ -7436,43 +7439,63 @@ retry_attrdir_open(char *name) * for example: a mode such as r-xr--r-- * won't let us create an attribute dir * if it doesn't already exist. + * + * If file has a non-trivial ACL, then save it + * off so that we can place it back on after doing + * chmod's. */ if (stat(name, &parentstat) == -1) { msg(ERRN, "Cannot stat file %s", name); return (-1); } + + if ((error = acl_get(name, ACL_NO_TRIVIAL, &aclp)) != 0) { + msg(ERRN, + "Failed to retrieve ACL on %s %s", name, strerror(errno)); + return (-1); + } + newmode = S_IWUSR | parentstat.st_mode; if (chmod(name, newmode) == -1) { msg(ERRN, "Cannot change mode of file %s to %o", name, newmode); + if (aclp) + acl_free(aclp); return (-1); } dirfd = attropen(name, ".", O_RDONLY); - if (dirfd == -1) { - msg(ERRN, "Cannot open attribute directory of file %s", name); - return (-1); - } else { - /* - * Put mode back to original - */ - if (chmod(name, parentstat.st_mode) != 0) { - msg(ERRN, "Cannot restore permissions of file %s to %o", - name, parentstat.st_mode); - } + /* + * Don't print error here, caller will handle printing out + * can't open message. + */ - /* - * Put back time stamps - */ + /* + * Put mode back to original + */ + if (chmod(name, parentstat.st_mode) != 0) { + msg(ERRN, "Cannot restore permissions of file %s to %o", + name, parentstat.st_mode); + } - times[0].tv_sec = parentstat.st_atime; - times[0].tv_usec = 0; - times[1].tv_sec = parentstat.st_mtime; - times[1].tv_usec = 0; - if (utimes(name, times) != 0) { - msg(ERRN, "Cannot reset timestamps on file %s"); + if (aclp) { + error = acl_set(name, aclp); + if (error) { + msg(ERRN, "failed to set ACL on %s", name); } + acl_free(aclp); + } + /* + * Put back time stamps + */ + + times[0].tv_sec = parentstat.st_atime; + times[0].tv_usec = 0; + times[1].tv_sec = parentstat.st_mtime; + times[1].tv_usec = 0; + if (utimes(name, times) != 0) { + msg(ERRN, "Cannot reset timestamps on file %s"); } return (dirfd); diff --git a/usr/src/cmd/mv/mv.c b/usr/src/cmd/mv/mv.c index 3cdceeafb4..0e5fe13d32 100644 --- a/usr/src/cmd/mv/mv.c +++ b/usr/src/cmd/mv/mv.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -872,6 +872,25 @@ copy: if ((ret = chg_mode(target, UID(s1), GID(s1), FMODE(s1))) > 0) return (1); + /* + * Reapply ACL, since chmod may have + * altered ACL + */ + if (s1acl != NULL) { + if ((acl_set(target, s1acl)) < 0) { + if (pflg || mve) { + (void) fprintf( + stderr, + "%s: failed to set acl entries on %s\n", + cmd, + target); + } + /* + * else: silent and + * continue + */ + } + } if ((ret = chg_time(target, s1)) > 0) return (1); } @@ -1620,6 +1639,10 @@ copydir(char *source, char *target) * ACL for directory */ if (pflg || mve) { + if ((pret = chg_mode(target, UID(s1save), GID(s1save), + FMODE(s1save))) == 0) + pret = chg_time(target, s1save); + ret += pret; if (s1acl_save != NULL) { if (acl_set(target, s1acl_save) < 0) { #ifdef XPG4 @@ -1641,10 +1664,6 @@ copydir(char *source, char *target) acl_free(s1acl_save); s1acl_save = NULL; } - if ((pret = chg_mode(target, UID(s1save), GID(s1save), - FMODE(s1save))) == 0) - pret = chg_time(target, s1save); - ret += pret; } else if (fixmode != (mode_t)0) (void) chmod(target, fixmode & MODEBITS); @@ -2157,6 +2176,17 @@ copyattributes(char *source, char *target) } } } + if (xacl && ((facl_set(targattrfd, xacl)) < 0)) { + if (!attrsilent) { + (void) fprintf(stderr, gettext( + "%s: failed to set acl entries on" + " attribute %s for" + "%s\n"), cmd, dp->d_name, target); + ++error; + } + acl_free(xacl); + xacl = NULL; + } } next: if (xacl != NULL) { diff --git a/usr/src/cmd/tar/tar.c b/usr/src/cmd/tar/tar.c index d546fa2b4d..76ca6b5a5d 100644 --- a/usr/src/cmd/tar/tar.c +++ b/usr/src/cmd/tar/tar.c @@ -1404,7 +1404,7 @@ top: xattrp->h_typeflag == '5') { Hiddendir = 1; sp->st_mode = - (S_IFDIR | (sp->st_mode & S_IAMB)); + (S_IFDIR | (sp->st_mode & POSIXMODES)); } dblock.dbuf.typeflag = xattrp->h_typeflag; } @@ -2461,9 +2461,32 @@ doxtract(char *argv[]) } #endif if (dirfd == -1) { - (void) fprintf(stderr, gettext( - "tar: cannot open %s %s\n"), dirp, - strerror(errno)); +#if defined(O_XATTR) + if (xattrp) { + (void) fprintf(vfile, + gettext("tar: cannot open " + "attribute %s of file %s: %s\n"), + xattraname, dirp, strerror(errno)); + /* + * Reset typeflag back to real + * value so passtape will skip + * ahead correctly. + */ + dblock.dbuf.typeflag = _XATTR_HDRTYPE; + free(xattrhead); + xattrp = NULL; + xattr_linkp = NULL; + xattrhead = NULL; + } else { + fprintf(vfile, + gettext("tar: cannot open %s %s\n"), + dirp, strerror(errno)); + } +#else + fprintf(vfile, + gettext("tar: cannot open %s %s\n"), + dirp, strerror(errno)); +#endif passtape(); continue; } @@ -6534,7 +6557,6 @@ getstat(int dirfd, char *longname, char *shortname) else i = fstatat(dirfd, shortname, &stbuf, 0); - if (i < 0) { /* Initialize flag to print error mesg. */ printerr = 1; @@ -6881,6 +6903,7 @@ read_xattr_hdr() } else { xattr_linkaname = NULL; } + return (0); } #else @@ -6981,6 +7004,8 @@ retry_attrdir_open(char *name) struct timeval times[2]; mode_t newmode; struct stat parentstat; + acl_t *aclp = NULL; + int error; /* * We couldn't get to attrdir. See if its @@ -6988,46 +7013,69 @@ retry_attrdir_open(char *name) * for example: a mode such as r-xr--r-- * won't let us create an attribute dir * if it doesn't already exist. + * + * If file has a non-trivial ACL, then save it + * off so that we can place it back on after doing + * chmod's. */ if (stat(name, &parentstat) == -1) { - (void) fprintf(stderr, gettext("Cannot stat file %s %s\n"), + (void) fprintf(stderr, gettext("tar: cannot stat file %s %s\n"), name, strerror(errno)); - return (1); + return (-1); } + if ((error = acl_get(name, ACL_NO_TRIVIAL, &aclp)) != 0) { + (void) fprintf(stderr, gettext("tar: failed to retrieve ACL on" + " %s %s\n"), name, strerror(errno)); + return (-1); + } + newmode = S_IWUSR | parentstat.st_mode; if (chmod(name, newmode) == -1) { (void) fprintf(stderr, - gettext("Cannot chmod file %s to %o %s\n"), + gettext("tar: cannot chmod file %s to %o %s\n"), name, newmode, strerror(errno)); - return (1); - + if (aclp) + acl_free(aclp); + return (-1); } dirfd = attropen(name, ".", O_RDONLY); - if (dirfd == -1) { - (void) fprintf(stderr, - gettext("Cannot open attribute directory of" - " file %s %s\n"), name, strerror(errno)); - return (1); - } else { - /* - * Put mode back to original - */ - (void) chmod(name, parentstat.st_mode); + /* + * Don't print error message if attropen() failed, + * caller will print message. + */ - /* - * Put back time stamps - */ + /* + * Put mode back to original + */ + if (chmod(name, parentstat.st_mode) == -1) { + (void) fprintf(stderr, + gettext("tar: cannot chmod file %s to %o %s\n"), + name, newmode, strerror(errno)); + } - times[0].tv_sec = parentstat.st_atime; - times[0].tv_usec = 0; - times[1].tv_sec = parentstat.st_mtime; - times[1].tv_usec = 0; - (void) utimes(name, times); + if (aclp) { + error = acl_set(name, aclp); + if (error) { + (void) fprintf(stderr, + gettext("tar: %s: failed to set acl entries\n"), + name); + } + acl_free(aclp); } + /* + * Put back time stamps + */ + + times[0].tv_sec = parentstat.st_atime; + times[0].tv_usec = 0; + times[1].tv_sec = parentstat.st_mtime; + times[1].tv_usec = 0; + (void) utimes(name, times); + return (dirfd); } diff --git a/usr/src/lib/libsec/common/aclutils.c b/usr/src/lib/libsec/common/aclutils.c index f3c8856054..700cefa9a9 100644 --- a/usr/src/lib/libsec/common/aclutils.c +++ b/usr/src/lib/libsec/common/aclutils.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -72,7 +72,7 @@ #define ACL_WRITE_OWNER_ERR_DENY 0x0000040 #define ACL_READ_NAMED_READER_SET_DENY 0x1000000 -#define ACL_WRITE_NAMED_WRITER_SET_ALLO W0x0200000 + typedef union { const char *file; int fd; @@ -148,21 +148,18 @@ acl_trivial(const char *filename) aclcnt = acl(filename, cntcmd, 0, NULL); if (aclcnt > 0) { if (acl_flavor == _ACL_ACE_ENABLED) { - if (aclcnt != 6) - val = 1; - else { - acep = malloc(sizeof (ace_t) * aclcnt); - if (acep == NULL) - return (-1); - if (acl(filename, ACE_GETACL, - aclcnt, acep) < 0) { - free(acep); - return (-1); - } - - val = ace_trivial(acep, aclcnt); + acep = malloc(sizeof (ace_t) * aclcnt); + if (acep == NULL) + return (-1); + if (acl(filename, ACE_GETACL, + aclcnt, acep) < 0) { free(acep); + return (-1); } + + val = ace_trivial(acep, aclcnt); + free(acep); + } else if (aclcnt > MIN_ACL_ENTRIES) val = 1; } diff --git a/usr/src/uts/common/fs/zfs/zfs_dir.c b/usr/src/uts/common/fs/zfs/zfs_dir.c index 0ec9b742c6..61b14030ea 100644 --- a/usr/src/uts/common/fs/zfs/zfs_dir.c +++ b/usr/src/uts/common/fs/zfs/zfs_dir.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -809,7 +809,7 @@ top: */ va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; va.va_type = VDIR; - va.va_mode = S_IFDIR | 0755; + va.va_mode = S_IFDIR | S_ISVTX | 0777; va.va_uid = (uid_t)zp->z_phys->zp_uid; va.va_gid = (gid_t)zp->z_phys->zp_gid; diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c index 8d304a0dca..ef54f76c0d 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vnops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1407,10 +1407,6 @@ zfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr) } top: *vpp = NULL; - if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, cr)) { - ZFS_EXIT(zfsvfs); - return (error); - } /* * First make sure the new directory doesn't exist. @@ -1420,6 +1416,12 @@ top: return (error); } + if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, cr)) { + zfs_dirent_unlock(dl); + ZFS_EXIT(zfsvfs); + return (error); + } + /* * Add a new entry to the directory. */ @@ -1911,6 +1913,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, int trim_mask = FALSE; int saved_mask; uint64_t new_mode; + znode_t *attrzp; int have_grow_lock; int need_policy = FALSE; int err; @@ -1928,6 +1931,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, top: have_grow_lock = FALSE; + attrzp = NULL; if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) { ZFS_EXIT(zfsvfs); @@ -2063,8 +2067,22 @@ top: dmu_tx_hold_write(tx, zp->z_id, 0, zp->z_phys->zp_size); } + if ((mask & (AT_UID | AT_GID)) && zp->z_phys->zp_xattr != 0) { + err = zfs_zget(zp->z_zfsvfs, zp->z_phys->zp_xattr, &attrzp); + if (err) { + dmu_tx_abort(tx); + if (have_grow_lock) + rw_exit(&zp->z_grow_lock); + ZFS_EXIT(zfsvfs); + return (err); + } + dmu_tx_hold_bonus(tx, attrzp->z_id); + } + err = dmu_tx_assign(tx, zfsvfs->z_assign); if (err) { + if (attrzp) + VN_RELE(ZTOV(attrzp)); dmu_tx_abort(tx); if (have_grow_lock) rw_exit(&zp->z_grow_lock); @@ -2109,11 +2127,24 @@ top: ASSERT3U(err, ==, 0); } - if (mask & AT_UID) + if (attrzp) + mutex_enter(&attrzp->z_lock); + + if (mask & AT_UID) { zp->z_phys->zp_uid = (uint64_t)vap->va_uid; + if (attrzp) { + attrzp->z_phys->zp_uid = (uint64_t)vap->va_uid; + } + } - if (mask & AT_GID) + if (mask & AT_GID) { zp->z_phys->zp_gid = (uint64_t)vap->va_gid; + if (attrzp) + attrzp->z_phys->zp_gid = (uint64_t)vap->va_gid; + } + + if (attrzp) + mutex_exit(&attrzp->z_lock); if (mask & AT_ATIME) ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime); @@ -2127,12 +2158,16 @@ top: zfs_time_stamper_locked(zp, STATE_CHANGED, tx); out: + if (mask_applied != 0) seq = zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask_applied); mutex_exit(&zp->z_lock); + if (attrzp) + VN_RELE(ZTOV(attrzp)); + if (have_grow_lock) rw_exit(&zp->z_grow_lock); |