The lsm_get_self_attr() syscall allows callers to pass in a NULL context
buffer to find out the size of the output needed. That path still
compared the computed entry size against the caller provided size first,
so a NULL buffer with size 0 incorrectly returned -E2BIG rather than
reporting the required size.

Only enforce the available buffer length after checking for the NULL
buffer. Cover the zero length sizing query in the self test.

Fixes: d7cf3412a9f6 ("lsm: consolidate buffer size handling into 
lsm_fill_user_ctx()")
Cc: [email protected]
Signed-off-by: Bradley Morgan <[email protected]>
---
 security/security.c                                  | 8 ++++----
 tools/testing/selftests/lsm/lsm_get_self_attr_test.c | 5 ++---
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/security/security.c b/security/security.c
index 71aea8fdf014..fa0d7e036249 100644
--- a/security/security.c
+++ b/security/security.c
@@ -406,15 +406,15 @@ int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 
*uctx_len,
        int rc = 0;
 
        nctx_len = ALIGN(struct_size(nctx, ctx, val_len), sizeof(void *));
+       /* no buffer - return success/0 and set @uctx_len to the req size */
+       if (!uctx)
+               goto out;
+
        if (nctx_len > *uctx_len) {
                rc = -E2BIG;
                goto out;
        }
 
-       /* no buffer - return success/0 and set @uctx_len to the req size */
-       if (!uctx)
-               goto out;
-
        nctx = kzalloc(nctx_len, GFP_KERNEL);
        if (nctx == NULL) {
                rc = -ENOMEM;
diff --git a/tools/testing/selftests/lsm/lsm_get_self_attr_test.c 
b/tools/testing/selftests/lsm/lsm_get_self_attr_test.c
index 60caf8528f81..2f5ababc2b95 100644
--- a/tools/testing/selftests/lsm/lsm_get_self_attr_test.c
+++ b/tools/testing/selftests/lsm/lsm_get_self_attr_test.c
@@ -39,15 +39,14 @@ TEST(size_null_lsm_get_self_attr)
 
 TEST(ctx_null_lsm_get_self_attr)
 {
-       const long page_size = sysconf(_SC_PAGESIZE);
-       __u32 size = page_size;
+       __u32 size = 0;
        int rc;
 
        rc = lsm_get_self_attr(LSM_ATTR_CURRENT, NULL, &size, 0);
 
        if (attr_lsm_count()) {
                ASSERT_NE(-1, rc);
-               ASSERT_NE(1, size);
+               ASSERT_NE(0, size);
        } else {
                ASSERT_EQ(-1, rc);
        }
-- 
2.53.0


Reply via email to