mailweb.openeuler.org
Manage this list

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

Kernel

Threads by month
  • ----- 2025 -----
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
kernel@openeuler.org

  • 62 participants
  • 18365 discussions
[openeuler:OLK-5.10 2610/2610] fs/cachefiles/ondemand.c:23:25: warning: implicit conversion from 'enum cachefiles_obj_ref_trace' to 'enum fscache_obj_ref_trace'
by kernel test robot 31 Dec '24

31 Dec '24
tree: https://gitee.com/openeuler/kernel.git OLK-5.10 head: 8bba4b17284e774544bd01d9ea5190546e93a849 commit: 2937cd5f8c58bd8e7895f6b2698057721442248e [2610/2610] cachefiles: notify the user daemon when looking up cookie config: arm64-randconfig-004-20241230 (https://download.01.org/0day-ci/archive/20241231/202412310256.l8FuLcbO-lkp@…) compiler: aarch64-linux-gcc (GCC) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241231/202412310256.l8FuLcbO-lkp@…) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp(a)intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202412310256.l8FuLcbO-lkp@intel.com/ All warnings (new ones prefixed by >>): fs/cachefiles/ondemand.c: In function 'cachefiles_ondemand_fd_release': >> fs/cachefiles/ondemand.c:23:25: warning: implicit conversion from 'enum cachefiles_obj_ref_trace' to 'enum fscache_obj_ref_trace' [-Wenum-conversion] 23 | cachefiles_obj_put_ondemand_fd); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ fs/cachefiles/ondemand.c: In function 'cachefiles_ondemand_get_fd': fs/cachefiles/ondemand.c:145:25: warning: implicit conversion from 'enum cachefiles_obj_ref_trace' to 'enum fscache_obj_ref_trace' [-Wenum-conversion] 145 | cachefiles_obj_get_ondemand_fd) ? 0 : -EAGAIN; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ fs/cachefiles/ondemand.c:191:25: warning: implicit conversion from 'enum cachefiles_obj_ref_trace' to 'enum fscache_obj_ref_trace' [-Wenum-conversion] 191 | cachefiles_obj_put_ondemand_fd); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ vim +23 fs/cachefiles/ondemand.c 7 8 static int cachefiles_ondemand_fd_release(struct inode *inode, 9 struct file *file) 10 { 11 struct cachefiles_object *object = file->private_data; 12 int object_id = object->ondemand_id; 13 struct cachefiles_cache *cache; 14 15 cache = container_of(object->fscache.cache, 16 struct cachefiles_cache, cache); 17 18 object->ondemand_id = CACHEFILES_ONDEMAND_ID_CLOSED; 19 xa_lock(&cache->ondemand_ids.idr_rt); 20 idr_remove(&cache->ondemand_ids, object_id); 21 xa_unlock(&cache->ondemand_ids.idr_rt); 22 object->fscache.cache->ops->put_object(&object->fscache, > 23 cachefiles_obj_put_ondemand_fd); 24 return 0; 25 } 26 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
1 0
0 0
[openeuler:OLK-6.6 1673/1673] arch/x86/kvm/svm/csv.c:129:52: sparse: sparse: Using plain integer as NULL pointer
by kernel test robot 31 Dec '24

31 Dec '24
tree: https://gitee.com/openeuler/kernel.git OLK-6.6 head: 5672a2cb8a45de45872d2dd25d3dd94348c070eb commit: 07a18fb6c71ef75cc1205999cd2493b567649466 [1673/1673] KVM: SVM: Prepare memory pool to allocate buffers for KVM_CSV_COMMAND_BATCH config: x86_64-randconfig-121-20241230 (https://download.01.org/0day-ci/archive/20241231/202412310023.KFzowK2B-lkp@…) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241231/202412310023.KFzowK2B-lkp@…) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp(a)intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202412310023.KFzowK2B-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) arch/x86/kvm/svm/csv.c:53:5: sparse: sparse: symbol 'csv_vm_attestation' was not declared. Should it be static? >> arch/x86/kvm/svm/csv.c:129:52: sparse: sparse: Using plain integer as NULL pointer >> arch/x86/kvm/svm/csv.c:129:6: sparse: sparse: symbol 'g_trans_mempool' was not declared. Should it be static? vim +129 arch/x86/kvm/svm/csv.c 127 128 static size_t g_mempool_offset; > 129 void *g_trans_mempool[TRANS_MEMPOOL_BLOCK_NUM] = { 0, }; 130 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
1 0
0 0
[openeuler:OLK-6.6 1673/1673] arch/x86/kvm/svm/csv.c:30:5: sparse: sparse: symbol 'csv_vm_attestation' was not declared. Should it be static?
by kernel test robot 30 Dec '24

