Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
0004  */
0005 
0006 #include <linux/slab.h>
0007 #include <linux/sched.h>
0008 #include <linux/mm.h>
0009 #include <asm/page.h>
0010 #include <asm/elf.h>
0011 #include <linux/init.h>
0012 
0013 static unsigned int __read_mostly vdso_enabled = 1;
0014 unsigned long um_vdso_addr;
0015 
0016 extern unsigned long task_size;
0017 extern char vdso_start[], vdso_end[];
0018 
0019 static struct page **vdsop;
0020 
0021 static int __init init_vdso(void)
0022 {
0023     struct page *um_vdso;
0024 
0025     BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
0026 
0027     um_vdso_addr = task_size - PAGE_SIZE;
0028 
0029     vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL);
0030     if (!vdsop)
0031         goto oom;
0032 
0033     um_vdso = alloc_page(GFP_KERNEL);
0034     if (!um_vdso) {
0035         kfree(vdsop);
0036 
0037         goto oom;
0038     }
0039 
0040     copy_page(page_address(um_vdso), vdso_start);
0041     *vdsop = um_vdso;
0042 
0043     return 0;
0044 
0045 oom:
0046     printk(KERN_ERR "Cannot allocate vdso\n");
0047     vdso_enabled = 0;
0048 
0049     return -ENOMEM;
0050 }
0051 subsys_initcall(init_vdso);
0052 
0053 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
0054 {
0055     int err;
0056     struct mm_struct *mm = current->mm;
0057 
0058     if (!vdso_enabled)
0059         return 0;
0060 
0061     if (mmap_write_lock_killable(mm))
0062         return -EINTR;
0063 
0064     err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
0065         VM_READ|VM_EXEC|
0066         VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
0067         vdsop);
0068 
0069     mmap_write_unlock(mm);
0070 
0071     return err;
0072 }