GNU/Linux >> Belajar Linux >  >> Linux

Perbedaan antara kemampuan linux dan seccomp

Saya ingin mengetahui perbedaan pasti antara kemampuan linux dan seccomp.

Saya akan menjelaskan tepatnya perbedaan di bawah, tapi inilah penjelasan umumnya:Kemampuan melibatkan berbagai pemeriksaan dalam fungsi kernel yang dapat dijangkau oleh syscalls. Jika pemeriksaan gagal (yaitu proses tidak memiliki kemampuan yang diperlukan), syscall biasanya dibuat untuk mengembalikan kesalahan. Pemeriksaan dapat dilakukan tepat di awal syscall tertentu, atau lebih dalam di kernel di area yang mungkin dapat dijangkau melalui beberapa syscall yang berbeda (seperti menulis ke file istimewa tertentu).

Seccomp adalah filter syscall yang diterapkan ke semua syscall sebelum dijalankan. Suatu proses dapat mengatur filter yang memungkinkan mereka mencabut haknya untuk menjalankan syscall tertentu, atau argumen khusus untuk syscall tertentu. Filter biasanya dalam bentuk bytecode eBPF, yang digunakan kernel untuk memeriksa apakah syscall diizinkan atau tidak untuk proses itu. Setelah diterapkan, filter tidak dapat dilonggarkan sama sekali, hanya dibuat lebih ketat (dengan asumsi syscall yang bertanggung jawab untuk memuat kebijakan seccomp masih diizinkan).

Perhatikan bahwa beberapa syscall tidak dapat dibatasi oleh seccomp atau kapabilitas karena itu bukan syscall yang sebenarnya. Ini adalah kasus dengan panggilan vDSO, yang merupakan implementasi ruang pengguna dari beberapa syscall yang tidak benar-benar membutuhkan kernel. Mencoba memblokir getcpu() atau gettimeofday() sia-sia karena alasan ini, karena suatu proses akan menggunakan vDSO alih-alih syscall asli. Untungnya, syscall ini (dan implementasi virtual terkaitnya) sebagian besar tidak berbahaya.

Juga apakah kemampuan linux menggunakan seccomp secara internal atau sebaliknya atau keduanya sama sekali berbeda.

Mereka diimplementasikan dengan sangat berbeda secara internal. Saya menulis jawaban lain di tempat lain tentang implementasi saat ini dari berbagai teknologi kotak pasir yang menjelaskan perbedaannya dan untuk apa teknologi tersebut.

Kemampuan

Banyak syscall yang melakukan hal-hal istimewa mungkin menyertakan pemeriksaan internal untuk memastikan bahwa proses pemanggilan memiliki kemampuan yang memadai. Kernel menyimpan daftar kapabilitas yang dimiliki suatu proses, dan begitu suatu proses kehilangan kapabilitas, ia tidak dapat mendapatkannya kembali. Misalnya, mencoba menulis ke /dev/cpu/*/msr akan gagal kecuali proses memanggil open() syscall memiliki CAP_SYS_RAWIO . Ini dapat dilihat pada kode sumber kernel yang bertanggung jawab untuk memodifikasi MSR (fitur CPU tingkat rendah):

static int msr_open(struct inode *inode, struct file *file)
{
    unsigned int cpu = iminor(file_inode(file));
    struct cpuinfo_x86 *c;

    if (!capable(CAP_SYS_RAWIO))
        return -EPERM;

    if (cpu >= nr_cpu_ids || !cpu_online(cpu))
        return -ENXIO;  /* No such CPU */

    c = &cpu_data(cpu);
    if (!cpu_has(c, X86_FEATURE_MSR))
        return -EIO;    /* MSR not supported */

    return 0;
}

Beberapa syscalls tidak akan berjalan sama sekali jika kemampuan yang benar tidak ada, seperti vhangup() :

SYSCALL_DEFINE0(vhangup)
{
    if (capable(CAP_SYS_TTY_CONFIG)) {
        tty_vhangup_self();
        return 0;
    }
    return -EPERM;
}

