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>