Line data Source code
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 : 13 : static unsigned int __read_mostly vdso_enabled = 1; 14 : unsigned long um_vdso_addr; 15 : 16 : extern unsigned long task_size; 17 : extern char vdso_start[], vdso_end[]; 18 : 19 : static struct page **vdsop; 20 : 21 1 : static int __init init_vdso(void) 22 : { 23 : struct page *um_vdso; 24 : 25 1 : BUG_ON(vdso_end - vdso_start > PAGE_SIZE); 26 : 27 1 : um_vdso_addr = task_size - PAGE_SIZE; 28 : 29 1 : vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL); 30 1 : if (!vdsop) 31 : goto oom; 32 : 33 1 : um_vdso = alloc_page(GFP_KERNEL); 34 1 : if (!um_vdso) { 35 0 : kfree(vdsop); 36 : 37 0 : goto oom; 38 : } 39 : 40 2 : copy_page(page_address(um_vdso), vdso_start); 41 1 : *vdsop = um_vdso; 42 : 43 1 : return 0; 44 : 45 : oom: 46 0 : printk(KERN_ERR "Cannot allocate vdso\n"); 47 0 : vdso_enabled = 0; 48 : 49 0 : return -ENOMEM; 50 : } 51 : subsys_initcall(init_vdso); 52 : 53 0 : int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 54 : { 55 : int err; 56 0 : struct mm_struct *mm = current->mm; 57 : 58 0 : if (!vdso_enabled) 59 : return 0; 60 : 61 0 : if (mmap_write_lock_killable(mm)) 62 : return -EINTR; 63 : 64 0 : 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 0 : mmap_write_unlock(mm); 70 : 71 0 : return err; 72 : }