summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/cpio/cpio.c69
-rw-r--r--usr/src/cmd/mv/mv.c40
-rw-r--r--usr/src/cmd/tar/tar.c104
-rw-r--r--usr/src/lib/libsec/common/aclutils.c27
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_dir.c4
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c49
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);