No events planned
After weeks of reflecting and some discussions with other security developers and users, I have decided to throw Linux Security Modules (LSM) support out of the RSBAC code and return to the original hooks.
RSBAC has been ported to 2.6.0-test5 (just updated to -test7) as the current 1.2.3-pre1. The port uses LSM hooks, where available and applicable, and RSBAC hooks otherwise. Certainly, I might have misunderstood some code and could have argued with the LSM project about all these issues. On the other hand, the current RSBAC version would then probably be 1.2.0 or so. Please also read what other security projects say about LSM support: GrSecurity.
These items make LSM unacceptable for RSBAC:
The LSM security_ops array for RSBAC contains 32 decision and 5 notification entries, some of which are conditional. There are still 95 decision (rsbac_adf_request) and 39 notification (rsbac_adf_set_attr) calls left in the RSBAC patch. This means that only one quarter of the necessary decision hooks are provided by LSM, and even fewer notification hooks.
In order to use only LSM hooks for decision and notification, a real lot of additional hooks would have to be argued, written, verified and included into the official kernel code. I have neither time nor desire to do this. Also, I have read that some important hooks have already been rejected by major kernel maintainers, who are not willing to accept a small overhead for a lot more of security.
Even a big restructering of the RSBAC code would not help to add hooks that are plainly missing, e.g. control of network or firewall settings. Also, RSBAC needs system calls for administration - the once existing sys_security has even been removed, because some LSM modules can be administrated via /proc interface. I wonder what they do without /proc support.
LSM is only about additional, restrictive access control. However, the RSBAC system provides a lot of additional functionality, e.g. symlink redirection, secure_delete, partial Linux DAC disabling. All this has to be patched into kernel functions in a separate patch.
One can argue that all this is not essential, and so could be patched in as an optional addition. I hold against that it would cripple the whole RSBAC system.
LSM hooks export (expose) kernel internal data structures as parameters, from which all LSM modules have to extract their data. This is extremely dangerous, because a simple bug (like = instead of ==) can destabilize the whole system.
Additionally, kernel internal data structures tend to be changed quite frequently between releases - with every new kernel version, one has to check whether the items are used correctly and if the correct locks are held. All this leads to a mess of #ifdefs for the kernel version, instead of the IMHO very important independency of kernel versions.
The LSM design is not able to support more than one single decision module registration. Instead, a system of secondary registrations (”stacking”) has been introduced, which forms a call chain though all modules, until all have been called. Each module is responsible to forward the decision requests of all(!) hooks to its secondary module, and to combine its own and the secondary result to a return value.
With the stacking system, each registered decision module holds all others along the chain in its mercy. I am not willing to accept such a dependency on other modules. Furthermore, the need to supply forwarding for all hooks makes all code more LSM version dependent and unnecessarily complicates the decision code.
Once you have enabled LSM, you only get back Posix capabilities by another kernel config switch. This is not bad in itself, you can always have it on, but the capability implementation does not support LSM stacking - the usually fastest decision module will always have to be the last in the chain. This means that you cannot avoid Issue #4, if you want to have Posix capability support.
With RSBAC, every registered decision function is guaranteed to be called for every decision, unless an internal error occurs (return value UNDEFINED). This is important for logging and, specially, for notification and state update.
Those LSM modules I had a closer look at only forward requests, if they themselves allowed access. And, again, this is purely a decision of the module up in the chain. If it for some reason does not call its secondaries, too bad.
Since there will be need for a separate RSBAC patch for a long time to go, LSM support splits up the code. This means that it is more difficult to make sure that all interceptions are there exactly once, and it makes the code significantly less well structured.
As all LSM calls are stateless and do not transport additional data, the notification functions have to recalculate all decision relevant data, e.g. type and id of the object, which my original RSBAC hooks just keep from the decision call. Recalculation slows down the system. In worst case, the notification function works on different data from that of the decision.
Stateful decision modules require reliable knowledge, whether some system call functionality has been fully performed or stopped and reverted, so the notification calls may not be included in the decision calls to avoid this problem.
As far as I can see, supporting LSM requires a lot more work than my original hooks - despite the official LSM intention to make life easier for all access control extensions. Without significant advantages, I cannot see the point why I should invest all this extra work. without /proc support.
A few more personal remarks on recent events:
Back in the year 2000, the first common access control framework for all important then existing Linux kernel access control extensions was designed, people from LIDS, Medusa, SGI and RSBAC, as well as some other people, already solved most of these and some other important issues. Unfortunately, our design did not get the important impetus to prosper and died.
The LSM project, lead mostly by different people (who had also been invited to our previous discussion), felt itself bound to Linus’ order that security must not cost anything in performance, focused on single modules and, sorry to say that, mostly ignored the work done by the first approach.
The current official kernel includes only one(!) of the most important solutions, and, certainly purely accidentially, the current LSM specially meets this solution’s needs. I do not want to argue about political and market(ing) power, paying full-time developers and money, but I think that any integrated solution should at least have been called differently, without any hints on organizations outside the Linux community. Also, AFAIK, the solution now integrated includes US patented security models, which could at any time be activated to earn a lot of money after selling the patents.
Even if some of the issues were solved, I would still need more. And the whole hook design is broken, because all kernel data gets exposed to any module that likes to register - what an invitation to root kit authors. LSM is too low level and kernel version dependent, and it provides no support for more than one module. IMHO, the LSM project’s major fault is that it accepted Linus’ order what hooks should look like, regardless of known security principles.
I believe all this hurts the Linux project and makes it depend even more on commercial or political decisions of one single country - it should have been a Linux solution after all. In any case, I am going to continue work on RSBAC in the way I believe to be right and appropriate. If you think it should be different, convince me and we are back at the previous sentence...
It seems that LSM is about to be removed from the official kernel and SELinux allowed to have their individual hooks. Reason: All other LSM users live outside the official tree. Now I wonder why they have been outside the tree for so long.