30 Dec '24
tree: https://gitee.com/openeuler/kernel.git OLK-6.6 head: 8fc6624288123b0750ac5164020e637b70f1de2b commit: 0f13b8634792cff1f2fb18bf35e5a24d7a8cbf8e [1673/1673] KVM: x86: Support VM_ATTESTATION hypercall config: x86_64-randconfig-121-20241230 (https://download.01.org/0day-ci/archive/20241230/202412302222.H5YbllyE-lkp@…) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241230/202412302222.H5YbllyE-lkp@…) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp(a)intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202412302222.H5YbllyE-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> arch/x86/kvm/svm/csv.c:30:5: sparse: sparse: symbol 'csv_vm_attestation' was not declared. Should it be static? vim +/csv_vm_attestation +30 arch/x86/kvm/svm/csv.c 29 > 30 int csv_vm_attestation(struct kvm *kvm, unsigned long gpa, unsigned long len) 31 { 32 struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; 33 struct sev_data_attestation_report *data = NULL; 34 struct page **pages; 35 unsigned long guest_uaddr, n; 36 int ret = 0, offset, error; 37 38 if (!sev_guest(kvm) || !hygon_kvm_hooks.sev_hooks_installed) 39 return -ENOTTY; 40 41 /* 42 * The physical address of guest must valid and page aligned, and 43 * the length of guest memory region must be page size aligned. 44 */ 45 if (!gpa || (gpa & ~PAGE_MASK) || (len & ~PAGE_MASK)) { 46 pr_err("invalid guest address or length\n"); 47 return -EFAULT; 48 } 49 50 guest_uaddr = gfn_to_hva(kvm, gpa_to_gfn(gpa)); 51 pages = hygon_kvm_hooks.sev_pin_memory(kvm, guest_uaddr, len, &n, 1); 52 if (IS_ERR(pages)) 53 return PTR_ERR(pages); 54 55 /* 56 * The attestation report must be copied into contiguous memory region, 57 * lets verify that userspace memory pages are contiguous before we 58 * issue commmand. 59 */ 60 if (hygon_kvm_hooks.get_num_contig_pages(0, pages, n) != n) { 61 ret = -EINVAL; 62 goto e_unpin_memory; 63 } 64 65 ret = -ENOMEM; 66 data = kzalloc(sizeof(*data), GFP_KERNEL); 67 if (!data) 68 goto e_unpin_memory; 69 70 /* csv_vm_mnonce indicates attestation request from guest */ 71 if (sizeof(csv_vm_mnonce) >= sizeof(data->mnonce)) { 72 ret = -EINVAL; 73 goto e_free; 74 } 75 76 memcpy(data->mnonce, csv_vm_mnonce, sizeof(csv_vm_mnonce)); 77 78 offset = guest_uaddr & (PAGE_SIZE - 1); 79 data->address = __sme_page_pa(pages[0]) + offset; 80 data->len = len; 81 82 data->handle = sev->handle; 83 ret = hygon_kvm_hooks.sev_issue_cmd(kvm, SEV_CMD_ATTESTATION_REPORT, 84 data, &error); 85 86 if (ret) 87 pr_err("vm attestation ret %#x, error %#x\n", ret, error); 88 89 e_free: 90 kfree(data); 91 e_unpin_memory: 92 hygon_kvm_hooks.sev_unpin_memory(kvm, pages, n); 93 return ret; 94 } 95 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
1 0
0 0
[PATCH OLK-6.6] media: imx-jpeg: Ensure power suppliers be suspended before detach them
by Li Huafei 30 Dec '24

30 Dec '24
From: Ming Qian <ming.qian(a)nxp.com> stable inclusion from stable-v6.6.64 commit b7a830bbc25da0f641e3ef2bac3b1766b2777a8b category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEANC CVE: CVE-2024-56575 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- commit fd0af4cd35da0eb550ef682b71cda70a4e36f6b9 upstream. The power suppliers are always requested to suspend asynchronously, dev_pm_domain_detach() requires the caller to ensure proper synchronization of this function with power management callbacks. otherwise the detach may led to kernel panic, like below: [ 1457.107934] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000040 [ 1457.116777] Mem abort info: [ 1457.119589] ESR = 0x0000000096000004 [ 1457.123358] EC = 0x25: DABT (current EL), IL = 32 bits [ 1457.128692] SET = 0, FnV = 0 [ 1457.131764] EA = 0, S1PTW = 0 [ 1457.134920] FSC = 0x04: level 0 translation fault [ 1457.139812] Data abort info: [ 1457.142707] ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000 [ 1457.148196] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 [ 1457.153256] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 [ 1457.158563] user pgtable: 4k pages, 48-bit VAs, pgdp=00000001138b6000 [ 1457.165000] [0000000000000040] pgd=0000000000000000, p4d=0000000000000000 [ 1457.171792] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP [ 1457.178045] Modules linked in: v4l2_jpeg wave6_vpu_ctrl(-) [last unloaded: mxc_jpeg_encdec] [ 1457.186383] CPU: 0 PID: 51938 Comm: kworker/0:3 Not tainted 6.6.36-gd23d64eea511 #66 [ 1457.194112] Hardware name: NXP i.MX95 19X19 board (DT) [ 1457.199236] Workqueue: pm pm_runtime_work [ 1457.203247] pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 1457.210188] pc : genpd_runtime_suspend+0x20/0x290 [ 1457.214886] lr : __rpm_callback+0x48/0x1d8 [ 1457.218968] sp : ffff80008250bc50 [ 1457.222270] x29: ffff80008250bc50 x28: 0000000000000000 x27: 0000000000000000 [ 1457.229394] x26: 0000000000000000 x25: 0000000000000008 x24: 00000000000f4240 [ 1457.236518] x23: 0000000000000000 x22: ffff00008590f0e4 x21: 0000000000000008 [ 1457.243642] x20: ffff80008099c434 x19: ffff00008590f000 x18: ffffffffffffffff [ 1457.250766] x17: 5300326563697665 x16: 645f676e696c6f6f x15: 63343a6d726f6674 [ 1457.257890] x14: 0000000000000004 x13: 00000000000003a4 x12: 0000000000000002 [ 1457.265014] x11: 0000000000000000 x10: 0000000000000a60 x9 : ffff80008250bbb0 [ 1457.272138] x8 : ffff000092937200 x7 : ffff0003fdf6af80 x6 : 0000000000000000 [ 1457.279262] x5 : 00000000410fd050 x4 : 0000000000200000 x3 : 0000000000000000 [ 1457.286386] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff00008590f000 [ 1457.293510] Call trace: [ 1457.295946] genpd_runtime_suspend+0x20/0x290 [ 1457.300296] __rpm_callback+0x48/0x1d8 [ 1457.304038] rpm_callback+0x6c/0x78 [ 1457.307515] rpm_suspend+0x10c/0x570 [ 1457.311077] pm_runtime_work+0xc4/0xc8 [ 1457.314813] process_one_work+0x138/0x248 [ 1457.318816] worker_thread+0x320/0x438 [ 1457.322552] kthread+0x110/0x114 [ 1457.325767] ret_from_fork+0x10/0x20 Fixes: 2db16c6ed72c ("media: imx-jpeg: Add V4L2 driver for i.MX8 JPEG Encoder/Decoder") Cc: <stable(a)vger.kernel.org> Signed-off-by: Ming Qian <ming.qian(a)nxp.com> Reviewed-by: TaoJiang <tao.jiang_2(a)nxp.com> Signed-off-by: Hans Verkuil <hverkuil-cisco(a)xs4all.nl> Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org> Signed-off-by: Li Huafei <lihuafei1(a)huawei.com> --- drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c index 2007152cd7a4..f6fcee52d138 100644 --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c @@ -2674,6 +2674,8 @@ static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg) int i; for (i = 0; i < jpeg->num_domains; i++) { + if (jpeg->pd_dev[i] && !pm_runtime_suspended(jpeg->pd_dev[i])) + pm_runtime_force_suspend(jpeg->pd_dev[i]); if (jpeg->pd_link[i] && !IS_ERR(jpeg->pd_link[i])) device_link_del(jpeg->pd_link[i]); if (jpeg->pd_dev[i] && !IS_ERR(jpeg->pd_dev[i])) -- 2.25.1
2 1
0 0
[PATCH OLK-6.6] virtiofs: use pages instead of pointer for kernel direct IO
by Yifan Qiao 30 Dec '24

