* [PATCH v1 1/2] lsm: Refactor return value of LSM hook vm_enough_memory
2024-07-24 2:06 [PATCH v1 0/2] Refactor return value of two lsm hooks Xu Kuohai
@ 2024-07-24 2:06 ` Xu Kuohai
2024-07-24 2:06 ` [PATCH v1 2/2] lsm: Refactor return value of LSM hook inode_copy_up_xattr Xu Kuohai
2024-07-24 20:36 ` [PATCH v1 0/2] Refactor return value of two lsm hooks Casey Schaufler
2 siblings, 0 replies; 6+ messages in thread
From: Xu Kuohai @ 2024-07-24 2:06 UTC (permalink / raw)
To: linux-security-module, selinux, linux-unionfs, linux-integrity
Cc: Paul Moore, Casey Schaufler, Serge E . Hallyn, Miklos Szeredi,
Amir Goldstein, James Morris, Mimi Zohar, Roberto Sassu,
Dmitry Kasatkin, Eric Snowberg, Stephen Smalley, Ondrej Mosnacek
From: Xu Kuohai <xukuohai@huawei.com>
To be consistent with most LSM hooks, convert the return value of
hook vm_enough_memory to 0 or a negative error code.
Before:
- Hook vm_enough_memory returns 1 if permission is granted, 0 if not.
- LSM_RET_DEFAULT(vm_enough_memory_mm) is 1.
After:
- Hook vm_enough_memory reutrns 0 if permission is granted, negative
error code if not.
- LSM_RET_DEFAULT(vm_enough_memory_mm) is 0.
Signed-off-by: Xu Kuohai <xukuohai@huawei.com>
---
include/linux/lsm_hook_defs.h | 2 +-
include/linux/security.h | 2 +-
security/commoncap.c | 11 +++--------
security/security.c | 11 +++++------
security/selinux/hooks.c | 15 ++++-----------
5 files changed, 14 insertions(+), 27 deletions(-)
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 1d113a727098..06265e70013c 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -48,7 +48,7 @@ LSM_HOOK(int, 0, quota_on, struct dentry *dentry)
LSM_HOOK(int, 0, syslog, int type)
LSM_HOOK(int, 0, settime, const struct timespec64 *ts,
const struct timezone *tz)
-LSM_HOOK(int, 1, vm_enough_memory, struct mm_struct *mm, long pages)
+LSM_HOOK(int, 0, vm_enough_memory, struct mm_struct *mm, long pages)
LSM_HOOK(int, 0, bprm_creds_for_exec, struct linux_binprm *bprm)
LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, const struct file *file)
LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm)
diff --git a/include/linux/security.h b/include/linux/security.h
index 21cf70346b33..ed4deff36fff 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -634,7 +634,7 @@ static inline int security_settime64(const struct timespec64 *ts,
static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
{
- return __vm_enough_memory(mm, pages, cap_vm_enough_memory(mm, pages));
+ return __vm_enough_memory(mm, pages, !cap_vm_enough_memory(mm, pages));
}
static inline int security_bprm_creds_for_exec(struct linux_binprm *bprm)
diff --git a/security/commoncap.c b/security/commoncap.c
index 162d96b3a676..cefad323a0b1 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -1396,17 +1396,12 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
* Determine whether the allocation of a new virtual mapping by the current
* task is permitted.
*
- * Return: 1 if permission is granted, 0 if not.
+ * Return: 0 if permission granted, negative error code if not.
*/
int cap_vm_enough_memory(struct mm_struct *mm, long pages)
{
- int cap_sys_admin = 0;
-
- if (cap_capable(current_cred(), &init_user_ns,
- CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) == 0)
- cap_sys_admin = 1;
-
- return cap_sys_admin;
+ return cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
+ CAP_OPT_NOAUDIT);
}
/**
diff --git a/security/security.c b/security/security.c
index 12e402b7230f..ff5cca992ee1 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1218,15 +1218,14 @@ int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
int rc;
/*
- * The module will respond with a positive value if
- * it thinks the __vm_enough_memory() call should be
- * made with the cap_sys_admin set. If all of the modules
- * agree that it should be set it will. If any module
- * thinks it should not be set it won't.
+ * The module will respond with 0 if it thinks the __vm_enough_memory()
+ * call should be made with the cap_sys_admin set. If all of the modules
+ * agree that it should be set it will. If any module thinks it should
+ * not be set it won't.
*/
lsm_for_each_hook(scall, vm_enough_memory) {
rc = scall->hl->hook.vm_enough_memory(mm, pages);
- if (rc <= 0) {
+ if (rc < 0) {
cap_sys_admin = 0;
break;
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 0939816e9671..af7467cdd181 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2202,23 +2202,16 @@ static int selinux_syslog(int type)
}
/*
- * Check that a process has enough memory to allocate a new virtual
- * mapping. 0 means there is enough memory for the allocation to
- * succeed and -ENOMEM implies there is not.
+ * Check permission for allocating a new virtual mapping. Returns
+ * 0 if permission is granted, negative error code if not.
*
* Do not audit the selinux permission check, as this is applied to all
* processes that allocate mappings.
*/
static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
{
- int rc, cap_sys_admin = 0;
-
- rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
- CAP_OPT_NOAUDIT, true);
- if (rc == 0)
- cap_sys_admin = 1;
-
- return cap_sys_admin;
+ return cred_has_capability(current_cred(), CAP_SYS_ADMIN,
+ CAP_OPT_NOAUDIT, true);
}
/* binprm security operations */
--
2.39.2
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v1 2/2] lsm: Refactor return value of LSM hook inode_copy_up_xattr
2024-07-24 2:06 [PATCH v1 0/2] Refactor return value of two lsm hooks Xu Kuohai
2024-07-24 2:06 ` [PATCH v1 1/2] lsm: Refactor return value of LSM hook vm_enough_memory Xu Kuohai
@ 2024-07-24 2:06 ` Xu Kuohai
2024-07-24 20:36 ` [PATCH v1 0/2] Refactor return value of two lsm hooks Casey Schaufler
2 siblings, 0 replies; 6+ messages in thread
From: Xu Kuohai @ 2024-07-24 2:06 UTC (permalink / raw)
To: linux-security-module, selinux, linux-unionfs, linux-integrity
Cc: Paul Moore, Casey Schaufler, Serge E . Hallyn, Miklos Szeredi,
Amir Goldstein, James Morris, Mimi Zohar, Roberto Sassu,
Dmitry Kasatkin, Eric Snowberg, Stephen Smalley, Ondrej Mosnacek
From: Xu Kuohai <xukuohai@huawei.com>
To be consistent with most LSM hooks, convert the return value of
hook inode_copy_up_xattr to 0 or a negative error code.
Before:
- Hook inode_copy_up_xattr returns 0 when accepting xattr, 1 when
discarding xattr, -EOPNOTSUPP if it does not know xattr, or any
other negative error code otherwise.
After:
- Hook inode_copy_up_xattr returns 0 when accepting xattr, *-ECANCELED*
when discarding xattr, -EOPNOTSUPP if it does not know xattr, or
any other negative error code otherwise.
Signed-off-by: Xu Kuohai <xukuohai@huawei.com>
---
fs/overlayfs/copy_up.c | 6 +++---
security/integrity/evm/evm_main.c | 2 +-
security/security.c | 11 +++--------
security/selinux/hooks.c | 4 ++--
security/smack/smack_lsm.c | 6 +++---
5 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index a5ef2005a2cc..337a5be99ac9 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -115,12 +115,12 @@ int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct de
continue;
error = security_inode_copy_up_xattr(old, name);
- if (error < 0 && error != -EOPNOTSUPP)
- break;
- if (error == 1) {
+ if (error == -ECANCELED) {
error = 0;
continue; /* Discard */
}
+ if (error < 0 && error != -EOPNOTSUPP)
+ break;
if (is_posix_acl_xattr(name)) {
error = ovl_copy_acl(OVL_FS(sb), oldpath, new, name);
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 62fe66dd53ce..6924ed508ebd 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -1000,7 +1000,7 @@ static int evm_inode_copy_up_xattr(struct dentry *src, const char *name)
case EVM_XATTR_HMAC:
case EVM_IMA_XATTR_DIGSIG:
default:
- rc = 1; /* discard */
+ rc = -ECANCELED; /* discard */
}
kfree(xattr_data);
diff --git a/security/security.c b/security/security.c
index ff5cca992ee1..ca93d43ad475 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2760,19 +2760,14 @@ EXPORT_SYMBOL(security_inode_copy_up);
* lower layer to the union/overlay layer. The caller is responsible for
* reading and writing the xattrs, this hook is merely a filter.
*
- * Return: Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP
- * if the security module does not know about attribute, or a negative
- * error code to abort the copy up.
+ * Return: Returns 0 to accept the xattr, -ECANCELED to discard the xattr,
+ * -EOPNOTSUPP if the security module does not know about attribute,
+ * or a negative error code to abort the copy up.
*/
int security_inode_copy_up_xattr(struct dentry *src, const char *name)
{
int rc;
- /*
- * The implementation can return 0 (accept the xattr), 1 (discard the
- * xattr), -EOPNOTSUPP if it does not know anything about the xattr or
- * any other error code in case of an error.
- */
rc = call_int_hook(inode_copy_up_xattr, src, name);
if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr))
return rc;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index af7467cdd181..81fbfa5b80d4 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3531,8 +3531,8 @@ static int selinux_inode_copy_up_xattr(struct dentry *dentry, const char *name)
* xattrs up. Instead, filter out SELinux-related xattrs following
* policy load.
*/
- if (selinux_initialized() && strcmp(name, XATTR_NAME_SELINUX) == 0)
- return 1; /* Discard */
+ if (selinux_initialized() && !strcmp(name, XATTR_NAME_SELINUX))
+ return -ECANCELED; /* Discard */
/*
* Any other attribute apart from SELINUX is not claimed, supported
* by selinux.
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index b0e0205a5724..09ff7f24c0c6 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4902,10 +4902,10 @@ static int smack_inode_copy_up(struct dentry *dentry, struct cred **new)
static int smack_inode_copy_up_xattr(struct dentry *src, const char *name)
{
/*
- * Return 1 if this is the smack access Smack attribute.
+ * Return -ECANCELED if this is the smack access Smack attribute.
*/
- if (strcmp(name, XATTR_NAME_SMACK) == 0)
- return 1;
+ if (!strcmp(name, XATTR_NAME_SMACK))
+ return -ECANCELED;
return -EOPNOTSUPP;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v1 0/2] Refactor return value of two lsm hooks
2024-07-24 2:06 [PATCH v1 0/2] Refactor return value of two lsm hooks Xu Kuohai
2024-07-24 2:06 ` [PATCH v1 1/2] lsm: Refactor return value of LSM hook vm_enough_memory Xu Kuohai
2024-07-24 2:06 ` [PATCH v1 2/2] lsm: Refactor return value of LSM hook inode_copy_up_xattr Xu Kuohai
@ 2024-07-24 20:36 ` Casey Schaufler
2024-07-24 21:55 ` Paul Moore
2 siblings, 1 reply; 6+ messages in thread
From: Casey Schaufler @ 2024-07-24 20:36 UTC (permalink / raw)
To: Xu Kuohai, linux-security-module, selinux, linux-unionfs,
linux-integrity
Cc: Paul Moore, Serge E . Hallyn, Miklos Szeredi, Amir Goldstein,
James Morris, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Stephen Smalley, Ondrej Mosnacek, Casey Schaufler
On 7/23/2024 7:06 PM, Xu Kuohai wrote:
> From: Xu Kuohai <xukuohai@huawei.com>
>
> The BPF LSM program may cause a kernel panic if it returns an
> unexpected value, such as a positive value on the hook
> file_alloc_security.
>
> To fix it, series [1] refactored the LSM hook return values and
> added BPF return value checks.
>
> [1] used two methods to refactor hook return values:
>
> - converting positive return value to negative error code
>
> - adding additional output parameter to store odd return values
>
> Based on discussion in [1], only two hooks refactored with the
> second method may be acceptable. Since the second method requires
> extra work on BPF side to ensure that the output parameter is
> set properly, the extra work does not seem worthwhile for just
> two hooks. So this series includes only the two patches refactored
> with the first method.
>
> Changes to [1]:
> - Drop unnecessary patches
> - Rebase
> - Remove redundant comments in the inode_copy_up_xattr patch
>
> [1] https://lore.kernel.org/bpf/20240711111908.3817636-1-xukuohai@huaweicloud.com
> https://lore.kernel.org/bpf/20240711113828.3818398-1-xukuohai@huaweicloud.com
>
> Xu Kuohai (2):
> lsm: Refactor return value of LSM hook vm_enough_memory
> lsm: Refactor return value of LSM hook inode_copy_up_xattr
For the series:
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
>
> fs/overlayfs/copy_up.c | 6 +++---
> include/linux/lsm_hook_defs.h | 2 +-
> include/linux/security.h | 2 +-
> security/commoncap.c | 11 +++--------
> security/integrity/evm/evm_main.c | 2 +-
> security/security.c | 22 ++++++++--------------
> security/selinux/hooks.c | 19 ++++++-------------
> security/smack/smack_lsm.c | 6 +++---
> 8 files changed, 26 insertions(+), 44 deletions(-)
>
^ permalink raw reply [flat|nested] 6+ messages in thread