cregit-Linux how code gets into the kernel

Release 4.14 arch/x86/um/os-Linux/task_size.c

// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/mman.h>
#include <longjmp.h>

#ifdef __i386__


static jmp_buf buf;


static void segfault(int sig) { longjmp(buf, 1); }

Contributors

PersonTokensPropCommitsCommitProp
Jeff Dike16100.00%1100.00%
Total16100.00%1100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
Jeff Dike185100.00%1100.00%
Total185100.00%1100.00%


unsigned long os_get_top_address(void) { 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; 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); } top <<= UM_KERN_PAGE_SHIFT; printf("0x%lx\n", top); return top; }

Contributors

PersonTokensPropCommitsCommitProp
Jeff Dike17167.86%125.00%
Tom Spink5321.03%125.00%
Américo Wang2610.32%125.00%
Colin Ian King20.79%125.00%
Total252100.00%4100.00%

#else
unsigned long os_get_top_address(void) { /* The old value of CONFIG_TOP_ADDR */ return 0x7fc0000000; }

Contributors

PersonTokensPropCommitsCommitProp
Al Viro12100.00%1100.00%
Total12100.00%1100.00%

#endif

Overall Contributors

PersonTokensPropCommitsCommitProp
Jeff Dike39079.27%114.29%
Tom Spink5310.77%114.29%
Américo Wang265.28%114.29%
Al Viro204.07%228.57%
Colin Ian King20.41%114.29%
Greg Kroah-Hartman10.20%114.29%
Total492100.00%7100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.