Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 19 Dec 2012 15:55:08 +0000 (07:55 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 19 Dec 2012 15:55:08 +0000 (07:55 -0800)
Pull module update from Rusty Russell:
 "Nothing all that exciting; a new module-from-fd syscall for those who
  want to verify the source of the module (ChromeOS) and/or use standard
  IMA on it or other security hooks."

* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  MODSIGN: Fix kbuild output when using default extra_certificates
  MODSIGN: Avoid using .incbin in C source
  modules: don't hand 0 to vmalloc.
  module: Remove a extra null character at the top of module->strtab.
  ASN.1: Use the ASN1_LONG_TAG and ASN1_INDEFINITE_LENGTH constants
  ASN.1: Define indefinite length marker constant
  moduleparam: use __UNIQUE_ID()
  __UNIQUE_ID()
  MODSIGN: Add modules_sign make target
  powerpc: add finit_module syscall.
  ima: support new kernel module syscall
  add finit_module syscall to asm-generic
  ARM: add finit_module syscall to ARM
  security: introduce kernel_module_from_file hook
  module: add flags arg to sys_finit_module()
  module: add syscall to load module from fd

1  2 
Makefile
arch/arm/kernel/calls.S
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/x86/syscalls/syscall_32.tbl
include/linux/compiler-gcc4.h
include/linux/compiler.h
include/linux/syscalls.h
kernel/Makefile
kernel/module.c
lib/asn1_decoder.c

diff --combined Makefile
+++ b/Makefile
@@@ -1,7 -1,7 +1,7 @@@
  VERSION = 3
  PATCHLEVEL = 7
  SUBLEVEL = 0
 -EXTRAVERSION = -rc7
 +EXTRAVERSION =
  NAME = Terrified Chipmunk
  
  # *DOCUMENTATION*
@@@ -981,6 -981,12 +981,12 @@@ _modinst_post: _modinst
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
        $(call cmd,depmod)
  
+ ifeq ($(CONFIG_MODULE_SIG), y)
+ PHONY += modules_sign
+ modules_sign:
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign
+ endif
  else # CONFIG_MODULES
  
  # Modules not configured
diff --combined arch/arm/kernel/calls.S
@@@ -11,7 -11,7 +11,7 @@@
   */
  /* 0 */               CALL(sys_restart_syscall)
                CALL(sys_exit)
 -              CALL(sys_fork_wrapper)
 +              CALL(sys_fork)
                CALL(sys_read)
                CALL(sys_write)
  /* 5 */               CALL(sys_open)
                CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
                CALL(sys_fsync)
                CALL(sys_sigreturn_wrapper)
 -/* 120 */     CALL(sys_clone_wrapper)
 +/* 120 */     CALL(sys_clone)
                CALL(sys_setdomainname)
                CALL(sys_newuname)
                CALL(sys_ni_syscall)            /* modify_ldt */
                CALL(sys_sendfile)
                CALL(sys_ni_syscall)            /* getpmsg */
                CALL(sys_ni_syscall)            /* putpmsg */
 -/* 190 */     CALL(sys_vfork_wrapper)
 +/* 190 */     CALL(sys_vfork)
                CALL(sys_getrlimit)
                CALL(sys_mmap2)
                CALL(ABI(sys_truncate64, sys_oabi_truncate64))
                CALL(sys_process_vm_readv)
                CALL(sys_process_vm_writev)
                CALL(sys_ni_syscall)    /* reserved for sys_kcmp */
+               CALL(sys_finit_module)
  #ifndef syscalls_counted
  .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
  #define syscalls_counted
@@@ -164,7 -164,7 +164,7 @@@ COMPAT_SYS_SPU(sched_getscheduler
  SYSCALL_SPU(sched_yield)
  COMPAT_SYS_SPU(sched_get_priority_max)
  COMPAT_SYS_SPU(sched_get_priority_min)
 -COMPAT_SYS_SPU(sched_rr_get_interval)
 +SYSX_SPU(sys_sched_rr_get_interval,compat_sys_sched_rr_get_interval_wrapper,sys_sched_rr_get_interval)
  COMPAT_SYS_SPU(nanosleep)
  SYSCALL_SPU(mremap)
  SYSCALL_SPU(setresuid)
@@@ -356,3 -356,4 +356,4 @@@ COMPAT_SYS_SPU(sendmmsg
  SYSCALL_SPU(setns)
  COMPAT_SYS(process_vm_readv)
  COMPAT_SYS(process_vm_writev)
+ SYSCALL(finit_module)
@@@ -12,7 -12,7 +12,7 @@@
  #include <uapi/asm/unistd.h>
  
  
- #define __NR_syscalls         353
+ #define __NR_syscalls         354
  
  #define __NR__exit __NR_exit
  #define NR_syscalls   __NR_syscalls
  #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
  #define __ARCH_WANT_SYS_NEWFSTATAT
  #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 +#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
  #endif
  #define __ARCH_WANT_SYS_EXECVE
 -#define __ARCH_WANT_KERNEL_EXECVE
 +#define __ARCH_WANT_SYS_FORK
 +#define __ARCH_WANT_SYS_VFORK
 +#define __ARCH_WANT_SYS_CLONE
  
  /*
   * "Conditional" syscalls
@@@ -8,7 -8,7 +8,7 @@@
  #
  0     i386    restart_syscall         sys_restart_syscall
  1     i386    exit                    sys_exit
 -2     i386    fork                    ptregs_fork                     stub32_fork
 +2     i386    fork                    sys_fork                        stub32_fork
  3     i386    read                    sys_read
  4     i386    write                   sys_write
  5     i386    open                    sys_open                        compat_sys_open
  117   i386    ipc                     sys_ipc                         sys32_ipc
  118   i386    fsync                   sys_fsync
  119   i386    sigreturn               ptregs_sigreturn                stub32_sigreturn
 -120   i386    clone                   ptregs_clone                    stub32_clone
 +120   i386    clone                   sys_clone                       stub32_clone
  121   i386    setdomainname           sys_setdomainname
  122   i386    uname                   sys_newuname
  123   i386    modify_ldt              sys_modify_ldt
  187   i386    sendfile                sys_sendfile                    sys32_sendfile
  188   i386    getpmsg
  189   i386    putpmsg
 -190   i386    vfork                   ptregs_vfork                    stub32_vfork
 +190   i386    vfork                   sys_vfork                       stub32_vfork
  191   i386    ugetrlimit              sys_getrlimit                   compat_sys_getrlimit
  192   i386    mmap2                   sys_mmap_pgoff
  193   i386    truncate64              sys_truncate64                  sys32_truncate64
  347   i386    process_vm_readv        sys_process_vm_readv            compat_sys_process_vm_readv
  348   i386    process_vm_writev       sys_process_vm_writev           compat_sys_process_vm_writev
  349   i386    kcmp                    sys_kcmp
+ 350   i386    finit_module            sys_finit_module
@@@ -31,6 -31,8 +31,8 @@@
  
  #define __linktime_error(message) __attribute__((__error__(message)))
  
+ #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
  #if __GNUC_MINOR__ >= 5
  /*
   * Mark a position in code as unreachable.  This can be used to
  #define __compiletime_warning(message) __attribute__((warning(message)))
  #define __compiletime_error(message) __attribute__((error(message)))
  #endif
 +
 +#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
 +#if __GNUC_MINOR__ >= 4
 +#define __HAVE_BUILTIN_BSWAP32__
 +#define __HAVE_BUILTIN_BSWAP64__
 +#endif
 +#if __GNUC_MINOR__ >= 8 || (defined(__powerpc__) && __GNUC_MINOR__ >= 6)
 +#define __HAVE_BUILTIN_BSWAP16__
 +#endif
 +#endif
diff --combined include/linux/compiler.h
@@@ -10,7 -10,6 +10,7 @@@
  # define __force      __attribute__((force))
  # define __nocast     __attribute__((nocast))
  # define __iomem      __attribute__((noderef, address_space(2)))
 +# define __must_hold(x)       __attribute__((context(x,1,1)))
  # define __acquires(x)        __attribute__((context(x,0,1)))
  # define __releases(x)        __attribute__((context(x,1,0)))
  # define __acquire(x) __context__(x,1)
@@@ -34,7 -33,6 +34,7 @@@ extern void __chk_io_ptr(const volatil
  # define __chk_user_ptr(x) (void)0
  # define __chk_io_ptr(x) (void)0
  # define __builtin_warning(x, y...) (1)
 +# define __must_hold(x)
  # define __acquires(x)
  # define __releases(x)
  # define __acquire(x) (void)0
  # define __rcu
  #endif
  
+ /* Indirect macros required for expanded argument pasting, eg. __LINE__. */
+ #define ___PASTE(a,b) a##b
+ #define __PASTE(a,b) ___PASTE(a,b)
  #ifdef __KERNEL__
  
  #ifdef __GNUC__
@@@ -166,6 -168,11 +170,11 @@@ void ftrace_likely_update(struct ftrace
      (typeof(ptr)) (__ptr + (off)); })
  #endif
  
+ /* Not-quite-unique ID. */
+ #ifndef __UNIQUE_ID
+ # define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
+ #endif
  #endif /* __KERNEL__ */
  
  #endif /* __ASSEMBLY__ */
diff --combined include/linux/syscalls.h
@@@ -560,10 -560,10 +560,10 @@@ asmlinkage long sys_utime(char __user *
  asmlinkage long sys_utimes(char __user *filename,
                                struct timeval __user *utimes);
  asmlinkage long sys_lseek(unsigned int fd, off_t offset,
 -                        unsigned int origin);
 +                        unsigned int whence);
  asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
                        unsigned long offset_low, loff_t __user *result,
 -                      unsigned int origin);
 +                      unsigned int whence);
  asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count);
  asmlinkage long sys_readahead(int fd, loff_t offset, size_t count);
  asmlinkage long sys_readv(unsigned long fd,
@@@ -833,22 -833,10 +833,22 @@@ int kernel_execve(const char *filename
  #define kernel_execve(filename, argv, envp) \
        do_execve(filename, \
                (const char __user *const __user *)argv, \
 -              (const char __user *const __user *)envp, \
 -              current_pt_regs())
 +              (const char __user *const __user *)envp)
  #endif
  
 +asmlinkage long sys_fork(void);
 +asmlinkage long sys_vfork(void);
 +#ifdef CONFIG_CLONE_BACKWARDS
 +asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, int,
 +             int __user *);
 +#else
 +asmlinkage long sys_clone(unsigned long, unsigned long, int __user *,
 +             int __user *, int);
 +#endif
 +
 +asmlinkage long sys_execve(const char __user *filename,
 +              const char __user *const __user *argv,
 +              const char __user *const __user *envp);
  
  asmlinkage long sys_perf_event_open(
                struct perf_event_attr __user *attr_uptr,
@@@ -880,4 -868,5 +880,5 @@@ asmlinkage long sys_process_vm_writev(p
  
  asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
                         unsigned long idx1, unsigned long idx2);
+ asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
  #endif
diff --combined kernel/Makefile
@@@ -54,7 -54,7 +54,7 @@@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinloc
  obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
  obj-$(CONFIG_UID16) += uid16.o
  obj-$(CONFIG_MODULES) += module.o
- obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o
+ obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o
  obj-$(CONFIG_KALLSYMS) += kallsyms.o
  obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
  obj-$(CONFIG_KEXEC) += kexec.o
@@@ -110,7 -110,6 +110,7 @@@ obj-$(CONFIG_USER_RETURN_NOTIFIER) += u
  obj-$(CONFIG_PADATA) += padata.o
  obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
  obj-$(CONFIG_JUMP_LABEL) += jump_label.o
 +obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
  
  $(obj)/configs.o: $(obj)/config_data.h
  
@@@ -137,10 -136,14 +137,14 @@@ ifeq ($(CONFIG_MODULE_SIG),y
  #
  # Pull the signing certificate and any extra certificates into the kernel
  #
+ quiet_cmd_touch = TOUCH   $@
+       cmd_touch = touch   $@
  extra_certificates:
-       touch $@
+       $(call cmd,touch)
  
- kernel/modsign_pubkey.o: signing_key.x509 extra_certificates
+ kernel/modsign_certificate.o: signing_key.x509 extra_certificates
  
  ###############################################################################
  #
diff --combined kernel/module.c
@@@ -21,6 -21,7 +21,7 @@@
  #include <linux/ftrace_event.h>
  #include <linux/init.h>
  #include <linux/kallsyms.h>
+ #include <linux/file.h>
  #include <linux/fs.h>
  #include <linux/sysfs.h>
  #include <linux/kernel.h>
@@@ -28,6 -29,7 +29,7 @@@
  #include <linux/vmalloc.h>
  #include <linux/elf.h>
  #include <linux/proc_fs.h>
+ #include <linux/security.h>
  #include <linux/seq_file.h>
  #include <linux/syscalls.h>
  #include <linux/fcntl.h>
@@@ -59,6 -61,7 +61,7 @@@
  #include <linux/pfn.h>
  #include <linux/bsearch.h>
  #include <linux/fips.h>
+ #include <uapi/linux/module.h>
  #include "module-internal.h"
  
  #define CREATE_TRACE_POINTS
@@@ -372,6 -375,9 +375,6 @@@ static bool check_symbol(const struct s
                        printk(KERN_WARNING "Symbol %s is being used "
                               "by a non-GPL module, which will not "
                               "be allowed in the future\n", fsa->name);
 -                      printk(KERN_WARNING "Please see the file "
 -                             "Documentation/feature-removal-schedule.txt "
 -                             "in the kernel source tree for more details.\n");
                }
        }
  
@@@ -2279,7 -2285,7 +2282,7 @@@ static void layout_symtab(struct modul
        Elf_Shdr *symsect = info->sechdrs + info->index.sym;
        Elf_Shdr *strsect = info->sechdrs + info->index.str;
        const Elf_Sym *src;
-       unsigned int i, nsrc, ndst, strtab_size;
+       unsigned int i, nsrc, ndst, strtab_size = 0;
  
        /* Put symbol section at end of init part of module. */
        symsect->sh_flags |= SHF_ALLOC;
        src = (void *)info->hdr + symsect->sh_offset;
        nsrc = symsect->sh_size / sizeof(*src);
  
-       /* strtab always starts with a nul, so offset 0 is the empty string. */
-       strtab_size = 1;
        /* Compute total space required for the core symbols' strtab. */
        for (ndst = i = 0; i < nsrc; i++) {
                if (i == 0 ||
@@@ -2334,7 -2337,6 +2334,6 @@@ static void add_kallsyms(struct module 
        mod->core_symtab = dst = mod->module_core + info->symoffs;
        mod->core_strtab = s = mod->module_core + info->stroffs;
        src = mod->symtab;
-       *s++ = 0;
        for (ndst = i = 0; i < mod->num_symtab; i++) {
                if (i == 0 ||
                    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
@@@ -2375,7 -2377,7 +2374,7 @@@ static void dynamic_debug_remove(struc
  
  void * __weak module_alloc(unsigned long size)
  {
-       return size == 0 ? NULL : vmalloc_exec(size);
+       return vmalloc_exec(size);
  }
  
  static void *module_alloc_update_bounds(unsigned long size)
@@@ -2422,18 -2424,17 +2421,17 @@@ static inline void kmemleak_load_module
  #endif
  
  #ifdef CONFIG_MODULE_SIG
- static int module_sig_check(struct load_info *info,
-                           const void *mod, unsigned long *_len)
+ static int module_sig_check(struct load_info *info)
  {
        int err = -ENOKEY;
-       unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
-       unsigned long len = *_len;
+       const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
+       const void *mod = info->hdr;
  
-       if (len > markerlen &&
-           memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
+       if (info->len > markerlen &&
+           memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
                /* We truncate the module to discard the signature */
-               *_len -= markerlen;
-               err = mod_verify_sig(mod, _len);
+               info->len -= markerlen;
+               err = mod_verify_sig(mod, &info->len);
        }
  
        if (!err) {
        return err;
  }
  #else /* !CONFIG_MODULE_SIG */
- static int module_sig_check(struct load_info *info,
-                           void *mod, unsigned long *len)
+ static int module_sig_check(struct load_info *info)
  {
        return 0;
  }
  #endif /* !CONFIG_MODULE_SIG */
  
- /* Sets info->hdr, info->len and info->sig_ok. */
- static int copy_and_check(struct load_info *info,
-                         const void __user *umod, unsigned long len,
-                         const char __user *uargs)
+ /* Sanity checks against invalid binaries, wrong arch, weird elf version. */
+ static int elf_header_check(struct load_info *info)
+ {
+       if (info->len < sizeof(*(info->hdr)))
+               return -ENOEXEC;
+       if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
+           || info->hdr->e_type != ET_REL
+           || !elf_check_arch(info->hdr)
+           || info->hdr->e_shentsize != sizeof(Elf_Shdr))
+               return -ENOEXEC;
+       if (info->hdr->e_shoff >= info->len
+           || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
+               info->len - info->hdr->e_shoff))
+               return -ENOEXEC;
+       return 0;
+ }
+ /* Sets info->hdr and info->len. */
+ static int copy_module_from_user(const void __user *umod, unsigned long len,
+                                 struct load_info *info)
  {
        int err;
-       Elf_Ehdr *hdr;
  
-       if (len < sizeof(*hdr))
+       info->len = len;
+       if (info->len < sizeof(*(info->hdr)))
                return -ENOEXEC;
  
+       err = security_kernel_module_from_file(NULL);
+       if (err)
+               return err;
        /* Suck in entire file: we'll want most of it. */
-       if ((hdr = vmalloc(len)) == NULL)
+       info->hdr = vmalloc(info->len);
+       if (!info->hdr)
                return -ENOMEM;
  
-       if (copy_from_user(hdr, umod, len) != 0) {
-               err = -EFAULT;
-               goto free_hdr;
+       if (copy_from_user(info->hdr, umod, info->len) != 0) {
+               vfree(info->hdr);
+               return -EFAULT;
        }
  
-       err = module_sig_check(info, hdr, &len);
+       return 0;
+ }
+ /* Sets info->hdr and info->len. */
+ static int copy_module_from_fd(int fd, struct load_info *info)
+ {
+       struct file *file;
+       int err;
+       struct kstat stat;
+       loff_t pos;
+       ssize_t bytes = 0;
+       file = fget(fd);
+       if (!file)
+               return -ENOEXEC;
+       err = security_kernel_module_from_file(file);
        if (err)
-               goto free_hdr;
+               goto out;
  
-       /* Sanity checks against insmoding binaries or wrong arch,
-          weird elf version */
-       if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0
-           || hdr->e_type != ET_REL
-           || !elf_check_arch(hdr)
-           || hdr->e_shentsize != sizeof(Elf_Shdr)) {
-               err = -ENOEXEC;
-               goto free_hdr;
-       }
+       err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
+       if (err)
+               goto out;
  
-       if (hdr->e_shoff >= len ||
-           hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) {
-               err = -ENOEXEC;
-               goto free_hdr;
+       if (stat.size > INT_MAX) {
+               err = -EFBIG;
+               goto out;
+       }
+       info->hdr = vmalloc(stat.size);
+       if (!info->hdr) {
+               err = -ENOMEM;
+               goto out;
        }
  
-       info->hdr = hdr;
-       info->len = len;
-       return 0;
+       pos = 0;
+       while (pos < stat.size) {
+               bytes = kernel_read(file, pos, (char *)(info->hdr) + pos,
+                                   stat.size - pos);
+               if (bytes < 0) {
+                       vfree(info->hdr);
+                       err = bytes;
+                       goto out;
+               }
+               if (bytes == 0)
+                       break;
+               pos += bytes;
+       }
+       info->len = pos;
  
free_hdr:
-       vfree(hdr);
out:
+       fput(file);
        return err;
  }
  
@@@ -2512,7 -2561,7 +2558,7 @@@ static void free_copy(struct load_info 
        vfree(info->hdr);
  }
  
- static int rewrite_section_headers(struct load_info *info)
+ static int rewrite_section_headers(struct load_info *info, int flags)
  {
        unsigned int i;
  
        }
  
        /* Track but don't keep modinfo and version sections. */
-       info->index.vers = find_sec(info, "__versions");
+       if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
+               info->index.vers = 0; /* Pretend no __versions section! */
+       else
+               info->index.vers = find_sec(info, "__versions");
        info->index.info = find_sec(info, ".modinfo");
        info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
        info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
   * Return the temporary module pointer (we'll replace it with the final
   * one when we move the module sections around).
   */
- static struct module *setup_load_info(struct load_info *info)
+ static struct module *setup_load_info(struct load_info *info, int flags)
  {
        unsigned int i;
        int err;
        info->secstrings = (void *)info->hdr
                + info->sechdrs[info->hdr->e_shstrndx].sh_offset;
  
-       err = rewrite_section_headers(info);
+       err = rewrite_section_headers(info, flags);
        if (err)
                return ERR_PTR(err);
  
        return mod;
  }
  
- static int check_modinfo(struct module *mod, struct load_info *info)
+ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
  {
        const char *modmagic = get_modinfo(info, "vermagic");
        int err;
  
+       if (flags & MODULE_INIT_IGNORE_VERMAGIC)
+               modmagic = NULL;
        /* This is allowed: modprobe --force will invalidate it. */
        if (!modmagic) {
                err = try_to_force_load(mod, "bad vermagic");
@@@ -2738,20 -2793,23 +2790,23 @@@ static int move_module(struct module *m
        memset(ptr, 0, mod->core_size);
        mod->module_core = ptr;
  
-       ptr = module_alloc_update_bounds(mod->init_size);
-       /*
-        * The pointer to this block is stored in the module structure
-        * which is inside the block. This block doesn't need to be
-        * scanned as it contains data and code that will be freed
-        * after the module is initialized.
-        */
-       kmemleak_ignore(ptr);
-       if (!ptr && mod->init_size) {
-               module_free(mod, mod->module_core);
-               return -ENOMEM;
-       }
-       memset(ptr, 0, mod->init_size);
-       mod->module_init = ptr;
+       if (mod->init_size) {
+               ptr = module_alloc_update_bounds(mod->init_size);
+               /*
+                * The pointer to this block is stored in the module structure
+                * which is inside the block. This block doesn't need to be
+                * scanned as it contains data and code that will be freed
+                * after the module is initialized.
+                */
+               kmemleak_ignore(ptr);
+               if (!ptr) {
+                       module_free(mod, mod->module_core);
+                       return -ENOMEM;
+               }
+               memset(ptr, 0, mod->init_size);
+               mod->module_init = ptr;
+       } else
+               mod->module_init = NULL;
  
        /* Transfer each section which specifies SHF_ALLOC */
        pr_debug("final section addresses:\n");
@@@ -2844,18 -2902,18 +2899,18 @@@ int __weak module_frob_arch_sections(El
        return 0;
  }
  
- static struct module *layout_and_allocate(struct load_info *info)
+ static struct module *layout_and_allocate(struct load_info *info, int flags)
  {
        /* Module within temporary copy. */
        struct module *mod;
        Elf_Shdr *pcpusec;
        int err;
  
-       mod = setup_load_info(info);
+       mod = setup_load_info(info, flags);
        if (IS_ERR(mod))
                return mod;
  
-       err = check_modinfo(mod, info);
+       err = check_modinfo(mod, info, flags);
        if (err)
                return ERR_PTR(err);
  
@@@ -2942,33 -3000,124 +2997,124 @@@ static bool finished_loading(const cha
        return ret;
  }
  
+ /* Call module constructors. */
+ static void do_mod_ctors(struct module *mod)
+ {
+ #ifdef CONFIG_CONSTRUCTORS
+       unsigned long i;
+       for (i = 0; i < mod->num_ctors; i++)
+               mod->ctors[i]();
+ #endif
+ }
+ /* This is where the real work happens */
+ static int do_init_module(struct module *mod)
+ {
+       int ret = 0;
+       blocking_notifier_call_chain(&module_notify_list,
+                       MODULE_STATE_COMING, mod);
+       /* Set RO and NX regions for core */
+       set_section_ro_nx(mod->module_core,
+                               mod->core_text_size,
+                               mod->core_ro_size,
+                               mod->core_size);
+       /* Set RO and NX regions for init */
+       set_section_ro_nx(mod->module_init,
+                               mod->init_text_size,
+                               mod->init_ro_size,
+                               mod->init_size);
+       do_mod_ctors(mod);
+       /* Start the module */
+       if (mod->init != NULL)
+               ret = do_one_initcall(mod->init);
+       if (ret < 0) {
+               /* Init routine failed: abort.  Try to protect us from
+                    buggy refcounters. */
+               mod->state = MODULE_STATE_GOING;
+               synchronize_sched();
+               module_put(mod);
+               blocking_notifier_call_chain(&module_notify_list,
+                                            MODULE_STATE_GOING, mod);
+               free_module(mod);
+               wake_up_all(&module_wq);
+               return ret;
+       }
+       if (ret > 0) {
+               printk(KERN_WARNING
+ "%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
+ "%s: loading module anyway...\n",
+                      __func__, mod->name, ret,
+                      __func__);
+               dump_stack();
+       }
+       /* Now it's a first class citizen! */
+       mod->state = MODULE_STATE_LIVE;
+       blocking_notifier_call_chain(&module_notify_list,
+                                    MODULE_STATE_LIVE, mod);
+       /* We need to finish all async code before the module init sequence is done */
+       async_synchronize_full();
+       mutex_lock(&module_mutex);
+       /* Drop initial reference. */
+       module_put(mod);
+       trim_init_extable(mod);
+ #ifdef CONFIG_KALLSYMS
+       mod->num_symtab = mod->core_num_syms;
+       mod->symtab = mod->core_symtab;
+       mod->strtab = mod->core_strtab;
+ #endif
+       unset_module_init_ro_nx(mod);
+       module_free(mod, mod->module_init);
+       mod->module_init = NULL;
+       mod->init_size = 0;
+       mod->init_ro_size = 0;
+       mod->init_text_size = 0;
+       mutex_unlock(&module_mutex);
+       wake_up_all(&module_wq);
+       return 0;
+ }
+ static int may_init_module(void)
+ {
+       if (!capable(CAP_SYS_MODULE) || modules_disabled)
+               return -EPERM;
+       return 0;
+ }
  /* Allocate and load the module: note that size of section 0 is always
     zero, and we rely on this for optional sections. */
- static struct module *load_module(void __user *umod,
-                                 unsigned long len,
-                                 const char __user *uargs)
+ static int load_module(struct load_info *info, const char __user *uargs,
+                      int flags)
  {
-       struct load_info info = { NULL, };
        struct module *mod, *old;
        long err;
  
-       pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n",
-              umod, len, uargs);
+       err = module_sig_check(info);
+       if (err)
+               goto free_copy;
  
-       /* Copy in the blobs from userspace, check they are vaguely sane. */
-       err = copy_and_check(&info, umod, len, uargs);
+       err = elf_header_check(info);
        if (err)
-               return ERR_PTR(err);
+               goto free_copy;
  
        /* Figure out module layout, and allocate all the memory. */
-       mod = layout_and_allocate(&info);
+       mod = layout_and_allocate(info, flags);
        if (IS_ERR(mod)) {
                err = PTR_ERR(mod);
                goto free_copy;
        }
  
  #ifdef CONFIG_MODULE_SIG
-       mod->sig_ok = info.sig_ok;
+       mod->sig_ok = info->sig_ok;
        if (!mod->sig_ok)
                add_taint_module(mod, TAINT_FORCED_MODULE);
  #endif
  
        /* Now we've got everything in the final locations, we can
         * find optional sections. */
-       find_module_sections(mod, &info);
+       find_module_sections(mod, info);
  
        err = check_module_license_and_versions(mod);
        if (err)
                goto free_unload;
  
        /* Set up MODINFO_ATTR fields */
-       setup_modinfo(mod, &info);
+       setup_modinfo(mod, info);
  
        /* Fix up syms, so that st_value is a pointer to location. */
-       err = simplify_symbols(mod, &info);
+       err = simplify_symbols(mod, info);
        if (err < 0)
                goto free_modinfo;
  
-       err = apply_relocations(mod, &info);
+       err = apply_relocations(mod, info);
        if (err < 0)
                goto free_modinfo;
  
-       err = post_relocation(mod, &info);
+       err = post_relocation(mod, info);
        if (err < 0)
                goto free_modinfo;
  
@@@ -3038,14 -3187,14 +3184,14 @@@ again
        }
  
        /* This has to be done once we're sure module name is unique. */
-       dynamic_debug_setup(info.debug, info.num_debug);
+       dynamic_debug_setup(info->debug, info->num_debug);
  
        /* Find duplicate symbols */
        err = verify_export_symbols(mod);
        if (err < 0)
                goto ddebug;
  
-       module_bug_finalize(info.hdr, info.sechdrs, mod);
+       module_bug_finalize(info->hdr, info->sechdrs, mod);
        list_add_rcu(&mod->list, &modules);
        mutex_unlock(&module_mutex);
  
                goto unlink;
  
        /* Link in to syfs. */
-       err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp);
+       err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
        if (err < 0)
                goto unlink;
  
        /* Get rid of temporary copy. */
-       free_copy(&info);
+       free_copy(info);
  
        /* Done! */
        trace_module_load(mod);
-       return mod;
+       return do_init_module(mod);
  
   unlink:
        mutex_lock(&module_mutex);
        module_bug_cleanup(mod);
        wake_up_all(&module_wq);
   ddebug:
-       dynamic_debug_remove(info.debug);
+       dynamic_debug_remove(info->debug);
   unlock:
        mutex_unlock(&module_mutex);
        synchronize_sched();
   free_unload:
        module_unload_free(mod);
   free_module:
-       module_deallocate(mod, &info);
+       module_deallocate(mod, info);
   free_copy:
-       free_copy(&info);
-       return ERR_PTR(err);
- }
- /* Call module constructors. */
- static void do_mod_ctors(struct module *mod)
- {
- #ifdef CONFIG_CONSTRUCTORS
-       unsigned long i;
-       for (i = 0; i < mod->num_ctors; i++)
-               mod->ctors[i]();
- #endif
+       free_copy(info);
+       return err;
  }
  
- /* This is where the real work happens */
  SYSCALL_DEFINE3(init_module, void __user *, umod,
                unsigned long, len, const char __user *, uargs)
  {
-       struct module *mod;
-       int ret = 0;
+       int err;
+       struct load_info info = { };
  
-       /* Must have permission */
-       if (!capable(CAP_SYS_MODULE) || modules_disabled)
-               return -EPERM;
+       err = may_init_module();
+       if (err)
+               return err;
  
-       /* Do all the hard work */
-       mod = load_module(umod, len, uargs);
-       if (IS_ERR(mod))
-               return PTR_ERR(mod);
+       pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
+              umod, len, uargs);
  
-       blocking_notifier_call_chain(&module_notify_list,
-                       MODULE_STATE_COMING, mod);
+       err = copy_module_from_user(umod, len, &info);
+       if (err)
+               return err;
  
-       /* Set RO and NX regions for core */
-       set_section_ro_nx(mod->module_core,
-                               mod->core_text_size,
-                               mod->core_ro_size,
-                               mod->core_size);
+       return load_module(&info, uargs, 0);
+ }
  
-       /* Set RO and NX regions for init */
-       set_section_ro_nx(mod->module_init,
-                               mod->init_text_size,
-                               mod->init_ro_size,
-                               mod->init_size);
+ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
+ {
+       int err;
+       struct load_info info = { };
  
-       do_mod_ctors(mod);
-       /* Start the module */
-       if (mod->init != NULL)
-               ret = do_one_initcall(mod->init);
-       if (ret < 0) {
-               /* Init routine failed: abort.  Try to protect us from
-                    buggy refcounters. */
-               mod->state = MODULE_STATE_GOING;
-               synchronize_sched();
-               module_put(mod);
-               blocking_notifier_call_chain(&module_notify_list,
-                                            MODULE_STATE_GOING, mod);
-               free_module(mod);
-               wake_up_all(&module_wq);
-               return ret;
-       }
-       if (ret > 0) {
-               printk(KERN_WARNING
- "%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
- "%s: loading module anyway...\n",
-                      __func__, mod->name, ret,
-                      __func__);
-               dump_stack();
-       }
+       err = may_init_module();
+       if (err)
+               return err;
  
-       /* Now it's a first class citizen! */
-       mod->state = MODULE_STATE_LIVE;
-       blocking_notifier_call_chain(&module_notify_list,
-                                    MODULE_STATE_LIVE, mod);
+       pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags);
  
-       /* We need to finish all async code before the module init sequence is done */
-       async_synchronize_full();
+       if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS
+                     |MODULE_INIT_IGNORE_VERMAGIC))
+               return -EINVAL;
  
-       mutex_lock(&module_mutex);
-       /* Drop initial reference. */
-       module_put(mod);
-       trim_init_extable(mod);
- #ifdef CONFIG_KALLSYMS
-       mod->num_symtab = mod->core_num_syms;
-       mod->symtab = mod->core_symtab;
-       mod->strtab = mod->core_strtab;
- #endif
-       unset_module_init_ro_nx(mod);
-       module_free(mod, mod->module_init);
-       mod->module_init = NULL;
-       mod->init_size = 0;
-       mod->init_ro_size = 0;
-       mod->init_text_size = 0;
-       mutex_unlock(&module_mutex);
-       wake_up_all(&module_wq);
+       err = copy_module_from_fd(fd, &info);
+       if (err)
+               return err;
  
-       return 0;
+       return load_module(&info, uargs, flags);
  }
  
  static inline int within(unsigned long addr, void *start, unsigned long size)
diff --combined lib/asn1_decoder.c
@@@ -81,7 -81,7 +81,7 @@@ next_tag
                goto next_tag;
        }
  
-       if (unlikely((tag & 0x1f) == 0x1f)) {
+       if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) {
                do {
                        if (unlikely(datalen - dp < 2))
                                goto data_overrun_error;
  
        /* Extract the length */
        len = data[dp++];
 -      if (len < 0x7f) {
 +      if (len <= 0x7f) {
                dp += len;
                goto next_tag;
        }
  
-       if (unlikely(len == 0x80)) {
+       if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
                /* Indefinite length */
                if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5))
                        goto indefinite_len_primitive;
@@@ -222,7 -222,7 +222,7 @@@ next_op
                if (unlikely(dp >= datalen - 1))
                        goto data_overrun_error;
                tag = data[dp++];
-               if (unlikely((tag & 0x1f) == 0x1f))
+               if (unlikely((tag & 0x1f) == ASN1_LONG_TAG))
                        goto long_tag_not_supported;
  
                if (op & ASN1_OP_MATCH__ANY) {
  
                len = data[dp++];
                if (len > 0x7f) {
-                       if (unlikely(len == 0x80)) {
+                       if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
                                /* Indefinite length */
                                if (unlikely(!(tag & ASN1_CONS_BIT)))
                                        goto indefinite_len_primitive;