programing

경량 C 코드 샌드박스를 만드는 방법은?

easyjava 2023. 9. 26. 22:40
반응형

경량 C 코드 샌드박스를 만드는 방법은?

로컬 및 온라인 소스에서 함수를 수집할 수 있는 C 프리 프로세서/컴파일러를 만들고 싶습니다.즉:

#fetch MP3FileBuilder http://scripts.com/MP3Builder.gz
#fetch IpodDeviceReader http://apple.com/modules/MP3Builder.gz

void mymodule_main() {
  MP3FileBuilder(&some_data);
}

그게 쉬운 부분입니다.

어려운 점은 가져온 코드를 디스크나 시스템 리소스(메모리 할당 및 스택 포함)에 직접 또는 제한 없이 액세스할있도록 "샌드박스"할 수 있는 신뢰할 수 있는 방법이 필요하다는 것입니다.신뢰할 수 없는 C 코드(모듈)의 작은 토막을 별도의 프로세스, VM 또는 인터프리터에 배치하는 오버헤드 없이 안전하게 실행할 수 있는 방법을 원합니다(단, 별도의 스레드는 허용 가능합니다).

요구 사항들

  • CPU 시간을 포함하여 데이터 및 리소스에 대한 액세스에 할당량을 두어야 합니다.
  • 표준 라이브러리에 대한 직접적인 접근을 차단합니다.
  • 끝없는 재귀를 일으키는 악성코드를 막고 싶습니다.
  • 정적 및 동적 할당을 특정 제한으로 제한하고자 합니다.
  • 모듈이 제기할 수 있는 모든 예외(예: 0으로 나누기)를 잡고 싶습니다.
  • 모듈은 코어 인터페이스를 통해서만 다른 모듈과 상호 작용할 수 있습니다.
  • 모듈은 시스템(I/O 등)과만 상호작용할 수 있습니다.코어 인터페이스를 통해
  • 모듈은 비트 ops, math, array, enum, loop 및 branching을 허용해야 합니다.
  • 모듈이 ASM을 사용할 수 없음
  • 모듈용으로 예약된 메모리에 대한 포인터 및 배열 액세스를 제한합니다(사용자 지정 safe_malloc()).
  • ANSIC 또는 부분 집합을 지원해야 합니다(아래 참조).
  • 시스템은 경량이고 크로스 플랫폼(임베디드 시스템 포함)이어야 합니다.
  • 시스템이 GPL 또는 LGPL과 호환되어야 합니다.

저는 C의 부분집합에 만족하게 되어 기쁩니다.템플릿이나 수업 같은 것은 필요 없습니다.저는 빠른 수학, 비트 연산, 이진 데이터의 검색 및 처리와 같이 상위 언어가 잘 수행되지 않는 것에 주로 관심이 있습니다.

기존 C 코드를 수정 없이 재사용하여 모듈을 만들 수 있다는 의도는 아닙니다.모듈은 기본 논리 및 변환 작업(예를 들어 비디오 트랜스코드 또는 압축 작업)으로 모듈을 제한하도록 설계된 일련의 규칙 및 제한 사항을 준수해야 합니다.

이러한 컴파일러/프리 프로세서에 대한 이론적 입력은 module_main 함수가 있는 단일 ANSIC 파일(또는 safe subset)일 것이고, NO는 module_main 함수를 포함하거나 프리 프로세서 지시문을 포함하지 않으며, ASM이 없음, 루프, 분기, 함수 호출, 포인터 수학(모듈에 할당된 범위로 제한됨), 비트 쉬프팅, 비트필드, 캐스트, enum, 배열, int, float을 허용합니다.s, 현과 수학그 밖의 것은 선택 사항입니다.

구현 예시

이것을 더 잘 설명하기 위한 의사 코드 조각이 여기 있습니다.여기서 모듈은 메모리 할당 할당량을 초과하고 무한 재귀를 생성합니다.

buffer* transcodeToAVI_main( &in_buffer ) {
    int buffer[1000000000]; // allocation exceeding quota
    while(true) {} // infinite loop
    return buffer;
}

