Ejemplo n.º 1
0
void
zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
{
	uint64_t fuid, fgid;
	sa_bulk_attr_t bulk[2];
	int count = 0;

	if (IS_EPHEMERAL(zp->z_uid) || IS_EPHEMERAL(zp->z_gid)) {
		SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zp->z_zfsvfs),
		    NULL, &fuid, 8);
		SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zp->z_zfsvfs),
		    NULL, &fgid, 8);
		VERIFY(0 == sa_bulk_lookup(zp->z_sa_hdl, bulk, count));
	}
	if (IS_EPHEMERAL(zp->z_uid))
		*uidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
	else
		*uidp = zp->z_uid;
	if (IS_EPHEMERAL(zp->z_gid))
		*gidp = zfs_fuid_map_id(zp->z_zfsvfs,
		    zp->z_gid, cr, ZFS_GROUP);
	else
		*gidp = zp->z_gid;
}
Ejemplo n.º 2
0
/*
 * Create a file system FUID, based on information in the users cred
 */
uint64_t
zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
                     dmu_tx_t *tx, cred_t *cr, zfs_fuid_info_t **fuidp)
{
    uint64_t	idx;
    ksid_t		*ksid;
    uint32_t	rid;
    char 		*kdomain;
    const char	*domain;
    uid_t		id;

    VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);

    if (type == ZFS_OWNER)
        id = crgetuid(cr);
    else
        id = crgetgid(cr);

    if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id))
        return ((uint64_t)id);

#ifdef TODO
    ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);

    VERIFY(ksid != NULL);
    rid = ksid_getrid(ksid);
    domain = ksid_getdomain(ksid);

    idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, tx);

    zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type);

    return (FUID_ENCODE(idx, rid));
#else
    panic(__func__);
#endif
}
Ejemplo n.º 3
0
/*
 * Create a file system FUID for an ACL ace
 * or a chown/chgrp of the file.
 * This is similar to zfs_fuid_create_cred, except that
 * we can't find the domain + rid information in the
 * cred.  Instead we have to query Winchester for the
 * domain and rid.
 *
 * During replay operations the domain+rid information is
 * found in the zfs_fuid_info_t that the replay code has
 * attached to the zfsvfs of the file system.
 */
uint64_t
zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
    zfs_fuid_type_t type, dmu_tx_t *tx, zfs_fuid_info_t **fuidpp)
{
	const char *domain;
	char *kdomain;
	uint32_t fuid_idx = FUID_INDEX(id);
	uint32_t rid;
	idmap_stat status;
	uint64_t idx;
	boolean_t is_replay = (zfsvfs->z_assign >= TXG_INITIAL);
	zfs_fuid_t *zfuid = NULL;
	zfs_fuid_info_t *fuidp;

	/*
	 * If POSIX ID, or entry is already a FUID then
	 * just return the id
	 *
	 * We may also be handed an already FUID'ized id via
	 * chmod.
	 */

	if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id) || fuid_idx != 0)
		return (id);

	if (is_replay) {
		fuidp = zfsvfs->z_fuid_replay;

		/*
		 * If we are passed an ephemeral id, but no
		 * fuid_info was logged then return NOBODY.
		 * This is most likely a result of idmap service
		 * not being available.
		 */
		if (fuidp == NULL)
			return (UID_NOBODY);

		switch (type) {
		case ZFS_ACE_USER:
		case ZFS_ACE_GROUP:
			zfuid = list_head(&fuidp->z_fuids);
			rid = FUID_RID(zfuid->z_logfuid);
			idx = FUID_INDEX(zfuid->z_logfuid);
			break;
		case ZFS_OWNER:
			rid = FUID_RID(fuidp->z_fuid_owner);
			idx = FUID_INDEX(fuidp->z_fuid_owner);
			break;
		case ZFS_GROUP:
			rid = FUID_RID(fuidp->z_fuid_group);
			idx = FUID_INDEX(fuidp->z_fuid_group);
			break;
		};
		domain = fuidp->z_domain_table[idx -1];
	} else {
		if (type == ZFS_OWNER || type == ZFS_ACE_USER)
			status = kidmap_getsidbyuid(crgetzone(cr), id,
			    &domain, &rid);
		else
			status = kidmap_getsidbygid(crgetzone(cr), id,
			    &domain, &rid);

		if (status != 0) {
			/*
			 * When returning nobody we will need to
			 * make a dummy fuid table entry for logging
			 * purposes.
			 */
			rid = UID_NOBODY;
			domain = "";
		}
	}

	idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, tx);

	if (!is_replay)
		zfs_fuid_node_add(fuidpp, kdomain, rid, idx, id, type);
	else if (zfuid != NULL) {
		list_remove(&fuidp->z_fuids, zfuid);
		kmem_free(zfuid, sizeof (zfs_fuid_t));
	}
	return (FUID_ENCODE(idx, rid));
}
Ejemplo n.º 4
0
/*
 * Handles TX_CREATE, TX_CREATE_ATTR, TX_MKDIR, TX_MKDIR_ATTR and
 * TK_MKXATTR transactions.
 *
 * TX_CREATE and TX_MKDIR are standard creates, but they may have FUID
 * domain information appended prior to the name.  In this case the
 * uid/gid in the log record will be a log centric FUID.
 *
 * TX_CREATE_ACL_ATTR and TX_MKDIR_ACL_ATTR handle special creates that
 * may contain attributes, ACL and optional fuid information.
 *
 * TX_CREATE_ACL and TX_MKDIR_ACL handle special creates that specify
 * and ACL and normal users/groups in the ACEs.
 *
 * There may be an optional xvattr attribute information similar
 * to zfs_log_setattr.
 *
 * Also, after the file name "domain" strings may be appended.
 */
void
zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
    znode_t *dzp, znode_t *zp, char *name, vsecattr_t *vsecp,
    zfs_fuid_info_t *fuidp, vattr_t *vap)
{
	itx_t *itx;
	lr_create_t *lr;
	lr_acl_create_t *lracl;
	size_t aclsize = 0;
	size_t xvatsize = 0;
	size_t txsize;
	xvattr_t *xvap = (xvattr_t *)vap;
	void *end;
	size_t lrsize;
	size_t namesize = strlen(name) + 1;
	size_t fuidsz = 0;

	if (zil_replaying(zilog, tx))
		return;

	/*
	 * If we have FUIDs present then add in space for
	 * domains and ACE fuid's if any.
	 */
	if (fuidp) {
		fuidsz += fuidp->z_domain_str_sz;
		fuidsz += fuidp->z_fuid_cnt * sizeof (uint64_t);
	}

	if (vap->va_mask & ATTR_XVATTR)
		xvatsize = ZIL_XVAT_SIZE(xvap->xva_mapsize);

	if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR ||
	    (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR ||
	    (int)txtype == TX_MKXATTR) {
		txsize = sizeof (*lr) + namesize + fuidsz + xvatsize;
		lrsize = sizeof (*lr);
	} else {
		txsize =
		    sizeof (lr_acl_create_t) + namesize + fuidsz +
		    ZIL_ACE_LENGTH(aclsize) + xvatsize;
		lrsize = sizeof (lr_acl_create_t);
	}

	itx = zil_itx_create(txtype, txsize);

	lr = (lr_create_t *)&itx->itx_lr;
	lr->lr_doid = dzp->z_id;
	lr->lr_foid = zp->z_id;
	lr->lr_mode = zp->z_mode;
	if (!IS_EPHEMERAL(zp->z_uid)) {
		lr->lr_uid = (uint64_t)zp->z_uid;
	} else {
		lr->lr_uid = fuidp->z_fuid_owner;
	}
	if (!IS_EPHEMERAL(zp->z_gid)) {
		lr->lr_gid = (uint64_t)zp->z_gid;
	} else {
		lr->lr_gid = fuidp->z_fuid_group;
	}
	(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &lr->lr_gen,
	    sizeof (uint64_t));
	(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)),
	    lr->lr_crtime, sizeof (uint64_t) * 2);

	if (sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(ZTOZSB(zp)), &lr->lr_rdev,
	    sizeof (lr->lr_rdev)) != 0)
		lr->lr_rdev = 0;

	/*
	 * Fill in xvattr info if any
	 */
	if (vap->va_mask & ATTR_XVATTR) {
		zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap);
		end = (caddr_t)lr + lrsize + xvatsize;
	} else {
		end = (caddr_t)lr + lrsize;
	}

	/* Now fill in any ACL info */

	if (vsecp) {
		lracl = (lr_acl_create_t *)&itx->itx_lr;
		lracl->lr_aclcnt = vsecp->vsa_aclcnt;
		lracl->lr_acl_bytes = aclsize;
		lracl->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0;
		lracl->lr_fuidcnt  = fuidp ? fuidp->z_fuid_cnt : 0;
		if (vsecp->vsa_aclflags & VSA_ACE_ACLFLAGS)
			lracl->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags;
		else
			lracl->lr_acl_flags = 0;

		bcopy(vsecp->vsa_aclentp, end, aclsize);
		end = (caddr_t)end + ZIL_ACE_LENGTH(aclsize);
	}

	/* drop in FUID info */
	if (fuidp) {
		end = zfs_log_fuid_ids(fuidp, end);
		end = zfs_log_fuid_domains(fuidp, end);
	}
	/*
	 * Now place file name in log record
	 */
	bcopy(name, end, namesize);

	zil_itx_assign(zilog, itx, tx);
}
Ejemplo n.º 5
0
/*
 * zfs_log_create() is used to handle TX_CREATE, TX_CREATE_ATTR, TX_MKDIR,
 * TX_MKDIR_ATTR and TX_MKXATTR
 * transactions.
 *
 * TX_CREATE and TX_MKDIR are standard creates, but they may have FUID
 * domain information appended prior to the name.  In this case the
 * uid/gid in the log record will be a log centric FUID.
 *
 * TX_CREATE_ACL_ATTR and TX_MKDIR_ACL_ATTR handle special creates that
 * may contain attributes, ACL and optional fuid information.
 *
 * TX_CREATE_ACL and TX_MKDIR_ACL handle special creates that specify
 * and ACL and normal users/groups in the ACEs.
 *
 * There may be an optional xvattr attribute information similar
 * to zfs_log_setattr.
 *
 * Also, after the file name "domain" strings may be appended.
 */
void
zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
               znode_t *dzp, znode_t *zp, char *name, vsecattr_t *vsecp,
               zfs_fuid_info_t *fuidp, vattr_t *vap)
{
    itx_t *itx;
    uint64_t seq;
    lr_create_t *lr;
#ifdef HAVE_ZPL
    lr_acl_create_t *lracl;
#endif
    size_t aclsize;
    size_t xvatsize = 0;
    size_t txsize;
    xvattr_t *xvap = (xvattr_t *)vap;
    void *end;
    size_t lrsize;
    size_t namesize = strlen(name) + 1;
    size_t fuidsz = 0;

    if (zilog == NULL)
        return;

    ZFS_HANDLE_REPLAY(zilog, tx); /* exits if replay */

    /*
     * If we have FUIDs present then add in space for
     * domains and ACE fuid's if any.
     */
    if (fuidp) {
        fuidsz += fuidp->z_domain_str_sz;
        fuidsz += fuidp->z_fuid_cnt * sizeof (uint64_t);
    }

    if (vap->va_mask & AT_XVATTR)
        xvatsize = ZIL_XVAT_SIZE(xvap->xva_mapsize);

    if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR ||
            (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR ||
            (int)txtype == TX_MKXATTR) {
        txsize = sizeof (*lr) + namesize + fuidsz + xvatsize;
        lrsize = sizeof (*lr);
    } else {
        aclsize = (vsecp) ? vsecp->vsa_aclentsz : 0;
        txsize =
            sizeof (lr_acl_create_t) + namesize + fuidsz +
            ZIL_ACE_LENGTH(aclsize) + xvatsize;
        lrsize = sizeof (lr_acl_create_t);
    }

    itx = zil_itx_create(txtype, txsize);

    lr = (lr_create_t *)&itx->itx_lr;
    lr->lr_doid = dzp->z_id;
    lr->lr_foid = zp->z_id;
    lr->lr_mode = zp->z_phys->zp_mode;
    if (!IS_EPHEMERAL(zp->z_phys->zp_uid)) {
        lr->lr_uid = (uint64_t)zp->z_phys->zp_uid;
    } else {
        lr->lr_uid = fuidp->z_fuid_owner;
    }
    if (!IS_EPHEMERAL(zp->z_phys->zp_gid)) {
        lr->lr_gid = (uint64_t)zp->z_phys->zp_gid;
    } else {
        lr->lr_gid = fuidp->z_fuid_group;
    }
    lr->lr_gen = zp->z_phys->zp_gen;
    lr->lr_crtime[0] = zp->z_phys->zp_crtime[0];
    lr->lr_crtime[1] = zp->z_phys->zp_crtime[1];
    lr->lr_rdev = zp->z_phys->zp_rdev;

    /*
     * Fill in xvattr info if any
     */
#ifdef HAVE_ZPL
    if (vap->va_mask & AT_XVATTR) {
        zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap);
        end = (caddr_t)lr + lrsize + xvatsize;
    } else {
        end = (caddr_t)lr + lrsize;
    }
#else
    end = (caddr_t)lr + lrsize;
#endif /* HAVE_ZPL */


    /* Now fill in any ACL info */

#ifdef HAVE_ZPL
    if (vsecp) {
        lracl = (lr_acl_create_t *)&itx->itx_lr;
        lracl->lr_aclcnt = vsecp->vsa_aclcnt;
        lracl->lr_acl_bytes = aclsize;
        lracl->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0;
        lracl->lr_fuidcnt  = fuidp ? fuidp->z_fuid_cnt : 0;
        if (vsecp->vsa_aclflags & VSA_ACE_ACLFLAGS)
            lracl->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags;
        else
            lracl->lr_acl_flags = 0;

        bcopy(vsecp->vsa_aclentp, end, aclsize);
        end = (caddr_t)end + ZIL_ACE_LENGTH(aclsize);
    }

    /* drop in FUID info */
    if (fuidp) {
        end = zfs_log_fuid_ids(fuidp, end);
        end = zfs_log_fuid_domains(fuidp, end);
    }
#endif
    /*
     * Now place file name in log record
     */
    bcopy(name, end, namesize);

    seq = zil_itx_assign(zilog, itx, tx);
    dzp->z_last_itx = seq;
    zp->z_last_itx = seq;
}