Libseccomp: BUG: A2 معالجة مكسورة بواسطة إعادة صياغة src / db.c

تم إنشاؤها على ٢٦ فبراير ٢٠١٨  ·  18تعليقات  ·  مصدر: seccomp/libseccomp

لاختبار تحسينات أداء الشجرة الثنائية المقترحة ، كتبت مجموعة غير واقعية من القواعد للقراءة () وحجة حجم المخزن المؤقت (A2). ولكن يبدو أن التزام إعادة العمل src / db.c (ce3dda9a1) كسر معالجة A2 - على الأقل في حالة الاختبار هذه.

قبل تنفيذ إعادة صياغة db ، تمت إعادة قراءة مثل ما يلي - read(devzero_fd, buf, 8000) - تم إرجاع -10 . بعد هذا الالتزام ، يُرجع الآن -5 .

إليك رمز C الذي استخدمته لإنشاء قواعد القراءة السخيفة ():

        /* 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;
        } 

وإليك PFC الذي تم إنشاؤه:

  # 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

ال 18 كومينتر

بالمناسبة ، سأفعل ما بوسعي للمساعدة في إحداث ذلك

باستخدام scmp_bpf_disasm ، يضع أحدث libseccomp القفزات في الترتيب غير الصحيح

رئيس

 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

إعادة العمل المسبق

 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)

مثير للإعجاب. لذلك يبدو أن PFC "صحيح" ، لكن BPF المتولد هو ... إلى الوراء. الفردية. خاصة وأن الالتزام لم يغير كود إنشاء BPF.

أتساءل عما إذا كانت قيم الأولوية يتم إفسادها بطريقة ما؟

آسف على الغموض. PFC (بعد تغيير إعادة العمل) أيضًا بالترتيب غير الصحيح. PFC I المنشور أعلاه هو الترتيب الذي كان عليه قبل إعادة صياغة db.c.

إليك PFC التي تم إنشاؤها حاليًا بواسطة 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);

حسنًا ، هذا منطقي أكثر قليلاً. المشاكل تعيش بالتأكيد في مكان ما في طبقة ديسيبل.

إنه لأمر مضحك بعض الشيء كيف أن الأمر عكسي تمامًا .

لقد وجدت المشكلة. في إدارة وسيطة السلسلة ، تم تبديل سلوك lvl_nxt و lvl_prv بعد إعادة صياغة db.c الضخمة. بعض التغييرات الصغيرة على _db_tree_add () جعلته يطابق سلوك libseccomp السابق.

هنا فرع مع الإصلاح
https://github.com/drakenclimber/libseccomp/tree/issues/112

سأقوم بتنظيف التغييرات ، وإضافة اختبار أو اثنين ، والتأكد من أن تغطية الكود تصل إلى السعوط.

لقد وجدت بعض الوقت هذا الصباح ، على الأرجح قبل نشر ما ورد أعلاه مباشرة ، وقررت النظر في هذا قليلاً. يبدو أننا توصلنا إلى نفس النتيجة تقريبًا ، على الرغم من اختلاف الإصلاحات قليلاً. إليك إصلاحي الحالي ، على الرغم من أنه مثل إصلاحك ، فإنه يحتاج إلى بعض الأعمال / التنظيف الإضافي:

لست متأكدًا من الطريقة التي أحبها أكثر الآن ، أحتاج إلى التفكير في هذا قليلاً ، الأفكار؟

هممم ... لن أكذب ؛ أنا لست مغرمًا بأي من الإصلاحين في هذه المرحلة.

المنجم بسيط ، لكنه تجاهل تمامًا _db_tree_prune () والذي - كما قلت في مضمونك - ربما لديه مشكلات مماثلة.

تعجبني فكرتك في إعادة صياغة الماكرو gt () لاستخدام وحدات الماكرو lt () و eq () ، لكنها تصبح غير عملية - خاصةً lt (). هل هناك أي سبب لعدم تحويل lt () إلى دالة مضمنة؟
تحرير - لقد لاحظت للتو أنك قدمت تعليقًا مشابهًا في الجوهر.

لقد قمت بتشغيل gdb مقابل libseccomp القديم و HEAD ، وتغير سلوكيات lvl_prv و lvl_nxt بالفعل ، لكن ربما لم تكن هذه مشكلة كبيرة نظرًا لأنه متغير داخلي لا ينبغي لأحد رؤيته إلا نحن.

أعتقد بعد كل هذا التجوال ... لا أعرف. أوافق ، أحتاج إلى التفكير في الأمر ؛)

هممم ... لن أكذب ؛ أنا لست مغرمًا بأي من الإصلاحين في هذه المرحلة.

أشعر بالقلق من وجود بعض الأخطاء الدقيقة في إعادة ترتيب مستوى شجرة مثل هذا ، على الرغم من أنه يبدو أنه ربما تم إعادة ترتيب المستوى وهذا أحد الأخطاء الدقيقة.

في كلتا الحالتين ، أريد أن أفهم ما يجب أن يكون عليه الترتيب المطلوب للمستوى: "الأكبر" أولاً ، أو "الأكبر" أخيرًا؟ بمجرد أن نفهم أنه يمكننا المضي قدمًا في الاختبار / الإصلاح. أعتقد أن الإجابة ، إذا لم يكن لسبب آخر غير التوافق مع إصدارات 2.x السابقة ، هي "الأكبر" أولاً ، لكن لا يمكنني قول ذلك على وجه اليقين في هذه المرحلة.

المنجم بسيط ، لكنه تجاهل تمامًا _db_tree_prune () والذي - كما قلت في مضمونك - ربما لديه مشكلات مماثلة.

كلاهما يقومان بنفس الشيء من حيث المبدأ ، ويذهب لي أبعد قليلاً عن طريق إضافة بعض الشروط الإضافية وتنظيف الماكرو db_chain_lt (x ، y).

تعجبني فكرتك في إعادة صياغة الماكرو gt () لاستخدام وحدات الماكرو lt () و eq () ، لكنها تصبح غير عملية - خاصةً lt (). هل هناك أي سبب لعدم تحويل lt () إلى دالة مضمنة؟

في الغالب أسباب تاريخية. لقد بدأوا الحياة بقدر أبسط من وحدات الماكرو ، لكنهم نمتوا قليلاً لدرجة أنني أعتقد أنها ربما يجب أن تكون وظائف. أعتقد أنه سيكون من الجيد أيضًا تقييم ما إذا كانوا يحتاجون حقًا إلى أن يكونوا في ملف الرأس ، وأعتقد أنه يتم استخدامهم فقط بواسطة src / db.c.

لقد قمت بتشغيل gdb مقابل libseccomp القديم و HEAD ، وتغير سلوكيات lvl_prv و lvl_nxt بالفعل ، لكن ربما لم تكن هذه مشكلة كبيرة نظرًا لأنه متغير داخلي لا ينبغي لأحد رؤيته إلا نحن.

نعم ، إنها حالة / شجرة داخلية ، لست قلقًا جدًا بشأن ذلك. الشيء المهم هو صحة المرشح الذي تم إنشاؤه.

أعتقد بعد كل هذا التجوال ... لا أعرف. أوافق ، أحتاج إلى التفكير في الأمر ؛)

هيه. دعنا نمنح هذا يومًا أو يومين ونعيد التجميع :) في الوقت الحالي ، لا يؤثر هذا على أي إصدارات تم إصدارها ، إنه فقط في الفرع الرئيسي ، لذلك لدينا بعض الوقت لتصحيح الأمور.

في الوقت الحالي ، لا يؤثر هذا على أي إصدارات تم إصدارها ، إنه موجود فقط في الفرع الرئيسي ، لذلك لدينا بعض الوقت لتصحيح الأمور.

يبدو جيدا. سأقوم ببعض الاختبارات بينما نفكر في خطة

لقد كتبت برنامجًا لتقييم معالجة seccomp A2 الحالية. البرنامج بأكمله متاح هنا:

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

باختصار ، يتم إنشاء أكبر من القواعد في أمر "تم إنشاؤه مؤخرًا" "تمت معالجته لأول مرة".

  • لعامل التصفية حيث يتم إنشاء قواعد > بترتيب تصاعدي ، على سبيل المثال
    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)
    ثم سوف يتصرف المرشح بطريقة متماسكة ، على سبيل المثال
if (A2 > 30)
    do action3
if (A2 > 20)
    do action2
if (A2 > 10)
    do action1
  • بالنسبة إلى الفلتر حيث يتم إنشاء قواعد > بترتيب تنازلي ، على سبيل المثال
    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)
    ثم سيتم إنشاء الفلتر ، ولكن التصرف بشكل غريب. سيتم إنتاج رمز ميت. لا يمكن الوصول إلى آخر كشفين من if
if (A2 > 10)
    do action1
if (A2 > 20)
    do action2
if (A2 > 30)
    do action1
  • لا يسمح seccomp حاليًا باستخدام المرشحات ذات العمليات المتعددة < A2. يبدو هذا غريبًا لأنني لم أتمكن من اكتشاف طريقة لعمل ما <= > لفلتر
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

أظن أن المنطق else if المدفون بعمق في src/db.c يتسبب في فشل < ، على سبيل المثال. لست متأكدًا مما إذا كان الأمر يستحق التغيير / الإصلاح.

سأحاول تحويل بعض هذه التعليمات البرمجية إلى اختبارات آلية حتى نتمكن من التقاط السلوك الحالي.

كما هو مكتوب ، فشل جوهر هنا في الاختبارات الآلية التي أضفتها الأسبوع الماضي. سوف أحفر وأحاول معرفة السبب.

 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)

سيئتي - لقد أساءت تطبيق الجوهر. الاختبارات تمر. تفو :)

ها! :)

اعتقدت أنني أجريت الاختبارات ضدها ، لكنني كنت ألعب بالعديد من الأشياء في ذلك الوقت ، لذلك

لا داعى للقلق. هذه بالتأكيد أولوية أعلى.

لقد قمت بإجراء فحوصاتك من خلال العديد من الاختبارات غير الواقعية. لم أحصل على كسر ، لكنني أيضًا أمارس فقط أجزاء وأجزاء من _db_tree_prune () حتى الآن. بدأت أشعر براحة أكبر مع التغييرات ، لكنني أريد الحصول على مزيد من الوقت عليها.

لقد نقرت وحثت على كود _db_tree_prune () ولم أتمكن من كسره. يقوم اختبار 08-sim-subtree_checks بعمل جيد في اختبار معظم مسارات الكود داخل prune ().

أعتقد أن التغييرات من جوهر الخاص بك جيدة للذهاب.

قدمت طلب السحب رقم 115. أعتقد أن هذا جاهز للعمل

الإغلاق حيث يجب حل هذا الآن (انظر التاريخ أعلاه).

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات