diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2012-11-02 13:56:36 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2012-11-02 13:56:36 +0000 |
commit | 140dedb81c5bee09f8bc21997b990f4f96192ce7 (patch) | |
tree | 77eb9f8e9de108d0ae7792cfceedcd340198177e /sys/fs/nullfs | |
parent | cd463097e966f4b968964c7de2c34d9ebe8d5226 (diff) | |
download | src-140dedb81c5bee09f8bc21997b990f4f96192ce7.tar.gz src-140dedb81c5bee09f8bc21997b990f4f96192ce7.zip |
The r241025 fixed the case when a binary, executed from nullfs mount,
was still possible to open for write from the lower filesystem. There
is a symmetric situation where the binary could already has file
descriptors opened for write, but it can be executed from the nullfs
overlay.
Handle the issue by passing one v_writecount reference to the lower
vnode if nullfs vnode has non-zero v_writecount. Note that only one
write reference can be donated, since nullfs only keeps one use
reference on the lower vnode. Always use the lower vnode v_writecount
for the checks.
Introduce the VOP_GET_WRITECOUNT to read v_writecount, which is
currently always bypassed to the lower vnode, and VOP_ADD_WRITECOUNT
to manipulate the v_writecount value, which manages a single bypass
reference to the lower vnode. Caling the VOPs instead of directly
accessing v_writecount provide the fix described in the previous
paragraph.
Tested by: pho
MFC after: 3 weeks
Notes
Notes:
svn path=/head/; revision=242476
Diffstat (limited to 'sys/fs/nullfs')
-rw-r--r-- | sys/fs/nullfs/null_vnops.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 94bfea803979..f530ed217f2f 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -329,6 +329,26 @@ null_bypass(struct vop_generic_args *ap) return (error); } +static int +null_add_writecount(struct vop_add_writecount_args *ap) +{ + struct vnode *lvp, *vp; + int error; + + vp = ap->a_vp; + lvp = NULLVPTOLOWERVP(vp); + KASSERT(vp->v_writecount + ap->a_inc >= 0, ("wrong writecount inc")); + if (vp->v_writecount > 0 && vp->v_writecount + ap->a_inc == 0) + error = VOP_ADD_WRITECOUNT(lvp, -1); + else if (vp->v_writecount == 0 && vp->v_writecount + ap->a_inc > 0) + error = VOP_ADD_WRITECOUNT(lvp, 1); + else + error = 0; + if (error == 0) + vp->v_writecount += ap->a_inc; + 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 @@ -826,4 +846,5 @@ struct vop_vector null_vnodeops = { .vop_unlock = null_unlock, .vop_vptocnp = null_vptocnp, .vop_vptofh = null_vptofh, + .vop_add_writecount = null_add_writecount, }; |