30 Dec '24
From: Hou Tao <houtao1(a)huawei.com> mainline inclusion from mainline-v6.13-rc1 commit 41748675c0bf252b3c5f600a95830f0936d366c1 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAGA CVE: CVE-2024-53219 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- When trying to insert a 10MB kernel module kept in a virtio-fs with cache disabled, the following warning was reported: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 404 at mm/page_alloc.c:4551 ...... Modules linked in: CPU: 1 PID: 404 Comm: insmod Not tainted 6.9.0-rc5+ #123 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) ...... RIP: 0010:__alloc_pages+0x2bf/0x380 ...... Call Trace: <TASK> ? __warn+0x8e/0x150 ? __alloc_pages+0x2bf/0x380 __kmalloc_large_node+0x86/0x160 __kmalloc+0x33c/0x480 virtio_fs_enqueue_req+0x240/0x6d0 virtio_fs_wake_pending_and_unlock+0x7f/0x190 queue_request_and_unlock+0x55/0x60 fuse_simple_request+0x152/0x2b0 fuse_direct_io+0x5d2/0x8c0 fuse_file_read_iter+0x121/0x160 __kernel_read+0x151/0x2d0 kernel_read+0x45/0x50 kernel_read_file+0x1a9/0x2a0 init_module_from_file+0x6a/0xe0 idempotent_init_module+0x175/0x230 __x64_sys_finit_module+0x5d/0xb0 x64_sys_call+0x1c3/0x9e0 do_syscall_64+0x3d/0xc0 entry_SYSCALL_64_after_hwframe+0x4b/0x53 ...... </TASK> ---[ end trace 0000000000000000 ]--- The warning is triggered as follows: 1) syscall finit_module() handles the module insertion and it invokes kernel_read_file() to read the content of the module first. 2) kernel_read_file() allocates a 10MB buffer by using vmalloc() and passes it to kernel_read(). kernel_read() constructs a kvec iter by using iov_iter_kvec() and passes it to fuse_file_read_iter(). 3) virtio-fs disables the cache, so fuse_file_read_iter() invokes fuse_direct_io(). As for now, the maximal read size for kvec iter is only limited by fc->max_read. For virtio-fs, max_read is UINT_MAX, so fuse_direct_io() doesn't split the 10MB buffer. It saves the address and the size of the 10MB-sized buffer in out_args[0] of a fuse request and passes the fuse request to virtio_fs_wake_pending_and_unlock(). 4) virtio_fs_wake_pending_and_unlock() uses virtio_fs_enqueue_req() to queue the request. Because virtiofs need DMA-able address, so virtio_fs_enqueue_req() uses kmalloc() to allocate a bounce buffer for all fuse args, copies these args into the bounce buffer and passed the physical address of the bounce buffer to virtiofsd. The total length of these fuse args for the passed fuse request is about 10MB, so copy_args_to_argbuf() invokes kmalloc() with a 10MB size parameter and it triggers the warning in __alloc_pages(): if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp)) return NULL; 5) virtio_fs_enqueue_req() will retry the memory allocation in a kworker, but it won't help, because kmalloc() will always return NULL due to the abnormal size and finit_module() will hang forever. A feasible solution is to limit the value of max_read for virtio-fs, so the length passed to kmalloc() will be limited. However it will affect the maximal read size for normal read. And for virtio-fs write initiated from kernel, it has the similar problem but now there is no way to limit fc->max_write in kernel. So instead of limiting both the values of max_read and max_write in kernel, introducing use_pages_for_kvec_io in fuse_conn and setting it as true in virtiofs. When use_pages_for_kvec_io is enabled, fuse will use pages instead of pointer to pass the KVEC_IO data. After switching to pages for KVEC_IO data, these pages will be used for DMA through virtio-fs. If these pages are backed by vmalloc(), {flush|invalidate}_kernel_vmap_range() are necessary to flush or invalidate the cache before the DMA operation. So add two new fields in fuse_args_pages to record the base address of vmalloc area and the condition indicating whether invalidation is needed. Perform the flush in fuse_get_user_pages() for write operations and the invalidation in fuse_release_user_pages() for read operations. It may seem necessary to introduce another field in fuse_conn to indicate that these KVEC_IO pages are used for DMA, However, considering that virtio-fs is currently the only user of use_pages_for_kvec_io, just reuse use_pages_for_kvec_io to indicate that these pages will be used for DMA. Fixes: a62a8ef9d97d ("virtio-fs: add virtiofs filesystem") Signed-off-by: Hou Tao <houtao1(a)huawei.com> Tested-by: Jingbo Xu <jefflexu(a)linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi(a)redhat.com> Signed-off-by: Yifan Qiao <qiaoyifan4(a)huawei.com> --- fs/fuse/fuse_i.h | 6 +++++ fs/fuse/file.c | 62 +++++++++++++++++++++++++++++++-------------- fs/fuse/virtio_fs.c | 1 + 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 3d5734ed99cf..1bb136bcbe9e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -286,9 +286,12 @@ struct fuse_args { bool page_replace:1; bool may_block:1; bool is_ext:1; + bool invalidate_vmap:1; struct fuse_in_arg in_args[3]; struct fuse_arg out_args[2]; void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error); + /* Used for kvec iter backed by vmalloc address */ + void *vmap_base; }; struct fuse_args_pages { @@ -823,6 +826,9 @@ struct fuse_conn { /* Is statx not implemented by fs? */ unsigned int no_statx:1; + /* Use pages instead of pointer for kernel I/O */ + unsigned int use_pages_for_kvec_io:1; + /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index ceb9f7d23038..fca2be898336 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -625,7 +625,7 @@ void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos, args->out_args[0].size = count; } -static void fuse_release_user_pages(struct fuse_args_pages *ap, +static void fuse_release_user_pages(struct fuse_args_pages *ap, ssize_t nres, bool should_dirty) { unsigned int i; @@ -635,6 +635,9 @@ static void fuse_release_user_pages(struct fuse_args_pages *ap, set_page_dirty_lock(ap->pages[i]); put_page(ap->pages[i]); } + + if (nres > 0 && ap->args.invalidate_vmap) + invalidate_kernel_vmap_range(ap->args.vmap_base, nres); } static void fuse_io_release(struct kref *kref) @@ -733,25 +736,29 @@ static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args, struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args); struct fuse_io_priv *io = ia->io; ssize_t pos = -1; - - fuse_release_user_pages(&ia->ap, io->should_dirty); + size_t nres; if (err) { /* Nothing */ } else if (io->write) { if (ia->write.out.size > ia->write.in.size) { err = -EIO; - } else if (ia->write.in.size != ia->write.out.size) { - pos = ia->write.in.offset - io->offset + - ia->write.out.size; + } else { + nres = ia->write.out.size; + if (ia->write.in.size != ia->write.out.size) + pos = ia->write.in.offset - io->offset + + ia->write.out.size; } } else { u32 outsize = args->out_args[0].size; + nres = outsize; if (ia->read.in.size != outsize) pos = ia->read.in.offset - io->offset + outsize; } + fuse_release_user_pages(&ia->ap, err ?: nres, io->should_dirty); + fuse_aio_complete(io, err, pos); fuse_io_free(ia); } @@ -1368,24 +1375,37 @@ static inline size_t fuse_get_frag_size(const struct iov_iter *ii, static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, size_t *nbytesp, int write, - unsigned int max_pages) + unsigned int max_pages, + bool use_pages_for_kvec_io) { + bool flush_or_invalidate = false; size_t nbytes = 0; /* # bytes already packed in req */ ssize_t ret = 0; - /* Special case for kernel I/O: can copy directly into the buffer */ + /* Special case for kernel I/O: can copy directly into the buffer. + * However if the implementation of fuse_conn requires pages instead of + * pointer (e.g., virtio-fs), use iov_iter_extract_pages() instead. + */ if (iov_iter_is_kvec(ii)) { - unsigned long user_addr = fuse_get_user_addr(ii); - size_t frag_size = fuse_get_frag_size(ii, *nbytesp); + void *user_addr = (void *)fuse_get_user_addr(ii); - if (write) - ap->args.in_args[1].value = (void *) user_addr; - else - ap->args.out_args[0].value = (void *) user_addr; + if (!use_pages_for_kvec_io) { + size_t frag_size = fuse_get_frag_size(ii, *nbytesp); - iov_iter_advance(ii, frag_size); - *nbytesp = frag_size; - return 0; + if (write) + ap->args.in_args[1].value = user_addr; + else + ap->args.out_args[0].value = user_addr; + + iov_iter_advance(ii, frag_size); + *nbytesp = frag_size; + return 0; + } + + if (is_vmalloc_addr(user_addr)) { + ap->args.vmap_base = user_addr; + flush_or_invalidate = true; + } } while (nbytes < *nbytesp && ap->num_pages < max_pages) { @@ -1411,6 +1431,10 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, (PAGE_SIZE - ret) & (PAGE_SIZE - 1); } + if (write && flush_or_invalidate) + flush_kernel_vmap_range(ap->args.vmap_base, nbytes); + + ap->args.invalidate_vmap = !write && flush_or_invalidate; ap->args.user_pages = true; if (write) ap->args.in_pages = true; @@ -1478,7 +1502,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, size_t nbytes = min(count, nmax); err = fuse_get_user_pages(&ia->ap, iter, &nbytes, write, - max_pages); + max_pages, fc->use_pages_for_kvec_io); if (err && !nbytes) break; @@ -1492,7 +1516,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, } if (!io->async || nres < 0) { - fuse_release_user_pages(&ia->ap, io->should_dirty); + fuse_release_user_pages(&ia->ap, nres, io->should_dirty); fuse_io_free(ia); } ia = NULL; diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index d84dacbdce2c..5779c7ba1e3d 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -1458,6 +1458,7 @@ static int virtio_fs_get_tree(struct fs_context *fsc) fc->delete_stale = true; fc->auto_submounts = true; fc->sync_fs = true; + fc->use_pages_for_kvec_io = true; /* Tell FUSE to split requests that exceed the virtqueue's size */ fc->max_pages_limit = min_t(unsigned int, fc->max_pages_limit, -- 2.39.2
2 1
0 0
[PATCH openEuler-22.03-LTS-SP1] io_uring: check if iowq is killed before queuing
by Yifan Qiao 30 Dec '24

