linux/arch/x86/um/vdso/vma.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
   4 */
   5
   6#include <linux/slab.h>
   7#include <linux/sched.h>
   8#include <linux/mm.h>
   9#include <asm/page.h>
  10#include <asm/elf.h>
  11#include <linux/init.h>
  12
  13static unsigned int __read_mostly vdso_enabled = 1;
  14unsigned long um_vdso_addr;
  15
  16extern unsigned long task_size;
  17extern char vdso_start[], vdso_end[];
  18
  19static struct page **vdsop;
  20
  21static int __init init_vdso(void)
  22{
  23        struct page *um_vdso;
  24
  25        BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
  26
  27        um_vdso_addr = task_size - PAGE_SIZE;
  28
  29        vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL);
  30        if (!vdsop)
  31                goto oom;
  32
  33        um_vdso = alloc_page(GFP_KERNEL);
  34        if (!um_vdso) {
  35                kfree(vdsop);
  36
  37                goto oom;
  38        }
  39
  40        copy_page(page_address(um_vdso), vdso_start);
  41        *vdsop = um_vdso;
  42
  43        return 0;
  44
  45oom:
  46        printk(KERN_ERR "Cannot allocate vdso\n");
  47        vdso_enabled = 0;
  48
  49        return -ENOMEM;
  50}
  51subsys_initcall(init_vdso);
  52
  53int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
  54{
  55        int err;
  56        struct mm_struct *mm = current->mm;
  57
  58        if (!vdso_enabled)
  59                return 0;
  60
  61        if (down_write_killable(&mm->mmap_sem))
  62                return -EINTR;
  63
  64        err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
  65                VM_READ|VM_EXEC|
  66                VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
  67                vdsop);
  68
  69        up_write(&mm->mmap_sem);
  70
  71        return err;
  72}
  73