Files
kernel_google_wahoo/mm/maccess.c
Nathan Chancellor 725f0b5505 Merge 4.4.236 into android-msm-wahoo-4.4
Changes in 4.4.236: (63 commits)
        HID: core: Correctly handle ReportSize being zero
        HID: core: Sanitize event code and type when mapping input
        perf record/stat: Explicitly call out event modifiers in the documentation
        mm, page_alloc: remove unnecessary variable from free_pcppages_bulk
        hwmon: (applesmc) check status earlier.
        ceph: don't allow setlease on cephfs
        s390: don't trace preemption in percpu macros
        xen/xenbus: Fix granting of vmalloc'd memory
        dmaengine: of-dma: Fix of_dma_router_xlate's of_dma_xlate handling
        batman-adv: Avoid uninitialized chaddr when handling DHCP
        batman-adv: bla: use netif_rx_ni when not in interrupt context
        dmaengine: at_hdmac: check return value of of_find_device_by_node() in at_dma_xlate()
        netfilter: nf_tables: incorrect enum nft_list_attributes definition
        netfilter: nf_tables: fix destination register zeroing
        dmaengine: pl330: Fix burst length if burst size is smaller than bus width
        bnxt_en: Check for zero dir entries in NVRAM.
        fix regression in "epoll: Keep a reference on files added to the check list"
        tg3: Fix soft lockup when tg3_reset_task() fails.
        iommu/vt-d: Serialize IOMMU GCMD register modifications
        thermal: ti-soc-thermal: Fix bogus thermal shutdowns for omap4430
        include/linux/log2.h: add missing () around n in roundup_pow_of_two()
        btrfs: drop path before adding new uuid tree entry
        btrfs: Remove redundant extent_buffer_get in get_old_root
        btrfs: Remove extraneous extent_buffer_get from tree_mod_log_rewind
        btrfs: set the lockdep class for log tree extent buffers
        uaccess: Add non-pagefault user-space read functions
        uaccess: Add non-pagefault user-space write function
        btrfs: fix potential deadlock in the search ioctl
        net: qmi_wwan: MDM9x30 specific power management
        net: qmi_wwan: support "raw IP" mode
        net: qmi_wwan: should hold RTNL while changing netdev type
        net: qmi_wwan: ignore bogus CDC Union descriptors
        Add Dell Wireless 5809e Gobi 4G HSPA+ Mobile Broadband Card (rev3) to qmi_wwan
        qmi_wwan: Added support for Gemalto's Cinterion PHxx WWAN interface
        qmi_wwan: add support for Quectel EC21 and EC25
        NET: usb: qmi_wwan: add support for Telit LE922A PID 0x1040
        drivers: net: usb: qmi_wwan: add QMI_QUIRK_SET_DTR for Telit PID 0x1201
        usb: qmi_wwan: add D-Link DWM-222 A2 device ID
        net: usb: qmi_wwan: add Telit ME910 support
        net: usb: qmi_wwan: add Telit 0x1050 composition
        ALSA: ca0106: fix error code handling
        ALSA: pcm: oss: Remove superfluous WARN_ON() for mulaw sanity check
        dm cache metadata: Avoid returning cmd->bm wild pointer on error
        dm thin metadata: Avoid returning cmd->bm wild pointer on error
        net: refactor bind_bucket fastreuse into helper
        net: initialize fastreuse on inet_inherit_port
        checkpatch: fix the usage of capture group ( ... )
        mm/hugetlb: fix a race between hugetlb sysctl handlers
        cfg80211: regulatory: reject invalid hints
        net: usb: Fix uninit-was-stored issue in asix_read_phy_addr()
        ALSA: firewire-digi00x: add support for console models of Digi00x series
        ALSA: firewire-digi00x: exclude Avid Adrenaline from detection
        ALSA; firewire-tascam: exclude Tascam FE-8 from detection
        fs/affs: use octal for permissions
        affs: fix basic permission bits to actually work
        ravb: Fixed to be able to unload modules
        net: ethernet: mlx4: Fix memory allocation in mlx4_buddy_init()
        bnxt_en: Failure to update PHY is not fatal condition.
        bnxt: don't enable NAPI until rings are ready
        net: usb: dm9601: Add USB ID of Keenetic Plus DSL
        sctp: not disable bh in the whole sctp_get_port_local()
        net: disable netpoll on fresh napis
        Linux 4.4.236

Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
2020-09-12 09:47:22 -07:00

255 lines
6.8 KiB
C

