TRAVERTINE (CVE-2025-24118) macOS 内核中存在绝对疯狂的竞争条件

admin 2025年2月4日21:00:48评论11 views字数 10879阅读36分15秒阅读模式

TRAVERTINE (CVE-2025-24118) macOS 内核中存在绝对疯狂的竞争条件

这是我报告过的最疯狂的内核错误。

它涉及 macOS 内核 ( XNU )中几项尖端功能的组合- 安全内存回收 (SMR)、只读页面映射、每个线程凭据、memcpy 实现细节,当然还有将所有内容联系在一起的竞争条件。

此错误会导致线程的凭据指针损坏。具体来说,进程的只读结构的受kauth_cred_tSMR 保护的字段可能会被损坏,从而指向无效内存,或者可能指向不同的(甚至可能具有更高权限的)凭据。p_ucred

在发现和报告此错误的过程中,我根据最新的操作系统研究,了解到大量有关 XNU 的一些前沿功能的信息。我将分享我在触发此错误过程中了解到的信息(当然,还有错误本身的工作原理)。

您可以在此处找到概念证明。https://github.com/jprx/CVE-2025-24118

目录

  1. 安全内存回收:它是什么以及它如何工作。

  2. XNU 中的只读页面:XNU 如何通过只读映射保护其最重要的数据免受只读攻击。

  3. 每个线程的凭证:凭证在 XNU 中的工作方式,以及 XNU 如何允许并发线程管理不同的凭证。

  4. 竞争条件:这些主题如何结合在一起导致竞争条件,进而引发 CVE-2025-24118。

  5. 结论:当我们赢得比赛时会发生什么?

  6. 系好安全带,这将是一次相当漫长的旅程。

1. 安全内存回收

用一句话来说,安全内存回收 (SMR) 描述了一种无需使用锁即可回收内存的算法,同时还使释放后使用成为不可能。SMR 是关于如何在并发、无锁的环境中访问和回收内存。

SMR 最近才在 XNU 的几个地方被添加,其中之一就是进程凭证结构(此漏洞的主题)。将来的某个时候,我可能会对 SMR 内部进行全面描述,但在这里我只会介绍理解 CVE-2025-24118 所需的基础知识。

对于今天的错误,我们只关心 SMR 如何允许对给定的数据结构进行并发读取和写入(而不是 SMR 如何释放旧内存)。

并发编程中的锁定

通常在并发编程(例如内核)中,多个使用者可能访问的数据需要锁定才能序列化访问。从高层次来看,基本思想是避免一个线程正在读取某些数据而另一个线程正在更新该数据的情况。锁定通过提供一种获取对给定资源的独占访问权的机制来实现这一点。

当您想要访问共享资源时,您必须首先“获取”该资源的锁。您可以将锁视为一个特殊的内存地址,当持有时设置为 1,否则设置为 0。特殊的 CPU 魔法用于确保一次只有一个线程可以持有它(将其设置为 1)。持有锁会向其他线程发出信号,表明您已拥有该资源的所有权,他们不应对其进行读取或写入。获取锁后,您可以自由读取或写入对象。最后,当您完成后,您“释放”锁(将其设置回 0)以允许其他线程轮流访问该资源。

假设每个人都玩得很好并且尊重锁,那么对共享资源的所有读取和写入都将彼此看起来是原子的。也就是说,不应该出现一个读取器可以观察到对象部分写入/中间状态的情况。我们称这种情况为竞争条件,这是一件非常糟糕的事情(TM),可能会导致内存损坏错误(稍后会回来;D)。

对于读取者非常常见而写入者不常见的情况,每次读取时锁定整个结构既昂贵又不必要。在 Linux 中,您可以使用reader-writer锁,允许多个读取者同时访问资源。这样,多个读取者就可以同时读取对象。

无锁并发

TRAVERTINE (CVE-2025-24118) macOS 内核中存在绝对疯狂的竞争条件

操作系统通常使用替代机制来同步线程之间的数据,而不是使用锁。Linux 的经典示例是RCU(Read, Copy, Update),它允许读取器和最多一个写入器同时运行。RCU 可以被认为是一种“发布-订阅”算法,其中对象的各种版本会随时间发布,而旧版本会保留在内存中,直到确保没有读取器正在使用它们。并发更新会发布对象的较新版本,而读取器在想要引用该对象时会获取最新发布的版本。

