Libseccomp: BUG: jangan hasilkan BPF untuk pseudo-syscalls

Dibuat pada 15 Jun 2020  ·  20Komentar  ·  Sumber: seccomp/libseccomp

Lihat masalah #249, khususnya komentar ini :

Mengapa memeriksa syscall 4294957285 yang tidak ada dalam bpf yang sebenarnya dihasilkan?

Seharusnya tidak, dan kami tidak terbiasa melakukan itu, tetapi sepertinya libseccomp saat ini memiliki bug di sini.

Kredit ke @vt-alt untuk melaporkan bug ini.

bug prioritmedium

Semua 20 komentar

REPRODUKSI DIHAPUS UNTUK MENINGKATKAN DRAFT DI BAWAH INI

Agar jelas, kita masih harus memancarkan pseudo-syscalls di PFC, untuk tujuan debugging, tetapi kita tidak boleh memancarkan aturan filter BPF (tidak berguna).

Terima kasih telah membuat masalah dari laporan saya.

Agar jelas, kita masih harus memancarkan pseudo-syscalls di PFC, untuk tujuan debugging, tetapi kita tidak boleh memancarkan aturan filter BPF (tidak berguna).

Tolong pikirkan kembali ini. Saya percaya ini hanya akan memperumit dan mengaburkan hal-hal jika PFC tidak mencerminkan BPF.

Tolong pikirkan kembali ini. Saya percaya ini hanya akan memperumit dan mengaburkan hal-hal jika PFC tidak mencerminkan BPF.

Jika syscall hilang dari PFC, kami akan menerima sejumlah laporan bug palsu yang berbicara tentang bagaimana perpustakaan gagal menambahkan filter untuk syscalls (tidak ada).

Bagi mereka yang memahami konsep pseudo-syscalls, ini adalah latihan sepele untuk menghapusnya dari output PFC. Perlu juga disebutkan bahwa output PFC tidak dimaksudkan sebagai salinan persis dari output BPF, itu ada hanya sebagai alat debugging dan cara mudah untuk memvisualisasikan kode filter yang dihasilkan.

cara mudah untuk memvisualisasikan kode filter yang dihasilkan

Tapi, itu tidak akan memvisualisasikan kode filter _generated_ karena dalam kode pseudo syscalls yang dihasilkan seharusnya tidak ada.

Jika syscall hilang dari PFC, kami akan menerima sejumlah laporan bug palsu yang berbicara tentang bagaimana perpustakaan gagal menambahkan filter untuk syscalls (tidak ada).

Jauh lebih mudah untuk memahami bahwa pemeriksaan pseudo syscall tidak boleh ada dalam kode (seperti dalam 'dioptimalkan', karena '' tidak ada panggilan syscall untuk arch'), daripada perbedaan logika (ada dan tidak adanya persyaratan) di visualisasi kode dan kode yang sebenarnya.

Saya lebih suka PFC untuk mencerminkan bpf daripada menggunakan scmp_bpf_disasm karena keluaran PFC jauh lebih mudah dibaca.

Saya memahami kekhawatiran Anda @vt-alt, dan mungkin dalam rilis mendatang kami melakukannya dengan PFC, tetapi menurut saya menghapus pseudo-syscalls dari output PFC adalah kesalahan.

@drakenclimber apakah Anda punya pendapat kuat tentang ini?

Reproduksi yang direvisi untuk x86_64:

#include <stdlib.h>
#include <errno.h>

#include <seccomp.h>

#include "util.h"

int main(int argc, char *argv[])
{
        int rc;
        struct util_options opts;
        scmp_filter_ctx ctx = NULL;

        rc = util_getopt(argc, argv, &opts);
        if (rc < 0)
                goto out;

        ctx = seccomp_init(SCMP_ACT_KILL);
        if (ctx == NULL)
                return ENOMEM;

        rc = seccomp_arch_add(ctx, SCMP_ARCH_X32);
        if (rc < 0)
                goto out;

        rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
        if (rc < 0)
                goto out;
        rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(arm_fadvise64_64), 0);
        if (rc < 0)
                goto out;

        rc = util_filter_output(&opts, ctx);
        if (rc)
                goto out;

out:
        seccomp_release(ctx);
        return (rc < 0 ? -rc : rc);
}

