为什么CLR的jmp指令无法验证?

发布于 2024-09-01 17:46:38 字数 193 浏览 7 评论 0原文

我已经知道 jmp 指令有一段时间了,但我从来没有觉得它有一点不安全。我最近有理由检查 CIL 规范,非常惊讶发现 jmp 被认为是不可验证的

I've known about the jmp instruction for awhile, but it never struck me as being even remotely unsafe. I recently had cause to check the CIL specs and was very surprised to discover jmp is considered unverifiable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮云落日 2024-09-08 17:46:38

因为,与 callcallvirtcalli 不同,调用者的堆栈帧将保留在堆栈上,以便将来的代码访问安全性看到由被调用者触发(可能间接)的堆栈遍历,jmp 指令会在转换到被调用者之前拆除调用者的堆栈帧,因此对于被调用者可能触发的任何 CAS 堆栈遍历都是不可见的。

编辑:我认为 naasking 的说法是正确的,上面的答案是错误的。我现在认为(可验证的)tail.call序列和(不可验证的)jmp序列之间的区别可能是尾部调用需要推送参数到对评估堆栈的调用,可以在其中以正常方式验证它们,而 jmp 要求评估堆栈为空并导致 Jump-ee 继承 Jump-er 的参数。可能没有理由使验证程序复杂化以检查 jmp 指令,但在类似于 tail.call 序列(其中之一)的条件下可能会这样做也就是说,调用者和被调用者必须位于同一个程序集中,这排除了我上面的 CAS 猜测,至少在显式 .Deny( ) 调用之前)。

如果是这样,这将是规范的相关部分:(第 III 部分,第 3.37 节)

当前参数已传输
到目标方法。

计算堆栈必须为空
当这条指令被执行时。这
调用约定、数量和类型
目标地址的参数
必须与当前方法匹配。

Because, unlike a call, callvirt, or calli, where the caller's stack frame would remain on the stack to be seen by future code access security stackwalks triggered (perhaps indirectly) by the callee, a jmp instruction tears down the caller's stack frame prior to transitioning into the callee and is thus invisible to any CAS stackwalks that the callee may trigger.

Edit: I think naasking is right about the answer above being wrong. I now think the difference between (verifiable) tail.call sequences and (unverifiable) jmp sequences may be that a tail call requires pushing the arguments to the call onto the evaluation stack where they can be verified in the normal way, whereas a jmp requires the evaluation stack to be empty and causes the jump-ee to inherit the arguments of the jump-er. There was probably no reason to complicate the verifier to check jmp instructions, but it might be possible to do so under conditions similar to those imposed on tail.call sequences (one of which is that the caller and callee must be in the same assembly, which rules out my CAS guess above, at least up to explicit .Deny( ) calls).

If so, this would be the relevant part of the spec: (Partition III, Section 3.37)

The current arguments are transferred
to the destination method.

The evaluation stack must be empty
when this instruction is executed. The
calling convention, number and type of
arguments at the destination address
must match that of the current method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文