30 Dec '24
From: Pavel Begunkov <asml.silence(a)gmail.com> stable inclusion from stable-v6.6.68 commit 2ca94c8de36091067b9ce7527ae8db3812d38781 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEG43 CVE: CVE-2024-56709 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- commit dbd2ca9367eb19bc5e269b8c58b0b1514ada9156 upstream. task work can be executed after the task has gone through io_uring termination, whether it's the final task_work run or the fallback path. In this case, task work will find ->io_wq being already killed and null'ed, which is a problem if it then tries to forward the request to io_queue_iowq(). Make io_queue_iowq() fail requests in this case. Note that it also checks PF_KTHREAD, because the user can first close a DEFER_TASKRUN ring and shortly after kill the task, in which case ->iowq check would race. Cc: stable(a)vger.kernel.org Fixes: 50c52250e2d74 ("block: implement async io_uring discard cmd") Fixes: 773af69121ecc ("io_uring: always reissue from task_work context") Reported-by: Will <willsroot(a)protonmail.com> Signed-off-by: Pavel Begunkov <asml.silence(a)gmail.com> Link: https://lore.kernel.org/r/63312b4a2c2bb67ad67b857d17a300e1d3b078e8.17346379… Signed-off-by: Jens Axboe <axboe(a)kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org> Signed-off-by: Yifan Qiao <qiaoyifan4(a)huawei.com> --- io_uring/io_uring.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 4d69fb4cf803..bb37e8f08ae5 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -1090,6 +1090,7 @@ static struct file *io_file_get(struct io_ring_ctx *ctx, unsigned int issue_flags); static void __io_queue_sqe(struct io_kiocb *req); static void io_rsrc_put_work(struct work_struct *work); +static void io_req_task_queue_fail(struct io_kiocb *req, int ret); static void io_req_task_queue(struct io_kiocb *req); static void io_submit_flush_completions(struct io_ring_ctx *ctx); @@ -1459,7 +1460,11 @@ static void io_queue_async_work(struct io_kiocb *req, bool *locked) locked = NULL; BUG_ON(!tctx); - BUG_ON(!tctx->io_wq); + + if ((current->flags & PF_KTHREAD) || !tctx->io_wq) { + io_req_task_queue_fail(req, -ECANCELED); + return; + } /* init ->work of the whole link before punting */ io_prep_async_link(req); -- 2.39.2
2 1
0 0
[PATCH openEuler-22.03-LTS-SP1] virtiofs: use pages instead of pointer for kernel direct IO
by Yifan Qiao 30 Dec '24

