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