lkml.org 
[lkml]   [2020]   [May]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 15/20] maccess: allow architectures to provide kernel probing directly
    Date
    Provide alternative versions of probe_kernel_read, probe_kernel_write
    and strncpy_from_kernel_unsafe that don't need set_fs magic, but instead
    use arch hooks that are modelled after unsafe_{get,put}_user to access
    kernel memory in an exception safe way.

    Signed-off-by: Christoph Hellwig <hch@lst.de>
    ---
    mm/maccess.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 76 insertions(+)

    diff --git a/mm/maccess.c b/mm/maccess.c
    index 9773e2253b495..01129cbdf4484 100644
    --- a/mm/maccess.c
    +++ b/mm/maccess.c
    @@ -12,6 +12,81 @@ bool __weak probe_kernel_read_allowed(void *dst, const void *unsafe_src,
    return true;
    }

    +#ifdef HAVE_GET_KERNEL_NOFAULT
    +
    +#define probe_kernel_read_loop(dst, src, len, type, err_label) \
    + while (len >= sizeof(type)) { \
    + __get_kernel_nofault(dst, src, type, err_label); \
    + dst += sizeof(type); \
    + src += sizeof(type); \
    + len -= sizeof(type); \
    + }
    +
    +long probe_kernel_read(void *dst, const void *src, size_t size)
    +{
    + if (!probe_kernel_read_allowed(dst, src, size))
    + return -EFAULT;
    +
    + pagefault_disable();
    + probe_kernel_read_loop(dst, src, size, u64, Efault);
    + probe_kernel_read_loop(dst, src, size, u32, Efault);
    + probe_kernel_read_loop(dst, src, size, u16, Efault);
    + probe_kernel_read_loop(dst, src, size, u8, Efault);
    + pagefault_enable();
    + return 0;
    +Efault:
    + pagefault_enable();
    + return -EFAULT;
    +}
    +EXPORT_SYMBOL_GPL(probe_kernel_read);
    +
    +#define probe_kernel_write_loop(dst, src, len, type, err_label) \
    + while (len >= sizeof(type)) { \
    + __put_kernel_nofault(dst, src, type, err_label); \
    + dst += sizeof(type); \
    + src += sizeof(type); \
    + len -= sizeof(type); \
    + }
    +
    +long probe_kernel_write(void *dst, const void *src, size_t size)
    +{
    + pagefault_disable();
    + probe_kernel_write_loop(dst, src, size, u64, Efault);
    + probe_kernel_write_loop(dst, src, size, u32, Efault);
    + probe_kernel_write_loop(dst, src, size, u16, Efault);
    + probe_kernel_write_loop(dst, src, size, u8, Efault);
    + pagefault_enable();
    + return 0;
    +Efault:
    + pagefault_enable();
    + return -EFAULT;
    +}
    +
    +long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
    +{
    + const void *src = unsafe_addr;
    +
    + if (unlikely(count <= 0))
    + return 0;
    + if (!probe_kernel_read_allowed(dst, unsafe_addr, count))
    + return -EFAULT;
    +
    + pagefault_disable();
    + do {
    + __get_kernel_nofault(dst, src, u8, Efault);
    + dst++;
    + src++;
    + } while (dst[-1] && src - unsafe_addr < count);
    + pagefault_enable();
    +
    + dst[-1] = '\0';
    + return src - unsafe_addr;
    +Efault:
    + pagefault_enable();
    + dst[-1] = '\0';
    + return -EFAULT;
    +}
    +#else /* HAVE_GET_KERNEL_NOFAULT */
    /**
    * probe_kernel_read(): safely attempt to read from kernel-space
    * @dst: pointer to the buffer that shall take the data
    @@ -114,6 +189,7 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)

    return ret ? -EFAULT : src - unsafe_addr;
    }
    +#endif /* HAVE_GET_KERNEL_NOFAULT */

    /**
    * probe_user_read(): safely attempt to read from a user-space location
    --
    2.26.2
    \
     
     \ /
      Last update: 2020-05-19 15:46    [W:2.055 / U:1.308 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site