๐Ÿ›ก๏ธ Linux Stackable LSM Architecture Kernel 6.12+

๋Œ€๊ธฐ ์ค‘ (PAUSED)

๐Ÿ”— Stacked Hook Execution Pipeline

๋ฆฌ๋ˆ…์Šค ์ปค๋„์˜ LSM ํ›„ํฌ๋Š” ๋‹จ์ผ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๊ฐ€ ์•„๋‹Œ ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ(hlist_head)๋กœ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ๋ณด์•ˆ ๊ฒ€์‚ฌ ์š”์ฒญ ๋ฐœ์ƒ ์‹œ ์ฒด์ธ์— ๋“ฑ๋ก๋œ ๋ชจ๋“ˆ๋“ค์ด ์ˆœ์ฐจ์ ์œผ๋กœ ํ˜ธ์ถœ๋˜๋ฉฐ, ์–ด๋А ํ•œ ๋ชจ๋“ˆ์ด๋ผ๋„ ์Œ์ˆ˜ ์—๋Ÿฌ(-EPERM, -EACCES)๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ฆ‰์‹œ ๊ฑฐ๋ถ€(Fail-Closed)๋˜๊ณ  ํ›„์† ํ‰๊ฐ€๋Š” ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

Kernel Syscall security_hook [1] Capability Standard DAC/Root [2] Landlock Unpriv Sandboxing [3] Lockdown Kernel Tamper Block [4] Yama Ptrace Protection Final Decision PENDING

๐Ÿ“œ ์ปค๋„ ํ›„ํฌ ํ‰๊ฐ€ ๋กœ๊ทธ (dmesg)

[ 0.000000] LSM: Initializing: capability,landlock,lockdown,yama,bpf
[ 0.000000] LSM: Registered 5 security modules in order.
[Ready] ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์„ ํƒํ•˜๊ณ  [๋‹จ๊ณ„๋ณ„ ์‹คํ–‰] ๋˜๋Š” [์ž๋™ ์‹คํ–‰]์„ ํด๋ฆญํ•˜์‹ญ์‹œ์˜ค.

๐Ÿ’ก ํ›„ํฌ ์ฒด์ธ ํ‰๊ฐ€ ๋ฉ”์ปค๋‹ˆ์ฆ˜

/* include/linux/lsm_hook_defs.h */
#define call_int_hook(FUNC, IRC, ...) ({       \
    int RC = IRC;                              \
    struct security_hook_list *P;              \
    hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \
        RC = P->hook.FUNC(__VA_ARGS__);        \
        if (RC != 0)                           \
            break; /* Fail-Closed! ์ฆ‰์‹œ ์ค‘๋‹จ */ \
    }                                          \
    RC;                                        \
})

์ฒด์ธ์— ๋“ฑ๋ก๋œ ๋ชจ๋“  LSM์ด 0(์„ฑ๊ณต)์„ ๋ฐ˜ํ™˜ํ•ด์•ผ๋งŒ ์ ‘๊ทผ์ด ์ตœ์ข… ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. ์–ด๋А ํ•˜๋‚˜๋ผ๋„ 0์ด ์•„๋‹Œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๊ทธ ์ฆ‰์‹œ ๋ฃจํ”„๊ฐ€ break๋˜์–ด ํ›„์† ๋ชจ๋“ˆ์€ ํ‰๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๐Ÿ“ฆ Composite Shared Security Blobs

๋ฆฌ๋ˆ…์Šค 5.1 ์ด์ „์—๋Š” ๋ชจ๋“ˆ๋งˆ๋‹ค void *security ํฌ์ธํ„ฐ๋ฅผ ๋…์ ํ•˜๋ ค ํ•˜์—ฌ ๋ณต์ˆ˜ LSM ๋™์‹œ ํ™œ์„ฑํ™”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค. ํ˜„๋Œ€ ์Šคํƒํ˜• LSM์€ ์ปค๋„ ๋ถ€ํŒ… ์‹œ ๊ฐ ๋ชจ๋“ˆ์ด ์š”์ฒญํ•œ ํฌ๊ธฐ(lsm_blob_sizes)๋ฅผ ํ•ฉ์‚ฐํ•˜์—ฌ ๋‹จ์ผ ์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก์œผ๋กœ ํ• ๋‹นํ•˜๊ณ , ๊ฐ ๋ชจ๋“ˆ์— ๊ณ ์ • ์˜คํ”„์…‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