변형된 버전은 우리의 전처리기가 메모리 사용량과 재귀성을 확인하기 위해 워치포인트를 추가하고 전체를 예외 처리기로 포장한 것입니다.

buffer* transcodeToAVI_main( &in_buffer ) {
    try {
        core_funcStart(__FILE__,__FUNC__); // tell core we're executing this function
        buffer = core_newArray(1000000000, __FILE__, __FUNC__); // memory allocation from quota
        while(true) {
           core_checkLoop(__FILE__, __FUNC__, __LINE__) && break; // break loop on recursion limit
        } 
        core_moduleEnd(__FILE__,__FUNC__);
    } catch {
        core_exceptionHandler(__FILE__, __FUNC__);
    }
    return buffer;
}

이러한 점검을 수행하는 것이 모듈 성능에 영향을 미친다는 것을 알고 있지만, 여전히 해결하고자 하는 작업에서 상위 레벨이나 VM 언어보다 성능이 뛰어날 것으로 예상됩니다.저는 모듈이 위험한 일을 하는 것을 노골적으로 막으려는 것이 아니라, 단지 사용자 피드백을 통해 위험한 일이 통제된 방식으로 발생하도록 강요하려는 것입니다.즉, "모듈 X가 메모리 할당을 초과했습니다. 계속하시겠습니까, 중단하시겠습니까?"

갱신하다

지금까지 제가 가진 최선의 방법은 경계 검사와 일부 사용자 정의 함수 및 루프 코드가 있는 사용자 정의 컴파일러(해킹된 TCC와 같은)를 사용하여 재귀를 잡는 것입니다.그 밖에 확인해야 할 사항이나 해결책이 무엇인지에 대한 생각을 듣고 싶습니다.ASM을 제거하고 사용하기 전에 포인터를 확인하는 것이 아래의 이전 답변에서 나타난 많은 우려를 해결해 줄 것으로 생각합니다.SO 커뮤니티에서 피드백을 좀 더 끌어내기 위해 현상금을 추가했습니다.

내가 찾는 현상금을 위해:

  • 위에서 정의한 이론적 체계에 대한 잠재적인 악용의 세부 사항
  • 각 액세스에서 포인터를 확인하는 것보다 가능한 최적화
  • 개념의 실험적 오픈 소스 구현(Google Native Client 등)
  • 광범위한 OS 및 장치를 지원하는 솔루션(OS/하드웨어 기반 솔루션 없음)
  • 가장 많은 C 운영을 지원하는 솔루션, 또는 C++(가능한 경우)

GCC와 함께 작동할 수 있는 방법(즉, 전처리기 또는 소형 GCC 패치)에 대한 추가 크레딧.

제가 시도하는 것이 전혀 불가능하다는 것을 단정적으로 증명할 수 있는 사람도 배려하겠습니다.하지만 지금까지 어떤 반대도 그들이 왜 불가능하다고 생각하는지에 대한 기술적인 측면을 실제로 못박지 않았기 때문에 꽤 설득력이 있어야 할 것입니다.이 질문은 원래 C++를 안전하게 실행하기 위한 방법으로 제기되었습니다.저는 이제 C의 제한된 부분집합으로 요구사항을 축소하였습니다.

My understanding of C could be classed as "intermediate", my understanding of PC hardware is maybe a step below "advanced". Try to coach your answers for that level if you can. Since I'm no C expert I'll be going largely based on votes given to an answer as well as how closely the answer comes to my requirements. You can assist by providing sufficient evidence for your claims (respondents) and by voting (everyone else). I'll assign an answer once the bounty countdown reaches 6 hours.

Finally, I believe solving this problem would be a major step towards maintaining C's relevance in an increasingly networked and paranoid world. As other languages close the gap performance-wise and computing power grows it will be harder and harder to justify the added risk of C development (as it is now with ASM). I believe your answers will have a much greater relevance than scoring a few SO points so please contribute what you can, even if the bounty has expired.

Since the C standard is much too broad to be allowed, you would need to go the other way around: specify the minimum subset of C which you need, and try to implement that. Even ANSI C is already too complicated and allows unwanted behaviour.

The aspect of C which is most problematic are the pointers: the C language requires pointer arithmitic, and those are not checked. For example:

