เดมอนบันทึกความล้มเหลวของ chroot และโปรไฟล์ดูใจกว้างอยู่แล้ว การแก้ที่ชวนทำจึงเป็นการขยายกฎพาธแล้วรีสตาร์ต ซึ่งมักไม่เปลี่ยนอะไร เพราะ chroot ถูกกำหนดโดยสิทธิพิเศษที่โปรไฟล์ไม่เคยส่งต่อได้ การตัดสินใจว่าจะแตะชั้นไหนต้องใช้การตรวจสามอย่าง และมันถูก: โปรเซสได้รับอนุญาตให้ถืออะไร นโยบายอนุญาตอะไร และตัวเรียกใช้ลบอะไรออกไปก่อนที่ทั้งสองอย่างจะมีความหมาย

สองประตูที่แยกจากกัน และมีเพียงประตูเดียวที่เป็นของ AppArmor

chroot ต้องมี CAP_SYS_CHROOT ในเนมสเปซของผู้ใช้ที่โปรเซสกำลังทำงานอยู่ นั่นคือสิทธิพิเศษปกติของ Linux ซึ่งเคอร์เนลตรวจสอบก่อนที่การเรียกจะทำอะไรกับพาธ แยกจากกันนั้น โปรไฟล์ AppArmor ที่บังคับใช้สามารถปฏิเสธความสามารถได้แม้โปรเซสจะถืออยู่ เพราะนโยบายภาคบังคับถูกพิจารณาเพิ่มจากข้อมูลรับรอง ไม่ใช่แทนที่ข้อมูลเหล่านั้น ความต่างนี้สำคัญในทางปฏิบัติ: ทั้งสองชั้นอยู่ในไฟล์ต่างกันและมักดูแลโดยคนละคน

ประตูทั้งสองล้มเหลวด้วย errno เดียวกัน ทั้งคู่ให้ EPERM และทั้งคู่ปรากฏเป็นข้อร้องเรียนเรื่องสิทธิ์แบบกว้าง ๆ ในบันทึกของเดมอน นั่นคือเหตุผลที่การเดาเนื้อหาโปรไฟล์ทำให้เสียเวลามาก กฎพาธที่คุณกำลังจะเพิ่มควบคุมการเข้าถึงไฟล์หลังจาก chroot สำเร็จเท่านั้น มันไม่มีผลต่อว่าการกระทำนั้นได้รับอนุญาตหรือไม่

ประตูที่สามอยู่เหนือทั้งสอง ชุด ถ้าตัวจัดการบริการหรือตัวห่อเริ่มโปรเซสโดยไม่มีความสามารถนั้นในชุดขอบเขตของมัน การเปลี่ยน AppArmor ใด ๆ ก็เอากลับมาไม่ได้ และการเพิ่มความสามารถในโปรไฟล์เป็นเพียงการบันทึกเจตนาที่เคอร์เนลจะไม่ปฏิบัติตาม

อ่านสถานะสิทธิพิเศษก่อนแก้ไขนโยบาย

เริ่มจากโปรเซสที่กำลังทำงาน ไม่ใช่จากคอนฟิกที่คุณคิดว่าใช้งานอยู่ ไฟล์สถานะแสดงมาสก์ความสามารถห้าตัวและแฟล็ก no-new-privileges และมันตอบคำถามต่างกัน:

grep -E '^(CapInh|CapPrm|CapEff|CapBnd|CapAmb|NoNewPrivs):' /proc/$(pidof openvpn)/status
sudo aa-status | grep -i openvpn

