IMA/EVM (무결성(Integrity) 검증)
IMA(Integrity Measurement Architecture)와 EVM(Extended Verification Module)은 리눅스 커널의 무결성 서브시스템(integrity subsystem)의 핵심 구성요소입니다. IMA는 파일을 측정(measure), 평가(appraise), 감사(audit)하고, EVM은 보안 확장 속성(xattr)의 변조를 감지합니다. TPM과 결합하면 부팅부터 런타임까지 이어지는 신뢰 체인(chain of trust)을 형성하여, 원격 증명(remote attestation)과 FIPS 140-3, Common Criteria 등 컴플라이언스 요구사항을 충족합니다.
핵심 요약
- IMA Measure — 파일 해시를 측정 리스트에 기록하고 TPM PCR 10을 확장하여 원격 증명에 사용합니다.
- IMA Appraise —
security.imaxattr과 파일 해시를 비교하여 무결성을 검증하며, enforce 모드에서는 불일치 시 접근을 차단합니다. - IMA Audit — 파일 접근 이벤트를 audit 로그에 기록하여 감사 추적을 지원합니다.
- EVM HMAC/서명 — 보안 xattr의 HMAC 또는 디지털 서명으로 메타데이터 변조를 방지합니다.
- IMA 정책 — 어떤 파일을 언제 측정/평가/감사할지 결정하는 규칙을
/sys/kernel/security/ima/policy에서 관리합니다. - dm-verity / fs-verity — 블록 장치 또는 파일 단위 Merkle 트리로 읽기 전용 데이터의 무결성을 보장합니다.
| 구성요소 | 역할 | 저장 위치 | TPM 연동 |
|---|---|---|---|
| IMA Measure | 파일 해시를 측정 리스트에 기록, TPM PCR 10 확장 | 커널 메모리 (측정 리스트) | PCR 10 extend |
| IMA Appraise | security.ima xattr과 파일 해시 비교 검증 | security.ima xattr | 선택적 |
| IMA Audit | 파일 접근 이벤트를 audit 로그에 기록 | audit 로그 | 불필요 |
| EVM HMAC | 보안 xattr의 HMAC 보호 (대칭 키) | security.evm xattr | sealed key |
| EVM 디지털 서명 | 보안 xattr의 비대칭 서명 검증(Signature Verification) | security.evm xattr | 선택적 |
| IMA 정책 | 어떤 파일을 언제 측정/평가/감사할지 결정 | /sys/kernel/security/ima/policy | 불필요 |
| dm-verity | 블록 장치(Block Device) 수준 Merkle 트리 검증 | 별도 해시 파티션 | 선택적 |
| fs-verity | 파일 단위 Merkle 트리 (읽기 전용(Read-Only)) | 파일 메타데이터 | 선택적 |
단계별 이해
- IMA 활성화 확인 —
/sys/kernel/security/ima/디렉터리로 IMA가 활성화되었는지 확인합니다.ascii_runtime_measurements와runtime_measurements_count로 현재 측정 상태를 파악합니다. - 3가지 모드 이해 — Measure(측정), Appraise(평가), Audit(감사) 모드의 차이를 학습합니다.
Measure는 TPM 기반 원격 증명, Appraise는 파일 무결성 보호, Audit는 감사 로그 기록에 사용됩니다.
- IMA 정책 작성 — 어떤 파일을 어떤 조건에서 측정/평가할지 정책을 구성합니다.
기본 정책부터 시작하여 커스텀 정책으로 확장합니다.
- EVM 보호 설정 — HMAC 또는 디지털 서명으로 보안 xattr의 변조를 방지합니다.
TPM sealed key로 HMAC 키를 보호하고, evmctl로 서명을 적용합니다.
- 원격 증명 연동 — TPM PCR 값과 측정 리스트를 원격 서버로 전송하여 시스템 무결성을 검증합니다.
IMA 측정 리스트의 각 엔트리가 PCR extend 체인으로 연결되어 변조를 감지합니다.
커널 소스 위치: IMA/EVM 코드는 security/integrity/ 디렉터리에 위치합니다. IMA는 security/integrity/ima/, EVM은 security/integrity/evm/, 공통 코드는 security/integrity/ 루트에 있습니다.
IMA/EVM 기본 동작 확인 (빠른 시작)
# 1. IMA 활성화 여부 확인
ls /sys/kernel/security/ima/
# ascii_runtime_measurements binary_runtime_measurements
# policy runtime_measurements_count violations
# 2. 현재 측정 상태
echo "측정 엔트리 수: $(cat /sys/kernel/security/ima/runtime_measurements_count)"
echo "위반 수: $(cat /sys/kernel/security/ima/violations)"
# 3. 최근 측정 엔트리 5개
tail -5 /sys/kernel/security/ima/ascii_runtime_measurements
# 4. EVM 상태
cat /sys/kernel/security/evm 2>/dev/null || echo "EVM 미활성"
# 5. ima-evm-utils 설치 확인
evmctl --version 2>/dev/null || echo "evmctl 미설치: dnf install ima-evm-utils"
# 6. 특정 파일의 IMA xattr 확인
getfattr -n security.ima -e hex /usr/bin/bash 2>/dev/null || \
echo "security.ima xattr 없음"
IMA 3가지 동작 모드 비교
| 모드 | 동작 | TPM 필요 | xattr 필요 | 접근 차단 | 주요 용도 |
|---|---|---|---|---|---|
| Measure | 해시 기록 + PCR extend | 예 | 아니오 | 아니오 | 원격 증명 |
| Appraise | 해시 vs xattr 비교 | 아니오 | 예 | enforce 시 예 | 무결성 보호 |
| Audit | audit 로그 기록 | 아니오 | 아니오 | 아니오 | 감사 추적 |
IMA 아키텍처 개요
IMA는 LSM(Linux Security Module) 인프라의 무결성 후크(Hook)를 사용하여 파일 접근 시점에 개입합니다. security_inode_alloc(), security_file_open(), security_bprm_check() 등의 후크에서 IMA 콜백(Callback)이 호출되며, 정책에 따라 측정(measure), 평가(appraise), 감사(audit) 동작을 수행합니다.
IMA의 핵심 동작 흐름은 다음과 같습니다:
- VFS 계층에서 파일 접근(open, exec, mmap, kernel_read) 시 LSM 후크가 호출됩니다.
- IMA 정책 엔진(Policy Engine)이 해당 접근에 대한 규칙 매칭을 수행합니다.
- 매칭된 규칙에 따라 measure, appraise, audit 중 하나 이상의 동작이 실행됩니다.
- EVM이 활성화되어 있으면
security.imaxattr 자체의 무결성도security.evm으로 검증합니다.
| LSM 후크 | 호출 시점 | IMA 함수 |
|---|---|---|
file_open | 파일 열기 | ima_file_check() |
bprm_check | exec 실행 | ima_bprm_check() |
mmap_file | 공유 라이브러리(Shared Library) mmap | ima_file_mmap() |
kernel_read_file | 커널 모듈(Kernel Module), 펌웨어(Firmware) 로드 | ima_read_file() |
kernel_load_data | kexec 이미지, 정책 로드 | ima_load_data() |
Measure 모드
IMA Measure는 파일의 해시 값을 측정 리스트(measurement list)에 추가하고, 해당 해시를 TPM의 PCR 10에 extend 하는 동작입니다. 한 번 extend된 PCR 값은 TPM 리셋(재부팅) 전까지 되돌릴 수 없으므로, 부팅 이후 실행된 모든 바이너리와 읽혀진 보안 관련 파일의 이력이 변조 불가능하게 기록됩니다.
측정 리스트는 /sys/kernel/security/ima/ascii_runtime_measurements에서 확인할 수 있습니다.
# 현재 측정 리스트 확인
cat /sys/kernel/security/ima/ascii_runtime_measurements | head -20
# 측정 리스트 엔트리 수
wc -l /sys/kernel/security/ima/ascii_runtime_measurements
# TPM PCR 10 현재 값 확인 (tpm2-tools)
tpm2_pcrread sha256:10
# 바이너리 측정 리스트 (원격 증명 시 사용)
xxd /sys/kernel/security/ima/binary_runtime_measurements | head
PCR extend는 비가역: TPM PCR은 extend 전용 레지스터(Register)로, PCR_new = Hash(PCR_old || data) 연산만 가능합니다. 한 번 기록되면 재부팅 전까지 이전 값으로 되돌릴 수 없어, 공격자가 측정 기록을 삭제하거나 변조할 수 없습니다.
측정 리스트 세부 분석
측정 리스트의 각 레코드는 다음 필드로 구성됩니다:
| 필드 | 크기 | 설명 |
|---|---|---|
PCR | 2~3자 | extend 대상 PCR 번호 (기본 10) |
template-hash | 알고리즘별 가변 | 전체 레코드의 해시 (PCR extend 입력) |
template-name | 가변 | 사용된 템플릿 이름 (ima-ng, ima-sig 등) |
filedata-hash | 알고리즘별 가변 | 파일 내용의 해시 |
filename-hint | 가변 | 파일 경로 (n-ng 필드) |
template-hash는 레코드 전체의 해시로, TPM PCR extend에 사용됩니다. filedata-hash는 파일 내용의 해시로, 파일 무결성 검증에 사용됩니다. 이 두 해시는 다른 용도이므로 혼동하지 않아야 합니다.
boot_aggregate 상세
IMA 측정 리스트의 첫 번째 엔트리는 항상 boot_aggregate입니다. 이 값은 부팅 시점의 TPM PCR 0~9 값을 연결하여 해싱한 결과로, 부팅 환경의 무결성을 나타냅니다. 원격 증명 서버는 이 값을 확인하여 부팅 체인이 신뢰할 수 있는지 판단합니다.
/* security/integrity/ima/ima_init.c */
static int __init ima_calc_boot_aggregate(struct ima_digest_data *hash)
{
struct tpm_digest d = { .alg_id = TPM_ALG_SHA256 };
int rc, i;
rc = crypto_shash_init(shash);
if (rc)
return rc;
/* PCR 0~9의 값을 순서대로 해싱 */
for (i = 0; i <= 9; i++) {
rc = tpm_pcr_read(NULL, i, &d);
if (rc)
return rc;
crypto_shash_update(shash, d.digest, d.digest_size);
}
crypto_shash_final(shash, hash->digest);
return 0;
}
IMA 해시 알고리즘과 TPM 2.0 뱅크
TPM 2.0은 여러 해시 알고리즘 뱅크(SHA-1, SHA-256, SHA-384, SHA-512)를 동시에 지원합니다. IMA는 ima_hash= 부트 파라미터로 지정된 알고리즘을 사용하지만, TPM PCR extend 시에는 TPM이 지원하는 모든 뱅크에 동시 extend됩니다.
| IMA 해시 | TPM 뱅크 | PCR extend 입력 | 비고 |
|---|---|---|---|
| sha256 | SHA-256 | SHA-256(template-hash) | 권장 (기본) |
| sha512 | SHA-256 + SHA-512 | 각 뱅크별 해시 | 높은 보안 |
| sha1 | SHA-1 | SHA-1(template-hash) | 레거시, 비권장 |
IMA는 동일 파일의 중복 측정을 방지하기 위해 ima_iint_cache에 inode별 무결성 정보를 캐싱합니다. 파일이 변경되면(쓰기 후 닫기) 캐시(Cache)가 무효화(Invalidation)되어 다음 접근 시 재측정됩니다.
/* security/integrity/ima/ima.h */
struct ima_iint_cache {
unsigned long flags;
unsigned long measured_pcrs;
enum integrity_status ima_file_status;
enum integrity_status ima_mmap_status;
enum integrity_status ima_bprm_status;
enum integrity_status ima_read_status;
struct ima_digest_data *ima_hash;
};
Appraise 모드
IMA Appraise는 파일의 실제 해시를 계산하고, 이를 security.ima 확장 속성(xattr)에 저장된 참조 값과 비교하여 파일 무결성을 검증합니다. 검증 실패 시 정책 모드에 따라 접근을 차단(enforce)하거나, 로그만 남기고 허용(log)하거나, xattr을 업데이트(fix)할 수 있습니다.
security.ima xattr의 형식은 해시 알고리즘과 저장 방식에 따라 달라집니다:
| 타입 | xattr 구조 | 설명 |
|---|---|---|
IMA_XATTR_DIGEST (0x01) | type(1) + digest | 단순 해시 (레거시) |
IMA_XATTR_DIGEST_NG (0x04) | type(1) + algo(1) + digest | 알고리즘 지정 해시 |
EVM_IMA_XATTR_DIGSIG (0x03) | type(1) + signature header + sig | 디지털 서명 |
# security.ima xattr 확인
getfattr -n security.ima -e hex /usr/bin/bash
# evmctl로 IMA 해시 확인
evmctl ima_hash /usr/bin/bash
# IMA 서명 검증
evmctl ima_verify /usr/bin/bash
# IMA appraise 모드 확인
cat /proc/cmdline | grep ima_appraise
/* security/integrity/ima/ima_appraise.c — 핵심 검증 로직 */
int ima_appraise_measurement(enum ima_hooks func,
struct integrity_iint_cache *iint,
struct file *file,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
int xattr_len)
{
enum integrity_status status = INTEGRITY_UNKNOWN;
/* xattr 없음 */
if (!xattr_value) {
status = INTEGRITY_NOLABEL;
goto out;
}
/* 해시 비교 */
rc = ima_calc_file_hash(file, &hash);
if (rc == 0 && xattr_verify(xattr_value, &hash))
status = INTEGRITY_PASS;
else
status = INTEGRITY_FAIL;
out:
/* enforce 모드면 FAIL/NOLABEL 시 -EACCES 반환 */
if (ima_appraise & IMA_APPRAISE_ENFORCE)
return (status == INTEGRITY_PASS) ? 0 : -EACCES;
return 0;
}
Audit 모드
IMA Audit는 파일 접근 이벤트를 커널 audit 서브시스템에 기록합니다. 측정이나 평가와 달리 TPM이나 xattr을 사용하지 않으며, 순수하게 감사 추적(audit trail) 목적으로 동작합니다. IMA audit는 커널의 audit_log_start() / audit_log_format() API를 사용하여 INTEGRITY_RULE 타입의 audit 레코드를 생성합니다.
audit 모드는 단독으로 사용하거나, measure/appraise와 함께 사용할 수 있습니다. 파일 접근이 정책 규칙에 매칭되면 해당 이벤트의 해시, 파일 경로, SELinux 컨텍스트 등이 audit 로그에 기록됩니다.
| audit 레코드 필드 | 설명 | 예시 값 |
|---|---|---|
INTEGRITY_RULE | 매칭된 IMA 정책 규칙 | func=FILE_CHECK mask=MAY_READ |
cause | 감사 사유 | policy_rule |
hash | 파일 해시 | sha256:3b5a...c2f1 |
subj | 주체 보안 컨텍스트 (SELinux) | system_u:system_r:httpd_t:s0 |
obj | 객체 보안 컨텍스트 | system_u:object_r:httpd_exec_t:s0 |
# IMA audit 이벤트 검색
ausearch -m INTEGRITY_RULE -ts today
# 출력 예시:
# type=INTEGRITY_RULE msg=audit(1710000000.123:456):
# file="/usr/bin/curl" hash="sha256:a1b2..." cause="policy_rule"
# subj=unconfined_u:unconfined_r:unconfined_t:s0
# IMA 무결성 검증 실패 이벤트
ausearch -m INTEGRITY_DATA -m INTEGRITY_STATUS -ts today
Measure vs Audit: Measure는 TPM PCR에 해시를 extend하여 원격 증명에 사용할 수 있지만, Audit는 커널 audit 로그에만 기록합니다. 일반적으로 둘을 함께 사용하여 측정(검증)과 감사(추적)를 동시에 수행합니다.
IMA audit 내부 구현
/* security/integrity/ima/ima_api.c */
void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename)
{
struct audit_buffer *ab;
char *hash_str;
int i;
/* audit 버퍼 할당 */
ab = audit_log_start(audit_context(), GFP_KERNEL,
AUDIT_INTEGRITY_RULE);
if (!ab)
return;
/* 해시를 16진 문자열로 변환 */
hash_str = iint->ima_hash->digest;
audit_log_format(ab, "file=\"%s\" hash=\"%s:%s\"",
filename, hash_algo_name[iint->ima_hash->algo],
hash_str);
/* 정책 규칙 정보 추가 */
audit_log_format(ab, " cause=\"policy_rule\"");
audit_log_end(ab);
}
IMA audit 이벤트는 AUDIT_INTEGRITY_RULE(1805), AUDIT_INTEGRITY_DATA(1800), AUDIT_INTEGRITY_STATUS(1802) 등의 메시지 타입으로 생성됩니다. 각 타입의 의미는 다음과 같습니다:
| 메시지 타입 | ID | 발생 조건 |
|---|---|---|
AUDIT_INTEGRITY_DATA | 1800 | 파일 해시 불일치 (appraise FAIL) |
AUDIT_INTEGRITY_METADATA | 1801 | 메타데이터 검증 실패 (EVM FAIL) |
AUDIT_INTEGRITY_STATUS | 1802 | 무결성 상태 변경 |
AUDIT_INTEGRITY_HASH | 1803 | 해시 계산 오류 |
AUDIT_INTEGRITY_PCR | 1804 | PCR 무효화 |
AUDIT_INTEGRITY_RULE | 1805 | 정책 규칙 매칭 (audit action) |
AUDIT_INTEGRITY_EVM_XATTR | 1806 | EVM xattr 검증 결과 |
AUDIT_INTEGRITY_POLICY_RULE | 1807 | 정책 규칙 로드/변경 |
IMA 정책 문법
IMA 정책은 어떤 파일을 언제 어떻게 처리할지 결정하는 규칙 집합입니다. 커널 부트 파라미터(ima_policy=)로 내장 정책을 선택하거나, /sys/kernel/security/ima/policy에 커스텀 정책을 기록할 수 있습니다.
# 정책 규칙 형식
action condition [condition ...] [template=] [pcr=]
# action: measure | dont_measure | appraise | dont_appraise | audit
# condition: func= | mask= | fowner= | uid= | euid= | fsuuid= |
# fsmagic= | fsname= | subtype= | obj_type= | subj_type=
| 조건 키워드 | 설명 | 예시 |
|---|---|---|
func= | LSM 후크 함수 지정 | FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK, FIRMWARE_CHECK, KEXEC_KERNEL_CHECK, POLICY_CHECK, KEY_CHECK |
mask= | 파일 접근 모드 | MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND |
fowner= | 파일 소유자 UID | fowner=0 (root 소유) |
uid= / euid= | 프로세스(Process) UID/EUID | uid=0 |
fsuuid= | 파일시스템(Filesystem) UUID | fsuuid=a1b2c3d4-... |
fsmagic= | 파일시스템 매직 넘버 | fsmagic=0x9fa0 (proc), 0x62656572 (sysfs) |
fsname= | 파일시스템 이름 | fsname=ext4 |
obj_type= | SELinux 객체 타입 | obj_type=httpd_exec_t |
subj_type= | SELinux 주체 타입 | subj_type=init_t |
pcr= | 측정에 사용할 PCR 번호 | pcr=10 (기본), pcr=11 |
template= | 측정 레코드 템플릿 | template=ima-ng, template=ima-sig |
내장 정책(Built-in Policy)
| 부트 파라미터 | 동작 |
|---|---|
ima_policy=tcb | 모든 실행 파일, 공유 라이브러리, 커널 모듈 측정 |
ima_policy=appraise_tcb | root 소유 파일 평가 (enforce) |
ima_policy=critical_data | 커널 모듈, 펌웨어, kexec 이미지 측정 |
ima_policy=secure_boot | Secure Boot 키로 서명된 파일만 허용 |
커스텀 정책 예시
# /etc/ima/ima-policy — 실전 정책 예시
# 가상 파일시스템 측정 제외
dont_measure fsmagic=0x9fa0 # proc
dont_measure fsmagic=0x62656572 # sysfs
dont_measure fsmagic=0x64626720 # debugfs
dont_measure fsmagic=0x01021994 # tmpfs
dont_measure fsmagic=0x73636673 # securityfs
dont_measure fsmagic=0x28cd3d45 # cramfs
dont_measure fsmagic=0x1cd1 # devpts
dont_measure fsmagic=0x42494e4d # binfmt_misc
# 실행 파일과 공유 라이브러리 측정+평가
measure func=BPRM_CHECK template=ima-ng pcr=10
appraise func=BPRM_CHECK fowner=0
measure func=MMAP_CHECK mask=MAY_EXEC template=ima-ng pcr=10
appraise func=MMAP_CHECK mask=MAY_EXEC fowner=0
# 커널 모듈 측정+평가 (서명 필수)
measure func=MODULE_CHECK template=ima-sig pcr=10
appraise func=MODULE_CHECK appraise_type=imasig
# 펌웨어 측정+평가
measure func=FIRMWARE_CHECK template=ima-ng pcr=10
appraise func=FIRMWARE_CHECK appraise_type=imasig
# kexec 커널 이미지 서명 필수
appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig
# IMA 정책 자체도 서명 필수
appraise func=POLICY_CHECK appraise_type=imasig
# SELinux 컨텍스트 기반 정책
measure func=FILE_CHECK obj_type=httpd_exec_t template=ima-ng
# 특정 파일시스템만 감사
audit func=FILE_CHECK fsname=ext4
# 정책 로드
# cat /etc/ima/ima-policy > /sys/kernel/security/ima/policy
정책 로드는 단방향: 기본적으로 /sys/kernel/security/ima/policy에 기록된 정책은 추가(append)만 가능하고, 삭제나 수정은 불가능합니다. CONFIG_IMA_WRITE_POLICY=y를 설정하면 재기록이 가능하지만, 보안상 프로덕션에서는 권장하지 않습니다.
IMA 템플릿
IMA 템플릿은 측정 리스트 레코드의 형식을 정의합니다. 각 레코드가 어떤 정보(해시, 파일명, 서명 등)를 포함할지 결정합니다.
| 템플릿 이름 | 필드 | 설명 | 커널 버전 |
|---|---|---|---|
ima | d|n | SHA-1 해시 + 파일명 (레거시) | 2.6.30+ |
ima-ng | d-ng|n-ng | 알고리즘 접두사 해시 + 긴 파일명 | 3.13+ |
ima-sig | d-ng|n-ng|sig | ima-ng + 디지털 서명 | 3.13+ |
ima-buf | d-ng|n-ng|buf | ima-ng + 임의 버퍼(Buffer) 데이터 | 4.17+ |
ima-modsig | d-ng|n-ng|sig|d-modsig|modsig | 모듈 내장 서명 포함 | 5.4+ |
템플릿 필드 상세
| 필드 | 설명 | 형식 |
|---|---|---|
d | SHA-1 해시 (고정) | 20바이트 |
n | 파일명 (256자 제한) | null-terminated string |
d-ng | 알고리즘:해시 | sha256:3b5a...c2f1 |
n-ng | 긴 파일명 (제한 없음) | length-prefixed string |
sig | xattr의 IMA 서명 | PKCS#7 / 커스텀 v2 |
buf | 커널 버퍼 데이터 | 가변 길이 바이너리 |
d-modsig | 모듈 appended 서명 해시 | algo:hash |
modsig | 모듈 appended 서명 원본 | PKCS#7 |
# 현재 사용 중인 기본 템플릿 확인
cat /sys/kernel/security/ima/ima_template
# 템플릿 형식 확인
cat /sys/kernel/security/ima/ima_template_fmt
# 부트 파라미터로 템플릿 지정
# ima_template=ima-sig ima_hash=sha256
/* security/integrity/ima/ima_template_lib.c */
static struct ima_template_desc builtin_templates[] = {
{ .name = "ima", .fmt = "d|n" },
{ .name = "ima-ng", .fmt = "d-ng|n-ng" },
{ .name = "ima-sig", .fmt = "d-ng|n-ng|sig" },
{ .name = "ima-buf", .fmt = "d-ng|n-ng|buf" },
{ .name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig" },
};
커스텀 템플릿 정의
커널 6.x부터 부트 파라미터로 커스텀 템플릿 형식을 정의할 수 있습니다:
# 커스텀 템플릿 정의 (부트 파라미터)
ima_template_fmt=d-ng|n-ng|sig|buf
# 여러 템플릿을 정책 규칙별로 지정 가능
measure func=BPRM_CHECK template=ima-sig
measure func=KEY_CHECK template=ima-buf
measure func=CRITICAL_DATA template=ima-buf
IMA 템플릿 시스템의 확장성은 ima_template_field 구조체(Struct)의 field_init / field_show 콜백으로 구현됩니다:
/* security/integrity/ima/ima.h */
struct ima_template_field {
const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN];
int (*field_init)(struct ima_event_data *event_data,
struct ima_field_data *field_data);
void (*field_show)(struct seq_file *m,
enum ima_show_type show,
struct ima_field_data *field_data);
};
/* 등록된 필드 함수들 */
static struct ima_template_field supported_fields[] = {
{ .field_id = "d", .field_init = ima_eventdigest_init },
{ .field_id = "n", .field_init = ima_eventname_init },
{ .field_id = "d-ng", .field_init = ima_eventdigest_ng_init },
{ .field_id = "n-ng", .field_init = ima_eventname_ng_init },
{ .field_id = "sig", .field_init = ima_eventsig_init },
{ .field_id = "buf", .field_init = ima_eventbuf_init },
{ .field_id = "d-modsig", .field_init = ima_eventdigest_modsig_init },
{ .field_id = "modsig", .field_init = ima_eventmodsig_init },
};
KEY_CHECK와 CRITICAL_DATA: 커널 5.11+에서 func=KEY_CHECK는 키링(Keyring)에 로드되는 인증서를 측정하고, func=CRITICAL_DATA는 SELinux 정책 해시, dm-crypt 키 설명 등 커널 내부 중요 데이터를 측정합니다. 이 기능은 ima-buf 템플릿과 함께 사용합니다.
다이제스트 리스트
대규모 배포 환경에서 모든 파일에 개별적으로 security.ima xattr을 설정하는 것은 비효율적입니다. 다이제스트 리스트(digest list)는 배포판이 제공하는 알려진 파일 해시 목록으로, IMA가 이 목록에 포함된 해시와 일치하면 파일을 신뢰합니다.
# digest-list-tools 패키지 사용
# RPM 패키지에서 다이제스트 리스트 생성
manage_digest_lists -a add -d /etc/ima/digest_lists \
-i rpm+file -p /var/lib/rpm
# 다이제스트 리스트 서명
evmctl sign -k /etc/keys/privkey.pem \
/etc/ima/digest_lists/0-metadata_list-compact-rpm
# 정책에서 다이제스트 리스트 평가 설정
appraise func=BPRM_CHECK appraise_type=imasig|imasig_digest_list
# 로드된 다이제스트 리스트 확인
cat /sys/kernel/security/ima/digests_count
compact list 형식: 다이제스트 리스트의 compact 형식은 헤더(알고리즘, 타입, 개수)와 연속된 해시 바이트로 구성됩니다. TLV(Type-Length-Value) 형식도 지원하며, 배포판별로 RPM, DEB 패키지 메타데이터에서 자동 생성됩니다.
다이제스트 리스트 데이터 구조
/* 다이제스트 리스트 compact 형식 헤더 */
struct compact_list_hdr {
u8 version; /* 형식 버전 */
u8 _reserved;
u16 type; /* COMPACT_FILE, COMPACT_METADATA 등 */
u16 modifiers; /* 수정자 플래그 */
u16 algo; /* 해시 알고리즘 ID */
u32 count; /* 다이제스트 개수 */
u32 datalen; /* 다이제스트 데이터 전체 길이 */
} __packed;
/* 헤더 뒤에 count × digest_size 바이트의 해시가 연속 */
/* 예: SHA-256, 1000개 파일 → 32000 바이트 */
| 다이제스트 리스트 타입 | 설명 | 용도 |
|---|---|---|
COMPACT_FILE | 파일 내용 해시 | IMA appraise |
COMPACT_METADATA | 메타데이터 해시 | EVM 검증 |
COMPACT_PARSER | 파서 바이너리 해시 | 다이제스트 리스트 파서 자체 |
COMPACT_KEY | 키 해시 | 키 검증 |
# 다이제스트 리스트 생성 워크플로 (RPM 기반)
# 1. RPM 데이터베이스에서 파일 해시 추출
rpm -qa --queryformat '%{FILEDIGESTS}\n' | head
# 2. manage_digest_lists로 compact 리스트 생성
manage_digest_lists -a add -d /etc/ima/digest_lists \
-i rpm+file -p /var/lib/rpm
# 3. 생성된 리스트 확인
ls -la /etc/ima/digest_lists/
# 4. 다이제스트 리스트에 서명
for f in /etc/ima/digest_lists/0-*; do
evmctl sign -k /etc/keys/ima-privkey.pem "$f"
done
# 5. 커널에 다이제스트 리스트 로드
echo "/etc/ima/digest_lists" > /sys/kernel/security/ima/digest_list_data
IMA 네임스페이스(Namespace)
컨테이너(Container) 환경에서 각 네임스페이스가 독립적인 IMA 정책과 측정 리스트를 가질 수 있도록 하는 기능입니다. 커널 6.x에서 IMA 네임스페이스 지원이 점진적으로 도입되고 있습니다.
| 기능 | 지원 상태 (6.x) | 설명 |
|---|---|---|
| 네임스페이스별 정책 | 실험적 (패치(Patch)셋) | user namespace별 독립 IMA 정책 |
| 네임스페이스별 측정 리스트 | 실험적 | 컨테이너별 별도 ascii_runtime_measurements |
| 네임스페이스별 securityfs | 부분 지원 | mount -t securityfs per namespace |
| 네임스페이스별 appraise | 제한적 | 부분적 키링 격리(Isolation) |
/* IMA 네임스페이스 구조 (패치 기반) */
struct ima_namespace {
struct user_namespace *user_ns;
struct list_head ima_measurements; /* 네임스페이스별 측정 리스트 */
struct list_head ima_default_rules;
struct list_head ima_policy_rules;
int ima_policy_loaded;
struct mutex ima_write_mutex;
};
개발 중인 기능: IMA 네임스페이스는 아직 메인라인 커널에 완전히 통합되지 않았습니다. 실험적 패치셋이 존재하며, Stefan Berger 등의 개발자들이 user namespace 기반 IMA 격리를 제안하고 있습니다. 프로덕션 사용은 배포판의 백포트 상태를 확인하세요.
현재 프로덕션에서 컨테이너 IMA를 사용하려면 호스트 IMA 정책으로 컨테이너 내부 파일도 함께 관리하는 방식이 일반적입니다:
# 호스트 정책에서 특정 컨테이너 rootfs 대상 측정
measure func=FILE_CHECK fsuuid=container-rootfs-uuid template=ima-ng
# overlay 파일시스템 대상
measure func=FILE_CHECK fsname=overlay template=ima-ng
IMA 커널 내부 구현
IMA의 핵심 코드는 security/integrity/ima/ 디렉터리에 위치하며, 약 15개의 소스 파일로 구성됩니다.
| 소스 파일 | 역할 |
|---|---|
ima_main.c | LSM 후크 콜백, process_measurement() 핵심 흐름 |
ima_api.c | ima_collect_measurement(), ima_store_measurement(), ima_audit_measurement() |
ima_policy.c | 정책 파싱, 매칭, securityfs 인터페이스 |
ima_crypto.c | 파일 해시 계산, ahash/shash 선택, 비동기 해싱 |
ima_queue.c | 측정 리스트 관리, TPM PCR extend |
ima_appraise.c | xattr 기반 평가 로직, enforce/fix/log 판정 |
ima_template.c | 템플릿 등록/조회, 커스텀 템플릿 지원 |
ima_template_lib.c | 필드별 직렬화(Serialization)/역직렬화 (d-ng, n-ng, sig 등) |
ima_fs.c | securityfs 인터페이스 (measurements, policy, violations) |
ima_init.c | 부팅 시 초기화, boot aggregate 측정 |
ima_crypto.c 해시 계산 상세
IMA는 파일 해시 계산 시 커널의 Crypto API를 사용하며, 비동기 해시(ahash)를 우선 시도하고 실패 시 동기 해시(shash)로 폴백합니다. 비동기 해시는 하드웨어 가속(AES-NI 기반 SHA 등)을 활용할 수 있어 대용량 파일에서 성능 이점이 있습니다.
/* security/integrity/ima/ima_crypto.c — 해시 계산 */
int ima_calc_file_hash(struct file *file,
struct ima_digest_data *hash)
{
struct crypto_ahash *tfm;
loff_t i_size = i_size_read(file_inode(file));
/* 작은 파일: shash (동기) 사용 — 오버헤드 최소 */
if (i_size <= IMA_HASH_READ_SIZE)
return ima_calc_file_shash(file, hash);
/* 큰 파일: ahash (비동기) 사용 — 하드웨어 가속 활용 */
tfm = ima_alloc_ahash(hash->algo);
if (IS_ERR(tfm))
return ima_calc_file_shash(file, hash);
/* 파일을 페이지 단위로 읽으며 해시 업데이트 */
while (offset < i_size) {
rbuf = read_page(file, offset);
ahash_request_set_crypt(req, &sg, NULL, rbuf_len);
rc = crypto_ahash_update(req);
offset += rbuf_len;
}
crypto_ahash_final(req, hash->digest);
return 0;
}
process_measurement() 핵심 흐름
/* security/integrity/ima/ima_main.c — 단순화된 흐름 */
static int process_measurement(struct file *file,
const struct cred *cred,
u32 secid,
char *buf, loff_t size,
int mask,
enum ima_hooks func)
{
struct inode *inode = file_inode(file);
struct integrity_iint_cache *iint;
struct ima_template_desc *template_desc;
int action;
/* 1. 정책 매칭 — 어떤 action을 수행할지 결정 */
action = ima_get_action(file->f_path.mnt, inode, cred,
secid, mask, func, &pcr,
&template_desc, NULL, NULL);
if (!action)
return 0; /* 매칭 규칙 없음 → 통과 */
/* 2. inode 무결성 캐시 조회/생성 */
iint = integrity_inode_get(inode);
/* 3. 파일 해시 수집 */
if (action & IMA_COLLECTED && !(iint->flags & IMA_COLLECTED))
ima_collect_measurement(iint, file, buf, size, hash_algo, modsig);
/* 4. 측정 (measure) */
if (action & IMA_MEASURE)
ima_store_measurement(iint, file, template_desc);
/* 5. 평가 (appraise) */
if (action & IMA_APPRAISE_SUBMASK)
rc = ima_appraise_measurement(func, iint, file, ...);
/* 6. 감사 (audit) */
if (action & IMA_AUDIT)
ima_audit_measurement(iint, pathname);
return rc;
}
EVM 아키텍처
EVM(Extended Verification Module)은 보안 관련 확장 속성(xattr)의 무결성을 보호합니다. security.ima, security.selinux, security.capability 등의 xattr이 변조되지 않았음을 HMAC 또는 디지털 서명으로 보장하며, 그 검증 값을 security.evm xattr에 저장합니다.
EVM이 HMAC를 계산할 때 포함하는 데이터:
- 보호 대상 xattr 값들:
security.ima,security.selinux,security.capability,security.apparmor,security.SMACK64 - inode 메타데이터:
i_ino,i_generation,i_uid,i_gid,i_mode - 파일시스템 UUID
/* security/integrity/evm/evm_crypto.c */
static int evm_calc_hmac_or_hash(struct dentry *dentry,
const char *req_xattr_name,
const char *req_xattr_value,
size_t req_xattr_value_len,
char type,
struct evm_digest *data)
{
/* 1. 각 보호 대상 xattr 값을 HMAC 입력에 추가 */
for (xattr = evm_config_xattrnames; *xattr; xattr++) {
rc = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, *xattr, ...);
crypto_shash_update(desc, xattr_value, xattr_size);
}
/* 2. inode 메타데이터 추가 */
hmac_add_misc(desc, inode, type, data);
/* 3. 최종 HMAC/해시 계산 */
crypto_shash_final(desc, data->digest);
}
EVM HMAC 모드
EVM HMAC 모드는 대칭 키를 사용하여 xattr의 무결성을 보호합니다. 키는 커널 키링에 로드되며, TPM sealed key를 사용하면 키가 TPM 외부에서 복호화(Decryption)될 수 없어 보안이 강화됩니다.
| 키 타입 | 저장 방식 | 보안 수준 | 사용 사례 |
|---|---|---|---|
| trusted key | TPM sealed blob | 높음 | 프로덕션, TPM 있는 시스템 |
| encrypted key | master key로 암호화 | 중간 | TPM 없는 환경 |
| user key | 평문 커널 메모리 | 낮음 | 개발/테스트 전용 |
# TPM trusted key 생성 (TPM으로 sealed)
keyctl add trusted evm-key "new 32" @u
# trusted key를 파일로 백업 (sealed blob)
keyctl pipe $(keyctl search @u trusted evm-key) > /etc/keys/evm-trusted.blob
# 부팅 시 trusted key 복원
keyctl add trusted evm-key "load $(cat /etc/keys/evm-trusted.blob)" @u
# encrypted key 대안 (TPM 없는 경우)
keyctl add encrypted evm-key "new default user:masterkey 32" @u
# EVM 활성화 (키 로드 후)
echo 1 > /sys/kernel/security/evm
# EVM HMAC으로 xattr 보호 생성
evmctl hmac /usr/bin/bash
# EVM xattr 확인
getfattr -n security.evm -e hex /usr/bin/bash
HMAC 재계산: 보호 대상 xattr(security.ima, security.selinux 등)이 변경되면 EVM이 자동으로 security.evm HMAC을 재계산합니다. 단, EVM이 활성화(echo 1 > /sys/kernel/security/evm)된 상태에서만 동작합니다.
EVM 상태 값
| 값 | 의미 | 설명 |
|---|---|---|
0 | 비활성 | EVM 미초기화, xattr 검증 안 함 |
1 | HMAC 모드 | 대칭 키(trusted/encrypted) 로드 완료 |
2 | 서명 모드 | 공개 키 로드 완료, 서명 검증만 |
6 | HMAC + 서명 | 양쪽 모두 활성화 (1+2+4) |
# EVM 초기화 시퀀스 (initramfs 또는 init 스크립트)
# 1. HMAC 키 로드 (TPM trusted key)
keyctl add trusted evm-key \
"load $(xxd -p /etc/keys/evm-trusted.blob | tr -d '\n')" @u
# 2. 서명 검증용 공개 키 로드
keyctl padd asymmetric "" %keyring:.evm < /etc/keys/evm-cert.x509
# 3. EVM 활성화
echo 1 > /sys/kernel/security/evm # HMAC 모드
# 또는
echo 2 > /sys/kernel/security/evm # 서명 검증 전용
# 4. 상태 확인
cat /sys/kernel/security/evm
# 출력: 1 (HMAC) 또는 2 (서명) 또는 6 (둘 다)
# 5. 보호 대상 xattr 목록 확인
cat /sys/kernel/security/integrity/evm/evm_xattrs
# security.ima
# security.selinux
# security.capability
# security.apparmor
# security.SMACK64
EVM HMAC vs 디지털 서명 선택 기준
| 기준 | HMAC | 디지털 서명 |
|---|---|---|
| 키 관리 | 대칭 키 하나 | 공개/개인 키 쌍 |
| 서명 주체 | 시스템 자체 (런타임) | 빌드 시스템(Build System)/관리자 |
| 변조 방지 | root도 키 없으면 위조 불가 (TPM sealed) | 개인 키 없으면 위조 불가 |
| xattr 갱신 | 자동 (커널이 재계산) | 수동 (evmctl sign) |
| 이식성 | 같은 시스템만 (키+inode 종속) | portable 서명 사용 시 이식 가능 |
| 성능 | 빠름 (HMAC-SHA1) | 느림 (RSA/EC 서명 검증) |
| 권장 사용 | 프로덕션 런타임 | 패키지 서명, 배포 |
EVM 디지털 서명 모드
EVM 디지털 서명 모드는 비대칭 키(RSA/EC)를 사용합니다. 빌드/패키징 시점에 개인 키로 서명하고, 런타임에 공개 키로 검증합니다. HMAC과 달리 검증 키만 있으면 되므로 시스템이 서명을 위조할 수 없어 보안이 더 강합니다.
| 서명 버전 | 형식 | 특징 |
|---|---|---|
| v2 | 커스텀 바이너리 헤더 | 기본, struct signature_v2_hdr |
| v5 (portable) | PKCS#7 래핑 | 이식가능, 파일시스템 간 이동 지원 |
/* security/integrity/integrity.h */
struct signature_v2_hdr {
uint8_t type; /* DIGSIG_VERSION_2 (0x02) */
uint8_t version; /* 서명 형식 버전 */
uint8_t hash_algo; /* 해시 알고리즘 ID */
uint32_t keyid; /* 키 식별자 (SubjectKeyIdentifier 하위 4바이트) */
uint16_t sig_size; /* 서명 크기 */
uint8_t sig[]; /* 실제 서명 데이터 */
} __packed;
서명 헤더 상세
security.evm xattr의 첫 번째 바이트가 서명 타입을 나타냅니다:
| 타입 바이트 | 의미 | 설명 |
|---|---|---|
0x01 | EVM_XATTR_HMAC | HMAC 값 (20바이트 SHA-1) |
0x02 | IMA_XATTR_DIGSIG | 디지털 서명 (signature_v2_hdr) |
0x03 | EVM_IMA_XATTR_DIGSIG | EVM 디지털 서명 (immutable) |
0x04 | IMA_XATTR_DIGEST_NG | 알고리즘 지정 해시 |
0x05 | EVM_XATTR_PORTABLE_DIGSIG | 이식가능 서명 (portable) |
# xattr 타입 확인 (첫 바이트)
getfattr -n security.evm -e hex /usr/bin/bash 2>/dev/null | grep "0x"
# 0x01... → HMAC
# 0x03... → immutable 서명
# 0x05... → portable 서명
getfattr -n security.ima -e hex /usr/bin/bash 2>/dev/null | grep "0x"
# 0x04... → digest-ng (해시)
# 0x03... → 디지털 서명
# EVM 서명 키 생성
openssl genrsa -out /etc/keys/evm-privkey.pem 2048
openssl rsa -in /etc/keys/evm-privkey.pem -pubout -out /etc/keys/evm-pubkey.pem
# X.509 인증서 생성 (커널 키링 로드용)
openssl req -new -x509 -key /etc/keys/evm-privkey.pem \
-out /etc/keys/evm-cert.x509 -days 3650 -subj '/CN=EVM/'
# 커널 키링에 공개 키 로드
keyctl padd asymmetric "" %keyring:.evm < /etc/keys/evm-cert.x509
# EVM 디지털 서명 생성
evmctl sign -k /etc/keys/evm-privkey.pem /usr/bin/bash
# 서명 검증
evmctl verify /usr/bin/bash
이식가능 서명 (Portable Signature)
기본 EVM 서명(immutable)은 inode 번호, generation 번호 등 파일시스템 고유 메타데이터를 포함하므로, 파일을 다른 파일시스템으로 복사하면 서명이 무효화됩니다. 이식가능 서명(portable signature)은 파일시스템 독립적인 메타데이터만 사용하여 배포판 간 파일 이동을 지원합니다.
# 이식가능 서명 생성
evmctl sign --portable -k /etc/keys/evm-privkey.pem /usr/bin/bash
# 이식가능 서명 확인 (타입 필드가 0x05)
getfattr -n security.evm -e hex /usr/bin/bash
# 0x05... (portable) vs 0x03... (immutable)
# RPM 빌드 시 이식가능 서명 포함
# %__ ima_sign_file_cmd evmctl sign --portable -k key.pem %{buildroot}%{_bindir}/*
Fedora/RHEL IMA: Fedora 39+와 RHEL 9에서는 RPM 패키지에 이식가능 서명을 기본으로 포함하는 실험적 지원이 진행 중입니다. rpm --import으로 IMA 서명 키를 시스템 키링에 로드하고, ima_appraise=enforce로 부팅하면 rpm 패키지 파일만 실행 가능합니다.
IMA + EVM + TPM 신뢰 체인
IMA/EVM과 TPM이 결합하면 부팅부터 런타임까지 이어지는 완전한 신뢰 체인(chain of trust)이 형성됩니다. UEFI Secure Boot → 부트로더(Bootloader) → 커널 → IMA 측정으로 이어지는 체인입니다.
# boot aggregate 확인 (측정 리스트 첫 번째 엔트리)
head -1 /sys/kernel/security/ima/ascii_runtime_measurements
# 10 sha256:xxxx ima-ng sha256:yyyy boot_aggregate
# boot aggregate 수동 계산 (TPM 2.0)
# SHA-256(PCR0 || PCR1 || ... || PCR9)
tpm2_pcrread sha256:0,1,2,3,4,5,6,7,8,9 -o pcrs.bin
sha256sum pcrs.bin
dm-verity 연동
dm-verity는 블록 장치 수준에서 Merkle 트리를 사용한 읽기 전용 무결성 검증을 제공합니다. IMA와 dm-verity를 결합하면 블록 레벨과 파일 레벨의 이중 검증이 가능합니다.
| 비교 항목 | dm-verity | IMA |
|---|---|---|
| 검증 단위 | 블록 (4KB) | 파일 |
| 검증 시점 | 블록 I/O 시 | 파일 open/exec/mmap 시 |
| 쓰기 지원 | 읽기 전용만 | 읽기/쓰기 모두 |
| 해시 저장 | 별도 파티션 (Merkle 트리) | xattr 또는 다이제스트 리스트 |
| TPM 연동 | root hash 서명 검증 | PCR extend, 원격 증명 |
| 대표 사용 | Android AVB, ChromeOS | RHEL, Fedora, Keylime |
# dm-verity 설정 (veritysetup)
veritysetup format /dev/sda2 /dev/sda3
# Root hash: 4a8c...f1d2 (이 값을 커널 cmdline에 전달)
# dm-verity 활성화
veritysetup open /dev/sda2 verified-root /dev/sda3 4a8c...f1d2
mount /dev/mapper/verified-root /mnt/root
# Android AVB (vbmeta에 root hash 포함)
# 커널 cmdline: dm="... verity ... root_hash=4a8c...f1d2"
# IMA와 dm-verity 결합: dm-verity 위에서 IMA 측정
# dm-verity가 블록 무결성 보장 + IMA가 파일 해시를 PCR에 기록
measure func=FILE_CHECK fsname=ext4 template=ima-ng
Android Verified Boot (AVB)와 IMA
Android는 dm-verity를 AVB(Android Verified Boot) 프레임워크의 핵심으로 사용합니다. vbmeta 파티션에 각 파티션의 dm-verity root hash를 서명하여 저장하고, 부트로더가 이를 검증합니다.
| AVB 구성요소 | 역할 | IMA 대응 |
|---|---|---|
vbmeta | 모든 파티션 해시 서명 저장 | IMA 다이제스트 리스트 |
dm-verity | 블록 단위 Merkle 검증 | IMA 파일 단위 해시 |
rollback protection | RPMB 카운터로 롤백(Rollback) 방지 | TPM monotonic counter |
chain of trust | 부트로더→vbmeta→파티션 | Secure Boot→IMA→PCR |
# dm-verity + IMA 결합 시나리오 (서버 환경)
# 읽기 전용 루트 (dm-verity 보호)
veritysetup format /dev/sda2 /dev/sda3
# Root hash: 4a8c3b...f1d2
# 부트 파라미터
# root=/dev/mapper/vroot ro
# dm="vroot,,0,ro,0 sectors verity ... root_hash=4a8c3b...f1d2"
# ima_policy=tcb ima_appraise=enforce
# dm-verity가 블록 무결성 보장
# + IMA가 실행 파일 해시를 TPM PCR에 기록
# + 원격 증명 서버가 PCR Quote로 전체 체인 검증
# dm-verity 상태 확인
dmsetup status vroot
# 0 sectors verity V ... (V=verified)
dm-verity vs IMA 선택: 읽기 전용 루트 파일시스템이라면 dm-verity가 더 효율적입니다(블록 I/O 시 자동 검증). 읽기-쓰기 파일시스템이나 개별 파일 수준 정책이 필요하면 IMA가 적합합니다. 최고 보안은 둘을 결합하여 사용합니다.
fs-verity 연동
fs-verity는 파일 단위로 Merkle 트리를 사용하여 읽기 전용 파일의 무결성을 검증합니다. dm-verity와 달리 전체 파티션이 아닌 개별 파일에 적용되며, ext4와 f2fs에서 지원합니다. IMA의 appraise_type=sigv3를 통해 fs-verity 다이제스트 기반 IMA 평가가 가능합니다.
| 기능 | 설명 |
|---|---|
fsverity enable | 파일에 Merkle 트리 추가 (이후 읽기 전용) |
fsverity measure | 파일의 fs-verity 다이제스트 출력 |
fsverity sign | 다이제스트에 대한 PKCS#7 서명 생성 |
| IMA sigv3 | IMA가 fs-verity 다이제스트를 appraise에 사용 |
# fs-verity 활성화 (ext4)
tune2fs -O verity /dev/sda1
# 파일에 fs-verity 적용
fsverity enable /usr/bin/bash
# 이후 파일은 읽기 전용 (쓰기 시도 시 -ETXTBSY)
# fs-verity 다이제스트 확인
fsverity measure /usr/bin/bash
# sha256:3b5a7c...f1d2 /usr/bin/bash
# fs-verity 서명 생성
fsverity sign /usr/bin/bash fsverity.sig \
--key=/etc/keys/fsverity-privkey.pem \
--cert=/etc/keys/fsverity-cert.pem
# 서명된 fs-verity 내장 설정
fsverity enable /usr/bin/bash --signature=fsverity.sig
# IMA 정책에서 fs-verity 기반 appraise
# appraise func=BPRM_CHECK appraise_type=sigv3
fs-verity vs IMA 해시: fs-verity는 파일 내용의 Merkle root hash를 사용하므로 전체 파일을 읽지 않고도 부분 검증이 가능합니다 (on-demand 검증). 반면 IMA는 전체 파일 해시를 계산합니다. 대용량 파일이 많은 환경에서 fs-verity가 성능상 유리합니다.
fs-verity + IMA 통합 상세
커널 5.15+에서 IMA는 appraise_type=sigv3를 통해 fs-verity 다이제스트 기반 평가를 지원합니다. 이 모드에서 IMA는 파일의 전체 해시를 직접 계산하는 대신, fs-verity 서브시스템이 제공하는 Merkle root hash를 사용합니다.
# fs-verity + IMA 정책 예시
# fs-verity 다이제스트 기반 IMA appraise (sigv3)
appraise func=BPRM_CHECK appraise_type=sigv3
# security.ima xattr에 fs-verity 다이제스트 서명 저장
# type = 0x05 (IMA_VERITY_DIGSIG)
evmctl ima_sign --verity -k /etc/keys/ima-privkey.pem /usr/bin/bash
# fs-verity 활성화 후 IMA 서명
fsverity enable /usr/bin/bash
evmctl ima_sign --verity -a sha256 -k /etc/keys/ima-privkey.pem /usr/bin/bash
/* security/integrity/ima/ima_appraise.c — fs-verity 지원 */
static int ima_get_verity_digest(struct integrity_iint_cache *iint,
struct ima_max_digest_data *hash)
{
enum hash_algo alg;
int digest_len;
/* fs-verity에서 Merkle root hash 가져오기 */
digest_len = fsverity_get_digest(iint->inode,
hash->digest,
NULL, &alg);
if (digest_len) {
hash->hdr.algo = alg;
hash->hdr.length = digest_len;
}
return digest_len;
}
| 비교 항목 | IMA 전체 해시 | IMA + fs-verity (sigv3) |
|---|---|---|
| 해시 계산 | 파일 전체 읽기 필요 | fs-verity Merkle root만 사용 |
| 파일 열기 성능 | O(n) — 파일 크기 비례 | O(1) — 메타데이터만 |
| 읽기 검증 | 열기 시 1회 | 모든 페이지 읽기마다 (on-demand) |
| 쓰기 지원 | 가능 (재해싱) | 불가 (읽기 전용) |
| xattr 타입 | 0x03 (IMA_XATTR_DIGSIG) | 0x05 (IMA_VERITY_DIGSIG) |
원격 증명 (Remote Attestation)
원격 증명은 신뢰할 수 없는 원격 시스템의 무결성을 검증하는 프로토콜입니다. IMA 측정 리스트와 TPM Quote를 결합하여, 원격 서버가 대상 시스템에서 실행된 모든 소프트웨어의 무결성을 검증할 수 있습니다.
Keylime 설정
# Keylime 설치 (Python 패키지)
pip install keylime
# 또는 배포판 패키지
dnf install keylime # Fedora/RHEL
# Keylime Verifier 시작
keylime_verifier
# Keylime Registrar 시작
keylime_registrar
# Agent 등록 (대상 시스템에서)
keylime_agent
# Tenant CLI로 에이전트 추가 (IMA 검증 활성화)
keylime_tenant -c add \
--uuid d432fbb3-d2f1-4a97-9ef7-75bd81c00000 \
-t 192.168.1.100 \
--ima_sign_verification_keys /etc/keys/ima-cert.pem \
--ima_allowlist /etc/keylime/allowlist.txt
# IMA allowlist 생성 (신뢰할 파일 해시 목록)
# sha256:3b5a... /usr/bin/bash
# sha256:7c2d... /usr/lib64/libc.so.6
create_allowlist.sh /etc/keylime/allowlist.txt
Keylime 아키텍처: Keylime은 3개 구성요소로 동작합니다. Registrar는 에이전트의 TPM EK/AIK 인증서를 등록하고, Agent는 대상 시스템에서 TPM Quote를 생성하며, Verifier는 주기적으로 Quote와 IMA 측정 리스트를 검증합니다. 검증 실패 시 revocation 스크립트를 실행하여 자동 대응합니다.
원격 증명 검증 알고리즘
검증 서버(Verifier)는 다음 단계로 측정 리스트의 진정성을 확인합니다:
- TPM Quote 검증: AIK(Attestation Identity Key)로 서명된 Quote를 검증하여 PCR 값이 TPM에서 직접 생성되었음을 확인합니다.
- 측정 리스트 리플레이: 수신한 측정 리스트의 각 엔트리를 순서대로 해싱하고 PCR extend 연산을 시뮬레이션합니다.
- PCR 비교: 리플레이 결과 PCR 값과 Quote에 포함된 PCR 값을 비교합니다. 일치하면 측정 리스트가 변조되지 않았음이 증명됩니다.
- allowlist 매칭: 측정 리스트의 각 엔트리 해시를 신뢰할 수 있는 해시 목록(allowlist)과 비교합니다.
- 서명 검증 (옵션):
ima-sig템플릿을 사용하면 각 엔트리의 서명도 검증할 수 있습니다.
/* 원격 증명 검증 의사코드 (Python/Go 구현 기반) */
/* 1. PCR 리플레이 */
pcr_simulated = bytes(32) /* SHA-256 크기, 0으로 초기화 */
for entry in measurement_list:
/* template_hash = SHA-256(filedata_hash || filename) */
template_hash = entry.template_hash
/* PCR extend 시뮬레이션 */
pcr_simulated = SHA256(pcr_simulated + template_hash)
/* 2. Quote의 PCR 값과 비교 */
if pcr_simulated != quote.pcr_values[10]:
FAIL("PCR mismatch — 측정 리스트 변조 의심")
/* 3. allowlist 확인 */
for entry in measurement_list:
if entry.filedata_hash not in allowlist:
ALERT("미승인 파일: %s", entry.filename)
대안 원격 증명 도구
| 도구 | 개발사 | 특징 |
|---|---|---|
| Keylime | MIT/CNCF | Python/Rust, IMA 통합, CNCF 프로젝트 |
| go-attestation | Go 라이브러리, GCE 통합 | |
| IBM ACS | IBM | 엔터프라이즈, TPM 2.0 전용 |
| ISECL | Intel | Intel Security Libraries, SGX 통합 |
| RATS | IETF | 표준 프로토콜 (RFC 9334) |
vTPM 주의: 클라우드 환경에서 vTPM(가상 TPM)을 사용하면 하이퍼바이저(Hypervisor)가 vTPM을 제어할 수 있어 하드웨어 TPM보다 신뢰 수준이 낮습니다. 높은 보안이 필요한 환경에서는 하드웨어 TPM 또는 Intel TXT/AMD SEV와 결합한 DRTM(Dynamic Root of Trust for Measurement)을 고려하세요.
LoadPin & IPE
LoadPin과 IPE(Integrity Policy Enforcement)는 IMA/EVM과 함께 커널의 파일 무결성을 강화하는 보조 메커니즘입니다.
LoadPin
LoadPin은 커널이 읽는 파일(모듈, 펌웨어, kexec 이미지)의 출처를 고정합니다. 첫 번째 커널 파일 로드 시 해당 파일시스템의 root를 "고정(pin)"하고, 이후 모든 커널 파일 로드는 동일한 root에서만 허용합니다.
| 설정 | 설명 |
|---|---|
CONFIG_SECURITY_LOADPIN=y | LoadPin LSM 활성화 |
loadpin.enforce=1 | 부트 파라미터: 강제 모드 |
loadpin.exclude= | 제외할 파일 타입 (firmware 등) |
/* security/loadpin/loadpin.c */
static int loadpin_read_file(struct file *file,
enum kernel_read_file_id id,
bool contents)
{
struct super_block *load_root = READ_ONCE(pinned_root);
/* 첫 번째 로드: root 고정 */
if (!load_root) {
cmpxchg(&pinned_root, NULL, file->f_path.mnt->mnt_sb);
return 0;
}
/* 이후 로드: 고정된 root와 비교 */
if (file->f_path.mnt->mnt_sb != load_root)
return -EPERM; /* 다른 파일시스템 → 거부 */
return 0;
}
IPE (Integrity Policy Enforcement)
IPE는 커널 6.x에서 도입된 새로운 LSM으로, dm-verity 검증 파티션에서 온 파일만 실행을 허용하는 정책을 시행합니다.
# IPE 정책 예시
policy_name="example" policy_version=0.0.1
DEFAULT op=EXECUTE action=DENY
DEFAULT op=KERNEL_READ action=DENY
# dm-verity 검증된 볼륨의 파일만 실행 허용
op=EXECUTE dmverity_roothash=4a8c...f1d2 action=ALLOW
op=KERNEL_READ dmverity_roothash=4a8c...f1d2 action=ALLOW
# fs-verity 검증 파일도 허용
op=EXECUTE fsverity_digest=sha256:3b5a...c2f1 action=ALLOW
LoadPin과 IMA 비교 활용
| 시나리오 | 권장 조합 | 설명 |
|---|---|---|
| 임베디드 (읽기 전용 rootfs) | dm-verity + LoadPin | 단순하고 오버헤드(Overhead) 최소 |
| 서버 (RHEL/Fedora) | IMA + EVM + 원격 증명 | 유연한 정책, TPM 기반 증명 |
| 컨테이너 호스트 | IMA + dm-verity + IPE | 이미지 무결성 + 실행 제어 |
| 클라우드 VM | IMA + vTPM + Keylime | 가상 TPM 기반 원격 증명 |
| 데스크탑 | IMA measure (tcb) | 측정만, 평가는 선택적 |
# LoadPin + IMA 동시 사용 (커널 cmdline)
loadpin.enforce=1 loadpin.exclude=firmware \
ima_policy=tcb ima_appraise=enforce ima_hash=sha256
# IPE 정책 로드
echo "policy_name=prod policy_version=1.0.0
DEFAULT op=EXECUTE action=DENY
DEFAULT op=KERNEL_READ action=DENY
op=EXECUTE boot_verified=TRUE action=ALLOW
op=KERNEL_READ boot_verified=TRUE action=ALLOW" \
> /sys/kernel/security/ipe/new_policy
# IPE 정책 활성화
echo 1 > /sys/kernel/security/ipe/prod/active
evmctl 명령어 레퍼런스
evmctl은 IMA/EVM 관련 xattr을 관리하는 사용자 공간(User Space) 도구로, ima-evm-utils 패키지에 포함됩니다.
| 명령어 | 설명 | 예시 |
|---|---|---|
ima_hash | 파일 해시를 security.ima에 저장 | evmctl ima_hash /usr/bin/bash |
ima_sign | 파일 해시에 서명하여 security.ima에 저장 | evmctl ima_sign -k key.pem /usr/bin/bash |
ima_verify | security.ima 서명 검증 | evmctl ima_verify /usr/bin/bash |
ima_measurement | 측정 리스트 검증 | evmctl ima_measurement ascii_runtime_measurements |
hmac | EVM HMAC 생성 | evmctl hmac /usr/bin/bash |
sign | EVM 디지털 서명 생성 | evmctl sign -k key.pem /usr/bin/bash |
verify | EVM 서명 검증 | evmctl verify /usr/bin/bash |
import | 키를 커널 키링에 로드 | evmctl import cert.x509 %keyring:.ima |
실전 워크플로
# 1. 키 쌍 생성
openssl genrsa -out /etc/keys/ima-privkey.pem 2048
openssl req -new -x509 -key /etc/keys/ima-privkey.pem \
-out /etc/keys/ima-cert.x509 -days 3650 -subj '/CN=IMA/'
# 2. 공개 키를 .ima 키링에 로드
evmctl import /etc/keys/ima-cert.x509 %keyring:.ima
# 3. 시스템 전체 파일에 IMA 서명 적용
find /usr/bin /usr/sbin /usr/lib64 -type f -exec \
evmctl ima_sign -k /etc/keys/ima-privkey.pem -a sha256 {} \;
# 4. EVM 서명도 함께 적용
find /usr/bin /usr/sbin /usr/lib64 -type f -exec \
evmctl sign --portable -k /etc/keys/evm-privkey.pem {} \;
# 5. 서명 검증
evmctl ima_verify -k /etc/keys/ima-cert.x509 /usr/bin/bash
evmctl verify -k /etc/keys/evm-cert.x509 /usr/bin/bash
# 6. 해시 알고리즘 지정
evmctl ima_hash -a sha512 /usr/bin/bash
# 7. 재귀적 서명 (디렉터리 전체)
evmctl ima_sign -r -k /etc/keys/ima-privkey.pem /usr/bin/
커널 설정 종합
| 설정 옵션 | 설명 | 기본 |
|---|---|---|
| IMA 핵심 | ||
CONFIG_INTEGRITY | 무결성 서브시스템 루트 | y |
CONFIG_IMA | IMA 활성화 | y |
CONFIG_IMA_MEASURE_PCR_IDX | 기본 PCR 번호 | 10 |
CONFIG_IMA_DEFAULT_HASH | 기본 해시 알고리즘 | sha256 |
CONFIG_IMA_DEFAULT_TEMPLATE | 기본 템플릿 | ima-ng |
CONFIG_IMA_APPRAISE | IMA 평가 모드 | y |
CONFIG_IMA_APPRAISE_BOOTPARAM | 부트 파라미터로 appraise 모드 설정 | y |
CONFIG_IMA_WRITE_POLICY | 정책 재기록 허용 | n |
CONFIG_IMA_READ_POLICY | 정책 읽기 허용 | y |
CONFIG_IMA_APPRAISE_MODSIG | 모듈 appended 서명 지원 | n |
CONFIG_IMA_TRUSTED_KEYRING | .ima 키링에 system keyring 제한 | y |
CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY | 빌트인/보조 키로 서명된 키만 .ima에 추가 | y |
| EVM | ||
CONFIG_EVM | EVM 활성화 | y |
CONFIG_EVM_ATTR_FSUUID | HMAC에 파일시스템 UUID 포함 | y |
CONFIG_EVM_EXTRA_SMACK_XATTRS | SMACK xattr 추가 보호 | n |
CONFIG_EVM_ADD_XATTRS | EVM 보호 xattr 동적 추가 | n |
| 지원 서브시스템 | ||
CONFIG_INTEGRITY_SIGNATURE | 무결성 서브시스템 서명 지원 | y |
CONFIG_INTEGRITY_ASYMMETRIC_KEYS | 비대칭 키 지원 | y |
CONFIG_INTEGRITY_TRUSTED_KEYRING | 신뢰 키링 | y |
CONFIG_INTEGRITY_PLATFORM_KEYRING | 플랫폼 키링 (UEFI db/MOK) | y |
CONFIG_INTEGRITY_MACHINE_KEYRING | 머신 키링 (MOK) | y |
CONFIG_FS_VERITY | fs-verity 지원 | n |
CONFIG_DM_VERITY | dm-verity 지원 | m |
CONFIG_SECURITY_LOADPIN | LoadPin LSM | n |
CONFIG_IPE | IPE LSM (6.x+) | n |
# IMA/EVM 최소 설정 확인
grep -E "^CONFIG_(IMA|EVM|INTEGRITY)" /boot/config-$(uname -r)
# 권장 프로덕션 설정
# CONFIG_IMA=y
# CONFIG_IMA_APPRAISE=y
# CONFIG_IMA_DEFAULT_HASH="sha256"
# CONFIG_IMA_DEFAULT_TEMPLATE="ima-sig"
# CONFIG_IMA_APPRAISE_BOOTPARAM=y
# CONFIG_IMA_TRUSTED_KEYRING=y
# CONFIG_EVM=y
# CONFIG_EVM_ATTR_FSUUID=y
# CONFIG_INTEGRITY_SIGNATURE=y
# CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
배포판별 기본 설정
| 배포판 | IMA | EVM | 기본 정책 | appraise 모드 |
|---|---|---|---|---|
| RHEL 9 | y | y | tcb (비활성) | off |
| Fedora 39+ | y | y | tcb 실험적 | log (실험) |
| Ubuntu 22.04+ | y | n (모듈) | 비활성 | off |
| SUSE SLES 15 | y | y | 비활성 | off |
| Debian 12 | y | n | 비활성 | off |
| ChromeOS | y | n | LoadPin + dm-verity | N/A |
| Android (AOSP) | 부분적 | n | dm-verity + AVB | N/A |
RHEL에서 IMA 활성화: RHEL 9에서 IMA를 활성화하려면 grubby --update-kernel=ALL --args="ima_policy=appraise_tcb ima_appraise=fix"로 fix 모드 부팅 후 evmctl로 서명 작업을 수행하고, 이후 ima_appraise=enforce로 전환합니다.
initramfs에서 IMA/EVM 초기화 순서
IMA/EVM을 enforce 모드로 사용하려면 initramfs 단계에서 올바른 순서로 초기화해야 합니다:
# dracut IMA/EVM 초기화 스크립트 예시
# /usr/lib/dracut/modules.d/98integrity/module-setup.sh
# 1단계: EVM 키 로드
keyctl add trusted evm-key \
"load $(cat /etc/keys/evm-trusted.blob)" @u
# 2단계: IMA 공개 키 로드
evmctl import /etc/keys/ima-cert.x509 %keyring:.ima
# 3단계: EVM 활성화 (HMAC 모드)
echo 1 > /sys/kernel/security/evm
# 4단계: IMA 커스텀 정책 로드 (선택)
cat /etc/ima/ima-policy > /sys/kernel/security/ima/policy
# 주의: 이 순서를 지키지 않으면 enforce 모드에서 부팅 실패
# - EVM 키 없이 enforce → 모든 파일 접근 거부
# - IMA 정책 로드 전 EVM 활성화 → 정상 동작
# - EVM 활성화 전 IMA 정책 로드 → 정상 동작
securityfs 인터페이스 종합
| 경로 | 읽기/쓰기 | 설명 |
|---|---|---|
/sys/kernel/security/ima/ascii_runtime_measurements | R | 텍스트 측정 리스트 |
/sys/kernel/security/ima/binary_runtime_measurements | R | 바이너리 측정 리스트 (원격 증명용) |
/sys/kernel/security/ima/runtime_measurements_count | R | 측정 엔트리 수 |
/sys/kernel/security/ima/violations | R | 무결성 위반 카운터 |
/sys/kernel/security/ima/policy | R/W | 정책 읽기/추가 |
/sys/kernel/security/ima/ima_hash | R | 현재 해시 알고리즘 |
/sys/kernel/security/ima/ima_template | R | 현재 템플릿 |
/sys/kernel/security/ima/ima_template_fmt | R | 현재 템플릿 형식 |
/sys/kernel/security/evm | R/W | EVM 상태 (0/1/2/6) |
부트 파라미터 종합
| 파라미터 | 값 | 설명 |
|---|---|---|
ima_policy= | tcb | 실행 파일/라이브러리/모듈 측정 (기본 정책) |
appraise_tcb | root 소유 파일 평가 | |
critical_data | 모듈/펌웨어/kexec만 측정 | |
secure_boot | Secure Boot 키 기반 평가 | |
ima_appraise= | enforce | 검증 실패 시 접근 거부 (기본) |
fix | xattr 자동 생성/업데이트 | |
log | 로그만 남기고 허용 | |
off | 평가 비활성화 | |
ima_hash= | sha256 | IMA 해시 알고리즘 |
sha512 | ||
sha1 | 레거시 (비권장) | |
ima_template= | ima-ng | 기본 템플릿 |
ima-sig | 서명 포함 템플릿 | |
ima-buf | 버퍼 데이터 템플릿 | |
ima_canonical_fmt | (플래그) | 리틀 엔디안(Endianness) 정규 형식 사용 |
evm= | fix | EVM fix 모드 (초기 설정 시) |
ima_tcb | (플래그) | ima_policy=tcb와 동일 (레거시) |
# /etc/default/grub 예시 (RHEL/Fedora)
GRUB_CMDLINE_LINUX="ima_policy=appraise_tcb ima_appraise=enforce \
ima_hash=sha256 ima_template=ima-sig"
# 초기 설정 시 (xattr 생성 모드)
GRUB_CMDLINE_LINUX="ima_policy=appraise_tcb ima_appraise=fix \
evm=fix ima_hash=sha256"
# GRUB 설정 적용
grub2-mkconfig -o /boot/grub2/grub.cfg
초기 설정 주의: ima_appraise=enforce로 부팅하기 전에 반드시 ima_appraise=fix 모드에서 모든 파일에 security.ima xattr을 생성해야 합니다. xattr 없이 enforce 모드로 부팅하면 시스템이 부팅되지 않을 수 있습니다.
IMA/EVM 초기 배포 절차 (단계별)
프로덕션 서버에 IMA/EVM을 처음 배포할 때의 권장 절차입니다:
# ================================================
# Phase 1: 키 생성 (오프라인 환경)
# ================================================
# IMA 서명 키 (RSA 2048 또는 EC P-256)
openssl ecparam -genkey -name prime256v1 -out /etc/keys/ima-privkey.pem
openssl req -new -x509 -key /etc/keys/ima-privkey.pem \
-out /etc/keys/ima-cert.x509 -days 3650 \
-subj '/O=MyOrg/CN=IMA Signing Key/'
# EVM 서명 키
openssl ecparam -genkey -name prime256v1 -out /etc/keys/evm-privkey.pem
openssl req -new -x509 -key /etc/keys/evm-privkey.pem \
-out /etc/keys/evm-cert.x509 -days 3650 \
-subj '/O=MyOrg/CN=EVM Signing Key/'
# ================================================
# Phase 2: fix 모드 부팅 (xattr 생성)
# ================================================
# /etc/default/grub:
# GRUB_CMDLINE_LINUX="ima_policy=appraise_tcb ima_appraise=fix
# evm=fix ima_hash=sha256 ima_template=ima-sig"
grub2-mkconfig -o /boot/grub2/grub.cfg
reboot
# ================================================
# Phase 3: 파일 서명 (fix 모드에서)
# ================================================
# 커널 키링에 키 로드
evmctl import /etc/keys/ima-cert.x509 %keyring:.ima
# EVM trusted key 생성 및 활성화
keyctl add trusted evm-key "new 32" @u
echo 1 > /sys/kernel/security/evm
# 시스템 전체 IMA 서명
find /usr /etc /boot /lib /sbin /bin -type f 2>/dev/null | \
xargs -P4 -n100 evmctl ima_sign -k /etc/keys/ima-privkey.pem \
-a sha256 2>/dev/null
# EVM 이식가능 서명
find /usr /etc /boot /lib /sbin /bin -type f 2>/dev/null | \
xargs -P4 -n100 evmctl sign --portable \
-k /etc/keys/evm-privkey.pem 2>/dev/null
# ================================================
# Phase 4: enforce 모드 전환
# ================================================
# /etc/default/grub 수정:
# GRUB_CMDLINE_LINUX="ima_policy=appraise_tcb ima_appraise=enforce
# ima_hash=sha256 ima_template=ima-sig"
grub2-mkconfig -o /boot/grub2/grub.cfg
# EVM trusted key 백업 (중요!)
keyctl pipe $(keyctl search @u trusted evm-key) > /etc/keys/evm-trusted.blob
chmod 600 /etc/keys/evm-trusted.blob
reboot
롤백 준비: enforce 모드 전환 전에 반드시 rescue 커널이나 USB 부팅 미디어를 준비하세요. 서명이 누락된 파일이 있으면 시스템이 부팅 불가 상태에 빠질 수 있습니다. ima_appraise=log 모드에서 먼저 테스트하는 것을 권장합니다.
컴플라이언스 매핑(Mapping)
IMA/EVM은 다양한 보안 인증과 컴플라이언스 표준의 요구사항을 충족합니다.
| 표준 | 관련 요구사항 | IMA/EVM 충족 방법 |
|---|---|---|
| FIPS 140-3 | 암호 모듈 무결성 검증 | 커널 암호 모듈의 IMA 서명 검증, HMAC 기반 무결성 테스트 |
| Common Criteria (CC) | EAL4+ 무결성 보호 (FIA, FPT) | IMA appraise로 실행 파일 무결성, EVM으로 메타데이터 보호 |
| NIST SP 800-155 | BIOS 무결성 측정 가이드라인 | IMA가 BIOS→부트로더→커널→사용자공간까지 체인 확장 |
| STIG (DISA) | V-230264: FIPS 모드, V-230502: 파일 무결성 | ima_appraise=enforce + fips=1 |
| CIS Benchmark | 파일 무결성 모니터링 (1.4.1) | IMA measure + 원격 증명으로 지속적 모니터링 |
| PCI-DSS v4 | 11.5: 파일 무결성 모니터링 | IMA audit + 측정 리스트 모니터링 |
| NIST SP 800-53 | SI-7: 소프트웨어/펌웨어/정보 무결성 | IMA measure/appraise + EVM 서명 |
| TCG (Trusted Computing) | TPM 기반 플랫폼 무결성 | IMA+TPM으로 TCG 사양 준수 측정/증명 |
# FIPS 140-3 + IMA 설정 예시
# 커널 cmdline:
# fips=1 ima_policy=appraise_tcb ima_appraise=enforce ima_hash=sha256
# STIG 준수 확인
fips-mode-setup --check
grep ima_appraise /proc/cmdline
# CIS 파일 무결성 체크
cat /sys/kernel/security/ima/violations
# 0이 아니면 무결성 위반 발생
# 원격 증명 기반 지속적 모니터링 (PCI-DSS 11.5)
keylime_tenant -c add --ima_sign_verification_keys /etc/keys/ima-cert.pem \
--uuid $(cat /sys/class/dmi/id/product_uuid)
컴플라이언스별 IMA/EVM 구성 가이드
| 컴플라이언스 | 필수 커널 설정 | 부트 파라미터 | 추가 요구사항 |
|---|---|---|---|
| FIPS 140-3 | CONFIG_IMA=yCONFIG_CRYPTO_FIPS=y | fips=1 ima_hash=sha256 | FIPS 인증 암호 모듈만 사용 |
| CC EAL4+ | CONFIG_IMA_APPRAISE=yCONFIG_EVM=y | ima_appraise=enforce | 전체 파일 서명, EVM 활성화 |
| STIG | CONFIG_IMA=y | ima_policy=appraise_tcb | aide 또는 IMA 측정 리스트 모니터링 |
| CIS Level 2 | CONFIG_IMA=y | ima_policy=tcb | 파일 무결성 모니터링 도구 |
| PCI-DSS v4 | CONFIG_IMA=yCONFIG_AUDIT=y | ima_policy=tcbaudit=1 | 변경 탐지 메커니즘, 주간 리포트 |
# FIPS + IMA 종합 체크 스크립트
#!/bin/bash
echo "=== FIPS 모드 확인 ==="
cat /proc/sys/crypto/fips_enabled
echo "=== IMA 상태 확인 ==="
echo "측정 엔트리: $(cat /sys/kernel/security/ima/runtime_measurements_count)"
echo "위반 수: $(cat /sys/kernel/security/ima/violations)"
echo "해시 알고리즘: $(cat /sys/kernel/security/ima/ima_hash 2>/dev/null || echo N/A)"
echo "템플릿: $(cat /sys/kernel/security/ima/ima_template 2>/dev/null || echo N/A)"
echo "=== EVM 상태 ==="
cat /sys/kernel/security/evm
echo "=== TPM PCR 10 ==="
tpm2_pcrread sha256:10 2>/dev/null || echo "TPM 접근 실패"
echo "=== 키링 상태 ==="
keyctl show %keyring:.ima 2>/dev/null
keyctl show %keyring:.evm 2>/dev/null
echo "=== Audit IMA 이벤트 (최근 10건) ==="
ausearch -m INTEGRITY_DATA -m INTEGRITY_STATUS -ts recent 2>/dev/null | tail -10
트러블슈팅
| 증상 | 원인 | 해결 |
|---|---|---|
부팅 중 Permission denied 폭주 | ima_appraise=enforce + xattr 미설정 | ima_appraise=fix로 부팅 후 evmctl ima_sign |
security.ima: unable to set | 읽기 전용 파일시스템 또는 xattr 미지원 | mount -o remount,rw, tune2fs -O user_xattr |
EVM: verification failed | EVM 키 미로드 상태에서 접근 | echo 1 > /sys/kernel/security/evm 후 재시도 |
| 측정 리스트가 비어있음 | IMA 정책 미로드 | ima_policy=tcb 부트 파라미터 추가 |
appraise: MISSING | security.ima xattr 없음 | evmctl ima_hash 또는 evmctl ima_sign |
appraise: FAIL | 파일 변경 후 xattr 미갱신 | evmctl ima_sign -k key.pem 파일경로 |
| TPM PCR 값 불일치 | TPM 접근 실패 또는 tpm2-tss 문제 | systemctl restart tpm2-abrmd, TPM 드라이버 확인 |
Key was rejected by service | 서명 키가 .ima/.evm 키링에 없음 | evmctl import cert.x509 %keyring:.ima |
| initramfs 내 파일 appraise 실패 | initramfs 재생성 시 서명 미포함 | dracut --rebuild --force + IMA 서명 |
violations 카운터 증가 | 파일 변경 후 측정 전 접근 | 정책 순서 점검, TOE(Time of Evaluation) 확인 |
디버그 절차
# 1. IMA 상태 전반 확인
cat /sys/kernel/security/ima/ascii_runtime_measurements | wc -l
cat /sys/kernel/security/ima/violations
cat /sys/kernel/security/ima/runtime_measurements_count
# 2. 현재 로드된 정책 확인
cat /sys/kernel/security/ima/policy 2>/dev/null || \
echo "CONFIG_IMA_READ_POLICY=n 또는 정책 미로드"
# 3. EVM 상태 확인
cat /sys/kernel/security/evm
# 0: 비활성, 1: HMAC, 2: 서명, 6: HMAC+서명
# 4. xattr 상세 확인
getfattr -d -m security /usr/bin/bash
getfattr -n security.ima -e hex /usr/bin/bash
getfattr -n security.evm -e hex /usr/bin/bash
# 5. audit 로그에서 IMA 이벤트 검색
ausearch -m INTEGRITY_DATA -m INTEGRITY_STATUS \
-m INTEGRITY_RULE -m INTEGRITY_PCR -ts recent
# 6. dmesg에서 IMA/EVM 메시지 확인
dmesg | grep -iE "ima|evm|integrity"
# 7. 키링 상태 확인
keyctl show %keyring:.ima
keyctl show %keyring:.evm
keyctl show %keyring:.builtin_trusted_keys
keyctl show %keyring:.platform
# 8. TPM 상태 확인
tpm2_pcrread sha256:10
tpm2_getcap properties-fixed | grep -i manufacturer
성능 영향과 최적화
IMA/EVM은 파일 접근 경로에 암호화 연산을 추가하므로 성능 영향이 있습니다. 특히 ima_appraise=enforce 모드에서 대량의 파일을 여는 워크로드(예: 컴파일, 컨테이너 이미지 풀)에서 체감됩니다.
| 시나리오 | 성능 영향 | 최적화 방법 |
|---|---|---|
| IMA measure만 (tcb) | 1~3% | dont_measure로 가상 FS 제외 |
| IMA appraise (enforce) | 3~8% | iint 캐시, dont_appraise 활용 |
| EVM HMAC | 추가 1~2% | HMAC-SHA1 (SHA256보다 빠름) |
| 대용량 파일 해싱 | I/O 바운드 | 비동기 해시 (ahash), fs-verity 전환 |
| 컨테이너 이미지 풀 | 5~15% | 다이제스트 리스트, 이미지 사전 서명 |
# IMA 성능 프로파일링
# 1. 파일 열기 지연 측정 (strace)
strace -T -e trace=open,openat ls /usr/bin/ 2>&1 | tail
# 2. IMA 해시 계산 시간 (ftrace)
echo 1 > /sys/kernel/debug/tracing/events/ima/ima_hash/enable
cat /sys/kernel/debug/tracing/trace_pipe
# 3. iint 캐시 히트율 확인
cat /proc/slabinfo | grep ima_iint
# 4. 비동기 해시 사용 확인
grep -r "ahash" /sys/kernel/security/ima/ 2>/dev/null
# 5. 정책 최적화 — 불필요한 파일시스템 제외
dont_measure fsmagic=0x9fa0 # proc
dont_measure fsmagic=0x62656572 # sysfs
dont_measure fsmagic=0x64626720 # debugfs
dont_measure fsmagic=0x01021994 # tmpfs
dont_measure fsmagic=0x73636673 # securityfs
dont_measure fsmagic=0xcafe4a11 # bpf
dont_measure fsmagic=0x27e0eb # cgroup
dont_measure fsmagic=0x63677270 # cgroup2
dont_measure fsmagic=0x19800202 # mqueue
dont_measure fsmagic=0x858458f6 # ramfs
dont_measure fsmagic=0x6e736673 # nsfs
성능 최적화 핵심: IMA의 성능 영향을 최소화하려면 (1) 가상 파일시스템(VFS)을 dont_measure/dont_appraise로 제외하고, (2) CONFIG_IMA_DEFAULT_HASH=sha256을 사용하며(SHA-512보다 빠름), (3) 다이제스트 리스트를 활용하여 xattr 조회 횟수를 줄이세요. fs-verity 지원 환경에서는 sigv3 모드가 대용량 파일에서 가장 빠릅니다.