1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-10 06:47:55 -08:00

A few fixes from Pedro Martelletto, adapted from

https://github.com/bitrig/bitrig/commits/pedro_tmpfs_fixes

7efd381ac3:

# mkdir -p x/y
# mv x/y/. z (or mv x/y/.. z)
(panic)

264ecd2c7b:

# mknod x b 100 100 (can be any block/character device)
# ls -lR /
(panic)

7da08d22fd:

# mkfifo x (or mknod x)
# mv x y
(panic)

af0666c65a:

# mount -t tmpfs -o -n16 tmpfs /mnt (create tmpfs with 16 inodes limit)
# cd /mnt
# touch x
# for i in `jot 100 1 100`; do ln -s x $i; done (create 100 symlinks, =
they "succeed" even though they failed)
# ls -lart

7e9296a6f8:

# mkdir x
# touch x/y
# chflags uappnd x (or sappnd)
# rm x/y

936b9cf257:

# mkdir -p x/y
# rmdir x/y/..
(panic)

de541406ef:

# touch x
# ln x y
# stat -f %c x
# sleep 10
# rm y
# stat -f %c x

okay guenther@, krw@
This commit is contained in:
espie 2013-10-10 11:00:28 +00:00
parent c8824adcac
commit 46905cb9a9
3 changed files with 74 additions and 27 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tmpfs_fifoops.c,v 1.2 2013/06/03 10:37:02 espie Exp $ */
/* $OpenBSD: tmpfs_fifoops.c,v 1.3 2013/10/10 11:00:28 espie Exp $ */
/* $NetBSD: tmpfs_fifoops.c,v 1.9 2011/05/24 20:17:49 rmind Exp $ */
/*
@ -89,6 +89,7 @@ struct vops tmpfs_fifovops = {
.vop_bmap = vop_generic_bmap,
.vop_strategy = fifo_badop,
.vop_print = tmpfs_print,
.vop_islocked = tmpfs_islocked,
.vop_pathconf = fifo_pathconf,
.vop_advlock = fifo_advlock,
.vop_bwrite = tmpfs_bwrite,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tmpfs_specops.c,v 1.2 2013/06/03 10:37:02 espie Exp $ */
/* $OpenBSD: tmpfs_specops.c,v 1.3 2013/10/10 11:00:28 espie Exp $ */
/* $NetBSD: tmpfs_specops.c,v 1.10 2011/05/24 20:17:49 rmind Exp $ */
/*
@ -88,6 +88,7 @@ struct vops tmpfs_specvops = {
.vop_bmap = vop_generic_bmap,
.vop_strategy = spec_strategy,
.vop_print = tmpfs_print,
.vop_islocked = tmpfs_islocked,
.vop_pathconf = spec_pathconf,
.vop_advlock = spec_advlock,
.vop_bwrite = vop_generic_bwrite,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tmpfs_vnops.c,v 1.8 2013/09/22 03:34:31 guenther Exp $ */
/* $OpenBSD: tmpfs_vnops.c,v 1.9 2013/10/10 11:00:28 espie Exp $ */
/* $NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland Exp $ */
/*
@ -166,9 +166,15 @@ tmpfs_lookup(void *v)
/*
* Lookup of ".." case.
*/
if (lastcn && cnp->cn_nameiop == RENAME) {
error = EINVAL;
goto out;
if (lastcn) {
if (cnp->cn_nameiop == RENAME) {
error = EINVAL;
goto out;
}
if (cnp->cn_nameiop == DELETE) {
/* Keep the name for tmpfs_rmdir(). */
cnp->cn_flags |= SAVENAME;
}
}
KASSERT(dnode->tn_type == VDIR);
pnode = dnode->tn_spec.tn_dir.tn_parent;
@ -353,15 +359,7 @@ tmpfs_mknod(void *v)
if (error)
return error;
/*
* As in ufs_mknod(), remove inode so that it will be reloaded by
* VFS_VGET and checked to see if it is an alias of an existing entry
* in the vnode cache.
*/
vput(*vpp);
(*vpp)->v_type = VNON;
vgone(*vpp);
*vpp = NULL;
return 0;
}
@ -689,7 +687,7 @@ tmpfs_remove(void *v)
} */ *ap = v;
struct vnode *dvp = ap->a_dvp, *vp = ap->a_vp;
struct componentname *cnp = ap->a_cnp;
tmpfs_node_t *node;
tmpfs_node_t *dnode, *node;
tmpfs_dirent_t *de;
int error;
@ -701,6 +699,8 @@ tmpfs_remove(void *v)
error = EPERM;
goto out;
}
dnode = VP_TO_TMPFS_NODE(dvp);
node = VP_TO_TMPFS_NODE(vp);
/* Files marked as immutable or append-only cannot be deleted. */
@ -709,6 +709,15 @@ tmpfs_remove(void *v)
goto out;
}
/*
* Likewise, files residing on directories marked as append-only cannot
* be deleted.
*/
if (dnode->tn_flags & APPEND) {
error = EPERM;
goto out;
}
/* Lookup the directory entry (check the cached hint first). */
de = tmpfs_dir_cached(node);
if (de == NULL) {
@ -729,6 +738,10 @@ tmpfs_remove(void *v)
tmpfs_dir_attach(dvp, de, TMPFS_NODE_WHITEOUT);
else
tmpfs_free_dirent(VFS_TO_TMPFS(vp->v_mount), de);
if (node->tn_links > 0) {
/* We removed a hard link. */
tmpfs_update(node, TMPFS_NODE_CHANGED);
}
error = 0;
out:
pool_put(&namei_pool, cnp->cn_pnbuf);
@ -856,9 +869,16 @@ tmpfs_rmdir(void *v)
KASSERT(VOP_ISLOCKED(dvp));
KASSERT(VOP_ISLOCKED(vp));
KASSERT(node->tn_spec.tn_dir.tn_parent == dnode);
KASSERT(cnp->cn_flags & HASBUF);
if (cnp->cn_namelen == 2 && cnp->cn_nameptr[0] == '.' &&
cnp->cn_nameptr[1] == '.') {
error = ENOTEMPTY;
goto out;
}
KASSERT(node->tn_spec.tn_dir.tn_parent == dnode);
/*
* Directories with more than two non-whiteout
* entries ('.' and '..') cannot be removed.
@ -948,7 +968,7 @@ tmpfs_symlink(void *v)
if (error == 0)
vput(*vpp);
return 0;
return error;
}
int
@ -1437,6 +1457,7 @@ int tmpfs_check_sticky(struct ucred *,
struct tmpfs_node *, struct tmpfs_node *);
void tmpfs_rename_cache_purge(struct vnode *, struct vnode *, struct vnode *,
struct vnode *);
void tmpfs_rename_abort(void *);
int
tmpfs_rename(void *v)
@ -1482,19 +1503,20 @@ tmpfs_rename(void *v)
*/
if (fvp->v_mount != tdvp->v_mount ||
(tvp != NULL && (fvp->v_mount != tvp->v_mount))) {
VOP_ABORTOP(tdvp, tcnp);
if (tdvp == tvp)
vrele(tdvp);
else
vput(tdvp);
if (tvp != NULL)
vput(tvp);
VOP_ABORTOP(fdvp, fcnp);
vrele(fdvp);
vrele(fvp);
tmpfs_rename_abort(v);
return EXDEV;
}
/*
* Reject renaming '.' and '..'.
*/
if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
(fcnp->cn_namelen == 2 && fcnp->cn_nameptr[0] == '.' &&
fcnp->cn_nameptr[1] == '.')) {
tmpfs_rename_abort(v);
return EINVAL;
}
/*
* Sanitize our world from the VFS insanity. Unlock the target
* directory and node, which are locked. Release the children,
@ -2698,3 +2720,26 @@ tmpfs_rename_cache_purge(struct vnode *fdvp, struct vnode *fvp,
if ((tvp != NULL) && (tvp->v_type == VDIR))
cache_purge(tvp);
}
void
tmpfs_rename_abort(void *v)
{
struct vop_rename_args *ap = v;
struct vnode *fdvp = ap->a_fdvp;
struct vnode *fvp = ap->a_fvp;
struct componentname *fcnp = ap->a_fcnp;
struct vnode *tdvp = ap->a_tdvp;
struct vnode *tvp = ap->a_tvp;
struct componentname *tcnp = ap->a_tcnp;
VOP_ABORTOP(tdvp, tcnp);
if (tdvp == tvp)
vrele(tdvp);
else
vput(tdvp);
if (tvp != NULL)
vput(tvp);
VOP_ABORTOP(fdvp, fcnp);
vrele(fdvp);
vrele(fvp);
}