Libseccomp: BUG: Penanganan A2 Rusak oleh src/db.c Pengerjaan Ulang

Dibuat pada 26 Feb 2018  ·  18Komentar  ·  Sumber: seccomp/libseccomp

Untuk menguji peningkatan kinerja pohon biner yang saya usulkan, saya menulis seperangkat aturan yang tidak realistis untuk read() dan argumen ukuran buffernya (A2). Tetapi tampaknya komit pengerjaan ulang src/db.c (ce3dda9a1) merusak pemrosesan A2 - setidaknya untuk kasus uji ini.

Sebelum komit pengerjaan ulang db, baca seperti berikut - read(devzero_fd, buf, 8000) - dikembalikan -10 . Setelah komit ini, sekarang mengembalikan -5 .

Inilah kode C yang saya gunakan untuk membuat aturan read() konyol saya:

        /* read */
        for (i = 5; i <= 12; i++) {
                rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(i), SCMP_SYS(read), 1,
                        SCMP_A2(SCMP_CMP_GT, 4 << i));
                if (rc < 0) {
                        fprintf(stdout, "%s:%d Failed to add read rule %d : rc = %d\n",
                                __FUNCTION__, __LINE__, i, rc);
                        goto error;
                }   
        }   
        rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
                SCMP_A2(SCMP_CMP_LE, 64));
        if (rc < 0) {
                fprintf(stdout, "%s:%d Failed to add read allow rule : rc = %d\n",
                        __FUNCTION__, __LINE__, rc);
                goto error;
        } 

Dan inilah PFC yang dihasilkannya:

  # filter for syscall "read" (0) [priority: 65525]
  if ($syscall == 0)
    if ($a2.hi32 >= 0)
      if ($a2.lo32 > 64)
      else
        action ALLOW;
      if ($a2.lo32 > 16384)
        action ERRNO(12);
      if ($a2.lo32 > 8192)
        action ERRNO(11);
      if ($a2.lo32 > 4096)
        action ERRNO(10);
      if ($a2.lo32 > 2048)
        action ERRNO(9);
      if ($a2.lo32 > 1024)
        action ERRNO(8);
      if ($a2.lo32 > 512)
        action ERRNO(7);
      if ($a2.lo32 > 256)
        action ERRNO(6);
      if ($a2.lo32 > 128)
        action ERRNO(5);
    else
      action ALLOW;
  # default action
  action ERRNO(34);
bug priorithigh

Semua 18 komentar

Omong-omong, saya akan melakukan apa yang saya bisa untuk membantu akar penyebabnya

Menggunakan scmp_bpf_disasm, libseccomp terbaru menempatkan lompatan dalam urutan yang salah

KEPALA

 0014: 0x25 0x11 0x00 0x00000080   jgt 128  true:0032 false:0015
 0015: 0x25 0x0f 0x00 0x00000100   jgt 256  true:0031 false:0016
 0016: 0x25 0x0d 0x00 0x00000200   jgt 512  true:0030 false:0017
 0017: 0x25 0x0b 0x00 0x00000400   jgt 1024 true:0029 false:0018
 0018: 0x25 0x09 0x00 0x00000800   jgt 2048 true:0028 false:0019
 0019: 0x25 0x07 0x00 0x00001000   jgt 4096 true:0027 false:0020
 0020: 0x25 0x05 0x00 0x00002000   jgt 8192 true:0026 false:0021
 0021: 0x25 0x03 0x00 0x00004000   jgt 16384 true:0025 false:0022
 0022: 0x25 0x01 0x00 0x00000040   jgt 64   true:0024 false:0023
 0023: 0x06 0x00 0x00 0x7fff0000   ret ALLOW

