From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Ingo Molnar <mingo@kernel.org>,
Masami Hiramatsu <mhiramat@kernel.org>,
"Steven Rostedt (VMware)" <rostedt@goodmis.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 4.14 42/65] uaccess: Add non-pagefault user-space read functions
Date: Tue, 8 Sep 2020 17:26:27 +0200 [thread overview]
Message-ID: <20200908152219.211957098@linuxfoundation.org> (raw)
In-Reply-To: <20200908152217.022816723@linuxfoundation.org>
From: Masami Hiramatsu <mhiramat@kernel.org>
[ Upstream commit 3d7081822f7f9eab867d9bcc8fd635208ec438e0 ]
Add probe_user_read(), strncpy_from_unsafe_user() and
strnlen_unsafe_user() which allows caller to access user-space
in IRQ context.
Current probe_kernel_read() and strncpy_from_unsafe() are
not available for user-space memory, because it sets
KERNEL_DS while accessing data. On some arch, user address
space and kernel address space can be co-exist, but others
can not. In that case, setting KERNEL_DS means given
address is treated as a kernel address space.
Also strnlen_user() is only available from user context since
it can sleep if pagefault is enabled.
To access user-space memory without pagefault, we need
these new functions which sets USER_DS while accessing
the data.
Link: http://lkml.kernel.org/r/155789869802.26965.4940338412595759063.stgit@devnote2
Acked-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/linux/uaccess.h | 14 +++++
mm/maccess.c | 122 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 130 insertions(+), 6 deletions(-)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index ec4f0053d6d8e..c64a685a55640 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -242,6 +242,17 @@ static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
extern long probe_kernel_read(void *dst, const void *src, size_t size);
extern long __probe_kernel_read(void *dst, const void *src, size_t size);
+/*
+ * probe_user_read(): safely attempt to read from a location in user space
+ * @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.
+ */
+extern long probe_user_read(void *dst, const void __user *src, size_t size);
+
/*
* probe_kernel_write(): safely attempt to write to a location
* @dst: address to write to
@@ -255,6 +266,9 @@ extern long notrace probe_kernel_write(void *dst, const void *src, size_t size);
extern long notrace __probe_kernel_write(void *dst, const void *src, size_t size);
extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count);
+extern long strncpy_from_unsafe_user(char *dst, const void __user *unsafe_addr,
+ long count);
+extern long strnlen_unsafe_user(const void __user *unsafe_addr, long count);
/**
* probe_kernel_address(): safely attempt to read from a location
diff --git a/mm/maccess.c b/mm/maccess.c
index 78f9274dd49d0..5ebf9a3ca3674 100644
--- a/mm/maccess.c
+++ b/mm/maccess.c
@@ -5,8 +5,20 @@
#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;
+}
+
/**
- * probe_kernel_read(): safely attempt to read from a location
+ * 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
@@ -29,16 +41,40 @@ long __probe_kernel_read(void *dst, const void *src, size_t size)
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
- pagefault_disable();
- ret = __copy_from_user_inatomic(dst,
- (__force const void __user *)src, size);
- pagefault_enable();
+ ret = probe_read_common(dst, (__force const void __user *)src, size);
set_fs(old_fs);
- return ret ? -EFAULT : 0;
+ 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
@@ -66,6 +102,7 @@ long __probe_kernel_write(void *dst, const void *src, size_t size)
}
EXPORT_SYMBOL_GPL(probe_kernel_write);
+
/**
* strncpy_from_unsafe: - Copy a NUL terminated string from unsafe address.
* @dst: Destination address, in kernel space. This buffer must be at
@@ -105,3 +142,76 @@ long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
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;
+}
--
2.25.1
next prev parent reply other threads:[~2020-09-08 17:51 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-08 15:25 [PATCH 4.14 00/65] 4.14.197-rc1 review Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 01/65] HID: core: Correctly handle ReportSize being zero Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 02/65] HID: core: Sanitize event code and type when mapping input Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 03/65] perf record/stat: Explicitly call out event modifiers in the documentation Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 04/65] drm/msm: add shutdown support for display platform_driver Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 05/65] hwmon: (applesmc) check status earlier Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 06/65] nvmet: Disable keep-alive timer when kato is cleared to 0h Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 07/65] ceph: dont allow setlease on cephfs Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 08/65] cpuidle: Fixup IRQ state Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 09/65] s390: dont trace preemption in percpu macros Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 10/65] xen/xenbus: Fix granting of vmallocd memory Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 11/65] dmaengine: of-dma: Fix of_dma_router_xlates of_dma_xlate handling Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 12/65] batman-adv: Avoid uninitialized chaddr when handling DHCP Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 13/65] batman-adv: Fix own OGM check in aggregated OGMs Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.14 14/65] batman-adv: bla: use netif_rx_ni when not in interrupt context Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 15/65] dmaengine: at_hdmac: check return value of of_find_device_by_node() in at_dma_xlate() Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 16/65] MIPS: mm: BMIPS5000 has inclusive physical caches Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 17/65] MIPS: BMIPS: Also call bmips_cpu_setup() for secondary cores Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 18/65] netfilter: nf_tables: add NFTA_SET_USERDATA if not null Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 19/65] netfilter: nf_tables: incorrect enum nft_list_attributes definition Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 20/65] netfilter: nf_tables: fix destination register zeroing Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 21/65] net: hns: Fix memleak in hns_nic_dev_probe Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 22/65] net: systemport: Fix memleak in bcm_sysport_probe Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 23/65] ravb: Fixed to be able to unload modules Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 24/65] net: arc_emac: Fix memleak in arc_mdio_probe Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 25/65] dmaengine: pl330: Fix burst length if burst size is smaller than bus width Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 26/65] gtp: add GTPA_LINK info to msg sent to userspace Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 27/65] bnxt_en: Check for zero dir entries in NVRAM Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 28/65] bnxt_en: Fix PCI AER error recovery flow Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 29/65] nvmet-fc: Fix a missed _irqsave version of spin_lock in nvmet_fc_fod_op_done() Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 30/65] perf tools: Correct SNOOPX field offset Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 31/65] net: ethernet: mlx4: Fix memory allocation in mlx4_buddy_init() Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 32/65] fix regression in "epoll: Keep a reference on files added to the check list" Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 33/65] drm/radeon: Prefer lower feedback dividers Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 34/65] tg3: Fix soft lockup when tg3_reset_task() fails Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 35/65] iommu/vt-d: Serialize IOMMU GCMD register modifications Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 36/65] thermal: ti-soc-thermal: Fix bogus thermal shutdowns for omap4430 Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 37/65] include/linux/log2.h: add missing () around n in roundup_pow_of_two() Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 38/65] btrfs: drop path before adding new uuid tree entry Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 39/65] btrfs: Remove redundant extent_buffer_get in get_old_root Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 40/65] btrfs: Remove extraneous extent_buffer_get from tree_mod_log_rewind Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 41/65] btrfs: set the lockdep class for log tree extent buffers Greg Kroah-Hartman
2020-09-08 15:26 ` Greg Kroah-Hartman [this message]
2020-09-08 15:26 ` [PATCH 4.14 43/65] uaccess: Add non-pagefault user-space write function Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 44/65] btrfs: fix potential deadlock in the search ioctl Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 45/65] net: usb: qmi_wwan: add Telit 0x1050 composition Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 46/65] usb: qmi_wwan: add D-Link DWM-222 A2 device ID Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 47/65] ALSA: ca0106: fix error code handling Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 48/65] ALSA: pcm: oss: Remove superfluous WARN_ON() for mulaw sanity check Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 49/65] ALSA: hda/hdmi: always check pin power status in i915 pin fixup Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 50/65] ALSA: firewire-digi00x: exclude Avid Adrenaline from detection Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 51/65] affs: fix basic permission bits to actually work Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 52/65] block: allow for_each_bvec to support zero len bvec Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 53/65] block: Move SECTOR_SIZE and SECTOR_SHIFT definitions into <linux/blkdev.h> Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 54/65] libata: implement ATA_HORKAGE_MAX_TRIM_128M and apply to Sandisks Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 55/65] dm cache metadata: Avoid returning cmd->bm wild pointer on error Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 56/65] dm thin " Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 57/65] mm: slub: fix conversion of freelist_corrupted() Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 58/65] KVM: arm64: Add kvm_extable for vaxorcism code Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 59/65] KVM: arm64: Defer guest entry when an asynchronous exception is pending Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 60/65] KVM: arm64: Survive synchronous exceptions caused by AT instructions Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 61/65] KVM: arm64: Set HCR_EL2.PTW to prevent AT taking synchronous exception Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 62/65] checkpatch: fix the usage of capture group ( ... ) Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 63/65] mm/hugetlb: fix a race between hugetlb sysctl handlers Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 64/65] cfg80211: regulatory: reject invalid hints Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.14 65/65] net: usb: Fix uninit-was-stored issue in asix_read_phy_addr() Greg Kroah-Hartman
2020-09-09 1:47 ` [PATCH 4.14 00/65] 4.14.197-rc1 review Shuah Khan
2020-09-09 8:19 ` Naresh Kamboju
2020-09-09 16:39 ` Guenter Roeck
2020-09-09 16:39 ` Guenter Roeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200908152219.211957098@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=mingo@kernel.org \
--cc=rostedt@goodmis.org \
--cc=sashal@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®