DIPERBARUI: memperbaiki masalah dengan TSKIP

Belum sepenuhnya diuji, tetapi ini mungkin perbaikan - dapatkah Anda memverifikasi ini masuk akal untuk algoritme pengoptimalan pohon seimbang @drakenclimber?

diff --git a/src/arch-arm.c b/src/arch-arm.c
index 3465111..4dd4b63 100644
--- a/src/arch-arm.c
+++ b/src/arch-arm.c
@@ -54,7 +54,7 @@ int arm_syscall_resolve_name_munge(const char *name)
        if (sys == __NR_SCMP_ERROR)
                return sys;

-       return sys + __SCMP_NR_BASE;
+       return (sys | __SCMP_NR_BASE);
 }

 /**
@@ -68,7 +68,7 @@ int arm_syscall_resolve_name_munge(const char *name)
  */
 const char *arm_syscall_resolve_num_munge(int num)
 {
-       return arm_syscall_resolve_num(num - __SCMP_NR_BASE);
+       return arm_syscall_resolve_num(num & (~__SCMP_NR_BASE));
 }

 const struct arch_def arch_def_arm = {
diff --git a/src/arch-x32.c b/src/arch-x32.c
index 7b97fb3..3890968 100644
--- a/src/arch-x32.c
+++ b/src/arch-x32.c
@@ -43,7 +43,7 @@ int x32_syscall_resolve_name_munge(const char *name)
        if (sys == __NR_SCMP_ERROR)
                return sys;

-       return sys + X32_SYSCALL_BIT;
+       return (sys | X32_SYSCALL_BIT);
 }

 /**
@@ -57,7 +57,7 @@ int x32_syscall_resolve_name_munge(const char *name)
  */
 const char *x32_syscall_resolve_num_munge(int num)
 {
-       return x32_syscall_resolve_num(num - X32_SYSCALL_BIT);
+       return x32_syscall_resolve_num(num & (~X32_SYSCALL_BIT));
 }

 const struct arch_def arch_def_x32 = {
diff --git a/src/gen_bpf.c b/src/gen_bpf.c
index 55a7958..ae9c3f4 100644
--- a/src/gen_bpf.c
+++ b/src/gen_bpf.c
@@ -1555,6 +1555,10 @@ static int _gen_bpf_syscalls(struct bpf_state *state,
        for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) {
                if (!s_iter->valid)
                        continue;
+               /* skip pseudo-syscalls */
+               if ((s_iter->num & 0x80000000) &&
+                   (state->attr->api_tskip == 0 || s_iter->num != -1))
+                       continue;

                if (*bintree_levels > 0 &&
                    ((syscall_cnt + empty_cnt) % SYSCALLS_PER_NODE) == 0)

Saya memahami kekhawatiran Anda @vt-alt, dan mungkin dalam rilis mendatang kami melakukannya dengan PFC, tetapi menurut saya menghapus pseudo-syscalls dari output PFC adalah kesalahan.

@drakenclimber apakah Anda punya pendapat kuat tentang ini?

Tidak juga, tapi saya pikir akar masalahnya adalah output PFC digunakan dalam berbagai cara yang berbeda:

  1. Seperti disebutkan di atas, ini adalah cara mudah bagi pengguna baru untuk memverifikasi filter mereka secara kasar
  2. Pengguna yang lebih mahir mengharapkannya menjadi pendekatan yang mendekati filter BPF yang sebenarnya

Mungkin kita bisa menambahkan flag --no-pseudo-syscalls ke logika PFC? Maka itu bisa tetap sama untuk pengguna pemula, tetapi pengguna tingkat lanjut bisa mendapatkan perkiraan BPF yang lebih baik.

_UPDATED: memperbaiki masalah dengan TSKIP_

Belum sepenuhnya diuji, tetapi ini mungkin perbaikan - dapatkah Anda memverifikasi ini masuk akal untuk algoritme pengoptimalan pohon seimbang @drakenclimber?

Akan melakukan. Saya ingin melihat apakah saya dapat membuat tes otomatis yang akan mereproduksi skenario ini.

_UPDATED: memperbaiki masalah dengan TSKIP_
Belum sepenuhnya diuji, tetapi ini mungkin perbaikan - dapatkah Anda memverifikasi ini masuk akal untuk algoritme pengoptimalan pohon seimbang @drakenclimber?

Akan melakukan. Saya ingin melihat apakah saya dapat membuat tes otomatis yang akan mereproduksi skenario ini.

Dan tentu saja saya akan mulai dengan tes reproduksi yang Anda miliki di atas. Terima kasih!

_UPDATED: memperbaiki masalah dengan TSKIP_

Belum sepenuhnya diuji, tetapi ini mungkin perbaikan - dapatkah Anda memverifikasi ini masuk akal untuk algoritme pengoptimalan pohon seimbang @drakenclimber?

Pohon biner menghitung sebelumnya kapan akumulator perlu dimodifikasi, dan ini adalah cara mengetahui untuk memasukkan logika jge . Mencabut syscalls (seperti proposal di atas) saat membangun filter merusak logika ini.

Saya belum sepenuhnya menguji perubahan saya :), tapi saya cukup yakin kita akan membutuhkan sesuatu seperti ini untuk membuat pohon biner bekerja dengan penghapusan pseudo-syscalls. Saya membuat pohon biner BPF menggunakan ini dan itu terlihat masuk akal. Saat kami semakin dekat dengan solusi siap produksi, saya akan memverifikasinya sepenuhnya.

@@ -1532,11 +1532,31 @@ static int _gen_bpf_syscalls(struct bpf_state *state,
                _sys_sort(db_secondary->syscalls, &s_head, &s_tail, optimize);

        if (optimize == 2) {
+               /* since pseudo-syscalls are removed from the filter, we need
+                * to calculate the syscall count by hand
+                */
+               for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) {
+                       if (!s_iter->valid)
+                               continue;
+
+                       /* skip pseudo-syscalls */
+                       if ((s_iter->num & 0x80000000) &&
+                           (state->attr->api_tskip == 0 || s_iter->num != -1))
+                               continue;
+
+                       syscall_cnt++;
+               }
+
                rc = _gen_bpf_init_bintree(&bintree_hashes, &bintree_syscalls,
-                                          bintree_levels, db->syscall_cnt,
+                                          bintree_levels, syscall_cnt,
                                           &empty_cnt);
                if (rc < 0)
                        goto out;
+
+               /* reset the syscall_cnt variable because later in this
+                * function it's used as a counter
+                */
+               syscall_cnt = 0;
        }

Ini bisa dibuat lebih pintar/lebih cepat jika kita memiliki variabel dalam struktur db yang melacak jumlah panggilan syscall yang "valid".

Mungkin kita bisa menambahkan flag --no-pseudo-syscalls ke logika PFC?

Kemana perginya bendera ini? Saya tidak berpikir kami menginginkan ini sebagai opsi waktu pembuatan. Saya kira kita bisa menambahkan opsi filter, tapi saya tidak terlalu tertarik dengan itu. Saya akan memilih untuk tetap menggunakan pseudo-syscalls di PFC tetapi menjatuhkannya dari BPF (jelas) untuk saat ini, dan jika kita perlu menambah ini di beberapa titik di masa depan kita bisa.

Saya belum sepenuhnya menguji perubahan saya :), tapi saya cukup yakin kita akan membutuhkan sesuatu seperti ini untuk membuat pohon biner bekerja dengan penghapusan pseudo-syscalls. Saya membuat pohon biner BPF menggunakan ini dan itu terlihat masuk akal. Saat kami semakin dekat dengan solusi siap produksi, saya akan memverifikasinya sepenuhnya.

