dir: fileserver leaks names of file and directories 58/12458/3
authorMark Vitale <mvitale@sinenomine.net>
Fri, 13 May 2016 04:01:31 +0000 (00:01 -0400)
committerBenjamin Kaduk <kaduk@mit.edu>
Wed, 30 Nov 2016 16:43:51 +0000 (11:43 -0500)
Summary:
Due to incomplete initialization or clearing of reused memory,
fileserver directory objects are likely to contain "dead" directory
entry information.  These extraneous entries are not active - that is,
they are logically invisible to the fileserver and client.  However,
they are physically visible on the fileserver vice partition, on the
wire in FetchData replies, and on the client cache partition.  This
constitutes a leak of directory information.

Characterization:
There are three different kinds of "dead" residual directory entry
leaks, each with a different cause:

1. There may be partial name data after the null terminator in a live
directory entry.   This happens when a previously used directory entry
becomes free, then is reused for a directory entry with a shorter name.
This may be addressed in a future commit.

2. "Dead" directory entries are left uncleared after an object is
deleted or renamed.  This may be addressed in a future commit.

3. Residual directory entries may be inadvertently picked up when a new
directory is created or an existing directory is extended by a 2kiBi
page.  This is the most severe problem and is addressed by this commit.

This third kind of leak is the most severe because the leaked
directory information may be from _any_ other directory residing on the
fileserver, even if the current user is not authorized to see that
directory.

Root cause:
The fileserver's directory/buffer package shares a pool of directory
page buffers among all fileserver threads for both directory reads and
directory writes.  When the fileserver creates a new directory or
extends an existing one, it uses any available unlocked buffer in the
pool.  This buffer is likely to contain another directory page recently
read or written by the fileserver.  Unfortunately the fileserver only
initializes the page header fields (and the first two "dot" and "dotdot"
entries in the case of a new directory).  Any residual entries in the
rest of the directory page are now logically "dead", but still
physically present in the directory.  They can easily be seen on the
vice partition, on the wire in a FetchData reply, and on the cache
partition.

Note:
The directory/buffer package used by the fileserver is also used by the
salvager and the volserver.  Therefore, salvager activity may also leak
directory information to a certain extent.   The volserver vos split
command may also contribute to leaks.  Any volserver operation that
creates volumes (create, move, copy, restore, release) may also have
insignificant leaks.  These less significant leaks are addressed by this
commit as well.

Exploits:
Any AFS user authorized to read directories may passively exploit this
leak by capturing wire traffic or examining his local cache as he/she
performs authorized reads on existing directories.  Any leaked data will
be for other directories the fileserver had in the buffer pool at the
time the authorized directories were created or extended.

Any AFS user authorized to write a new directory may actively exploit
this leak by creating a new directory, flushing cache, then re-reading
the newly created directory.  Any leaked data will be for other
directories the fileserver had in the buffer pool within the last few
seconds.  In this way an authorized user may sample current fileserver
directory buffer contents for as long as he/she desires, without being
detected.

Directories already containing leaked data may themselves be leaked,
leading to multiple layers of leaked data propagating with every new or
extended directory.

The names of files and directories are the most obvious source of
information in this leak, but the FID vnode and uniqueid are leaked as
well.  Careful examination of the sequences of leaked vnode numbers and
uniqueids may allow an attacker to:
- Discern each layer of old directories by observing breaks in
  consecutive runs of vnode and/or uniqueid numbers.
- Infer which objects may reside on the same volume.
- Discover the order in which objects were created (vnode) or modified
  (uniqueid).
- Know whether an object is a file (even vnode) or a directory (odd
  vnode).

Prevent new leaks by always clearing a pool buffer before using it to
create or extend a directory.

Existing leaks on the fileserver vice partitions may be addressed in a
future commit.

Change-Id: Ia980ada6a2b1b2fd473ffc71e9fd38255393b352
Reviewed-on: https://gerrit.openafs.org/12458
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Tested-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>

src/dir/buffer.c

index 889f07e..1a8da8f 100644 (file)
@@ -313,6 +313,7 @@ newslot(dir_file_t dir, afs_int32 apage, struct buffer *lp)
     /* Now fill in the header. */
     FidZap(bufferDir(lp));
     FidCpy(bufferDir(lp), dir);        /* set this */
+    memset(lp->data, 0, BUFFER_PAGE_SIZE);  /* Don't leak stale data. */
     lp->page = apage;
     lp->accesstime = ++timecounter;