* [PATCH 4.19.y 6/9] loop: properly observe rotational flag of underlying device
[not found] <20240301011944.2197153-1-zhanggenjian@126.com>
@ 2024-03-01 1:19 ` Genjian
2024-03-01 1:19 ` [PATCH 4.19.y 8/9] loop: Check for overflow while configuring loop Genjian
1 sibling, 0 replies; 3+ messages in thread
From: Genjian @ 2024-03-01 1:19 UTC (permalink / raw)
To: 1192843200
Cc: Holger Hoffstätte, Jens Axboe, linux-block, holger,
Gwendal Grignou, Benjamin Gordon, Guenter Roeck, Genjian Zhang
From: Holger Hoffstätte <holger.hoffstaette@googlemail.com>
[ Upstream commit 56a85fd8376ef32458efb6ea97a820754e12f6bb ]
The loop driver always declares the rotational flag of its device as
rotational, even when the device of the mapped file is nonrotational,
as is the case with SSDs or on tmpfs. This can confuse filesystem tools
which are SSD-aware; in my case I frequently forget to tell mkfs.btrfs
that my loop device on tmpfs is nonrotational, and that I really don't
need any automatic metadata redundancy.
The attached patch fixes this by introspecting the rotational flag of the
mapped file's underlying block device, if it exists. If the mapped file's
filesystem has no associated block device - as is the case on e.g. tmpfs -
we assume nonrotational storage. If there is a better way to identify such
non-devices I'd love to hear them.
Cc: Jens Axboe <axboe@kernel.dk>
Cc: linux-block@vger.kernel.org
Cc: holger@applied-asynchrony.com
Signed-off-by: Holger Hoffstätte <holger.hoffstaette@googlemail.com>
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Benjamin Gordon <bmgordon@chromium.org>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Genjian Zhang <zhanggenjian@kylinos.cn>
---
drivers/block/loop.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 1a6805642ed2..7a0461a6160b 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -940,6 +940,24 @@ static int loop_prepare_queue(struct loop_device *lo)
return 0;
}
+static void loop_update_rotational(struct loop_device *lo)
+{
+ struct file *file = lo->lo_backing_file;
+ struct inode *file_inode = file->f_mapping->host;
+ struct block_device *file_bdev = file_inode->i_sb->s_bdev;
+ struct request_queue *q = lo->lo_queue;
+ bool nonrot = true;
+
+ /* not all filesystems (e.g. tmpfs) have a sb->s_bdev */
+ if (file_bdev)
+ nonrot = blk_queue_nonrot(bdev_get_queue(file_bdev));
+
+ if (nonrot)
+ blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
+ else
+ blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
+}
+
static int loop_set_fd(struct loop_device *lo, fmode_t mode,
struct block_device *bdev, unsigned int arg)
{
@@ -1001,6 +1019,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
blk_queue_write_cache(lo->lo_queue, true, false);
+ loop_update_rotational(lo);
loop_update_dio(lo);
loop_sysfs_init(lo);
loop_set_size(lo, size);
--
2.25.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 4.19.y 8/9] loop: Check for overflow while configuring loop
[not found] <20240301011944.2197153-1-zhanggenjian@126.com>
2024-03-01 1:19 ` [PATCH 4.19.y 6/9] loop: properly observe rotational flag of underlying device Genjian
@ 2024-03-01 1:19 ` Genjian
1 sibling, 0 replies; 3+ messages in thread
From: Genjian @ 2024-03-01 1:19 UTC (permalink / raw)
To: 1192843200
Cc: Siddh Raman Pant, syzbot+a8e049cd3abd342936b6, stable,
Matthew Wilcox, Christoph Hellwig, Jens Axboe, Genjian Zhang
From: Siddh Raman Pant <code@siddh.me>
[ Upstream commit c490a0b5a4f36da3918181a8acdc6991d967c5f3 ]
The userspace can configure a loop using an ioctl call, wherein
a configuration of type loop_config is passed (see lo_ioctl()'s
case on line 1550 of drivers/block/loop.c). This proceeds to call
loop_configure() which in turn calls loop_set_status_from_info()
(see line 1050 of loop.c), passing &config->info which is of type
loop_info64*. This function then sets the appropriate values, like
the offset.
loop_device has lo_offset of type loff_t (see line 52 of loop.c),
which is typdef-chained to long long, whereas loop_info64 has
lo_offset of type __u64 (see line 56 of include/uapi/linux/loop.h).
The function directly copies offset from info to the device as
follows (See line 980 of loop.c):
lo->lo_offset = info->lo_offset;
This results in an overflow, which triggers a warning in iomap_iter()
due to a call to iomap_iter_done() which has:
WARN_ON_ONCE(iter->iomap.offset > iter->pos);
Thus, check for negative value during loop_set_status_from_info().
Bug report: https://syzkaller.appspot.com/bug?id=c620fe14aac810396d3c3edc9ad73848bf69a29e
Reported-and-tested-by: syzbot+a8e049cd3abd342936b6@syzkaller.appspotmail.com
Cc: stable@vger.kernel.org
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Siddh Raman Pant <code@siddh.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20220823160810.181275-1-code@siddh.me
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Genjian Zhang <zhanggenjian@kylinos.cn>
---
drivers/block/loop.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0fefd21f0c71..c1caa3e2355f 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1271,6 +1271,11 @@ loop_set_status_from_info(struct loop_device *lo,
lo->lo_offset = info->lo_offset;
lo->lo_sizelimit = info->lo_sizelimit;
+
+ /* loff_t vars have been assigned __u64 */
+ if (lo->lo_offset < 0 || lo->lo_sizelimit < 0)
+ return -EOVERFLOW;
+
memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
lo->lo_file_name[LO_NAME_SIZE-1] = 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 4.19.y 0/9] Fix the UAF issue caused by the loop driver
@ 2024-03-01 1:30 Genjian
2024-03-01 1:30 ` [PATCH 4.19.y 8/9] loop: Check for overflow while configuring loop Genjian
0 siblings, 1 reply; 3+ messages in thread
From: Genjian @ 2024-03-01 1:30 UTC (permalink / raw)
To: stable
Cc: axboe, stable, linux-block, linux-kernel, zhanggenjian123, Genjian Zhang
From: Genjian Zhang <zhanggenjian@kylinos.cn>
Hello!
We found that 2035c770bfdb ("loop: Check for overflow while configuring loop") lost a unlock loop_ctl_mutex in loop_get_status(...).
which caused syzbot to report a UAF issue. However, the upstream patch does not have this issue.
So, we revert this patch and directly apply the unmodified upstream patch.
Risk use-after-free as reported by syzbot:
[ 174.437352] BUG: KASAN: use-after-free in __mutex_lock.isra.10+0xbc4/0xc30
[ 174.437772] Read of size 4 at addr ffff8880bac49ab8 by task syz-executor.0/13897
[ 174.438205]
[ 174.438306] CPU: 1 PID: 13897 Comm: syz-executor.0 Not tainted 4.19.306 #1
[ 174.438712] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1kylin1 04/01/2014
[ 174.439236] Call Trace:
[ 174.439392] dump_stack+0x94/0xc7
[ 174.439596] ? __mutex_lock.isra.10+0xbc4/0xc30
[ 174.439881] print_address_description+0x60/0x229
[ 174.440165] ? __mutex_lock.isra.10+0xbc4/0xc30
[ 174.440436] kasan_report.cold.6+0x241/0x2fd
[ 174.440696] __mutex_lock.isra.10+0xbc4/0xc30
[ 174.440959] ? entry_SYSCALL_64_after_hwframe+0x5c/0xc1
[ 174.441272] ? mutex_trylock+0xa0/0xa0
[ 174.441500] ? entry_SYSCALL_64_after_hwframe+0x5c/0xc1
[ 174.441816] ? kobject_get_unless_zero+0x129/0x1c0
[ 174.442106] ? kset_unregister+0x30/0x30
[ 174.442351] ? find_symbol_in_section+0x310/0x310
[ 174.442634] ? __mutex_lock_slowpath+0x10/0x10
[ 174.442901] mutex_lock_killable+0xb0/0xf0
[ 174.443149] ? __mutex_lock_killable_slowpath+0x10/0x10
[ 174.443465] ? __mutex_lock_slowpath+0x10/0x10
[ 174.443732] ? _cond_resched+0x10/0x20
[ 174.443966] ? kobject_get+0x54/0xa0
[ 174.444190] lo_open+0x16/0xc0
[ 174.444382] __blkdev_get+0x273/0x10f0
[ 174.444612] ? lo_fallocate.isra.20+0x150/0x150
[ 174.444886] ? bdev_disk_changed+0x190/0x190
[ 174.445146] ? path_init+0x1030/0x1030
[ 174.445371] ? do_syscall_64+0x9a/0x2d0
[ 174.445608] ? deref_stack_reg+0xab/0xe0
[ 174.445852] blkdev_get+0x97/0x880
[ 174.446061] ? walk_component+0x297/0xdc0
[ 174.446303] ? __blkdev_get+0x10f0/0x10f0
[ 174.446547] ? __fsnotify_inode_delete+0x20/0x20
[ 174.446822] blkdev_open+0x1bd/0x240
[ 174.447040] do_dentry_open+0x448/0xf80
[ 174.447274] ? blkdev_get_by_dev+0x60/0x60
[ 174.447522] ? __x64_sys_fchdir+0x1a0/0x1a0
[ 174.447775] ? inode_permission+0x86/0x320
[ 174.448022] path_openat+0xa83/0x3ed0
[ 174.448248] ? path_mountpoint+0xb50/0xb50
[ 174.448495] ? kasan_kmalloc+0xbf/0xe0
[ 174.448723] ? kmem_cache_alloc+0xbc/0x1b0
[ 174.448971] ? getname_flags+0xc4/0x560
[ 174.449203] ? do_sys_open+0x1ce/0x3f0
[ 174.449432] ? do_syscall_64+0x9a/0x2d0
[ 174.449706] ? entry_SYSCALL_64_after_hwframe+0x5c/0xc1
[ 174.450022] ? __d_alloc+0x2a/0xa50
[ 174.450232] ? kasan_unpoison_shadow+0x30/0x40
[ 174.450510] ? should_fail+0x117/0x6c0
[ 174.450737] ? timespec64_trunc+0xc1/0x150
[ 174.450986] ? inode_init_owner+0x2e0/0x2e0
[ 174.451237] ? timespec64_trunc+0xc1/0x150
[ 174.451484] ? inode_init_owner+0x2e0/0x2e0
[ 174.451736] do_filp_open+0x197/0x270
[ 174.451959] ? may_open_dev+0xd0/0xd0
[ 174.452182] ? kasan_unpoison_shadow+0x30/0x40
[ 174.452448] ? kasan_kmalloc+0xbf/0xe0
[ 174.452672] ? __alloc_fd+0x1a3/0x4b0
[ 174.452895] do_sys_open+0x2c7/0x3f0
[ 174.453114] ? filp_open+0x60/0x60
[ 174.453320] do_syscall_64+0x9a/0x2d0
[ 174.453541] ? prepare_exit_to_usermode+0xf3/0x170
[ 174.453832] entry_SYSCALL_64_after_hwframe+0x5c/0xc1
[ 174.454136] RIP: 0033:0x41edee
[ 174.454321] Code: 25 00 00 41 00 3d 00 00 41 00 74 48 48 c7 c0 a4 af 0b 01 8b 00 85 c0 75 69 89 f2 b8 01 01 00 00 48 89 fe bf 9c ff ff ff 0f 05 <48> 3d 00 f0 ff ff 0f 87 a6 00 00 00 48 8b 4c 24 28 64 48 33 0c5
[ 174.455404] RSP: 002b:00007ffd2501fbd0 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
[ 174.455854] RAX: ffffffffffffffda RBX: 00007ffd2501fc90 RCX: 000000000041edee
[ 174.456273] RDX: 0000000000000002 RSI: 00007ffd2501fcd0 RDI: 00000000ffffff9c
[ 174.456698] RBP: 0000000000000003 R08: 0000000000000001 R09: 00007ffd2501f9a7
[ 174.457116] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000003
[ 174.457535] R13: 0000000000565e48 R14: 00007ffd2501fcd0 R15: 0000000000400510
[ 174.457955]
[ 174.458052] Allocated by task 945:
[ 174.458261] kasan_kmalloc+0xbf/0xe0
[ 174.458478] kmem_cache_alloc_node+0xb4/0x1d0
[ 174.458743] copy_process.part.57+0x14b0/0x7010
[ 174.459017] _do_fork+0x197/0x980
[ 174.459218] kernel_thread+0x2f/0x40
[ 174.459438] call_usermodehelper_exec_work+0xa8/0x240
[ 174.459742] process_one_work+0x933/0x13b0
[ 174.459986] worker_thread+0x8c/0x1000
[ 174.460212] kthread+0x343/0x410
[ 174.460408] ret_from_fork+0x35/0x40
[ 174.460621]
[ 174.460716] Freed by task 22902:
[ 174.460913] __kasan_slab_free+0x125/0x170
[ 174.461159] kmem_cache_free+0x6e/0x1b0
[ 174.461391] __put_task_struct+0x1c4/0x440
[ 174.461636] delayed_put_task_struct+0x135/0x170
[ 174.461915] rcu_process_callbacks+0x578/0x15c0
[ 174.462184] __do_softirq+0x175/0x60e
[ 174.462403]
[ 174.462501] The buggy address belongs to the object at ffff8880bac49a80
[ 174.462501] which belongs to the cache task_struct of size 3264
[ 174.463235] The buggy address is located 56 bytes inside of
[ 174.463235] 3264-byte region [ffff8880bac49a80, ffff8880bac4a740)
[ 174.463923] The buggy address belongs to the page:
[ 174.464210] page:ffffea0002eb1200 count:1 mapcount:0 mapping:ffff888188ca0a00 index:0x0 compound_mapcount: 0
[ 174.464784] flags: 0x100000000008100(slab|head)
[ 174.465079] raw: 0100000000008100 ffffea0002eaa400 0000000400000004 ffff888188ca0a00
[ 174.465533] raw: 0000000000000000 0000000000090009 00000001ffffffff 0000000000000000
[ 174.465988] page dumped because: kasan: bad access detected
[ 174.466321]
[ 174.466322] Memory state around the buggy address:
[ 174.466325] ffff8880bac49980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 174.466327] ffff8880bac49a00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 174.466329] >ffff8880bac49a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 174.466329] ^
[ 174.466331] ffff8880bac49b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 174.466333] ffff8880bac49b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 174.466333] ==================================================================
[ 174.466338] Disabling lock debugging due to kernel taint
Best regards
Genjian
Genjian Zhang (1):
Revert "loop: Check for overflow while configuring loop"
Holger Hoffstätte (1):
loop: properly observe rotational flag of underlying device
Martijn Coenen (5):
loop: Call loop_config_discard() only after new config is applied
loop: Remove sector_t truncation checks
loop: Factor out setting loop device size
loop: Refactor loop_set_status() size calculation
loop: Factor out configuring loop from status
Siddh Raman Pant (1):
loop: Check for overflow while configuring loop
Zhong Jinghua (1):
loop: loop_set_status_from_info() check before assignment
drivers/block/loop.c | 204 ++++++++++++++++++++++++++-----------------
1 file changed, 123 insertions(+), 81 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 4.19.y 8/9] loop: Check for overflow while configuring loop
2024-03-01 1:30 [PATCH 4.19.y 0/9] Fix the UAF issue caused by the loop driver Genjian
@ 2024-03-01 1:30 ` Genjian
0 siblings, 0 replies; 3+ messages in thread
From: Genjian @ 2024-03-01 1:30 UTC (permalink / raw)
To: stable
Cc: axboe, stable, linux-block, linux-kernel, zhanggenjian123,
Siddh Raman Pant, syzbot+a8e049cd3abd342936b6, Matthew Wilcox,
Christoph Hellwig, Genjian Zhang
From: Siddh Raman Pant <code@siddh.me>
[ Upstream commit c490a0b5a4f36da3918181a8acdc6991d967c5f3 ]
The userspace can configure a loop using an ioctl call, wherein
a configuration of type loop_config is passed (see lo_ioctl()'s
case on line 1550 of drivers/block/loop.c). This proceeds to call
loop_configure() which in turn calls loop_set_status_from_info()
(see line 1050 of loop.c), passing &config->info which is of type
loop_info64*. This function then sets the appropriate values, like
the offset.
loop_device has lo_offset of type loff_t (see line 52 of loop.c),
which is typdef-chained to long long, whereas loop_info64 has
lo_offset of type __u64 (see line 56 of include/uapi/linux/loop.h).
The function directly copies offset from info to the device as
follows (See line 980 of loop.c):
lo->lo_offset = info->lo_offset;
This results in an overflow, which triggers a warning in iomap_iter()
due to a call to iomap_iter_done() which has:
WARN_ON_ONCE(iter->iomap.offset > iter->pos);
Thus, check for negative value during loop_set_status_from_info().
Bug report: https://syzkaller.appspot.com/bug?id=c620fe14aac810396d3c3edc9ad73848bf69a29e
Reported-and-tested-by: syzbot+a8e049cd3abd342936b6@syzkaller.appspotmail.com
Cc: stable@vger.kernel.org
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Siddh Raman Pant <code@siddh.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20220823160810.181275-1-code@siddh.me
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Genjian Zhang <zhanggenjian@kylinos.cn>
---
drivers/block/loop.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0fefd21f0c71..c1caa3e2355f 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1271,6 +1271,11 @@ loop_set_status_from_info(struct loop_device *lo,
lo->lo_offset = info->lo_offset;
lo->lo_sizelimit = info->lo_sizelimit;
+
+ /* loff_t vars have been assigned __u64 */
+ if (lo->lo_offset < 0 || lo->lo_sizelimit < 0)
+ return -EOVERFLOW;
+
memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
lo->lo_file_name[LO_NAME_SIZE-1] = 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-03-01 1:48 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20240301011944.2197153-1-zhanggenjian@126.com>
2024-03-01 1:19 ` [PATCH 4.19.y 6/9] loop: properly observe rotational flag of underlying device Genjian
2024-03-01 1:19 ` [PATCH 4.19.y 8/9] loop: Check for overflow while configuring loop Genjian
2024-03-01 1:30 [PATCH 4.19.y 0/9] Fix the UAF issue caused by the loop driver Genjian
2024-03-01 1:30 ` [PATCH 4.19.y 8/9] loop: Check for overflow while configuring loop Genjian
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.