Skip to content

Commit

Permalink
pefs: Fix setkey
Browse files Browse the repository at this point in the history
Reference vnode before calling vn_vptocnp().
Perform VOP_LOOKUP() before VOP_RENAME (required by ufs).
Check new destination file doesn't exist.

sbin/pefs:
Handle -x option (add missing key).
Open specified directory instead of file system root.
Postpone key destruction.
  • Loading branch information
glk committed Jun 20, 2012
1 parent c236799 commit c17d0b3
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 33 deletions.
38 changes: 24 additions & 14 deletions sbin/pefs/pefs_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,8 @@ pefs_delkey(int argc, char *argv[])
static int
pefs_setkey(int argc, char *argv[])
{
struct pefs_xkey k;
struct pefs_keychain_head kch;
struct pefs_keychain *kc;
struct pefs_keyparam kp;
char fsroot[MAXPATHLEN];
int error, fd, i;
Expand All @@ -370,12 +370,6 @@ pefs_setkey(int argc, char *argv[])
pefs_keyparam_create(&kp);
while ((i = getopt(argc, argv, "cCpvxa:i:k:")) != -1)
switch(i) {
case 'v':
verbose = 1;
break;
case 'x':
addkey = 1;
break;
case 'a':
if (pefs_keyparam_setalg(&kp, optarg) != 0)
pefs_usage_alg();
Expand All @@ -396,6 +390,12 @@ pefs_setkey(int argc, char *argv[])
case 'k':
kp.kp_keyfile = optarg;
break;
case 'v':
verbose = 1;
break;
case 'x':
addkey = 1;
break;
default:
pefs_usage();
}
Expand All @@ -415,23 +415,33 @@ pefs_setkey(int argc, char *argv[])
pefs_usage();
}

if (pefs_getfsroot(argv[0], 0, fsroot, sizeof(fsroot)) != 0)
return (PEFS_ERR_INVALID);
initfsroot(argc, argv, 0, fsroot, sizeof(fsroot));

error = pefs_keychain_lookup(&kch, fsroot, chain, &kp);
if (error != 0)
return (error);
pefs_keychain_free(&kch);

fd = openx_rdonly(fsroot);
if (fd == -1)
fd = openx_rdonly(argv[0]);
if (fd == -1) {
pefs_keychain_free(&kch);
return (PEFS_ERR_IO);
}