pra-pengerjaan ulang

 0014: 0x25 0x01 0x00 0x00000040   jgt 64   true:0016 false:0015
 0015: 0x06 0x00 0x00 0x7fff0000   ret ALLOW
 0016: 0x25 0x0f 0x00 0x00004000   jgt 16384 true:0032 false:0017
 0017: 0x25 0x0d 0x00 0x00002000   jgt 8192 true:0031 false:0018
 0018: 0x25 0x0b 0x00 0x00001000   jgt 4096 true:0030 false:0019
 0019: 0x25 0x09 0x00 0x00000800   jgt 2048 true:0029 false:0020
 0020: 0x25 0x07 0x00 0x00000400   jgt 1024 true:0028 false:0021
 0021: 0x25 0x05 0x00 0x00000200   jgt 512  true:0027 false:0022
 0022: 0x25 0x03 0x00 0x00000100   jgt 256  true:0026 false:0023
 0023: 0x25 0x01 0x00 0x00000080   jgt 128  true:0025 false:0024
 0024: 0x06 0x00 0x00 0x00050022   ret ERRNO(34)

Menarik. Jadi PFC tampaknya "benar", tetapi BPF yang dihasilkan adalah ... mundur. Aneh. Terutama mengingat bahwa komit tidak mengubah kode pembuatan BPF.

Saya ingin tahu apakah nilai prioritas entah bagaimana menjadi kacau?

Maaf atas ambiguitasnya. PFC (posting perubahan pengerjaan ulang) juga dalam urutan yang salah. PFC yang saya posting di atas adalah urutannya sebelum pengerjaan ulang db.c.

Inilah PFC yang saat ini dihasilkan oleh HEAD

  # filter for syscall "read" (0) [priority: 65525]
  if ($syscall == 0)
    if ($a2.hi32 >= 0)
      if ($a2.lo32 > 128)
        action ERRNO(5);
      if ($a2.lo32 > 256)
        action ERRNO(6);
      if ($a2.lo32 > 512)
        action ERRNO(7);
      if ($a2.lo32 > 1024)
        action ERRNO(8);
      if ($a2.lo32 > 2048)
        action ERRNO(9);
      if ($a2.lo32 > 4096)
        action ERRNO(10);
      if ($a2.lo32 > 8192)
        action ERRNO(11);
      if ($a2.lo32 > 16384)
        action ERRNO(12);
      if ($a2.lo32 > 64) 
      else
        action ALLOW;
    else
      action ALLOW;
  # default action
  action ERRNO(34);

Oke, itu sedikit lebih masuk akal. Masalahnya pasti ada di suatu tempat di lapisan db.

Agak lucu bagaimana persisnya terbalik.

Saya menemukan masalahnya. Dalam manajemen argumen rantai, perilaku lvl_nxt dan lvl_prv bertukar setelah pengerjaan ulang db.c besar-besaran. Beberapa perubahan kecil pada _db_tree_add() membuatnya cocok dengan perilaku libseccomp sebelumnya.

Inilah cabang dengan perbaikannya
https://github.com/drakenclimber/libseccomp/tree/issues/112

Saya akan membersihkan perubahan, menambahkan satu atau dua tes, dan memastikan cakupan kode sudah habis.

Saya menemukan waktu pagi ini, mungkin tepat sebelum Anda memposting hal di atas, dan memutuskan untuk melihat ini sedikit. Sepertinya kami sampai pada kesimpulan yang hampir sama, meskipun perbaikannya sedikit berbeda. Ini adalah perbaikan saya saat ini, meskipun seperti milik Anda, perlu beberapa pekerjaan/pembersihan tambahan:

Saya tidak yakin pendekatan mana yang lebih saya sukai saat ini, saya perlu memikirkan ini sedikit, pikiran?

Hmmm... Saya tidak akan berbohong; Saya tidak terpikat dengan salah satu perbaikan pada saat ini.

Milik saya sederhana, tetapi sepenuhnya mengabaikan _db_tree_prune() yang - seperti yang Anda katakan di Intisari Anda - mungkin memiliki masalah serupa.

Saya suka ide Anda untuk mengerjakan ulang makro gt() untuk memanfaatkan makro lt() dan eq(), tetapi mereka semakin berat - terutama lt(). Apakah ada alasan untuk tidak mengonversi lt() ke fungsi sebaris?
EDIT - Saya baru tahu Anda membuat komentar serupa di intinya.

Saya menjalankan gdb terhadap libseccomp dan HEAD lama, dan perilaku lvl_prv dan lvl_nxt memang berubah, tetapi mungkin itu bukan masalah besar karena ini adalah variabel internal yang tidak boleh dilihat siapa pun kecuali kita.

