From 487313dde283a4f8d1890d9d23dc45e481d68dbf Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 5 May 2002 19:19:51 +0000 Subject: 2002-05-05 Roland McGrath * fakeroot.c (netfs_attempt_lookup): Unlock DIR before doing RPCs. --- trans/fakeroot.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'trans/fakeroot.c') diff --git a/trans/fakeroot.c b/trans/fakeroot.c index 0eb514a9..3592d720 100644 --- a/trans/fakeroot.c +++ b/trans/fakeroot.c @@ -324,23 +324,32 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir, char *name, struct node **np) { error_t err; - int flags = O_RDWR|O_EXEC; - file_t file = file_name_lookup_under (dir->nn->file, name, - flags | O_NOLINK, 0); + int flags; + const file_t dirfile = dir->nn->file; + file_t file; + + /* We must unlock the directory before making RPCs to the underlying + filesystem in case they somehow wind up trying to refer back to one of + our nodes. The DIRFILE port will not change or die as long as DIR + lives, and our caller holds a reference keeping it alive. */ + mutex_unlock (&dir->lock); + + flags = O_RDWR|O_EXEC; + file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0); if (file == MACH_PORT_NULL && errno == EACCES) { flags = O_RDWR; - file = file_name_lookup_under (dir->nn->file, name, flags | O_NOLINK, 0); + file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0); } if (file == MACH_PORT_NULL && errno == EACCES) { flags = O_READ|O_EXEC; - file = file_name_lookup_under (dir->nn->file, name, flags | O_NOLINK, 0); + file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0); } if (file == MACH_PORT_NULL && errno == EACCES) { flags = O_READ; - file = file_name_lookup_under (dir->nn->file, name, flags | O_NOLINK, 0); + file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0); } *np = 0; if (file == MACH_PORT_NULL) @@ -372,7 +381,7 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir, } } } - mutex_unlock (&dir->lock); + if (*np) mutex_lock (&(*np)->lock); return err; -- cgit v1.2.3