• Paul Moore's avatar
    lsm: fixup the inode xattr capability handling · 61df7b82
    Paul Moore authored
    The current security_inode_setxattr() and security_inode_removexattr()
    hooks rely on individual LSMs to either call into the associated
    capability hooks (cap_inode_setxattr() or cap_inode_removexattr()), or
    return a magic value of 1 to indicate that the LSM layer itself should
    perform the capability checks.  Unfortunately, with the default return
    value for these LSM hooks being 0, an individual LSM hook returning a
    1 will cause the LSM hook processing to exit early, potentially
    skipping a LSM.  Thankfully, with the exception of the BPF LSM, none
    of the LSMs which currently register inode xattr hooks should end up
    returning a value of 1, and in the BPF LSM case, with the BPF LSM hooks
    executing last there should be no real harm in stopping processing of
    the LSM hooks.  However, the reliance on the individual LSMs to either
    call the capability hooks themselves, or signal the LSM with a return
    value of 1, is fragile and relies on a specific set of LSMs being
    enabled.  This patch is an effort to resolve, or minimize, these
    issues.
    
    Before we discuss the solution, there are a few observations and
    considerations that we need to take into account:
    * BPF LSM registers an implementation for every LSM hook, and that
      implementation simply returns the hook's default return value, a
      0 in this case.  We want to ensure that the default BPF LSM behavior
      results in the capability checks being called.
    * SELinux and Smack do not expect the traditional capability checks
      to be applied to the xattrs that they "own".
    * SELinux and Smack are currently written in such a way that the
      xattr capability checks happen before any additional LSM specific
      access control checks.  SELinux does apply SELinux specific access
      controls to all xattrs, even those not "owned" by SELinux.
    * IMA and EVM also register xattr hooks but assume that the LSM layer
      and specific LSMs have already authorized the basic xattr operation.
    
    In order to ensure we perform the capability based access controls
    before the individual LSM access controls, perform only one capability
    access control check for each operation, and clarify the logic around
    applying the capability controls, we need a mechanism to determine if
    any of the enabled LSMs "own" a particular xattr and want to take
    responsibility for controlling access to that xattr.  The solution in
    this patch is to create a new LSM hook, 'inode_xattr_skipcap', that is
    not exported to the rest of the kernel via a security_XXX() function,
    but is used by the LSM layer to determine if a LSM wants to control
    access to a given xattr and avoid the traditional capability controls.
    Registering an inode_xattr_skipcap hook is optional, if a LSM declines
    to register an implementation, or uses an implementation that simply
    returns the default value (0), there is no effect as the LSM continues
    to enforce the capability based controls (unless another LSM takes
    ownership of the xattr).  If none of the LSMs signal that the
    capability checks should be skipped, the capability check is performed
    and if access is granted the individual LSM xattr access control hooks
    are executed, keeping with the DAC-before-LSM convention.
    
    Cc: stable@vger.kernel.org
    Acked-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
    Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
    61df7b82
smack_lsm.c 129 KB