cap_capable() has a special case for the owner of a user namespace. A task in the parent namespace whose euid is the uid that created the namespace has every capability over it. That makes a uid the authority over whatever the namespace owns. The authority over a cell is the cellfd, not a uid. Skip the special case for the user namespace of a cell. A capability that a task holds in an ancestor user namespace still applies to the cell. Signed-off-by: Josef Bacik --- security/commoncap.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/security/commoncap.c b/security/commoncap.c index d47ab3022343..8af343c78d35 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -3,6 +3,7 @@ */ #include +#include #include #include #include @@ -90,9 +91,11 @@ static inline int cap_capable_helper(const struct cred *cred, /* * The owner of the user namespace in the parent of the - * user namespace has all caps. + * user namespace has all caps. Not over a cell: authority + * over a cell is a handle, not a uid. */ - if ((ns->parent == cred_ns) && uid_eq(ns->owner, cred->euid)) + if ((ns->parent == cred_ns) && uid_eq(ns->owner, cred->euid) && + !userns_is_cell(ns)) return 0; /* -- 2.55.0