1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 25c48b108SAl Viro /* 35c48b108SAl Viro * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> 45c48b108SAl Viro */ 55c48b108SAl Viro 65c48b108SAl Viro #include <linux/slab.h> 75c48b108SAl Viro #include <linux/sched.h> 85c48b108SAl Viro #include <linux/mm.h> 95c48b108SAl Viro #include <asm/page.h> 109b46e212SRichard Weinberger #include <asm/elf.h> 115c48b108SAl Viro #include <linux/init.h> 125c48b108SAl Viro 133d7ee969SAndy Lutomirski static unsigned int __read_mostly vdso_enabled = 1; 145c48b108SAl Viro unsigned long um_vdso_addr; 155c48b108SAl Viro 165c48b108SAl Viro extern unsigned long task_size; 175c48b108SAl Viro extern char vdso_start[], vdso_end[]; 185c48b108SAl Viro 195c48b108SAl Viro static struct page **vdsop; 205c48b108SAl Viro init_vdso(void)215c48b108SAl Virostatic int __init init_vdso(void) 225c48b108SAl Viro { 235c48b108SAl Viro struct page *um_vdso; 245c48b108SAl Viro 255c48b108SAl Viro BUG_ON(vdso_end - vdso_start > PAGE_SIZE); 265c48b108SAl Viro 275c48b108SAl Viro um_vdso_addr = task_size - PAGE_SIZE; 285c48b108SAl Viro 290d65ede0SDave Jones vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL); 305c48b108SAl Viro if (!vdsop) 315c48b108SAl Viro goto oom; 325c48b108SAl Viro 335c48b108SAl Viro um_vdso = alloc_page(GFP_KERNEL); 345c48b108SAl Viro if (!um_vdso) { 355c48b108SAl Viro kfree(vdsop); 365c48b108SAl Viro 375c48b108SAl Viro goto oom; 385c48b108SAl Viro } 395c48b108SAl Viro 405c48b108SAl Viro copy_page(page_address(um_vdso), vdso_start); 415c48b108SAl Viro *vdsop = um_vdso; 425c48b108SAl Viro 435c48b108SAl Viro return 0; 445c48b108SAl Viro 455c48b108SAl Viro oom: 465c48b108SAl Viro printk(KERN_ERR "Cannot allocate vdso\n"); 475c48b108SAl Viro vdso_enabled = 0; 485c48b108SAl Viro 495c48b108SAl Viro return -ENOMEM; 505c48b108SAl Viro } 515c48b108SAl Viro subsys_initcall(init_vdso); 525c48b108SAl Viro arch_setup_additional_pages(struct linux_binprm * bprm,int uses_interp)535c48b108SAl Viroint arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 545c48b108SAl Viro { 555c48b108SAl Viro int err; 565c48b108SAl Viro struct mm_struct *mm = current->mm; 575c48b108SAl Viro 585c48b108SAl Viro if (!vdso_enabled) 595c48b108SAl Viro return 0; 605c48b108SAl Viro 61*d8ed45c5SMichel Lespinasse if (mmap_write_lock_killable(mm)) 6269048176SMichal Hocko return -EINTR; 635c48b108SAl Viro 645c48b108SAl Viro err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE, 655c48b108SAl Viro VM_READ|VM_EXEC| 66909af768SJason Baron VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, 675c48b108SAl Viro vdsop); 685c48b108SAl Viro 69*d8ed45c5SMichel Lespinasse mmap_write_unlock(mm); 705c48b108SAl Viro 715c48b108SAl Viro return err; 725c48b108SAl Viro } 73