struct cred atomic_t usage kuid_t uid, gid kernel_cap_t cap_effective void *security โ”€โ”€โ”€โ”€โ–ถ /* Single shared pointer */ Composite Security Blob (kmalloc) AppArmor/SELinux Offset: +0 bytes Size: 16 bytes struct aa_task_ctx Landlock Offset: +16 bytes Size: 8 bytes struct landlock_ruleset* SafeSetID Offset: +24 bytes Size: 8 bytes struct safesetid_ctx BPF LSM Offset: +32 bytes Size: 16 bytes struct bpf_storage*

โš™๏ธ ์ธํ”„๋ผ ์ŠคํŠธ๋Ÿญ์ฒ˜: lsm_blob_sizes

struct lsm_blob_sizes {
    int lbs_cred;   /* Task credentials */
    int lbs_file;   /* Open file description */
    int lbs_inode;  /* Inode metadata */
    int lbs_ipc;    /* IPC objects */
    int lbs_msg;    /* SysV msg */
    int lbs_task;   /* Task struct */
    int lbs_xattr;  /* Security xattrs */
};

๐Ÿš€ ๊ฐœ์ธ ์˜คํ”„์…‹ ์ ‘๊ทผ ๋งคํฌ๋กœ

/* ์˜ˆ: Landlock ๋ชจ๋“ˆ์˜ ๊ฐœ์ธ ๋ธ”๋กญ ์ ‘๊ทผ */
static inline struct landlock_ruleset *
landlock_cred(const struct cred *cred)
{
    return (struct landlock_ruleset *)
        (cred->security + landlock_blob_sizes.lbs_cred);
}

๐Ÿ› ๏ธ ๋ถ€ํŒ… ํŒŒ๋ผ๋ฏธํ„ฐ ์ œ์–ด ๋ฐ lsm=... ํ•ด์„ ์—”์ง„

์ปค๋„ ์ปดํŒŒ์ผ ์‹œ CONFIG_LSM์œผ๋กœ ๊ธฐ๋ณธ ์Šคํƒ์„ ์ง€์ •ํ•˜๊ณ , ๋ถ€ํŒ… ์‹œ ์ปค๋„ ๋ช…๋ น์ค„์˜ lsm=... ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ˆœ์„œ ๋ณ€๊ฒฝ ๋ฐ ๋น„ํ™œ์„ฑํ™”๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ๋ถ€ํŒ… ์Šคํƒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ

์•„๋ž˜ ์ž…๋ ฅ๋ž€์— ์›ํ•˜๋Š” lsm=... ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์ ์šฉํ•ด ๋ณด์‹ญ์‹œ์˜ค.

๐Ÿ” SecurityFS ์ธํ„ฐํŽ˜์ด์Šค (/sys/kernel/security/lsm)

capability,landlock,lockdown,yama,loadpin,safesetid,bpf

ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ LSM ๋ชฉ๋ก์ด ์ปด๋งˆ๋กœ ๊ตฌ๋ถ„๋˜์–ด ์œ ์ €์ŠคํŽ˜์ด์Šค์— ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“ก LSM ์ „์šฉ ์‹œ์Šคํ…œ ์ฝœ (__NR_lsm_list_modules)

syscall(461, ids, &size, 0)
 -> Detected Modules:
    [1] ID: 100 (capability)
    [2] ID: 110 (landlock)
    [3] ID: 108 (lockdown)
    [4] ID: 105 (yama)
    [5] ID: 106 (loadpin)
    [6] ID: 107 (safesetid)
    [7] ID: 109 (bpf)

