- يجب تسجيل المعلومات حول جميع العمليات ، حتى عن العمليات قصيرة العمر.
- يجب أن يكون لدينا معلومات حول المسار الكامل للملف القابل للتنفيذ لجميع العمليات قيد التشغيل.
- يجب ألا نحتاج ، في حدود المعقول ، إلى تعديل أو إعادة ترجمة الكود الخاص بنا لإصدارات مختلفة من النواة.
- : - Kubernetes Docker, , / .
cgroup ID. , , «» « ». , « », « », « », API, Docker . ID , . Docker .
دعنا نتحدث عن واجهات برمجة تطبيقات Linux الشائعة التي يمكن أن تساعد في هذه المهمة. من أجل عدم تعقيد القصة ، سنولي اهتمامًا خاصًا للعمليات التي تم إنشاؤها باستخدام مكالمات النظام
execve. إذا تحدثنا عن حل أكثر اكتمالا للمشكلة ، فمن الضروري أثناء تنفيذه ، بالإضافة إلى ذلك ، مراقبة العمليات التي تم إنشاؤها باستخدام مكالمات النظام fork/cloneومتغيراتها ، وكذلك نتائج المكالمات execveat.
حلول بسيطة تنفذ في وضع المستخدم
- الاتصال
/proc. هذه الطريقة ، بسبب مشكلة العمليات قصيرة العمر ، ليست مناسبة بشكل خاص لنا. - netlink. netlink ,
PID. ./proc, . - Linux. — , . API . . . — , , , . , API ,
auditdosquery. , ,auditdgo-audit، من الناحية النظرية ، يمكن أن يخفف من هذه المشكلة. ولكن في حالة الحلول على مستوى المؤسسات ، لا يمكنك معرفة ما إذا كان العملاء يستخدمون مثل هذه الأدوات ، وإذا كانوا يستخدمون هذه الأدوات ، فما هي تلك الأدوات. كما أنه من غير الممكن معرفة ما هي ضوابط الأمان التي تعمل مباشرة مع Auditing API والتي يتم استخدامها من قبل العملاء. العيب الثاني هو أن واجهات برمجة التطبيقات للتدقيق لا تعرف شيئًا عن الحاويات. وهذا على الرغم من حقيقة أن هذه القضية قد نوقشت لسنوات عديدة.
أدوات تصحيح أخطاء وضع kernel البسيطة
يتضمن تنفيذ هذه الآليات استخدام "مجسات" من أنواع مختلفة في نسخة واحدة.
▍ نقاط التتبع
استخدام نقاط التتبع (
tracepoint). نقاط التتبع هي مستشعرات يتم توصيلها بشكل ثابت بمواقع محددة في النواة أثناء التجميع. يمكن تشغيل كل جهاز استشعار بشكل مستقل عن الآخرين ، ونتيجة لذلك سيصدر إشعارات في الحالات التي يتم فيها الوصول إلى مكان رمز kernel حيث يتم تضمينه. تحتوي النواة على عدة نقاط تتبع مناسبة لنا ، ويتم تنفيذ الكود الخاص بها في نقاط مختلفة في استدعاء النظام execve. هذا - sched_process_exec، open_exec، sys_enter_execve، sys_exit_execve. من أجل الحصول على هذه القائمة ، قمت بتشغيل الأمرcat /sys/kernel/tracing/available_events | grep execوتصفية القائمة الناتجة باستخدام المعلومات التي تم الحصول عليها من قراءة كود النواة. تناسبنا نقاط التتبع هذه بشكل أفضل من الآليات الموضحة أعلاه ، لأنها تسمح لنا بتنظيم مراقبة العمليات قصيرة العمر. لكن لا يقدم أي منهم معلومات حول المسار الكامل للملف القابل للتنفيذ للعملية إذا كانت المعلمات execهي المسار النسبي لمثل هذا الملف. بمعنى آخر ، إذا نفذ المستخدم أمرًا مثل cd /bin && ./ls، فإننا نحصل على معلومات المسار في النموذج ./ls، وليس في النموذج /bin/ls. إليك مثال بسيط:
# the sched_process_exec
sudo -s
cd /sys/kernel/debug/tracing
echo 1 > events/sched/sched_process_exec/enable
# ls
cd /bin && ./ls
# sched_process_exec
# ,
cd -
cat trace | grep ls
#
echo 0 > events/sched/sched_process_exec/enable
مجسات kprobe / kretprobe
kprobeتسمح لك
المستشعرات باستخراج معلومات التصحيح من أي مكان تقريبًا في النواة. إنها مثل نقاط التوقف الخاصة في كود النواة التي تعطي معلومات دون إيقاف تنفيذ الكود. kprobeيمكن توصيل المستشعر ، على عكس نقاط التتبع ، بمجموعة متنوعة من الوظائف. سيتم تشغيل رمز هذا المستشعر أثناء تنفيذ مكالمة النظام execve. لكنني لم أجد في الرسم البياني للاستدعاء execveأي وظيفة تكون معلماتها هي PIDالعملية والمسار الكامل لملفها القابل للتنفيذ. نتيجة لذلك ، نواجه نفس "مشكلة المسار النسبي" كما هو الحال عند استخدام نقاط التتبع. هنا يمكنك ، بالاعتماد على خصائص نواة معينة ، "تعديل" شيء ما. بعد كل شيء ، أجهزة الاستشعارkprobeيمكنه قراءة البيانات من مكدس استدعاء kernel. لكن مثل هذا الحل لن يعمل بثبات في إصدارات النواة المختلفة. لذلك ، أنا لا أعتبرها.
▍ استخدام برامج eBPF مع نقاط التتبع ، مع مجسات kprobe و kretprobe
نحن هنا نتحدث عن حقيقة أنه عند تنفيذ بعض التعليمات البرمجية ، سيتم تشغيل نقاط التتبع أو المستشعرات ، ولكن سيتم تنفيذ رمز برامج eBPF ، وليس رمز معالجات الأحداث العادية.
إن استخدام هذا النهج يفتح لنا بعض الاحتمالات الجديدة. يمكننا الآن تشغيل تعليمات برمجية عشوائية في النواة عندما نجري مكالمة نظام
execve. هذا ، من الناحية النظرية ، يجب أن يمنحنا القدرة على استخراج أي معلومات نحتاجها من النواة وإرسالها إلى مساحة المستخدم. هناك طريقتان للحصول على هذا النوع من البيانات ، لكن لا أحد منهما يلبي المتطلبات المذكورة أعلاه.
- ,
task_structlinux_binprm. , , . ,sched_process_exec, eBPF- , dentrybprm->file->f_path.dentry, . eBPF- . . , eBPF- , , , . - eBPF . , . — API. — . (, eBPF,
cgroup ID, ).
«»
-
LD_PRELOADexeclibc. , . , , , , . -
execve,fork/clonechdir, . ,execveexecve. — eBPF- eBPF- , . - ,
ptrace. -. —ptraceseccompSECCOMP_RET_TRACE.seccompexecve,execveseccompexecve. - باستخدام AppArmor. يمكنك كتابة ملف تعريف AppArmor لمنع العمليات من استدعاء الملفات القابلة للتنفيذ. إذا كنت تستخدم ملف التعريف هذا في وضع التدريب (تقديم شكوى) ، فلن يحظر AppArmor تنفيذ العمليات ، ولكنه سيصدر فقط إشعارات حول انتهاكات القواعد المحددة في الملف الشخصي. إذا قمنا بتوصيل ملف تعريف بكل عملية قيد التشغيل ، فإننا نحصل على حل فعال ولكنه غير جذاب للغاية و "اختراق" للغاية. ربما لا يستحق استخدام هذا النهج.
حلول أخرى
سأقول على الفور أن أيًا من هذه الحلول لا يلبي متطلباتنا ، لكن مع ذلك ، سأدرجها:
- استخدام الأداة
ps. تشير هذه الأداة ببساطة/proc، ونتيجة لذلك ، تعاني من نفس المشاكل مثل الوصول المباشر إلى/proc. - execsnoop, eBPF. , , ,
kprobe/kretprobe, , , . ,execsnoop, , , . -
execsnoop, eBPF. —kprobe, .
في المستقبل ، سيكون من الممكن استخدام وظيفة eBPF المساعدة get_fd_path ، والتي لم تتوفر بعد . بعد إضافته إلى النواة ، سيكون مفيدًا في حل مشكلتنا. صحيح ، يجب الحصول على المسار الكامل للملف القابل للتنفيذ للعملية باستخدام طريقة لا توفر قراءة المعلومات من هياكل بيانات kernel.
النتيجة
لم تعد أيًا من واجهات برمجة التطبيقات التي قمنا بمراجعتها مثالية. أدناه ، أود أن أقدم بعض الإرشادات حول الأساليب التي يجب استخدامها للحصول على معلومات حول العمليات ، ومتى يتم استخدامها:
- —
auditdgo-audit. , . , , , . , , , - API , , . — , . - , , , , ,
execsnoop. — . - , , , , , . , . , , eBPF- eBPF-,
perf... قصة عن كل هذا تستحق مقالة منفصلة. أهم شيء يجب تذكره عند اختيار طريقة عمليات المراقبة هذه هو ما يلي. إذا كنت تستخدم برامج eBPF ، فتحقق من إمكانية تجميعها الثابت ، والذي سيسمح لك بعدم الاعتماد على رؤوس kernel. ولكن هذا الاعتماد على وجه التحديد هو الذي نحاول تجنبه باستخدام هذه الطريقة. يعني استخدام هذه الطريقة أيضًا أنه لا يمكنك العمل مع هياكل بيانات kernel وأنه لا يمكنك استخدام أطر عمل مثل BCC التي تجمع برامج eBPF في وقت التشغيل. - إذا لم تكن مهتمًا بالعمليات قصيرة العمر والتوصيات السابقة لا تناسبك ، فاستخدم إمكانات netlink معًا
/proc.
كيف تنظم مراقبة العمليات الجارية في Linux؟