Kemampuan dapat dianggap sebagai kelas yang luas dari fungsionalitas istimewa yang dapat dihapus secara selektif dari proses atau pengguna. Fungsi khusus yang memiliki pemeriksaan kemampuan bervariasi dari versi kernel ke versi kernel, dan sering terjadi pertengkaran antara pengembang kernel mengenai apakah fungsi yang diberikan harus memerlukan kemampuan untuk dijalankan atau tidak. Umumnya , mengurangi kemampuan dari suatu proses meningkatkan keamanan dengan mengurangi jumlah tindakan istimewa yang dapat dilakukannya. Perhatikan bahwa beberapa kemampuan dianggap setara dengan akar , artinya, meskipun Anda menonaktifkan semua kemampuan lainnya, dalam beberapa kondisi, kemampuan tersebut dapat digunakan untuk mendapatkan kembali izin penuh. Banyak contoh yang diberikan oleh pencipta grsecurity, Brad Spengler. Contoh yang jelas adalah CAP_SYS_MODULE yang memungkinkan memuat modul kernel sewenang-wenang. Lainnya adalah CAP_SYS_ADMIN yang merupakan kemampuan catch-all yang hampir setara dengan root.

Mode 1 detik

Ada dua jenis seccomp:mode 1 (ketat) dan mode 2 (filter). Mode 1 sangat membatasi dan, setelah diaktifkan, hanya mengizinkan empat syscall. Syscall ini adalah read() , write() , exit() , dan rt_sigreturn() . Sebuah proses segera mengirimkan fatal SIGKILL sinyal dari kernel jika pernah mencoba menggunakan syscall yang tidak ada dalam daftar putih. Mode ini adalah mode seccomp asli dan tidak memerlukan pembuatan dan pengiriman bytecode eBPF ke kernel. Syscall khusus dibuat, setelah itu mode 1 akan aktif selama masa proses:seccomp(SECCOMP_SET_MODE_STRICT) atau prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT) . Setelah aktif, tidak dapat dimatikan.

Berikut adalah contoh program yang mengeksekusi bytecode dengan aman yang mengembalikan 42:

#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <linux/seccomp.h>

/* "mov al,42; ret" aka "return 42" */
static const unsigned char code[] = "\xb0\x2a\xc3";

void main(void)
{
    int fd[2], ret;

    /* spawn child process, connected by a pipe */
    pipe(fd);
    if (fork() == 0) {
        close(fd[0]);

        /* enter mode 1 seccomp and execute untrusted bytecode */
        prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
        ret = (*(uint8_t(*)())code)();

        /* send result over pipe, and exit */
        write(fd[1], &ret, sizeof(ret));
        syscall(SYS_exit, 0);
    } else {
        close(fd[1]);

        /* read the result from the pipe, and print it */
        read(fd[0], &ret, sizeof(ret));
        printf("untrusted bytecode returned %d\n", ret);
    }
}

Mode 1 adalah mode asli, dan ditambahkan dengan tujuan memungkinkan untuk mengeksekusi kode byte yang tidak dipercaya untuk perhitungan mentah. Proses broker akan memotong anak (dan mungkin mengatur komunikasi melalui pipa), dan anak akan mengaktifkan seccomp, mencegahnya melakukan apa pun selain membaca dan menulis dari deskriptor file yang sudah terbuka, dan keluar. Proses anak ini kemudian dapat mengeksekusi bytecode yang tidak dipercaya dengan aman. Tidak banyak orang yang menggunakan mode ini, tetapi sebelum Linus dapat mengeluh cukup keras untuk mematikannya, tim Google Chrome menyatakan keinginan untuk menggunakannya untuk browser mereka. Ini menciptakan minat baru pada seccomp dan menyelamatkannya dari kematian sebelum waktunya.

Mode 2 detik

