embedded tripwire (fs white paper)

Bear Giles (bear@coyotesong.com)
Sat, 2 Oct 1999 10:24:35 -0600 (MDT)


The recent discussion on ACLs prompts me to write the following
informal white paper. ("green paper"?)

"Embedded Tripwire" in Linux Filesystems

With minor changes, it is now possible to "embed" limited tripwire
support into Linux filesystems under the internationalized kernel.
(We only require the "digest" functions from the i-kernel.) The
basic mechanism is

CREATION:

- creat() a new file. creat sets an internal flag which indicates
that this is a new file.
- write() data into the file
- ioctl()? set extended attributes to include TRIPWIRE. This
attribute should only be permitted on new files.
- close() the file. Use fs-defined digest functions to compute
several strong checksums and store them as extended attributes.

In practice, the TRIPWIRE and IMMUTABLE flags will typically be
used together. Even if the flags are kept distinct, it might
be best for TRIPWIRE to forcefully clear any write permissions.

USE:

- open() an existing file. If the TRIPWIRE extended attribute is
set the file is scanned and the checksums compared. If the
checksums match, everything proceeds as before. If the checksums
do not match, one of four conditions hold:

- the secure level is zero, the file is opened as before.

- the secure level is non-zero or the STRICT_TRIPWIRE flag is
set on the open, the file is not opened and a new error
status is returned, ECHKSM

- the IGNORE_TRIPWIRE flag is set on the open and the securelevel
is less than 0 or 1, the file is opened as before.

- the IGNORE_TRIPWIRE flag is set on the open and the securelevel
is 2 or more, the file is not opened and a new error status
is returned, CHKSM.

- close() the file. The checksums are never changed. (To modify
a checksummed file you must copy it, modify the copy, then remove
the original and replace it with the copy.)

This is a minimal system. One or two additional file_operations
can also be productively used:

ssize_t (*digest) (struct dentry *d, int digest_id, char *digest, size_t cnt)

int (*verify_digest) (struct dentry *d, int digest_id)

The first operation computes the specified digest and returns it in the
specified buffer. This operation can be implemented immediately without
change to any file system.

The second operation computes the specified digest and compares the results
with those cached upon file creation. The return code indicates success,
failure, unknown digest and uncached digest. This requires extensive
changes to the file sytem for the non-trivial handler.

There are two significant benefits to these functions:

1) they eliminate the need to copy the file contents into user space,
so they will always be more efficient than user space equivalents.

2) since the file contents are never copied into user space, it is
practical to relax the permissions on these functions. In fact, it's
not unreasonable to provide file digests in any situation where you
would provide attributes for a non-special device. This, in turn,
allows a program like tripwire to run without root permission.

The devil is definitely in the details in this proposal. Is the cost
of potential DoS worth the benefits of never running a compromised program?
Because of these details I don't expect this proposal to appear in the
2.4 kernel as anything other than a "highly experimental" option.

Bear Giles
bgiles@coyotesong.com

-
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/