/*
* Access kernel memory without faulting.
*/
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
static __always_inline long
probe_read_common(void *dst, const void __user *src, size_t size)
{
long ret;
pagefault_disable();
ret = __copy_from_user_inatomic(dst, src, size);
pagefault_enable();
return ret ? -EFAULT : 0;
}
static __always_inline long
probe_write_common(void __user *dst, const void *src, size_t size)
{
long ret;
pagefault_disable();
ret = __copy_to_user_inatomic(dst, src, size);
pagefault_enable();
return ret ? -EFAULT : 0;
}
/**
* probe_kernel_read(): safely attempt to read from a kernel-space location
* @dst: pointer to the buffer that shall take the data
* @src: address to read from
* @size: size of the data chunk
*
* Safely read from address @src to the buffer at @dst. If a kernel fault
* happens, handle that and return -EFAULT.
*
* We ensure that the copy_from_user is executed in atomic context so that
* do_page_fault() doesn't attempt to take mmap_sem. This makes
* probe_kernel_read() suitable for use within regions where the caller
* already holds mmap_sem, or other locks which nest inside mmap_sem.
*/
long __weak probe_kernel_read(void *dst, const void *src, size_t size)
__attribute__((alias("__probe_kernel_read")));
long __probe_kernel_read(void *dst, const void *src, size_t size)
{
long ret;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
ret = probe_read_common(dst, (__force const void __user *)src, size);
set_fs(old_fs);
return ret;
}
EXPORT_SYMBOL_GPL(probe_kernel_read);
/**
* probe_user_read(): safely attempt to read from a user-space location
* @dst: pointer to the buffer that shall take the data
* @src: address to read from. This must be a user address.
* @size: size of the data chunk
*
* Safely read from user address @src to the buffer at @dst. If a kernel fault
* happens, handle that and return -EFAULT.
*/
long __weak probe_user_read(void *dst, const void __user *src, size_t size)
__attribute__((alias("__probe_user_read")));
long __probe_user_read(void *dst, const void __user *src, size_t size)
{
long ret = -EFAULT;
mm_segment_t old_fs = get_fs();
set_fs(USER_DS);
if (access_ok(VERIFY_READ, src, size))
ret = probe_read_common(dst, src, size);
set_fs(old_fs);
return ret;
}
EXPORT_SYMBOL_GPL(probe_user_read);
/**
* probe_kernel_write(): safely attempt to write to a location
* @dst: address to write to
* @src: pointer to the data that shall be written
* @size: size of the data chunk
*
* Safely write to address @dst from the buffer at @src. If a kernel fault
* happens, handle that and return -EFAULT.
*/
long __weak probe_kernel_write(void *dst, const void *src, size_t size)
__attribute__((alias("__probe_kernel_write")));
long __probe_kernel_write(void *dst, const void *src, size_t size)
{
long ret;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
ret = probe_write_common((__force void __user *)dst, src, size);
set_fs(old_fs);
return ret;
}
EXPORT_SYMBOL_GPL(probe_kernel_write);
/**
* probe_user_write(): safely attempt to write to a user-space location
* @dst: address to write to
* @src: pointer to the data that shall be written
* @size: size of the data chunk
*
* Safely write to address @dst from the buffer at @src. If a kernel fault
* happens, handle that and return -EFAULT.
*/
long __weak probe_user_write(void __user *dst, const void *src, size_t size)
__attribute__((alias("__probe_user_write")));
long __probe_user_write(void __user *dst, const void *src, size_t size)
{
long ret = -EFAULT;
mm_segment_t old_fs = get_fs();
set_fs(USER_DS);
if (access_ok(VERIFY_WRITE, dst, size))
ret = probe_write_common(dst, src, size);
set_fs(old_fs);
return ret;
}
EXPORT_SYMBOL_GPL(probe_user_write);
/**
* strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address.
* @dst: Destination address, in kernel space. This buffer must be at
* least @count bytes long.
* @src: Unsafe address.
* @count: Maximum number of bytes to copy, including the trailing NUL.
*
* Copies a NUL-terminated string from unsafe address to kernel buffer.
*
* On success, returns the length of the string INCLUDING the trailing NUL.
*
* If access fails, returns -EFAULT (some data may have been copied
* and the trailing NUL added).
*
* If @count is smaller than the length of the string, copies @count-1 bytes,
* sets the last byte of @dst buffer to NUL and returns @count.
*/
long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
{
mm_segment_t old_fs = get_fs();
const void *src = unsafe_addr;
long ret;
if (unlikely(count <= 0))
return 0;
set_fs(KERNEL_DS);
pagefault_disable();
do {
ret = __get_user(*dst++, (const char __user __force *)src++);
} while (dst[-1] && ret == 0 && src - unsafe_addr < count);
dst[-1] = '\0';
pagefault_enable();
set_fs(old_fs);
return ret ? -EFAULT : src - unsafe_addr;
}
/**
* strncpy_from_unsafe_user: - Copy a NUL terminated string from unsafe user
* address.
* @dst: Destination address, in kernel space. This buffer must be at
* least @count bytes long.
* @unsafe_addr: Unsafe user address.
* @count: Maximum number of bytes to copy, including the trailing NUL.
*
* Copies a NUL-terminated string from unsafe user address to kernel buffer.
*
* On success, returns the length of the string INCLUDING the trailing NUL.
*
* If access fails, returns -EFAULT (some data may have been copied
* and the trailing NUL added).
*
* If @count is smaller than the length of the string, copies @count-1 bytes,
* sets the last byte of @dst buffer to NUL and returns @count.
*/
long strncpy_from_unsafe_user(char *dst, const void __user *unsafe_addr,
long count)
{
mm_segment_t old_fs = get_fs();
long ret;
if (unlikely(count <= 0))
return 0;
set_fs(USER_DS);
pagefault_disable();
ret = strncpy_from_user(dst, unsafe_addr, count);
pagefault_enable();
set_fs(old_fs);
if (ret >= count) {
ret = count;
dst[ret - 1] = '\0';
} else if (ret > 0) {
ret++;
}
return ret;
}
/**
* strnlen_unsafe_user: - Get the size of a user string INCLUDING final NUL.
* @unsafe_addr: The string to measure.
* @count: Maximum count (including NUL)
*
* Get the size of a NUL-terminated string in user space without pagefault.
*
* Returns the size of the string INCLUDING the terminating NUL.
*
* If the string is too long, returns a number larger than @count. User
* has to check the return value against "> count".
* On exception (or invalid count), returns 0.
*
* Unlike strnlen_user, this can be used from IRQ handler etc. because
* it disables pagefaults.
*/
long strnlen_unsafe_user(const void __user *unsafe_addr, long count)
{
mm_segment_t old_fs = get_fs();
int ret;
set_fs(USER_DS);
pagefault_disable();
ret = strnlen_user(unsafe_addr, count);
pagefault_enable();
set_fs(old_fs);
return ret;
}