Mode kedua, filter, juga disebut seccomp-bpf, memungkinkan proses untuk mengirim kebijakan filter berbutir halus ke kernel, mengizinkan atau menolak seluruh syscall, atau argumen syscall tertentu atau rentang argumen. Kebijakan tersebut juga menentukan apa yang terjadi jika terjadi pelanggaran (misalnya, haruskah proses dimatikan, atau haruskah syscall ditolak saja?) dan apakah pelanggaran harus dicatat atau tidak. Karena syscall Linux disimpan dalam register dan dengan demikian hanya dapat berupa bilangan bulat, tidak mungkin memfilter konten memori yang mungkin ditunjuk oleh argumen syscall. Misalnya, meskipun Anda dapat mencegah open() dari dipanggil dengan O_RDWR berkemampuan tulis atau O_WRONLY bendera, Anda tidak dapat memasukkan jalur individual yang dibuka ke daftar putih. Alasan untuk ini adalah, untuk seccomp, jalur tidak lebih dari penunjuk ke memori yang berisi jalur sistem file yang diakhiri dengan null. Tidak ada cara untuk menjamin bahwa memori yang menahan jalur belum diubah oleh utas saudara antara penerusan pemeriksaan seccomp dan penunjuk yang direferensikan, singkatnya memasukkannya ke dalam memori hanya-baca dan menolak akses syscall terkait memori ke sana. Seringkali perlu menggunakan LSM seperti AppArmor.

Ini adalah contoh program yang menggunakan mode 2 seccomp untuk memastikannya hanya dapat mencetak PID saat ini. Program ini menggunakan pustaka libseccomp yang membuat pembuatan filter eBPF seccomp lebih mudah, meskipun juga memungkinkan untuk melakukannya dengan cara yang sulit tanpa pustaka pengabstraksi.

#include <seccomp.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

void main(void)
{
    /* initialize the libseccomp context */
    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);

    /* allow exiting */
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

    /* allow getting the current pid */
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);

    /* allow changing data segment size, as required by glibc */
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);

    /* allow writing up to 512 bytes to fd 1 */
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 2,
        SCMP_A0(SCMP_CMP_EQ, 1),
        SCMP_A2(SCMP_CMP_LE, 512));

    /* if writing to any other fd, return -EBADF */
    seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EBADF), SCMP_SYS(write), 1,
        SCMP_A0(SCMP_CMP_NE, 1));

    /* load and enforce the filters */
    seccomp_load(ctx);
    seccomp_release(ctx);

    printf("this process is %d\n", getpid());
}

Mode 2 seccomp dibuat karena mode 1 jelas memiliki keterbatasan. Tidak setiap tugas dapat dipisahkan menjadi proses bytecode murni yang dapat dijalankan dalam proses anak dan berkomunikasi melalui pipa atau memori bersama. Mode ini memiliki lebih banyak fitur dan fungsinya terus diperluas secara perlahan. Namun, itu masih memiliki kelemahan. Aman menggunakan mode 2 seccomp membutuhkan pemahaman yang mendalam tentang syscalls (ingin memblokir kill() dari membunuh proses lain? Buruknya, Anda dapat mematikan proses dengan fcntl() juga!). Itu juga rapuh, karena perubahan pada libc yang mendasarinya dapat menyebabkan kerusakan. glibc open() fungsi, misalnya, tidak lagi selalu menggunakan syscall dari nama tersebut dan sebaliknya dapat menggunakan openat() , melanggar kebijakan yang hanya mengizinkan yang sebelumnya.


Linux
  1. Apa perbedaan antara wadah Linux dan gambar?

  2. Perbedaan Antara Perintah "su" dan "su -" di Linux

  3. Perbedaan Antara [[ $a ==Z* ]] Dan [ $a ==Z* ]?

  1. Linux – Perbedaan Antara Ruang Pengguna dan Ruang Kernel?

  2. Linux – Perbedaan Antara Pts Dan Tty?

  3. Apa perbedaan antara 'temukan' dan 'temukan' di Linux?

  1. Pelajari Perbedaan Antara Perintah "su" dan "su -" di Linux

  2. Apa perbedaan antara Suspend dan Hibernate di Linux

  3. Linux – Perbedaan Reboot , Init 6 Dan Shutdown -r Sekarang?