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