summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Espie <espie@cvs.openbsd.org>2013-10-10 11:00:29 +0000
committerMarc Espie <espie@cvs.openbsd.org>2013-10-10 11:00:29 +0000
commit49e3f17d4c8dd6ebd9d7e65468ea09e49838da5f (patch)
treecd76b4c4be03cb715dde4031b3500ed162e52a74
parent929026206bb7ec352247a2031e29e0d63dd09071 (diff)
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@
-rw-r--r--sys/tmpfs/tmpfs_fifoops.c3
-rw-r--r--sys/tmpfs/tmpfs_specops.c3
-rw-r--r--sys/tmpfs/tmpfs_vnops.c95
3 files changed, 74 insertions, 27 deletions
diff --git a/sys/tmpfs/tmpfs_fifoops.c b/sys/tmpfs/tmpfs_fifoops.c
index ba6e2b8c9d2..217fdbbf0bc 100644
--- a/sys/tmpfs/tmpfs_fifoops.c
+++ b/sys/tmpfs/tmpfs_fifoops.c
@@ -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,
diff --git a/sys/tmpfs/tmpfs_specops.c b/sys/tmpfs/tmpfs_specops.c
index cd298d5f3ed..e0165bcfc62 100644
--- a/sys/tmpfs/tmpfs_specops.c
+++ b/sys/tmpfs/tmpfs_specops.c
@@ -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,
diff --git a/sys/tmpfs/tmpfs_vnops.c b/sys/tmpfs/tmpfs_vnops.c
index 892e9cd645a..7b9b5c883d8 100644
--- a/sys/tmpfs/tmpfs_vnops.c
+++ b/sys/tmpfs/tmpfs_vnops.c
@@ -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,20 +1503,21 @@ 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,
* which are referenced. Check for rename("x", "y/."), which
@@ -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);
+}