[PATCH] Oopsable bug in __prefix_lookup_dentry() on mips and sparc*

Alexander Viro (viro@math.psu.edu)
Wed, 9 Jun 1999 18:07:15 -0400 (EDT)


__mips_lookup_dentry() (and its relatives on sparc) pass
LOOKUP_SLASHOK to lookup_dentry(). It has no effect unless
* /usr/gnuemul/ exist and
* /usr/gnuemul/{irix,sunos,solaris}/ doesn't.
Assume that it is the case. Now, any lookup on /foo will give an oops:
1) we are calling lookup_dentry("/foo", whatever, whatever).
name == "/foo".
2) we see that *name=='/'. Trimming the leading slashes leaves us
with name == "foo".
3) __prefix_lookup_dentry happens. It's a macro, expanding to
dentry = __mips_lookup_dentry(name, lookup_flags);
if (!IS_ERR(dentry)) return dentry;
4) we are calling __mips_lookup_dentry("foo", whatever); which does
base = lookup_dentry("usr/gnuemul/irix/", dget(current->fs->root),
LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_SLASHOK);
if (IS_ERR(base)) return base;
base = lookup_dentry(name, base, lookup_flags);
5) First lookup_dentry gives us a negative dentry of /usr/gnuemul/irix
(if we didn't pass LOOKUP_SLASHOK we would get ERR_PTR(-ENOENT);)
and we are calling lookup_dentry("foo", negative_dentry, whatever);
6) ... which calls permission(NULL, MAY_EXEC). Oops.

Proposed fix: remove LOOKUP_SLASHOK from the __mips_lookup_dentry().

Results:

* If the process is not running with PER_IRIX32 - no changes, relevant
call never happens.
* If /usr/gnuemul/irix exists or is unreachable - no changes,
LOOKUP_SLASHOK has no effect.
* If the name doesn't start from / - no changes, relevant call never
happens.
* If the name consists of several slashes - new variant will give us the
root, current one gives the (negative) dentry of /usr/gnuemul/irix.
* If the name consists of several slashes followed by something else - new
variant will give us expected result (lookup of the rest of name from
root), current one gives an oops.

In other words, removing LOOKUP_SLASHOK from __mips_lookup_dentry() is the
right thing - in all cases when it changes behaviour of lookup_dentry()
it fixes a bug.

The same applies to __sparc_lookup_dentry() and __sparc64_lookup_dentry().

Patch follows:
diff -urN linux-2.3.6-pre2/include/asm-mips/namei.h linux-bird.misc/include/asm-mips/namei.h
--- linux-2.3.6-pre2/include/asm-mips/namei.h Thu May 13 07:03:14 1999
+++ linux-bird.misc/include/asm-mips/namei.h Wed Jun 9 18:00:02 1999
@@ -23,7 +23,7 @@

base = lookup_dentry (IRIX32_EMUL,
dget (current->fs->root),
- (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
+ (LOOKUP_FOLLOW | LOOKUP_DIRECTORY));

if (IS_ERR (base)) return base;

diff -urN linux-2.3.6-pre2/include/asm-sparc/namei.h linux-bird.misc/include/asm-sparc/namei.h
--- linux-2.3.6-pre2/include/asm-sparc/namei.h Thu May 13 07:03:18 1999
+++ linux-bird.misc/include/asm-sparc/namei.h Wed Jun 9 18:00:42 1999
@@ -28,7 +28,7 @@

base = lookup_dentry (emul,
dget (current->fs->root),
- (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
+ (LOOKUP_FOLLOW | LOOKUP_DIRECTORY));

if (IS_ERR (base)) return NULL;

diff -urN linux-2.3.6-pre2/include/asm-sparc64/namei.h linux-bird.misc/include/asm-sparc64/namei.h
--- linux-2.3.6-pre2/include/asm-sparc64/namei.h Thu May 13 07:03:20 1999
+++ linux-bird.misc/include/asm-sparc64/namei.h Wed Jun 9 18:01:24 1999
@@ -28,7 +28,7 @@

base = lookup_dentry (emul,
dget (current->fs->root),
- (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
+ (LOOKUP_FOLLOW | LOOKUP_DIRECTORY));

if (IS_ERR (base)) return NULL;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/