30 Dec '24
From: Hou Tao <houtao1(a)huawei.com> mainline inclusion from mainline-v6.13-rc1 commit 41748675c0bf252b3c5f600a95830f0936d366c1 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAGA CVE: CVE-2024-53219 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- When trying to insert a 10MB kernel module kept in a virtio-fs with cache disabled, the following warning was reported: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 404 at mm/page_alloc.c:4551 ...... Modules linked in: CPU: 1 PID: 404 Comm: insmod Not tainted 6.9.0-rc5+ #123 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) ...... RIP: 0010:__alloc_pages+0x2bf/0x380 ...... Call Trace: <TASK> ? __warn+0x8e/0x150 ? __alloc_pages+0x2bf/0x380 __kmalloc_large_node+0x86/0x160 __kmalloc+0x33c/0x480 virtio_fs_enqueue_req+0x240/0x6d0 virtio_fs_wake_pending_and_unlock+0x7f/0x190 queue_request_and_unlock+0x55/0x60 fuse_simple_request+0x152/0x2b0 fuse_direct_io+0x5d2/0x8c0 fuse_file_read_iter+0x121/0x160 __kernel_read+0x151/0x2d0 kernel_read+0x45/0x50 kernel_read_file+0x1a9/0x2a0 init_module_from_file+0x6a/0xe0 idempotent_init_module+0x175/0x230 __x64_sys_finit_module+0x5d/0xb0 x64_sys_call+0x1c3/0x9e0 do_syscall_64+0x3d/0xc0 entry_SYSCALL_64_after_hwframe+0x4b/0x53 ...... </TASK> ---[ end trace 0000000000000000 ]--- The warning is triggered as follows: 1) syscall finit_module() handles the module insertion and it invokes kernel_read_file() to read the content of the module first. 2) kernel_read_file() allocates a 10MB buffer by using vmalloc() and passes it to kernel_read(). kernel_read() constructs a kvec iter by using iov_iter_kvec() and passes it to fuse_file_read_iter(). 3) virtio-fs disables the cache, so fuse_file_read_iter() invokes fuse_direct_io(). As for now, the maximal read size for kvec iter is only limited by fc->max_read. For virtio-fs, max_read is UINT_MAX, so fuse_direct_io() doesn't split the 10MB buffer. It saves the address and the size of the 10MB-sized buffer in out_args[0] of a fuse request and passes the fuse request to virtio_fs_wake_pending_and_unlock(). 4) virtio_fs_wake_pending_and_unlock() uses virtio_fs_enqueue_req() to queue the request. Because virtiofs need DMA-able address, so virtio_fs_enqueue_req() uses kmalloc() to allocate a bounce buffer for all fuse args, copies these args into the bounce buffer and passed the physical address of the bounce buffer to virtiofsd. The total length of these fuse args for the passed fuse request is about 10MB, so copy_args_to_argbuf() invokes kmalloc() with a 10MB size parameter and it triggers the warning in __alloc_pages(): if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp)) return NULL; 5) virtio_fs_enqueue_req() will retry the memory allocation in a kworker, but it won't help, because kmalloc() will always return NULL due to the abnormal size and finit_module() will hang forever. A feasible solution is to limit the value of max_read for virtio-fs, so the length passed to kmalloc() will be limited. However it will affect the maximal read size for normal read. And for virtio-fs write initiated from kernel, it has the similar problem but now there is no way to limit fc->max_write in kernel. So instead of limiting both the values of max_read and max_write in kernel, introducing use_pages_for_kvec_io in fuse_conn and setting it as true in virtiofs. When use_pages_for_kvec_io is enabled, fuse will use pages instead of pointer to pass the KVEC_IO data. After switching to pages for KVEC_IO data, these pages will be used for DMA through virtio-fs. If these pages are backed by vmalloc(), {flush|invalidate}_kernel_vmap_range() are necessary to flush or invalidate the cache before the DMA operation. So add two new fields in fuse_args_pages to record the base address of vmalloc area and the condition indicating whether invalidation is needed. Perform the flush in fuse_get_user_pages() for write operations and the invalidation in fuse_release_user_pages() for read operations. It may seem necessary to introduce another field in fuse_conn to indicate that these KVEC_IO pages are used for DMA, However, considering that virtio-fs is currently the only user of use_pages_for_kvec_io, just reuse use_pages_for_kvec_io to indicate that these pages will be used for DMA. Fixes: a62a8ef9d97d ("virtio-fs: add virtiofs filesystem") Signed-off-by: Hou Tao <houtao1(a)huawei.com> Tested-by: Jingbo Xu <jefflexu(a)linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi(a)redhat.com> Signed-off-by: Yifan Qiao <qiaoyifan4(a)huawei.com> --- fs/fuse/fuse_i.h | 6 +++++ fs/fuse/file.c | 62 +++++++++++++++++++++++++++++++-------------- fs/fuse/virtio_fs.c | 1 + 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 029f8e382c97..4ad05b0c72b7 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -273,9 +273,12 @@ struct fuse_args { #ifndef __GENKSYMS__ bool user_pages:1; #endif + bool invalidate_vmap:1; struct fuse_in_arg in_args[3]; struct fuse_arg out_args[2]; void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error); + /* Used for kvec iter backed by vmalloc address */ + void *vmap_base; }; struct fuse_args_pages { @@ -763,6 +766,9 @@ struct fuse_conn { /* Auto-mount submounts announced by the server */ unsigned int auto_submounts:1; + /* Use pages instead of pointer for kernel I/O */ + unsigned int use_pages_for_kvec_io:1; + /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 86f2e1c2ad0f..da6d8e241e8f 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -610,7 +610,7 @@ void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos, args->out_args[0].size = count; } -static void fuse_release_user_pages(struct fuse_args_pages *ap, +static void fuse_release_user_pages(struct fuse_args_pages *ap, ssize_t nres, bool should_dirty) { unsigned int i; @@ -620,6 +620,9 @@ static void fuse_release_user_pages(struct fuse_args_pages *ap, set_page_dirty_lock(ap->pages[i]); put_page(ap->pages[i]); } + + if (nres > 0 && ap->args.invalidate_vmap) + invalidate_kernel_vmap_range(ap->args.vmap_base, nres); } static void fuse_io_release(struct kref *kref) @@ -718,25 +721,29 @@ static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args, struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args); struct fuse_io_priv *io = ia->io; ssize_t pos = -1; - - fuse_release_user_pages(&ia->ap, io->should_dirty); + size_t nres; if (err) { /* Nothing */ } else if (io->write) { if (ia->write.out.size > ia->write.in.size) { err = -EIO; - } else if (ia->write.in.size != ia->write.out.size) { - pos = ia->write.in.offset - io->offset + - ia->write.out.size; + } else { + nres = ia->write.out.size; + if (ia->write.in.size != ia->write.out.size) + pos = ia->write.in.offset - io->offset + + ia->write.out.size; } } else { u32 outsize = args->out_args[0].size; + nres = outsize; if (ia->read.in.size != outsize) pos = ia->read.in.offset - io->offset + outsize; } + fuse_release_user_pages(&ia->ap, err ?: nres, io->should_dirty); + fuse_aio_complete(io, err, pos); fuse_io_free(ia); } @@ -1389,24 +1396,37 @@ static inline size_t fuse_get_frag_size(const struct iov_iter *ii, static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, size_t *nbytesp, int write, - unsigned int max_pages) + unsigned int max_pages, + bool use_pages_for_kvec_io) { + bool flush_or_invalidate = false; size_t nbytes = 0; /* # bytes already packed in req */ ssize_t ret = 0; - /* Special case for kernel I/O: can copy directly into the buffer */ + /* Special case for kernel I/O: can copy directly into the buffer. + * However if the implementation of fuse_conn requires pages instead of + * pointer (e.g., virtio-fs), use iov_iter_extract_pages() instead. + */ if (iov_iter_is_kvec(ii)) { - unsigned long user_addr = fuse_get_user_addr(ii); - size_t frag_size = fuse_get_frag_size(ii, *nbytesp); + void *user_addr = (void *)fuse_get_user_addr(ii); - if (write) - ap->args.in_args[1].value = (void *) user_addr; - else - ap->args.out_args[0].value = (void *) user_addr; + if (!use_pages_for_kvec_io) { + size_t frag_size = fuse_get_frag_size(ii, *nbytesp); - iov_iter_advance(ii, frag_size); - *nbytesp = frag_size; - return 0; + if (write) + ap->args.in_args[1].value = user_addr; + else + ap->args.out_args[0].value = user_addr; + + iov_iter_advance(ii, frag_size); + *nbytesp = frag_size; + return 0; + } + + if (is_vmalloc_addr(user_addr)) { + ap->args.vmap_base = user_addr; + flush_or_invalidate = true; + } } while (nbytes < *nbytesp && ap->num_pages < max_pages) { @@ -1433,6 +1453,10 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, (PAGE_SIZE - ret) & (PAGE_SIZE - 1); } + if (write && flush_or_invalidate) + flush_kernel_vmap_range(ap->args.vmap_base, nbytes); + + ap->args.invalidate_vmap = !write && flush_or_invalidate; ap->args.user_pages = true; if (write) ap->args.in_pages = true; @@ -1484,7 +1508,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, size_t nbytes = min(count, nmax); err = fuse_get_user_pages(&ia->ap, iter, &nbytes, write, - max_pages); + max_pages, fc->use_pages_for_kvec_io); if (err && !nbytes) break; @@ -1498,7 +1522,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, } if (!io->async || nres < 0) { - fuse_release_user_pages(&ia->ap, io->should_dirty); + fuse_release_user_pages(&ia->ap, nres, io->should_dirty); fuse_io_free(ia); } ia = NULL; diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index 77338f139cb2..da5e1d1826ff 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -1461,6 +1461,7 @@ static int virtio_fs_get_tree(struct fs_context *fsc) fc->release = fuse_free_conn; fc->delete_stale = true; fc->auto_submounts = true; + fc->use_pages_for_kvec_io = true; fsc->s_fs_info = fm; sb = sget_fc(fsc, virtio_fs_test_super, virtio_fs_set_super); -- 2.39.2
2 1
0 0
[PATCH OLK-5.10] virtiofs: use pages instead of pointer for kernel direct IO
by Yifan Qiao 30 Dec '24

