diff mbox series

Fixes: ec16b147a55bfa14e858 ("fs: Fix rw_hint validation")

Message ID 20240701032110.3601345-1-hui81.qi@samsung.com (mailing list archive)
State New
Headers show
Series Fixes: ec16b147a55bfa14e858 ("fs: Fix rw_hint validation") | expand

Commit Message

Hui Qi July 1, 2024, 3:21 a.m. UTC
The high 32 bits is filled with arbitrary value. If hint is set
WRITE_LIFE_SHORT (2) by fcntl, the value is 0xf6d1374000000002,
which causes rw_hint_valid always returns false. i_write_hint of inode and
bi_write_hint of bio are both enum rw_hint. The value would be truncated
only if the element value exceeds 2^32.

Signed-off-by: Hui Qi <hui81.qi@samsung.com>
---
 fs/fcntl.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

Comments

Bart Van Assche July 1, 2024, 4:59 p.m. UTC | #1
On 6/30/24 8:21 PM, Hui Qi wrote:
> The high 32 bits is filled with arbitrary value.

Which application does this? This is a user space bug. Additionally, the
patch title looks weird. Please improve the patch title.

> If hint is set WRITE_LIFE_SHORT (2) by fcntl, the value is
> 0xf6d1374000000002,
This is a user space bug. The fcntl() man page clearly mentions that
F_SET_RW_HINT accepts a 64-bit value. See also
https://www.man7.org/linux/man-pages/man2/fcntl.2.html.

> which causes rw_hint_valid always returns false. i_write_hint of inode and
> bi_write_hint of bio are both enum rw_hint. The value would be truncated
> only if the element value exceeds 2^32.
> 
> Signed-off-by: Hui Qi <hui81.qi@samsung.com>

If you want this patch to be merged you will have to add Fixes: and Cc:
stable tags.

Bart.
diff mbox series

Patch

diff --git a/fs/fcntl.c b/fs/fcntl.c
index 300e5d9ad913..bab45c5586c6 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -269,7 +269,7 @@  static int f_getowner_uids(struct file *filp, unsigned long arg)
 }
 #endif
 
-static bool rw_hint_valid(u64 hint)
+static bool rw_hint_valid(enum rw_hint hint)
 {
 	BUILD_BUG_ON(WRITE_LIFE_NOT_SET != RWH_WRITE_LIFE_NOT_SET);
 	BUILD_BUG_ON(WRITE_LIFE_NONE != RWH_WRITE_LIFE_NONE);
@@ -295,8 +295,8 @@  static long fcntl_get_rw_hint(struct file *file, unsigned int cmd,
 			      unsigned long arg)
 {
 	struct inode *inode = file_inode(file);
-	u64 __user *argp = (u64 __user *)arg;
-	u64 hint = READ_ONCE(inode->i_write_hint);
+	enum rw_hint __user *argp = (enum rw_hint __user *)arg;
+	enum rw_hint hint = READ_ONCE(inode->i_write_hint);
 
 	if (copy_to_user(argp, &hint, sizeof(*argp)))
 		return -EFAULT;
@@ -307,8 +307,8 @@  static long fcntl_set_rw_hint(struct file *file, unsigned int cmd,
 			      unsigned long arg)
 {
 	struct inode *inode = file_inode(file);
-	u64 __user *argp = (u64 __user *)arg;
-	u64 hint;
+	enum rw_hint __user *argp = (enum rw_hint __user *)arg;
+	enum rw_hint hint;
 
 	if (copy_from_user(&hint, argp, sizeof(hint)))
 		return -EFAULT;