๋ฆฌ๋ˆ…์Šค 6.8์— ์ถ”๊ฐ€๋œ UAPI ์‹œ์Šคํ…œ ์ฝœ๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ ID ๋ชฉ๋ก์„ ์•ˆ์ „ํ•˜๊ฒŒ ์งˆ์˜ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Š ๋ฆฌ๋ˆ…์Šค ๋ณด์•ˆ ๋ชจ๋“ˆ (LSM) ์ข…ํ•ฉ ๋น„๊ต ๋งคํŠธ๋ฆญ์Šค

๋ชจ๋“ˆ๋ช… (LSM) ๋„์ž… ๋ฒ„์ „ ์Šคํƒ ์ง€์› ๋น„ํŠน๊ถŒ์ž ์‚ฌ์šฉ ์ฃผ์š” ๋ฐฉ์–ด ์˜์—ญ ๋ฐ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋ธ”๋กญ ์š”๊ตฌ
Capability 2.6.0 (ํ•„์ˆ˜) ํ•ญ์ƒ 1์ˆœ์œ„ ๊ถŒํ•œ ์ƒ์† ์ „ํ†ต์  POSIX capability ๋ฐ DAC ๊ถŒํ•œ ๊ฒ€์‚ฌ (๋ฃจํŠธ ๋ถ„ํ• ) 0 bytes
Landlock 5.13 ์Šคํƒ ๊ฐ€๋Šฅ ์™„์ „ ์ง€์› ๋น„ํŠน๊ถŒ ํ”„๋กœ์„ธ์Šค ์ƒŒ๋“œ๋ฐ•์‹ฑ (ํŒŒ์ผ์‹œ์Šคํ…œ ๊ฒฝ๋กœ ๋ฐ ๋„คํŠธ์›Œํฌ ํฌํŠธ ์ œํ•œ) Cred, Inode
Lockdown 5.4 ์Šคํƒ ๊ฐ€๋Šฅ ๋ฃจํŠธ ์ „์šฉ ์ปค๋„ ๋ฌด๊ฒฐ์„ฑ ๋ฐ ๊ธฐ๋ฐ€์„ฑ ๋ณดํ˜ธ (/dev/mem, I/O ํฌํŠธ, BPF ์“ฐ๊ธฐ ๋ฐฉ์ง€) 0 bytes
Yama 3.4 ์Šคํƒ ๊ฐ€๋Šฅ ๊ธฐ๋ณธ ๋ณดํ˜ธ ptrace ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์ž… ๋ฐ ๋””๋ฒ„๊น… ์ ‘๊ทผ ํ†ต์ œ (ptrace_scope) 0 bytes
LoadPin 4.7 ์Šคํƒ ๊ฐ€๋Šฅ ๋ถ€ํŒ… ์ „์šฉ ์ปค๋„ ๋ชจ๋“ˆ/ํŽŒ์›จ์–ด๊ฐ€ ์ตœ์ดˆ ๋งˆ์šดํŠธ๋œ ์‹ ๋ขฐ ๋ฃจํŠธ์—์„œ๋งŒ ๋กœ๋“œ๋˜๋„๋ก ๊ณ ์ • 0 bytes
SafeSetID 5.1 ์Šคํƒ ๊ฐ€๋Šฅ ๋ฃจํŠธ ์ •์ฑ… UID/GID ์ „ํ™˜ ์ „์ด(Transition) ๊ทœ์น™ ํ†ต์ œ (๊ถŒํ•œ ์ƒ์Šน ํ†ต๋กœ ์ œํ•œ) Cred
BPF LSM 5.7 ์Šคํƒ ๊ฐ€๋Šฅ CAP_BPF eBPF ํ”„๋กœ๊ทธ๋žจ์„ ํ†ตํ•œ ๋™์  ๋Ÿฐํƒ€์ž„ ๋ณด์•ˆ ์ •์ฑ… ์ฃผ์ž… ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง Dynamic
SELinux / AppArmor 2.6.0 / 2.6.36 ๋‹จ์ผ ์ฃผ ๋ชจ๋“ˆ ๊ด€๋ฆฌ์ž ์ •์ฑ… ์‹œ์Šคํ…œ ์ „์—ญ ๊ฐ•์ œ์  ์ ‘๊ทผ ์ œ์–ด (MAC - ๋ ˆ์ด๋ธ” ๋ฐ ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜) Full Blobs