为什么CLR的jmp指令无法验证?
我已经知道 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因为,与
call
、callvirt
或calli
不同,调用者的堆栈帧将保留在堆栈上,以便将来的代码访问安全性看到由被调用者触发(可能间接)的堆栈遍历,jmp
指令会在转换到被调用者之前拆除调用者的堆栈帧,因此对于被调用者可能触发的任何 CAS 堆栈遍历都是不可见的。编辑:我认为 naasking 的说法是正确的,上面的答案是错误的。我现在认为(可验证的)tail.call序列和(不可验证的)jmp序列之间的区别可能是尾部调用需要推送参数到对评估堆栈的调用,可以在其中以正常方式验证它们,而
jmp
要求评估堆栈为空并导致 Jump-ee 继承 Jump-er 的参数。可能没有理由使验证程序复杂化以检查jmp
指令,但在类似于tail.call
序列(其中之一)的条件下可能会这样做也就是说,调用者和被调用者必须位于同一个程序集中,这排除了我上面的 CAS 猜测,至少在显式.Deny( )
调用之前)。如果是这样,这将是规范的相关部分:(第 III 部分,第 3.37 节)
Because, unlike a
call
,callvirt
, orcalli
, 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, ajmp
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 checkjmp
instructions, but it might be possible to do so under conditions similar to those imposed ontail.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)