XNU 中的安全内存回收

XNU 的安全内存回收方法基于 epoch,并受到FreeBSD 全局无界序列/UMA 分配器 SMR 机制的影响。基于 epoch 的 SMR 策略的基本思想是系统维护一个全局计数器,称为epoch,该计数器随时间递增。线程跟踪它们观察到的给定对象的 epoch,当所有线程都已充分进展时,可以释放来自较旧 epoch 的对象副本(因为没有线程可能再引用它们)。您可以将 epoch 视为对象的一种“版本号”。

让我们仔细看看 XNU 中的 SMR。SMR 的文档在此处。

对于 CVE-2025-24118 的情况,我们其实并不关心内存是如何回收的。这个漏洞只涉及 SMR 下并发读取器和写入器之间的交互。具体来说,我们需要了解写入器发布新值的机制。

基本思想是,受 SMR 保护的字段使用一个指针,该指针始终由最多一位写入者自动更新。读取者可以在任何时候异步读取此指针并检索对象的正确状态。虽然此状态可能不是已发布对象的最新值(当读取者和写入者同时访问指针时),但指针将始终指向对象的某个正确已发布版本。

与 RCU 非常相似,XNU 的 SMR 实现利用了读取端临界区。也就是说,读取器必须smr_enter()在读取任何受 SMR 保护的字段之前调用,并smr_leave()在读取完成后调用。这会将读取器标记为从特定时期读取。只要您处于 SMR 临界区中,就可以安全地取消引用受 SMR 保护的指针而无需锁定。

在写入方,使用锁来序列化写入方,确保一次只能有一个写入方。写入方使用原子更新来发布数据结构的新版本。这样,读取方将读取指向结构旧值的指针,或新值。因此,写入方使用原子 CPU 指令来更新内存非常重要,否则读取方可能会读取 SMR 指针的中间值(这将是一个严重的问题)。提示:这是预兆。

总而言之,有三种方法可以访问受 SMR 保护的内存(此处描述),其中两种是我们关心的:

  1. “已进入”(读者) -我们在smr_enter和之间smr_leave,可以自由阅读,无需锁定。

  2. “序列化”(写入器) ——我们持有写入器序列化锁并可以自由写入,只要我们以原子方式执行(如果有并发读取器)。

  3. “非序列化”(回收器) ——保证没有读者可以看到内存,所以我们可以释放它。(这与错误无关)。

写入器(处于该Serialized状态)使用锁来序列化其原子写入,以确保一次只有一个写入器更新 SMR 指针。理论上,这意味着正确的指针将始终存在于内存中,从而允许读取器(处于该Entered状态)无需锁定即可读取。这仅在所有写入器都是原子的情况下才有效。如果任何写入器都是非原子的,则读取器可能会观察到 SMR 保护指针中的中间/部分写入值,这可能导致指针指向无效内存。

2. XNU 中的只读页面

在执行仅数据攻击时,攻击者的目标通常是将其用户 ID 更改为 root。这使得凭证结构成为攻击者非常诱人的对象,因为用户 ID 存储在其中。出于这个原因,XNU 将凭证与其他敏感进程信息一起放在只读页面中。事实上,XNU 提供了一个用于分配和管理只读对象的内核 API。让我们来看看用于操作这些只读对象的 API。

只读 API 记录在doc/allocators/read-only.md中。

只读对象可以用 来分配zalloc_ro,它是专为只读映射而设计的区域分配器的特殊版本。zalloc_ro_mut及其相关方法是修改只读区域中数据的唯一方法。它以要修改的对象和要写入的内容作为参数,有点像 memcpy 的特殊版本,但适用于只读对象。

zalloc_ro_mut内部使用pmap_ro_zone_memcpy,根据架构的不同,可能需要经过页面保护层 (PPL) 来解锁页面。在 X86_64 上,pmap_ro_zone_memcpy是映射的包装器memcpy,其中所有物理内存都以虚拟方式映射(称为“物理孔径”)。

我们看一下memcpy在X86_64上的实现:

ENTRY(memcpy)
  movq %rdi, %rax /* return destination */
  movq %rdx, %rcx
  cld /* copy forwards */
  rep movsb
  ret

