mirror of
https://github.com/torvalds/linux
synced 2024-09-29 07:50:45 +00:00
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:
commit
11ab4cd5ec
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in a new issue