if (ioctl(fd, PEFS_SETKEY, &k) == -1) {
if (addkey) {
TAILQ_FOREACH(kc, &kch, kc_entry) {
if (ioctl(fd, PEFS_ADDKEY, &kc->kc_key) == 0 && verbose)
printf("Key added: %016jx\n",
pefs_keyid_as_int(kc->kc_key.pxk_keyid));
}
}
kc = TAILQ_FIRST(&kch);
if (ioctl(fd, PEFS_SETKEY, &kc->kc_key) == -1) {
warn("cannot set key");
error = PEFS_ERR_SYS;
} else if (verbose)
pefs_key_shownode(&k, argv[0]);
pefs_key_shownode(&kc->kc_key, argv[0]);

pefs_keychain_free(&kch);

close(fd);

Expand Down
2 changes: 1 addition & 1 deletion sys/fs/pefs/pefs_subr.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ pefs_node_lookup_name(struct vnode *lvp, struct vnode *ldvp, struct ucred *cred,
nldvp = lvp;
error = vn_vptocnp(&nldvp, cred, encname, encname_len);
if (error == 0) {
#if __FreeBSD_version >= 1000001
#if __FreeBSD_version >= 900501
vrele(nldvp);
#else
vdrop(nldvp);
Expand Down
64 changes: 46 additions & 18 deletions sys/fs/pefs/pefs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2254,9 +2254,7 @@ static int
pefs_setkey(struct vnode *vp, struct pefs_key *pk, struct ucred *cred,
struct thread *td)
{
struct vnode *dvp;
struct vnode *lvp;
struct vnode *ldvp;
struct vnode *dvp, *ldvp, *lvp;
struct componentname cn;
struct pefs_node *pn = VP_TO_PN(vp);
struct pefs_enccn fenccn, tenccn;
Expand All @@ -2276,6 +2274,7 @@ pefs_setkey(struct vnode *vp, struct pefs_key *pk, struct ucred *cred,
namebuf = malloc(MAXNAMLEN, M_PEFSBUF, M_WAITOK | M_ZERO);
namelen = MAXNAMLEN - 1;
dvp = vp;
vref(vp);
error = vn_vptocnp(&dvp, cred, namebuf, &namelen);
if (error != 0) {
PEFSDEBUG("pefs_setkey: vn_vptocnp failed: error=%d; vp=%p\n",
Expand All @@ -2284,42 +2283,42 @@ pefs_setkey(struct vnode *vp, struct pefs_key *pk, struct ucred *cred,
return (error);
}
bzero(&cn, sizeof(cn));
cn.cn_nameiop = RENAME;
cn.cn_thread = td;
cn.cn_cred = cred;
cn.cn_flags = LOCKPARENT | LOCKLEAF | ISLASTCN | SAVENAME;
cn.cn_lkflags = LK_EXCLUSIVE;
cn.cn_pnbuf = cn.cn_nameptr = namebuf + namelen;
cn.cn_namelen = MAXNAMLEN - 1 - namelen;

MPASS(dvp->v_mount == vp->v_mount);
lvp = PEFS_LOWERVP(vp);
ldvp = PEFS_LOWERVP(dvp);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
#if __FreeBSD_version < 1000001
vdrop(dvp); /* vhold by vn_vptocnp */
#endif

error = VOP_ACCESS(vp, VWRITE, cred, td);
if (error == 0)
if (error == 0) {
cn.cn_nameiop = DELETE;
error = pefs_enccn_get(&fenccn, dvp, vp, &cn);
}
if (error != 0) {
VOP_UNLOCK(vp, 0);
#if __FreeBSD_version >= 1000001
#if __FreeBSD_version >= 900501
vput(dvp); /* vref by vn_vptocnp */
#else
VOP_UNLOCK(dvp, 0);
vdrop(dvp); /* vrele by vn_vptocnp */
#endif
PEFSDEBUG("pefs_setkey: pefs_enccn_get failed: %d\n", error);
goto out;
}
cn.cn_nameiop = RENAME;
error = pefs_enccn_create(&tenccn, pk, NULL, &cn);
if (error != 0) {
VOP_UNLOCK(vp, 0);
#if __FreeBSD_version >= 1000001
#if __FreeBSD_version >= 900501
vput(dvp); /* vref by vn_vptocnp */
#else
VOP_UNLOCK(dvp, 0);
vdrop(dvp); /* vrele by vn_vptocnp */
#endif
pefs_enccn_free(&fenccn);
goto out;
Expand All @@ -2328,21 +2327,51 @@ pefs_setkey(struct vnode *vp, struct pefs_key *pk, struct ucred *cred,
fenccn.pec_cn.cn_nameptr, fenccn.pec_tkey.ptk_key);
PEFSDEBUG("pefs_setkey: toname=%s; key=%p\n",
tenccn.pec_cn.cn_nameptr, tenccn.pec_tkey.ptk_key);
vref(lvp);
vref(lvp);
ldvp = PEFS_LOWERVP(dvp);
VOP_UNLOCK(PEFS_LOWERVP(vp), 0);
error = VOP_LOOKUP(ldvp, &lvp, &fenccn.pec_cn);
if (error != 0) {
PEFSDEBUG("pefs_setkey: lookup faild: %s\n",
fenccn.pec_cn.cn_nameptr);
#if __FreeBSD_version >= 900501
vput(dvp); /* vref by vn_vptocnp */
#else
VOP_UNLOCK(dvp, 0);
vdrop(dvp); /* vrele by vn_vptocnp */
#endif
goto out_enccn;
}
MPASS(lvp == PEFS_LOWERVP(vp));
VOP_UNLOCK(PEFS_LOWERVP(vp), 0);
error = VOP_LOOKUP(ldvp, &lvp, &tenccn.pec_cn);
if (error != EJUSTRETURN) {
PEFSDEBUG("pefs_setkey: lookup faild: %s\n",
tenccn.pec_cn.cn_nameptr);
#if __FreeBSD_version >= 900501
vput(dvp); /* vref by vn_vptocnp */
#else
VOP_UNLOCK(dvp, 0);
vdrop(dvp); /* vrele by vn_vptocnp */
#endif
error = EBUSY;
goto out_enccn;
}
vref(ldvp);
vref(ldvp);
error = VOP_RENAME(ldvp, lvp, &fenccn.pec_cn, ldvp, lvp,
error = VOP_RENAME(ldvp, PEFS_LOWERVP(vp), &fenccn.pec_cn, ldvp, NULL,
&tenccn.pec_cn);
#if __FreeBSD_version >= 1000001
#if __FreeBSD_version >= 900501
vrele(dvp); /* vref by vn_vptocnp */
#else
vdrop(dvp); /* vrele by vn_vptocnp */
#endif
if (error == 0) {
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
vgone(vp);
VOP_UNLOCK(vp, 0);
}

out_enccn:
pefs_enccn_free(&fenccn);
pefs_enccn_free(&tenccn);

Expand All @@ -2351,7 +2380,6 @@ pefs_setkey(struct vnode *vp, struct pefs_key *pk, struct ucred *cred,

return (error);
}

static int
pefs_ioctl(struct vop_ioctl_args *ap)
{
Expand Down Expand Up @@ -2401,7 +2429,7 @@ pefs_ioctl(struct vop_ioctl_args *ap)
error = ENOENT;
break;
case PEFS_GETNODEKEY:
PEFSDEBUG("pefs_ioctl: set key: %8D\n", xk->pxk_keyid, "");
PEFSDEBUG("pefs_ioctl: get key: %8D\n", xk->pxk_keyid, "");
pn = VP_TO_PN(vp);
if ((pn->pn_flags & PN_HASKEY) != 0) {
mtx_lock(&pm->pm_keys_lock);
Expand Down

0 comments on commit c17d0b3

Please sign in to comment.