{"id":21597,"date":"2026-09-12T04:31:24","date_gmt":"2026-09-11T20:31:24","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-89675"},"modified":"2026-09-12T04:31:24","modified_gmt":"2026-09-11T20:31:24","slug":"cve-2026-89675","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-89675","title":{"rendered":"CVE-2026-89675 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nnfsd: fix UAF in asyn"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>nfsd: fix UAF in async copy cancel and shutdown<\/p>\n<p>An async copy could be freed or used after free while a teardown caller<br \/>\n(OFFLOAD_CANCEL, nfsd4_shutdown_copy, nfsd4_cancel_copy_by_sb) raced the<br \/>\ncopy kthread:<\/p>\n<p>  &#8211; find_async_copy() bumped copy-&gt;refcount but left the copy on<br \/>\n    clp-&gt;async_copies, so the reaper&#8217;s cleanup_async_copy() could run<br \/>\n    release_copy_files() concurrently with a cancel\/shutdown caller. Both<br \/>\n    put and NULL nf_src\/nf_dst without a common lock, double-putting the<br \/>\n    nfsd_file and freeing it early.<\/p>\n<p>  &#8211; nfsd4_do_async_copy() set NFSD4_COPY_F_STOPPED before its final uses<br \/>\n    of the copy (nfsd_update_cmtime_attr() on copy-&gt;nf_dst,<br \/>\n    nfsd4_send_cb_offload()). nfsd4_stop_copy() treats a set STOPPED bit<br \/>\n    as &#8220;kthread done, skip kthread_stop()&#8221;, so a teardown caller ran<br \/>\n    release_copy_files() &#8212; which puts and NULLs nf_dst &#8212; while the<br \/>\n    kthread still dereferenced it (NULL\/UAF).<\/p>\n<p>  &#8211; copy-&gt;copy_task was never pinned. The one-shot kthread self-reaps on<br \/>\n    return, so kthread_stop()&#8217;s get_task_struct() could touch a freed<br \/>\n    task_struct.<\/p>\n<p>  &#8211; co_cb is embedded in the copy, but nfsd4_send_cb_offload() held a<br \/>\n    reference only on the client, so a concurrent teardown could free<br \/>\n    the copy while the CB_OFFLOAD callback was in flight.<\/p>\n<p>Fix the teardown lifetime as a whole:<\/p>\n<p>  &#8211; find_async_copy() unlinks the copy (clear cp_clp, list_del_init)<br \/>\n    under async_lock; the cancel, shutdown, and sb-cancel paths drop the<br \/>\n    list-membership reference via nfs4_put_copy() after nfsd4_stop_copy().<br \/>\n    Drop the now-redundant list_del fixup from cleanup_async_copy().<\/p>\n<p>  &#8211; Because unlinking hides the copy from the reaper, its<br \/>\n    cleanup_async_copy() can no longer remove the copy&#8217;s s2s_cp_stateids<br \/>\n    entry; the cancel\/shutdown\/sb-cancel paths now call<br \/>\n    nfs4_free_copy_state() themselves (while cp_clp is still valid) so<br \/>\n    the entry does not dangle at freed memory for the laundromat and<br \/>\n    manage_cpntf_state() to dereference.<\/p>\n<p>  &#8211; Give the kthread its own reference, taken in nfsd4_copy() before<br \/>\n    wake_up_process() and dropped at the end of nfsd4_do_async_copy();<br \/>\n    call wake_up_process() before list_add().<\/p>\n<p>  &#8211; Pin the task_struct with get_task_struct() in nfsd4_copy(), released<br \/>\n    in nfs4_put_copy(), so kthread_stop() is safe whenever the kthread<br \/>\n    exits. Set NFSD4_COPY_F_STOPPED only in nfsd4_stop_copy(), which now<br \/>\n    always kthread_stop()s before release_copy_files(); completion is<br \/>\n    still reported via NFSD4_COPY_F_COMPLETED, so<br \/>\n    nfsd4_has_active_async_copies() is unaffected. Each teardown caller<br \/>\n    removes the copy from clp-&gt;async_copies first, so kthread_stop() runs<br \/>\n    exactly once.<\/p>\n<p>  &#8211; Take a copy reference in nfsd4_send_cb_offload(), dropped in<br \/>\n    nfsd4_cb_offload_release(). The kthread still holds its own reference<br \/>\n    there, so the refcount_inc() cannot race the final free.<\/p>\n<p>  &#8211; Read cp_clp with smp_load_acquire() to pair with the unordered<br \/>\n    set_bit()\/clear_bit() writers (Documentation\/atomic_bitops.rst).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>nfsd: fix UAF in async copy cancel and shutdown<\/p>\n<p>An async copy could be freed or used after free while a teardown caller<br \/>\n(OFFLOAD_C<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-21597","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/21597","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln"}],"about":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/types\/vuln"}],"wp:attachment":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=21597"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=21597"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=21597"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}