30 Dec '24
From: Hou Tao <houtao1(a)huawei.com> mainline inclusion from mainline-v6.13-rc1 commit 41748675c0bf252b3c5f600a95830f0936d366c1 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAGA CVE: CVE-2024-53219 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- When trying to insert a 10MB kernel module kept in a virtio-fs with cache disabled, the following warning was reported: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 404 at mm/page_alloc.c:4551 ...... Modules linked in: CPU: 1 PID: 404 Comm: insmod Not tainted 6.9.0-rc5+ #123 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) ...... RIP: 0010:__alloc_pages+0x2bf/0x380 ...... Call Trace: <TASK> ? __warn+0x8e/0x150 ? __alloc_pages+0x2bf/0x380 __kmalloc_large_node+0x86/0x160 __kmalloc+0x33c/0x480 virtio_fs_enqueue_req+0x240/0x6d0 virtio_fs_wake_pending_and_unlock+0x7f/0x190 queue_request_and_unlock+0x55/0x60 fuse_simple_request+0x152/0x2b0 fuse_direct_io+0x5d2/0x8c0 fuse_file_read_iter+0x121/0x160 __kernel_read+0x151/0x2d0 kernel_read+0x45/0x50 kernel_read_file+0x1a9/0x2a0 init_module_from_file+0x6a/0xe0 idempotent_init_module+0x175/0x230 __x64_sys_finit_module+0x5d/0xb0 x64_sys_call+0x1c3/0x9e0 do_syscall_64+0x3d/0xc0 entry_SYSCALL_64_after_hwframe+0x4b/0x53 ...... </TASK> ---[ end trace 0000000000000000 ]--- The warning is triggered as follows: 1) syscall finit_module() handles the module insertion and it invokes kernel_read_file() to read the content of the module first. 2) kernel_read_file() allocates a 10MB buffer by using vmalloc() and passes it to kernel_read(). kernel_read() constructs a kvec iter by using iov_iter_kvec() and passes it to fuse_file_read_iter(). 3) virtio-fs disables the cache, so fuse_file_read_iter() invokes fuse_direct_io(). As for now, the maximal read size for kvec iter is only limited by fc->max_read. For virtio-fs, max_read is UINT_MAX, so fuse_direct_io() doesn't split the 10MB buffer. It saves the address and the size of the 10MB-sized buffer in out_args[0] of a fuse request and passes the fuse request to virtio_fs_wake_pending_and_unlock(). 4) virtio_fs_wake_pending_and_unlock() uses virtio_fs_enqueue_req() to queue the request. Because virtiofs need DMA-able address, so virtio_fs_enqueue_req() uses kmalloc() to allocate a bounce buffer for all fuse args, copies these args into the bounce buffer and passed the physical address of the bounce buffer to virtiofsd. The total length of these fuse args for the passed fuse request is about 10MB, so copy_args_to_argbuf() invokes kmalloc() with a 10MB size parameter and it triggers the warning in __alloc_pages(): if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp)) return NULL; 5) virtio_fs_enqueue_req() will retry the memory allocation in a kworker, but it won't help, because kmalloc() will always return NULL due to the abnormal size and finit_module() will hang forever. A feasible solution is to limit the value of max_read for virtio-fs, so the length passed to kmalloc() will be limited. However it will affect the maximal read size for normal read. And for virtio-fs write initiated from kernel, it has the similar problem but now there is no way to limit fc->max_write in kernel. So instead of limiting both the values of max_read and max_write in kernel, introducing use_pages_for_kvec_io in fuse_conn and setting it as true in virtiofs. When use_pages_for_kvec_io is enabled, fuse will use pages instead of pointer to pass the KVEC_IO data. After switching to pages for KVEC_IO data, these pages will be used for DMA through virtio-fs. If these pages are backed by vmalloc(), {flush|invalidate}_kernel_vmap_range() are necessary to flush or invalidate the cache before the DMA operation. So add two new fields in fuse_args_pages to record the base address of vmalloc area and the condition indicating whether invalidation is needed. Perform the flush in fuse_get_user_pages() for write operations and the invalidation in fuse_release_user_pages() for read operations. It may seem necessary to introduce another field in fuse_conn to indicate that these KVEC_IO pages are used for DMA, However, considering that virtio-fs is currently the only user of use_pages_for_kvec_io, just reuse use_pages_for_kvec_io to indicate that these pages will be used for DMA. Fixes: a62a8ef9d97d ("virtio-fs: add virtiofs filesystem") Signed-off-by: Hou Tao <houtao1(a)huawei.com> Tested-by: Jingbo Xu <jefflexu(a)linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi(a)redhat.com> Signed-off-by: Yifan Qiao <qiaoyifan4(a)huawei.com> --- fs/fuse/fuse_i.h | 6 +++++ fs/fuse/file.c | 62 +++++++++++++++++++++++++++++++-------------- fs/fuse/virtio_fs.c | 1 + 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 11cc437fe078..749003487776 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -273,9 +273,12 @@ struct fuse_args { #ifndef __GENKSYMS__ bool user_pages:1; #endif + bool invalidate_vmap:1; struct fuse_in_arg in_args[3]; struct fuse_arg out_args[2]; void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error); + /* Used for kvec iter backed by vmalloc address */ + void *vmap_base; }; struct fuse_args_pages { @@ -766,6 +769,9 @@ struct fuse_conn { /* Auto-mount submounts announced by the server */ unsigned int auto_submounts:1; + /* Use pages instead of pointer for kernel I/O */ + unsigned int use_pages_for_kvec_io:1; + /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d3e798b5a560..e0aac6019cdb 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -615,7 +615,7 @@ void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos, args->out_args[0].size = count; } -static void fuse_release_user_pages(struct fuse_args_pages *ap, +static void fuse_release_user_pages(struct fuse_args_pages *ap, ssize_t nres, bool should_dirty) { unsigned int i; @@ -625,6 +625,9 @@ static void fuse_release_user_pages(struct fuse_args_pages *ap, set_page_dirty_lock(ap->pages[i]); put_page(ap->pages[i]); } + + if (nres > 0 && ap->args.invalidate_vmap) + invalidate_kernel_vmap_range(ap->args.vmap_base, nres); } static void fuse_io_release(struct kref *kref) @@ -723,25 +726,29 @@ static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args, struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args); struct fuse_io_priv *io = ia->io; ssize_t pos = -1; - - fuse_release_user_pages(&ia->ap, io->should_dirty); + size_t nres; if (err) { /* Nothing */ } else if (io->write) { if (ia->write.out.size > ia->write.in.size) { err = -EIO; - } else if (ia->write.in.size != ia->write.out.size) { - pos = ia->write.in.offset - io->offset + - ia->write.out.size; + } else { + nres = ia->write.out.size; + if (ia->write.in.size != ia->write.out.size) + pos = ia->write.in.offset - io->offset + + ia->write.out.size; } } else { u32 outsize = args->out_args[0].size; + nres = outsize; if (ia->read.in.size != outsize) pos = ia->read.in.offset - io->offset + outsize; } + fuse_release_user_pages(&ia->ap, err ?: nres, io->should_dirty); + fuse_aio_complete(io, err, pos); fuse_io_free(ia); } @@ -1394,24 +1401,37 @@ static inline size_t fuse_get_frag_size(const struct iov_iter *ii, static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, size_t *nbytesp, int write, - unsigned int max_pages) + unsigned int max_pages, + bool use_pages_for_kvec_io) { + bool flush_or_invalidate = false; size_t nbytes = 0; /* # bytes already packed in req */ ssize_t ret = 0; - /* Special case for kernel I/O: can copy directly into the buffer */ + /* Special case for kernel I/O: can copy directly into the buffer. + * However if the implementation of fuse_conn requires pages instead of + * pointer (e.g., virtio-fs), use iov_iter_extract_pages() instead. + */ if (iov_iter_is_kvec(ii)) { - unsigned long user_addr = fuse_get_user_addr(ii); - size_t frag_size = fuse_get_frag_size(ii, *nbytesp); + void *user_addr = (void *)fuse_get_user_addr(ii); - if (write) - ap->args.in_args[1].value = (void *) user_addr; - else - ap->args.out_args[0].value = (void *) user_addr; + if (!use_pages_for_kvec_io) { + size_t frag_size = fuse_get_frag_size(ii, *nbytesp); - iov_iter_advance(ii, frag_size); - *nbytesp = frag_size; - return 0; + if (write) + ap->args.in_args[1].value = user_addr; + else + ap->args.out_args[0].value = user_addr; + + iov_iter_advance(ii, frag_size); + *nbytesp = frag_size; + return 0; + } + + if (is_vmalloc_addr(user_addr)) { + ap->args.vmap_base = user_addr; + flush_or_invalidate = true; + } } while (nbytes < *nbytesp && ap->num_pages < max_pages) { @@ -1438,6 +1458,10 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, (PAGE_SIZE - ret) & (PAGE_SIZE - 1); } + if (write && flush_or_invalidate) + flush_kernel_vmap_range(ap->args.vmap_base, nbytes); + + ap->args.invalidate_vmap = !write && flush_or_invalidate; ap->args.user_pages = true; if (write) ap->args.in_pages = true; @@ -1489,7 +1513,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, size_t nbytes = min(count, nmax); err = fuse_get_user_pages(&ia->ap, iter, &nbytes, write, - max_pages); + max_pages, fc->use_pages_for_kvec_io); if (err && !nbytes) break; @@ -1503,7 +1527,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, } if (!io->async || nres < 0) { - fuse_release_user_pages(&ia->ap, io->should_dirty); + fuse_release_user_pages(&ia->ap, nres, io->should_dirty); fuse_io_free(ia); } ia = NULL; diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index 17d30577340a..4ef123691a83 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -1464,6 +1464,7 @@ static int virtio_fs_get_tree(struct fs_context *fsc) fc->release = fuse_free_conn; fc->delete_stale = true; fc->auto_submounts = true; + fc->use_pages_for_kvec_io = true; /* Tell FUSE to split requests that exceed the virtqueue's size */ fc->max_pages_limit = min_t(unsigned int, fc->max_pages_limit, -- 2.39.2
2 1
0 0
[PATCH OLK-5.10] io_uring: check if iowq is killed before queuing
by Yifan Qiao 30 Dec '24

