Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 Oct 1996 11:45:02 -0700 (MST)
From:      Terry Lambert <terry@lambert.org>
To:        graphix@iastate.edu
Cc:        hackers@FreeBSD.org
Subject:   Re: new filesystem
Message-ID:  <199610181845.LAA01719@phaeton.artisoft.com>
In-Reply-To: <9610180215.AA12203@spiff.cc.iastate.edu> from "Kent Vander Velden" at Oct 17, 96 09:15:41 pm

next in thread | previous in thread | raw e-mail | index | archive | help
Well, despite Poul's attempted throttleing, FS hackers should be
encouraged (even if I'm not one of the people who gets encouraged),
so here is a longer than 10 line response.


>   For a computer security class project I would like to implement the
> BPL security model in a filesystem and am looking for a hint as to where
> to begin.
> 
>   The BPL model uses classifications, compartments and a few simple
> rules to determine if a user can access the files.  Users and files
> have classifications placed on them as well as belonging in
> compartments.  At the moment I am thinking that for the project that I
> could get by with an extra 64 bits of information per file.  Perhaps
> 10 bits for classification and the remainder for compartment.

Look at /sys/ufs/ufs/dinode.h.  This file contains the on disk inode
structure used by both FFS and LFS.

At the end of the structure is an filed called di_spare; it is 64 bits
in length, and can be used for what you want.

This is the filed you referenced in your doc, but I'd like to confirm
that it's OK to use it if you have ytour own FS.

You will need to decide whether you want this to be an experimental,
or a permananent feature of the OS.

If you want this to be a permanenet feature of the OS, you will need
to either duplicated the ffs or lfs or mfs code portion of the tree
into another area of the tree.  I suggest "/sys/ufs/bplfs", if you
go this route.

To make the job easier, I suggest you start with the ffs code.  The
lfs code will have you fighting two batlles at once.  Without Margo's
changes, the Lite2 changes, and my changes, it will be an uphill battle.
Doing the integration would probably be harder than your initial
project definition.

If, on the other hand, this is just experimental, then you can probably
get by with #ifdef's in your local ffs code and a mount option to the
ffs mount.  If you go this route, then you should place the mount option
changes in /sys/ufs/ffs/ffs_vfsops.c, in the mount code.  You will
probably need to reserve bits in the incore file system structure,
"struct fs".  This structure is defined in /sys/ufs/ffs/fs.h.

In either case, it's *VERY* important that you change your FS's "magic"
number.  You can either "hack" mkfs, or use a binary editor on an ffs
mkfs'ed partition to put the new magic number on the disk.

It would be much easier for you to implement the "experimental" version
of a modified ffs (and a modified mount to pass the flag parameter to
indicate a BPL mount).  This is because the ffs code contains the
embedded string "ffs" all over the pace, and is self-referential.  This
is actaully a violation of the reuse abstraction in the Heidemann master's
thesis, but was apparantly a "rush to market" compromise put together
by CSRG following the USL/UCB lawsuit settlement.  It unfortunately
damages your ability to "just reuse" the code simply, without a lot
of function and variable name hacking.

Note that if you reserve bits here, you will need to make sure that
the mount, when it compares the superblocks to determine if the FS
is corrupt, does not compare the areas which you are now using.  This
will require a change to fsck, as well, since by default fsck will
compare and bail when unused fields do not match (this is intentional
for versionioning).


>   "The Design and Implementation of the 4.4 BSD OS" talks about using
> the nullfs as a starting place for a new filesystem or a layer but I am
> not completely certain that this is the best choice in this case.
> Perhaps the extra information could be handled at the vnode level
> instead of the inode level...
> 
>   I am curious what others more experienced feel would be the best way to
> do this.  I would like to minimize the impact that my changes have on
> the actual kernel of course.

You probably *do NOT* want to use the stacking architecture for this
change.  The problem with stacking a security layer on top of an FS
is that if the FS is a presentation export layer itself, rather than
simply a block store mechanism, it would be possible to mount without
the security layer, and defeat the security.  This is a generic problem
with their being no commonly defined "bottom end" block interface; the
FS bottom end is not the same as the FS top end for FS's which consume
direct storage services (this is where most of the VM complications lie,
as well).

This is because the default is not "deny without intervention of an
upper (credential enforcement) layer".


Note the current VFS framework does not allow additional routines
to be added to the list of VOP's for a new FS without compiling and
rebuilding all existing FS's.

Because of this flaw (in /sys/kern/vfs_init.c and in the generated files
/sys/compile/*/vnode_if.c created by "config"), it is likely that you
will want to avoid using an extended VOP set to control your extension
data (ie: don't add your own VOP_ calls if you can avoid it).

Instead, I suggest you modify the VOP_IOCTL() to take arguments to
configure your FS.

For security reasons, you should check the incoming credentials to
ensure that the call is being made by the superuser (in the general
interface for a non-device FS, like devfs or specfs, the VOP_IOCTL
is defined to return ENOTTY -- for non-root, you should return ENOTTY).

For the system call interface for the control interface, I assume you
will want to allow users to manipulate their own files.

Toward this end, the control structure you pass down to the ffs_ioctl()
code from the VOP_IOCTL() caller should be larger than the required
structure to add credential information for the user.

Then, when you implement the system call, you can load the parameters,
and the real credentials, and then call the VOP_IOCTL() interface with
the superuser credentials.  This mesches nicely with the superuser
check, and only allows the superuser or the owner to manipulate the
fields.

Additionally, it allows you to enforce against the superuser (if you
wanted to do so).  This is a standard "cover channel" technique which
you might find useful.  Alternately, it will let you test your code
from user space by making calls on any open fd to get a vnode in your
fs to get down to your FS to do a manipulation there.  So you can fill
out the credential fields and call down using a user space utility
(as root) to test your interfaces, before you go to work adding a
system call.

Another note on using vnodes to get to specific FS routines: if I make an
ioctl(0 call on an fd that is an open file or directory on my FS, then
it will call my own *_ioctl(0 routine with the vnode as a paramenter.
If I want, I can then use additional parameters to the ioctl(), for
instance a path name, reeenter myself for the path lookup, and actually
operate on another vnode than the one that got me to the FS.

This means that I can use the mount point (or from user space, an fd
for the directory where the FS is mounted) to get me to the FS I want
to perform the operation on, even if I'm not going to do anything to
the mount point itself.


Unfortunately, the best reference right now is the code; I'd write
something up, if all my time weren't spent maintaining my diffs against
-current for my own research (internationalization, multiple name
space support, Unicode support, and soft updates, etc.).

Let me know if you need additional help with anything; I'll give you
information when and where I can.


					Regards,
					Terry Lambert
					terry@lambert.org
---
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?199610181845.LAA01719>