在 X86_64 上,rep movsb不是原子的- 它逐字节复制。

由于 X86_64 是严格有序的,其他线程会观察到逐字节写入的顺序,但无法保证这些写入的可见性字节对齐。如果使用rep movsb(例如,当更新指针的目标时) 写入 8 个字节,则并发读取器可能会看到写入 0 到 8 个字节之间的任何值,具体取决于并发读取发生的确切时间。

如果并发读取器观察到部分更新的指针,它将尝试取消引用由两个有效值(旧值和写入器线程写入的新值)的部分连接而成的无效地址。此无效地址可能是两个有效地址附近的其他对象(可能位于同一分配器区域中),并且可能准确指向从未被任何写入器引用到此字段的有效第三个对象。

回顾更新只读对象时的调用树,我们看到以下函数调用顺序:

zalloc_ro_mut -> pmap_ro_zone_memcpy -> memcpy -> rep movsb

显然,正如zalloc_ro_mut最终使用的那样rep movsb,它不是原子的,不应该在需要原子写入的地方使用(还记得 SMR 对写入器的要求吗?)。XNU 作者似乎已经zalloc_ro_mut通过提供私有zalloc_ro_mut_atomicAPI 解决了的非原子性问题,该 API 接受一个参数来表示应该执行哪种原子操作。

因此,如果我们能找到一个应该zalloc_ro_mut被使用的地方zalloc_ro_mut_atomic(或其变体之一),那么很有可能存在竞争条件错误。(提示:这是预兆)。

XNU 中只读对象的使用

我观察到这些只读对象的一般模式是,它们通常与互补的读写结构“配对”。例如,struct proc表示进程的 具有匹配的只读struct proc_ro。proc.p_proc_ro指向给定 proc 的 proc_ro,并proc_ro.pr_proc指向其匹配的 proc。

结构中真正重要的部分存储在只读对象中,而相对不重要的部分存储在读写版本中。

该图显示了proc's 和ucred's 之间的关系。

TRAVERTINE (CVE-2025-24118) macOS 内核中存在绝对疯狂的竞争条件

每个进程都有一个struct proc和struct task(彼此相邻分配)。BSD 世界使用struct proc,而 Mach 世界使用struct task。这两个结构都指向一个匹配的struct proc_ro,而后者又指向它们两个。

是proc_ro从区域分配的只读对象proc_ro。它用于存储此进程的敏感数据 - 例如,指向 的受 SMR 保护的指针struct ucred。还具有指向的ucred匹配结构。struct ucred_rw

这里重要的一点是每个proc都有一个proc_ro,它是一个只读对象,包含一个指向其凭证的 SMR 指针。

这意味着如果需要更改进程的凭据,则需要使用zalloc_roAPI 来执行。我真希望没有地方可以zalloc_ro_mut写入p_ucred而不是原子 API,因为p_ucred是 SMR 指针,因此必须原子地写入(提示:预兆)。

3. 每个线程的凭证

XNU 中的凭据 ( struct ucred) 是一种数据结构,用于跟踪许多与安全相关的字段,例如线程的用户 ID。以下是 ucred 的定义:

TRAVERTINE (CVE-2025-24118) macOS 内核中存在绝对疯狂的竞争条件

凭证的一部分posix_cred用于跟踪当前线程的权限。系统中的大多数线程将具有相同的权限 - 无论当前用户拥有什么权限。为每个线程存储这些相同凭证的副本将花费相当多的内存。相反,XNU 使用 SMR 哈希表来散列这些凭证结构,以允许线程共享相同的凭证对象。凭证对象使用引用计数(cr_ref)来跟踪何时可以释放它们。

哈希值是使用凭据的后半部分(例如cr_posix及以后)计算的。这允许具有相同权限的线程共享相同的凭据对象,从而节省内存。这在后面很重要。

管理凭证

在 XNU 中,属于同一进程的线程可以具有不同的凭据。这是使用 进行管理的current_cached_proc_cred_update,它在每次系统调用期间都会被调用。在每次系统调用进入期间,内核都会检索当前进程凭据指针并将其与每个线程的凭据进行比较,以查看是否需要进行任何更改。

