Re: [PATCH v2] libkmod: add finit_module logic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi, just checking on this. Any objections to this patch? I'd like to
get it into the tree so more people can verify it.

Thanks!

-Kees

On Tue, Jan 22, 2013 at 9:54 PM, Kees Cook <keescook@xxxxxxxxxxxx> wrote:
> When a module is being loaded directly from disk (no compression,
> etc), pass the file descriptor to the new finit_module() syscall. If
> finit_module is exported by glibc, use it. Otherwise, manually make
> the syscall on architectures where it is known to exist. Also update
> testsuite to expect the call, and fix callers of mmap() to use NULL
> instead of 0.
>
> Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
> ---
>  configure.ac              |    1 +
>  libkmod/libkmod-file.c    |   16 +++++++++++++++-
>  libkmod/libkmod-index.c   |    4 ++--
>  libkmod/libkmod-module.c  |   29 +++++++++++++++++++++++++++++
>  libkmod/libkmod-private.h |    2 ++
>  testsuite/init_module.c   |   24 ++++++++++++++++++++++++
>  6 files changed, 73 insertions(+), 3 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index 0f86c25..faab6bd 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -39,6 +39,7 @@ PKG_PROG_PKG_CONFIG
>  #####################################################################
>
>  AC_CHECK_FUNCS_ONCE(__xstat)
> +AC_CHECK_FUNCS_ONCE(finit_module)
>
>  # dietlibc doesn't have st.st_mtim struct member
>  AC_CHECK_MEMBERS([struct stat.st_mtim], [], [], [#include <sys/stat.h>])
> diff --git a/libkmod/libkmod-file.c b/libkmod/libkmod-file.c
> index ced20a8..76585f5 100644
> --- a/libkmod/libkmod-file.c
> +++ b/libkmod/libkmod-file.c
> @@ -52,6 +52,7 @@ struct kmod_file {
>         gzFile gzf;
>  #endif
>         int fd;
> +       int direct;
>         off_t size;
>         void *memory;
>         const struct file_ops *ops;
> @@ -254,9 +255,11 @@ static int load_reg(struct kmod_file *file)
>                 return -errno;
>
>         file->size = st.st_size;
> -       file->memory = mmap(0, file->size, PROT_READ, MAP_PRIVATE, file->fd, 0);
> +       file->memory = mmap(NULL, file->size, PROT_READ, MAP_PRIVATE,
> +                           file->fd, 0);
>         if (file->memory == MAP_FAILED)
>                 return -errno;
> +       file->direct = 1;
>         return 0;
>  }
>
> @@ -300,6 +303,7 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
>                         magic_size_max = itr->magic_size;
>         }
>
> +       file->direct = 0;
>         if (magic_size_max > 0) {
>                 char *buf = alloca(magic_size_max + 1);
>                 ssize_t sz;
> @@ -353,6 +357,16 @@ off_t kmod_file_get_size(const struct kmod_file *file)
>         return file->size;
>  }
>
> +int kmod_file_get_direct(const struct kmod_file *file)
> +{
> +       return file->direct;
> +}
> +
> +int kmod_file_get_fd(const struct kmod_file *file)
> +{
> +       return file->fd;
> +}
> +
>  void kmod_file_unref(struct kmod_file *file)
>  {
>         if (file->elf)
> diff --git a/libkmod/libkmod-index.c b/libkmod/libkmod-index.c
> index 516240e..d386f00 100644
> --- a/libkmod/libkmod-index.c
> +++ b/libkmod/libkmod-index.c
> @@ -801,9 +801,9 @@ struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename,
>         if ((size_t) st.st_size < sizeof(hdr))
>                 goto fail_nommap;
>
> -       if ((idx->mm = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0))
> +       if ((idx->mm = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0))
>                                                         == MAP_FAILED) {
> -               ERR(ctx, "mmap(0, %"PRIu64", PROT_READ, %d, MAP_PRIVATE, 0): %m\n",
> +               ERR(ctx, "mmap(NULL, %"PRIu64", PROT_READ, %d, MAP_PRIVATE, 0): %m\n",
>                                                         st.st_size, fd);
>                 goto fail_nommap;
>         }
> diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
> index b1d40b1..31ad5fc 100644
> --- a/libkmod/libkmod-module.c
> +++ b/libkmod/libkmod-module.c
> @@ -762,6 +762,26 @@ KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
>  }
>
>  extern long init_module(const void *mem, unsigned long len, const char *args);
> +#ifdef HAVE_FINIT_MODULE
> +extern int finit_module(int fd, const char *uargs, int flags);
> +#else
> +# include <sys/syscall.h>
> +# ifndef __NR_finit_module
> +#  if defined(__x86_64__)
> +#   define __NR_finit_module 313
> +#  elif defined(__i386__)
> +#   define __NR_finit_module 350
> +#  elif defined(__arm__)
> +#   define __NR_finit_module 379
> +#  else
> +#   define __NR_finit_module -1
> +#  endif
> +# endif
> +static inline int finit_module(int fd, const char *uargs, int flags)
> +{
> +   return syscall(__NR_finit_module, fd, uargs, flags);
> +}
> +#endif
>
>  /**
>   * kmod_module_insert_module:
> @@ -803,6 +823,14 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
>                 return err;
>         }
>
> +       if (kmod_file_get_direct(file)) {
> +               err = finit_module(kmod_file_get_fd(file), args,
> +                                  flags & (KMOD_INSERT_FORCE_VERMAGIC |
> +                                           KMOD_INSERT_FORCE_MODVERSION));
> +               if (err == 0 || errno != ENOSYS)
> +                       goto init_finished;
> +       }
> +
>         size = kmod_file_get_size(file);
>         mem = kmod_file_get_contents(file);
>
> @@ -829,6 +857,7 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
>         }
>
>         err = init_module(mem, size, args);
> +init_finished:
>         if (err < 0) {
>                 err = -errno;
>                 INFO(mod->ctx, "Failed to insert module '%s': %m\n", path);
> diff --git a/libkmod/libkmod-private.h b/libkmod/libkmod-private.h
> index b472c62..c765003 100644
> --- a/libkmod/libkmod-private.h
> +++ b/libkmod/libkmod-private.h
> @@ -142,6 +142,8 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx, const char *filenam
>  struct kmod_elf *kmod_file_get_elf(struct kmod_file *file) __attribute__((nonnull(1)));
>  void *kmod_file_get_contents(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
>  off_t kmod_file_get_size(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
> +int kmod_file_get_direct(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
> +int kmod_file_get_fd(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
>  void kmod_file_unref(struct kmod_file *file) __attribute__((nonnull(1)));
>
>  /* libkmod-elf.c */
> diff --git a/testsuite/init_module.c b/testsuite/init_module.c
> index c4d7efb..ca9f84c 100644
> --- a/testsuite/init_module.c
> +++ b/testsuite/init_module.c
> @@ -28,6 +28,7 @@
>  #include <stddef.h>
>  #include <string.h>
>  #include <stdio.h>
> +#include <sys/mman.h>
>  #include <sys/types.h>
>  #include <sys/stat.h>
>  #include <unistd.h>
> @@ -274,6 +275,29 @@ long init_module(void *mem, unsigned long len, const char *args)
>         return err;
>  }
>
> +TS_EXPORT int finit_module(const int fd, const char *args, const int flags);
> +
> +int finit_module(const int fd, const char *args, const int flags)
> +{
> +       int err;
> +       void *mem;
> +       unsigned long len;
> +       struct stat st;
> +
> +       if (fstat(fd, &st) < 0)
> +               return -1;
> +
> +       len = st.st_size;
> +       mem = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
> +       if (mem == MAP_FAILED)
> +               return -1;
> +
> +       err = init_module(mem, len, args);
> +       munmap(mem, len);
> +
> +       return err;
> +}
> +
>  /* the test is going away anyway, but lets keep valgrind happy */
>  void free_resources(void) __attribute__((destructor));
>  void free_resources(void)
> --
> 1.7.9.5
>
>
> --
> Kees Cook
> Chrome OS Security



-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-modules" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux