.\" -*- coding: UTF-8 -*- .\" Copyright 1999, ike Coleman .\" Copyright 2011, Denys Vlasenko .\" Copyright 2015-2016, Michael Kerrisk .\" Copyright, the authors of the Linux man-pages project .\" .\" SPDX-License-Identifier: GPL-2.0-or-later .\" .\" FIXME The following are undocumented: .\" .\" PTRACE_GETWMMXREGS .\" PTRACE_SETWMMXREGS .\" ARM .\" Linux 2.6.12 .\" .\" PTRACE_SET_SYSCALL .\" ARM and ARM64 .\" Linux 2.6.16 .\" commit 3f471126ee53feb5e9b210ea2f525ed3bb9b7a7f .\" Author: Nicolas Pitre .\" Date: Sat Jan 14 19:30:04 2006 +0000 .\" .\" PTRACE_GETCRUNCHREGS .\" PTRACE_SETCRUNCHREGS .\" ARM .\" Linux 2.6.18 .\" commit 3bec6ded282b331552587267d67a06ed7fd95ddd .\" Author: Lennert Buytenhek .\" Date: Tue Jun 27 22:56:18 2006 +0100 .\" .\" PTRACE_GETVFPREGS .\" PTRACE_SETVFPREGS .\" ARM and ARM64 .\" Linux 2.6.30 .\" commit 3d1228ead618b88e8606015cbabc49019981805d .\" Author: Catalin Marinas .\" Date: Wed Feb 11 13:12:56 2009 +0100 .\" .\" PTRACE_GETHBPREGS .\" PTRACE_SETHBPREGS .\" ARM and ARM64 .\" Linux 2.6.37 .\" commit 864232fa1a2f8dfe003438ef0851a56722740f3e .\" Author: Will Deacon .\" Date: Fri Sep 3 10:42:55 2010 +0100 .\" .\" PTRACE_SINGLEBLOCK .\" Since at least Linux 2.4.0 on various architectures .\" Since Linux 2.6.25 on x86 (and others?) .\" commit 5b88abbf770a0e1975c668743100f42934f385e8 .\" Author: Roland McGrath .\" Date: Wed Jan 30 13:30:53 2008 +0100 .\" ptrace: generic PTRACE_SINGLEBLOCK .\" .\" PTRACE_GETFPXREGS .\" PTRACE_SETFPXREGS .\" Since at least Linux 2.4.0 on various architectures .\" .\" PTRACE_GETFDPIC .\" PTRACE_GETFDPIC_EXEC .\" PTRACE_GETFDPIC_INTERP .\" blackfin, c6x, frv, sh .\" First appearance in Linux 2.6.11 on frv .\" .\" and others that can be found in the arch/*/include/uapi/asm/ptrace files .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH ptrace 2 "10 فبراير 2026" "صفحات دليل لينكس 6.18" .SH الاسم ptrace \- تتبع العمليات .SH المكتبة مكتبة سي المعيارية (\fIlibc\fP،\ \fI\-lc\fP) .SH موجز .nf \fB#include \fP .P \fBlong ptrace(enum __ptrace_request \fP\fIop\fP\fB, pid_t \fP\fIpid\fP\fB,\fP \fB void *\fP\fIaddr\fP\fB, void *\fP\fIdata\fP\fB);\fP .fi .SH الوصف يوفر استدعاء النظام \fBptrace\fP() وسيلة تُمكّن عملية واحدة (المُتتبِّع "tracer") من مراقبة والتحكم في تنفيذ عملية أخرى (المُتتبَّع "tracee")، وفحص وتغيير ذاكرة وسجلات المُتتبَّع. يُستخدم هذا الاستدعاء بشكل رئيس لترسيخ تنقيح نقاط التوقف وتتبع استدعاءات النظام. .P يحتاج المُتتبَّع أولاً إلى أن يُربط بالمُتتبِّع. الربط والأوامر اللاحقة تكون لكل خيط: في عملية متعددة الخيوط، يمكن ربط كل خيط بشكل منفرد بمُتتبِّع (ربما يكون مختلفاً)، أو تركه غير مربوط وبالتالي لا يُنقّح. لذلك، تعني كلمة "المُتتبَّع" دائماً "خيطاً (واحداً)"، ولا تعني أبداً "عملية (ربما تكون متعددة الخيوط)". تُرسل أوامر Ptrace دائماً إلى مُتتبَّع محدد باستخدام استدعاء على الشكل .P .in +4n .EX ptrace(PTRACE_foo, pid, ...) .EE .in .P حيث \fIpid\fP هو معرف الخيط لخيط لينكس المقابل. .P (لاحظ أنه في هذه الصفحة، تعني "العملية متعددة الخيوط" مجموعة خيوط تتكون من خيوط أُنشئت باستخدام علامة \fBCLONE_THREAD\fP في \fBclone\fP(2).) .P يمكن لعملية أن تبدأ تتبعاً عبر استدعاء \fBfork\fP(2) وجعل الابن الناتج ينفذ \fBPTRACE_TRACEME\fP، يتبعه (عادةً) \fBexecve\fP(2). بدلاً من ذلك، يمكن لعملية أن تبدأ تتبع عملية أخرى باستخدام \fBPTRACE_ATTACH\fP أو \fBPTRACE_SEIZE\fP. .P أثناء التتبع، سيتوقف المُتتبَّع في كل مرة تُسلّم فيها إشارة، حتى لو كانت الإشارة مهملة. (الاستثناء هو \fBSIGKILL\fP، التي تملك تأثيرها المعتاد). سيُخطر المُتتبِّع عند استدعائه القادم لـ \fBwaitpid\fP(2) (أو أحد استدعاءات نظام "الانتظار" ذات الصلة)؛ سيُعيد ذلك الاستدعاء قيمة \fIstatus\fP تحتوي على معلومات تشير إلى سبب التوقف في المُتتبَّع. وبينما يكون المُتتبَّع متوقفاً، يمكن للمُتتبِّع استخدام عمليات ptrace متنوعة لفحص وتعديل المُتتبَّع. ثم يجعل المُتتبِّع المُتتبَّعَ يواصل العمل، مع إمكانية تجاهل الإشارة المُسلّمة (أو حتى تسليم إشارة مختلفة بدلاً عنها). .P إذا لم يكن خيار \fBPTRACE_O_TRACEEXEC\fP سارياً، فإن جميع استدعاءات \fBexecve\fP(2) الناجحة من قِبل العملية المُتتبَّعة ستؤدي إلى إرسال إشارة \fBSIGTRAP\fP إليها، مما يعطي الأب فرصة للسيطرة قبل أن يبدأ البرنامج الجديد في التنفيذ. .P عندما ينتهي المُتتبِّع من التتبع، يمكنه جعل المُتتبَّع يواصل التنفيذ في وضع طبيعي وغير مُتتبَّع عبر \fBPTRACE_DETACH\fP. .P تحدد قيمة \fIop\fP العملية التي ستُنفذ: .TP \fBPTRACE_TRACEME\fP تُشير إلى أن هذه العملية سيتبعها والدها. لا ينبغي لعملية أن تقوم بهذه العملية إلا إذا كان والدها يتوقع تتبعها. (تُهمل \fIpid\fP و \fIaddr\fP و \fIdata\fP.) .IP تُستخدم عملية \fBPTRACE_TRACEME\fP من قِبل المُتتبَّع فقط؛ بينما تُستخدم العمليات المتبقية من قِبل المُتتبِّع فقط. في العمليات التالية، يحدد \fIpid\fP معرف الخيط للمُتتبَّع المراد التعامل معه. بالنسبة للعمليات بخلاف \fBPTRACE_ATTACH\fP و \fBPTRACE_SEIZE\fP و \fBPTRACE_INTERRUPT\fP و \fBPTRACE_KILL\fP، يجب أن يكون المُتتبَّع متوقفاً. .TP \fBPTRACE_PEEKTEXT\fP .TQ \fBPTRACE_PEEKDATA\fP تقرأ كلمة عند العنوان \fIaddr\fP في ذاكرة المُتتبَّع، وتُعيد الكلمة كنتيجة لاستدعاء \fBptrace\fP(). لا يملك لينكس مساحات عناوين منفصلة للنص والبيانات، لذا فإن هاتين العمليتين متكافئتان حالياً. (تُهمل \fIdata\fP؛ لكن انظر NOTES.) .TP \fBPTRACE_PEEKUSER\fP .\" PTRACE_PEEKUSR in kernel source, but glibc uses PTRACE_PEEKUSER, .\" and that is the name that seems common on other systems. تقرأ كلمة عند الإزاحة \fIaddr\fP في منطقة USER الخاصة بالمُتتبَّع، والتي تحوي السجلات ومعلومات أخرى عن العملية (انظر \fI\fP). تُعاد الكلمة كنتيجة لاستدعاء \fBptrace\fP(). عادةً، يجب أن تكون الإزاحة محاذية للكلمة (word\-aligned)، رغم أن هذا قد يختلف حسب البنية. انظر NOTES. (تُهمل \fIdata\fP؛ لكن انظر NOTES.) .TP \fBPTRACE_POKETEXT\fP .TQ \fBPTRACE_POKEDATA\fP تنسخ الكلمة \fIdata\fP إلى العنوان \fIaddr\fP في ذاكرة المُتتبَّع. وكما هو الحال في \fBPTRACE_PEEKTEXT\fP و \fBPTRACE_PEEKDATA\fP، فإن هاتين العمليتين متكافئتان حالياً. .TP \fBPTRACE_POKEUSER\fP .\" PTRACE_POKEUSR in kernel source, but glibc uses PTRACE_POKEUSER, .\" and that is the name that seems common on other systems. .\" FIXME In the preceding sentence, which modifications are disallowed, .\" and when they are disallowed, how does user space discover that fact? تنسخ الكلمة \fIdata\fP إلى الإزاحة \fIaddr\fP في منطقة USER الخاصة بالمُتتبَّع. وكما هو الحال في \fBPTRACE_PEEKUSER\fP، يجب أن تكون الإزاحة عادةً محاذية للكلمة. وحفاظاً على سلامة النواة، فإن بعض التعديلات على منطقة USER غير مسموح بها. .TP \fBPTRACE_GETREGS\fP .TQ \fBPTRACE_GETFPREGS\fP تنسخ سجلات المُتتبَّع العامة أو سجلات الفاصلة العائمة، على التوالي، إلى العنوان \fIdata\fP في المُتتبِّع. انظر \fI\fP للحصول على معلومات حول تنسيق هذه البيانات. (تُهمل \fIaddr\fP). لاحظ أن أنظمة SPARC تكون فيها معاني \fIdata\fP و \fIaddr\fP معكوسة؛ أي تُهمل \fIdata\fP وتُنسخ السجلات إلى العنوان \fIaddr\fP. لا تتوفر \fBPTRACE_GETREGS\fP و \fBPTRACE_GETFPREGS\fP في جميع البنيات. .TP \fBPTRACE_GETREGSET\fP (منذ لينكس 2.6.34) تقرأ سجلات المُتتبَّع. يحدد \fIaddr\fP، بطريقة تعتمد على البنية، نوع السجلات التي ستُقرأ. تؤدي \fBNT_PRSTATUS\fP (بالقيمة الرقمية 1) عادةً إلى قراءة السجلات العامة. إذا كان المعالج يحتوي، على سبيل المثال، سجلات فاصلة عائمة أو سجلات متجهية، فيمكن جلبها عبر ضبط \fIaddr\fP إلى ثابت \fBNT_foo\fP المقابل. يشير \fIdata\fP إلى \fBstruct iovec\fP، الذي يصف موقع وحجم المخزن المؤقت الوجهة. عند العودة، تُعدل النواة \fBiov.len\fP للإشارة إلى عدد البايتات الفعلي الذي أُعيد. .TP \fBPTRACE_SETREGS\fP .TQ \fBPTRACE_SETFPREGS\fP .\" FIXME . In the preceding sentence, which modifications are disallowed, .\" and when they are disallowed, how does user space discover that fact? تُعدل سجلات المُتتبَّع العامة أو سجلات الفاصلة العائمة، على التوالي، من العنوان \fIdata\fP في المُتتبِّع. وكما في \fBPTRACE_POKEUSER\fP، قد تُمنع بعض تعديلات السجلات العامة. (تُهمل \fIaddr\fP). لاحظ أن أنظمة SPARC تكون فيها معاني \fIdata\fP و \fIaddr\fP معكوسة؛ أي تُهمل \fIdata\fP وتُنسخ السجلات من العنوان \fIaddr\fP. لا تتوفر \fBPTRACE_SETREGS\fP و \fBPTRACE_SETFPREGS\fP في جميع البنيات. .TP \fBPTRACE_SETREGSET\fP (منذ لينكس 2.6.34) تُعدل سجلات المُتتبَّع. معنى \fIaddr\fP و \fIdata\fP مماثل لـ \fBPTRACE_GETREGSET\fP. .TP \fBPTRACE_GETSIGINFO\fP (منذ لينكس 2.3.99\-pre6) تجلب معلومات حول الإشارة التي تسببت في التوقف. تنسخ بنية \fIsiginfo_t\fP (انظر \fBsigaction\fP(2)) من المُتتبَّع إلى العنوان \fIdata\fP في المُتتبِّع. (تُهمل \fIaddr\fP). .TP \fBPTRACE_SETSIGINFO\fP (منذ لينكس 2.3.99\-pre6) تضبط معلومات الإشارة: تنسخ بنية \fIsiginfo_t\fP من العنوان \fIdata\fP في المُتتبِّع إلى المُتتبَّع. سيؤثر هذا فقط على الإشارات التي كانت ستُسلّم بشكل طبيعي إلى المُتتبَّع والتقطها المُتتبِّع. قد يصعب تمييز هذه الإشارات الطبيعية عن الإشارات الاصطناعية التي يولدها \fBptrace\fP() نفسه. (تُهمل \fIaddr\fP). .TP \fBPTRACE_PEEKSIGINFO\fP (منذ لينكس 3.10) .\" commit 84c751bd4aebbaae995fe32279d3dba48327bad4 تجلب بنيات \fIsiginfo_t\fP دون إزالة الإشارات من الطابور. يشير \fIaddr\fP إلى بنية \fIptrace_peeksiginfo_args\fP التي تحدد الموضع الترتيبي الذي يجب أن يبدأ منه نسخ الإشارات، وعدد الإشارات المراد نسخها. تُنسخ بنيات \fIsiginfo_t\fP إلى المخزن المؤقت الذي يشير إليه \fIdata\fP. تحتوي القيمة المعادة على عدد الإشارات المنسوخة (يشير الصفر إلى عدم وجود إشارة تقابل الموضع الترتيبي المحدد). داخل بنيات \fIsiginfo\fP المعادة، يتضمن الحقل \fIsi_code\fP معلومات (\fB__SI_CHLD\fP و \fB__SI_FAULT\fP، إلخ) لا تُكشف عادةً لمساحة المستخدم. .P .in +4n .EX struct ptrace_peeksiginfo_args { u64 off; /* الموضع الترتيبي في الطابور الذي يبدأ منه نسخ الإشارات */ u32 flags; /* PTRACE_PEEKSIGINFO_SHARED أو 0 */ s32 nr; /* عدد الإشارات المراد نسخها */ }; .EE .in .IP حالياً، توجد علامة واحدة فقط، وهي \fBPTRACE_PEEKSIGINFO_SHARED\fP، لتفريغ الإشارات من طابور إشارات العملية بالكامل. إذا لم تُضبط هذه العلامة، تُقرأ الإشارات من طابور الخيط المحدد. .in .TP \fBPTRACE_GETSIGMASK\fP (منذ لينكس 3.11) .\" commit 29000caecbe87b6b66f144f72111f0d02fbbf0c1 تضع نسخة من قناع الإشارات المحجوبة (انظر \fBsigprocmask\fP(2)) في المخزن المؤقت الذي يشير إليه \fIdata\fP، والذي ينبغي أن يكون مؤشراً إلى مخزن من النوع \fIsigset_t\fP. يحتوي المعطى \fIaddr\fP على حجم المخزن المؤقت الذي يشير إليه \fIdata\fP (أي \fIsizeof(sigset_t)\fP). .TP \fBPTRACE_SETSIGMASK\fP (منذ لينكس 3.11) تغير قناع الإشارات المحجوبة (انظر \fBsigprocmask\fP(2)) إلى القيمة المحددة في المخزن المؤقت الذي يشير إليه \fIdata\fP، والذي ينبغي أن يكون مؤشراً إلى مخزن من النوع \fIsigset_t\fP. يحتوي المعطى \fIaddr\fP على حجم المخزن المؤقت الذي يشير إليه \fIdata\fP (أي \fIsizeof(sigset_t)\fP). .TP \fBPTRACE_SETOPTIONS\fP (منذ لينكس 2.4.6؛ انظر BUGS للتحذيرات) تضبط خيارات ptrace من \fIdata\fP. (تُهمل \fIaddr\fP). تُفسر \fIdata\fP كقناع بتات للخيارات، والتي تُحدد بالعلامات التالية: .RS .TP \fBPTRACE_O_EXITKILL\fP (منذ لينكس 3.8) .\" commit 992fb6e170639b0849bace8e49bf31bd37c4123 تُرسل إشارة \fBSIGKILL\fP إلى المُتتبَّع إذا خرج المُتتبِّع. هذا الخيار مفيد لمسؤولي سجون ptrace (jailers) الذين يريدون ضمان عدم هروب المُتتبَّعين من سيطرة المُتتبِّع أبداً. .TP \fBPTRACE_O_TRACECLONE\fP (منذ لينكس 2.5.46) توقف المُتتبَّع عند استدعاء \fBclone\fP(2) القادم وتبدأ آلياً بتتبع العملية المنسوخة حديثاً، والتي ستبدأ بإشارة \fBSIGSTOP\fP، أو \fBPTRACE_EVENT_STOP\fP إذا استُخدم \fBPTRACE_SEIZE\fP. سيُعيد استدعاء \fBwaitpid\fP(2) من قِبل المُتتبِّع قيمة \fIstatus\fP بحيث .IP .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8)) .fi .IP يمكن جلب معرف العملية (PID) للعملية الجديدة باستخدام \fBPTRACE_GETEVENTMSG\fP. .IP قد لا يمسك هذا الخيار استدعاءات \fBclone\fP(2) في جميع الحالات. إذا استدعى المُتتبَّع \fBclone\fP(2) مع علامة \fBCLONE_VFORK\fP، ستُسلّم \fBPTRACE_EVENT_VFORK\fP بدلاً من ذلك إذا كان \fBPTRACE_O_TRACEVFORK\fP مضبوطاً؛ وإلا إذا استدعى المُتتبَّع \fBclone\fP(2) مع ضبط إشارة الخروج إلى \fBSIGCHLD\fP، ستُسلّم \fBPTRACE_EVENT_FORK\fP إذا كان \fBPTRACE_O_TRACEFORK\fP مضبوطاً. .TP \fBPTRACE_O_TRACEEXEC\fP (منذ لينكس 2.5.46) توقف المُتتبَّع عند استدعاء \fBexecve\fP(2) القادم. سيُعيد استدعاء \fBwaitpid\fP(2) من قِبل المُتتبِّع قيمة \fIstatus\fP بحيث .IP .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8)) .fi .IP إذا لم يكن الخيط المنفِّذ هو قائد مجموعة الخيوط، يُعاد تعيين معرف الخيط إلى معرف قائد المجموعة قبل هذا التوقف. منذ لينكس 3.0، يمكن جلب معرف الخيط السابق باستخدام \fBPTRACE_GETEVENTMSG\fP. .TP \fBPTRACE_O_TRACEEXIT\fP (منذ لينكس 2.5.60) توقف المُتتبَّع عند الخروج. سيُعيد استدعاء \fBwaitpid\fP(2) من قِبل المُتتبِّع قيمة \fIstatus\fP بحيث .IP .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8)) .fi .IP يمكن جلب حالة خروج المُتتبَّع باستخدام \fBPTRACE_GETEVENTMSG\fP. .IP يتوقف المُتتبَّع مبكراً أثناء خروج العملية، عندما تكون السجلات لا تزال متاحة، مما يسمح للمُتتبِّع برؤية مكان وقوع الخروج، بينما يتم إشعار الخروج الطبيعي بعد انتهاء خروج العملية. ورغم توفر السياق، لا يمكن للمُتتبِّع منع وقوع الخروج عند هذه النقطة. .TP \fBPTRACE_O_TRACEFORK\fP (منذ لينكس 2.5.46) توقف المُتتبَّع عند استدعاء \fBfork\fP(2) القادم وتبدأ آلياً بتتبع العملية المتفرعة حديثاً، والتي ستبدأ بإشارة \fBSIGSTOP\fP، أو \fBPTRACE_EVENT_STOP\fP إذا استُخدم \fBPTRACE_SEIZE\fP. سيُعيد استدعاء \fBwaitpid\fP(2) من قِبل المُتتبِّع قيمة \fIstatus\fP بحيث .IP .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_FORK<<8)) .fi .IP يمكن جلب معرف العملية (PID) للعملية الجديدة باستخدام \fBPTRACE_GETEVENTMSG\fP. .TP \fBPTRACE_O_TRACESYSGOOD\fP (منذ لينكس 2.4.6) عند تسليم فخاخ استدعاء النظام، تضبط البت 7 في رقم الإشارة (أي تسلّم \fISIGTRAP|0x80\fP). هذا يسهل على المُتتبِّع تمييز الفخاخ الطبيعية عن تلك الناتجة عن استدعاء نظام. .TP \fBPTRACE_O_TRACEVFORK\fP (منذ لينكس 2.5.46) توقف المُتتبَّع عند استدعاء \fBvfork\fP(2) القادم وتبدأ آلياً بتتبع العملية المتفرعة (vforked) حديثاً، والتي ستبدأ بإشارة \fBSIGSTOP\fP، أو \fBPTRACE_EVENT_STOP\fP إذا استُخدم \fBPTRACE_SEIZE\fP. سيُعيد استدعاء \fBwaitpid\fP(2) من قِبل المُتتبِّع قيمة \fIstatus\fP بحيث .IP .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK<<8)) .fi .IP يمكن جلب معرف العملية (PID) للعملية الجديدة باستخدام \fBPTRACE_GETEVENTMSG\fP. .TP \fBPTRACE_O_TRACEVFORKDONE\fP (منذ لينكس 2.5.60) توقف المُتتبَّع عند اكتمال استدعاء \fBvfork\fP(2) القادم. سيُعيد استدعاء \fBwaitpid\fP(2) من قِبل المُتتبِّع قيمة \fIstatus\fP بحيث .IP .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE<<8)) .fi .IP يمكن (منذ لينكس 2.6.18) جلب معرف العملية (PID) للعملية الجديدة باستخدام \fBPTRACE_GETEVENTMSG\fP. .TP \fBPTRACE_O_TRACESECCOMP\fP (منذ لينكس 3.5) توقف المُتتبَّع عند انطلاق قاعدة \fBSECCOMP_RET_TRACE\fP الخاصة بـ \fBseccomp\fP(2). سيُعيد استدعاء \fBwaitpid\fP(2) من قِبل المُتتبِّع قيمة \fIstatus\fP بحيث .IP .nf status>>8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP<<8)) .fi .IP بينما يطلق هذا توقف \fBPTRACE_EVENT\fP، إلا أنه مشابه لتوقف syscall\-enter\-stop. للتفاصيل، انظر الملاحظة حول \fBPTRACE_EVENT_SECCOMP\fP أدناه. يمكن جلب بيانات رسالة حدث seccomp (من جزء \fBSECCOMP_RET_DATA\fP لقاعدة مرشح seccomp) باستخدام \fBPTRACE_GETEVENTMSG\fP. .TP \fBPTRACE_O_SUSPEND_SECCOMP\fP (منذ لينكس 4.3) .\" commit 13c4a90119d28cfcb6b5bdd820c233b86c2b0237 تُعلّق حماية seccomp الخاصة بالمُتتبَّع. ينطبق هذا بغض النظر عن الوضع، ويمكن استخدامه عندما لا يكون المُتتبَّع قد ثبّت مرشحات seccomp بعد. أي أن حالة الاستخدام الصالحة هي تعليق حماية seccomp للمُتتبَّع قبل تثبيتها من قِبله، ثم السماح له بتثبيتها، ثم مسح هذه العلامة عندما يجب استئناف عمل المرشحات. يتطلب ضبط هذا الخيار أن يمتلك المُتتبِّع صلاحية \fBCAP_SYS_ADMIN\fP، وألا يكون لديه أي حماية seccomp مثبتة، وألا يكون خيار \fBPTRACE_O_SUSPEND_SECCOMP\fP مضبوطاً على نفسه. .RE .TP \fBPTRACE_GETEVENTMSG\fP (منذ لينكس 2.5.46) تجلب رسالة (كـ \fIunsigned long\fP) حول حدث ptrace الذي وقع للتو، وتضعها في العنوان \fIdata\fP في المُتتبِّع. بالنسبة لـ \fBPTRACE_EVENT_EXIT\fP، تكون هذه حالة خروج المُتتبَّع. ولـ \fBPTRACE_EVENT_FORK\fP و \fBPTRACE_EVENT_VFORK\fP و \fBPTRACE_EVENT_VFORK_DONE\fP و \fBPTRACE_EVENT_CLONE\fP، تكون هذه معرف العملية (PID) للعملية الجديدة. ولـ \fBPTRACE_EVENT_SECCOMP\fP، تكون هذه قيمة \fBSECCOMP_RET_DATA\fP لمرشح \fBseccomp\fP(2) المرتبطة بالقاعدة التي انطلقت. (تُهمل \fIaddr\fP). .TP \fBPTRACE_CONT\fP تُعيد تشغيل عملية المُتتبَّع المتوقفة. إذا كانت \fIdata\fP غير صفرية، تُفسر على أنها رقم الإشارة المراد تسليمها للمُتتبَّع؛ وإلا فلا تُسلّم أي إشارة. وبذلك، يمكن للمُتتبِّع، على سبيل المثال، التحكم في تسليم الإشارة المرسلة إلى المُتتبَّع من عدمه. (تُهمل \fIaddr\fP). .TP \fBPTRACE_SYSCALL\fP .TQ \fBPTRACE_SINGLESTEP\fP تُعيد تشغيل المُتتبَّع المتوقف كما في \fBPTRACE_CONT\fP، ولكنها تُرتّب لتوقفه عند الدخول القادم إلى استدعاء نظام أو الخروج منه، أو بعد تنفيذ تعليمة واحدة، على التوالي. (سيتوقف المُتتبَّع أيضًا، كالمعتاد، عند استلام إشارة). من منظور المُتتبِّع، سيبدو أن المُتتبَّع قد توقف بسبب استلام \fBSIGTRAP\fP. لذا، بالنسبة لـ \fBPTRACE_SYSCALL\fP مثلاً، تكمن الفكرة في فحص معطيات استدعاء النظام عند التوقف الأول، ثم القيام بـ \fBPTRACE_SYSCALL\fP آخر وفحص القيمة المعادة من استدعاء النظام عند التوقف الثاني. يُعامل المعطى \fIdata\fP كما في \fBPTRACE_CONT\fP. (تُهمل \fIaddr\fP). .TP \fBPTRACE_SET_SYSCALL\fP (منذ لينكس 2.6.16) .\" commit 3f471126ee53feb5e9b210ea2f525ed3bb9b7a7f .\" As of 4.19-rc2 .\" commit 27aa55c5e5123fa8b8ad0156559d34d7edff58ca .\" see change_syscall in tools/testing/selftests/seccomp/seccomp_bpf.c .\" and also strace's linux/*/set_scno.c files. عندما يكون في syscall\-enter\-stop، غيّر رقم استدعاء النظام الذي يوشك أن يُنفذ إلى الرقم المحدد في وسيط \fIdata\fP. يُتجاهل الوسيط \fIaddr\fP. هذه العملية مدعومة حاليًا فقط على arm (و arm64، وإن كان ذلك للتوافق مع الإصدارات السابقة فقط)، ولكن معظم المعماريات الأخرى لديها وسائل أخرى لتحقيق ذلك (عادةً عن طريق تغيير السجل الذي مررت فيه شيفرة نطاق المستخدم رقم استدعاء النظام). .TP \fBPTRACE_SYSEMU\fP .TQ \fBPTRACE_SYSEMU_SINGLESTEP\fP (منذ لينكس 2.6.14) .\" As at 3.7 بالنسبة لـ \fBPTRACE_SYSEMU\fP، استمر وتوقف عند الدخول إلى استدعاء النظام التالي، والذي لن يُنفذ. انظر التوثيق الخاص بـ syscall\-stops أدناه. بالنسبة لـ \fBPTRACE_SYSEMU_SINGLESTEP\fP، افعل الشيء نفسه ولكن نفذ أيضًا خطوة واحدة إذا لم يكن استدعاء نظام. يُستخدم هذا الاستدعاء من قبل برامج مثل User Mode Linux التي تريد محاكاة جميع استدعاءات نظام المتتبَّع. يُعامل الوسيط \fIdata\fP كما هو الحال في \fBPTRACE_CONT\fP. يُتجاهل الوسيط \fIaddr\fP. هذه العمليات مدعومة حاليًا فقط على x86. .TP \fBPTRACE_LISTEN\fP (منذ لينكس 3.4) أعد تشغيل المتتبَّع المتوقف، ولكن امنعه من التنفيذ. الحالة الناتجة للمتتبَّع مشابهة لعملية أُوقفت بواسطة \fBSIGSTOP\fP (أو أي إشارة إيقاف أخرى). انظر القسم الفرعي "group\-stop" للحصول على معلومات إضافية. يعمل \fBPTRACE_LISTEN\fP فقط على المتتبَّعين المرفقين بواسطة \fBPTRACE_SEIZE\fP. .TP \fBPTRACE_KILL\fP أرسل \fBSIGKILL\fP إلى المتتبَّع لإنهاء عمله. (يُتجاهل \fIaddr\fP و \fIdata\fP.) .IP .\" [Note from Denys Vlasenko: .\" deprecation suggested by Oleg Nesterov. He prefers to deprecate it .\" instead of describing (and needing to support) PTRACE_KILL's quirks.] \fIهذه العملية مهجورة؛ لا تستخدمها!\fP بدلاً من ذلك، أرسل \fBSIGKILL\fP مباشرة باستخدام \fBkill\fP(2) أو \fBtgkill\fP(2). تكمن المشكلة في \fBPTRACE_KILL\fP في أنها تتطلب أن يكون المتتبَّع في حالة signal\-delivery\-stop، وإلا فقد لا تعمل (أي قد تكتمل بنجاح ولكنها لن تقتل المتتبَّع). على النقيض من ذلك، فإن إرسال \fBSIGKILL\fP مباشرة ليس له مثل هذا القيد. .TP \fBPTRACE_INTERRUPT\fP (منذ لينكس 3.4) أوقف المتتبَّع. إذا كان المتتبَّع يعمل أو ينام في مساحة النواة وكان \fBPTRACE_SYSCALL\fP ساري المفعول، يُقاطع استدعاء النظام ويُبلغ عن syscall\-exit\-stop. (يُعاد تشغيل استدعاء النظام المقاطع عند إعادة تشغيل المتتبَّع). إذا كان المتتبَّع قد توقف بالفعل بسبب إشارة وأُرسل إليه \fBPTRACE_LISTEN\fP، يتوقف المتتبَّع مع \fBPTRACE_EVENT_STOP\fP ويعيد \fIWSTOPSIG(status)\fP إشارة التوقف. إذا وُلد أي توقف ptrace\-stop آخر في نفس الوقت (على سبيل المثال، إذا أُرسلت إشارة إلى المتتبَّع)، يحدث توقف ptrace\-stop هذا. إذا لم ينطبق أي مما سبق (على سبيل المثال، إذا كان المتتبَّع يعمل في مساحة المستخدم)، فإنه يتوقف مع \fBPTRACE_EVENT_STOP\fP مع كون \fIWSTOPSIG(status)\fP مساوياً لـ \fBSIGTRAP\fP. يعمل \fBPTRACE_INTERRUPT\fP فقط على المتتبَّعين المرفقين بواسطة \fBPTRACE_SEIZE\fP. .TP \fBPTRACE_ATTACH\fP .\" No longer true (removed by Denys Vlasenko, 2011, who remarks: .\" "I think it isn't true in non-ancient 2.4 and in Linux 2.6/3.x. .\" Basically, it's not true for any Linux in practical use. .\" the behavior of the tracee is as if it had done a .\" .BR PTRACE_TRACEME . .\" The calling process actually becomes the parent of the tracee .\" process for most purposes (e.g., it will receive .\" notification of tracee events and appears in .\" .BR ps (1) .\" output as the tracee's parent), but a .\" .BR getppid (2) .\" by the tracee will still return the PID of the original parent. أرفق العملية المحددة في \fIpid\fP، مما يجعلها متتبَّعاً للعملية المستدعِية. تُرسل إشارة \fBSIGSTOP\fP إلى المتتبَّع، ولكن ليس بالضرورة أن يكون قد توقف بانتهاء هذا الاستدعاء؛ استخدم \fBwaitpid\fP(2) لانتظار توقف المتتبَّع. انظر القسم الفرعي "Attaching and detaching" لمزيد من المعلومات. (يُتجاهل \fIaddr\fP و \fIdata\fP.) .IP تُحكم صلاحية تنفيذ \fBPTRACE_ATTACH\fP بواسطة فحص وضع وصول ptrace \fBPTRACE_MODE_ATTACH_REALCREDS\fP؛ انظر أدناه. .TP \fBPTRACE_SEIZE\fP (منذ لينكس 3.4) .\" .\" Noted by Dmitry Levin: .\" .\" PTRACE_SEIZE was introduced by commit v3.1-rc1~308^2~28, but .\" it had to be used along with a temporary flag PTRACE_SEIZE_DEVEL, .\" which was removed later by commit v3.4-rc1~109^2~20. .\" .\" That is, [before] v3.4 we had a test mode of PTRACE_SEIZE API, .\" which was not compatible with the current PTRACE_SEIZE API introduced .\" in Linux 3.4. .\" أرفق العملية المحددة في \fIpid\fP، مما يجعلها متتبَّعاً للعملية المستدعِية. على عكس \fBPTRACE_ATTACH\fP، لا يوقف \fBPTRACE_SEIZE\fP العملية. يُبلغ عن توقفات المجموعة (Group\-stops) كـ \fBPTRACE_EVENT_STOP\fP ويعيد \fIWSTOPSIG(status)\fP إشارة التوقف. الأبناء المرفقون آليًا يتوقفون مع \fBPTRACE_EVENT_STOP\fP ويعيد \fIWSTOPSIG(status)\fP القيمة \fBSIGTRAP\fP بدلاً من إرسال إشارة \fBSIGSTOP\fP إليهم. لا يرسل \fBexecve\fP(2) إشارة \fBSIGTRAP\fP إضافية. فقط العمليات المرفقة عبر \fBPTRACE_SEIZE\fP يمكنها قبول أوامر \fBPTRACE_INTERRUPT\fP و \fBPTRACE_LISTEN\fP. السلوك "المستولى عليه" الموصوف للتو يورث للأبناء الذين أُرفقوا آليًا باستخدام \fBPTRACE_O_TRACEFORK\fP و \fBPTRACE_O_TRACEVFORK\fP و \fBPTRACE_O_TRACECLONE\fP. يجب أن يكون \fIaddr\fP صفرًا. يحتوي \fIdata\fP على قناع بت لخيارات ptrace لتنشيطها فورًا. .IP .\" تُحكم صلاحية تنفيذ \fBPTRACE_SEIZE\fP بواسطة فحص وضع وصول ptrace \fBPTRACE_MODE_ATTACH_REALCREDS\fP؛ انظر أدناه. .TP \fBPTRACE_SECCOMP_GET_FILTER\fP (منذ لينكس 4.4) .\" commit f8e529ed941ba2bbcbf310b575d968159ce7e895 تسمح هذه العملية للمتتبِّع بتفريغ مرشحات BPF الكلاسيكية الخاصة بالمتتبَّع. .IP \fIaddr\fP هو عدد صحيح يحدد فهرس المرشح المراد تفريغه. أحدث مرشح ثُبت له الفهرس 0. إذا كان \fIaddr\fP أكبر من عدد المرشحات المثبتة، تفشل العملية بالخطأ \fBENOENT\fP. .IP \fIdata\fP هو إما مؤشر إلى مصفوفة \fIstruct sock_filter\fP كبيرة بما يكفي لتخزين برنامج BPF، أو NULL إذا كان البرنامج لن يُخزن. .IP عند النجاح، تكون القيمة المعادة هي عدد التعليمات في برنامج BPF. إذا كان \fIdata\fP هو NULL، فيمكن استخدام هذه القيمة المعادة لتحديد حجم مصفوفة \fIstruct sock_filter\fP الممرة في استدعاء لاحق بشكل صحيح. .IP تفشل هذه العملية بالخطأ \fBEACCES\fP إذا لم يكن لدى المستدعِي قدرة \fBCAP_SYS_ADMIN\fP أو إذا كان المستدعِي في وضع seccomp الصارم أو المرشح. إذا لم يكن المرشح المشار إليه بواسطة \fIaddr\fP مرشح BPF كلاسيكيًا، تفشل العملية بالخطأ \fBEMEDIUMTYPE\fP. .IP هذه العملية متاحة إذا ضُبطت النواة بكل من خياري \fBCONFIG_SECCOMP_FILTER\fP و \fBCONFIG_CHECKPOINT_RESTORE\fP. .TP \fBPTRACE_DETACH\fP .\" أعد تشغيل المتتبَّع المتوقف كما في \fBPTRACE_CONT\fP، ولكن افصل عنه أولاً. تحت نظام لينكس، يمكن فصل المتتبَّع بهذه الطريقة بغض النظر عن الطريقة التي استُخدمت لبدء التتبع. (يُتجاهل \fIaddr\fP.) .TP \fBPTRACE_GET_THREAD_AREA\fP (منذ لينكس 2.6.0) تؤدي هذه العملية مهمة مماثلة لـ \fBget_thread_area\fP(2). حيث تقرأ مدخل TLS في GDT الذي أُعطي فهرسه في \fIaddr\fP، وتضع نسخة من المدخل في \fIstruct user_desc\fP الذي يشير إليه \fIdata\fP. (على النقيض من \fBget_thread_area\fP(2)، يُتجاهل \fIentry_number\fP الخاص بـ \fIstruct user_desc\fP.) .TP \fBPTRACE_SET_THREAD_AREA\fP (منذ لينكس 2.6.0) تؤدي هذه العملية مهمة مماثلة لـ \fBset_thread_area\fP(2). حيث تضبط مدخل TLS في GDT الذي أُعطي فهرسه في \fIaddr\fP، وتعين له البيانات المتوفرة في \fIstruct user_desc\fP الذي يشير إليه \fIdata\fP. (على النقيض من \fBset_thread_area\fP(2)، يُتجاهل \fIentry_number\fP الخاص بـ \fIstruct user_desc\fP؛ وبعبارة أخرى، لا يمكن استخدام عملية ptrace هذه لتخصيص مدخل TLS حر.) .TP \fBPTRACE_GET_SYSCALL_INFO\fP (منذ لينكس 5.3) .\" commit 201766a20e30f982ccfe36bebfad9602c3ff574a استرجع معلومات حول استدعاء النظام الذي تسبب في التوقف. توضع المعلومات في الذاكرة الوسيطة التي يشير إليها الوسيط \fIdata\fP، والذي يجب أن يكون مؤشرًا إلى ذاكرة وسيطة من النوع \fIstruct ptrace_syscall_info\fP. يحتوي الوسيط \fIaddr\fP على حجم الذاكرة الوسيطة التي يشير إليها الوسيط \fIdata\fP (أي \fIsizeof(struct ptrace_syscall_info)\fP). تحتوي القيمة المعادة على عدد البايتات المتاحة لتكتبها النواة. إذا تجاوز حجم البيانات التي ستكتبها النواة الحجم المحدد بواسطة الوسيط \fIaddr\fP، تُقتطع بيانات المخرجات. .IP تحتوي البنية \fIptrace_syscall_info\fP على الحقول التالية: .IP .in +4n .EX struct ptrace_syscall_info { __u8 op; /* نوع توقف استدعاء النظام */ __u8 reserved; /* محجوز للاستخدام المستقبلي، يجب أن يكون صفراً */ __u16 flags; /* محجوز للاستخدام المستقبلي، يجب أن يكون صفراً */ __u32 arch; /* قيمة AUDIT_ARCH_*؛ انظر seccomp(2) */ __u64 instruction_pointer; /* مؤشر تعليمات المعالج */ __u64 stack_pointer; /* مؤشر مكدس المعالج */ union { struct { /* op == PTRACE_SYSCALL_INFO_ENTRY */ __u64 nr; /* رقم استدعاء النظام */ __u64 args[6]; /* وسائط استدعاء النظام */ } entry; struct { /* op == PTRACE_SYSCALL_INFO_EXIT */ __s64 rval; /* قيمة إرجاع استدعاء النظام */ __u8 is_error; /* علامة خطأ استدعاء النظام؛ قيمة منطقية: هل يحتوي rval على قيمة خطأ (\-ERRCODE) أم قيمة إرجاع غير خاطئة؟ */ } exit; struct { /* op == PTRACE_SYSCALL_INFO_SECCOMP */ __u64 nr; /* رقم استدعاء النظام */ __u64 args[6]; /* وسائط استدعاء النظام */ __u32 ret_data; /* جزء SECCOMP_RET_DATA من قيمة إرجاع SECCOMP_RET_TRACE */ } seccomp; }; }; .EE .in .IP تُعرف حقول \fIop\fP و \fIarch\fP و \fIinstruction_pointer\fP و \fIstack_pointer\fP لجميع أنواع توقفات استدعاء نظام ptrace. بقية البنية هي اتحاد (union)؛ يجب قراءة الحقول ذات المغزى فقط لنوع توقف استدعاء النظام المحدد بواسطة حقل \fIop\fP. .IP يحتوي حقل \fIop\fP على إحدى القيم التالية (المعرفة في \fI\fP) التي تشير إلى نوع التوقف الذي حدث وأي جزء من الاتحاد (union) قد مُلئ: .RS .TP \fBPTRACE_SYSCALL_INFO_ENTRY\fP يحتوي مكون \fIentry\fP في الاتحاد على معلومات تتعلق بتوقف الدخول في استدعاء نظام. .TP \fBPTRACE_SYSCALL_INFO_EXIT\fP يحتوي مكون \fIexit\fP في الاتحاد على معلومات تتعلق بتوقف الخروج من استدعاء نظام. .TP \fBPTRACE_SYSCALL_INFO_SECCOMP\fP يحتوي مكون \fIseccomp\fP في الاتحاد على معلومات تتعلق بتوقف \fBPTRACE_EVENT_SECCOMP\fP. .TP \fBPTRACE_SYSCALL_INFO_NONE\fP لا يوجد أي مكون من الاتحاد يحتوي على معلومات ذات صلة. .RE .IP في حالة توقفات الدخول أو الخروج من استدعاء النظام، تقتصر البيانات المعادة بواسطة \fBPTRACE_GET_SYSCALL_INFO\fP على النوع \fBPTRACE_SYSCALL_INFO_NONE\fP ما لم يُضبط خيار \fBPTRACE_O_TRACESYSGOOD\fP قبل حدوث توقف استدعاء النظام المقابل. .TP \fBPTRACE_SET_SYSCALL_INFO\fP (منذ لينكس 6.16) .\" commit 26bb32768fe6552de044f782a58b3272073fbfc0 .\" عدل المعلومات المتعلقة باستدعاء النظام الذي تسبب في التوقف. الوسيط \fIdata\fP هو مؤشر إلى \fIstruct ptrace_syscall_info\fP يحدد معلومات استدعاء النظام المراد ضبطها. يجب ضبط الوسيط \fIaddr\fP على \fIsizeof(struct ptrace_syscall_info)\fP. يمكن تعديل حقول \fInr\fP و \fIargs\fP و \fIrval\fP فقط. .SS "الموت تحت ptrace" عندما تتلقى عملية (ربما متعددة الخيوط) إشارة قتل (تلك التي ضُبط تصرفها على \fBSIG_DFL\fP وإجراءها المبدئي هو قتل العملية)، تخرج جميع الخيوط. يبلغ المتتبَّعون عن موتهم إلى متتبِّعيهم. يُسلم إشعار بهذا الحدث عبر \fBwaitpid\fP(2). .P لاحظ أن إشارة القتل ستؤدي أولاً إلى signal\-delivery\-stop (على متتبَّع واحد فقط)، وفقط بعد حقنها من قبل المتتبِّع (أو بعد إرسالها إلى خيط غير متتبَّع)، سيحدث الموت بسبب الإشارة على \fIجميع\fP المتتبَّعين داخل عملية متعددة الخيوط. (يُشرح مصطلح "signal\-delivery\-stop" أدناه). .P لا يولد \fBSIGKILL\fP حالة signal\-delivery\-stop، وبالتالي لا يمكن للمتتبِّع قمعها. يقتل \fBSIGKILL\fP حتى داخل استدعاءات النظام (لا يولد syscall\-exit\-stop قبل الموت بـ \fBSIGKILL\fP). الأثر الصافي هو أن \fBSIGKILL\fP يقتل العملية دائمًا (جميع خيوطها)، حتى لو كانت بعض خيوط العملية خاضعة للتتبع بـ ptrace. .P عندما يستدعي المتتبَّع \fB_exit\fP(2)، يبلغ عن موته لمتتبِّعه. لا تتأثر الخيوط الأخرى. .P عندما ينفذ أي خيط \fBexit_group\fP(2)، يبلغ كل متتبَّع في مجموعة خيوطه عن موته لمتتبِّعه. .P إذا كان خيار \fBPTRACE_O_TRACEEXIT\fP مفعلًا، سيحدث \fBPTRACE_EVENT_EXIT\fP قبل الموت الفعلي. ينطبق هذا على حالات الخروج عبر \fBexit\fP(2)، و \fBexit_group\fP(2)، والوفيات الناجمة عن الإشارات (باستثناء \fBSIGKILL\fP، اعتمادًا على إصدار النواة؛ انظر BUGS أدناه)، وعندما تُهدم الخيوط عند \fBexecve\fP(2) في عملية متعددة الخيوط. .P لا يمكن للمتتبِّع أن يفترض وجود المتتبَّع المتوقف بـ ptrace. هناك سيناريوهات عديدة قد يموت فيها المتتبَّع أثناء توقفه (مثل \fBSIGKILL\fP). لذلك، يجب أن يكون المتتبِّع مستعدًا للتعامل مع خطأ \fBESRCH\fP في أي عملية ptrace. لسوء الحظ، يُعاد نفس الخطأ إذا كان المتتبَّع موجودًا ولكنه ليس متوقفًا بـ ptrace (بالنسبة للأوامر التي تتطلب متتبَّعًا متوقفًا)، أو إذا لم يكن متتبعًا من قبل العملية التي أصدرت استدعاء ptrace. يحتاج المتتبِّع إلى تتبع حالة التوقف/التشغيل للمتتبَّع، وتفسير \fBESRCH\fP على أنه "مات المتتبَّع بشكل غير متوقع" فقط إذا كان يعلم أن المتتبَّع قد لوحظ وهو يدخل في حالة ptrace\-stop. لاحظ أنه لا يوجد ضمان بأن \fIwaitpid(WNOHANG)\fP سيبلغ بشكل موثوق عن حالة موت المتتبَّع إذا أعادت عملية ptrace الخطأ \fBESRCH\fP. قد يعيد \fIwaitpid(WNOHANG)\fP القيمة 0 بدلاً من ذلك. بعبارة أخرى، قد يكون المتتبَّع "لم يمت تمامًا بعد"، ولكنه يرفض بالفعل عمليات ptrace. .P لا يمكن للمتتبِّع أن يفترض أن المتتبَّع ينهي حياته \fIدائمًا\fP بالإبلاغ عن \fIWIFEXITED(status)\fP أو \fIWIFSIGNALED(status)\fP؛ فهناك حالات لا يحدث فيها ذلك. على سبيل المثال، إذا قام خيط آخر غير قائد مجموعة الخيوط بتنفيذ \fBexecve\fP(2)، فإنه يختفي؛ ولن يُرى معرف العملية (PID) الخاص به مرة أخرى، وسيُبلغ عن أي توقفات ptrace لاحقة تحت معرف العملية الخاص بقائد مجموعة الخيوط. .SS "حالات التوقف" يمكن أن يكون المتتبَّع في حالتين: يعمل أو متوقف. لأغراض ptrace، فإن المتتبَّع المحجوز في استدعاء نظام (مثل \fBread\fP(2) أو \fBpause\fP(2)، إلخ) يُعتبر مع ذلك يعمل، حتى لو كان المتتبَّع محجوزًا لفترة طويلة. حالة المتتبَّع بعد \fBPTRACE_LISTEN\fP هي منطقة رمادية إلى حد ما: فهو ليس في أي ptrace\-stop (أوامر ptrace لن تعمل عليه، وسيقوم بتسليم إشعارات \fBwaitpid\fP(2))، ولكنه قد يُعتبر أيضًا "متوقفًا" لأنه لا ينفذ التعليمات (لم يُجدول)، وإذا كان في حالة group\-stop قبل \fBPTRACE_LISTEN\fP، فلن يستجيب للإشارات حتى تُتلقى إشارة \fBSIGCONT\fP. .P هناك أنواع عديدة من الحالات عندما يكون المتتبَّع متوقفًا، وغالبًا ما يُخلط بينها في مناقشات ptrace. لذلك، من المهم استخدام مصطلحات دقيقة. .P في صفحة الدليل هذه، تُسمى أي حالة توقف يكون فيها المتتبَّع جاهزًا لقبول أوامر ptrace من المتتبِّع بـ \fIptrace\-stop\fP. يمكن تقسيم توقفات ptrace أكثر إلى \fIsignal\-delivery\-stop\fP و \fIgroup\-stop\fP و \fIsyscall\-stop\fP و \fIPTRACE_EVENT stops\fP، وما إلى ذلك. توصف حالات التوقف هذه بالتفصيل أدناه. .P عندما يدخل المتتبَّع العامل في حالة ptrace\-stop، فإنه يخطر متتبِّعه باستخدام \fBwaitpid\fP(2) (أو أحد استدعاءات نظام "الانتظار" الأخرى). تفترض معظم صفحة الدليل هذه أن المتتبِّع ينتظر بـ: .P .in +4n .EX pid = waitpid(pid_or_minus_1, &status, __WALL); .EE .in .P .\" Denys Vlasenko: .\" Do we require __WALL usage, or will just using 0 be ok? (With 0, .\" I am not 100% sure there aren't ugly corner cases.) Are the .\" rules different if user wants to use waitid? Will waitid require .\" WEXITED? .\" يُبلغ عن المتتبَّعين المتوقفين بـ ptrace كقيم معادة مع \fIpid\fP أكبر من 0 وكون \fIWIFSTOPPED(status)\fP صحيحًا. .P لا يتضمن علم \fB__WALL\fP علمي \fBWSTOPPED\fP و \fBWEXITED\fP، لكنه يتضمن وظائفهما ضمنيًا. .P لا يوصى بضبط علم \fBWCONTINUED\fP عند استدعاء \fBwaitpid\fP(2): حالة "الاستمرار" تكون لكل عملية واستهلاكها يمكن أن يربك الأب الحقيقي للمتتبَّع. .P قد يؤدي استخدام علم \fBWNOHANG\fP إلى إعادة \fBwaitpid\fP(2) للقيمة 0 ("لا توجد نتائج انتظار متاحة بعد") حتى لو كان المتتبِّع يعلم أنه يجب أن يكون هناك إشعار. مثال: .P .in +4n .EX errno = 0; ptrace(PTRACE_CONT, pid, 0L, 0L); if (errno == ESRCH) { /* المتتبَّع ميت */ r = waitpid(tracee, &status, __WALL | WNOHANG); /* يمكن أن يظل r صفراً هنا! */ } .EE .in .\" FIXME . .\" waitid usage? WNOWAIT? .\" describe how wait notifications queue (or not queue) .P توجد الأنواع التالية من توقفات ptrace\-stops: signal\-delivery\-stops و group\-stops و \fBPTRACE_EVENT\fP stops و syscall\-stops. يُبلغ عنها جميعًا بواسطة \fBwaitpid\fP(2) مع كون \fIWIFSTOPPED(status)\fP صحيحًا. يمكن التمييز بينها بفحص القيمة \fIstatus>>8\fP، وإذا كان هناك غموض في تلك القيمة، فعن طريق الاستعلام عن \fBPTRACE_GETSIGINFO\fP. (ملاحظة: لا يمكن استخدام ماكرو \fIWSTOPSIG(status)\fP لإجراء هذا الفحص، لأنه يعيد القيمة \fI(status>>8)\ &\ 0xff\fP.) .SS "توقف تسليم الإشارة (Signal\-delivery\-stop)" عندما تتلقى عملية (ربما متعددة الخيوط) أي إشارة باستثناء \fBSIGKILL\fP، تختار النواة خيطًا عشوائيًا يتعامل مع الإشارة. (إذا وُلدت الإشارة باستخدام \fBtgkill\fP(2)، فيمكن للمستدعِي تحديد الخيط المستهدف صراحةً). إذا كان الخيط المختار متتبَّعًا، فإنه يدخل في حالة signal\-delivery\-stop. في هذه المرحلة، لم تُسلم الإشارة بعد إلى العملية، ويمكن للمتتبِّع قمعها. إذا لم يقمع المتتبِّع الإشارة، فإنه يمرر الإشارة إلى المتتبَّع في عملية إعادة تشغيل ptrace التالية. تُسمى هذه الخطوة الثانية من تسليم الإشارة بـ \fIحقن الإشارة\fP (signal injection) في صفحة الدليل هذه. لاحظ أنه إذا كانت الإشارة محجوبة، فلن يحدث signal\-delivery\-stop حتى يُرفع الحجب عن الإشارة، مع الاستثناء المعتاد وهو أن \fBSIGSTOP\fP لا يمكن حجبه. .P يلاحظ المتتبِّع حالة Signal\-delivery\-stop عن طريق إعادة \fBwaitpid\fP(2) لقيمة مع كون \fIWIFSTOPPED(status)\fP صحيحًا، مع إعادة الإشارة بواسطة \fIWSTOPSIG(status)\fP. إذا كانت الإشارة هي \fBSIGTRAP\fP، فقد يكون هذا نوعًا مختلفًا من ptrace\-stop؛ انظر قسمي "Syscall\-stops" و "execve" أدناه للتفاصيل. إذا أعاد \fIWSTOPSIG(status)\fP إشارة توقف، فقد يكون هذا group\-stop؛ انظر أدناه. .SS "حقن الإشارة وقمعها" بعد ملاحظة signal\-delivery\-stop من قبل المتتبِّع، يجب على المتتبِّع إعادة تشغيل المتتبَّع بالاستدعاء .P .in +4n .EX ptrace(PTRACE_restart, pid, 0, sig) .EE .in .P حيث \fBPTRACE_restart\fP هي إحدى عمليات إعادة تشغيل ptrace. إذا كان \fIsig\fP هو 0، فلن تُسلم الإشارة. بخلاف ذلك، تُسلم الإشارة \fIsig\fP. تُسمى هذه العملية \fIحقن الإشارة\fP (signal injection) في صفحة الدليل هذه، لتمييزها عن signal\-delivery\-stop. .P قد تكون قيمة \fIsig\fP مختلفة عن قيمة \fIWSTOPSIG(status)\fP: حيث يمكن للمتتبِّع أن يتسبب في حقن إشارة مختلفة. .P لاحظ أن الإشارة المقْموعة تظل تتسبب في عودة استدعاءات النظام قبل الأوان. في هذه الحالة، سيُعاد تشغيل استدعاءات النظام: سيلاحظ المتتبِّع المتتبَّع وهو يعيد تنفيذ استدعاء النظام المقاطع (أو استدعاء النظام \fBrestart_syscall\fP(2) لعدد قليل من استدعاءات النظام التي تستخدم آلية مختلفة لإعادة التشغيل) إذا استخدم المتتبِّع \fBPTRACE_SYSCALL\fP. حتى استدعاءات النظام (مثل \fBpoll\fP(2)) التي لا يمكن إعادة تشغيلها بعد الإشارة يُعاد تشغيلها بعد قمع الإشارة؛ ومع ذلك، توجد أخطاء برمجية في النواة تتسبب في فشل بعض استدعاءات النظام بـ \fBEINTR\fP على الرغم من عدم حقن إشارة ملحوظة في المتتبَّع. .P أوامر إعادة تشغيل ptrace الصادرة في حالات ptrace\-stops بخلاف signal\-delivery\-stop غير مضمونة لحقن إشارة، حتى لو كان \fIsig\fP غير صفري. لا يُبلغ عن أي خطأ؛ وقد يُتجاهل \fIsig\fP غير الصفري ببساطة. يجب ألا يحاول مستخدمو Ptrace "إنشاء إشارة جديدة" بهذه الطريقة: استخدم \fBtgkill\fP(2) بدلاً من ذلك. .P إن حقيقة أن عمليات حقن الإشارة قد تُتجاهل عند إعادة تشغيل المتتبَّع بعد حالات توقف ptrace التي ليست signal\-delivery\-stops هي سبب للارتباك بين مستخدمي ptrace. أحد السيناريوهات النمطية هو أن يلاحظ المتتبِّع حالة group\-stop، ويخطئ في اعتبارها signal\-delivery\-stop، فيعيد تشغيل المتتبَّع بـ .P .in +4n .EX ptrace(PTRACE_restart, pid, 0, stopsig) .EE .in .P بنية حقن \fIstopsig\fP، ولكن يُتجاهل \fIstopsig\fP ويستمر المتتبَّع في العمل. .P لإشارة \fBSIGCONT\fP أثر جانبي يتمثل في إيقاظ (جميع خيوط) عملية متوقفة في مجموعة (group\-stopped). يحدث هذا الأثر الجانبي قبل signal\-delivery\-stop. لا يمكن للمتتبِّع قمع هذا الأثر الجانبي (يمكنه فقط قمع حقن الإشارة، مما يتسبب فقط في عدم تنفيذ معالج \fBSIGCONT\fP في المتتبَّع، إذا كان مثل هذا المعالج مثبتًا). في الواقع، الاستيقاظ من group\-stop قد يتبعه signal\-delivery\-stop لإشارة (أو إشارات) \fIبخلاف\fP \fBSIGCONT\fP، إذا كانت معلقة عند تسليم \fBSIGCONT\fP. بعبارة أخرى، قد لا تكون \fBSIGCONT\fP هي أول إشارة يلاحظها المتتبَّع بعد إرسالها. .P تتسبب إشارات الإيقاف في دخول (جميع خيوط) العملية في حالة group\-stop. يحدث هذا الأثر الجانبي بعد حقن الإشارة، وبالتالي يمكن للمتتبِّع قمعه. .P .\" In the Linux 2.4 sources, in arch/i386/kernel/signal.c::do_signal(), .\" there is: .\" .\" /* The debugger continued. Ignore SIGSTOP. */ .\" if (signr == SIGSTOP) .\" continue; في لينكس 2.4 وما قبله، لا يمكن حقن إشارة \fBSIGSTOP\fP. .P يمكن استخدام \fBPTRACE_GETSIGINFO\fP لاستعادة بنية \fIsiginfo_t\fP التي تقابل الإشارة المسلمة. يمكن استخدام \fBPTRACE_SETSIGINFO\fP لتعديلها. إذا استُخدم \fBPTRACE_SETSIGINFO\fP لتغيير \fIsiginfo_t\fP، فيجب أن يتطابق حقل \fIsi_signo\fP والمعامل \fIsig\fP في أمر إعادة التشغيل، وإلا ستكون النتيجة غير محددة. .SS "توقف المجموعة (Group\-stop)" عندما تتلقى عملية (قد تكون متعددة الخيوط) إشارة إيقاف، تتوقف جميع الخيوط. وإذا كان بعض هذه الخيوط خاضعًا للتتبع، فإنها تدخل في حالة "توقف المجموعة" (group\-stop). لاحظ أن إشارة الإيقاف ستؤدي أولاً إلى "توقف تسليم الإشارة" (signal\-delivery\-stop) (على متتبَّع واحد فقط)، وفقط بعد أن يتم حقنها بواسطة المتتبِّع (أو بعد إرسالها إلى خيط غير خاضع للتتبع)، سيبدأ "توقف المجموعة" في \fIكافة\fP المتتبَّعين داخل العملية متعددة الخيوط. وكما هو معتاد، يبلغ كل متتبَّع عن "توقف المجموعة" الخاص به بشكل منفصل إلى المتتبِّع المقابل له. .P يلاحظ المتتبِّع حالة Group\-stop عن طريق إعادة \fBwaitpid\fP(2) لقيمة مع كون \fIWIFSTOPPED(status)\fP صحيحًا، مع توفر إشارة التوقف عبر \fIWSTOPSIG(status)\fP. تُعاد نفس النتيجة من قبل بعض الفئات الأخرى من ptrace\-stops، لذلك فإن الممارسة الموصى بها هي إجراء الاستدعاء .P .in +4n .EX ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo) .EE .in .P يمكن تجنب الاستدعاء إذا لم تكن الإشارة \fBSIGSTOP\fP أو \fBSIGTSTP\fP أو \fBSIGTTIN\fP أو \fBSIGTTOU\fP؛ فهذه الإشارات الأربع فقط هي إشارات توقف. إذا رأى المتتبِّع شيئًا آخر، فلا يمكن أن يكون group\-stop. بخلاف ذلك، يحتاج المتتبِّع لاستدعاء \fBPTRACE_GETSIGINFO\fP. إذا فشل \fBPTRACE_GETSIGINFO\fP بـ \fBEINVAL\fP، فهو بالتأكيد group\-stop. (رموز فشل أخرى ممكنة، مثل \fBESRCH\fP ("لا توجد عملية كهذه") إذا قتل \fBSIGKILL\fP المتتبَّع). .P إذا أُرفق المتتبَّع باستخدام \fBPTRACE_SEIZE\fP، يُشار إلى group\-stop بواسطة \fBPTRACE_EVENT_STOP\fP: القيمة \fIstatus>>16 == PTRACE_EVENT_STOP\fP. يسمح هذا باكتشاف group\-stops دون الحاجة إلى استدعاء \fBPTRACE_GETSIGINFO\fP إضافي. .P اعتبارًا من لينكس 2.6.38، بعد أن يرى المتتبِّع حالة ptrace\-stop للمتتبَّع وحتى يعيد تشغيله أو يقتله، لن يعمل المتتبَّع، ولن يرسل إشعارات (باستثناء الموت بـ \fBSIGKILL\fP) للمتتبِّع، حتى لو دخل المتتبِّع في استدعاء \fBwaitpid\fP(2) آخر. .P يتسبب سلوك النواة الموصوف في الفقرة السابقة في حدوث مشكلة في التعامل الشفاف مع إشارات الإيقاف. إذا أعاد المتتبِّع تشغيل المتتبَّع بعد group\-stop، فستُتجاهل إشارة الإيقاف فعليًا\[em]إذ لا يظل المتتبَّع متوقفًا بل يعمل. إذا لم يعد المتتبِّع تشغيل المتتبَّع قبل الدخول في استدعاء \fBwaitpid\fP(2) التالي، فلن يُبلغ عن إشارات \fBSIGCONT\fP المستقبلية للمتتبِّع؛ وهذا سيجعل إشارات \fBSIGCONT\fP ليس لها أي تأثير على المتتبَّع. .P منذ لينكس 3.4، توجد طريقة للتغلب على هذه المشكلة: بدلاً من \fBPTRACE_CONT\fP، يمكن استخدام أمر \fBPTRACE_LISTEN\fP لإعادة تشغيل المتتبَّع بطريقة لا ينفذ فيها تعليمات، بل ينتظر حدثًا جديدًا يمكنه الإبلاغ عنه عبر \fBwaitpid\fP(2) (مثل عندما يُعاد تشغيله بواسطة \fBSIGCONT\fP). .SS "توقفات PTRACE_EVENT" إذا ضبط المتتبِّع خيارات \fBPTRACE_O_TRACE_*\fP، سيدخل المتتبَّع في حالات ptrace\-stops تُسمى توقفات \fBPTRACE_EVENT\fP. .P يلاحظ المتتبِّع توقفات \fBPTRACE_EVENT\fP عن طريق إعادة \fBwaitpid\fP(2) لقيمة مع \fIWIFSTOPPED(status)\fP، ويعيد \fIWSTOPSIG(status)\fP القيمة \fBSIGTRAP\fP (أو بالنسبة لـ \fBPTRACE_EVENT_STOP\fP، يعيد إشارة التوقف إذا كان المتتبَّع في حالة group\-stop). يُضبط بت إضافي في البايت الأعلى من كلمة الحالة: ستكون القيمة \fIstatus>>8\fP هي .P .in +4n .EX ((PTRACE_EVENT_foo<<8) | SIGTRAP). .EE .in .P توجد الأحداث التالية: .TP \fBPTRACE_EVENT_VFORK\fP توقف قبل العودة من \fBvfork\fP(2) أو \fBclone\fP(2) مع وسم \fBCLONE_VFORK\fP. عندما يستأنف المُتتبَّع بعد هذا التوقف، فإنه سينتظر خروج الابن أو تنفيذه لأمر exec قبل متابعة تنفيذه (بمعنى آخر، السلوك المعتاد في \fBvfork\fP(2)). .TP \fBPTRACE_EVENT_FORK\fP توقف قبل العودة من \fBfork\fP(2) أو \fBclone\fP(2) مع ضبط إشارة الخروج لتكون \fBSIGCHLD\fP. .TP \fBPTRACE_EVENT_CLONE\fP توقف قبل العودة من \fBclone\fP(2). .TP \fBPTRACE_EVENT_VFORK_DONE\fP توقف قبل العودة من \fBvfork\fP(2) أو \fBclone\fP(2) مع وسم \fBCLONE_VFORK\fP، ولكن بعد أن يرفع الابن الحظر عن هذا المُتتبَّع بالخروج أو تنفيذ exec. .P في جميع حالات التوقف الأربعة الموصوفة أعلاه، يحدث التوقف في الأب (أي المُتتبَّع)، وليس في الخيط المنشأ حديثًا. يمكن استخدام \fBPTRACE_GETEVENTMSG\fP لاسترداد معرف الخيط الجديد. .TP \fBPTRACE_EVENT_EXEC\fP توقف قبل العودة من \fBexecve\fP(2). منذ الإصدار 3.0 من لينكس، يعيد \fBPTRACE_GETEVENTMSG\fP معرف الخيط السابق. .TP \fBPTRACE_EVENT_EXIT\fP توقف قبل الخروج (بما في ذلك الموت الناتج عن \fBexit_group\fP(2))، أو الموت بسبب إشارة، أو الخروج الناتج عن \fBexecve\fP(2) في عملية متعددة الخيوط. يعيد \fBPTRACE_GETEVENTMSG\fP حالة الخروج. يمكن فحص المسجلات (على عكس ما يحدث عند الخروج "الحقيقي"). المُتتبَّع لا يزال حيًا؛ ويجب استئنافه عبر \fBPTRACE_CONT\fP أو فصله بـ \fBPTRACE_DETACH\fP لإنهاء عملية الخروج. .TP \fBPTRACE_EVENT_STOP\fP توقف ناتج عن أمر \fBPTRACE_INTERRUPT\fP، أو توقف جماعي، أو توقف ptrace أولي عند إرفاق ابن جديد (فقط إذا أُرفق باستخدام \fBPTRACE_SEIZE\fP). .TP \fBPTRACE_EVENT_SECCOMP\fP توقف أطلقت شرارته قاعدة \fBseccomp\fP(2) عند دخول المُتتبَّع لاستدعاء نظام عندما يضبط المتتبع خيار \fBPTRACE_O_TRACESECCOMP\fP. يمكن استرداد بيانات رسالة حدث seccomp (من جزء \fBSECCOMP_RET_DATA\fP في قاعدة مرشح seccomp) عبر \fBPTRACE_GETEVENTMSG\fP. تم وصف دلالات هذا التوقف بالتفصيل في قسم منفصل أدناه. .P يعيد \fBPTRACE_GETSIGINFO\fP عند توقفات \fBPTRACE_EVENT\fP القيمة \fBSIGTRAP\fP في \fIsi_signo\fP، مع ضبط \fIsi_code\fP على \fI(event<<8)\ |\ SIGTRAP\fP. .SS "توقفات استدعاء النظام" إذا أُعيد تشغيل المُتتبَّع بواسطة \fBPTRACE_SYSCALL\fP أو \fBPTRACE_SYSEMU\fP، يدخل المُتتبَّع في "توقف\-دخول\-استدعاء\-النظام" قبيل الدخول في أي استدعاء نظام (والذي لن يُنفذ إذا كانت إعادة التشغيل باستخدام \fBPTRACE_SYSEMU\fP، بغض النظر عن أي تغيير أُجري على المسجلات في هذه النقطة أو كيفية إعادة تشغيل المُتتبَّع بعد هذا التوقف). وبغض النظر عن الطريقة التي تسببت في توقف\-دخول\-استدعاء\-النظام، إذا أعاد المتتبع تشغيل المُتتبَّع باستخدام \fBPTRACE_SYSCALL\fP، يدخل المُتتبَّع في "توقف\-خروج\-استدعاء\-النظام" عند انتهاء استدعاء النظام، أو إذا قاطعته إشارة. (أي أن توقف\-تسليم\-الإشارة لا يحدث أبدًا بين توقف\-دخول\-استدعاء\-النظام وتوقف\-خروج\-استدعاء\-النظام؛ بل يحدث \fIبعد\fP توقف\-خروج\-استدعاء\-النظام). إذا استُؤنف المُتتبَّع باستخدام أي طريقة أخرى (بما في ذلك \fBPTRACE_SYSEMU\fP)، فلن يحدث توقف\-خروج\-استدعاء\-النظام. لاحظ أن جميع ذكر \fBPTRACE_SYSEMU\fP ينطبق بالتساوي على \fBPTRACE_SYSEMU_SINGLESTEP\fP. .P ومع ذلك، حتى لو استُؤنف المُتتبَّع باستخدام \fBPTRACE_SYSCALL\fP، فليس مضمونًا أن يكون التوقف التالي هو توقف\-خروج\-استدعاء\-النظام. الاحتمالات الأخرى هي أن يتوقف المُتتبَّع في توقف \fBPTRACE_EVENT\fP (بما في ذلك توقفات seccomp)، أو يخرج (إذا دخل \fB_exit\fP(2) أو \fBexit_group\fP(2))، أو يُقتل بواسطة \fBSIGKILL\fP، أو يموت بصمت (إذا كان قائدًا لمجموعة خيوط، وحدث \fBexecve\fP(2) في خيط آخر، وهذا الخيط لا يتتبعه نفس المتتبع؛ ستُناقش هذه الحالة لاحقًا). .P يُلاحظ المتتبع توقف\-دخول\-استدعاء\-النظام وتوقف\-خروج\-استدعاء\-النظام عندما يعيد \fBwaitpid\fP(2) القيمة \fIWIFSTOPPED(status)\fP صحيحة، ويعطي \fIWSTOPSIG(status)\fP القيمة \fBSIGTRAP\fP. إذا ضُبط خيار \fBPTRACE_O_TRACESYSGOOD\fP بواسطة المتتبع، فسيعطي \fIWSTOPSIG(status)\fP القيمة \fI(SIGTRAP\ |\ 0x80)\fP. .P يمكن تمييز توقفات استدعاء النظام عن توقف\-تسليم\-الإشارة مع \fBSIGTRAP\fP عبر الاستعلام بـ \fBPTRACE_GETSIGINFO\fP للحالات التالية: .TP \fIsi_code\fP <= 0 سُلّمت \fBSIGTRAP\fP نتيجة لإجراء في مساحة المستخدم، على سبيل المثال، استدعاء نظام (\fBtgkill\fP(2)، \fBkill\fP(2)، \fBsigqueue\fP(3)، إلخ)، أو انتهاء صلاحية مؤقت POSIX، أو تغيير حالة في طابور رسائل POSIX، أو اكتمال عملية إدخال/إخراج غير متزامنة. .TP \fIsi_code\fP == SI_KERNEL (0x80) أُرسلت \fBSIGTRAP\fP بواسطة النواة. .TP \fIsi_code\fP == SIGTRAP أو \fIsi_code\fP == (SIGTRAP|0x80) هذا توقف استدعاء نظام. .P ومع ذلك، تحدث توقفات استدعاء النظام بشكل متكرر للغاية (مرتين لكل استدعاء نظام)، وقد يكون تنفيذ \fBPTRACE_GETSIGINFO\fP لكل توقف مكلفًا بعض الشيء. .P تسمح بعض المعماريات بتمييز الحالات من خلال فحص المسجلات. على سبيل المثال، في x86، تكون القيمة \fIrax\fP == \-\fBENOSYS\fP في توقف\-دخول\-استدعاء\-النظام. بما أن \fBSIGTRAP\fP (مثل أي إشارة أخرى) تحدث دائمًا \fIبعد\fP توقف\-خروج\-استدعاء\-النظام، وفي هذه النقطة نادرًا ما تحتوي \fIrax\fP على \-\fBENOSYS\fP، فإن \fBSIGTRAP\fP تبدو كأنها "توقف استدعاء نظام ليس توقف\-دخول\-استدعاء\-النظام"؛ بمعنى آخر، تبدو كأنها "توقف\-خروج\-استدعاء\-نظام شارد" ويمكن اكتشافها بهذه الطريقة. لكن هذا الاكتشاف هش ويُفضل تجنبه. .P استخدام خيار \fBPTRACE_O_TRACESYSGOOD\fP هو الطريقة الموصى بها لتمييز توقفات استدعاء النظام عن الأنواع الأخرى من توقفات ptrace، لأنها موثوقة ولا تسبب ضعفًا في الأداء. .P لا يمكن للمتتبع التمييز بين توقف\-دخول\-استدعاء\-النظام وتوقف\-خروج\-استدعاء\-النظام. يحتاج المتتبع إلى تتبع تسلسل توقفات ptrace لتجنب تفسير توقف الدخول على أنه توقف خروج أو العكس. بشكل عام، يتبع توقف\-دخول\-استدعاء\-النظام دائمًا توقف\-خروج\-استدعاء\-النظام، أو توقف \fBPTRACE_EVENT\fP، أو موت المُتتبَّع؛ ولا يمكن لأي أنواع أخرى من توقف ptrace أن تحدث بينهما. ومع ذلك، لاحظ أن توقفات seccomp (انظر أدناه) قد تسبب توقفات\-خروج\-استدعاء\-النظام، دون توقفات دخول سابقة. إذا كان seccomp قيد الاستخدام، فيجب توخي الحذر لعدم تفسير مثل هذه التوقفات على أنها توقفات\-دخول\-استدعاء\-نظام. .P إذا استخدم المتتبع، بعد توقف\-دخول\-استدعاء\-النظام، أمر إعادة تشغيل غير \fBPTRACE_SYSCALL\fP، فلن يُولَّد توقف\-خروج\-استدعاء\-النظام. .P .\" يعيد \fBPTRACE_GETSIGINFO\fP عند توقفات استدعاء النظام القيمة \fBSIGTRAP\fP في \fIsi_signo\fP، مع ضبط \fIsi_code\fP على \fBSIGTRAP\fP أو \fI(SIGTRAP|0x80)\fP. .SS "توقفات PTRACE_EVENT_SECCOMP (لينكس 3.5 إلى لينكس 4.7)" تغير سلوك توقفات \fBPTRACE_EVENT_SECCOMP\fP وتفاعلها مع الأنواع الأخرى من توقفات ptrace بين إصدارات النواة. هذا يوثق السلوك من وقت تقديمها حتى لينكس 4.7 (شاملة). أما السلوك في إصدارات النواة اللاحقة فهو موثق في القسم التالي. .P يحدث توقف \fBPTRACE_EVENT_SECCOMP\fP كلما أُطلقت قاعدة \fBSECCOMP_RET_TRACE\fP. هذا مستقل عن الطريقة المستخدمة لإعادة تشغيل استدعاء النظام. والجدير بالذكر أن seccomp لا يزال يعمل حتى لو أُعيد تشغيل المُتتبَّع باستخدام \fBPTRACE_SYSEMU\fP ويتم تخطي استدعاء النظام هذا دون قيد أو شرط. .P .\" ستتصرف عمليات إعادة التشغيل من هذا التوقف كما لو أن التوقف حدث مباشرة قبل استدعاء النظام المعني. على وجه الخصوص، سيتسبب كل من \fBPTRACE_SYSCALL\fP و \fBPTRACE_SYSEMU\fP عادة في توقف\-دخول\-استدعاء\-نظام لاحق. ومع ذلك، إذا كان رقم استدعاء النظام سالبًا بعد \fBPTRACE_EVENT_SECCOMP\fP، فسيتم تخطي كل من توقف\-دخول\-استدعاء\-النظام واستدعاء النظام نفسه. وهذا يعني أنه إذا كان رقم استدعاء النظام سالبًا بعد \fBPTRACE_EVENT_SECCOMP\fP وأُعيد تشغيل المُتتبَّع باستخدام \fBPTRACE_SYSCALL\fP، فإن التوقف التالي الملاحظ سيكون توقف\-خروج\-استدعاء\-نظام، بدلاً من توقف\-دخول\-استدعاء\-النظام الذي كان متوقعًا. .SS "توقفات PTRACE_EVENT_SECCOMP (منذ لينكس 4.8)" .\" commit 93e35efb8de45393cf61ed07f7b407629bf698ea بدءًا من لينكس 4.8، أُعيد ترتيب توقف \fBPTRACE_EVENT_SECCOMP\fP ليحدث بين توقف\-دخول\-استدعاء\-النظام وتوقف\-خروج\-استدعاء\-النظام. لاحظ أن seccomp لم يعد يعمل (ولن يتم الإبلاغ عن \fBPTRACE_EVENT_SECCOMP\fP) إذا تم تخطي استدعاء النظام بسبب \fBPTRACE_SYSEMU\fP. .P من الناحية الوظيفية، يعمل توقف \fBPTRACE_EVENT_SECCOMP\fP بشكل مشابه لـ توقف\-دخول\-استدعاء\-النظام (أي أن الاستمرارات باستخدام \fBPTRACE_SYSCALL\fP ستؤدي إلى توقفات\-خروج\-استدعاء\-النظام، ويمكن تغيير رقم استدعاء النظام وأي مسجلات أخرى معدلة تكون مرئية لاستدعاء النظام المراد تنفيذه أيضًا). لاحظ أنه قد يكون هناك، ولكن ليس بالضرورة، توقف\-دخول\-استدعاء\-نظام سابق. .P .\" بعد توقف \fBPTRACE_EVENT_SECCOMP\fP، سيُعاد تشغيل seccomp، مع عمل قاعدة \fBSECCOMP_RET_TRACE\fP الآن بنفس طريقة \fBSECCOMP_RET_ALLOW\fP. تحديدًا، هذا يعني أنه إذا لم تُعدل المسجلات أثناء توقف \fBPTRACE_EVENT_SECCOMP\fP، فسيتم السماح باستدعاء النظام حينها. .SS "توقفات PTRACE_SINGLESTEP" .\" .\" FIXME . .\" document stops occurring with PTRACE_SINGLESTEP .\" [تفاصيل هذا النوع من التوقفات لم تُوثق بعد.] .SS "أوامر ptrace المعلوماتية وأوامر إعادة التشغيل" تتطلب معظم أوامر ptrace (الكل باستثناء \fBPTRACE_ATTACH\fP، و \fBPTRACE_SEIZE\fP، و \fBPTRACE_TRACEME\fP، و \fBPTRACE_INTERRUPT\fP، و \fBPTRACE_KILL\fP) أن يكون المُتتبَّع في حالة توقف\-ptrace، وإلا فإنها تفشل مع الخطأ \fBESRCH\fP. .P عندما يكون المُتتبَّع في توقف\-ptrace، يمكن للمتتبع قراءة وكتابة البيانات إليه باستخدام الأوامر المعلوماتية. تترك هذه الأوامر المُتتبَّع في حالة توقف\-ptrace: .P .in +4n .EX ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0); ptrace(PTRACE_POKETEXT/POKEDATA/POKEUSER, pid, addr, long_val); ptrace(PTRACE_GETREGS/GETFPREGS, pid, 0, &struct); ptrace(PTRACE_SETREGS/SETFPREGS, pid, 0, &struct); ptrace(PTRACE_GETREGSET, pid, NT_foo, &iov); ptrace(PTRACE_SETREGSET, pid, NT_foo, &iov); ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo); ptrace(PTRACE_SETSIGINFO, pid, 0, &siginfo); ptrace(PTRACE_GETEVENTMSG, pid, 0, &long_var); ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags); .EE .in .P لاحظ أن بعض الأخطاء لا يتم الإبلاغ عنها. على سبيل المثال، قد لا يكون لضبط معلومات الإشارة (\fIsiginfo\fP) أي تأثير في بعض توقفات ptrace، ومع ذلك قد ينجح الاستدعاء (يعيد 0 ولا يضبط \fIerrno\fP)؛ كما أن الاستعلام عن \fBPTRACE_GETEVENTMSG\fP قد ينجح ويعيد قيمة عشوائية إذا لم يكن توقف ptrace الحالي موثقًا كأنه يعيد رسالة حدث ذات مغزى. .P الاستدعاء .P .in +4n .EX ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags); .EE .in .P يؤثر على مُتتبَّع واحد. تُستبدل الأعلام الحالية للمُتتبَّع. تُورَّث الأعلام بواسطة المُتتبَّعين الجدد المنشئين والذين أُرفقوا آليًا عبر خيارات \fBPTRACE_O_TRACEFORK\fP، أو \fBPTRACE_O_TRACEVFORK\fP، أو \fBPTRACE_O_TRACECLONE\fP النشطة. .P مجموعة أخرى من الأوامر تجعل المُتتبَّع المتوقف بـ ptrace يعمل. لها الشكل التالي: .P .in +4n .EX ptrace(cmd, pid, 0, sig); .EE .in .P حيث \fIcmd\fP هو \fBPTRACE_CONT\fP، أو \fBPTRACE_LISTEN\fP، أو \fBPTRACE_DETACH\fP، أو \fBPTRACE_SYSCALL\fP، أو \fBPTRACE_SINGLESTEP\fP، أو \fBPTRACE_SYSEMU\fP، أو \fBPTRACE_SYSEMU_SINGLESTEP\fP. إذا كان المُتتبَّع في توقف\-تسليم\-الإشارة، فإن \fIsig\fP هي الإشارة المراد حقنها (إذا كانت غير صفرية). وإلا، فقد يتم تجاهل \fIsig\fP. (عند إعادة تشغيل مُتتبَّع من توقف ptrace غير توقف\-تسليم\-الإشارة، فإن الممارسة الموصى بها هي تمرير 0 دائمًا في \fIsig\fP). .SS "الإرفاق والفصل" يمكن إرفاق خيط بالمتتبع باستخدام الاستدعاء .P .in +4n .EX ptrace(PTRACE_ATTACH, pid, 0, 0); .EE .in .P أو .P .in +4n .EX ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_flags); .EE .in .P .\" .\" FIXME Describe how to attach to a thread which is already group-stopped. يرسل \fBPTRACE_ATTACH\fP إشارة \fBSIGSTOP\fP إلى هذا الخيط. إذا أراد المتتبع ألا يكون لهذه \fBSIGSTOP\fP أي تأثير، فيجب عليه كبتها. لاحظ أنه إذا أُرسلت إشارات أخرى بشكل متزامن إلى هذا الخيط أثناء الإرفاق، فقد يرى المتتبع أن المُتتبَّع يدخل في توقف\-تسليم\-الإشارة مع إشارة (إشارات) أخرى أولاً! الممارسة المعتادة هي إعادة حقن هذه الإشارات حتى تُرى \fBSIGSTOP\fP، ثم كبت حقن \fBSIGSTOP\fP. الخلل التصميمي هنا هو أن إرفاق ptrace وإشارة \fBSIGSTOP\fP المسلمة بشكل متزامن قد يتسابقان وقد تضيع \fBSIGSTOP\fP المتزامنة. .P بما أن الإرفاق يرسل \fBSIGSTOP\fP والمتتبع يكبتها عادة، فقد يتسبب ذلك في عودة \fBEINTR\fP شاردة من استدعاء النظام الذي يتم تنفيذه حاليًا في المُتتبَّع، كما هو موضح في قسم "حقن الإشارة وكبتها". .P منذ لينكس 3.4، يمكن استخدام \fBPTRACE_SEIZE\fP بدلاً من \fBPTRACE_ATTACH\fP. لا يوقف \fBPTRACE_SEIZE\fP العملية المرفقة. إذا كنت بحاجة إلى إيقافها بعد الإرفاق (أو في أي وقت آخر) دون إرسال أي إشارات إليها، فاستخدم أمر \fBPTRACE_INTERRUPT\fP. .P العملية .P .in +4n .EX ptrace(PTRACE_TRACEME, 0, 0, 0); .EE .in .P تحول الخيط المستدعي إلى مُتتبَّع. يستمر الخيط في العمل (لا يدخل في توقف\-ptrace). الممارسة الشائعة هي اتباع \fBPTRACE_TRACEME\fP بـ .P .in +4n .EX raise(SIGSTOP); .EE .in .P والسماح للأب (الذي أصبح متتبعنا الآن) بمراقبة توقف\-تسليم\-الإشارة الخاص بنا. .P إذا كانت خيارات \fBPTRACE_O_TRACEFORK\fP، أو \fBPTRACE_O_TRACEVFORK\fP، أو \fBPTRACE_O_TRACECLONE\fP سارية المفعول، فإن الأبناء الذين أُنشئوا بواسطة، على التوالي، \fBvfork\fP(2) أو \fBclone\fP(2) مع علم \fBCLONE_VFORK\fP، و \fBfork\fP(2) أو \fBclone\fP(2) مع ضبط إشارة الخروج على \fBSIGCHLD\fP، وأنواع أخرى من \fBclone\fP(2)، يتم إرفاقهم آليًا بنفس المتتبع الذي تتبع والدهم. تُسلم \fBSIGSTOP\fP للأبناء، مما يجعلهم يدخلون في توقف\-تسليم\-الإشارة بعد خروجهم من استدعاء النظام الذي أنشأهم. .P يتم فصل المُتتبَّع بواسطة: .P .in +4n .EX ptrace(PTRACE_DETACH, pid, 0, sig); .EE .in .P \fBPTRACE_DETACH\fP هي عملية إعادة تشغيل؛ لذا فهي تتطلب أن يكون المُتتبَّع في توقف\-ptrace. إذا كان المُتتبَّع في توقف\-تسليم\-الإشارة، فيمكن حقن إشارة. وإلا، فقد يتم تجاهل معامل \fIsig\fP بصمت. .P .\" FIXME Describe how to detach from a group-stopped tracee so that it .\" doesn't run, but continues to wait for SIGCONT. إذا كان المُتتبَّع يعمل عندما يريد المتتبع فصله، فإن الحل المعتاد هو إرسال \fBSIGSTOP\fP (باستخدام \fBtgkill\fP(2)، للتأكد من وصولها إلى الخيط الصحيح)، وانتظار المُتتبَّع حتى يتوقف في توقف\-تسليم\-الإشارة لـ \fBSIGSTOP\fP ثم فصله (مع كبت حقن \fBSIGSTOP\fP). ثمة خلل تصميمي هو أن هذا يمكن أن يتسابق مع إشارات \fBSIGSTOP\fP المتزامنة. تعقيد آخر هو أن المُتتبَّع قد يدخل في توقفات ptrace أخرى ويحتاج إلى إعادة تشغيله وانتظاره مرة أخرى حتى تُرى \fBSIGSTOP\fP. تعقيد إضافي هو التأكد من أن المُتتبَّع ليس متوقفًا بالفعل بـ ptrace، لأنه لا يحدث تسليم إشارات أثناء توقفه \- ولا حتى \fBSIGSTOP\fP. .P إذا مات المتتبع، يتم فصل جميع المُتتبَّعين آليًا وإعادة تشغيلهم، ما لم يكونوا في حالة توقف جماعي. معالجة إعادة التشغيل من التوقف الجماعي تحتوي حاليًا على أخطاء، ولكن السلوك "كما هو مخطط له" هو ترك المُتتبَّع متوقفًا وينتظر \fBSIGCONT\fP. إذا أُعيد تشغيل المُتتبَّع من توقف\-تسليم\-الإشارة، فسيتم حقن الإشارة المعلقة. .SS "execve(2) تحت ptrace" .\" clone(2) CLONE_THREAD says: .\" If any of the threads in a thread group performs an execve(2), .\" then all threads other than the thread group leader are terminated, .\" and the new program is executed in the thread group leader. .\" .\" In Linux 3.1 sources, see fs/exec.c::de_thread() عندما يستدعي خيط واحد في عملية متعددة الخيوط \fBexecve\fP(2)، تدمر النواة جميع الخيوط الأخرى في العملية، وتعيد ضبط معرف الخيط للخيط المنفذ إلى معرف مجموعة الخيوط (معرف العملية). (أو، بعبارة أخرى، عندما تقوم عملية متعددة الخيوط بـ \fBexecve\fP(2)، عند اكتمال الاستدعاء، يبدو الأمر كما لو أن \fBexecve\fP(2) حدثت في قائد مجموعة الخيوط، بغض النظر عن الخيط الذي قام بـ \fBexecve\fP(2)). إعادة ضبط معرف الخيط هذه تبدو مربكة للغاية للمتتبعين: .IP \[bu] 3 تتوقف جميع الخيوط الأخرى في توقف \fBPTRACE_EVENT_EXIT\fP، إذا كان خيار \fBPTRACE_O_TRACEEXIT\fP مفعلًا. ثم تبلغ جميع الخيوط الأخرى باستثناء قائد مجموعة الخيوط عن الموت كما لو أنها خرجت عبر \fB_exit\fP(2) مع رمز الخروج 0. .IP \[bu] يغير المُتتبَّع المنفذ معرف خيطه أثناء وجوده في \fBexecve\fP(2). (تذكر أنه تحت ptrace، فإن "pid" العائد من \fBwaitpid\fP(2)، أو الذي يتم تغذيته في استدعاءات ptrace، هو معرف خيط المُتتبَّع). أي أنه يتم إعادة ضبط معرف خيط المُتتبَّع ليكون هو نفسه معرف عمليته، وهو نفسه معرف خيط قائد مجموعة الخيوط. .IP \[bu] ثم يحدث توقف \fBPTRACE_EVENT_EXEC\fP، إذا كان خيار \fBPTRACE_O_TRACEEXEC\fP مفعلًا. .IP \[bu] إذا كان قائد مجموعة الخيوط قد أبلغ عن توقف \fBPTRACE_EVENT_EXIT\fP الخاص به بحلول هذا الوقت، فسيظهر للمتتبِّع أن قائد الخيوط الميت "يظهر مجددًا من العدم". (ملاحظة: لا يبلغ قائد مجموعة الخيوط عن موته عبر \fIWIFEXITED(status)\fP إلا بعد أن يكون هناك خيط حي واحد آخر على الأقل؛ وهذا يلغي احتمالية أن يراه المتتبِّع يموت ثم يظهر مجددًا). وإذا كان قائد مجموعة الخيوط لا يزال حيًا، فقد يبدو للمتتبِّع كما لو أن قائد مجموعة الخيوط عاد من استدعاء نظام مختلف عن الذي دخله، أو حتى "عاد من استدعاء نظام على الرغم من أنه لم يكن في أي استدعاء نظام". أما إذا كان قائد مجموعة الخيوط غير متتبَّع (أو كان يتتبعه متتبِّع مختلف)، فإنه أثناء \fBexecve\fP(2) سيظهر كما لو أنه أصبح متتبَّعًا لمتتبِّع الخيط المتتبَّع الذي ينفذ عملية التنفيذ (execing tracee). .P كل الآثار المذكورة أعلاه هي نتاج لتغير معرف الخيط في المُتتبَّع. .P خيار \fBPTRACE_O_TRACEEXEC\fP هو الأداة الموصى بها للتعامل مع هذا الموقف. أولاً، يفعل توقف \fBPTRACE_EVENT_EXEC\fP، الذي يحدث قبل عودة \fBexecve\fP(2). في هذا التوقف، يمكن للمتتبع استخدام \fBPTRACE_GETEVENTMSG\fP لاسترداد معرف الخيط السابق للمُتتبَّع. (قُدمت هذه الميزة في لينكس 3.0). ثانيًا، يعطل خيار \fBPTRACE_O_TRACEEXEC\fP توليد إشارة \fBSIGTRAP\fP التقليدية عند \fBexecve\fP(2). .P عندما يتلقى المتتبع إشعار توقف \fBPTRACE_EVENT_EXEC\fP، فمن المضمون أنه باستثناء هذا المُتتبَّع وقائد مجموعة الخيوط، لا توجد خيوط أخرى من العملية حية. .P عند تلقي إشعار توقف \fBPTRACE_EVENT_EXEC\fP، يجب على المتتبع تنظيف جميع هياكل بياناته الداخلية التي تصف خيوط هذه العملية، والاحتفاظ بهيكل بيانات واحد فقط \- ذلك الذي يصف المُتتبَّع الوحيد الذي لا يزال يعمل، مع .P .in +4n .EX معرف الخيط == معرف مجموعة الخيوط == معرف العملية. .EE .in .P مثال: استدعاء خيطين لـ \fBexecve\fP(2) في نفس الوقت: .P .nf *** حصلنا على توقف\-دخول\-استدعاء\-نظام في الخيط 1: ** PID1 execve("/bin/foo", "foo" *** أصدرنا PTRACE_SYSCALL للخيط 1 ** *** حصلنا على توقف\-دخول\-استدعاء\-نظام في الخيط 2: ** PID2 execve("/bin/bar", "bar" *** أصدرنا PTRACE_SYSCALL للخيط 2 ** *** حصلنا على PTRACE_EVENT_EXEC لـ PID0، أصدرنا PTRACE_SYSCALL ** *** حصلنا على توقف\-خروج\-استدعاء\-نظام لـ PID0: ** PID0 <...\& execve resumed> ) = 0 .fi .P إذا كان خيار \fBPTRACE_O_TRACEEXEC\fP \fIليس\fP ساري المفعول للمُتتبَّع المنفذ، وإذا كان المُتتبَّع قد أُرفق عبر \fBPTRACE_ATTACH\fP بدلاً من \fBPTRACE_SEIZE\fP، فإن النواة تسلم إشارة \fBSIGTRAP\fP إضافية للمُتتبَّع بعد عودة \fBexecve\fP(2). هذه إشارة عادية (مشابهة لتلك التي يمكن توليدها بواسطة \fIkill \-TRAP\fP)، وليست نوعًا خاصًا من توقف ptrace. استخدام \fBPTRACE_GETSIGINFO\fP لهذه الإشارة يعيد \fIsi_code\fP مضبوطًا على 0 (\fISI_USER\fP). قد يتم حجب هذه الإشارة بواسطة قناع الإشارة، وبالتالي قد يتم تسليمها لاحقًا (بكثير). .P عادة، لا يرغب المتتبع (على سبيل المثال، \fBstrace\fP(1)) في إظهار إشارة \fBSIGTRAP\fP الإضافية هذه لما بعد execve للمستخدم، وسيكبت تسليمها للمُتتبَّع (إذا كانت \fBSIGTRAP\fP مضبوطة على \fBSIG_DFL\fP، فهي إشارة قاتلة). ومع ذلك، فإن تحديد \fIأي\fP \fBSIGTRAP\fP يجب كبتها ليس بالأمر السهل. ضبط خيار \fBPTRACE_O_TRACEEXEC\fP أو استخدام \fBPTRACE_SEIZE\fP وبالتالي كبت هذه الـ \fBSIGTRAP\fP الإضافية هو النهج الموصى به. .SS "الأب الحقيقي" تسيء واجهة برمجة تطبيقات ptrace استخدام نظام إشارات الأب/الابن القياسي في يونكس عبر \fBwaitpid\fP(2). كان هذا يتسبب في توقف الأب الحقيقي للعملية عن تلقي عدة أنواع من إشعارات \fBwaitpid\fP(2) عندما يتم تتبع العملية الابنة بواسطة عملية أخرى. .P أُصلحت العديد من هذه الأخطاء، ولكن اعتبارًا من لينكس 2.6.38 لا يزال هناك عدة أخطاء قائمة؛ انظر قسم الأخطاء (BUGS) أدناه. .P اعتبارًا من لينكس 2.6.38، يُعتقد أن ما يلي يعمل بشكل صحيح: .IP \[bu] 3 يتم الإبلاغ عن الخروج/الموت بسبب إشارة أولاً للمتتبع، ثم عندما يستهلك المتتبع نتيجة \fBwaitpid\fP(2)، يُبلغ الأب الحقيقي (للأب الحقيقي فقط عندما تخرج العملية متعددة الخيوط بالكامل). إذا كان المتتبع والأب الحقيقي هما نفس العملية، فيُرسل التقرير مرة واحدة فقط. .SH "قيمة الإرجاع" عند النجاح، تعيد عمليات \fBPTRACE_PEEK*\fP البيانات المطلوبة (ولكن انظر الملاحظات)، وتعيد عملية \fBPTRACE_SECCOMP_GET_FILTER\fP عدد التعليمات في برنامج BPF، وتعيد عملية \fBPTRACE_GET_SYSCALL_INFO\fP عدد البايتات المتاحة لتتم كتابتها بواسطة النواة، والعمليات الأخرى تعيد صفرًا. .P عند حدوث خطأ، تعيد جميع العمليات \-1، ويُضبط \fIerrno\fP للإشارة إلى الخطأ. بما أن القيمة العائدة من عملية \fBPTRACE_PEEK*\fP ناجحة قد تكون \-1، فيجب على المستدعي مسح \fIerrno\fP قبل الاستدعاء، ثم التحقق منه بعد ذلك لتحديد ما إذا كان هناك خطأ قد وقع أم لا. .SH الأخطاء .TP \fBEBUSY\fP (في i386 فقط) حدث خطأ أثناء تخصيص أو تحرير سجل تنقيح. .TP \fBEFAULT\fP حدثت محاولة للقراءة من أو الكتابة في منطقة غير صالحة في ذاكرة المتتبِّع أو المتتبَّع، ربما لأن المنطقة لم تكن ممسوحة أو لا يمكن الوصول إليها. لسوء الحظ، في لينكس، ستُرجع التنوعات المختلفة لهذا الخطأ \fBEIO\fP أو \fBEFAULT\fP بشكل عشوائي تقريبًا. .TP \fBEINVAL\fP حدثت محاولة لضبط خيار غير صالح. .TP \fBEIO\fP \fIop\fP غير صالحة، أو حدثت محاولة للقراءة من أو الكتابة في منطقة غير صالحة في ذاكرة المتتبِّع أو المتتبَّع، أو حدث انتهاك لمحاذاة الكلمة، أو عُينت إشارة غير صالحة خلال عملية إعادة تشغيل. .TP \fBEPERM\fP لا يمكن تتبع العملية المحددة. قد يكون هذا بسبب امتلاك المتتبِّع امتيازات غير كافية (القدرة المطلوبة هي \fBCAP_SYS_PTRACE\fP)؛ لا تستطيع العمليات غير المميزة تتبع العمليات التي لا يمكنها إرسال إشارات إليها أو تلك التي تُشغل برامج set\-user\-ID/set\-group\-ID، لأسباب واضحة. بدلاً من ذلك، قد تكون العملية قيد التتبع بالفعل، أو (قبل لينكس 2.6.26) قد تكون \fBinit\fP(1) (PID 1). .TP \fBESRCH\fP العملية المحددة غير موجودة، أو لا يتبعها المستدعِي حاليًا، أو ليست متوقفة (للعمليات التي تتطلب أن يكون المتتبَّع متوقفًا). .SH المعايير لا يوجد. .SH التاريخ SVr4, 4.3BSD. .P .\" See commit 00cd5c37afd5f431ac186dd131705048c0a11fdb قبل لينكس 2.6.26، لم يكن بالإمكان تتبع \fBinit\fP(1)، العملية ذات المعرف PID 1. .SH ملاحظات على الرغم من أن المعاملات المُمررة إلى \fBptrace\fP() تُفسر وفقًا للنموذج المذكور، إلا أن glibc تعلن حاليًا عن \fBptrace\fP() كدالة متغيرة المعاملات مع تثبيت معامل \fIop\fP فقط. يُوصى دائمًا بتوفير أربعة معاملات، حتى لو كانت العملية المطلوبة لا تستخدمها، مع ضبط المعاملات غير المستخدمة/المتجاهلة إلى \fI0L\fP أو \fI(void\ *)\ 0\fP. .P يستمر والد المتتبَّع في كونه المتتبِّع حتى لو استدعى ذلك المتتبِّع \fBexecve\fP(2). .P .\" See http://lkml.org/lkml/2008/5/8/375 تخطيط محتويات الذاكرة ومنطقة USER يعتمد بشكل كبير على نظام التشغيل والمعمارية. الإزاحة المزودة، والبيانات المُرجعة، قد لا تتطابق تمامًا مع تعريف \fIstruct user\fP. .P حجم "الكلمة" يُحدد حسب نوع نظام التشغيل (على سبيل المثال، في لينكس 32\-بت يكون 32 بت). .P .\" .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" توثق هذه الصفحة الطريقة التي يعمل بها استدعاء \fBptrace\fP() حاليًا في لينكس. يختلف سلوكه بشكل كبير في نكهات يونكس الأخرى. في كل الأحوال، استخدام \fBptrace\fP() مخصص للغاية لنظام التشغيل والمعمارية. .SS "التحقق من وضع الوصول لـ Ptrace" تتطلب أجزاء مختلفة من واجهة برمجة تطبيقات فضاء المستخدم\-النواة (وليس فقط عمليات \fBptrace\fP()) ما يسمى بفحوصات "وضع الوصول لـ ptrace"، التي تحدد نتيجتها ما إذا كانت العملية مسموحًا بها (أو، في حالات قليلة، تجعل عملية "القراءة" تُرجع بيانات مطهرة). تُجرى هذه الفحوصات في الحالات التي يمكن فيها لعملية واحدة فحص معلومات حساسة عن عملية أخرى، أو في بعض الحالات تعديل حالتها. تعتمد الفحوصات على عوامل مثل أوراق الاعتماد والقدرات للعمليتين، وما إذا كانت العملية "الهدف" قابلة للتفريغ أم لا، ونتائج الفحوصات التي تُجريها أي وحدة أمن لينكس (LSM) مفعّلة —على سبيل المثال، SELinux أو Yama أو Smack— وبواسطة وحدة commoncap LSM (التي تُستدعى دائمًا). .P .\" commit 006ebb40d3d65338bd74abb03b945f8d60e362bd قبل لينكس 2.6.27، كانت جميع فحوصات الوصول من نوع واحد. منذ لينكس 2.6.27، صُنّف مستويان لوضع الوصول: .TP \fBPTRACE_MODE_READ\fP لعمليات "القراءة" أو العمليات الأخرى الأقل خطورة، مثل: \fBget_robust_list\fP(2)؛ و \fBkcmp\fP(2)؛ وقراءة \fI/proc/\fPpid\fI/auxv\fP، أو \fI/proc/\fPpid\fI/environ\fP، أو \fI/proc/\fPpid\fI/stat\fP؛ أو \fBreadlink\fP(2) لملف \fI/proc/\fPpid\fI/ns/*\fP. .TP \fBPTRACE_MODE_ATTACH\fP .\" .\" Regarding the above description of the distinction between .\" PTRACE_MODE_READ and PTRACE_MODE_ATTACH, Stephen Smalley notes: .\" .\" That was the intent when the distinction was introduced, but it doesn't .\" appear to have been properly maintained, e.g., there is now a common .\" helper lock_trace() that is used for .\" /proc/pid/{stack,syscall,personality} but checks PTRACE_MODE_ATTACH, and .\" PTRACE_MODE_ATTACH is also used in timerslack_ns_write/show(). Likely .\" should review and make them consistent. There was also some debate .\" about proper handling of /proc/pid/fd. Arguably that one might belong .\" back in the _ATTACH camp. .\" لعمليات "الكتابة"، أو العمليات الأخرى الأكثر خطورة، مثل: إرفاق ptrace (\fBPTRACE_ATTACH\fP) بعملية أخرى أو استدعاء \fBprocess_vm_writev\fP(2). (كان \fBPTRACE_MODE_ATTACH\fP فعليًا هو المبدئي قبل لينكس 2.6.27.) .P .\" commit caaee6234d05a58c5b4d05e7bf766131b810a657 منذ لينكس 4.5، تدمج فحوصات وضع الوصول المذكورة أعلاه (عبر معامل OR) مع أحد المعدلات التالية: .TP \fBPTRACE_MODE_FSCREDS\fP استخدام UID و GID لنظام ملفات المستدعِي (انظر \fBcredentials\fP(7)) أو القدرات الفعالة لفحوصات وحدة LSM. .TP \fBPTRACE_MODE_REALCREDS\fP استخدام UID و GID الحقيقيين للمستدعِي أو القدرات المسموح بها لفحوصات وحدة LSM. كان هذا فعليًا هو المبدئي قبل لينكس 4.5. .P نظرًا لأن دمج أحد معدلات أوراق الاعتماد مع أحد أوضاع الوصول المذكورة آنفًا هو أمر شائع، فقد عُرفت بعض الماكرو في مصادر النواة لهذه التوليفات: .TP \fBPTRACE_MODE_READ_FSCREDS\fP عُرف كـ \fBPTRACE_MODE_READ | PTRACE_MODE_FSCREDS\fP. .TP \fBPTRACE_MODE_READ_REALCREDS\fP عُرف كـ \fBPTRACE_MODE_READ | PTRACE_MODE_REALCREDS\fP. .TP \fBPTRACE_MODE_ATTACH_FSCREDS\fP عُرف كـ \fBPTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS\fP. .TP \fBPTRACE_MODE_ATTACH_REALCREDS\fP عُرف كـ \fBPTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS\fP. .P يمكن دمج معدل إضافي واحد (عبر OR) مع وضع الوصول: .TP \fBPTRACE_MODE_NOAUDIT\fP (منذ لينكس 3.3) .\" commit 69f594a38967f4540ce7a29b3fd214e68a8330bd .\" Just for /proc/pid/stat عدم تدقيق فحص وضع الوصول هذا. يُستخدم هذا المعدل لفحوصات وضع وصول ptrace (مثل الفحوصات عند قراءة \fI/proc/\fPpid\fI/stat\fP) التي تؤدي مجرد تصفية المخرجات أو تطهيرها، بدلاً من التسبب في إرجاع خطأ إلى المستدعِي. في هذه الحالات، لا يعد الوصول إلى الملف انتهاكًا أمنيًا ولا يوجد سبب لإنشاء سجل تدقيق أمني. يقمع هذا المعدل إنشاء سجل تدقيق كهذا لفحص وصول معين. .P لاحظ أن جميع ثوابت \fBPTRACE_MODE_*\fP الموصوفة في هذا القسم الفرعي هي ثوابت داخلية للنواة، وغير مرئية لفضاء المستخدم. ذُكرت أسماء الثوابت هنا من أجل تسمية الأنواع المختلفة لفحوصات وضع وصول ptrace التي تُجرى لاستدعاءات النظام المختلفة والوصول إلى الملفات الوهمية المختلفة (مثل الموجودة تحت \fI/proc\fP). تُستخدم هذه الأسماء في صفحات الدليل الأخرى لتوفير اختصار بسيط لتسمية فحوصات النواة المختلفة. .P الخوارزمية المستخدمة للتحقق من وضع وصول ptrace تحدد ما إذا كان مسموحًا للعملية المستدعية إجراء الإجراء المقابل على العملية الهدف. (في حالة فتح ملفات \fI/proc/\fPpid، فإن "العملية المستدعية" هي التي تفتح الملف، والعملية ذات المعرف PID المقابل هي "العملية الهدف".) الخوارزمية هي كما يلي: .IP (1) 5 إذا كان خيط الاستدعاء والخيط الهدف في نفس مجموعة الخيوط، فإن الوصول مسموح به دائمًا. .IP (2) إذا حدد وضع الوصول \fBPTRACE_MODE_FSCREDS\fP، فاستخدم للفحص في الخطوة التالية UID و GID لنظام ملفات المستدعِي. (كما لوحظ في \fBcredentials\fP(7)، فإن UID و GID لنظام الملفات لهما نفس القيم تقريبًا للمعرفات الفعالة المقابلة.) .IP خلاف ذلك، يحدد وضع الوصول \fBPTRACE_MODE_REALCREDS\fP، لذا استخدم UID و GID الحقيقيين للمستدعِي للفحوصات في الخطوة التالية. (معظم واجهات برمجة التطبيقات التي تفحص UID و GID للمستدعِي تستخدم المعرفات الفعالة. لأسباب تاريخية، يستخدم فحص \fBPTRACE_MODE_REALCREDS\fP المعرفات الحقيقية بدلاً من ذلك.) .IP (3) يُرفض الوصول إذا لم يتحقق \fIأي\fP مما يلي: .RS .IP \[bu] 3 معرفات المستخدم الحقيقية، والفعالة، والمحفوظة للهدف تطابق معرف مستخدم المستدعِي، \fIو\fP معرفات المجموعة الحقيقية، والفعالة، والمحفوظة للهدف تطابق معرف مجموعة المستدعِي. .IP \[bu] يمتلك المستدعِي قدرة \fBCAP_SYS_PTRACE\fP في فضاء مستخدم الهدف. .RE .IP (4) يُرفض الوصول إذا كانت سمة "قابلية التفريغ" للعملية الهدف لها قيمة غير 1 (\fBSUID_DUMP_USER\fP؛ انظر مناقشة \fBPR_SET_DUMPABLE\fP في \fBprctl\fP(2))، ولم يمتلك المستدعِي قدرة \fBCAP_SYS_PTRACE\fP في فضاء مستخدم العملية الهدف. .IP (5) .\" (in cap_ptrace_access_check()): تُستدعى واجهة LSM للنواة \fIsecurity_ptrace_access_check\fP() لمعرفة ما إذا كان وصول ptrace مسموحًا به. تعتمد النتائج على وحدات LSM. ينفذ تطبيق هذه الواجهة في commoncap LSM الخطوات التالية: .RS .IP (5.1) 7 إذا تضمن وضع الوصول \fBPTRACE_MODE_FSCREDS\fP، فاستخدم مجموعة القدرات \fIالفعالة\fP للمستدعِي في الفحص التالي؛ وإلا (يحدد وضع الوصول \fBPTRACE_MODE_REALCREDS\fP، لذا) استخدم مجموعة قدرات المستدعِي \fIالمسموح بها\fP. .IP (5.2) يُرفض الوصول إذا لم يتحقق \fIأي\fP مما يلي: .RS .IP \[bu] 3 المستدعِي والعملية الهدف في نفس فضاء المستخدم، وقدرات المستدعِي هي مجموعة شاملة لقدرات العملية الهدف \fIالمسموح بها\fP. .IP \[bu] يمتلك المستدعِي قدرة \fBCAP_SYS_PTRACE\fP في فضاء مستخدم العملية الهدف. .RE .IP لاحظ أن commoncap LSM لا تفرق بين \fBPTRACE_MODE_READ\fP و \fBPTRACE_MODE_ATTACH\fP. .RE .IP (6) .\" .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" إذا لم يُرفض الوصول بأي من الخطوات السابقة، فإن الوصول مسموح به. .SS /proc/sys/kernel/yama/ptrace_scope .\" commit 2d514487faf188938a4ee4fb3464eeecfbdcf8eb على الأنظمة التي ثبتت عليها وحدة Yama Linux Security Module (LSM) (أي أن النواة ضُبطت بـ \fBCONFIG_SECURITY_YAMA\fP)، يمكن استخدام ملف \fI/proc/sys/kernel/yama/ptrace_scope\fP (المتاح منذ لينكس 3.4) لتقييد القدرة على تتبع عملية باستخدام \fBptrace\fP() (وبالتالي القدرة على استخدام أدوات مثل \fBstrace\fP(1) و \fBgdb\fP(1)). الهدف من هذه القيود هو منع تصعيد الهجمات حيث يمكن لعملية مخترقة إرفاق ptrace لعمليات حساسة أخرى (مثل وكيل GPG أو جلسة SSH) يملكها المستخدم من أجل الحصول على أوراق اعتماد إضافية قد توجد في الذاكرة وبالتالي توسيع نطاق الهجوم. .P بشكل أدق، تحد وحدة Yama LSM من نوعين من العمليات: .IP \[bu] 3 أي عملية تجري فحصًا لوضع وصول ptrace من نوع \fBPTRACE_MODE_ATTACH\fP —على سبيل المثال، \fBptrace\fP() \fBPTRACE_ATTACH\fP. (انظر مناقشة "التحقق من وضع وصول Ptrace" أعلاه.) .IP \[bu] \fBptrace\fP() \fBPTRACE_TRACEME\fP. .P العملية التي تمتلك قدرة \fBCAP_SYS_PTRACE\fP يمكنها تحديث ملف \fI/proc/sys/kernel/yama/ptrace_scope\fP بإحدى القيم التالية: .TP 0 ("أذونات ptrace التقليدية") لا توجد قيود إضافية على العمليات التي تجري فحوصات \fBPTRACE_MODE_ATTACH\fP (بخلاف تلك التي تفرضها commoncap ووحدات LSM الأخرى). .IP استخدام \fBPTRACE_TRACEME\fP لم يتغير. .TP 1 ("ptrace مقيد") [القيمة المبدئية] عند إجراء عملية تتطلب فحص \fBPTRACE_MODE_ATTACH\fP، يجب أن تمتلك العملية المستدعية إما قدرة \fBCAP_SYS_PTRACE\fP في فضاء مستخدم العملية الهدف أو يجب أن تكون لها علاقة محددة مسبقًا بالعملية الهدف. بشكل مبدئي، العلاقة المحددة مسبقًا هي أن تكون العملية الهدف من نسل المستدعِي. .IP يمكن للعملية الهدف استخدام عملية \fBprctl\fP(2) \fBPR_SET_PTRACER\fP للتصريح عن معرف PID إضافي مسموح له بإجراء عمليات \fBPTRACE_MODE_ATTACH\fP على الهدف. انظر ملف مصدر النواة \fIDocumentation/admin\-guide/LSM/Yama.rst\fP لمزيد من التفاصيل. .IP استخدام \fBPTRACE_TRACEME\fP لم يتغير. .TP 2 ("إرفاق للمدير فقط") العمليات التي تمتلك قدرة \fBCAP_SYS_PTRACE\fP في فضاء مستخدم العملية الهدف فقط هي التي يمكنها إجراء عمليات \fBPTRACE_MODE_ATTACH\fP أو تتبع الأبناء الذين يستخدمون \fBPTRACE_TRACEME\fP. .TP 3 ("لا إرفاق") لا يمكن لأي عملية إجراء عمليات \fBPTRACE_MODE_ATTACH\fP أو تتبع الأبناء الذين يستخدمون \fBPTRACE_TRACEME\fP. .IP بمجرد كتابة هذه القيمة في الملف، لا يمكن تغييرها. .P .\" .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" فيما يتعلق بالقيمتين 1 و 2، لاحظ أن إنشاء فضاء مستخدم جديد يزيل فعليًا الحماية التي توفرها Yama. هذا لأن العملية في فضاء مستخدم الوالد التي يطابق معرف UID الفعال لها معرف UID لمنشئ فضاء الأبناء تمتلك جميع القدرات (بما في ذلك \fBCAP_SYS_PTRACE\fP) عند إجراء العمليات داخل فضاء مستخدم الأبناء (والنسل الأبعد لهذا الفضاء). بناءً على ذلك، عندما تحاول عملية ما استخدام فضاءات المستخدم لعزل نفسها، فإنها تضعف دون قصد الحماية التي توفرها وحدة Yama LSM. .SS "الاختلافات بين مكتبة C والنواة" على مستوى استدعاء النظام، تمتلك عمليات \fBPTRACE_PEEKTEXT\fP و \fBPTRACE_PEEKDATA\fP و \fBPTRACE_PEEKUSER\fP واجهة برمجة تطبيقات مختلفة: فهي تخزن النتيجة في العنوان الموضح بواسطة معامل \fIdata\fP، وتكون القيمة المُرجعة هي راية الخطأ. توفر دالة تغليف glibc واجهة برمجة التطبيقات المذكورة في قسم "الوصف" أعلاه، حيث تُرجع النتيجة عبر القيمة المُرجعة للدالة. .SH العلل على المضيفين الذين لديهم ترويسات نواة لينكس 2.6، يُصرح عن \fBPTRACE_SETOPTIONS\fP بقيمة مختلفة عن القيمة المستخدمة في لينكس 2.4. يؤدي هذا إلى فشل التطبيقات المجمعة بترويسات نواة لينكس 2.6 عند تشغيلها على لينكس 2.4. يمكن الالتفاف على هذا بإعادة تعريف \fBPTRACE_SETOPTIONS\fP إلى \fBPTRACE_OLDSETOPTIONS\fP، إذا كان ذلك معرفًا. .P تُرسل إشعارات توقف المجموعة إلى المتتبِّع، ولكن ليس إلى الوالد الحقيقي. آخر تأكيد كان في 2.6.38.6. .P .\" Note from Denys Vlasenko: .\" Here "exits" means any kind of death - _exit, exit_group, .\" signal death. Signal death and exit_group cases are trivial, .\" though: since signal death and exit_group kill all other threads .\" too, "until all other threads exit" thing happens rather soon .\" in these cases. Therefore, only _exit presents observably .\" puzzling behavior to ptrace users: thread leader _exit's, .\" but WIFEXITED isn't reported! We are trying to explain here .\" why it is so. .\" FIXME . need to test/verify this scenario إذا كان قائد مجموعة الخيوط متبوعًا وخرج باستدعاء \fB_exit\fP(2)، سيحدث توقف \fBPTRACE_EVENT_EXIT\fP له (إذا طُلب ذلك)، ولكن إشعار \fBWIFEXITED\fP اللاحق لن يُسلم حتى تخرج جميع الخيوط الأخرى. كما شُرح أعلاه، إذا استدعى أحد الخيوط الأخرى \fBexecve\fP(2)، فإن موت قائد مجموعة الخيوط لن يُبلغ عنه \fIأبدًا\fP. إذا لم يكن الخيط الذي نُفذ متبوعًا بواسطة هذا المتتبِّع، فلن يعرف المتتبِّع أبدًا أن \fBexecve\fP(2) قد حدث. أحد الحلول الممكنة هو إجراء \fBPTRACE_DETACH\fP لقائد مجموعة الخيوط بدلاً من إعادة تشغيله في هذه الحالة. آخر تأكيد كان في 2.6.38.6. .P قد تظل إشارة \fBSIGKILL\fP تسبب توقف \fBPTRACE_EVENT_EXIT\fP قبل الموت الفعلي بالإشارة. قد يتغير هذا في المستقبل؛ الغرض من \fBSIGKILL\fP هو قتل المهام دائمًا وفورًا حتى تحت ptrace. آخر تأكيد كان في لينكس 3.13. .P تُرجع بعض استدعاءات النظام \fBEINTR\fP إذا أُرسلت إشارة إلى المتتبَّع، ولكن قُمع تسليمها بواسطة المتتبِّع. (هذه عملية شائعة جدًا: يقوم بها المنقحون عادةً عند كل إرفاق، لكي لا يقدموا \fBSIGSTOP\fP زائفة). اعتبارًا من لينكس 3.2.9، تأثرت استدعاءات النظام التالية (هذه القائمة من المرجح أنها غير مكتملة): \fBepoll_wait\fP(2)، و \fBread\fP(2) من واصف ملف \fBinotify\fP(7). العرض المعتاد لهذه العلة هو أنه عندما ترفق عملية ساكنة بالأمر .P .in +4n .EX strace \-p .EE .in .P عندها، وبدلاً من المخرجات المعتادة والمتوقعة في سطر واحد مثل .P .in +4n .EX restart_syscall(<...\& استئناف الاستدعاء المقاطع ...>_ .EE .in .P أو .P .in +4n .EX select(6, [5], NULL, [5], NULL_ .EE .in .P ('‏_' تشير إلى موضع المؤشر)، تلاحظ أكثر من سطر واحد. على سبيل المثال: .P .in +4n .EX clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0 epoll_wait(4,_ .EE .in .P ما لا يظهر هنا هو أن العملية كانت محجوزة في \fBepoll_wait\fP(2) قبل أن يُربط \fBstrace\fP(1) بها. تسبب الربط في عودة \fBepoll_wait\fP(2) إلى مساحة المستخدم مع الخطأ \fBEINTR\fP. في هذه الحالة المعينة، استجاب البرنامج للخطأ \fBEINTR\fP بالتحقق من الوقت الحالي، ثم تنفيذ \fBepoll_wait\fP(2) مرة أخرى. (البرامج التي لا تتوقع أخطاء \fBEINTR\fP «الشاردة» هذه قد تتصرف بطريقة غير مقصودة عند ربط \fBstrace\fP(1) بها.) .P على عكس القواعد العادية، يمكن لغلاف glibc لتابع \fBptrace\fP() أن يضبط \fIerrno\fP على صفر. .SH "انظر أيضًا" \fBgdb\fP(1)، \fBltrace\fP(1)، \fBstrace\fP(1)، \fBclone\fP(2)، \fBexecve\fP(2)، \fBfork\fP(2)، \fBgettid\fP(2)، \fBprctl\fP(2)، \fBseccomp\fP(2)، \fBsigaction\fP(2)، \fBtgkill\fP(2)، \fBvfork\fP(2)، \fBwaitpid\fP(2)، \fBexec\fP(3)، \fBcapabilities\fP(7)، \fBsignal\fP(7) .PP .SH ترجمة تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي . .PP هذه الترجمة هي وثيقة مجانية؛ راجع .UR https://www.gnu.org/licenses/gpl-3.0.html رخصة جنو العامة الإصدار 3 .UE أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات. .PP إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: .MT kde-l10n-ar@kde.org .ME .