lsm/stable-6.11 PR 20240715

-----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmaVT+gUHHBhdWxAcGF1
 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXPr0BAA1JDxr3dcRnylZgQYy9LU9fIbqPhH
 OnV3LsPvuH+dQujluKqjOSaHpxx5EM/DZ+Heot59eY81S/shYnkEg2Z7TvvCAqBD
 2rNjufU4wwisU1RgCTCXMdQ5qgtX+ya5p93Q0r1zRRzkE7qcEZxIbxuN/yRotgiF
 ie5FFA5tk7bEwt4MKCqlvfn8p6yu+YZNLINHcBmOYVVlBd1BPoOlK0TlvT4p/dtM
 z9RSnpuu52HU35w5UJ0hj5I9i/M1LH6cPID5/Uj2/PXVPJkw5FMwNLPGgKVpmswm
 PQZQPsSC7+eKlNLmI98BAfQfYgdk0yShKQkQgnJ1UfZkSx/scLLY/kr7LrbzkOkN
 KI5jhCFsQibQ4CWuOD4mjSJJZCIyKj6TPzXTq0meEAePblnoyAVWO6sUP71tCtFn
 503a3a/kDpvRqv5BRqjOQsxvLTjPHkZCDfZMTnlSU0+U3Ww/gbcnXmkHh9HdUdgQ
 qkyWJmfgiIk2V0aebXchDTxCT3qclvLisxcCJSZm/9EQkc6xKWIQE/YPa4y4UGdk
 tI2U8nKwGimEU4oi6dP3DBYFZc3RNBB3iF+iIveHX2k5+TBqNvESYCN6wRY/TBBb
 TMFjEYyYDEBwvJhzNxioVuJ7u1gxc3EUMfwQPmuJk2oUFEWxbWXucdGeBbpkddrV
 wbUjT9FTVOcS9b0=
 =w5mj
 -----END PGP SIGNATURE-----

Merge tag 'lsm-pr-20240715' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm

Pull lsm updates from Paul Moore:
 "Two LSM patches focused on cleaning up the inode xattr capability
  handling"

* tag 'lsm-pr-20240715' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm:
  selinux,smack: remove the capability checks in the removexattr hooks
  lsm: fixup the inode xattr capability handling
This commit is contained in:
Linus Torvalds 2024-07-16 14:50:44 -07:00
commit 11ab4cd5ec
4 changed files with 101 additions and 42 deletions

View File

@ -144,6 +144,7 @@ LSM_HOOK(int, 0, inode_setattr, struct mnt_idmap *idmap, struct dentry *dentry,
LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, struct mnt_idmap *idmap,
struct dentry *dentry, int ia_valid)
LSM_HOOK(int, 0, inode_getattr, const struct path *path)
LSM_HOOK(int, 0, inode_xattr_skipcap, const char *name)
LSM_HOOK(int, 0, inode_setxattr, struct mnt_idmap *idmap,
struct dentry *dentry, const char *name, const void *value,
size_t size, int flags)

View File

