想像해 보세요. 거대한 사무실 (소프트웨어 프로그램) 이 있습니다. 여기에는 **일반 문서 (공개 정보)**와 **기밀 문서 (비밀 정보)**가 섞여 있습니다.
1. 기존 방식 (코쿤, Cocoon) 의 문제점: "모든 것을 가두는 금고"
기존에 있던 '코쿤'이라는 도구는 기밀 문서를 다룰 때, 특정 금고 (Secret Block) 안에만 들어갈 수 있도록 했습니다.
문제: 금고 안에서는 모든 것이 기밀로 간주됩니다. 그래서 금고 안에서 일반 문서 (공개 정보) 를 다룰 때조차 "이건 비밀이야!"라고 계속 경고하거나, 금고 밖으로 문서를 꺼낼 때마다 복잡한 절차 (해석/재포장) 를 거쳐야 했습니다.
결과: 개발자들은 매번 "이건 괜찮아, 이건 안 돼"라고 수동으로 확인해야 했고, 너무 까다로운 규칙 때문에 보안이 필요 없는 부분까지도 보안 장벽을 뚫고 지나가는 '구멍 (Escape Hatch)'을 만들어야 하는 불편함이 있었습니다.
2. 필라멘트 (Filament) 의 혁신: "각 문서에 붙는 라벨"
필라멘트는 이 방식을 완전히 바꿉니다. 금고 전체를 가두는 대신, 각 문서 (변수) 에 직접 라벨을 붙입니다.
라벨링 (Labeling): "이 문서는 '비밀 (A)' 등급이야", "저 문서는 '공개 (Public)' 등급이야"라고 각 데이터에 태그를 붙입니다.
자동 추적: 개발자가 코드를 작성할 때, Rust 언어의 자동 추론 기능을 이용해 라벨이 자동으로 따라다니게 합니다. 예를 들어, '비밀' 문서와 '공개' 문서를 합치면, 결과물은 자동으로 '비밀' 등급이 됩니다. 개발자가 일일이 "이건 비밀로 해줘"라고 말하지 않아도 시스템이 알아서 처리합니다.
🌟 필라멘트가 해결한 3 가지 주요 문제
1. "조금만 봐도 돼" (세밀한 감시)
과거: 금고 안에서는 모든 것이 비밀이라, 공개된 정보를 다룰 때도 "비밀 구역에 들어왔으니 조심해!"라고 경고를 보냈습니다.
필라멘트: **"어디서 무엇을 했는지"**를 정확히 봅니다. 공개된 정보를 다룰 때는 공개된 정보처럼, 비밀 정보를 다룰 때는 비밀처럼 취급합니다. 불필요한 경고를 줄여 개발자가 더 자유롭게 일할 수 있게 해줍니다.
2. "조건부 비밀" (PC 블록)
상황: "만약 비밀번호가 맞다면 (비밀 조건), 이 파일을 열어라"라고 하는 코드가 있습니다. 여기서 '비밀번호 확인'이라는 조건 자체가 비밀이라면, 그 결과도 비밀이어야 합니다.
필라멘트:pc_block!이라는 작은 도구로, **"지금은 비밀 조건을 확인 중이니까, 이 블록 안의 모든 결과는 비밀로 간주하자"**라고 자동으로 설정합니다. 이 블록이 끝나면 다시 평범한 상태로 돌아옵니다. 이렇게 하면 불필요하게 전체 프로그램을 비밀 구역으로 만들 필요가 없습니다.
3. "외부 업체와의 협업" (fcall!/mcall!)
상황: 우리 회사 내부 시스템은 보안이 철저한데, 외부 업체 (표준 라이브러리) 는 보안 라벨을 모릅니다.
과거: 외부 업체와 일할 때, 비밀 문서를 일단 '일반 문서'로 위장 (해석) 시켰다가 다시 '비밀 문서'로 되돌려야 했습니다. 이 과정에서 실수로 비밀이 새어 나가는 경우가 많았습니다.
필라멘트:fcall!이나 mcall!이라는 마법을 부려, 외부 업체에게 비밀 문서를 건네줄 때 라벨이 자동으로 유지되도록 합니다. 개발자가 수동으로 위장하거나 되돌릴 필요가 없어, 실수가 거의 없습니다.
📊 왜 이것이 중요한가요?
컴파일러를 고칠 필요가 없습니다: 기존 보안 도구들은 프로그래밍 언어 자체를 뜯어고쳐야 했지만, 필라멘트는 기존 Rust 언어와 컴파일러를 그대로 사용하면서 보안 기능을 추가합니다. 마치 기존 자동차에 최신 내비게이션을 추가하는 것과 같습니다.
개발자가 덜 힘들어집니다: 코드를 많이 수정하거나 복잡한 주석을 달 필요가 없습니다. Rust 가 알아서 라벨을 추론해 주기 때문에, 보안 코드가 원래 코드처럼 자연스럽게 보입니다.
보안이 더 강력합니다: 불필요한 '구멍 (Escape Hatch)'을 뚫지 않아도 되므로, 의도치 않게 비밀 정보가 유출될 위험이 줄어듭니다.
💡 결론
필라멘트는 복잡한 보안 시스템을 개발자가 자연스럽게 다룰 수 있게 해주는 **'똑똑한 보안 비서'**입니다.
기존 방식이 "비밀 구역에 들어오면 모든 것이 비밀이야!"라고 막무가내로 통제했다면, 필라멘트는 **"네가 가진 물건이 비밀인지 공개인지 라벨을 보고, 그 상황에 맞게 행동해"**라고 정교하게 안내합니다. 그 결과, 개발자는 더 적은 노력으로 더 안전한 프로그램을 만들 수 있게 되었습니다.
Filament: Denning-Style Information Flow Control for Rust 기술 요약
이 논문은 Filament라는 새로운 정적 정보 흐름 제어 (IFC, Information Flow Control) 라이브러리를 소개합니다. Filament 는 Rust 프로그래밍 언어를 대상으로 하며, 컴파일러 수정 없이 Denning 스타일의 세밀한 (fine-grained) 정보 흐름 제어를 구현합니다.
1. 문제 정의 (Problem)
기존 언어 기반 IFC 도구들은 다음과 같은 근본적인 딜레마에 직면해 있습니다:
Denning 스타일 시스템: 변수 수준에서 명시적 흐름 (explicit flow) 과 암시적 흐름 (implicit flow) 을 모두 추적하는 정밀한 시스템이지만, 이를 구현하려면 언어와 컴파일러를 수정해야 합니다. 이는 기존 대규모 소프트웨어 시스템을 재작성하고 커스텀 컴파일러를 유지하는 데 막대한 비용이 들어 실용성이 떨어집니다.
조밀한 (Coarse-grained) 접근법: 최근의 Cocoon 과 같은 도구는 컴파일러 수정 없이 라이브러리만으로 IFC 를 구현하지만, '블록 단위 (block-level)'로만 정보를 제어합니다. 이는 프로그래밍 모델을 지나치게 제한적으로 만들고, 보안을 우회하기 위한 '탈출구 (escape hatches)'를 빈번하게 사용하게 하여 보안 강도를 약화시킵니다.
Rust 는 현대적인 시스템 프로그래밍 언어이지만, 기존 IFC 구현체들은 Rust 의 타입 시스템과 호환되지 않거나 커스텀 컴파일러가 필요하여 채택이 어렵습니다.
2. 방법론 (Methodology)
Filament 는 Rust 의 타입 추론 (type inference), 제네릭스 (generics), 트레이트 (traits) 시스템을 활용하여 컴파일러 수정 없이 Denning 스타일의 IFC 를 구현합니다. 주요 기술적 구성 요소는 다음과 같습니다:
2.1. 명시적 흐름 제어 (Explicit Flows)
Labeled<T, L> 타입: 모든 민감한 데이터는 Labeled<T, L> 타입으로 감싸집니다. 여기서 L 은 보안 라벨 (정적 타입) 입니다.
Phantom Types: 런타임 오버헤드를 피하기 위해 보안 라벨은 PhantomData 를 사용하여 타입 시스템에만 존재합니다.
Relabeling: Rust 의 타입 시스템은 서로 다른 라벨 간의 할당을 기본적으로 거부합니다. Filament 는 relabel! 매크로를 사용하여 명시적으로 라벨을 업그레이드 (승격) 하도록 하여, 타입 불일치를 해결하면서도 흐름 제어를 강제합니다.
타입 추론 활용: 연산 결과물의 라벨은 입력값 라벨의 Join(최소 상한) 을 자동으로 추론하여 프로그래머의 주석 부담을 줄입니다.
2.2. 암시적 흐름 제어 (Implicit Flows)
pc_block! 매크로: Denning 스타일의 핵심인 프로그램 카운터 (PC) 라벨을 추적하기 위해 pc_block! 매크로를 도입했습니다.
민감한 데이터에 의존하는 조건문 (if/loop) 내부에서 실행될 때, 이 블록의 PC 라벨이 상승합니다.
블록 내 모든 할당 문에 대해 명시적 흐름과 함께 암시적 흐름 (PC 라벨이 대상 변수 라벨보다 낮아야 함) 을 정적 검사합니다.
Cocoon 의 secret_block 과 달리, 민감한 데이터가 포함된 전체 함수나 블록을 감싸는 것이 아니라 조건부 분기점에만 적용되므로 훨씬 덜 제한적입니다.
2.3. 외부 라이브러리 상호 운용성
fcall! 및 mcall! 매크로: Rust 표준 라이브러리나 서드파티 라이브러리는 보안 라벨을 인식하지 못합니다.
fcall!: 함수 호출 시 인자의 라벨을 자동으로 언래핑 (unwrap) 하고, 호출 후 결과물에 가장 엄격한 라벨을 자동으로 부여합니다.
mcall!: 메서드 호출 시 수신자 (receiver) 의 라벨을 유지하며 결과를 래핑합니다.
이를 통해 개발자는 declassify (등급 하향) 나 wrap/unwrap 을 수동으로 반복할 필요가 없어지며, 보안 오류를 방지합니다.
3. 주요 기여 (Key Contributions)
컴파일러 수정 없는 첫 번째 Denning 스타일 Rust IFC: 기존에 불가능하다고 여겨졌던, Rust 의 안정판 (stable) 컴파일러 위에서 Denning 스타일의 세밀한 흐름 제어를 구현했습니다.
낮은 주석 부담과 유연한 프로그래밍 모델:
Rust 의 타입 추론을 활용하여 명시적 흐름에 대한 주석을 최소화했습니다.
pc_block! 을 통해 암시적 흐름을 효율적으로 제어하여, Cocoon 의 secret_block 과 같은 과도한 제한을 제거했습니다.
안전한 상호 운용성:fcall! 과 mcall! 을 통해 서드파티 라이브러리 사용 시 보안 라벨이 유실되거나 수동 오류가 발생할 가능성을 제거했습니다.
실증 평가: Battleship, Calendar, Spotify TUI, Servo, JPMail 등 5 가지 애플리케이션을 재구현하여 성능과 사용성을 검증했습니다.
4. 평가 결과 (Results)
코드 주석 부담: Filament 는 Cocoon 에 비해 주석과 API 호출 횟수가 현저히 적습니다. 특히 secret_block 이 필요 없어지면서 불필요한 declassify 나 unchecked_operation 사용이 크게 감소했습니다.
예: Battleship 구현 시 Cocoon 은 36 개의 secret_block 이 필요했으나 Filament 는 0 개였습니다.
Spotify TUI 와 Servo 와 같은 대규모 프로젝트에서도 코드 변경량은 0.5% 미만으로 미미했습니다.
보안성 (Permissiveness): Cocoon 은 제한적인 모델로 인해 보안 검사를 우회하기 위한 '탈출구'를 빈번히 사용해야 했지만, Filament 는 Denning 스타일의 정밀한 제어로 인해 불필요한 탈출구 사용이 제거되었습니다. (예: Cocoon 의 Spotify TUI 구현에는 10 개의 불필요한 declassify 가 있었으나 Filament 에서는 제거됨).
컴파일 오버헤드: Filament 는 컴파일 시간에 거의 영향을 미치지 않습니다.
Spotify TUI: +0.45%
Servo: -2.32% (캐시 변동 등 요인)
작은 프로젝트 (Battleship) 에서 상대적으로 오버헤드가 높게 나타났으나, 이는 IFC 라이브러리 컴파일 고정 비용 때문이며 대규모 프로젝트에서는 오버헤드가 상쇄됩니다.
5. 의의 (Significance)
Filament 는 Rust 생태계에서 정보 흐름 보안을 실현하는 중요한 이정표입니다.
실용성: 커스텀 컴파일러 없이 기존 Rust 프로젝트에 IFC 를 도입할 수 있게 하여, 기존 코드베이스의 보안 강화 비용을 획기적으로 낮췄습니다.
정밀성: Denning 스타일의 세밀한 제어를 통해 불필요한 정보 유출을 방지하면서도, 개발자의 생산성을 해치지 않는 균형을 찾았습니다.
확장성: 서드파티 라이브러리와의 호환성을 해결함으로써, 실제 산업 환경에서 IFC 를 적용하는 데 있어 가장 큰 장벽 중 하나를 제거했습니다.
결론적으로 Filament 는 이론적으로 강력하지만 실용성이 부족했던 Denning 스타일 IFC 를 현대적인 시스템 프로그래밍 언어 (Rust) 에 성공적으로 접목시킨 사례로, 향후 안전한 소프트웨어 개발의 새로운 표준이 될 잠재력을 가지고 있습니다.