Saya kira setelah semua bertele-tele ini ... Saya tidak tahu. Saya setuju, saya harus memikirkannya;)

Hmmm... Saya tidak akan berbohong; Saya tidak terpikat dengan salah satu perbaikan pada saat ini.

Saya khawatir bahwa ada beberapa bug halus dengan menyusun ulang level pohon seperti ini, meskipun sepertinya level tersebut disusun ulang oleh komit sebelumnya dan ini adalah salah satu bug halus.

Apa pun itu, saya ingin memahami seperti apa urutan yang diinginkan untuk suatu level: "terbesar" terlebih dahulu, atau "terbesar" terakhir? Setelah kami memahaminya, kami dapat melanjutkan dengan pengujian/perbaikan. Saya pikir jawabannya, jika tidak ada alasan lain selain kompatibilitas dengan rilis 2.x sebelumnya, adalah yang "terbesar" terlebih dahulu, tetapi saya tidak dapat mengatakannya dengan pasti saat ini.

Milik saya sederhana, tetapi sepenuhnya mengabaikan _db_tree_prune() yang - seperti yang Anda katakan di Intisari Anda - mungkin memiliki masalah serupa.

Mereka berdua pada dasarnya melakukan hal yang sama pada prinsipnya, milik saya melangkah lebih jauh dengan menambahkan beberapa kondisi tambahan dan membersihkan makro db_chain_lt(x,y).

Saya suka ide Anda untuk mengerjakan ulang makro gt() untuk memanfaatkan makro lt() dan eq(), tetapi mereka semakin berat - terutama lt(). Apakah ada alasan untuk tidak mengonversi lt() ke fungsi sebaris?

Sebagian besar alasan historis. Mereka memulai hidup sebagai makro yang jauh lebih sederhana, tetapi mereka telah tumbuh sedikit ke titik di mana saya pikir mereka mungkin seharusnya menjadi fungsi. Saya pikir itu juga akan baik untuk mengevaluasi apakah mereka benar-benar perlu ada di file header, saya yakin mereka hanya digunakan oleh src/db.c.

Saya menjalankan gdb terhadap libseccomp dan HEAD lama, dan perilaku lvl_prv dan lvl_nxt memang berubah, tetapi mungkin itu bukan masalah besar karena ini adalah variabel internal yang tidak boleh dilihat siapa pun kecuali kita.

Ya, ini adalah status/pohon internal, saya tidak terlalu khawatir tentang itu. Yang penting adalah kebenaran filter yang dihasilkan.

Saya kira setelah semua bertele-tele ini ... Saya tidak tahu. Saya setuju, saya harus memikirkannya;)

Heh. Mari kita beri ini satu atau dua hari dan berkumpul kembali :) Saat ini ini tidak memengaruhi versi yang dirilis, itu hanya di cabang master, jadi kami punya waktu untuk memperbaikinya.

Saat ini, ini tidak memengaruhi versi yang dirilis, itu hanya di cabang master, jadi kami punya waktu untuk memperbaikinya.

Kedengarannya bagus. Saya akan membuat beberapa tes sementara kita memikirkan rencana

Saya menulis sebuah program untuk mengevaluasi penanganan seccomp A2 saat ini. Seluruh program tersedia di sini:

https://Gist.github.com/drakenclimber/3c6b45ecd973ee495281ef225fa5e54a

