[PATCH] linux-user: report EINVAL for a misaligned mincore() start

Michael Morrell posted 1 patch 1 day, 22 hours ago
linux-user/syscall.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
[PATCH] linux-user: report EINVAL for a misaligned mincore() start
Posted by Michael Morrell 1 day, 22 hours ago
From: Igor Shevlyakov <igor@tachyum.com>

mincore(2) rejects a misaligned start address before it looks the range
up, so a start that is both misaligned and unmapped is EINVAL.  Here
lock_user() runs first and fails, and the call reports ENOMEM instead.

When the range is mapped this changes nothing -- the host syscall
receives the misaligned pointer and answers EINVAL by itself -- which is
why only the unmapped case is visibly wrong.

Caught by glibc's misc/test-errno-linux.

Signed-off-by: Igor Shevlyakov <igor@tachyum.com>
---
 linux-user/syscall.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9f454502cb..a878feedf2 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -13051,7 +13051,17 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR_mincore
     case TARGET_NR_mincore:
         {
-            void *a = lock_user(VERIFY_NONE, arg1, arg2, 0);
+            void *a;
+
+            /*
+             * The kernel rejects a misaligned start before it looks the range
+             * up, so a start that is both misaligned and unmapped is EINVAL,
+             * not the ENOMEM that a failing lock_user() would report.
+             */
+            if (arg1 & ~TARGET_PAGE_MASK) {
+                return -TARGET_EINVAL;
+            }
+            a = lock_user(VERIFY_NONE, arg1, arg2, 0);
             if (!a) {
                 return -TARGET_ENOMEM;
             }
-- 
2.43.0
Re: [PATCH] linux-user: report EINVAL for a misaligned mincore() start
Posted by Helge Deller 1 day, 21 hours ago
On 9/24/26 21:31, Michael Morrell wrote:
> From: Igor Shevlyakov <igor@tachyum.com>
> 
> mincore(2) rejects a misaligned start address before it looks the range
> up, so a start that is both misaligned and unmapped is EINVAL.  Here
> lock_user() runs first and fails, and the call reports ENOMEM instead.
> 
> When the range is mapped this changes nothing -- the host syscall
> receives the misaligned pointer and answers EINVAL by itself -- which is
> why only the unmapped case is visibly wrong.
> 
> Caught by glibc's misc/test-errno-linux.
> 
> Signed-off-by: Igor Shevlyakov <igor@tachyum.com>
> ---
>   linux-user/syscall.c | 12 +++++++++++-
>   1 file changed, 11 insertions(+), 1 deletion(-)
Reviewed-by: Helge Deller <deller@gmx.de>