char a[100];
printf("%p %p\n", a[10], 10[a]);

will both print the same address. Since a[10] == 10[a] == *(10 + a) == *(a + 10).

All these pointer accesses cannot be checked at compile time. That's the same complexity as asking the compiler for 'all bugs in a program' which would require solving the halting problem.

Since you want this function to be able to run in the same process (potentially in a different thread) you share memory between your application and the 'safe' module since that's the whole point of having a thread: share data for faster access. However, this also means that both threads can read and write the same memory.

And since you cannot prove compile time where pointers end up, you have to do that at runtime. Which means that code like 'a[10]' has to be translated to something like 'get_byte(a + 10)' at which point I wouldn't call it C anymore.

구글 네이티브 클라이언트

그렇다면 그것이 사실이라면, 구글은 어떻게 그것을 할까요?여기의 요구사항(크로스 플랫폼(임베디드 시스템 포함)과는 대조적으로, Google은 페이지 보호 기능과 세그먼트 레지스터를 포함한 페이징 외에도 x86에 집중합니다.이를 통해 다른 스레드가 동일한 메모리를 공유하지 않는 샌드박스를 만들 수 있습니다. 샌드박스는 자신의 메모리 범위만 변경하도록 제한된 세그먼트화에 의해 생성됩니다.또한 다음과 같은 사항을 제공합니다.

  • 안전한 x86 조립 구조물의 목록이 조립되어 있습니다.
  • gcc는 안전한 구조물을 배출하기 위해 변경되었습니다.
  • 이 목록은 확인 가능한 방식으로 구성됩니다.
  • 모듈을 로드한 후 이 확인이 완료됩니다.

따라서 이는 플랫폼에 따라 다르며, '단순한' 솔루션은 아니지만 실제로 작동하는 솔루션입니다.그들의 연구 논문에서 더 많은 것을 읽어보세요.

결론

따라서 어떤 경로를 선택하든 검증 가능한 새로운 것으로 시작해야 하며, 그래야 기존 컴파일러를 적응시키거나 새로운 컴파일러를 생성함으로써 시작할 수 있습니다.그러나 ANSIC를 흉내 내기 위해서는 포인터 문제에 대해 생각해 보아야 합니다.구글은 ANSIC가 아닌 x86의 서브셋으로 샌드박스를 모델링하여 기존 컴파일러를 사용할 수 있게 하였고 x86과 연결된다는 단점이 있었습니다.

브라우저에서 (안전하게) x86 코드를 실행하는 시스템인 Native Client를 설계할 때 Google이 했던 구현에 대한 우려와 선택사항을 읽어보면 많은 것을 알 수 있을 것 같습니다.코드가 안전하지 않을 경우 소스 재작성 또는 소스 대 소스 컴파일을 수행해야 할 수도 있지만 NaCL 샌드박스가 너무 기능적인 작업을 수행하려고 할 경우 생성된 어셈블리 코드를 잡을 수 있습니다.

이 작업을 수행하려면 다음 두 가지 방법 중 하나를 조사해야 합니다.

  • CERN의 CINT를 사용하여 인터프리터에서 샌드박스된 코드를 실행하고 인터프리터가 허용하는 것을 제한하는 것에 대해 확인합니다.이것은 아마 아주 좋은 성과를 가져다 주지는 못할 것입니다.
  • LLVM을 사용하여 C++ 코드의 중간 표현을 생성한 다음 해당 바이트 코드를 샌드박스된 Java 스타일 VM에서 실행할 수 있는지 확인합니다.

하지만 저는 이것이 아마 끔찍한 프로젝트일 것이라는 다른 사람들의 의견에 동의합니다.웹 브라우저가 버그가 있거나 플러그인이 걸려 브라우저 전체를 불안정하게 하는 문제를 살펴봅니다.또는 Wireshark 프로젝트의 릴리스 노트를 살펴보십시오. 거의 모든 릴리스에는 프로토콜 탐지 중 하나의 문제에 대한 보안 수정 사항이 포함되어 있으며 이 문제는 전체 프로그램에 영향을 미칩니다.C/C++ 샌드박스가 가능하다면 지금쯤 이 프로젝트들이 하나씩 붙었을 것으로 예상합니다.

우연히 TCC(Tiny C Compiler)를 만났습니다.이것이 제가 필요로 하는 것일 수 있습니다.

*  SMALL! You can compile and execute C code everywhere, for example on rescue disks (about 100KB for x86 TCC executable, including C preprocessor, C compiler, assembler and linker).
* FAST! tcc generates x86 code. No byte code overhead. Compile, assemble and link several times faster than GCC.
* UNLIMITED! Any C dynamic library can be used directly. TCC is heading torward full ISOC99 compliance. TCC can of course compile itself.
* SAFE! tcc includes an optional memory and bound checker. Bound checked code can be mixed freely with standard code.
* Compile and execute C source directly. No linking or assembly necessary. Full C preprocessor and GNU-like assembler included.
* C script supported : just add '#!/usr/local/bin/tcc -run' at the first line of your C source, and execute it directly from the command line.
* With libtcc, you can use TCC as a backend for dynamic code generation.

그것에 대한 해킹을 실행 가능한 옵션으로 만드는 매우 작은 프로그램입니다. (해킹 GCC?, 이 일생 동안이 아닙니다!)나는 그것이 나만의 제한된 컴파일러를 만들기 위한 훌륭한 기반이 될 것이라고 생각합니다.안전하게 할 수 없는 언어 기능에 대한 지원을 제거하고 메모리 할당 및 루프 핸들링을 랩핑 또는 교체하겠습니다.

TCC는 이미 저의 요구사항 중 하나인 메모리 액세스에 대한 경계 검사를 할 수 있습니다.

내부적으로 코드 컴파일을 관리할 수 있기 때문에 libtcc 또한 좋은 기능입니다.

쉽지 않을 것으로 예상하지만 위험 부담을 덜면서도 C에 근접할 수 있다는 희망을 갖게 합니다.

그래도 다른 아이디어는 듣고 싶어요.

이것은 사소한 것은 아니지만, 그렇게 어렵지는 않습니다.

샌드박스에서 이진 코드를 실행할 수 있습니다.모든 운영 체제는 하루 종일 이 작업을 수행합니다.

표준 라이브러리(일반 Clib)를 사용해야 합니다.표준 라이브러리에서 사용자가 원하는 모든 제어를 적용합니다.

다음으로 실행 시간에 "실행 가능한 코드"를 만들지 못하도록 해야 합니다.즉, 스택은 실행 가능하지 않습니다. 실행 가능한 메모리를 할당할 수 없습니다.즉, 컴파일러(YOUR 컴파일러)가 생성한 코드만 실행 가능합니다.

컴파일러가 실행 파일에 암호학적으로 서명하면 런타임에서 변조된 이진 파일을 탐지할 수 있고 로드할 수 없습니다.이렇게 하면 사용자가 원하지 않는 이진 파일에 해당 파일을 "끼우는" 것을 방지할 수 있습니다.

"안전한" 코드를 생성하는 통제된 컴파일러와 통제된 시스템 라이브러리로, 실제 기계어 코드를 사용하더라도 합리적으로 통제된 샌드박스를 제공해야 합니다.

메모리 제한을 적용하시겠습니까?Malloc에 수표를 넣어요.스택이 할당되는 양을 제한하시겠습니까?스택 세그먼트를 제한합니다.

운영 체제는 하루 종일 가상 메모리 관리자를 사용하여 이러한 종류의 제한된 환경을 만들어 내기 때문에 최신 OS에서 이러한 작업을 쉽게 수행할 수 있습니다.

이를 위한 노력이 가치 있는 것인지 아니면 기성 가상 머신과 바이트 코드 런타임을 사용하는 것인지에 대해서는 말할 수 없습니다.

전혀 불가능합니다.언어가 이런 식으로 작동하지 않습니다.GCC를 포함한 대부분의 컴파일러에서 클래스의 개념은 매우 일찍 사라집니다.그렇다고 해도 "모듈"은 말할 것도 없고, 각 메모리 할당을 실시간 객체와 연결할 방법도 없을 것입니다.

저는 이것을 매우 면밀하게 조사하지 않았지만, 크롬(일명 구글 크롬)에서 일하는 사람들은 이미 거의 이와 같은 샌드박스를 작업하고 있습니다. 조사할 가치가 있을지도 모릅니다.

http://dev.chromium.org/developers/design-documents/sandbox/Sandbox-FAQ

오픈 소스이므로 사용이 가능할 것입니다.

8년 후, 저는 제가 원래 요구했던 모든 것을 충족하는 새로운 플랫폼을 발견했습니다.웹 어셈블리를 사용하면 브라우저 내에서 C/C++ 서브셋을 안전하게 실행할 수 있으며 메모리 액세스 제한 및 OS 및 상위 프로세스의 안전하지 않은 작동 방지와 같은 내 요구 사항과 유사한 안전 제한 사항이 제공됩니다.파이어폭스 52에서 구현되었으며 향후 다른 브라우저에서 지원할 가능성이 높습니다.

언어가 튜링 완전한 경우 모든 가능한 코드에 대해 코드 집합이 안전하거나 안전하지 않다고 판단할 수 있는 정적 코드 검증기를 만드는 것은 불가능합니다.그것은 멈춤 문제와 맞먹습니다.

물론 이 점은 감독자 코드가 더 낮은 링 레벨에서 실행되거나 해석 언어(즉, 해석 언어)일 경우 무트입니다.에뮬레이트합니다.

이것을 하는 가장 좋은 방법은 다른 프로세스에서 코드를 시작하는 것입니다(ipc는 그렇게 나쁘지 않습니다). 리눅스 http://linux.die.net/man/2/ptrace 의 Ptrace와 같은 트랩 시스템 호출입니다.

리란은 위의 댓글에서 codepad.org 을 지적했습니다.ptrace, chroot 및 아웃바운드 방화벽으로 구성된 매우 무거운 환경에 의존하기 때문에 적합하지 않지만 여기서 공유하려고 생각했던 몇 가지 g++ 안전 스위치를 찾았습니다.

gcc 4.1.2 flags: -O -fmessage-length=0 -fno-merge-constants -fstrict-aliasing -fstack-protector-all

g++ 4.1.2 flags: -O -std=c++98 -pedantic-errors -Wfatal-errors -Werror -Wall -Wextra -Wno-missing-field-initializers -Wwrite-strings -Wno-deprecated -Wno-unused -Wno-non-virtual-dtor -Wno-variadic-macros -fmessage-length=0 -ftemplate-depth-128 -fno-merge-constants -fno-nonansi-builtins -fno-gnu-keywords -fno-elide-constructors -fstrict-aliasing -fstack-protector-all -Winvalid-pch

The options are explained in the GCC manual

What really caught my eye was the stack-protector flag. I believe it is a merge of this IBM research project (Stack-Smashing Protector) with the official GCC.

The protection is realized by buffer overflow detection and the variable reordering feature to avoid the corruption of pointers. The basic idea of buffer overflow detection comes from StackGuard system.

The novel features are (1) the reordering of local variables to place buffers after pointers to avoid the corruption of pointers that could be used to further corrupt arbitrary memory locations, (2) the copying of pointers in function arguments to an area preceding local variable buffers to prevent the corruption of pointers that could be used to further corrupt arbitrary memory locations, and the (3) omission of instrumentation code from some functions to decrease the performance overhead.

Nice idea, but I'm fairly sure what you're trying to do is impossible with C or C++. If you dropped the sandbox idea it might work.

Java's already got a similar (as in a large library of 3rd party code) system in Maven2

If you want to be really sure, I think the best and perhaps only way to do this is do go down the line of seperate processes and let the O/S handle the access control. It's not that painful to write a generic threaded loader and once you have it, you can override some functions to load specific libraries.

Youy appear to be trying to solve two non-problems. In my own code I have no memory alocation problems or issues with recursion or infinite loops.

What you seem to be proposingh is a different, more limited language than C++. This is something you can pursue of course, but as others have noted you will have to write a compiler for it - simple textual processing will not give you what you want.

ReferenceURL : https://stackoverflow.com/questions/980170/how-to-create-a-lightweight-c-code-sandbox

반응형