All of lore.kernel.org
 help / color / mirror / Atom feed
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.19 61/88] uaccess: Add non-pagefault user-space read functions
Date: Tue,  8 Sep 2020 17:26:02 +0200	[thread overview]
Message-ID: <20200908152224.178177600@linuxfoundation.org> (raw)
In-Reply-To: <20200908152221.082184905@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 d55b68b113de1..db88f36540e9e 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 ec00be51a24fd..80d70cb5cc0bd 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




  parent reply	other threads:[~2020-09-08 18:32 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-08 15:25 [PATCH 4.19 00/88] 4.19.144-rc1 review Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 01/88] HID: core: Correctly handle ReportSize being zero Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 02/88] HID: core: Sanitize event code and type when mapping input Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 03/88] perf record/stat: Explicitly call out event modifiers in the documentation Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 04/88] scsi: target: tcmu: Fix size in calls to tcmu_flush_dcache_range Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 05/88] scsi: target: tcmu: Optimize use of flush_dcache_page Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 06/88] tty: serial: qcom_geni_serial: Drop __init from qcom_geni_console_setup Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 07/88] drm/msm: add shutdown support for display platform_driver Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 08/88] hwmon: (applesmc) check status earlier Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 09/88] nvmet: Disable keep-alive timer when kato is cleared to 0h Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 10/88] drm/msm/a6xx: fix gmu start on newer firmware Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 11/88] ceph: dont allow setlease on cephfs Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 12/88] cpuidle: Fixup IRQ state Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 13/88] s390: dont trace preemption in percpu macros Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 14/88] xen/xenbus: Fix granting of vmallocd memory Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 15/88] dmaengine: of-dma: Fix of_dma_router_xlates of_dma_xlate handling Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 16/88] batman-adv: Avoid uninitialized chaddr when handling DHCP Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 17/88] batman-adv: Fix own OGM check in aggregated OGMs Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 18/88] batman-adv: bla: use netif_rx_ni when not in interrupt context Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 19/88] dmaengine: at_hdmac: check return value of of_find_device_by_node() in at_dma_xlate() Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 20/88] MIPS: mm: BMIPS5000 has inclusive physical caches Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 21/88] MIPS: BMIPS: Also call bmips_cpu_setup() for secondary cores Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 22/88] netfilter: nf_tables: add NFTA_SET_USERDATA if not null Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 23/88] netfilter: nf_tables: incorrect enum nft_list_attributes definition Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 24/88] netfilter: nf_tables: fix destination register zeroing Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 25/88] net: hns: Fix memleak in hns_nic_dev_probe Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 26/88] net: systemport: Fix memleak in bcm_sysport_probe Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 27/88] ravb: Fixed to be able to unload modules Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 28/88] net: arc_emac: Fix memleak in arc_mdio_probe Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 29/88] dmaengine: pl330: Fix burst length if burst size is smaller than bus width Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 30/88] gtp: add GTPA_LINK info to msg sent to userspace Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 31/88] bnxt_en: Dont query FW when netif_running() is false Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 32/88] bnxt_en: Check for zero dir entries in NVRAM Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 33/88] bnxt_en: Fix PCI AER error recovery flow Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 34/88] bnxt_en: fix HWRM error when querying VF temperature Greg Kroah-Hartman