Singkatnya, lebih besar dari aturan dihasilkan dalam urutan "terakhir dibuat" "diproses pertama".

  • Untuk filter di mana aturan > dibuat dalam urutan menaik , mis
    seccomp_rule_add(ctx, action1, syscall, 1, SCMP(SCMP_CMP_GT, 10)
    seccomp_rule_add(ctx, action2, syscall, 1, SCMP(SCMP_CMP_GT, 20)
    seccomp_rule_add(ctx, action3, syscall, 1, SCMP(SCMP_CMP_GT. 30)
    maka filter akan berperilaku secara koheren, mis
if (A2 > 30)
    do action3
if (A2 > 20)
    do action2
if (A2 > 10)
    do action1
  • Untuk filter di mana aturan > dibuat dalam urutan menurun , mis
    seccomp_rule_add(ctx, action3, syscall, 1, SCMP(SCMP_CMP_GT, 30)
    seccomp_rule_add(ctx, action2, syscall, 1, SCMP(SCMP_CMP_GT, 20)
    seccomp_rule_add(ctx, action1, syscall, 1, SCMP(SCMP_CMP_GT. 10)
    maka filter akan dibuat, tetapi berperilaku aneh. Kode mati akan diproduksi. Dua pernyataan if tidak dapat dijangkau
if (A2 > 10)
    do action1
if (A2 > 20)
    do action2
if (A2 > 30)
    do action1
  • Filter dengan beberapa operasi < A2 saat ini tidak diizinkan oleh seccomp. Ini tampak aneh karena saya tidak dapat menemukan cara untuk membuat <= setara dengan > filter di atas
tom<strong i="43">@OracleDesktop</strong> $ ./a2test 3
Failed to add rule
        action = 0x5000e op = 0x3 datum = 18000 rc = -17
Mode 3 (LE descending) test failed.  rc = -17
tom<strong i="46">@OracleDesktop</strong> $ ./a2test 4
Failed to add rule
        action = 0x50006 op = 0x3 datum = 250 rc = -17
Mode 4 (LE ascending) test failed.  rc = -17

Saya menduga logika else if terkubur jauh di src/db.c menyebabkan < gagal, mis. Saya tidak yakin apakah itu layak diubah/diperbaiki.

Saya akan mencoba dan mengubah beberapa kode ini menjadi pengujian otomatis sehingga kami dapat menangkap perilaku saat ini.

Seperti yang tertulis, intinya di sini gagal dalam tes otomatis yang saya tambahkan minggu lalu. Saya akan menggali dan mencoba mencari tahu mengapa.

 batch name: 43-sim-a2_order
 test mode:  c
 test type:  bpf-sim
Test 43-sim-a2_order%%001-00001 result:   SUCCESS
Test 43-sim-a2_order%%002-00001 result:   SUCCESS
Test 43-sim-a2_order%%003-00001 result:   SUCCESS
Test 43-sim-a2_order%%004-00001 result:   SUCCESS
Test 43-sim-a2_order%%005-00001 result:   SUCCESS
Test 43-sim-a2_order%%006-00001 result:   SUCCESS
Test 43-sim-a2_order%%007-00001 result:   SUCCESS
Test 43-sim-a2_order%%008-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%009-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%010-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%011-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%012-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%013-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%014-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%015-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%016-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%017-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%018-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%019-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%020-00001 result:   FAILURE bpf_sim resulted in ERRNO(5)

Buruk saya - saya salah menerapkan intinya. Ujian sedang berlalu. Fiuh :)

Ha! :)

Saya pikir saya menjalankan tes terhadapnya, tetapi saya bermain dengan banyak hal pada waktu itu, jadi saya pikir saya hanya salah mengingat. Terima kasih untuk terus melihat ini, saya masih sedikit macet dengan SELinux dan audit, tetapi karena kernel berada di -rc5 sekarang, saya berharap untuk segera tenang setelah saya meletakkan istirahat pada kode baru sebelum penggabungan jendela...

Jangan khawatir. Itu pasti prioritas yang lebih tinggi.

Saya telah menjalankan Intisari Anda melalui berbagai tes yang tidak realistis. Saya belum memecahkannya, tetapi saya juga hanya melatih sedikit demi sedikit _db_tree_prune() sejauh ini. Saya mulai merasa lebih nyaman dengan perubahan, tetapi saya ingin mendapatkan sedikit lebih banyak waktu untuk itu.

Saya menyodok dan mendorong kode _db_tree_prune() dan saya tidak dapat memecahkannya. Test 08-sim-subtree_checks benar-benar melakukan pekerjaan yang baik untuk menguji sebagian besar jalur kode dalam Prune().

Saya pikir perubahan dari inti Anda bagus untuk dilakukan.

Saya mengirimkan permintaan tarik #115. Saya pikir ini siap untuk bergulir

Penutupan karena ini sekarang harus diselesaikan (lihat riwayat di atas).

Apakah halaman ini membantu?
0 / 5 - 0 peringkat