Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Apr 95 15:27:12 MDT
From:      terry@cs.weber.edu (Terry Lambert)
To:        craig@munich.gcomm.com (Craig Yap)
Cc:        bugs@FreeBSD.org
Subject:   Re: seekdir bug
Message-ID:  <9504122127.AA19075@cs.weber.edu>
In-Reply-To: <199504121348.JAA27823@munich.gcomm.com> from "Craig Yap" at Apr 12, 95 09:48:27 am

next in thread | previous in thread | raw e-mail | index | archive | help
> There is a bug when seeking through a directory.  telldir() seems to return
> a position in the directory that doesnt match the name of the file.  I've
> included a program that will exploit the bug.  I ran it as followed:

[ ... seekdir after close then reopen of dir ... ]

If there is a bug, it's in the man page.  Here's what the Sun man page
has to say:

    seekdir() sets the position of the next readdir()  operation
         on  the  directory  stream.  The new position reverts to the
         one associated with the directory stream when the  telldir()
         operation  was  performed.  Values returned by telldir() are
         good only for the lifetime of the  DIR  pointer  from  which
         they  are  derived.   If  the  directory  is closed and then
         reopened, the telldir() value  may  be  invalidated  due  to
         undetected directory compaction.  It is safe to use a previ-
         ous telldir() value immediately after a  call  to  opendir()
         and before any calls to readdir.

Admittedly, no compation is taking place in your use of the code, at
least not from the code itself.


The main problem is that telldir/seekdir imply the ability to save
state across opens; in reality, they are abominations, and their use
is to be frowned upon.


The way directory entries are returned in the opendir is through the
use of the internal system call getdents() which is supposed to
return an atomic block of directory entries (an atomic block being
defined as a block of data wherin changes to the data will not span
a block boundry).  In other words, getdents() takes a snapshot that
is guranteed to be consistant for an external observer.

Then the readdir/telldir operations operate on the user space copy
of the block.  The telldir() returns an offset which is not supposed
to be a seek offset in the file itself, but a block/offset_into_block
combination.  A lot of the current code assumes that it is an actual
file offset -- this is bogus, since POSIX does not guarantee that
directories are themselves represented via a file abstraction in
the first place (it just so happens that for the majority of UNIX
file systems that they are).


So the first problem is that you are violating the usage protocol, and
the second problem is that you are doing so with an interface that
doesn't guarantee atomicity for lookup and directory modification
operations.


					Terry Lambert
					terry@cs.weber.edu
---
Any opinions in this posting are my own and not those of my present
or previous employers.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9504122127.AA19075>