Export limit exceeded: 200632 CVEs match your query. Please refine your search to export 10,000 CVEs or fewer.

Search

Search Results (200632 CVEs found)

CVE Vendors Products Updated CVSS v3.1
CVE-2026-89762 1 Linux 1 Linux Kernel 2026-10-30 7.8 High
In the Linux kernel, the following vulnerability has been resolved: apparmor: fix cred UAF caused by begin_current_label_crit_section() AppArmor's begin_current_label_crit_section() is a scary function called from lots of LSM hooks (in particular VFS/socket-related ones) that checks if the label referenced by the current creds is marked FLAG_STALE, and if so, attempts to use aa_replace_current_label() to replace the creds with an updated version that uses a new label. The first problem with this is that it would directly lead to UAF of `struct cred` if anything in the kernel takes a pointer to the current creds and accesses these past a security hook invocation that replaces creds, like so: ``` const struct cred *cred = current_cred(); alloc_file_pseudo(...); uid_t uid = cred->euid; ``` I don't know if anything in the kernel actually does this, but I think it is very surprising that this pattern could lead to UAF. The second problem is that things go wrong when aa_replace_current_label() runs with overridden credentials. aa_replace_current_label() bails out if `current_cred() != current_real_cred()` (mirroring the check in proc_pid_attr_write()), but this check can't actually reliably detect overridden credentials because the overridden creds can be the same as the objective creds. So in approximately the following scenario, things go wrong: 1. task begins with <creds A> (as both objective and subjective creds), with refcount=2 2. task grabs an extra reference on <creds A> for overriding 3. task calls override_creds(<creds A>), which returns a pointer to the old subjective creds (<creds A>) 4. task enters AppArmor LSM hook 5. AppArmor checks that objective/subjective creds are equal 6. AppArmor replaces both cred pointers with <creds B> and drops 2 refs on <creds A> 7. task leaves AppArmor LSM hook 8. task calls revert_creds(<creds A>) 9. now task->cred is <creds A> while task->real_cred is <creds B>, but the task_struct logically holds two references to <creds B> 10. another task drops the extra reference on <creds A> that was used for overriding, refcount drops to 0 11. now task->real_cred points to freed creds At this point, any access to current_cred() will be UAF. I have a test case where I run aa-disable on a profile while a process using that profile is blocked on splice() from a FUSE passthrough file into a full pipe; after the profile update, the pipe becomes empty, splice() resumes, the credentials go out of sync, and a subsequent getuid() syscall results in a KASAN UAF splat. To fix this, instead of directly replacing creds, do it via task_work that will run at the end of the current syscall. (The point in time at which the cred replacement happens should have no correctness impact; it is just a performance optimization to avoid unnecessarily touching the refcount of the new label.) Note that AppArmor still performs direct cred replacements in the sb_pivotroot LSM hook after this change, and that direct cred replacements can still happen in VFS ->write() callbacks via proc_pid_attr_write(). There are two options for what to do with aa_dup_task_ctx(): Either explicitly reset new->label_replacement_pending after the entire aa_task_ctx has been copied, or switch to manually copying members over. I am switching to manually copying members over because that should make bugs more obvious.
CVE-2026-89761 1 Linux 1 Linux Kernel 2026-10-30 7.8 High
In the Linux kernel, the following vulnerability has been resolved: apparmor: fix out-of-bounds write when null terminating a label vec aa_vec_unique() null terminates at vec[n - dups] when VEC_FLAG_TERMINATE is passed. If the components are all distinct no duplicates are dropped, dups is 0 and the terminator goes to vec[n], so the caller has to provide room for n + 1 entries. aa_label_strn_parse() sets up its vector with vec_setup(profile, vec, len, gfp) and then calls aa_vec_unique(vec, len, VEC_FLAG_TERMINATE), but vec_setup() does not reserve the terminator entry. Up to LOCAL_VEC_ENTRIES it uses the local array of LOCAL_VEC_ENTRIES pointers, above that it allocates exactly len pointers. The terminator therefore lands one entry past the end of the local array when len is LOCAL_VEC_ENTRIES, and one entry past the end of the allocation when len is larger. len comes from the number of "//&" separated components in the label name and label_count_strn_entries() does not bound it. An unprivileged task reaches the parse by writing to /proc/self/attr/apparmor/current or through lsm_set_self_attr(2), both of which go through do_setattr(), and the name is parsed before the change_profile permission is checked. The query_label() path behind the securityfs .access file, which is mode 0666, performs no permission check at all. Every component has to resolve to a loaded profile, so a system with policy loaded is required. The other two VEC_FLAG_TERMINATE users work on a label vec that aa_label_alloc() has already sized with "+ 1 for null terminator entry on vec". Reserve the same entry in vec_setup() and DEFINE_VEC(). Passing len + 1 from the caller instead would move len == LOCAL_VEC_ENTRIES out of the local array and into kzalloc().
CVE-2026-89757 1 Linux 1 Linux Kernel 2026-10-30 5.3 Medium
In the Linux kernel, the following vulnerability has been resolved: mm/mglru: fix and remove redundant unevictable folio handling sort_folio() has a shortcut for moving folios that are no longer evictable but are still sitting on a generation list. However, this shortcut is buggy. It does not follow the PG_lru usage convention, and it has a more serious issue. Unevictable folios are not threaded on lists[LRU_UNEVICTABLE], so that folio->lru can be reused to hold folio->mlock_count (see the comment in lruvec_init()). Hence lruvec_add_folio() skips the list_add() for them, and every other place that turns a folio unevictable initialises mlock_count explicitly: lru_add() sets it to 0, __mlock_folio() and __mlock_new_folio() set it to !!folio_test_mlocked(folio). sort_folio() sets nothing, and the lru_gen_del_folio() right above it may have already poisoned folio->lru via list_del(), so mlock_count ends up aliasing LIST_POISON2, which reads as 0x122, i.e. 290. The result is user visible. On munlock, __munlock_folio() decrements that bogus count, finds it still non-zero and bails out before clearing PG_mlocked, so the folio remains unevictable and the Mlocked accounting stays inflated until the folio is freed. The shortcut also touches the LRU flags in the wrong order. It calls lru_gen_del_folio() while PG_lru is still set, so a concurrent folio_test_clear_lru() (e.g. compaction, folio_isolate_lru()) can succeed on a folio that has already been taken off the generation list, which may lead to unexpected behavior. So fix it by isolating them as common folios and letting the generic shrink path cull them. This matches the classical LRU behavior, and there should be no visible effect on the generic eviction or isolation behavior. There is no performance concern either, such a folio goes through this once, and then it is off the generation lists for good.
CVE-2026-89740 1 Linux 1 Linux Kernel 2026-10-30 6.3 Medium
In the Linux kernel, the following vulnerability has been resolved: serial: imx: serialize imx_uart_ports[] lifetime imx_uart_probe() publishes its devm-allocated port in imx_uart_ports[] before uart_add_one_port() because console setup uses the table. The entry is not cleared when adding the port fails or after removal, leaving a dangling pointer. A sibling probe can register the shared console through that stale entry. This was reproduced under KASAN on QEMU mcimx6ul-evk by unbinding a sibling UART, unbinding the console UART and rebinding the sibling. Keep the entry valid through uart_remove_one_port(), then clear it. Protect port addition and removal together with their table updates so sibling operations cannot interleave. Reject an occupied slot rather than clobbering an active port during a duplicate-line probe.
CVE-2026-89738 1 Linux 1 Linux Kernel 2026-10-30 7.8 High
In the Linux kernel, the following vulnerability has been resolved: usb: gadget: at91_udc: drain polled-VBUS timer/work before udc is freed In polled-VBUS mode (board.vbus_pin && board.vbus_polled), probe arms a self-restarting cycle: at91_vbus_timer() schedules vbus_timer_work, and at91_vbus_timer_work() calls at91_vbus_update() and re-arms the timer via mod_timer(). Both recover the same udc through container_of and dereference it on every iteration. Neither teardown path cancels this cycle. udc is devm-allocated, so it is freed after at91udc_remove() returns, and is likewise freed when probe fails and devres runs. A timer callback or work item that is pending or running at either point dereferences the freed udc. Add at91_udc_shutdown_vbus_timer() and call it from at91udc_remove() and from the usb_add_gadget_udc() failure path in probe; the remaining probe error paths fail before the timer is armed. timer_shutdown_sync() waits for a running callback and clears timer->function, which makes the work handler's mod_timer() a permanent no-op; cancel_work_sync() then drains any pending or running work whose re-arm attempt now does nothing. The timer must be shut down first, since cancelling the work alone would let the timer re-queue it. The guard mirrors probe: in IRQ mode the timer and work_struct are never initialized. This does not require a fault; a normal driver unbind can interleave with an already queued work item. This issue was found by an in-house static analysis tool.
CVE-2026-89713 1 Linux 1 Linux Kernel 2026-10-30 9.1 Critical
In the Linux kernel, the following vulnerability has been resolved: NFSD: check truncate permission under inode lock nfsd_setattr() checks whether a size update needs NFSD_MAY_TRUNC before it takes inode_lock(). The comparison uses the file size sampled by that unlocked read, but the actual ATTR_SIZE update is applied later under inode_lock() by notify_change(). This leaves a TOCTOU window for append-only files. If a client sends a SETATTR that does not shrink the file at the time of the unlocked sample, a concurrent append can extend the file before nfsd_setattr() takes inode_lock(). notify_change() then applies a real truncation without the NFSD_MAY_TRUNC check that rejects IS_APPEND(inode). The VFS truncate syscall paths perform their own append-only checks before calling notify_change(), so NFSD must make this decision against the locked size it is about to change. Split the write-count acquisition from the truncation permission check. Keep get_write_access() before the locked setattr work, then recheck whether the requested size is below i_size_read(inode) after inode_lock() has been acquired and before notify_change(ATTR_SIZE). This also avoids the plain unlocked inode->i_size load.
CVE-2026-89709 1 Linux 1 Linux Kernel 2026-10-30 8.1 High
In the Linux kernel, the following vulnerability has been resolved: lockd, nfsd: RCU-protect nlmsvc_ops dispatch nlmsvc_ops is published by nfsd_lockd_init() and cleared by nfsd_lockd_shutdown() with plain stores, while lockd dereferences it unguarded from dispatch sites in fs/lockd/svcsubs.c. The pointer targets nfsd's .rodata and the fopen/fclose callbacks live in nfsd's .text, so a stale load after rmmod nfsd results in either a NULL deref or a module-text use-after-free. Declare nlmsvc_ops as __rcu, publish via rcu_assign_pointer(), clear via RCU_INIT_POINTER() + synchronize_rcu(). Add a struct module *owner field to nlmsvc_binding and pin the module across indirect calls with try_module_get/module_put. When the binding is torn down, fall back to fput() to avoid leaking struct file references.
CVE-2026-89707 1 Linux 1 Linux Kernel 2026-10-30 7.5 High
In the Linux kernel, the following vulnerability has been resolved: nfsd: release path refs on follow_down() error nfsd_cross_mnt() initializes a local struct path with mntget() and dget() before calling follow_down(). On a negative return the error arm jumps to out without releasing those references: err = follow_down(&path, follow_flags); if (err < 0) goto out; follow_down() never drops the caller's entry-time refs on any error sub-case; for example a pre-cross d_manage() failure leaves path untouched, so the mntget()/dget() taken on entry survive the call. Every other early-exit arm in nfsd_cross_mnt() (other-namespace return, IS_ERR(exp2), and the success tail after the swap) already calls path_put(&path); the err < 0 arm is the lone omission. The leak inflates mnt_count and d_count on each failed cross-mount, blocking umount and pinning dentries against the shrinker, and is reachable by any authenticated NFS client through nfsd_lookup_dentry or the NFSv4 READDIR encode path. Fix by calling path_put(&path) before the goto out in the err < 0 arm so the entry-time refs are released on all follow_down() error returns.
CVE-2026-89702 1 Linux 1 Linux Kernel 2026-10-30 9.8 Critical
In the Linux kernel, the following vulnerability has been resolved: nfsd: size fh_verify server sockaddr slot by xpt_locallen The nfsd_fh_verify and nfsd_fh_verify_err tracepoints declare the server sockaddr slot sized by xpt_remotelen but fill it from xpt_local using xpt_locallen: TP_STRUCT__entry( ... __sockaddr(server, rqstp->rq_xprt->xpt_remotelen) ... ) TP_fast_assign( ... __assign_sockaddr(server, &rqstp->rq_xprt->xpt_local, rqstp->rq_xprt->xpt_locallen); ... ) When xpt_locallen exceeds xpt_remotelen, __assign_sockaddr's memcpy writes past the reserved ring-buffer slot. In the reverse direction (xpt_locallen < xpt_remotelen) the slot is oversized and the unwritten tail leaks prior ring-buffer contents to trace consumers. The write-past-end case is reachable on NFS/UDP. svc_xprt_set_remote() is only called from svc_tcp_accept() (net/sunrpc/svcsock.c) and from the RDMA connect path; svc_create_socket() for UDP calls only svc_xprt_set_local(), so xpt_remotelen stays 0 for the xprt's lifetime. Every fh_verify trace for an NFSv2/v3-over-UDP request then copies 16 or 28 bytes from xpt_local into a zero-byte slot. The other NFSD tracepoints that record the server address (NFSD_TRACE_PROC_CALL_FIELDS, NFSD_TRACE_PROC_RES_FIELDS, SVC_RQST_ENDPOINT_FIELDS) already size the server slot by xpt_locallen; nfsd_fh_verify and nfsd_fh_verify_err were the only exceptions. Fix by sizing the server slot with xpt_locallen so the declared slot matches the copy length. The client slot and its assignment already agree on xpt_remotelen and are left untouched.
CVE-2026-89686 1 Linux 1 Linux Kernel 2026-10-30 9.8 Critical
In the Linux kernel, the following vulnerability has been resolved: nfsd: fix BUG_ON in nfsd4_alloc_layout_stateid on racing delegation revoke nfsd4_alloc_layout_stateid reads fp->fi_deleg_file without holding fi_lock when the parent stateid is a delegation. A concurrent delegation revoke via the laundromat can clear fi_deleg_file under fi_lock, causing nfsd_file_get() to return NULL and triggering the BUG_ON. This race is client-reachable: two NFS clients can trigger it by having one hold a delegation while another opens the same file to force a recall. When the first client doesn't respond to the recall, the laundromat revokes it. A concurrent LAYOUTGET from any client using the delegation stateid hits the race window. Fix this by taking fi_lock around the fi_deleg_file read in the SC_TYPE_DELEG path, matching the locking discipline of the find_any_file() arm, and replacing the BUG_ON with a graceful error return that cleans up the partially-initialized layout stateid.
CVE-2026-89685 1 Linux 1 Linux Kernel 2026-10-30 7.5 High
In the Linux kernel, the following vulnerability has been resolved: nfsd: fix clock domain mismatch in clients_still_reclaiming() clients_still_reclaiming() computes a deadline from nn->boot_time (CLOCK_REALTIME, ~1.7 billion) but compares it against ktime_get_boottime_seconds() (CLOCK_BOOTTIME, seconds since boot). The comparison is always false — it would take ~54 years of uptime for BOOTTIME to exceed the REALTIME-derived deadline. This means any client can hold the server in grace indefinitely by sending CLAIM_PREVIOUS OPEN requests, blocking all non-reclaim operations for all other clients. Add boot_time_bt (CLOCK_BOOTTIME) alongside the existing boot_time and use it for the deadline computation. boot_time (CLOCK_REALTIME) is preserved for its cl_boot clientid-nonce role.
CVE-2026-89682 1 Linux 1 Linux Kernel 2026-10-30 8.1 High
In the Linux kernel, the following vulnerability has been resolved: nfsd: fix fcache_disposal UAF by inlining dispose state into nfsd_net nfsd_file_dispose_list_delayed() defers fput() to nfsd service threads via a per-net freeme queue, preventing the shrinker and GC worker from bearing the cost of closing files (see ffb402596147). However, the queue lives in a separately-allocated struct nfsd_fcache_disposal that is freed by nfsd_free_fcache_disposal_net() during per-net teardown. The global shrinker, laundrette, and fsnotify callbacks can still be inside nfsd_file_dispose_list_delayed() dereferencing that pointer, causing a use-after-free. Inline the spinlock and freeme list directly into struct nfsd_net (as fcache_dispose_lock and fcache_dispose_list), eliminating the separately allocated struct nfsd_fcache_disposal entirely. These fields now have the same lifetime as the net namespace itself, so there is no dangling pointer to chase. nfsd_file_cache_start_net() now just initializes the inline fields and cannot fail due to allocation. nfsd_file_cache_shutdown_net() drains the inline list directly instead of freeing a separate struct. The alloc/free helpers are removed.
CVE-2026-89680 1 Linux 1 Linux Kernel 2026-10-30 7.5 High
In the Linux kernel, the following vulnerability has been resolved: nfsd: fix nfsd_file leak on inter-server COPY setup failure When nfsd4_setup_inter_ssc() fails, nfsd4_copy() returns nfserr_offload_denied directly, bypassing the out: label where release_copy_files() would drop the nf_dst reference taken by nfs4_preprocess_stateid_op(). Each failed inter-server COPY leaks one nfsd_file, pinning file/inode/dentry/vfsmount. Fix by setting status and jumping to out: instead of returning directly.
CVE-2026-89676 1 Linux 1 Linux Kernel 2026-10-30 9.8 Critical
In the Linux kernel, the following vulnerability has been resolved: nfsd: fix stale s2s_cp_stateids IDR entry for async COPY For an async COPY, nfsd4_copy() called nfs4_init_copy_state() before dup_copy_fields(), so the s2s_cp_stateids IDR was pointed at &u->copy->cp_stateid -- memory in the per-rqstp COMPOUND buffer that is reused by the next request. dup_copy_fields() copies only the value into async_copy, so the IDR slot dangled at the transient buffer for the whole background copy. Any IDR walker then dereferences reused request memory: the laundromat reads cs_type from it and, if the bytes look like an expired NFS4_COPYNOTIFY_STID, follows into refcount_dec()/idr_remove()/kfree() on garbage; manage_cpntf_state() has the same exposure via idr_find(). Duplicate the fields first, then register the stateid on the stable async_copy. result->cb_stateid is unchanged.
CVE-2026-89672 1 Linux 1 Linux Kernel 2026-10-30 9.1 Critical
In the Linux kernel, the following vulnerability has been resolved: nfsd: gate nfs2 setacl by argp->mask The NFSACL v2 SETACL path shares the decoder convention used by its v3 sibling: nfsaclsvc_decode_setaclargs() fills in argp->acl_access only when NFS_ACL is set in the request mask and argp->acl_default only when NFS_DFACL is set, leaving the other pointer NULL because the argument buffer is zeroed up to pc_argzero before decode. nfsacld_proc_setacl() then hands both pointers to set_posix_acl() unconditionally. set_posix_acl(idmap, dentry, type, NULL) is the VFS "remove this ACL type" operation, so an omitted arm is indistinguishable from an explicit request to delete that ACL. A SETACL carrying only NFS_ACL silently strips the directory's default ACL; mask=0 strips both. This is the same defect just fixed in nfsd3_proc_setacl(); apply the same remedy. Gate each set_posix_acl() call on its mask bit and initialize error to 0 so that a request with neither bit set leaves the on-disk ACLs untouched and returns success. The out_drop_lock path and the unconditional posix_acl_release() in nfsaclsvc_release_setacl() already tolerate the skipped arms.
CVE-2026-89671 1 Linux 1 Linux Kernel 2026-10-30 9.1 Critical
In the Linux kernel, the following vulnerability has been resolved: nfsd: gate nfs3 setacl by argp->mask nfsd3_proc_setacl() calls set_posix_acl() unconditionally for both ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT, passing argp->acl_access and argp->acl_default verbatim. The NFSv3 ACL decoder only populates those pointers when the corresponding mask bit is set: nfs3svc_decode_setaclargs() if (args->mask & NFS_ACL) decode into acl_access if (args->mask & NFS_DFACL) decode into acl_default /* otherwise the pointer stays NULL (pc_argzero) */ nfsd3_proc_setacl() set_posix_acl(.., ACL_TYPE_ACCESS, argp->acl_access) set_posix_acl(.., ACL_TYPE_DEFAULT, argp->acl_default) set_posix_acl(idmap, dentry, type, NULL) is the VFS "remove this ACL type" operation. A NULL pointer that means "the client did not send this arm" is therefore indistinguishable from "the client asked to remove this ACL". A SETACL with mask=NFS_ACL silently drops the directory's default ACL; mask=0 drops both. The sibling nfsd3_proc_getacl() already consults argp->mask before touching each arm; mirror that in setacl. Fix by wrapping each set_posix_acl() call in the matching mask bit check and initializing error to 0 before inode_lock so that a request with neither bit set leaves the on-disk ACLs untouched and returns nfs_ok. The out_drop_lock path and the unconditional posix_acl_release() at out: are preserved; both NULL-tolerate the skipped arms.
CVE-2026-89659 1 Linux 1 Linux Kernel 2026-10-30 9.8 Critical
In the Linux kernel, the following vulnerability has been resolved: NFSD: Prevent client use-after-free during delegation revoke A delegation stateid holds only a bare pointer to its owning nfs4_client and does not keep it alive. The client survives its stateids only because __destroy_client() drains cl_delegations and cl_revoked before free_client() runs. nfs4_laundromat() breaks that invariant: it unhashes an expired delegation from cl_delegations, drops deleg_lock, then revoke_delegation() relinks it onto cl_revoked under cl_lock. In that window the delegation is on neither list, so client_has_state() can report no remaining state. Every teardown path first requires cl_rpc_users to be zero, but the laundromat holds no such reference. A client whose recalled delegation has just timed out can therefore reach free_client() while revoke_delegation() is still about to dereference cl_lock, a use-after-free. Pin the client with cl_rpc_users across the revoke so teardown blocks until it completes, then reap the delegation from cl_revoked. A client already expiring reaps its own, so skip it and leave the delegation on del_recall_lru.
CVE-2026-89654 1 Linux 1 Linux Kernel 2026-10-30 9.8 Critical
In the Linux kernel, the following vulnerability has been resolved: ceph: fix UAF in check_new_map() on session freed during unlock check_new_map() iterates mdsc->sessions[] and for each active session drops mdsc->mutex to perform per-session operations. The forced-close path (rank removed from map) correctly takes a reference on s via ceph_get_mds_session() before releasing mdsc->mutex, but three other paths do not: Path A (address changed): mutex_unlock → mutex_lock(&s->s_mutex) Path B (reconnect): mutex_unlock → send_mds_reconnect(mdsc, s) Path C (active transition): mutex_unlock → mutex_lock(&s->s_mutex) Without the extra reference, another thread can acquire mdsc->mutex during the unlock window, call __unregister_session() which drops the last reference on s, and free it. The original thread then accesses freed memory via s->s_mutex. Fix by adding ceph_get_mds_session(s) before each mutex_unlock and ceph_put_mds_session(s) after the corresponding mutex_lock, matching the pattern already used in the forced-close path. Race timeline (Path A): Thread A (check_new_map) Thread B (another map update holds mdsc->mutex or session teardown) -------------------------- -------------------------- s = mdsc->sessions[i] (refcount == 1, held only by sessions[] array) mutex_unlock(&mdsc->mutex) ---> acquires mdsc->mutex __unregister_session(mdsc, s) sessions[i] = NULL ceph_put_mds_session(s) refcount: 1 -> 0 kfree(s) <--- freed! mutex_lock(&s->s_mutex) UAF on freed s->s_mutex
CVE-2026-89652 1 Linux 1 Linux Kernel 2026-10-30 9.8 Critical
In the Linux kernel, the following vulnerability has been resolved: ceph: bound copied dentry name length in NFS export get_name ceph_get_name() copies the MDS-supplied name into the caller's NAME_MAX-sized buffer with memcpy(name, rinfo->dname, rinfo->dname_len) and then writes name[rinfo->dname_len] = 0, without checking dname_len against NAME_MAX. A malicious or buggy MDS that returns a LOOKUPNAME reply with dname_len > NAME_MAX overflows the buffer. __get_snap_name() copies rde->name / rde->name_len the same unchecked way. Impact: a malicious or compromised Ceph MDS overflows the NAME_MAX name buffer in a client's NFS-export get_name path, a slab out-of-bounds write reported by KASAN. Reachable when a CephFS mount is re-exported over NFS. Add ceph_export_copy_name(), which rejects lengths above NAME_MAX with -ENAMETOOLONG before the copy, and use it in both ceph_get_name() and __get_snap_name().
CVE-2026-89650 1 Linux 1 Linux Kernel 2026-10-30 9.1 Critical
In the Linux kernel, the following vulnerability has been resolved: ceph: bound num_export_targets array for mds info v2/v3 ceph_mdsmap_decode() in fs/ceph/mdsmap.c reads num_export_targets from each per-mds info record and advances the decode cursor by num_export_targets * sizeof(u32) without first checking that many bytes remain. The only upper-bound check that catches a runaway cursor (*p > info_end) is gated on info_v >= 4, because info_end is left NULL for info_v 2 and 3. When the monitor sends an MDS map whose per-mds info version is 2 or 3 with an oversized num_export_targets, the cursor moves past the message front buffer and the later export-targets loop calls the unchecked ceph_decode_32() on out-of-bounds memory. A kernel client processes CEPH_MSG_MDS_MAP from its monitor session (net/ceph/mon_client.c dispatches it; fs/ceph/super.c routes it to ceph_mdsc_handle_mdsmap(), which sets end to the front buffer bound and calls ceph_mdsmap_decode()). A malicious or compromised monitor, or an on-path attacker on an unsigned/unencrypted messenger session, can therefore drive an out-of-bounds read in the client kernel; on x86_64 with KASAN it is reported as a slab-out-of-bounds read in ceph_mdsmap_decode(). The decoded values land in the internal info->export_targets[] array, so the consequence is a kernel out-of-bounds read, not an information leak to the attacker. Impact: a malicious or compromised Ceph monitor sending an MDS map with a per-mds info version of 2 or 3 and an oversized num_export_targets field triggers an out-of-bounds read in the CephFS client kernel. Add a ceph_decode_need() for the export-targets array before advancing the cursor, so the bound is enforced for every info_v >= 2, not only info_v >= 4. This mirrors the count-then-need idiom already used for m_data_pg_pools later in the same function. Compute the export-targets byte count with size_mul() and reuse that checked length when advancing the cursor, so the attacker-controlled num_export_targets multiplication fails closed on overflow rather than relying on the later kcalloc() guard.