void current_cached_proc_cred_update(void) {
  thread_ro_t tro = current_thread_ro();
  proc_t      proc = tro->tro_proc;

  if (__improbable(tro->tro_task != kernel_task &&
    tro->tro_realcred != proc_ucred_unsafe(proc))) {
    kauth_cred_thread_update_slow(tro, proc);
  }
}

此方法将p_ucred来自的指针proc_ro与tro_realcred来自当前 的指针进行比较thread_ro。如果凭证等同(例如,它们具有相同的cr_posix值),则这些指针将指向哈希表中的相同凭证。

如果指针不匹配,kauth_cred_thread_update_slow则调用 来更新内容,最终进入 SMR 区域并取消引用p_ucred。请注意,在 中current_cached_proc_cred_update,使用proc_ucred_unsafe(p_ucred不在 SMR 区域中读取)是可以的,因为我们只读取凭证指针的值,并且尚未取消引用它。

这里最重要的是,每个系统调用都可能导致内核进入 SMR 区域并取消引用受p_ucredSMR 保护的指向进程凭据结构的指针。只要线程的凭据发生轻微变化,就会发生这种情况。

4. 竞争条件

现在我们已经掌握了所有知识点,让我们将它们组合在一起。

回顾一下:

  • proc_ro是一个只读对象,用于管理进程的敏感数据(例如其凭据),并且只能通过zalloc_ro_mut*函数系列进行修改。

  • proc_ro.p_ucred是指向进程凭证结构的受 SMR 保护的指针。

  • 由于是 SMR 指针,因此写入者必须通过锁(特别是这个p_ucred)相互同步,并且在写入时必须使用原子操作来改变。p_ucred

  • zalloc_ro_mut,用于修改只读对象的函数,是非原子的,因此不适合修改p_ucred。

您也许能够看到事情的进展。

错误在于代码中有一个地方proc_ro.p_ucred使用 进行非原子更新zalloc_ro_mut。我找到了一种方法来将此更新调用与 的 SMR 取消引用进行竞争p_ucred,这将在不锁定的情况下加载。如果你这样做足够多次,最终你将观察到 的部分写入值p_ucred指向不同的凭证!

Buggy 函数

该错误存在于 中kauth_cred_proc_update,这是负责更新 指针的函数proc_ro。p_ucred我用红色突出显示了有缺陷的行。

TRAVERTINE (CVE-2025-24118) macOS 内核中存在绝对疯狂的竞争条件

要触发该漏洞,我们需要能够频繁更新凭证。我尝试了几种方法,发现最好的方法是反复setgid调整组 ID。每次组 ID 发生变化时,kauth_cred_proc_update都需要调用调整p_ucred以指向哈希表中正确的凭证对象。

让我们仔细看看p_ucred是如何读取和写入的。

阅读 p_ucred

读者可以p_ucred用来从给定的中proc_ucred_smr获取字段。p_proc_ro->p_ucredproc_t

kauth_cred_t proc_ucred_unsafe(proc_t p) {
  kauth_cred_t cred = smr_serialized_load(&proc_get_ro(p)->p_ucred);
  return kauth_cred_require(cred);
}

kauth_cred_t proc_ucred_smr(proc_t p) {
  assert(smr_entered(&smr_proc_task));
  return proc_ucred_unsafe(p);
}

确保我们处于 中后smr_region,smr_serialized_load只需从内存中返回 的值p_ucred而不锁定。我们得到的是当前内存中的任何内容,即使它是来自非原子写入线程的正在进行的写入。

写入 p_ucred

XNU SMR API 要求通过外部机制对写入器进行序列化 - 在本例中,即p_ucred_mlock通过proc_ucred_lockedAPI。此锁将写入器序列化,因此理论上内存中始终存在正确的指针,从而允许读取器无需锁定即可读取。但是,正如我们所见,即使kauth_cred_proc_update正确获取了写入器锁,由于使用了非原子 API,它也违反了 SMR 要求zalloc_ro_mut。

触发漏洞

每次kauth_cred_proc_update更改时p_ucred,都会触发该错误。但是,大多数情况下,这不会造成问题,因为正常的工作流程很少更新其凭据,甚至根本不更新。要触发该错误,我们需要p_ucred在写入时进行读取。