30 Dec '24
From: Pavel Begunkov <asml.silence(a)gmail.com> stable inclusion from stable-v6.6.68 commit 2ca94c8de36091067b9ce7527ae8db3812d38781 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEG43 CVE: CVE-2024-56709 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- commit dbd2ca9367eb19bc5e269b8c58b0b1514ada9156 upstream. task work can be executed after the task has gone through io_uring termination, whether it's the final task_work run or the fallback path. In this case, task work will find ->io_wq being already killed and null'ed, which is a problem if it then tries to forward the request to io_queue_iowq(). Make io_queue_iowq() fail requests in this case. Note that it also checks PF_KTHREAD, because the user can first close a DEFER_TASKRUN ring and shortly after kill the task, in which case ->iowq check would race. Cc: stable(a)vger.kernel.org Fixes: 50c52250e2d74 ("block: implement async io_uring discard cmd") Fixes: 773af69121ecc ("io_uring: always reissue from task_work context") Reported-by: Will <willsroot(a)protonmail.com> Signed-off-by: Pavel Begunkov <asml.silence(a)gmail.com> Link: https://lore.kernel.org/r/63312b4a2c2bb67ad67b857d17a300e1d3b078e8.17346379… Signed-off-by: Jens Axboe <axboe(a)kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org> Signed-off-by: Yifan Qiao <qiaoyifan4(a)huawei.com> --- io_uring/io_uring.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 6e5e00a7692c..3a1eee5bac77 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -1096,6 +1096,7 @@ static struct file *io_file_get(struct io_ring_ctx *ctx, unsigned int issue_flags); static void __io_queue_sqe(struct io_kiocb *req); static void io_rsrc_put_work(struct work_struct *work); +static void io_req_task_queue_fail(struct io_kiocb *req, int ret); static void io_req_task_queue(struct io_kiocb *req); static void io_submit_flush_completions(struct io_ring_ctx *ctx); @@ -1465,7 +1466,11 @@ static void io_queue_async_work(struct io_kiocb *req, bool *locked) locked = NULL; BUG_ON(!tctx); - BUG_ON(!tctx->io_wq); + + if ((current->flags & PF_KTHREAD) || !tctx->io_wq) { + io_req_task_queue_fail(req, -ECANCELED); + return; + } /* init ->work of the whole link before punting */ io_prep_async_link(req); -- 2.39.2
2 1
0 0
[PATCH openEuler-22.03-LTS-SP1] ftrace: Fix regression with module command in stack_trace_filter
by Luo Gengkun 30 Dec '24