Saya menduga ini akan merusak optimasi pohon.

@drakenclimber mengingat ini berdampak pada penyortiran pohon lebih dari pengoptimalan standar, apakah Anda ingin mengambil masalah ini? Jangan ragu untuk mencuri sebanyak atau sesedikit kode yang saya salin dan tempel di atas jika masuk akal.

Satu hal yang saya pikir harus kita lakukan adalah perubahan pada "arch-arm.c" dan "arch-x32.c" karena lebih masuk akal.

Mungkin kita bisa menambahkan flag --no-pseudo-syscalls ke logika PFC?

Kemana perginya bendera ini? Saya tidak berpikir kami menginginkan ini sebagai opsi waktu pembuatan. Saya kira kita bisa menambahkan opsi filter, tapi saya tidak terlalu tertarik dengan itu. Saya akan memilih untuk tetap menggunakan pseudo-syscalls di PFC tetapi menjatuhkannya dari BPF (jelas) untuk saat ini, dan jika kita perlu menambah ini di beberapa titik di masa depan kita bisa.

Saya akui bahwa saya mengetik sebelum saya berpikir. ;)

Ya, itu harus menjadi opsi filter dan itu terasa salah. Saya setuju; mari kita lakukan seperti yang Anda uraikan di atas. Jika kami terus mendapatkan pertanyaan, maka kami dapat mengunjungi kembali.