2020-09-08 19:47   ` Pavel Machek
2020-09-08 20:49     ` Edwin Peer
2020-09-08 15:25 ` [PATCH 4.19 35/88] xfs: fix boundary test in xfs_attr_shortform_verify Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 36/88] bnxt: dont enable NAPI until rings are ready Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 37/88] selftests/bpf: Fix massive output from test_maps Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 38/88] netfilter: nfnetlink: nfnetlink_unicast() reports EAGAIN instead of ENOBUFS Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 39/88] nvmet-fc: Fix a missed _irqsave version of spin_lock in nvmet_fc_fod_op_done() Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 40/88] perf tools: Correct SNOOPX field offset Greg Kroah-Hartman
2020-09-08 19:32   ` Pavel Machek
2020-09-08 15:25 ` [PATCH 4.19 41/88] net: ethernet: mlx4: Fix memory allocation in mlx4_buddy_init() Greg Kroah-Hartman
2020-09-08 19:53   ` Pavel Machek
2020-09-09  3:13     ` Shung-Hsi Yu
2020-09-08 15:25 ` [PATCH 4.19 42/88] fix regression in "epoll: Keep a reference on files added to the check list" Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 43/88] net: gemini: Fix another missing clk_disable_unprepare() in probe Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 44/88] drm/radeon: Prefer lower feedback dividers Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 45/88] xfs: fix xfs_bmap_validate_extent_raw when checking attr fork of rt files Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 46/88] perf jevents: Fix suspicious code in fixregex() Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 47/88] tg3: Fix soft lockup when tg3_reset_task() fails Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 48/88] x86, fakenuma: Fix invalid starting node ID Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 49/88] iommu/vt-d: Serialize IOMMU GCMD register modifications Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 50/88] thermal: ti-soc-thermal: Fix bogus thermal shutdowns for omap4430 Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 51/88] include/linux/log2.h: add missing () around n in roundup_pow_of_two() Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 52/88] ext2: dont update mtime on COW faults Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 53/88] xfs: " Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 54/88] btrfs: drop path before adding new uuid tree entry Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 55/88] vfio/type1: Support faulting PFNMAP vmas Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 56/88] vfio-pci: Fault mmaps to enable vma tracking Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 57/88] vfio-pci: Invalidate mmaps and block MMIO access on disabled memory Greg Kroah-Hartman
2020-09-08 15:25 ` [PATCH 4.19 58/88] btrfs: Remove redundant extent_buffer_get in get_old_root Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 59/88] btrfs: Remove extraneous extent_buffer_get from tree_mod_log_rewind Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 60/88] 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.19 62/88] uaccess: Add non-pagefault user-space write function Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 63/88] btrfs: fix potential deadlock in the search ioctl Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 64/88] net: usb: qmi_wwan: add Telit 0x1050 composition Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 65/88] usb: qmi_wwan: add D-Link DWM-222 A2 device ID Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 66/88] ALSA: ca0106: fix error code handling Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 67/88] ALSA: pcm: oss: Remove superfluous WARN_ON() for mulaw sanity check Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 68/88] ALSA: hda/hdmi: always check pin power status in i915 pin fixup Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 69/88] ALSA: firewire-digi00x: exclude Avid Adrenaline from detection Greg Kroah-Hartman
2020-09-08 18:45   ` simon
2020-09-08 15:26 ` [PATCH 4.19 70/88] ALSA: hda - Fix silent audio output and corrupted input on MSI X570-A PRO Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 71/88] media: rc: do not access device via sysfs after rc_unregister_device() Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 72/88] media: rc: uevent sysfs file races with rc_unregister_device() Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 73/88] affs: fix basic permission bits to actually work Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 74/88] block: allow for_each_bvec to support zero len bvec Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 75/88] libata: implement ATA_HORKAGE_MAX_TRIM_128M and apply to Sandisks Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 76/88] dm writecache: handle DAX to partitions on persistent memory correctly Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 77/88] dm cache metadata: Avoid returning cmd->bm wild pointer on error Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 78/88] dm thin " Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 79/88] mm: slub: fix conversion of freelist_corrupted() Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 80/88] KVM: arm64: Add kvm_extable for vaxorcism code Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 81/88] KVM: arm64: Defer guest entry when an asynchronous exception is pending Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 82/88] KVM: arm64: Survive synchronous exceptions caused by AT instructions Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 83/88] KVM: arm64: Set HCR_EL2.PTW to prevent AT taking synchronous exception Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 84/88] vfio/pci: Fix SR-IOV VF handling with MMIO blocking Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 85/88] checkpatch: fix the usage of capture group ( ... ) Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 86/88] mm/hugetlb: fix a race between hugetlb sysctl handlers Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 87/88] cfg80211: regulatory: reject invalid hints Greg Kroah-Hartman
2020-09-08 15:26 ` [PATCH 4.19 88/88] net: usb: Fix uninit-was-stored issue in asix_read_phy_addr() Greg Kroah-Hartman
2020-09-08 19:54 ` [PATCH 4.19 00/88] 4.19.144-rc1 review Pavel Machek
2020-09-09  1:45 ` Shuah Khan
2020-09-09  7:03 ` Jon Hunter
2020-09-09  8:11 ` Naresh Kamboju
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=20200908152224.178177600@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.