All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	patches@lists.linux.dev, Chuck Lever <chuck.lever@oracle.com>,
	Christian Brauner <brauner@kernel.org>
Subject: [PATCH 6.12 21/40] libfs: Replace simple_offset end-of-directory detection
Date: Thu, 30 Jan 2025 14:59:21 +0100	[thread overview]
Message-ID: <20250130133500.561438053@linuxfoundation.org> (raw)
In-Reply-To: <20250130133459.700273275@linuxfoundation.org>

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Chuck Lever <chuck.lever@oracle.com>

commit 68a3a65003145644efcbb651e91db249ccd96281 upstream.

According to getdents(3), the d_off field in each returned directory
entry points to the next entry in the directory. The d_off field in
the last returned entry in the readdir buffer must contain a valid
offset value, but if it points to an actual directory entry, then
readdir/getdents can loop.

This patch introduces a specific fixed offset value that is placed
in the d_off field of the last entry in a directory. Some user space
applications assume that the EOD offset value is larger than the
offsets of real directory entries, so the largest valid offset value
is reserved for this purpose. This new value is never allocated by
simple_offset_add().

When ->iterate_dir() returns, getdents{64} inserts the ctx->pos
value into the d_off field of the last valid entry in the readdir
buffer. When it hits EOD, offset_readdir() sets ctx->pos to the EOD
offset value so the last entry is updated to point to the EOD marker.

When trying to read the entry at the EOD offset, offset_readdir()
terminates immediately.

It is worth noting that using a Maple tree for directory offset
value allocation does not guarantee a 63-bit range of values --
on platforms where "long" is a 32-bit type, the directory offset
value range is still 0..(2^31 - 1). For broad compatibility with
32-bit user space, the largest tmpfs directory cookie value is now
S32_MAX.

Fixes: 796432efab1e ("libfs: getdents() should return 0 after reaching EOD")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Link: https://lore.kernel.org/r/20241228175522.1854234-5-cel@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/libfs.c |   37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)

--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -241,9 +241,15 @@ const struct inode_operations simple_dir
 };
 EXPORT_SYMBOL(simple_dir_inode_operations);
 
-/* 0 is '.', 1 is '..', so always start with offset 2 or more */
+/* simple_offset_add() never assigns these to a dentry */
 enum {
-	DIR_OFFSET_MIN	= 2,
+	DIR_OFFSET_EOD		= S32_MAX,
+};
+
+/* simple_offset_add() allocation range */
+enum {
+	DIR_OFFSET_MIN		= 2,
+	DIR_OFFSET_MAX		= DIR_OFFSET_EOD - 1,
 };
 
 static void offset_set(struct dentry *dentry, long offset)
@@ -287,7 +293,8 @@ int simple_offset_add(struct offset_ctx
 		return -EBUSY;
 
 	ret = mtree_alloc_cyclic(&octx->mt, &offset, dentry, DIR_OFFSET_MIN,
-				 LONG_MAX, &octx->next_offset, GFP_KERNEL);
+				 DIR_OFFSET_MAX, &octx->next_offset,
+				 GFP_KERNEL);
 	if (unlikely(ret < 0))
 		return ret == -EBUSY ? -ENOSPC : ret;
 
@@ -443,8 +450,6 @@ static loff_t offset_dir_llseek(struct f
 		return -EINVAL;
 	}
 
-	/* In this case, ->private_data is protected by f_pos_lock */
-	file->private_data = NULL;
 	return vfs_setpos(file, offset, LONG_MAX);
 }
 
@@ -454,7 +459,7 @@ static struct dentry *offset_find_next(s
 	struct dentry *child, *found = NULL;
 
 	rcu_read_lock();
-	child = mas_find(&mas, LONG_MAX);
+	child = mas_find(&mas, DIR_OFFSET_MAX);
 	if (!child)
 		goto out;
 	spin_lock(&child->d_lock);
@@ -475,7 +480,7 @@ static bool offset_dir_emit(struct dir_c
 			  inode->i_ino, fs_umode_to_dtype(inode->i_mode));
 }
 
-static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
+static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
 {
 	struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode);
 	struct dentry *dentry;