Saya belum sepenuhnya menguji perubahan saya :), tapi saya cukup yakin kita akan membutuhkan sesuatu seperti ini untuk membuat pohon biner bekerja dengan penghapusan pseudo-syscalls. Saya membuat pohon biner BPF menggunakan ini dan itu terlihat masuk akal. Saat kami semakin dekat dengan solusi siap produksi, saya akan memverifikasinya sepenuhnya.

Saya menduga ini akan merusak optimasi pohon.

@drakenclimber mengingat ini berdampak pada penyortiran pohon lebih dari pengoptimalan standar, apakah Anda ingin mengambil masalah ini? Jangan ragu untuk mencuri sebanyak atau sesedikit kode yang saya salin dan tempel di atas jika masuk akal.

Satu hal yang saya pikir harus kita lakukan adalah perubahan pada "arch-arm.c" dan "arch-x32.c" karena lebih masuk akal.

Tentu. Saya bisa memiliki yang ini.

@drakenclimber "> Seperti disebutkan di atas, ini adalah cara mudah bagi pengguna baru untuk memverifikasi filter mereka secara kasar"

"Pseudo syscall" tidak ada di kernel dan juga bukan konsep yang terkenal. Ini murni penemuan libseccomp dan tidak dijelaskan di sini. Hanya menyatakan mereka adalah angka negatif dan mereka muncul ketika syscall diberikan tidak ada untuk arsitektur. Bagaimana ini berbeda dari syscall yang tidak ada? Untuk tujuan apa mereka negatif? Konsep pseudo syscall benar-benar membingungkan bagi pengguna baru.

Saya tidak percaya pengguna baru (er) ingin melihat syscalls yang tidak ada diperiksa di filter mereka.

Izinkan saya menambahkan satu poin lagi. Semua ini di bidang keamanan, di mana hanya pemahaman yang cermat dan terperinci yang bekerja. Anda membuat konsep baru yang tidak jelas (dari pseudo syscalls) dan perbedaan antara representasi (bpf dan pfc). Apakah ini benar-benar ditujukan untuk pengguna baru, untuk lebih membingungkan mereka?

@vt-alt terima kasih telah mengungkapkan kekhawatiran Anda, tetapi untuk rilis v2.5.0 kami akan menekan pseudo-syscalls dari filter BPF, dan terus menampilkannya di filter PFC. Saya menyadari bahwa Anda mungkin tidak setuju dengan keputusan ini, tetapi saya dengan hormat meminta Anda untuk menghormati keputusan ini. Dalam rilis mendatang kami akan melakukan pekerjaan yang lebih baik dengan menjelaskan tujuan di balik pseudo-syscalls (ini untuk beberapa dukungan ABI) dan mendokumentasikannya di halaman manual; Saya telah membuat masalah untuk itu (tautan di bawah), Anda dipersilakan dan didorong untuk berpartisipasi dalam diskusi itu dan PR apa pun yang dihasilkan. Mungkin juga kami merevisi pendekatan kami terhadap filter PFC di masa mendatang, tetapi saya tidak ingin menjanjikan apa pun di sini.

Sekali lagi, terima kasih telah membawa masalah BPF menjadi perhatian kami; Anda telah membantu meningkatkan rilis libseccomp berikutnya!

Penutupan melalui #264.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat