Date: Thu, 1 Oct 2009 20:30:50 GMT From: Gleb Kurtsou <gk@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 169106 for review Message-ID: <200910012030.n91KUofl062894@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=169106 Change 169106 by gk@gk_h1 on 2009/10/01 20:30:32 remove pefs_bypass add pefs_accessx pefs_rename: vput vnode after VOP_LOOKUP VOP_RENAME is expected to vrele vnodes in error case whitespace Affected files ... .. //depot/projects/soc2009/gk_pefs/sbin/pefs/Makefile#5 edit .. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.c#10 edit .. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_keychain.c#6 edit .. //depot/projects/soc2009/gk_pefs/sys/crypto/salsa20/salsa20.c#3 edit .. //depot/projects/soc2009/gk_pefs/sys/crypto/salsa20/salsa20.h#2 edit .. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#13 edit .. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#13 edit .. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_hmac.c#3 edit .. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#13 edit .. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#19 edit .. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_xbase64.c#6 edit Differences ... ==== //depot/projects/soc2009/gk_pefs/sbin/pefs/Makefile#5 (text+ko) ==== @@ -1,6 +1,6 @@ # $FreeBSD$ -MOUNT= ${.CURDIR}/../mount +MOUNT= ${.CURDIR}/../mount SYS= ${.CURDIR}/../../sys .PATH: ${MOUNT} ${SYS}/geom/eli ${SYS}/crypto/sha2 ==== //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.c#10 (text+ko) ==== @@ -370,7 +370,7 @@ warn("cannot open %s", argv[0]); return (EX_IOERR); } - + if (ioctl(fd, PEFS_SETKEY, &k) == -1) { warn("cannot set key"); error = EX_OSERR; @@ -463,7 +463,7 @@ } argc -= optind; argv += optind; - + if (!checkargs_fs(argc, argv)) { pefs_usage(); } @@ -805,7 +805,7 @@ pefs_keyid_as_int(k[1].pxk_keyid)); } } - + close(fd); return (0); @@ -882,7 +882,7 @@ return (cmd->func(argc, argv)); } } - + warnx("unknown command: %s", argv[1]); pefs_usage(); ==== //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_keychain.c#6 (text+ko) ==== @@ -112,11 +112,11 @@ } if (db_data.size != sizeof(struct pefs_xkeyenc)) errx(EX_DATAERR, "keychain: db damaged"); - + kc = calloc(1, sizeof(struct pefs_keychain)); if (kc == NULL) err(EX_OSERR, "calloc"); - + memcpy(&ke, db_data.data, sizeof(struct pefs_xkeyenc)); error = pefs_key_decrypt(&ke, &kc_parent->kc_key); if (error) @@ -164,7 +164,7 @@ err(EX_OSERR, "calloc"); kc->kc_key = *xk; TAILQ_INSERT_HEAD(kch, kc, kc_entry); - + if (flags == 0) return (0); @@ -205,7 +205,7 @@ ke.keybits = htole32(xk->pxk_keybits); if (pefs_key_encrypt(&ke, xk) != 0) return (-1); - + db = keychain_dbopen(filesystem, PEFS_KEYCHAIN_USE, O_RDWR | O_CREAT); if (db == NULL) return (-1); ==== //depot/projects/soc2009/gk_pefs/sys/crypto/salsa20/salsa20.c#3 (text+ko) ==== @@ -23,7 +23,7 @@ static const char sigma[16] = "expand 32-byte k"; static const char tau[16] = "expand 16-byte k"; -void +void salsa20_keysetup(salsa20_ctx *x, const uint8_t *k, uint32_t kbits) { const char *constants; @@ -48,7 +48,7 @@ x->input[15] = U8TO32_LITTLE(constants + 12); } -void +void salsa20_ivsetup(salsa20_ctx *x, const uint8_t *iv, uint64_t offset) { x->skip = offset & ((1 << 6) - 1); @@ -60,10 +60,10 @@ x->input[9] = htole32((uint32_t) offset); } -void +void salsa20_crypt(salsa20_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes) { - uint32_t x0, x1, x2, x3, x4, x5, x6, x7, + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; uint8_t *ctarget = NULL; const uint8_t *msrc = NULL; ==== //depot/projects/soc2009/gk_pefs/sys/crypto/salsa20/salsa20.h#2 (text+ko) ==== @@ -1,5 +1,5 @@ /* - * salsa20-merged.c version 20051118 + * salsa20-merged.c version 20051118 * D. J. Bernstein * Public domain. */ ==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#13 (text+ko) ==== @@ -171,7 +171,7 @@ void pefs_crypto_init(void); void pefs_crypto_uninit(void); -int pefs_node_get_nokey(struct mount *mp, struct vnode *lvp, +int pefs_node_get_nokey(struct mount *mp, struct vnode *lvp, struct vnode **vpp); int pefs_node_get_haskey(struct mount *mp, struct vnode *lvp, struct vnode **vpp, struct pefs_tkey *ptk); ==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#13 (text+ko) ==== @@ -50,7 +50,7 @@ #define PEFS_CTR_BLOCK_SIZE 16 #define PEFS_NAME_BLOCK_SIZE 16 -#define PEFS_BLOCK_ROUND(block, a) (((a) + (block) - 1) & ~((block) - 1)) +#define PEFS_BLOCK_ROUND(block, a) (((a) + (block) - 1) & ~((block) - 1)) CTASSERT(PEFS_KEY_SIZE <= SHA512_DIGEST_LENGTH); CTASSERT(PEFS_TWEAK_SIZE == 64/8); @@ -98,23 +98,23 @@ static algop_keysetup_t pefs_camellia_keysetup; static algop_crypt_t pefs_camellia_crypt; -static const struct pefs_alg pefs_alg_salsa20 = { +static const struct pefs_alg pefs_alg_salsa20 = { PEFS_ALG_SALSA20, - pefs_salsa20_keysetup, + pefs_salsa20_keysetup, pefs_salsa20_ivsetup, pefs_salsa20_crypt }; -static const struct pefs_alg pefs_alg_aes = { +static const struct pefs_alg pefs_alg_aes = { PEFS_ALG_AES_CTR, - pefs_aes_keysetup, + pefs_aes_keysetup, pefs_ctr_ivsetup, pefs_aes_crypt }; -static const struct pefs_alg pefs_alg_camellia = { +static const struct pefs_alg pefs_alg_camellia = { PEFS_ALG_CAMELLIA_CTR, - pefs_camellia_keysetup, + pefs_camellia_keysetup, pefs_ctr_ivsetup, pefs_camellia_crypt }; @@ -143,9 +143,9 @@ void pefs_crypto_init(void) { - pefs_ctx_zone = uma_zcreate("pefs_ctx", sizeof(struct pefs_ctx), + pefs_ctx_zone = uma_zcreate("pefs_ctx", sizeof(struct pefs_ctx), NULL, NULL, NULL, (uma_fini)bzero, UMA_ALIGN_PTR, 0); - pefs_key_zone = uma_zcreate("pefs_key", sizeof(struct pefs_key), + pefs_key_zone = uma_zcreate("pefs_key", sizeof(struct pefs_key), NULL, NULL, NULL, (uma_fini)bzero, UMA_ALIGN_PTR, 0); } @@ -447,7 +447,7 @@ MPASS(size > PEFS_NAME_CSUM_SIZE && size <= MAXNAMLEN); psize = size - PEFS_NAME_CSUM_SIZE; - psize = PEFS_NAME_CSUM_SIZE + + psize = PEFS_NAME_CSUM_SIZE + PEFS_BLOCK_ROUND(PEFS_NAME_BLOCK_SIZE, psize); return (psize); @@ -479,7 +479,7 @@ MPASS(size > PEFS_NAME_CSUM_SIZE && size <= MAXNAMLEN && (size - PEFS_NAME_CSUM_SIZE) % PEFS_NAME_BLOCK_SIZE == 0); - + pefs_ctx_cpy(ctx, pk->pk_name_csum_ctx); csum_int = vmac(name + PEFS_NAME_CSUM_SIZE, size - PEFS_NAME_CSUM_SIZE, @@ -710,13 +710,13 @@ pos = c->pctr_pos; while (len) { - l = pos + len > PEFS_CTR_BLOCK_SIZE ? + l = pos + len > PEFS_CTR_BLOCK_SIZE ? PEFS_CTR_BLOCK_SIZE - pos : len; le_offset = htole64(c->pctr_offset); - memcpy(c->pctr_block + PEFS_TWEAK_SIZE, &le_offset, + memcpy(c->pctr_block + PEFS_TWEAK_SIZE, &le_offset, sizeof(uint64_t)); memcpy(c->pctr_block, c->pctr_tweak, PEFS_TWEAK_SIZE); - + cryptblock(ctx, c->pctr_block); for (i = 0; i < l; i++) { *(ciphertext++) = c->pctr_block[pos + i] ^ @@ -744,10 +744,10 @@ } static void -pefs_camellia_crypt(struct pefs_ctx *ctx, const uint8_t *plaintext, +pefs_camellia_crypt(struct pefs_ctx *ctx, const uint8_t *plaintext, uint8_t *ciphertext, uint32_t len) { - pefs_ctr_crypt(ctx, pefs_camellia_cryptblock, + pefs_ctr_crypt(ctx, pefs_camellia_cryptblock, plaintext, ciphertext, len); } @@ -764,10 +764,10 @@ } static void -pefs_aes_crypt(struct pefs_ctx *ctx, const uint8_t *plaintext, +pefs_aes_crypt(struct pefs_ctx *ctx, const uint8_t *plaintext, uint8_t *ciphertext, uint32_t len) { - pefs_ctr_crypt(ctx, pefs_aes_cryptblock, + pefs_ctr_crypt(ctx, pefs_aes_cryptblock, plaintext, ciphertext, len); } ==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_hmac.c#3 (text+ko) ==== @@ -49,7 +49,7 @@ else if (hkeylen <= SHA512_BLOCK_LENGTH) bcopy(hkey, ctx->kpad, hkeylen); else { - /* + /* * If key is longer than SHA512_BLOCK_LENGTH bytes * reset it to key = SHA512(key). */ @@ -94,7 +94,7 @@ /* mdsize == 0 means "Give me the whole hash!" */ if (mdsize == 0) mdsize = SHA512_DIGEST_LENGTH; - + bcopy(digest, md, mdsize); } ==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#13 (text+ko) ==== @@ -127,7 +127,7 @@ pefs_node_zone = uma_zcreate("pefs_node", sizeof(struct pefs_node), NULL, NULL, NULL, (uma_fini) bzero, UMA_ALIGN_PTR, 0); - + pefs_node_hashtbl = hashinit(NPENODECACHE, M_PEFSHASH, &pefs_node_hash); mtx_init(&pefs_node_listmtx, "pefs_node_list", NULL, MTX_DEF); pefs_crypto_init(); @@ -240,7 +240,7 @@ struct vnode *nldvp; int error, locked, dlocked; int buflen = *encname_len; - + ASSERT_VOP_LOCKED(lvp, "pefs_node_lookup_name"); locked = VOP_ISLOCKED(lvp); if (ldvp) { @@ -250,7 +250,7 @@ } else { dlocked = 0; } - + vref(lvp); VOP_UNLOCK(lvp, 0); nldvp = lvp; @@ -277,34 +277,34 @@ pefs_node_lookup_key(struct pefs_mount *pm, struct vnode *lvp, struct vnode *ldvp, struct ucred *cred, struct pefs_tkey *ptk) { - char *namebuf; + char *namebuf; char *encname; int error, encname_len, name_len; - + namebuf = malloc((MAXNAMLEN + 1)*2, M_PEFSBUF, M_WAITOK | M_ZERO); encname = namebuf + MAXNAMLEN + 1; encname_len = MAXNAMLEN + 1; - + error = pefs_node_lookup_name(lvp, ldvp, cred, encname, &encname_len); if (error) { free(namebuf, M_PEFSBUF); return (error); } - + PEFSDEBUG("pefs_node_lookup_key: encname=%.*s\n", encname_len, encname); - - name_len = pefs_name_decrypt(NULL, pefs_rootkey(pm), ptk, - encname, encname_len, + + name_len = pefs_name_decrypt(NULL, pefs_rootkey(pm), ptk, + encname, encname_len, namebuf, MAXNAMLEN + 1); if (name_len > 0) { pefs_key_ref(ptk->ptk_key); - } else { + } else { PEFSDEBUG("pefs_node_lookup_key: not found: %.*s\n", encname_len, encname); } - - free(namebuf, M_PEFSBUF); - + + free(namebuf, M_PEFSBUF); + return (error); } @@ -361,7 +361,7 @@ * the caller's "spare" reference to created pefs vnode. */ static int -pefs_node_get(struct mount *mp, struct vnode *lvp, struct vnode **vpp, +pefs_node_get(struct mount *mp, struct vnode *lvp, struct vnode **vpp, pefs_node_init_fn *init_fn, void *context) { struct pefs_node *pn; ==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#19 (text+ko) ==== @@ -281,7 +281,7 @@ offset = uio->uio_offset; pefs_chunk_setsize(&pc, pc.pc_size - uio->uio_resid); - de = pefs_enccn_lookup_dirent(dpn_key, &ptk, + de = pefs_enccn_lookup_dirent(dpn_key, &ptk, pc.pc_base, pc.pc_size, cnp->cn_nameptr, cnp->cn_namelen); if (de != NULL) @@ -370,14 +370,14 @@ continue; VI_LOCK(vp); pn = VP_TO_PN(vp); - if (((pn->pn_flags & PN_HASKEY) && + if (((pn->pn_flags & PN_HASKEY) && ((flags & PEFS_FLUSHKEY_ALL) || pn->pn_tkey.ptk_key == pk)) || ((pn->pn_flags & PN_HASKEY) == 0 && pk == NULL)) { vholdl(vp); MNT_IUNLOCK(mp); error = vn_lock(vp, LK_INTERLOCK | LK_EXCLUSIVE); - if (error) { + if (error != 0) { vdrop(vp); MNT_ILOCK(mp); MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); @@ -398,154 +398,6 @@ return (0); } -/* - * This is the 10-Apr-92 bypass routine. - * This version has been optimized for speed, throwing away some - * safety checks. It should still always work, but it's not as - * robust to programmer errors. - * - * In general, we map all vnodes going down and unmap them on the way back. - * As an exception to this, vnodes can be marked "unmapped" by setting - * the Nth bit in operation's vdesc_flags. - * - * Also, some BSD vnode operations have the side effect of vrele'ing - * their arguments. With stacking, the reference counts are held - * by the upper node, not the lower one, so we must handle these - * side-effects here. This is not of concern in Sun-derived systems - * since there are no such side-effects. - * - * This makes the following assumptions: - * - only one returned vpp - * - no INOUT vpp's (Sun's vop_open has one of these) - * - the vnode operation vector of the first vnode should be used - * to determine what implementation of the op should be invoked - * - all mapped vnodes are of our vnode-type (NEEDSWORK: - * problems on rmdir'ing mount points and renaming?) - */ -static int -pefs_bypass(struct vop_generic_args *ap, struct pefs_tkey *ptk) -{ - struct vnode **this_vp_p; - int error; - struct vnode *old_vps[VDESC_MAX_VPS]; - struct vnode **vps_p[VDESC_MAX_VPS]; - struct vnode ***vppp; - struct vnodeop_desc *descp = ap->a_desc; - int reles, i; - - if (pefs_bug_bypass) - printf ("pefs_bypass: %s\n", descp->vdesc_name); - -#ifdef DIAGNOSTIC - /* - * We require at least one vp. - */ - if (descp->vdesc_vp_offsets == NULL || - descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET) - panic ("pefs_bypass: no vp's in map"); -#endif - - /* - * Map the vnodes going in. - * Later, we'll invoke the operation based on - * the first mapped vnode's operation vector. - */ - reles = descp->vdesc_flags; - for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) { - if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET) - break; /* bail out at end of list */ - vps_p[i] = this_vp_p = VOPARG_OFFSETTO(struct vnode**, - descp->vdesc_vp_offsets[i],ap); - /* - * We're not guaranteed that any but the first vnode - * are of our type. Check for and don't map any - * that aren't. (We must always map first vp or vclean fails.) - */ - if (i && (*this_vp_p == NULLVP || - (*this_vp_p)->v_op != &pefs_vnodeops)) { - old_vps[i] = NULLVP; - } else { - old_vps[i] = *this_vp_p; - *(vps_p[i]) = PEFS_LOWERVP(*this_vp_p); - /* - * XXX - Several operations have the side effect - * of vrele'ing their vp's. We must account for - * that. (This should go away in the future.) - */ - if (reles & VDESC_VP0_WILLRELE) - VREF(*this_vp_p); - } - - } - - /* - * Call the operation on the lower layer - * with the modified argument structure. - */ - if (vps_p[0] && *vps_p[0]) - error = VCALL(ap); - else { - printf("pefs_bypass: no map for %s\n", descp->vdesc_name); - error = EINVAL; - } - - /* - * Maintain the illusion of call-by-value - * by restoring vnodes in the argument structure - * to their original value. - */ - reles = descp->vdesc_flags; - for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) { - if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET) - break; /* bail out at end of list */ - if (old_vps[i]) { - *(vps_p[i]) = old_vps[i]; -#if 0 - if (reles & VDESC_VP0_WILLUNLOCK) - VOP_UNLOCK(*(vps_p[i]), 0); -#endif - if (reles & VDESC_VP0_WILLRELE) - vrele(*(vps_p[i])); - } - } - - /* - * Map the possible out-going vpp - * (Assumes that the lower layer always returns - * a VREF'ed vpp unless it gets an error.) - */ - if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET && - !(descp->vdesc_flags & VDESC_NOMAP_VPP) && - !error) { - /* XXX should panic here unconditionally or remove the func */ - if (ptk == NULL || ptk->ptk_key == NULL) { - panic("vop_bypass: map of outgoing vnode without encrypted name: %s", descp->vdesc_name); - } - /* - * XXX - even though some ops have vpp returned vp's, - * several ops actually vrele this before returning. - * We must avoid these ops. - * (This should go away when these ops are regularized.) - */ - if (descp->vdesc_flags & VDESC_VPP_WILLRELE) - goto out; - vppp = VOPARG_OFFSETTO(struct vnode***, - descp->vdesc_vpp_offset,ap); - if (*vppp) { - error = pefs_node_get_haskey(old_vps[0]->v_mount, - **vppp, *vppp, ptk); - } - } - - out: - return (error); -} - -/* - * We have to carry on the locking protocol on the null layer vnodes - * as we progress through the tree. We also have to enforce read-only - * if this layer is mounted read-only. - */ static int pefs_lookup(struct vop_cachedlookup_args *ap) { @@ -565,7 +417,7 @@ pefs_enccn_init(&enccn); - if ((flags & ISLASTCN) && + if ((flags & ISLASTCN) && ((dvp->v_mount->mnt_flag & MNT_RDONLY) || pefs_no_keys(dvp)) && (cnp->cn_nameiop != LOOKUP)) return (EROFS); @@ -589,7 +441,7 @@ (cnp->cn_nameiop == DELETE && (cnp->cn_flags & DOWHITEOUT) && (cnp->cn_flags & ISWHITEOUT)))) { - /* + /* * Some filesystems (like ufs) update internal inode * fields during VOP_LOOKUP which are later used by * VOP_CREATE, VOP_MKDIR, etc. That's why we can't @@ -640,13 +492,13 @@ else error = pefs_node_get_haskey(dvp->v_mount, lvp, &vp, &enccn.pec_tkey); - if (error) { + if (error != 0) { vput(lvp); } else { *ap->a_vpp = vp; if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) { - PEFSDEBUG("pefs_lookup: cache_enter %.*s\n", + PEFSDEBUG("pefs_lookup: cache_enter %.*s\n", (int)cnp->cn_namelen,cnp->cn_nameptr); cache_enter(dvp, vp, cnp); } @@ -669,16 +521,17 @@ pefs_open(struct vop_open_args *ap) { struct vnode *vp = ap->a_vp; + struct vnode *lvp = PEFS_LOWERVP(vp); struct pefs_node *pn = VP_TO_PN(vp); int error; if (pefs_no_keys(vp) && (ap->a_mode & (FWRITE | O_APPEND))) return (EROFS); - error = pefs_bypass(&ap->a_gen, NULL); + error = VOP_OPEN(lvp, ap->a_mode, ap->a_cred, ap->a_td, ap->a_fp); if (error == 0) { if ((pn->pn_flags & PN_HASKEY) == 0) - vp->v_object = PEFS_LOWERVP(vp)->v_object; + vp->v_object = lvp->v_object; else vnode_create_vobject(vp, 0, ap->a_td); } @@ -703,7 +556,7 @@ MPASS(pn->pn_flags & PN_HASKEY); error = VOP_GETATTR(lvp, &va, cred); - if (error) + if (error != 0) return (error); osize = va.va_size; @@ -713,7 +566,7 @@ if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { vn_lock(vp, LK_UPGRADE | LK_RETRY); error = VOP_GETATTR(lvp, &va, cred); - if (error) + if (error != 0) return (error); osize = va.va_size; if (nsize <= osize) @@ -739,9 +592,10 @@ pefs_chunk_zero(&pc); pefs_data_encrypt_update(ctx, &pn->pn_tkey, &pc); puio = pefs_chunk_uio(&pc, offset, UIO_WRITE); - PEFSDEBUG("pefs_tryextend: resizing file; filling with zeros: offset=0x%jx, resid=0x%jx\n", offset, bsize); + PEFSDEBUG("pefs_tryextend: resizing file; filling with zeros: offset=0x%jx, resid=0x%jx\n", + offset, bsize); error = VOP_WRITE(lvp, puio, 0, cred); - if (error) { + if (error != 0) { /* try to reset */ VATTR_NULL(&va); va.va_size = osize; @@ -772,20 +626,20 @@ struct vattr *vap = ap->a_vap; int error; - if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || + if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && (vp->v_mount->mnt_flag & MNT_RDONLY || pefs_no_keys(vp))) return (EROFS); if (vap->va_size != VNOVAL) { - switch (vp->v_type) { - case VDIR: - return (EISDIR); - case VCHR: - case VBLK: - case VSOCK: - case VFIFO: + switch (vp->v_type) { + case VDIR: + return (EISDIR); + case VCHR: + case VBLK: + case VSOCK: + case VFIFO: if (vap->va_flags != VNOVAL) return (EOPNOTSUPP); return (0); @@ -805,11 +659,11 @@ error = pefs_tryextend(vp, vap->va_size, cred); else error = EOPNOTSUPP; /* TODO */ - if (error) + if (error != 0) return (error); vnode_pager_setsize(vp, vap->va_size); break; - default: + default: return (EOPNOTSUPP); } } @@ -823,13 +677,15 @@ static int pefs_getattr(struct vop_getattr_args *ap) { + struct vnode *vp = ap->a_vp; struct vattr *vap = ap->a_vap; int error; - if ((error = pefs_bypass((struct vop_generic_args *)ap, NULL)) != 0) + error = VOP_GETATTR(PEFS_LOWERVP(vp), vap, ap->a_cred); + if (error != 0) return (error); - vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; + vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; if (vap->va_type == VLNK) { vap->va_size = PEFS_NAME_PTON_SIZE(vap->va_size); } @@ -840,11 +696,8 @@ * Handle to disallow write access if mounted read-only. */ static int -pefs_access(struct vop_access_args *ap) +pefs_access_checkmode(struct vnode *vp, accmode_t accmode) { - struct vnode *vp = ap->a_vp; - accmode_t accmode = ap->a_accmode; - /* * Disallow write attempts on read-only layers; * unless the file is a socket, fifo, or a block or @@ -855,6 +708,10 @@ case VDIR: case VLNK: case VREG: + /* + * Do not check pefs_no_keys(vp) here because ioctls + * expect filesystem to be writable right after mount + */ if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); break; @@ -862,21 +719,49 @@ break; } } - return (pefs_bypass((struct vop_generic_args *)ap, NULL)); + + return (0); +} + +static int +pefs_access(struct vop_access_args *ap) +{ + struct vnode *vp = ap->a_vp; + accmode_t accmode = ap->a_accmode; + int error; + + error = pefs_access_checkmode(vp, accmode); + if (error != 0) + return (error); + error = VOP_ACCESS(PEFS_LOWERVP(vp), accmode, ap->a_cred, ap->a_td); + return (error); +} + +static int +pefs_accessx(struct vop_accessx_args *ap) +{ + struct vnode *vp = ap->a_vp; + accmode_t accmode = ap->a_accmode; + int error; + + error = pefs_access_checkmode(vp, accmode); + if (error != 0) + return (error); + error = VOP_ACCESSX(PEFS_LOWERVP(vp), accmode, ap->a_cred, ap->a_td); + return (error); } -/* - * We handle this to eliminate null FS to lower FS - * file moving. Don't know why we don't allow this, - * possibly we should. - */ static int pefs_rename(struct vop_rename_args *ap) { struct vnode *fdvp = ap->a_fdvp; + struct vnode *lfdvp = PEFS_LOWERVP(fdvp); struct vnode *fvp = ap->a_fvp; + struct vnode *lfvp = PEFS_LOWERVP(fvp); struct vnode *tdvp = ap->a_tdvp; + struct vnode *ltdvp = PEFS_LOWERVP(tdvp); struct vnode *tvp = ap->a_tvp; + struct vnode *ltvp = (tvp == NULL ? NULL : PEFS_LOWERVP(tvp)); struct vnode *tovp = NULL; struct componentname *fcnp = ap->a_fcnp; struct componentname *tcnp = ap->a_tcnp; @@ -910,9 +795,14 @@ PEFSDEBUG("pefs_rename: target dir !HASKEY: %s\n", tcnp->cn_nameptr); /* Allow unencrypted to unencrypted rename. */ - error = pefs_bypass((struct vop_generic_args *)ap, - NULL); - return (error); + vref(lfdvp); + vref(lfvp); + vref(ltdvp); + if (ltvp != NULL) + vref(ltvp); + error = VOP_RENAME(lfdvp, lfvp, fcnp, ltdvp, ltvp, + tcnp); + goto done; } /* Target directory is encrypted. Files should be recreated. */ error = EXDEV; @@ -920,12 +810,12 @@ } error = pefs_enccn_get(&fenccn, fvp, fcnp); - if (error) { + if (error != 0) { goto bad; } error = pefs_enccn_create(&tenccn, fenccn.pec_tkey.ptk_key, fenccn.pec_tkey.ptk_tweak, tcnp); - if (error) { + if (error != 0) { pefs_enccn_free(&fenccn); goto bad; } @@ -933,27 +823,31 @@ tcnp->cn_nameiop = DELETE; error = VOP_LOOKUP(tdvp, &tovp, tcnp); tcnp->cn_nameiop = RENAME; - PEFSDEBUG("pefs_rename: lookup target vnode: %s: error=%d, tovp=%p\n", tcnp->cn_nameptr, error, tovp); + PEFSDEBUG("pefs_rename: lookup target vnode: %s: error=%d, tovp=%p\n", + tcnp->cn_nameptr, error, tovp); if (error == ENOENT) error = 0; } - if (error) { + if (error != 0) { pefs_enccn_free(&fenccn); pefs_enccn_free(&tenccn); goto bad; } - ap->a_fcnp = &fenccn.pec_cn; - ap->a_tcnp = &tenccn.pec_cn; - error = pefs_bypass((struct vop_generic_args *)ap, NULL); - ap->a_fcnp = fcnp; - ap->a_tcnp = tcnp; + vref(lfdvp); + vref(lfvp); + vref(ltdvp); + if (ltvp != NULL) + vref(ltvp); + error = VOP_RENAME(lfdvp, lfvp, &fenccn.pec_cn, ltdvp, ltvp, + &tenccn.pec_cn); pefs_enccn_free(&fenccn); pefs_enccn_free(&tenccn); - if (!error) { + if (error == 0) { if (tovp != NULL) { + MPASS(tovp->v_type == VREG); vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); tcnp->cn_nameiop = DELETE; error = VOP_REMOVE(tdvp, tovp, tcnp); @@ -964,10 +858,18 @@ cache_purge(fdvp); cache_purge(fvp); } else { - if (tovp != NULL); - VOP_UNLOCK(tovp, 0); + if (tovp != NULL) + vput(tovp); } +done: + ASSERT_VOP_UNLOCKED(tdvp, "pefs_rename"); + vrele(fdvp); + vrele(fvp); + vrele(tdvp); + if (tvp != NULL) + vrele(tvp); + return (error); bad: @@ -975,7 +877,7 @@ vrele(tdvp); else vput(tdvp); - if (tvp) + if (tvp != NULL) vput(tvp); vrele(fdvp); vrele(fvp); @@ -1264,6 +1166,7 @@ pefs_readdir(struct vop_readdir_args *ap) { struct vnode *vp = ap->a_vp; + struct vnode *lvp = PEFS_LOWERVP(vp); struct uio *uio = ap->a_uio; struct ucred *cred = ap->a_cred; int *eofflag = ap->a_eofflag; @@ -1278,8 +1181,11 @@ int *a_ncookies; u_long **a_cookies; - if (pefs_no_keys(vp)) - return (pefs_bypass((struct vop_generic_args *)ap, NULL)); + if (pefs_no_keys(vp)) { + error = VOP_READDIR(lvp, uio, cred, eofflag, ap->a_ncookies, + ap->a_cookies); + return (error); + } if (ap->a_ncookies == NULL || ap->a_cookies == NULL) { a_ncookies = NULL; @@ -1295,9 +1201,9 @@ if (uio->uio_resid < pc.pc_size) pefs_chunk_setsize(&pc, uio->uio_resid); puio = pefs_chunk_uio(&pc, uio->uio_offset, uio->uio_rw); - error = VOP_READDIR(PEFS_LOWERVP(vp), puio, cred, eofflag, + error = VOP_READDIR(lvp, puio, cred, eofflag, a_ncookies, a_cookies); - if (error) + if (error != 0) break; if (pc.pc_size == puio->uio_resid) @@ -1364,6 +1270,7 @@ pefs_mkdir(struct vop_mkdir_args *ap) { struct vnode *dvp = ap->a_dvp; + struct vnode *lvp; struct componentname *cnp = ap->a_cnp; struct pefs_enccn enccn; int error; @@ -1374,13 +1281,17 @@ pefs_enccn_init(&enccn); PEFS_ENCCN_ASSERT_NOENT(dvp, cnp); error = pefs_enccn_create_node(&enccn, dvp, cnp); - if (error) { + if (error != 0) { return (error); } - ap->a_cnp = &enccn.pec_cn; - error = pefs_bypass((struct vop_generic_args *)ap, &enccn.pec_tkey); - ap->a_cnp = cnp; + error = VOP_MKDIR(PEFS_LOWERVP(dvp), &lvp, &enccn.pec_cn, ap->a_vap); + if (error == 0 && lvp != NULL) { + error = pefs_node_get_haskey(dvp->v_mount, lvp, ap->a_vpp, + &enccn.pec_tkey); + if (error != 0) + vput(lvp); + } pefs_enccn_free(&enccn); @@ -1401,20 +1312,17 @@ return (EROFS); pefs_enccn_init(&enccn); error = pefs_enccn_get(&enccn, vp, cnp); - if (error) { + if (error != 0) { PEFSDEBUG("pefs_rmdir: pefs_enccn_get failed: %d\n", error); return (error); } - ap->a_cnp = &enccn.pec_cn; - error = pefs_bypass((struct vop_generic_args *)ap, NULL); - ap->a_cnp = cnp; - + error = VOP_RMDIR(PEFS_LOWERVP(dvp), PEFS_LOWERVP(vp), &enccn.pec_cn); VP_TO_PN(vp)->pn_flags |= PN_WANTRECYCLE; pefs_enccn_free(&enccn); - if (!error) { + if (error == 0) { cache_purge(dvp); cache_purge(vp); } @@ -1426,6 +1334,7 @@ pefs_create(struct vop_create_args *ap) { struct vnode *dvp = ap->a_dvp; + struct vnode *lvp; struct componentname *cnp = ap->a_cnp; struct pefs_enccn enccn; int error; @@ -1436,13 +1345,17 @@ pefs_enccn_init(&enccn); PEFS_ENCCN_ASSERT_NOENT(dvp, cnp); error = pefs_enccn_create_node(&enccn, dvp, cnp); - if (error) { + if (error != 0) { >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910012030.n91KUofl062894>