我们不需要触发任何分配或释放,我们只需要通过p_ucred来改变zalloc_ro_mut。具体来说,当kauth_cred_derive_t闭包返回时会发生这种情况true。内核中的许多路径都可能导致这种情况(例如setuid、setgid、setgroups等)。

为了解决这个问题,我们需要两个线程 - 一个用于触发频繁p_ucred更改,另一个用于读取p_ucred。

作家主题

为了让没有特权的本地攻击者能够更改凭据,我使用了带位的二进制文件setgid。这样我们就可以在调用方的保存组 ID 和实际组 ID 之间来回切换有效组 ID,而无需 root 权限。每次有效组 ID 更改时,p_ucred也需要更新。具体来说,哈希表中将分配两个凭据(每个可能的 GID 一个),并kauth_cred_proc_update在它们之间切换。

该线程如下所示:

while(true) { 
    setgid(rg); // 实际 gid
    setgid(eg); // 有效 gid
}
每次我们setgid以这种方式调用时,setgid都会用来kauth_cred_proc_update更新我们进程中的凭据指针p_ucred。非特权用户可以在不具有 root 权限的情况下在保存的 GID 和真实 GID 之间切换,因此这是一种触发许多凭据更改的实用方法。
每次p_ucred随着 而改变zalloc_ro_mut,并发读者就有机会观察到中间值。
读者主题
unix_syscall64每次系统调用时都会引用当前 proc cred,以支持跨线程维护不同的凭据。如我们所见,current_cached_proc_cred_update将尝试验证p_ucred凭据更改并取消引用以读取该cr_rw字段。
任何与组 ID 更改同时运行的系统调用都将触发此读取。我的读取器线程只是getgid()循环调用。
volatile gid_t tmp;
while(true) tmp = getgid();

在某个时候,其中一个读取将观察到p_ucred写入一半的值,如果您幸运的话,这将导致崩溃 - 或者如果您不幸的话,可能会导致凭证的无声破坏!

运行概念验证

该二进制文件需要以setgid与当前用户的实际 GID 不同的组运行,以便我们切换到不同的组。macOS 上的默认组是staff,因此我将everyone其用作第二个组。这只是为我们提供了一种无需 root 即可切换凭据的便捷方法kauth_cred_proc_update。其他触发此操作的方法也是可能的。

chgrp everyone poc
chmod g+s poc
./poc

运行概念验证一段时间后,最终您的进程的凭据指针将被损坏。这可能会导致内核崩溃,或者可能会导致您的凭据被悄悄更改为指向区域中的其他凭据对象kauth_cred。

您可以在此处:https://github.com/jprx/CVE-2025-24118 kauth_cred_proc_update找到使用两个线程进行竞争的概念证明。current_cached_proc_cred_update

5. 结论

首先,我应该指出,这场竞争很难取胜。由于我们要切换的两个凭证位于同一区域,因此其地址中的许多字节将相同。这意味着即使触发了这场竞争,也可能不会引起明显的问题。

在调查此错误时,我通常会设置一台运行 OCLP 的 2013 Mac Pro(我在 eBay 上花了几百美元买了一台),打开我的概念验证代码,并让它在连接调试器的情况下运行一整夜,希望当我第二天醒来时它会在恐慌状态下停止。

其次,我只观察到这个问题影响英特尔系统。我目前认为这是由于ARM64 中使用的 memcpy版本经过优化,可以一次复制更大的字节块,这在实践中提供了一定程度的原子性。虽然代码在 ARM 系统上仍然不完全正确(因为zalloc_ro_mut不能保证原子性),但我无法在那里造成任何损坏。也许有人读到这篇文章可以让它在 ARM 系统上运行?如果你这样做了,请在 X @0xjprxkauth_cred_t上告诉我。

建议修复

当我向 Apple 报告此错误时,我提供了以下建议的修复方法。