@ -2278,7 +2278,20 @@ int security_inode_getattr(const struct path *path)
* @size: size of xattr value
* @flags: flags
*
* Check permission before setting the extended attributes.
* This hook performs the desired permission checks before setting the extended
* attributes (xattrs) on @dentry. It is important to note that we have some
* additional logic before the main LSM implementation calls to detect if we
* need to perform an additional capability check at the LSM layer.
*
* Normally we enforce a capability check prior to executing the various LSM
* hook implementations, but if a LSM wants to avoid this capability check,
* it can register a 'inode_xattr_skipcap' hook and return a value of 1 for
* xattrs that it wants to avoid the capability check, leaving the LSM fully
* responsible for enforcing the access control for the specific xattr. If all
* of the enabled LSMs refrain from registering a 'inode_xattr_skipcap' hook,
* or return a 0 (the default return value), the capability check is still
* performed. If no 'inode_xattr_skipcap' hooks are registered the capability
* check is performed.
*
* Return: Returns 0 if permission is granted.
*/
@ -2286,20 +2299,20 @@ int security_inode_setxattr(struct mnt_idmap *idmap,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
int ret;
int rc;
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
/*
* SELinux and Smack integrate the cap call,
* so assume that all LSMs supplying this call do so.
*/
ret = call_int_hook(inode_setxattr, idmap, dentry, name, value, size,
flags);
if (ret == 1)
ret = cap_inode_setxattr(dentry, name, value, size, flags);
return ret;
/* enforce the capability checks at the lsm layer, if needed */
if (!call_int_hook(inode_xattr_skipcap, name)) {
rc = cap_inode_setxattr(dentry, name, value, size, flags);
if (rc)
return rc;
}
return call_int_hook(inode_setxattr, idmap, dentry, name, value, size,
flags);
}
/**
@ -2452,26 +2465,39 @@ int security_inode_listxattr(struct dentry *dentry)
* @dentry: file
* @name: xattr name
*
* Check permission before removing the extended attribute identified by @name
* for @dentry.
* This hook performs the desired permission checks before setting the extended
* attributes (xattrs) on @dentry. It is important to note that we have some
* additional logic before the main LSM implementation calls to detect if we
* need to perform an additional capability check at the LSM layer.
*
* Normally we enforce a capability check prior to executing the various LSM
* hook implementations, but if a LSM wants to avoid this capability check,
* it can register a 'inode_xattr_skipcap' hook and return a value of 1 for
* xattrs that it wants to avoid the capability check, leaving the LSM fully
* responsible for enforcing the access control for the specific xattr. If all
* of the enabled LSMs refrain from registering a 'inode_xattr_skipcap' hook,
* or return a 0 (the default return value), the capability check is still
* performed. If no 'inode_xattr_skipcap' hooks are registered the capability
* check is performed.
*
* Return: Returns 0 if permission is granted.
*/
int security_inode_removexattr(struct mnt_idmap *idmap,
struct dentry *dentry, const char *name)
{
int ret;
int rc;
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
/*
* SELinux and Smack integrate the cap call,
* so assume that all LSMs supplying this call do so.
*/
ret = call_int_hook(inode_removexattr, idmap, dentry, name);
if (ret == 1)
ret = cap_inode_removexattr(idmap, dentry, name);
return ret;
/* enforce the capability checks at the lsm layer, if needed */
if (!call_int_hook(inode_xattr_skipcap, name)) {
rc = cap_inode_removexattr(idmap, dentry, name);
if (rc)
return rc;
}
return call_int_hook(inode_removexattr, idmap, dentry, name);
}
/**

View File

@ -3177,6 +3177,23 @@ static bool has_cap_mac_admin(bool audit)
return true;
}
/**
* selinux_inode_xattr_skipcap - Skip the xattr capability checks?
* @name: name of the xattr
*
* Returns 1 to indicate that SELinux "owns" the access control rights to xattrs
* named @name; the LSM layer should avoid enforcing any traditional
* capability based access controls on this xattr. Returns 0 to indicate that
* SELinux does not "own" the access control rights to xattrs named @name and is
* deferring to the LSM layer for further access controls, including capability
* based controls.
*/
static int selinux_inode_xattr_skipcap(const char *name)
{
/* require capability check if not a selinux xattr */
return !strcmp(name, XATTR_NAME_SELINUX);
}
static int selinux_inode_setxattr(struct mnt_idmap *idmap,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
@ -3188,15 +3205,9 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap,
u32 newsid, sid = current_sid();
int rc = 0;
if (strcmp(name, XATTR_NAME_SELINUX)) {
rc = cap_inode_setxattr(dentry, name, value, size, flags);
if (rc)
return rc;
/* Not an attribute we recognize, so just check the
ordinary setattr permission. */
/* if not a selinux xattr, only check the ordinary setattr perm */
if (strcmp(name, XATTR_NAME_SELINUX))
return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
}
if (!selinux_initialized())
return (inode_owner_or_capable(idmap, inode) ? 0 : -EPERM);
@ -3345,15 +3356,9 @@ static int selinux_inode_listxattr(struct dentry *dentry)
static int selinux_inode_removexattr(struct mnt_idmap *idmap,
struct dentry *dentry, const char *name)
{
if (strcmp(name, XATTR_NAME_SELINUX)) {
int rc = cap_inode_removexattr(idmap, dentry, name);
if (rc)
return rc;
/* Not an attribute we recognize, so just check the
ordinary setattr permission. */
/* if not a selinux xattr, only check the ordinary setattr perm */
if (strcmp(name, XATTR_NAME_SELINUX))
return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
}
if (!selinux_initialized())
return 0;
@ -7175,6 +7180,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
LSM_HOOK_INIT(inode_xattr_skipcap, selinux_inode_xattr_skipcap),
LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),

View File

@ -1282,6 +1282,33 @@ static int smack_inode_getattr(const struct path *path)
return rc;
}
/**
* smack_inode_xattr_skipcap - Skip the xattr capability checks?
* @name: name of the xattr
*
* Returns 1 to indicate that Smack "owns" the access control rights to xattrs
* named @name; the LSM layer should avoid enforcing any traditional
* capability based access controls on this xattr. Returns 0 to indicate that
* Smack does not "own" the access control rights to xattrs named @name and is
* deferring to the LSM layer for further access controls, including capability
* based controls.
*/
static int smack_inode_xattr_skipcap(const char *name)
{
if (strncmp(name, XATTR_SMACK_SUFFIX, strlen(XATTR_SMACK_SUFFIX)))
return 0;
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
strcmp(name, XATTR_NAME_SMACKMMAP) == 0 ||
strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0)
return 1;
return 0;
}
/**
* smack_inode_setxattr - Smack check for setting xattrs
* @idmap: idmap of the mount
@ -1325,8 +1352,7 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
size != TRANS_TRUE_SIZE ||
strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
rc = -EINVAL;
} else
rc = cap_inode_setxattr(dentry, name, value, size, flags);
}
if (check_priv && !smack_privileged(CAP_MAC_ADMIN))
rc = -EPERM;
@ -1435,8 +1461,7 @@ static int smack_inode_removexattr(struct mnt_idmap *idmap,
strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
if (!smack_privileged(CAP_MAC_ADMIN))
rc = -EPERM;
} else
rc = cap_inode_removexattr(idmap, dentry, name);
}
if (rc != 0)
return rc;
@ -5053,6 +5078,7 @@ static struct security_hook_list smack_hooks[] __ro_after_init = {
LSM_HOOK_INIT(inode_permission, smack_inode_permission),
LSM_HOOK_INIT(inode_setattr, smack_inode_setattr),
LSM_HOOK_INIT(inode_getattr, smack_inode_getattr),
LSM_HOOK_INIT(inode_xattr_skipcap, smack_inode_xattr_skipcap),
LSM_HOOK_INIT(inode_setxattr, smack_inode_setxattr),
LSM_HOOK_INIT(inode_post_setxattr, smack_inode_post_setxattr),
LSM_HOOK_INIT(inode_getxattr, smack_inode_getxattr),