CapEff คือชุดที่สำคัญต่อการเรียก: ความสามารถที่มีใน CapBnd แต่ไม่มีใน CapEff ได้รับอนุญาตจากเพดานและไม่ได้ถูกถืออยู่ในขณะนั้น CapAmb สำคัญเมื่อไบนารีไม่ได้มีสิทธิพิเศษในความหมาย setuid ปกติ เพราะความสามารถแบบแอมเบียนต์คือวิธีที่บริการรักษาสิทธิพิเศษข้าม exec โดยไม่ต้องมีความสามารถระดับไฟล์ CapInh เก็บบิตที่อาจสืบทอดข้าม exec ได้ แต่เฉพาะเมื่อชุดสืบทอดของไฟล์ที่ถูกเรียกอนุญาต บิตที่นั่นจึงไม่ได้ให้อะไรด้วยตัวเอง

จากนั้นยืนยันว่าโปรไฟล์ใดถูกผูกอยู่จริง โปรเซสอาจถูกจำกัดด้วยชื่อโปรไฟล์ที่คุณไม่ได้คาดไว้ โดยเฉพาะเมื่อดิสทริบิวชันจัดส่ง unit และโปรไฟล์ของตัวเองมาด้วยกัน และการอ่าน /proc/PID/attr/current ก็ชี้ชัดในบรรทัดเดียว การเปรียบเทียบไฟล์ที่คุณแก้กับโปรไฟล์ที่เคอร์เนลรายงานคือ ความต่างระหว่างการแก้ที่ต้นเหตุกับการแก้ไฟล์ที่ไม่มีใครโหลด

เพิ่มกฎความสามารถเมื่อร่องรอยการตรวจสอบบอกเช่นนั้นเท่านั้น

บันทึกของเคอร์เนลและการตรวจสอบระบุชื่อชั้นที่ปฏิเสธ มองหาการปฏิเสธที่พา operation capable และชื่อ sys_chroot มาด้วย พร้อมโปรไฟล์ที่สร้างมันขึ้นมา ถ้าบันทึกนั้นมีอยู่ โปรเซสก็ถือความสามารถอยู่แล้วและ AppArmor ปฏิเสธมัน การเปลี่ยนแปลงที่ตรงจุดคือกฎความสามารถภายในโปรไฟล์จริง:

capability sys_chroot,

เก็บมันเป็นชิ้นส่วนในโปรไฟล์ที่ผูกอยู่จริง และตรวจคำสำคัญกับ เอกสารอ้างอิงโปรไฟล์ apparmor.d แทนการคัดลอกกฎจากบทแนะนำที่ไม่เกี่ยวข้อง การใส่มันใน include ที่ใช้ร่วมกันจะให้สิทธิ์นั้นกับทุกโปรแกรมที่ถูกจำกัดซึ่งโหลดไฟล์นั้น และการสลับโปรไฟล์ไปโหมด complain จะซ่อนการปฏิเสธครั้งถัดไปแทนที่จะแก้ครั้งนี้ กฎในโปรไฟล์ลบการปฏิเสธเชิงนโยบาย มันไม่ได้สร้างสิทธิพิเศษ โปรเซสที่ไม่เคยมี CAP_SYS_CHROOT ในชุดที่มีผลจึงยังล้มเหลวแม้มีกฎอยู่

ถ้าบันทึกการตรวจสอบไม่แสดงการปฏิเสธของ AppArmor เลย ให้หยุดแก้โปรไฟล์ คุณกำลังเผชิญปัญหาข้อมูลรับรอง และงานที่เหลืออยู่ใน unit หรือในโปรเซสแม่ ไม่ใช่ในภาษานโยบาย

ตัวจัดการบริการมีเพดานของตัวเอง

systemd กำหนดชุดขอบเขตความสามารถให้แต่ละบริการ และโดยค่าเริ่มต้นชุดนั้นแคบ สิ่งใดที่ถูกกีดกันไว้จะใช้ไม่ได้กับโปรเซสไม่ว่าโปรไฟล์จะว่าอย่างไร นั่นคือเหตุผลที่ unit ที่เสริมความแข็งแรงอาจล้มเหลวในการกระทำที่เคยทำงานเมื่อเริ่มเดมอนด้วยมือ คำสั่งที่เกี่ยวข้องอ่านง่ายใน unit และมองข้ามได้ง่ายเมื่อแอปพลิเคชันเองรายงานความผิดพลาด drop-in ที่แพ็กเกจดิสทริบิวชันจัดส่งมาเป็นแหล่งปกติของเพดานที่ไม่มีใครจำได้ว่าตั้งไว้