@@ -483,7 +488,7 @@ static void *offset_iterate_dir(struct i
 	while (true) {
 		dentry = offset_find_next(octx, ctx->pos);
 		if (!dentry)
-			return ERR_PTR(-ENOENT);
+			goto out_eod;
 
 		if (!offset_dir_emit(ctx, dentry)) {
 			dput(dentry);
@@ -493,7 +498,10 @@ static void *offset_iterate_dir(struct i
 		ctx->pos = dentry2offset(dentry) + 1;
 		dput(dentry);
 	}
-	return NULL;
+	return;
+
+out_eod:
+	ctx->pos = DIR_OFFSET_EOD;
 }
 
 /**
@@ -513,6 +521,8 @@ static void *offset_iterate_dir(struct i
  *
  * On return, @ctx->pos contains an offset that will read the next entry
  * in this directory when offset_readdir() is called again with @ctx.
+ * Caller places this value in the d_off field of the last entry in the
+ * user's buffer.
  *
  * Return values:
  *   %0 - Complete
@@ -525,13 +535,8 @@ static int offset_readdir(struct file *f
 
 	if (!dir_emit_dots(file, ctx))
 		return 0;
-
-	/* In this case, ->private_data is protected by f_pos_lock */
-	if (ctx->pos == DIR_OFFSET_MIN)
-		file->private_data = NULL;
-	else if (file->private_data == ERR_PTR(-ENOENT))
-		return 0;
-	file->private_data = offset_iterate_dir(d_inode(dir), ctx);
+	if (ctx->pos != DIR_OFFSET_EOD)
+		offset_iterate_dir(d_inode(dir), ctx);
 	return 0;
 }
 



  parent reply	other threads:[~2025-01-30 14:01 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-30 13:59 [PATCH 6.12 00/40] 6.12.12-rc1 review Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 01/40] ASoC: wm8994: Add depends on MFD core Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 02/40] ASoC: codecs: es8316: Fix HW rate calculation for 48Mhz MCLK Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 03/40] ASoC: samsung: Add missing selects for MFD_WM8994 Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 04/40] seccomp: Stub for !CONFIG_SECCOMP Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 05/40] ASoC: cs42l43: Add codec force suspend/resume ops Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 06/40] scsi: iscsi: Fix redundant response for ISCSI_UEVENT_GET_HOST_STATS request Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 07/40] drm/amd/display: Use HW lock mgr for PSR1 Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 08/40] drm/amd/display: Initialize denominator defaults to 1 Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 09/40] of/unittest: Add test that of_address_to_resource() fails on non-translatable address Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 10/40] ALSA: hda/realtek: Fix volume adjustment issue on Lenovo ThinkBook 16P Gen5 Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 11/40] drm/connector: hdmi: Validate supported_formats matches ycbcr_420_allowed Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 12/40] irqchip/sunxi-nmi: Add missing SKIP_WAKE flag Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 13/40] hwmon: (drivetemp) Set scsi command timeout to 10s Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 14/40] ASoC: samsung: Add missing depends on I2C Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 15/40] mm: zswap: properly synchronize freeing resources during CPU hotunplug Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 16/40] mm: zswap: move allocations during CPU init outside the lock Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 17/40] gfs2: Truncate address space when flipping GFS2_DIF_JDATA flag Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 18/40] libfs: Return ENOSPC when the directory offset range is exhausted Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 19/40] Revert "libfs: Add simple_offset_empty()" Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 20/40] Revert "libfs: fix infinite directory reads for offset dir" Greg Kroah-Hartman
2025-01-30 13:59 ` Greg Kroah-Hartman [this message]
2025-01-30 13:59 ` [PATCH 6.12 22/40] libfs: Use d_children list to iterate simple_offset directories Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 23/40] smb: client: handle lack of EA support in smb2_query_path_info() Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 24/40] net: sched: fix ets qdisc OOB Indexing Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 25/40] Revert "HID: multitouch: Add support for lenovo Y9000P Touchpad" Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 26/40] cachestat: fix page cache statistics permission checking Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 27/40] vfio/platform: check the bounds of read/write syscalls Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 28/40] scsi: storvsc: Ratelimit warning logs to prevent VM denial of service Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 29/40] USB: serial: quatech2: fix null-ptr-deref in qt2_process_read_urb() Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 30/40] Revert "usb: gadget: u_serial: Disable ep before setting port to null to fix the crash caused by port being null" Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 31/40] ALSA: usb-audio: Add delay quirk for USB Audio Device Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 32/40] wifi: rtl8xxxu: add more missing rtl8192cu USB IDs Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 33/40] HID: wacom: Initialize brightness of LED trigger Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 34/40] Input: xpad - add support for Nacon Pro Compact Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 35/40] Input: atkbd - map F23 key to support default copilot shortcut Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 36/40] Input: xpad - add unofficial Xbox 360 wireless receiver clone Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 37/40] Input: xpad - add QH Electronics VID/PID Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 38/40] Input: xpad - improve name of 8BitDo controller 2dc8:3106 Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 39/40] Input: xpad - add support for Nacon Evol-X Xbox One Controller Greg Kroah-Hartman
2025-01-30 13:59 ` [PATCH 6.12 40/40] Input: xpad - add support for wooting two he (arm) Greg Kroah-Hartman

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=20250130133500.561438053@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=brauner@kernel.org \
    --cc=chuck.lever@oracle.com \
    --cc=patches@lists.linux.dev \
    --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.