Re: Nasty 2.1.70 fs problem

Andrea Arcangeli (arcangeli@mbox.queen.it)
Wed, 10 Dec 1997 15:41:50 +0100 (CET)


On Tue, 9 Dec 1997, Richard B. Johnson wrote:

>
>The following commands (don't do this on a good fs):
>cd /tmp
>while [ 1 ] ; do mkdir foo ; cd foo ; done

Apply the patch I posted some days ago before running the script and the
script will stop after reach a PAGE_SIZE long pathname so you will be able
to rm -r the full path.

This is against 2.1.72:

--- linux/fs/namei.c Wed Dec 10 14:54:54 1997
+++ /tmp/linux/fs/namei.c Wed Dec 10 15:38:25 1997
@@ -741,6 +741,9 @@
if (IS_ERR(dir))
goto exit_dput;

+ if ((error = d_validate_path(dentry)))
+ goto exit_lock;
+
error = -EEXIST;
if (dentry->d_inode)
goto exit_lock;
--- linux/fs/dcache.c Wed Dec 10 14:54:24 1997
+++ /tmp/linux/fs/dcache.c Wed Dec 10 15:38:25 1997
@@ -13,6 +13,12 @@
* the dcache entry is deleted or garbage collected.
*/

+/*
+ * Added "d_validate_path()" to check dentry full pathname length in order
+ * to avoid the creation of pathnames that can' t be deleted.
+ * by Andrea Arcangeli
+ */
+
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/fs.h>
@@ -742,6 +748,34 @@
dentry = parent;
}
return retval;
+}
+
+/*
+ * Check if the dentry is placed in a reachable pathname. We assume that
+ * the max full pathname length is PAGE_SIZE as defined in do_getname().
+ */
+int d_validate_path(struct dentry *dentry)
+{
+ struct dentry * root = current->fs->root;
+ int buflen = PAGE_SIZE - 1;
+
+ for (;;) {
+ struct dentry * parent;
+ int namelen;
+
+ if (dentry == root)
+ break;
+ dentry = dentry->d_covers;
+ parent = dentry->d_parent;
+ if (dentry == parent)
+ break;
+ namelen = dentry->d_name.len;
+ buflen -= namelen + 1;
+ if (buflen < 0)
+ return(-ENAMETOOLONG);
+ dentry = parent;
+ }
+ return 0;
}

__initfunc(void dcache_init(void))
--- linux/include/linux/dcache.h Wed Dec 10 14:54:37 1997
+++ /tmp/linux/include/linux/dcache.h Wed Dec 10 15:38:25 1997
@@ -153,6 +153,9 @@
/* write full pathname into buffer and return start of pathname */
extern char * d_path(struct dentry * entry, char * buf, int buflen);

+/* check for valid dentry pathnames */
+extern int d_validate_path(struct dentry * entry);
+
/* Allocation counts.. */
static __inline__ struct dentry * dget(struct dentry *dentry)
{

Andrea[s] Arcangeli