On Tue, 30 Nov 2004 14:38:07 PST, Crispin Cowan said: > Right: stacking arbitrary security policies is intractable :) Amen. ;) > In a purely restrictive model, you can generalize the simple case of > "operation allowed if all modules allow it", but I don't believe you can > automate "A allows it if B is loaded/allows it/denies it/votes Republican". Fortunately for my sanity, most of the things I've wanted to stack can be categorized as either: 1) Another purely restrictive hook. 2) Another purely restrictive hook, but not needed if SELinux is active. (I'm still not sure how best to do (2) - although just wrapping the code in a '#ifndef CONFIG_SECURITY_SELINUX' and pushing appropriate policy upstream to the SELinux crew is a viable option.. ;) > Since I don't actually believe that stacking is all that useful in the > general case, I would actually rather have the permissive Capable hooks > than a powerful stacking composition capability. So what I would like to > see is: > > * keep the stacking mechanism as simple as possible, aiming at the > "allow if all modules allow" composition policy and not much else I'm fine on that - supporting only a purely restrictive composition is fairly sufficient for me, especially if we can use things like capabilities to implement (for instance) the 'realtime' LSM.. (Although I still think the 'realtime' LSM could equally well be addressed with support for set-capability binaries - more on that below) > * if there is a conflict between Capable and stacker, choose Capable I'd feel a lot better about Capable if we had a clear plan for killing CAP_SYS_ADMIN and fragmenting it into many little bits, within our lifetimes ;) I'm not sure how I feel about that particular conflict resolution - we'd have to be more specific about the calling order - would we: a) Call capable() first, and if it fails, then run the restrictive chain b) Call capable() first, and if it succeeds, run the restrictive chain c) call Capable(), run the chain, and return (capable || chain) d) Run the restrictive chain, and if it fails, call capable() as a last resort e) Run the restrictive chain, and if it succeeds, call capable() f) Run both, and return (chain || capable) (Note the slight semantic difference for the 'run both' and 'call second if first fails' cases - in one, we short-circuit, in the other we don't. This may matter for some chain entries that have side effects (saving state, etc). Also, how does this fit in with the current capabilities and Andy Lutomirsky's work on set-capability binaries (I remember some squirrelly corner cases in there)? Personally, I'd prefer a scenario where we first apply capabilities to create a possibly-larger-than-generic set of permissions, and then use a chain of strictly restrictive calls to limit it. So, for instance, you could make /usr/bin/ping have CAP_RAW_NETWORK so it starts off with the ability to send a raw packet, but then SELinux or any other restrictive LSM could deny the actual request. (And yes, I *know* there's subtle differences between this and using SELinux to restrict a set-UID-root binary..) Or did you have some other general direction to consider here?
This archive was generated by hypermail 2.1.3 : Wed Dec 01 2004 - 09:22:13 PST