Linux Security Module listsecurity (and security xattr hooks) only one called?
Hello everyone, In security/security.c (see here:https://github.com/torval ds/linux/blob/835c92d43b29eb354abdbd5475308a474d7efdfa/security/security.c) Looking at this: int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) { if (unlikely(IS_PRIVATE(inode))) return 0; return call_int_hook(inode_listsecurity, 0, inode, buffer, buffer_size); } One would expect all stacked security module to be called. However, when looking at this: #define call_int_hook(FUNC, IRC, ...) ({ \ int RC = IRC; \ do { \ struct security_hook_list *P; \ \ list_for_each_entry(P, &security_hook_heads.FUNC, list) { \ RC = P->hook.FUNC(__VA_ARGS__); \ if (RC != 0) \ break; \ } \ } while (0); \ RC; \ }) If one of the module return a non-zero value, the other are not called. That means that the list of security of xattr is not built (or rather that it only contains the first module being called), as the lenght of inserted element is returned. Similarly for setsecurity and getsecurity, it seems that only one module will be called as if the given module does not support the security xattr, it returns -EOPNOTSUPP (instead I believe the next module being called, until one supporting the attribute is met). I am aware that LSM stacking is not fully supported yet: https://lwn.net/Articles/635771/ https://lwn.net/Articles/697259/ Here fix setsecurity and getsecurity: https://github. com/cschaufler/smack-next/blob/next/security/security.c; but listsecurity would appear to still not behave as I would expect. However, I may be missing something. What is the rational here? I could change the code to support multiple security xattr, but don't want to do so before I am sure I understand why it was done like this. Any help is welcome. Thanks. Thomas
On Tue, Sep 06, 2016 at 07:05:54AM -0400, Pasquier, Thomas wrote:
Hello everyone,
In security/security.c (see here:https://github.com/torvalds/linux/blob/ 835c92d43b29eb354abdbd5475308a474d7efdfa/security/security.c)
Looking at this:
int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) { if (unlikely(IS_PRIVATE(inode))) return 0; return call_int_hook(inode_listsecurity, 0, inode, buffer, buffer_size); } One would expect all stacked security module to be called. However, when looking at this:
#define call_int_hook(FUNC, IRC, ...) ({ \ int RC = IRC; \ do { \ struct security_hook_list *P; \ \ list_for_each_entry(P, &security_hook_heads.FUNC, list) { \ RC = P->hook.FUNC(__VA_ARGS__); \ if (RC != 0) \ break; \ } \ } while (0); \ RC; \ }) If one of the module return a non-zero value, the other are not called. That means that the list of security of xattr is not built (or rather that it only contains the first module being called), as the lenght of inserted element is returned. Similarly for setsecurity and getsecurity, it seems that only one module will be called as if the given module does not support the security xattr, it returns -EOPNOTSUPP (instead I believe the next module being called, until one supporting the attribute is met).
I am aware that LSM stacking is not fully supported yet: https://lwn.net/Articles/635771/ https://lwn.net/Articles/697259/
Here fix setsecurity and getsecurity: https://github.com/cschaufler/smack-next/ blob/next/security/security.c; but listsecurity would appear to still not behave as I would expect. However, I may be missing something.
What is the rational here? I could change the code to support multiple security xattr, but don't want to do so before I am sure I understand why it was done like this. Any help is welcome.
Why not ask on the linux-security mailing list where the developers of this code live? good luck! greg k-h
On Tue, 06 Sep 2016 07:05:54 -0400, "Pasquier, Thomas" said:
If one of the module return a non-zero value, the other are not called. That means that the list of security of xattr is not built (or rather that it only contains the first module being called), as the lenght of inserted
That's working as designed, and won't be changing. The LSM framework is designed as restrictive, not permissive. In other words. the exit can deny an access, but cannot allow an otherwise denies access. In other words, as soon as the access is denied by any one exit, there's no reason to bother calling other exits - we can short-circuit the evaluation of the list. Think of it as being logically: if (exit1 || exit2 || exit3 ||.. |exitN) return access_denied; The reason it won't change is because doing analysis of a security system that has parts that are both restrictive and permissive is almost impossible. Even trivial stacking can produce problems - consider 3 exits that all can either deny a request or force it to be allowed. Now think of the game of rock-paper-scissors.... And if you're playing rock-paper-scissors-lizard-Spock, it gets worse....
element is returned. Similarly for setsecurity and getsecurity, it seems that only one module will be called as if the given module does not support the security xattr, it returns -EOPNOTSUPP (instead I believe the next module being called, until one supporting the attribute is met).
That is because currently, there's only support for one stacked module that uses xattrs at a time.
What is the rational here? I could change the code to support multiple security xattr, but don't want to do so before I am sure I understand why it was done like this. Any help is welcome.
Compositing two or more security schemes complicated enough to need xattrs, and doing so in a secure manner, is a lot harder than it looks. You'd be amazed at the number of ways things can go pear-shaped when things start interacting... (See the challenges of beating the original POSIX capabilities into submission for inclusion. Turned out the POSIX draft had some very subtle bugs in the ruleset....) If you're interested in chasing it further, you should probably ask on the linux-security-module@vger.kernel.org list.
participants (3)
-
Greg KH -
Pasquier, Thomas -
Valdis.Kletnieks@vt.edu