@@ -3947,9 +3947,9 @@ kauth_cred_proc_update( 
            kauth_cred_ref(new_cred);
            kauth_cred_hold(new_cred); - zalloc_ro_mut(ZONE_ID_PROC_RO, proc_get_ro (p), + zalloc_ro_mut_atomic(ZONE_ID_PROC_RO, proc_get_ro(p),
                offsetof(struct proc_ro, p_ucred),- &new_cred, sizeof(struct ucred *)); + ZRO_ATOMIC_XCHG_LONG, (uint64_t)new_cred);
            kauth_cred_drop(cur_cred);
            ucred_rw_unref_live(cur_cred->cr_rw);

运行应用了此补丁的内核完全消除了我的设置中的错误。我使用zalloc_ro_mut_atomicwithZRO_ATOMIC_XCHG_LONG自动将旧凭据指针替换为新凭据指针。

这里使用的更好的函数可能是类似的zalloc_ro_update_field_atomic,但我发现通过 SMR 指针宏声明的隐式结构与 update_field_atomic 使用的宏之间存在非平凡的不兼容性,所以我zalloc_ro_mut_atomic直接调用。

赢得比赛

当你赢得比赛时,如果无效指针没有正确对齐区域的元素,你就会陷入这样的恐慌:

panic: zone_require_ro failed: element improperly aligned (addr: 0xffffff86c79e8350) @zalloc.c:7376
Panicked task 0xffffff952d31db88: 3 threads: pid 1110: poc
Backtrace (CPU 8), panicked thread: 0xffffff90610770c8, Frame : Return Address
0xfffffff4078abac0 : 0xffffff8007becc41 mach_kernel : _handle_debugger_trap + 0x4c1
0xfffffff4078abb10 : 0xffffff8007d598ec mach_kernel : _kdp_i386_trap + 0x11c
0xfffffff4078abb50 : 0xffffff8007d48f6b mach_kernel : _kernel_trap + 0x48b
0xfffffff4078abc10 : 0xffffff8007b82971 mach_kernel : _return_from_trap + 0xc1
0xfffffff4078abc30 : 0xffffff8007becf37 mach_kernel : _DebuggerTrapWithState + 0x67
0xfffffff4078abd30 : 0xffffff8007bec5d2 mach_kernel : _panic_trap_to_debugger + 0x1e2
0xfffffff4078abda0 : 0xffffff80083d4938 mach_kernel : _panic + 0x81
0xfffffff4078abe90 : 0xffffff80083dab9f mach_kernel : ___smr_stail_invalid + 0x2ce9
0xfffffff4078abed0 : 0xffffff80080c6757 mach_kernel : _kauth_cred_proc_ref + 0x167
0xfffffff4078abf00 : 0xffffff80080c64c8 mach_kernel : _kauth_cred_ref + 0xc8
0xfffffff4078abf40 : 0xffffff800823b4eb mach_kernel : _unix_syscall64 + 0x39b
0xfffffff4078abfa0 : 0xffffff8007b82db6 mach_kernel : _hndl_unix_scall64 + 0x16

Process name corresponding to current thread: poc

Mac OS version:
24A335

Kernel version:
Darwin Kernel Version 24.0.0: Mon Aug 12 20:54:30 PDT 2024; root:xnu-11215.1.10~2/RELEASE_X86_64
Kernel UUID: 5DD51D41-0315-3DDD-BD5D-50E782643BDB
roots installed: 0
KernelCache slide: 0x0000000007800000
KernelCache base: 0xffffff8007a00000
Kernel slide: 0x00000000078e4000
Kernel text base: 0xffffff8007ae4000
__HIB text base: 0xffffff8007900000

也有可能凭证刚好正确对齐,这样将它们组合起来就会给您一个指向正确对齐的凭证的指针,从而有效地改变您流程的凭证。

如果没有其他机制来确定在内核中分配凭证对象的位置,那么就无法控制无效指针的形成方式,因此在实践中可能很难实现这一点。也许您可以尝试通过以特定模式喷洒凭证来将它们排列起来?我将把它留给读者作为“练习”。

即便如此,我认为这个漏洞非常有趣,是 XNU 一些非常酷的功能的绝佳学习示例。您觉得如何?欢迎随时通过 X @0xjprx与我们联系。

此错误已在 2025 年 1 月 27 日发布的 macOS 15.3 中修复。

原文始发于微信公众号(Ots安全):TRAVERTINE (CVE-2025-24118) macOS 内核中存在绝对疯狂的竞争条件

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月4日21:00:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   TRAVERTINE (CVE-2025-24118) macOS 内核中存在绝对疯狂的竞争条件https://cn-sec.com/archives/3698390.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息