Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Seccomp

mrtc0
April 17, 2021

Introduction to Seccomp

2021.04.17 第14回 コンテナ技術の情報交換会@オンライン
https://ct-study.connpass.com/event/205571/

mrtc0

April 17, 2021
Tweet

More Decks by mrtc0

Other Decks in Programming

Transcript

  1. ,PIFJ.PSJUB !NSUD

    ୈճίϯςφٕज़ͷ৘ใަ׵ձ!ΦϯϥΠϯ
    Introduction to Seccomp
    4FDDPNQͷ࢓૊ΈΛཧղ͢Δ

    View Slide

  2. ,PIFJ.PSJUB !NSUD
    4FOJPS4FDVSJUZ&OHJOFFS!(.01FQBCP *OD
    8FC"QQ4FD$POUBJOFS4FDVSJUZ
    ॳΊͯ৮Εͨίϯςφ͸'SFF#4%+BJM
    ޷͖ͳγεςϜίʔϧ͸QUBSDF

    IUUQTDPOUBJOFSTFDVSJUZEFWΛॻ͍͍ͯ·͢
    ɾ08"41'VLVPLB$IBQUFS-FBEFS
    ɾηΩϡϦςΟɾΩϟϯϓεςΞϦϯάίϛοςΟ

    View Slide

  3. ຊεϥΠυͱίʔυ
    εϥΠυ
    IUUQTTQFBLFSEFDLDPNNSUDJOUSPEVDUJPOUPTFDDPNQ
    ίʔυ
    IUUQTHJUIVCDPNNSUDTBOECPYUSFFNBTUFSTFDDPNQ
    ΦϯϥΠϯ։࠵ͷͨΊɺϑΥϯτΛখ͞Ίʹͯ͠٧ΊࠐΜͰ͍·͢ɻ

    View Slide

  4. Seccomp ͱ͸

    View Slide

  5. 4FDDPNQͱ͸
    4&$VSF$0.1VUJOH
    -JOVYΧʔωϧͷηΩϡϦςΟػೳͷҰͭͰɺϓϩηεͷαϯυϘοΫεԽΛࢧԉ͢Δ
    ϓϩηεࣗ਎͕γεςϜίʔϧͷൃߦ΍Ҿ਺Λ੍ݶ͢Δ͜ͱͰɺ߈ܸ͞Εͨ৔߹ͷӨڹΛখ͘͞Ͱ͖Δ
    Process
    SFBE

    FYFDWF

    4&$VSF$0.QVUJOH.PEFͱݺ͹ΕΔ͜ͱ΋͋Δ
    SFBE
    ͸ڐՄ͢Δ͕ɺFYFDWF
    ͸ېࢭ͢Δ
    ͳͲ͕Մೳ

    View Slide

  6. 4FDDPNQͱ͸
    4FDDPNQͷྺ࢙

    -JOVY,FSOFMʹϚʔδ͞ΕΔɻ
    ౰࣌͸read, write, exit, sigreturn
    ͷΈ͔࣮͠ߦͰ͖ͳ͍ɻ
    QSPDQJETFDDPNQͰ੍ޚɻ

    -JOVY,FSOFMͰprctl()ܦ༝
    Ͱ੍ޚͰ͖ΔΑ͏ʹͳΔɻ

    -JOVY,FSOFMʹ4FDDPNQ
    .PEF͕ొ৔ɻ
    ೚ҙͷγεςϜίʔϧΛ੍ݶͰ͖ɺ
    #1'ΛϕʔεʹϑΟϧλͰ͖Δɻ

    -JOVY,FSOFMͰseccomp(2)
    ͕௥Ճɻ
    TFDDPNQCQGͱ͔TFDDPNQͱ͔දه༳Ε͕ଟ͍
    4FDDPNQ/PUJGZ͕௥Ճɻ
    Ϣʔβʔεϖʔεͱ࿈ܞ͕औΕ
    ΔΑ͏ʹɻ

    ਖ਼໊ࣜশͰ͸ͳ͍ɻ4FDDPNQUSBQUPVTFSTQBDFͳͲͱ΋ݺ͹ΕΔ
    ݸਓతʹେ͖͍࠷ۙͷมߋΛϐοΫΞοϓ͍ͯ͠·͢ɻ

    View Slide

  7. 4FDDPNQͱ͸
    .PEFͱ.PEF
    .PEF͸read(2), write(2), exit(2), sigreturn(2)ͷΈڐՄ
    .PEF͸೚ҙͷγεςϜίʔϧͱͦͷҾ਺Λ੍ݶͰ͖Δ
    .PEFΛ4USJDU.PEF .PEFΛ'JMUFS.PEFͳͲͱݺͿ͜ͱ΋͋Δ

    View Slide

  8. 4FDDPNQ͕Ͳ͏ಈ͔͘
    ɾγεςϜίʔϧ͕ݺ͹ΕΔͨͼʹ4FDDPNQ͕ݕࠪΛߦ͏
    ɾ4FDDPNQͷϑΟϧλ͸ࢠϓϩηεʹ΋Ҿ͖ܧ͕ΕΔ
    Process
    read(2)Λݺͼग़͠
    Seccomp
    👮read(2)Ϥγο
    ໭Γ஋Λฦ͢
    $BMMread(2)
    Process
    execve(2)Λݺͼग़͠
    Seccomp
    👮execve(2)ΞΧϯ
    execve(2)͸࣮ߦ͞Εͳ͍
    SIGSYSͳΓܾΊΒΕͨ
    ΞΫγϣϯ͕࣮ߦ͞ΕΔ
    ΞΫγϣϯʹΑͬͯ͸࣮ߦ͞ΕΔέʔε΋͋Δ
    6TFSTQBDF
    ,FSOFMTQBDF
    ɾෆਖ਼ͳ৔߹͸ܾΊΒΕͨΞΫγϣϯ͕࣮ߦ͞ΕΔ
    ɾҰൠతʹɺγεςϜίʔϧ͕ࢭΊΒΕͯSIGSYS͕ฦΔ

    View Slide

  9. 3FBM8PSME4FDDPNQ
    4FDDPNQͷར༻ྫ
    ɾ"OESPJE΍$ISPNF04
    ɾ$ISPNJVN΍'JSFGPYͳͲͷϒϥ΢β
    ɾ0QFO44)΍WTGUQEͳͲͷϛυϧ΢ΣΞ
    ɾ%PDLFS΍-9%ͳͲͷίϯςφ

    View Slide

  10. $POUBJOFS4FDDPNQ
    %PDLFS-9$ͳͲͰ͸σϑΥϧτͰ4FDDPNQΛ࢖͍ͬͯ·͢
    kexec_load(2)΍reboot(2)ͳͲѱ༻Մೳͳ ϗετʹӨڹΛ༩͑Δ͜ͱ͕Ͱ͖Δ
    γεςϜίʔϧ͕
    ੍ݶ͞Ε͍ͯ·͢ɻ
    IUUQTHJUIVCDPNNPCZNPCZCMPCNBTUFSQSPpMFTTFDDPNQEFGBVMUKTPO
    IUUQTEPDTEPDLFSDPNFOHJOFTFDVSJUZTFDDPNQ

    View Slide

  11. Seccomp Examples

    View Slide

  12. 4FDDPNQ&YBNQMFT
    4FDDPNQJO%PDLFS
    4FDDPNQͷಈ͖Λମݧ͢Δʹ͸%PDLFS͕खܰ
    $ cat seccomp.json
    {
    "defaultAction": "SCMP_ACT_ALLOW", // શͯͷγεςϜίʔϧΛڐՄ
    "syscalls": [
    {
    "name": "mkdir",
    "action": "SCMP_ACT_ERRNO" // mkdir(2) Λېࢭ
    }
    ]
    }
    $ docker run --rm -it --security-opt seccomp=seccomp.json ubuntu:20.04
    bash
    root@ab9ad7d57f7f:/# mkdir /tmp/test
    mkdir: cannot create directory '/tmp/test': Operation not permitted

    View Slide

  13. 4FDDPNQ&YBNQMFT
    NBOTFDDPNQ
    int seccomp(unsigned int operation, unsigned int flags, void *args);
    ϓϩηεͰTFDDPNQΛར༻͢Δʹ͸seccomp(2)Λ࢖͏
    operation͸࣍ͷ஋ΛऔΔ
    SECCOMP_SET_MODE_STRICT ... read(2), write(2), _exit(2), sigreturn(2) ͷΈΛڐՄ͢Δɻ
    SECCOMP_SET_MODE_FILTER ... BPF ͰϑΟϧλΛॻ͍ͯ೚ҙͷγεςϜίʔϧͱͦͷҾ਺Λ੍ݶͰ͖Δɻ

    View Slide

  14. #include
    #include
    int main(void)
    {
    struct utsname name;
    if (uname(&name)) {
    perror("uname failed: ");
    return 1;
    }
    printf("uname: %s\n", name.sysname);
    return 0;
    }
    αϯϓϧͱͯ͠uname(2)Λېࢭ͢ΔϓϩάϥϜΛ࡞Γ·͢ɻ
    TFDDPNQ

    TBOECPYԽ͢ΔίʔυΛ༻ҙ
    TFDDPNQ
    Λ࣮ߦ͢Δؔ਺Λ༻ҙ
    #1'ϑΟϧλΛఆٛ
    TFDDPNQ
    Λద༻
    $ ./uname
    => Linux

    View Slide

  15. ...
    sandbox() // ௥Ճ
    if (uname(&name)) {
    perror("uname failed:
    ");
    return 1;
    }
    ...
    TFDDPNQΛద༻͍ͨ͠ॲཧͷલʹɺ
    seccomp(2)Λ࣮ߦ͢ΔTBOECPY
    ؔ਺Λ௥Ճ
    TBOECPYԽ͢ΔίʔυΛ༻ҙ
    TFDDPNQ
    Λ࣮ߦ͢Δؔ਺Λ༻ҙ
    #1'ϑΟϧλΛఆٛ
    TFDDPNQ
    Λద༻
    TFDDPNQ

    View Slide

  16. // seccomp BPF ϑΟϧλͷఆٛ
    struct sock_filter filter[] = {
    // 1. seccomp_data ߏ଄ମ͔Β arch ϑΟʔϧυͷ஋Λϩʔυ
    // γεςϜίʔϧ͸ΞʔΩςΫνϟʹΑͬͯ࠾൪͕ҟͳΔͨΊɺ
    // ඞͣνΣοΫ͢Δඞཁ͕͋Δɻ
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, arch))),
    // 2. x86_64 Ҏ֎ͷ৔߹͸ SECCOMP_RET_KILL
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0, 4),
    // 3. seccomp_data ߏ଄ମ͔Β nr ϑΟʔϧυͷ஋Λϩʔυ
    // ͜͜ʹ͸γεςϜίʔϧ൪߸͕֨ೲ͞Ε͍ͯΔ
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
    // 4. uname(2) Ͱ͋Ε͹ SECCOMP_RET_ERRNO ͰEPERM Λฦ͢
    // ͦΕҎ֎ͷ৔߹͸ڐՄ
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_uname, 0, 1),
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (EPERM & SECCOMP_RET_DATA)),
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
    };
    TBOECPYԽ͢ΔίʔυΛ༻ҙ
    TFDDPNQ
    Λ࣮ߦ͢Δؔ਺Λ༻ҙ
    #1'ϑΟϧλΛఆٛ
    TFDDPNQ
    Λద༻
    TFDDPNQ

    View Slide

  17. struct sock_fprog prog = {
    .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
    .filter = filter,
    };
    // SECCOMP_SET_MODE_FILTER Λར༻͢Δʹ͸ CAP_SYS_ADMIN ͔
    // εϨουʹ no_new_privs ͕ඞཁͳͷͰηοτ
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
    perror("PR_SET_NO_NEW_PRIVS failed");
    exit(1);
    };
    // seccomp γεςϜίʔϧͷݺͼग़͠
    if (syscall(SYS_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog)) {
    perror("seccomp failed");
    exit(1);
    };
    TBOECPYԽ͢ΔίʔυΛ༻ҙ
    TFDDPNQ
    Λ࣮ߦ͢Δؔ਺Λ༻ҙ
    #1'ϑΟϧλΛఆٛ
    TFDDPNQ
    Λద༻
    TFDDPNQ

    $ ./uname_with_seccomp
    uname failed: Operation not permitted

    View Slide

  18. 4FDDPNQ4UBUVT
    ϓϩηε͕4FDDPNQͰಈ࡞͍ͯ͠Δ͔Λௐ΂͍ͨ
    ɾprctl(2)ͰPR_GET_SECCOMPΛࢦఆ͢Δ͜ͱͰɺ֬ೝͰ͖ͨɻ
    ɾ-JOVY,FSOFMҎ߱Ͱ͸/proc/$PID/statusͰ4FDDPNQͷঢ়ଶΛ֬ೝͰ͖ΔΑ͏ʹͳͬͨɻ
    ubuntu@sandbox ~> cat /proc/4304/status | grep Seccomp
    Seccomp: 2
    4FDDPNQ%JTBCMFE
    .PEF 4USJDU

    .PEF 'JMUFS

    View Slide

  19. 4FDDPNQ&YBNQMFT
    #1'
    4&[email protected]%&@'*-5&3Λ࢖͏৔߹͸#1'1SPHSBNͰϑΟϧλΛॻ͘ɻ
    #1'͸UDQEVNQͷύέοτϑΟϧλϦϯάͰ΋ར༻͞Ε͍ͯΔٕज़ͰɺΧʔωϧͰϓϩάϥϜΛ
    ಈ͔͢͜ͱͰߴ଎ʹϑΟϧλϦϯά͢Δ͜ͱ͕Մೳɻ
    #1'͸ઐ༻ͷϨδελϕʔεͷ7.্Ͱಈ͘ઃܭʹͳ͍ͬͯΔɻ
    ύέοτϑΟϧλϦϯάͷٕज़ͳͷʹԿނ
    .PEF͕ݫ͗͢͠Δ SFBEXSJUFFYJUTJHSFUVSO͔͠ڐՄͰ͖ͳ͍

    ࣮ࡍʹGUSBDFQFSG"#*Λར༻ͨ͠ํ๏΋ݕ౼͞Ε͕ͨɺ͜ΕΒͷٕज़͸ద͞ͳ͔ͬͨΒ͍͠
    ͳͥ#1'
    IUUQTMPSFLFSOFMPSHMLNM'#![ZUPSDPN5

    View Slide

  20. 4FDDPNQ&YBNQMFT
    3FBEJOH#1'
    Ͱ͸#1'ͱ͸Ͳ͏͍ͬͨ΋ͷͳͷ͔ݟͯΈ·͠ΐ͏ɻ
    UDQEVNQͰA-dAΦϓγϣϯΛ࢖͏ͱ#1'ͷόΠτίʔυ΍໋ྩΛදࣔͰ͖·͢ɻ
    $ sudo tcpdump -d icmp
    (000) ldh [12] // ύέοτઌ಄͔Β 12byte ໨Λϩʔυ
    (001) jeq #0x800 jt 2 jf 5 // ಡΈࠐΜͩ஋͕ 0x800 Ͱ͋Ε͹ 2 ΁
    (002) ldb [23] // 23byte ໨
    (003) jeq #0x1 jt 4 jf 5 // ಡΈࠐΜͩ஋͕ 0x1 Ͱ͋Ε͹ 4 ΁
    (004) ret #262144
    (005) ret #0

    View Slide

  21. 4FDDPNQ&YBNQMFT
    $ sudo tcpdump -d icmp
    (000) ldh [12] // ύέοτઌ಄͔Β 12byte ϩʔυ
    (001) jeq #0x800 jt 2 jf 5 // ಡΈࠐΜͩ஋͕ 0x800 Ͱ͋Ε͹ 2 ΁
    (002) ldb [23] // 23byte໨
    (003) jeq #0x1 jt 4 jf 5 // ಡΈࠐΜͩ஋͕ 0x1 Ͱ͋Ε͹ 4 ΁
    (004) ret #262144
    (005) ret #0
    Ͱ͸#1'ͱ͸Ͳ͏͍ͬͨ΋ͷͳͷ͔ݟͯΈ·͠ΐ͏ɻ
    UDQEVNQͰA-dAΦϓγϣϯΛ࢖͏ͱ#1'ͷόΠτίʔυ΍໋ྩΛදࣔͰ͖·͢ɻ
    3FBEJOH#1'

    View Slide

  22. 4FDDPNQ&YBNQMFT
    3FBEJOH#1'
    ໋ྩηοτʹ͍ͭͯ͸%PDVNFOUBUJPOOFUXPSLJOHpMUFSUYUʹଘࡏ͢Δɻ
    ྫ͑͹ઌఔͷuname(2)Ͱఆٛͨ͠ϑΟϧλΛಡΈղ͘ͱ࣍ͷΑ͏ʹͳΔɻ
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, arch))),
    LD* ͸A(ΞΩϡϜϨʔλ)Ϩδελʹϩʔυ
    BPF_W ͸αΠζम০ࢠͰ Word Size (4byte) Λࣔ͢
    BPF_ABS ͸ mode म০ࢠͰઈରࢀরΛࣔ͢
    ΑͬͯɺA = P[k:4] Ͱ arch ΛϨδελʹϩʔυͱ͍͏ҙຯ
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0, 4),
    JEQ ͸ dst == src Λҙຯ͢Δ
    BPF_K ͸ଈ஋Λࣔ͢
    ΑͬͯɺA == AUDIT_ARCH_X86_64 ? 0 : 4 ͱͳΔ

    View Slide

  23. #1'໘౗

    View Slide

  24. #1'ϑΟϧλΛॻ͘ͷ͕೉͍͠
    ɾ#1'ͷ໋ྩηοτ΍࢓༷Λཧղ͢Δඞཁ͕͋Δ
    ɾϚΫϩΛॻ͚͹Θ͔Γ΍͘͢ͳΔ
    IUUQTHJUIVCDPNPQFOTTIPQFOTTIQPSUBCMFCMPCEECEEBFEDEFFFBETBOECPYTFDDPNQpMUFSD

    View Slide

  25. MJCTFDDPNQ
    ɾ4FDDPNQͷϑΟϧλΛ؆୯ʹॻͨ͘ΊͷΠϯλʔϑΣΠεΛఏڙ͢ΔϥΠϒϥϦ
    ɾΞʔΩςΫνϟͷࠩҟΛٵऩͯ͘͠ΕΔ Y "3. .*14 FUD

    ɾNBOʹ΋MJCTFDDPNQΛར༻ͯ͠ϑΟϧλΛॻ͘͜ͱ͕קΊΒΕ͍ͯΔ
    TFDDPNQMJCTFDDPNQ
    > Rather than hand-coding seccomp filters as shown in the example
    > below, you may prefer to employ the libseccomp library, which
    > provides a front-end for generating seccomp filters.
    IUUQTNBOPSHMJOVYNBOQBHFTNBOTFDDPNQIUNM

    View Slide

  26. MJCTFDDPNQ
    ɾઌఔͷuname(2)ͷ੍ݶΛߦ͏TBOECPY
    ͸࣍ͷΑ͏ʹॻ͖௚͢͜ͱ͕Ͱ͖Δ
    TFDDPNQMJCTFDDPNQ
    // શγεςϜίʔϧݺͼग़͠ΛڐՄ
    scmp_filter_ctx seccomp_ctx = seccomp_init(SCMP_ACT_ALLOW);
    if (!seccomp_ctx)
    err(1, "seccomp_init failed");
    // uname γεςϜίʔϧͰ͋Ε͹ Kill
    if (seccomp_rule_add_exact(seccomp_ctx, SCMP_ACT_KILL, seccomp_syscall_resolve_name("uname"), 0)) {
    perror("seccomp_rule_add_exact failed");
    exit(1);
    }
    // ϑΟϧλΛద༻
    if (seccomp_load(seccomp_ctx)) {
    perror("seccomp_load failed");
    exit(1);
    }
    seccomp_release(seccomp_ctx);

    View Slide

  27. ϓϩηεͷऴྃͷ࢓ํ
    MJCTFDDPNQͷར༻ͷ༗ແͰϓϩηεͷऴྃͷ࢓ํ͕ҟͳΔ͜ͱʹؾ͍ͮͨͰ͠ΐ͏͔
    $ ./uname_with_seccomp
    uname failed: Operation not permitted 👈
    $ ./uname_with_libseccomp
    Bad system call (core dumped) 👈
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_uname, 0, 1),
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (EPERM & SECCOMP_RET_DATA)),
    $ sudo strace ./uname_with_libseccomp
    ...
    uname( ) = ?
    +++ killed by SIGSYS (core dumped) +++
    Bad system call
    લऀ͸&1&3.Ληοτͯ͠ɺࣗ਎ͰΤϥʔϋϯυϦϯάΛ͍ͯ͠·ͨ͠ɻ
    ҰํͰɺMJCTFDDPNQଆͰ͸4*(4:4Ͱऴ͍ྃͯ͠·͢ɻ

    View Slide

  28. 4FDDPNQ"DUJPO
    SECCOMP_RET_KILL_PROCESS4*(4:4Ͱऴྃ͢ΔɻγεςϜίʔϧ͸࣮ߦ͞Εͳ͍ɻ
    SECCOMP_RET_ERRNOࢦఆͨ͠FSSOPͰฦ͢ɻγεςϜίʔϧ͸࣮ߦ͞Εͳ͍ɻ
    SECCOMP_RET_TRACEQUSBDFCBTFEͳτϨʔαʹ௨஌ɻ
    τϨʔα͸γεςϜίʔϧΛεΩοϓͨ͠Γɺ೚ҙͷγεςϜίʔϧʹมߋͰ͖Δ
    SECCOMP_RET_ALLOWγεςϜίʔϧͷ࣮ߦΛڐՄ͢Δɻ
    SECCOMP_RET_LOG"DUJPOͷ݁ՌΛBVEJUMPHʹه࿥͢Δɻ
    γεςϜίʔϧ࣮ߦͷѻ͍ΛͲ͏͢Δ͔ܾఆ͢Δɻ୯ʹڐՄېࢭ͢Δ͚ͩͰ͸ͳ͍ɻ

    View Slide

  29. ϓϩηεͷऴྃͷ࢓ํ
    ΤϥʔϋϯυϦϯάΛࣗ෼Ͱߦ͑ͨํ͕ॊೈͰ͕͢ɺ࣍ͷΑ͏ͳέʔε΋ߟ͑ΒΕ·͢
    ...
    sandbox(); // read(2) Λېࢭ
    // ΋͠ read(2) ʹࣦഊͯ͠΋ pread(2) ͰόΠύε͢Δ
    size = read(fd, buf, sizeof(buf));
    if (size == -1) {
    perror("read(2) failed ");
    size = pread(fd, buf, sizeof(buf), 0);
    if (size == -1) {
    perror("pread(2) failed ");
    ...
    ׬શͳϑΟϧλΛ༻ҙ͢Δͷ͸೉͍͠
    SIGSYSͰଈ࠲ʹऴྃ͢Δ͜ͱͰ߈ܸऀʹόΠύεͷ༨஍Λ༩͑ͳ͍ͱ͍͏ϝϦοτ͕͋Δ

    View Slide

  30. Apply Seccomp to Process

    View Slide

  31. 4FDDPNQΛద༻͢Δ
    ͜͜·Ͱ࿩Λฉ͔Εͨํɺ4FDDPNQΛద༻͍͚ͨ͠ͲMJCTFDDPNQΛॻ͘ͷ͸ͭΒ͍ͱࢥ͍·ͤΜ͔
    ͔͜͜Β͸ɺ࣮ࡍʹϓϩηεʹ4FDDPNQΛద༻͢Δํ๏Λ͍͔ͭ͘͝঺հ͠·͢ɻ
    -%@13&-0"%
    $MPVEqBSFTBOECPYUPPMLJUTZTUFNE
    %PDLFSͳͲͷίϯςφ
    γεςϜίʔϧͷݺͼग़֬͠ೝ TUSBDFF#1'EPDLFSTMJN

    View Slide

  32. -%@13&-0"%
    ($$֦ு__attribute__((constructor))Ͱ4FDDPNQΛηοτ͢Δ
    /* seccomp.c */
    #include
    #include
    __attribute__((constructor)) void configure_seccomp(void) {
    ...
    if (seccomp_rule_add_exact(seccomp_ctx, SCMP_ACT_KILL, seccomp_syscall_resolve_name("uname"), 0)) {
    perror("seccomp_rule_add_exact failed");
    }
    ...
    printf("Configuring seccomp\n");
    ...
    }
    $ gcc -shared -fPIC -o seccomp.so seccomp.c -lseccomp
    $ env LD_PRELOAD=./seccomp.so uname -a
    Configuring seccomp
    fish: “env LD_PRELOAD=./seccomp.so una…” terminated by signal SIGSYS (Bad system call)
    ͨͩ͠-%@13&-0"%Λ࢖͏৔߹ɺ੩తϦϯΫ͞ΕͨϑΝΠϧͰ͸ػೳ͠ͳ͍
    $ gcc uname.c -static -o uname-static
    $ env LD_PRELOAD=./seccomp.so./uname-static
    uname: Linux

    View Slide

  33. DMPVEGMBSFTBOECPY
    ઌఔͷ-%@13&-0"%Λ࢖͏ํ๏ΛɺΑΓ൚༻తʹ࢖͑ΔΑ͏ʹͨ͠΋ͷ
    ؀ڥม਺ʹڐՄ ېࢭ͢ΔγεςϜίʔϧΛࢦఆ͢Δ͜ͱͰػೳ͢Δ
    $ env LD_PRELOAD=./libsandbox.so SECCOMP_SYSCALL_DENY="uname" uname -a
    initializing seccomp with default action (allow)
    adding uname to the process seccomp filter (kill process)
    fish: 'env LD_PRELOAD=./libsandbox.so…' terminated by signal SIGSYS (Bad system call)
    IUUQTHJUIVCDPNDMPVEqBSFTBOECPY
    ੩తϦϯΫͨ͠ϑΝΠϧ΁ͷରԠͱͯ͠TBOECPYJGZͱ͍͏πʔϧΛఏڙ͍ͯ͠Δ
    GPSL
    FYFD
    ͢Δ͚ͩͷ΋ͷ
    # env SECCOMP_SYSCALL_DENY="uname" ./sandboxify ./uname-static
    initializing seccomp with default action (allow)
    adding uname to the process seccomp filter (kill process)
    fish: 'sudo env SECCOMP_SYSCALL_DENY="…' terminated by signal SIGSYS (Bad system call)
    TBOECPYJGZͱಉ༷ͷΞϓϩʔν͸TZTUFNEͰ΋Մೳ
    [Service]
    ExecStart = /path/to/uname
    SystemCallFilter = openat uname brk arch_prctl readlink access fstat write exit_group mmap close read mprotect munmap

    View Slide

  34. -%@13&-0"%WTTBOECPYJGZ
    TBOECPYJGZͷΑ͏ͳΞϓϩʔνͷ৔߹ɺϙϦγʔ͕ΏΔ͘ͳͬͯ͠·͏Մೳੑ͕͋Δɻ
    $ strace ./uname-static
    execve("/home/ubuntu/seccomp/uname-static", ["/home/ubuntu/secco...
    brk(NULL) = 0xba2000
    brk(0xba31c0) = 0xba31c0
    arch_prctl(ARCH_SET_FS, 0xba2880) = 0
    uname({sysname="Linux", nodename="sandbox", ...}) = 0
    readlink("/proc/self/exe", "/home/ubuntu/seccomp/uname-stati"..., 4096) = 33
    brk(0xbc41c0) = 0xbc41c0
    brk(0xbc5000) = 0xbc5000
    access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
    uname({sysname="Linux", nodename="sandbox", ...}) = 0
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
    write(1, "Linux\n", 6Linux
    -%@13&-0"%Λ࢖ͬͨΞϓϩʔνͰ͸ɺ͍ΘΏΔNBJO
    ͷલʹద༻͞ΕΔ͕ɺTBOECPYJGZͷΑ͏ͳΞϓϩʔ
    νͩͱϥϯλΠϜͷॳظԽͰ࣮ߦ͞ΕΔγεςϜίʔϧ΋ڐ༰͢Δඞཁ͕͋Δɻ
    IUUQTCMPHDMPVEqBSFDPNTBOECPYJOHJOMJOVYXJUI[FSPMJOFTPGDPEF

    View Slide

  35. %PDLFS
    ίϯςφͰಈ͔͢ΞϓϦέʔγϣϯʹରͯ͠TFDDPNQΛઃఆՄೳ
    $ cat seccomp.json
    {
    "defaultAction": "SCMP_ACT_ALLOW", // શͯͷγεςϜίʔϧΛڐՄ
    "syscalls": [
    {
    "name": "mkdir",
    "action": "SCMP_ACT_ERRNO" // mkdir(2) Λېࢭ
    }
    ]
    }
    $ docker run --rm -it --security-opt seccomp=seccomp.json ubuntu:20.04 bash
    root@ab9ad7d57f7f:/# mkdir /tmp/test
    mkdir: cannot create directory '/tmp/test': Operation not permitted
    -9%ͳͲଞͷଟ͘ͷίϯςφϥϯλΠϜ΋4FDDPNQ͸αϙʔτ͍ͯ͠·͢

    View Slide

  36. 4FDDPNQϑΟϧλͷ࡞Γํ
    ɾ࣮ࡍʹେมͳͷ͸4FDDPNQϑΟϧλ 1SPpMF
    Λ࡞Δ࡞ۀ
    ɾΞϓϦέʔγϣϯ͕ൃߦ͍ͯ͠ΔγεςϜίʔϧΛ೺Ѳ͠ͳ͚Ε͹͍͚ͳ͍
    ɾTUSBDFͳͲ
    ɾ৭ʑΞϓϩʔν͕͋Γ·͕͢ɺ͜͜Ͱ͸࣍ͷͭΛ঺հ͠·͢
    4&$$0.1@3&5@-0(4$.1@"$5@-0(
    F#1'
    EPDLFSTMJN

    View Slide

  37. 4&$$0.1@3&5@-0(4$.1@"$5@-0(
    -JOVY,FSOFMҎ߱Ͱ͸SECCOMP_RET_LOG"DUJPOͰBVEJUEʹϩάΛग़ྗͰ͖Δ
    struct sock_filter filter[] = {
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, arch))),
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0, 2),
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_LOG),
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
    }
    // libseccomp
    scmp_filter_ctx seccomp_ctx = seccomp_init(SCMP_ACT_LOG);
    if (!seccomp_ctx)
    err(1, "seccomp_init failed");
    if (seccomp_load(seccomp_ctx)) {
    perror("seccomp_load failed");
    exit(1);
    }
    $ tail -f /var/log/audit/audit.log
    type=SECCOMP msg=audit(1618574663.331:1719): ... comm="a.out" exe="/home/ubuntu/seccomp/logging/a.out" sig=0 arch=c000003e syscall=39 ...
    type=SECCOMP msg=audit(1618574663.331:1720): ... comm="a.out" exe="/home/ubuntu/seccomp/logging/a.out" sig=0 arch=c000003e syscall=63 ...
    type=SECCOMP msg=audit(1618574663.331:1721): ... comm="a.out" exe="/home/ubuntu/seccomp/logging/a.out" sig=0 arch=c000003e syscall=5 ...
    type=SECCOMP msg=audit(1618574663.331:1722): ... comm="a.out" exe="/home/ubuntu/seccomp/logging/a.out" sig=0 arch=c000003e syscall=1 ...
    type=SECCOMP msg=audit(1618574663.331:1723): ...comm="a.out" exe="/home/ubuntu/seccomp/logging/a.out" sig=0 arch=c000003e syscall=231 ...

    View Slide

  38. F#1'
    ɾF#1'Λ࢖ͬͯγεςϜίʔϧݺͼग़͠ΛτϨʔε͠ɺϓϩϑΝΠϧΛ࡞੒͢Δ
    # ./execsnoop
    PCOMM PID RET ARGS
    bash 15887 0 /usr/bin/man ls
    preconv 15894 0 /usr/bin/preconv -e UTF-8
    man 15896 0 /usr/bin/tbl
    man 15897 0 /usr/bin/nroff -mandoc -rLL=169n -rLT=169n -Tutf8
    man 15898 0 /usr/bin/pager -s
    nroff 15900 0 /usr/bin/locale charmap
    nroff 15901 0 /usr/bin/groff -mtty-char -Tutf8 -mandoc -rLL=169n -rLT=169n
    groff 15902 0 /usr/bin/troff -mtty-char -mandoc -rLL=169n -rLT=169n -Tutf8
    groff 15903 0 /usr/bin/grotty
    ɾFYUFOEFE#1'ͷུɻΧʔωϧτϨʔγϯάͷͨΊͷٕज़ɻ
    ɾৄ͘͠͸4PGUXBSF%FTJHO೥d݄߸Λ

    View Slide

  39. 0$*TFDDPNQCQGIPPL
    $ sudo podman run --annotation io.containers.trace-syscall=of:/tmp/uname.json ubuntu:latest uname
    $ cat /tmp/ls.json | jq
    {
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
    "SCMP_ARCH_X86_64"
    ],
    "syscalls": [
    {
    "names": [
    "access",
    "arch_prctl",
    "brk",
    "capset",
    "close",
    "execve",
    "exit_group"
    ...
    0$*SVOUJNFIPPLTͷQSFTUBSU0$*IPPLΛར༻ͯ͠ɺίϯςφͷJOJUϓϩηε͕։࢝͢Δ௚લ͔Β
    F#1'ϓϩάϥϜΛ࢖ͬͯτϨʔε͢Δɻ
    IUUQTHJUIVCDPNPQFODPOUBJOFSTSVOUJNFTQFDCMPCNBTUFSDPOpHNEQSFTUBSU
    IUUQTHJUIVCDPNDPOUBJOFSTPDJTFDDPNQCQGIPPL

    View Slide

  40. EPDLFSTMJN
    ubuntu@sandbox ~> docker-slim build ubuntu:latest --http-probe=false
    ...
    cmd=build info=results status='MINIFIED' by='19.62X' size.original='73 MB' size.optimized='3.7 MB'
    cmd=build info=results image.name='ubuntu.slim' image.size='3.7 MB' has.data='true'
    cmd=build info=results artifacts.location='/tmp/docker-slim-state/.docker-slim-state/images/.../artifacts'
    cmd=build info=results artifacts.report='creport.json'
    cmd=build info=results artifacts.dockerfile.reversed='Dockerfile.fat'
    cmd=build info=results artifacts.dockerfile.optimized='Dockerfile'
    cmd=build info=results artifacts.seccomp='ubuntu-seccomp.json'
    cmd=build info=results artifacts.apparmor='ubuntu-apparmor-profile'
    ubuntu@sandbox ~> cat /tmp/docker-slim-state/.docker-slim-state/images/.../artifacts/ubuntu-seccomp.json
    {
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
    "SCMP_ARCH_X86_64"
    ],
    "syscalls": [
    {
    "names": [
    "uname",
    "chdir",
    "execve",
    "read",
    ...
    ptrace(2)Λۦ࢖ͯ͠"QQ"SNPS΍4FDDPNQͷϓϩϑΝΠϧΛੜ੒ͯ͘͠ΕΔπʔϧ
    IUUQTHJUIVCDPNEPDLFSTMJNEPDLFSTMJN

    View Slide

  41. Deep Dive into Seccomp

    View Slide

  42. <࠶ܝ>4FDDPNQ͕Ͳ͏ಈ͔͘
    ɾγεςϜίʔϧ͕ݺ͹ΕΔͨͼʹ4FDDPNQ͕ݕࠪΛߦ͏
    ɾෆਖ਼ͳ৔߹͸ܾΊΒΕͨΞΫγϣϯ͕࣮ߦ͞ΕΔ
    ɾҰൠతʹɺγεςϜίʔϧ͕ࢭΊΒΕͯ4*(4:4͕ฦΔ
    Process
    SFBE
    Λݺͼग़͠
    Seccomp
    👮SFBE
    Ϥγο
    ໭Γ஋Λฦ͢
    $BMMSFBE

    Process
    FYFDWF
    Λݺͼग़͠
    Seccomp
    👮FYFDWF
    ΞΧϯ
    FYFDWF
    ͸࣮ߦ͞Εͳ͍
    4*(4:4ͳΓܾΊΒΕͨ
    ΞΫγϣϯ͕࣮ߦ͞ΕΔ
    ΞΫγϣϯʹΑͬͯ͸࣮ߦ͞ΕΔέʔε΋͋Δ
    6TFSTQBDF
    ,FSOFMTQBDF

    View Slide

  43. 4FDDPNQͷॲཧΛ௥͍͔͚Δ
    ΧʔωϧͰ͸ͲͷΑ͏ͳॲཧ͕͞Ε͍ͯΔ͔೷͍ͯΈ·͠ΐ͏
    ؀ڥ
    6CVOUV-54
    -JOVY,FSOFM
    LFSOFMTFDDPNQDʹॲཧ͕ॻ͔Ε͍ͯ·͢

    View Slide

  44. 4FDDPNQͷॲཧΛ௥͍͔͚Δ
    seccomp(2)͸಺෦Ͱdo_seccomp()ΛݺΜͰ͍Δ
    ϑΟϧλͷద༻
    do_seccomp()Ͱ͸.PEF͔.PEFΛ੾Γସ͍͑ͯΔ
    .PEFͷ৔߹͸seccomp_set_mode_strict()
    .PEFͷ৔߹͸seccomp_set_mode_filter()
    SECCOMP_GET_ACTION_AVAILΛ࢖͏ͱར༻Մೳͳ"DUJPOΛௐ΂
    Δ͜ͱ͕Ͱ͖Δɻ

    View Slide

  45. 4FDDPNQͷॲཧΛ௥͍͔͚Δ
    ɾݖݶͷνΣοΫ
    ɾϩοΫΛऔΔ
    ɾtask_struct->seccomp.modeΛઃఆ
    ϑΟϧλͷద༻
    ͢Ͱʹtask_struct->seccomp.mode͕ઃఆ͞Ε͍ͯΔ৔
    ߹͸ɺ৽نʹઃఆͰ͖ͳ͍ɻ
    ͭ·Γɺ.PEF͔Β.PEFʹ੾Γସ͑Δ͜ͱ͸Ͱ͖ͳ͍
    ͠ɺϑΟϧλͷมߋ΋Ͱ͖ͳ͍ɻ

    View Slide

  46. 4FDDPNQͷॲཧΛ௥͍͔͚Δ
    ͪΌΜͱγεςϜίʔϧݺͼग़͠௚લʹɺ
    ࣮ߦ͞Ε͍ͯΔ
    γεςϜίʔϧͷ؂ࠪ
    /*
    * Returns the syscall nr to run (which should match regs->orig_ax) or -1
    * to skip the syscall.
    */
    static long syscall_trace_enter(struct pt_regs *regs)
    {
    u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
    ...
    if (work & _TIF_SECCOMP) {
    struct seccomp_data sd;
    sd.arch = arch;
    sd.nr = regs->orig_ax;
    sd.instruction_pointer = regs->ip;
    ...
    ret = __secure_computing(&sd);
    if (ret == -1)
    return ret;
    do_syscall_64()
    -> syscall_trance_enter()
    -> __secure_computing()

    View Slide

  47. 4FDDPNQͷॲཧΛ௥͍͔͚Δ
    ͪ͜Β΋.PEFͰॲཧΛ෼ذɻ
    int __secure_computing(const struct seccomp_data *sd)
    {
    int mode = current->seccomp.mode;
    int this_syscall;
    if (IS_ENABLED(CONFIG_CHECKPOINT_RESTORE) &&
    unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
    return 0;
    this_syscall = sd ? sd->nr :
    syscall_get_nr(current, task_pt_regs(current));
    switch (mode) {
    case SECCOMP_MODE_STRICT:
    __secure_computing_strict(this_syscall); /* may call do_exit */
    return 0;
    case SECCOMP_MODE_FILTER:
    return __seccomp_filter(this_syscall, sd, false);
    default:
    BUG();
    }
    }
    γεςϜίʔϧͷ؂ࠪ
    __seccomp_filter()
    -> seccomp_run_filters()
    -> BPF_PROG_RUN()
    ධՁޙͷ໭Γ஋ͱͳΔ"DUJPOͰ෼ذ
    filter_ret = seccomp_run_filters(sd, &match);
    data = filter_ret & SECCOMP_RET_DATA;
    action = filter_ret & SECCOMP_RET_ACTION_FULL;
    switch (action) {
    case SECCOMP_RET_ERRNO:
    /* Set low-order bits as an errno, capped at MAX_ERRNO. */
    if (data > MAX_ERRNO)
    data = MAX_ERRNO;
    syscall_set_return_value(current, task_pt_regs(current),
    -data, 0);
    goto skip;
    case SECCOMP_RET_TRAP:
    ...

    View Slide

  48. Bypass Seccomp

    View Slide

  49. .VTUOPUBMMPXVTFPGQUSBDF

    NBOTFDDPNQ
    Before kernel 4.8, the seccomp check will not be
    run again after the tracer is notified. (This
    means that, on older kernels, seccomp-based
    sandboxes must not allow use of ptrace(2)—even of
    other sandboxed processes—without extreme care;
    ptracers can use this mechanism to escape from the
    seccomp sandbox.)

    View Slide

  50. %PTFDDPNQBGUFSQUSBDF
    4FDDPNQͷίʔυΛಡΉͱ࣍ͷΑ͏ͳίϝϯτ͕͋Γ·͢
    static long syscall_trace_enter(struct pt_regs *regs)
    {
    u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
    struct thread_info *ti = current_thread_info();
    unsigned long ret = 0;
    bool emulated = false;
    u32 work;
    ...
    /*
    *
    Do seccomp after ptrace, to catch any tracer changes.
    */
    if (work & _TIF_SECCOMP) {
    struct seccomp_data sd;
    sd.arch = arch;
    sd.nr = regs->orig_ax;
    sd.instruction_pointer = regs->ip;

    View Slide

  51. ݺͼग़͠ͷҧ͍
    -JOVY,FSOFMͰ͸࣍ͷΑ͏ͳݺͼग़͕͠͞Ε͍ͯΔ
    // in Linux Kernel 4.7
    long syscall_trace_enter(struct pt_regs *regs)
    {
    u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
    unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch);
    if (phase1_result == 0)
    return regs->orig_ax;
    else
    return syscall_trace_enter_phase2(regs, arch, phase1_result);
    }
    unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
    {
    ...
    if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
    BUG_ON(regs != task_pt_regs(current));
    work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY;
    /*
    * Do seccomp first -- it should minimize exposure of other
    * code, and keeping seccomp fast is probably more valuable
    * than the rest of this.
    */
    if (work & _TIF_SECCOMP) {
    struct seccomp_data sd;
    ret = seccomp_phase1(&sd);
    if (ret == SECCOMP_PHASE1_SKIP) {
    regs->orig_ax = -1;
    ret = 0;
    } else if (ret != SECCOMP_PHASE1_OK) {
    return ret; /* Go directly to phase 2 */
    }
    work &= ~_TIF_SECCOMP;
    }
    ...
    /* Do our best to finish without phase 2. */
    if (work == 0)
    return ret; /* seccomp and/or nohz only (ret == 0 here) */
    syscall_trace_enter()
    -> syscall_trace_enter_phase1()
    -> seccomp_phase1()
    -JOVY,FSOFMҎ߱Ͱ͸
    tracehook_report_syscall_entry()Ͱ5SBDFSʹ௨஌͍ͯ͠Δ
    // in Linux Kernel 4.8
    static long syscall_trace_enter(struct pt_regs *regs)
    {
    ...
    if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
    BUG_ON(regs != task_pt_regs(current));
    ...
    if ((emulated || (work & _TIF_SYSCALL_TRACE)) &&
    tracehook_report_syscall_entry(regs))
    return -1L;
    ...
    /*
    * Do seccomp after ptrace, to catch any tracer changes.
    */
    if (work & _TIF_SECCOMP) {
    struct seccomp_data sd;

    View Slide

  52. #ZQBTT4FDDPNQ
    -JOVY,FSOFMҎલͰ͸ptrace(2)ΛڐՄ͍ͯ͠Δͱ#ZQBTTͰ͖ͯ͠·͏
    Process
    getpid(2)
    👮getpid(2)Ϥγο
    Seccomp
    Tracer
    Ϩδελͷঢ়ଶΛexecve(2)ʹมߋ
    execve(2)

    View Slide

  53. #ZQBTT4FDDPNQ
    -JOVY,FSOFMҎ߱͸ptrace௨஌ޙʹνΣοΫ
    Process
    getpid(2)
    👮execve(2)͸ΞΧϯͰ
    Seccomp
    Tracer
    Ϩδελͷঢ়ଶΛexecve(2)ʹมߋ
    execve(2)

    View Slide

  54. #ZQBTT4FDDPNQ
    mkdirΛېࢭͨ͠%PDLFSίϯςφͰmkdirΛ࣮ߦ͠·͢
    void attack()
    {
    int rc;
    // mkdir("dir", 0777);
    // Ҿ਺෦෼ʹ SYS_mkdir ͱͦͷҾ਺Λ༩͓͑ͯ͘
    syscall(SYS_getpid, SYS_mkdir, "dir", 0777);
    }
    int main()
    {
    ...
    switch( (pid = fork()) ) {
    case -1: die("Failed fork");
    case 0:
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);
    kill(getpid(), SIGSTOP);
    attack();
    return 0;
    }
    waitpid(pid, 0, 0);
    ...
    forkͯ͠ࢠϓϩηεΛτϨʔε
    ࢠϓϩηεͰ͸ڐՄ͞Ε͍ͯΔTZTDBMM getpid
    ΛݺͿ
    ͜ͷͱ͖ɺϨδελௐ੔ͷͨΊʹmkdirͱͦͷҾ਺Λ༩͑Δ

    View Slide

  55. #ZQBTT4FDDPNQ
    ਌ϓϩηε τϨʔαʔ
    ଆͰϨδελΛมߋ͢Δ
    ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
    if (waitpid(pid, &st, __WALL) == -1) {
    break;
    }
    if (!(WIFSTOPPED(st) && WSTOPSIG(st) == SIGTRAP)) {
    break;
    }
    ptrace(PTRACE_GETREGS, pid, NULL, &regs);
    printf("orig_rax = %lld\n", regs.orig_rax);
    if (regs.rax != -ENOSYS) {
    continue;
    }
    if (regs.orig_rax == SYS_getpid) {
    regs.orig_rax = regs.rdi;
    regs.rdi = regs.rsi;
    regs.rsi = regs.rdx;
    regs.rdx = regs.r10;
    regs.r10 = regs.r8;
    regs.r8 = regs.r9;
    regs.r9 = 0;
    ptrace(PTRACE_SETREGS, pid, NULL, &regs);
    }
    ࢠϓϩηεΛ࠶։ͯ͠γεςϜίʔϧݺͼग़͠ͷλΠϛϯάͰ
    ϨδελΛऔಘ
    Ϩδελͷorgi_raxʹ͸γεςϜίʔϧ൪߸͕ೖ͍ͬͯΔͷ
    ͰɺͦΕ͕getpidͰ͋Ε͹mkdirʹมߋ͢Δ
    getpidݺͼग़࣌͠ʹmkdirͱͦͷҾ਺ΛؚΊ͍ͯͨͷ
    ͰɺͣΒ͚ͩ͢

    View Slide

  56. #ZQBTT4FDDPNQ
    4FDDPNQͰmkdir(2)Λېࢭ͍ͯ͠Δ%PDLFSίϯςφͷதͰmkdir(2)Λ࣮ߦ
    IUUQTBTDJJOFNBPSHBK5+N-77Z$D'LJT+910&/L

    View Slide

  57. ·ͱΊ

    View Slide

  58. ·ͱΊ
    4FDDPNQͱ͸
    γεςϜίʔϧ΍ͦͷҾ਺Λ੍ݶ͢Δ͜ͱͰϓϩηεΛखܰʹαϯυϘοΫεԽ͢Δٕज़ɻ
    NPEFͱNPEF͕͋ΓɺNPEFͰ͸#1'Λ࢖ͬͯϑΟϧλΛॻ͘ɻ
    4FDDPNQͷద༻ʹ͍ͭͯ
    MJCTFDDPNQΛ࢖͏͜ͱͰָʹϑΟϧλΛॻ͘͜ͱ͕Ͱ͖Δɻ
    0$*3VOUJNFͰ͸4FDDPNQ1SPpMFͱݺ͹ΕΔ+40/Ͱద༻Ͱ͖Δɻ
    ϑΟϧλ΍1SPpMFͷੜ੒ʹ͸TUSBDF F#1'ͳͲ͕ར༻Ͱ͖ɺEPDLFSTMJNͳͲͷπʔϧ͕ଟʑ͋Δɻ
    4FDDPNQͷηΩϡϦςΟ
    ϓϩϑΝΠϧͷੜ੒ํ๏ʹΑͬͯ͸ϓϩάϥϜͷॳظԽ෦෼΋ϧʔϧʹؚΊͯ͠·͏ͨΊɺϧʔϧ͕؇͘ͳͬͯ͠
    ·͏͜ͱ͕͋ΔͷͰ஫ҙɻ
    -JOVY,FSOFMҎલ͸ptrace(2)͕ར༻Ͱ͖Δ؀ڥͷ৔߹ɺόΠύε͕Մೳɻېࢭ͞Ε͍ͯΔγεςϜίʔϧ
    Λݺͼग़͢͜ͱ͕Ͱ͖Δɻ

    View Slide

  59. ࢀߟࢿྉ
    IUUQTXXXLFSOFMPSHEPDIUNMWVTFSTQBDFBQJTFDDPNQ@pMUFSIUNM
    IUUQTNBOPSHMJOVYNBOQBHFTNBOTFDDPNQIUNM
    IUUQTFMJYJSCPPUMJODPNMJOVYMBUFTUTPVSDFLFSOFMTFDDPNQD
    IUUQTMXOOFU"SUJDMFT
    IUUQTCMPHDMPVEqBSFDPNTBOECPYJOHJOMJOVYXJUI[FSPMJOFTPGDPEF
    IUUQTNNJIBUFOBCMPHDPNFOUSZ
    IUUQTBKYDIBQNBOHJUIVCJPMJOVYTFDDPNQBOETFDDPNQCQGIUNM

    View Slide