On Mon, Aug 18, 2003 at 03:19:39PM -0700, Crispin Cowan wrote: > Michael Halcrow wrote: > > >On Mon, Aug 18, 2003 at 11:16:36AM -0700, Seth Arnold wrote: > > > > > >>I guess I don't understand your security goals. > >> > >> > >Perhaps I should have made myself more clear on this. I want to > >implement BSD Secure Levels as an LSM. > > > >I want my policies to be enforced whenever I am in a secure level > >greater than or equal to 1, except when an atomic shutdown operation > >is taking place. That is, once the security has been relaxed to allow > >shutdown-related operations, an attacker cannot stop or otherwise > >hijack the shutdown process to obtain unauthorized control. > > > I still don't understand the goal, but that's because I never understood > the idea behind BSD Secure Levels. The target user for the Secure Levels LSM is the administrator who is already familiar with BSD secure levels, who wants to pop a module in and get equivalent functionality. Anything more complicated than that aims beyond the mark. > The pseudo code you provided doesn't > help, because I don't understand the implicit semantics of the > seclvl_capable function. The seclvl_capable function implements the capable function pointer in the security_operations struct. It takes as parameters a pointer to the task struct of the task requesting authorization for an operation and a capability bitfield (cap). At various placed in the kernel, there exist checks like so: if( !capable( CAP_NET_ADMIN ) ) { return -EACCES; } or: if( !capable( CAP_SYS_RAWIO ) ) { return -EACCES; } These will (eventually) call whatever function that is pointed to in the security_operations struct element ``capability.'' To find out which capability is being checked in the kernel, that function has logic like the following: if( cap & CAP_NET_ADMIN ) { // Verify conditions where an administrative network operation would // be allowed // Return 0 if allowed, -EXXX otherwise } else if( cap & CAP_SYS_RAWIO ) { // Verify conditions where a raw I/O operation would be allowed // Return 0 if allowed, -EXXX otherwise } The sementics may be along the lines of, ``Task `T' is requesting the capability `C' to perform some action, but I am not going to tell you exactly which action that is.'' All the capability function knows is the class of action to be authorized. Obviously, this model leaves something to be desired, but it seems to be the most straightforward approach to implementing BSD Secure Levels. While we're on the subject, I would actually make one modification to the capabilities implementation in the kernel. I would include in the capability.h header file a section with #define's like so: #define CAP_NET_ADMIN_ALTER_ARP_TABLE 1 #define CAP_NET_ADMIN_DELETE_ROUTE_TABLE_ENTRY 2 ... Or, perhaps another mechanism for defining these values would be better suited. Let's just run with this for now. Then I would have a global variable cap_action, which could be optionally set before the if( !capable(...) ) statement in the kernel. Of course, we may need to include locking protection for this sort of thing, but I would have to look a little closer to know for sure (an optional third argument to capable() might be in order). This would allow the policy enforced by the capable() function to be (optionally) aware of the specific action being authorized, in addition to the class of action being authorized. Then the capable function logic would either be unchanged, or it might also look more like: if( cap & CAP_SYS_ADMIN ) { switch( cap_action ) { case CAP_SYS_ADMIN_ROTATE_POD: // Even though the default policy is to authorize, I am // explicitely authorizing this action here to remove any // ambiguity. return 0; break; case CAP_SYS_ADMIN_OPEN_BAY_DOORS: if( model == HAL_9000 && intent == SHUTDOWN ) { printk( KERN_ERR "I'm sorry, Dave, I'm afraid I can't do that.\n" ); return -EPERM; break; default: // The default rule for this class of action: authorize. return 0; break; } } That way, everything currently in the kernel could be left alone, and those who wish to include support for specific actions could set the global variable accordingly. This might be a good compromise to avoid putting more hooks into the kernel while getting more granularity out of the hooks that are currently in there. If the global variable thing is too messy, then the capable() function definition could be altered to include an optional third argument (if that happens to be any less messy :-). > So, there you are in Secure Level 1 (or greater). You want to shut down. > The Secure Level thingie largely prevents Joe User from calling umount, > shutdown, & such nasties, and prevents Joe User from driving the Secure > Level below 1. It actually is designed to prevent the superuser from doing these things. It is designed to mitigate the potential damage of a root compromise. > Back to Seth's question: who or what is authorized to either shut the > machine down, or drive the Secure Level below 1 so that the machine can > be shut down? Whoever or whatever is authorized to do so in *BSD's implementation. If anyone knows the best answer to this, please don't hesitate to let me know. Meanwhile, I'm going to keep researching this. Mike -- ------------------------------------------- | --------------------- Michael Halcrow | mikeat_private Developer, IBM Linux Technology Center | | Want to make $$$$ really quick? It's easy: | Hold down Shift and hit '4' four times. | ------------------------------------------- | --------------------- GnuPG Keyprint: 05B5 08A8 713A 64C1 D35D 2371 2D3C FDDA 3EB6 601D
This archive was generated by hypermail 2b30 : Tue Aug 19 2003 - 07:49:59 PDT