On Thu, Sep 26, 2024 at 9:14 AM Stephen Smalley <stephen.smalley.work@xxxxxxxxx> wrote: > As I've been converting the permission checks to use namespace-aware > helpers, I've noted policy capabilities (as in network_peer_controls, > open_perms, extended_socket_class, always_check_network, etc) as a > case that isn't cleanly handled by my current approach. At present, > the hook functions are just checking the value of the policy > capability in the current SELinux namespace to decide which branch of > the hook function to follow, and then within whichever branch is > selected, each permission check that is converted to using > namespace-aware helpers is checking permissions against the current > and all ancestor namespaces. > > So for example, if the current namespace enables open permission, then > it will check open permission against the current namespace and all > ancestors, irrespective of whether the ancestor enabled that > capability or not. Similarly, if the current namespace disables open > permission, then it will NOT check open permission against any > namespaces, even if the ancestors enabled it. > > Lifting the logic to iterate through all of the namespaces up into > each hook function is possible but rather painful. That said, it may > be unavoidable if we want to support different policy capability > settings between child namespaces and their ancestors, or prevent > child namespaces from effectively disabling certain checks by > disabling those capabilities. > > If I were to go down that route, then I would also need to resolve how > to handle the non-permission checking logic in each hook across > multiple namespaces, e.g. labeling logic. Currently it is just > assigning SIDs/contexts to objects based on the current namespace, > then checking permissions against all namespaces with that > SID/context. But if each hook function has its body wrapped with the > same loop that currently exists inside the namespace-aware permission > checking functions to iterate through the namespaces, then we would > actually end up with multiple SIDs/contexts computed and need to > decide which one to use (or special case that part of the body to skip > doing so for anything but the first/current namespace). > > Thoughts? On 2nd thought, for hooks that don't depend on policy capabilities, I think the current approach is fine, and works for the majority of the hooks. For the subset of hooks that depend on policy capabilities, I will lift the logic where needed to ensure that we apply the right checks in each namespace based on that namespace's enabled policy capabilities. Labeling logic will still be based on the current SELinux namespace at the point where the kernel object is first created/instantiated, but permissions to that label will be checked in the current and ancestor namespaces. There are some potential gotchas there, e.g. a child namespace could load a policy that labels all objects it creates/instantiates with a context to which it has access, even overriding file xattrs by specifying something other than fs_use_xattr in its policy for the filesystem type. Some of the policy capabilities have effects other than changing which permissions are checked, e.g. extended_socket_class alters what security class is set in the security blob and later used in permission checks, so if a socket is created with that disabled in one namespace and accessed in another namespace, the permission checks might not be on the "correct" security class for the other namespace. Other policy capabilities affect labeling, e.g. cgroup_seclabel, genfs_seclabel_symlinks, userspace_initial_context, which likewise could lead to an object created and labeled in one namespace triggering permission checks against the "wrong" label if accessed in another namespace.