On 2024/7/5 03:05, Benjamin Berg wrote:
[...]
> diff --git a/arch/x86/um/os-Linux/task_size.c 
> b/arch/x86/um/os-Linux/task_size.c
> index 1dc9adc20b1c..a91599799b1a 100644
> --- a/arch/x86/um/os-Linux/task_size.c
> +++ b/arch/x86/um/os-Linux/task_size.c
> @@ -1,151 +1,19 @@
>  // SPDX-License-Identifier: GPL-2.0
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <signal.h>
> -#include <sys/mman.h>
> -#include <longjmp.h>
>  

Tiny nit: we need to include os.h to avoid below warning:

arch/x86/um/os-Linux/task_size.c:3:15: warning: no previous prototype for
‘os_get_top_address’ [-Wmissing-prototypes]
    3 | unsigned long os_get_top_address(char **envp)
      |               ^~~~~~~~~~~~~~~~~~

Regards,
Tiwei

> -#ifdef __i386__
> -
> -static jmp_buf buf;
> -
> -static void segfault(int sig)
> -{
> -     longjmp(buf, 1);
> -}
> -
> -static int page_ok(unsigned long page)
> -{
> -     unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
> -     unsigned long n = ~0UL;
> -     void *mapped = NULL;
> -     int ok = 0;
> -
> -     /*
> -      * First see if the page is readable.  If it is, it may still
> -      * be a VDSO, so we go on to see if it's writable.  If not
> -      * then try mapping memory there.  If that fails, then we're
> -      * still in the kernel area.  As a sanity check, we'll fail if
> -      * the mmap succeeds, but gives us an address different from
> -      * what we wanted.
> -      */
> -     if (setjmp(buf) == 0)
> -             n = *address;
> -     else {
> -             mapped = mmap(address, UM_KERN_PAGE_SIZE,
> -                           PROT_READ | PROT_WRITE,
> -                           MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> -             if (mapped == MAP_FAILED)
> -                     return 0;
> -             if (mapped != address)
> -                     goto out;
> -     }
> -
> -     /*
> -      * Now, is it writeable?  If so, then we're in user address
> -      * space.  If not, then try mprotecting it and try the write
> -      * again.
> -      */
> -     if (setjmp(buf) == 0) {
> -             *address = n;
> -             ok = 1;
> -             goto out;
> -     } else if (mprotect(address, UM_KERN_PAGE_SIZE,
> -                         PROT_READ | PROT_WRITE) != 0)
> -             goto out;
> -
> -     if (setjmp(buf) == 0) {
> -             *address = n;
> -             ok = 1;
> -     }
> -
> - out:
> -     if (mapped != NULL)
> -             munmap(mapped, UM_KERN_PAGE_SIZE);
> -     return ok;
> -}
> -
> -unsigned long os_get_top_address(void)
> +unsigned long os_get_top_address(char **envp)
>  {
> -     struct sigaction sa, old;
> -     unsigned long bottom = 0;
> -     /*
> -      * A 32-bit UML on a 64-bit host gets confused about the VDSO at
> -      * 0xffffe000.  It is mapped, is readable, can be reprotected writeable
> -      * and written.  However, exec discovers later that it can't be
> -      * unmapped.  So, just set the highest address to be checked to just
> -      * below it.  This might waste some address space on 4G/4G 32-bit
> -      * hosts, but shouldn't hurt otherwise.
> -      */
> -     unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
> -     unsigned long test, original;
> +     unsigned long top_addr = (unsigned long) &top_addr;
> +     int i;
>  
> -     printf("Locating the bottom of the address space ... ");
> -     fflush(stdout);
> -
> -     /*
> -      * We're going to be longjmping out of the signal handler, so
> -      * SA_DEFER needs to be set.
> -      */
> -     sa.sa_handler = segfault;
> -     sigemptyset(&sa.sa_mask);
> -     sa.sa_flags = SA_NODEFER;
> -     if (sigaction(SIGSEGV, &sa, &old)) {
> -             perror("os_get_top_address");
> -             exit(1);
> -     }
> -
> -     /* Manually scan the address space, bottom-up, until we find
> -      * the first valid page (or run out of them).
> -      */
> -     for (bottom = 0; bottom < top; bottom++) {
> -             if (page_ok(bottom))
> -                     break;
> -     }
> -
> -     /* If we've got this far, we ran out of pages. */
> -     if (bottom == top) {
> -             fprintf(stderr, "Unable to determine bottom of address "
> -                     "space.\n");
> -             exit(1);
> -     }
> -
> -     printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT);
> -     printf("Locating the top of the address space ... ");
> -     fflush(stdout);
> -
> -     original = bottom;
> -
> -     /* This could happen with a 4G/4G split */
> -     if (page_ok(top))
> -             goto out;
> -
> -     do {
> -             test = bottom + (top - bottom) / 2;
> -             if (page_ok(test))
> -                     bottom = test;
> -             else
> -                     top = test;
> -     } while (top - bottom > 1);
> -
> -out:
> -     /* Restore the old SIGSEGV handling */
> -     if (sigaction(SIGSEGV, &old, NULL)) {
> -             perror("os_get_top_address");
> -             exit(1);
> +     /* The earliest variable should be after the program name in ELF */
> +     for (i = 0; envp[i]; i++) {
> +             if ((unsigned long) envp[i] > top_addr)
> +                     top_addr = (unsigned long) envp[i];
>       }
> -     top <<= UM_KERN_PAGE_SHIFT;
> -     printf("0x%lx\n", top);
>  
> -     return top;
> -}
> -
> -#else
> +     top_addr &= ~(UM_KERN_PAGE_SIZE - 1);
> +     top_addr += UM_KERN_PAGE_SIZE;
>  
> -unsigned long os_get_top_address(void)
> -{
> -     /* The old value of CONFIG_TOP_ADDR */
> -     return 0x7fc0002000;
> +     return top_addr;
>  }
>  
> -#endif


Reply via email to