การยกเพดานกับการให้ความสามารถเป็นการเปลี่ยนแปลงสองอย่าง ไม่ใช่หนึ่งอย่าง รายการในชุดขอบเขตบอกว่าโปรเซสอาจถือความสามารถได้ มันไม่ได้เพิ่มเข้าไปในชุดที่มีผล และ NoNewPrivs อาจขัดขวางไม่ให้การยกระดับในภายหลังสำเร็จ แม้ทุกอย่างอื่นจะสอดคล้องกัน เพิ่มเฉพาะสิ่งที่การกระทำต้องการ รักษาการเสริมความแข็งแรงที่เหลือไว้ และอย่าหลงทางลัดของการให้ความสามารถทั้งหมดเพื่อให้การเรียกครั้งเดียวผ่าน

ลำดับก็สำคัญที่นี่ เปลี่ยนเพดานของ unit ก่อน ตรวจว่า CapEff มีบิตนั้นแล้ว และจากนั้นจึงตัดสินว่า AppArmor ยังปฏิเสธอยู่หรือไม่ การทำทั้งสองอย่างพร้อมกันจะทำให้คุณต้องเดาอีกครั้งหากความล้มเหลวยังคงอยู่

เมื่อการปฏิเสธหายไป ให้ตรวจตัวคุกเอง

chroot ที่สำเร็จจะย้ายรูท ดังนั้นทุกพาธที่เดมอนแตะหลังจากนั้นจะถูกแก้ภายในทรีใหม่ คอนฟิกที่หายไป โหนดอุปกรณ์ที่ไม่มี หรือไดเรกทอรีใบรับรองที่ไม่ได้คัดลอกเข้ามาจะปรากฏเป็นข้อผิดพลาดไฟล์ และข้อผิดพลาดนั้นเป็นปัญหาการจัดวาง ไม่ใช่ปัญหาความสามารถ อ่านเหตุการณ์ถัดไปแทนการเพิ่มสิทธิ์กว้างอีกอัน การย้ายยังเปลี่ยนความหมายของพาธสัมพัทธ์ ซึ่งเป็นเหตุผลที่คู่มือเสริมความแข็งแรงยืนยันให้ใช้พาธสัมบูรณ์ในคอนฟิกของเดมอน

ยังช่วยให้จำสิ่งที่ chroot ไม่ได้ทำด้วย มันเป็นขอบเขตของพาธ ไม่ใช่แซนด์บ็อกซ์: โปรเซสที่รักษาสิทธิพิเศษไว้สามารถหลบหนีออกไปได้ นั่นคือเหตุผลที่มักปลดความสามารถหลังการเรียก และเหตุผลที่การจำกัดควรอยู่รอบเดมอนต่อไป การเก็บโปรไฟล์ AppArmor ชุดขอบเขตความสามารถ และข้อจำกัดของระบบไฟล์ไว้ด้วยกันคือจุดประสงค์ของแบบฝึกหัดนี้ ไม่ใช่เศษที่ต้องถอดออกเมื่อบริการเริ่มทำงาน

กฎการตัดสินใจสั้น ถ้าบันทึกการตรวจสอบระบุชื่อ AppArmor ให้เพิ่มกฎความสามารถหนึ่งข้อในโปรไฟล์ที่ผูกอยู่ ถ้าชุดที่มีผลว่างเปล่า ให้แก้เพดานของ unit และลำดับการปลดสิทธิพิเศษ ถ้าโปรไฟล์ไม่ใช่ไฟล์ที่คุณแก้ ให้หยุดแก้แล้วหาไฟล์จริง

บทความที่เกี่ยวข้อง