30 Dec '24
From: guoweikang <guoweikang.kernel(a)gmail.com> stable inclusion from stable-v5.10.231 commit 5dabb7af57bc72308a6e2e81a5dd756eef283803 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAMJ CVE: CVE-2024-56569 Reference: https://git.kernel.org/stable/c/5dabb7af57bc72308a6e2e81a5dd756eef283803 -------------------------------- commit 45af52e7d3b8560f21d139b3759735eead8b1653 upstream. When executing the following command: # echo "write*:mod:ext3" > /sys/kernel/tracing/stack_trace_filter The current mod command causes a null pointer dereference. While commit 0f17976568b3f ("ftrace: Fix regression with module command in stack_trace_filter") has addressed part of the issue, it left a corner case unhandled, which still results in a kernel crash. Cc: stable(a)vger.kernel.org Cc: Masami Hiramatsu <mhiramat(a)kernel.org> Cc: Mark Rutland <mark.rutland(a)arm.com> Cc: Mathieu Desnoyers <mathieu.desnoyers(a)efficios.com> Link: https://lore.kernel.org/20241120052750.275463-1-guoweikang.kernel@gmail.com Fixes: 04ec7bb642b77 ("tracing: Have the trace_array hold the list of registered func probes"); Signed-off-by: guoweikang <guoweikang.kernel(a)gmail.com> Signed-off-by: Steven Rostedt (Google) <rostedt(a)goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org> Signed-off-by: Luo Gengkun <luogengkun2(a)huawei.com> --- kernel/trace/ftrace.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 9631df0bbbae..b06d8905b15e 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -4297,6 +4297,9 @@ ftrace_mod_callback(struct trace_array *tr, struct ftrace_hash *hash, char *func; int ret; + if (!tr) + return -ENODEV; + /* match_records() modifies func, and we need the original */ func = kstrdup(func_orig, GFP_KERNEL); if (!func) -- 2.34.1
2 1
0 0
  • ← Newer
  • 1
  • ...
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • ...
  • 1837
  • Older →

HyperKitty Powered by HyperKitty