setns(2)

الاسم
setns - إعادة ربط خيط مع نطاق

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#define _GNU_SOURCE             /* انظر feature_test_macros(7) */
#include <sched.h>

int setns(int fd, int nstype);

الوصف
استدعاء النظام setns() يسمح للخيط المستدعي بالانتقال إلى نطاقات مختلفة. الوسيط fd هو أحد التالي:

•   واصف ملف يشير إلى أحد الروابط السحرية في دليل /proc/pid/ns/ (أو ربط وصل لمثل هذا الرابط);

•   واصف ملف PID (انظر pidfd_open(2)).

يُفسر الوسيط nstype بشكل مختلف في كل حالة.

  fd يشير إلى رابط /proc/pid/ns/
إذا كان fd يشير إلى رابط /proc/pid/ns/، فإن setns() يعيد ربط الخيط المستدعي بالنطاق المرتبط بذلك الرابط، مع مراعاة أي قيود يفرضها الوسيط nstype. في هذا الاستخدام، كل استدعاء لـ setns() يغير عضوية نطاق واحدة فقط من عضوية المستدعي.

يحدد الوسيط nstype نوع النطاق الذي يمكن إعادة ربط الخيط المستدعي به. يمكن أن يأخذ هذا الوسيط قيمة واحدة من التالي:

0   السماح بالانضمام إلى أي نوع من النطاقات.

CLONE_NEWCGROUP (منذ لينكس 4.6)
    يجب أن يشير fd إلى نطاق cgroup.

CLONE_NEWIPC (منذ Linux 3.0)
    يجب أن يشير fd إلى نطاق IPC.

CLONE_NEWNET (منذ Linux 3.0)
    يجب أن يشير fd إلى نطاق شبكة.

CLONE_NEWNS (منذ Linux 3.8)
    يجب أن يشير fd إلى نطاق وصل.

CLONE_NEWPID (منذ لينكس 3.8)
    يجب أن يشير fd إلى نطاق PID سليل.

CLONE_NEWTIME (منذ Linux 5.8)
    يجب أن يشير fd إلى نطاق زمن.

CLONE_NEWUSER (منذ لينكس 3.8)
    يجب أن يشير fd إلى نطاق مستخدم.

CLONE_NEWUTS (منذ Linux 3.0)
    يجب أن يشير fd إلى نطاق UTS.

يكفي تحديد nstype كـ 0 إذا كان المستدعي يعرف (أو لا يهتم) بنوع النطاق الذي يشير إليه fd. تحديد قيمة غير صفرية لـ nstype مفيد إذا كان المستدعي لا يعرف نوع النطاق الذي يشير إليه fd ويريد التأكد من أن النطاق من نوع معين. (قد لا يعرف المستدعي نوع النطاق الذي يشير إليه fd إذا تم فتح واصف الملف بواسطة عملية أخرى و، على سبيل المثال، تم تمريره إلى المستدعي عبر مقبس نطاق UNIX.)

  fd هو واصف ملف PID
منذ Linux 5.8، يمكن أن يشير fd إلى واصف ملف PID تم الحصول عليه من pidfd_open(2) أو clone(2). في هذا الاستخدام، ينقل setns() الخيط المستدعي بشكل ذري إلى واحد أو أكثر من نفس النطاقات مثل الخيط المشار إليه بواسطة fd.

الوسيط nstype هو قناع بت يتم تحديده عن طريق الجمع بـ OR لـ واحد أو أكثر من ثوابت النطاق CLONE_NEW* المذكورة أعلاه. يتم نقل المستدعي إلى كل نطاق من نطاقات الخيط الهدف المحددة في nstype؛ تبقى عضويات المستدعي في النطاقات المتبقية دون تغيير.

على سبيل المثال، الكود التالي سينقل المستدعي إلى نفس نطاقات المستخدم والشبكة وUTS مثل PID 1234، لكنه سيترك عضويات المستدعي الأخرى في النطاقات دون تغيير:

    int fd = pidfd_open(1234, 0);
    setns(fd, CLONE_NEWUSER | CLONE_NEWNET | CLONE_NEWUTS);

  تفاصيل لأنواع مساحات الأسماء المحددة
لاحظ التفاصيل والقيود التالية عند إعادة الارتباط بأنواع مساحات أسماء محددة:

مساحات أسماء المستخدم
    يجب أن تمتلك عملية تعيد ربط نفسها بمساحة اسم مستخدم القدرة CAP_SYS_ADMIN في مساحة اسم المستخدم الهدف. (هذا يعني بالضرورة أنه من الممكن فقط الانضمام إلى مساحة اسم مستخدم سليلة.) عند الانضمام بنجاح إلى مساحة اسم مستخدم، تُمنح العملية جميع القدرات في تلك المساحة، بغض النظر عن معرفات المستخدم والمجموعة الخاصة بها.

    لا يجوز لعملية متعددة الخيوط تغيير مساحة اسم المستخدم باستخدام setns().

    لا يُسمح باستخدام setns() لإعادة الدخول إلى مساحة اسم المستخدم الحالية للمتصل. هذا يمنع المتصل الذي أسقط القدرات من استعادة تلك القدرات عبر استدعاء setns().

    لأسباب أمنية، لا يمكن لعملية الانضمام إلى مساحة اسم مستخدم جديدة إذا كانت تشارك سمات متعلقة بنظام الملفات (السمات التي يتحكم في مشاركتها علم clone(2) CLONE_FS) مع عملية أخرى.

    لمزيد من التفاصيل حول مساحات أسماء المستخدم، انظر user_namespaces(7).

فضاءات أسماء الوصل
    يتطلب تغيير مساحة اسم التثبيت أن يمتلك المتصل كلاً من القدرتين CAP_SYS_CHROOT و CAP_SYS_ADMIN في مساحة اسم المستخدم الخاصة به و CAP_SYS_ADMIN في مساحة اسم المستخدم التي تمتلك مساحة اسم التثبيت الهدف.

    لا يمكن لعملية الانضمام إلى مساحة اسم تثبيت جديدة إذا كانت تشارك سمات متعلقة بنظام الملفات (السمات التي يتحكم في مشاركتها علم clone(2) CLONE_FS) مع عملية أخرى.

    انظر user_namespaces(7) للحصول على تفاصيل حول تفاعل مساحات أسماء المستخدم ومساحات أسماء التثبيت.

مساحات أسماء PID
    من أجل إعادة ربط نفسها بمساحة اسم PID جديدة، يجب أن يمتلك المتصل القدرة CAP_SYS_ADMIN في كل من مساحة اسم المستخدم الخاصة به وفي مساحة اسم المستخدم التي تمتلك مساحة اسم PID الهدف.

    إعادة ربط مساحة اسم PID يختلف نوعًا ما عن أنواع مساحات الأسماء الأخرى. إعادة ربط خيط الاستدعاء بمساحة اسم PID يغير فقط مساحة اسم PID التي ستوضع فيها العمليات التابعة التي تم إنشاؤها لاحقًا للمتصل؛ لا يغير مساحة اسم PID للمتصل نفسه.

    يُسمح بإعادة الارتباط بمساحة اسم PID فقط إذا كانت مساحة اسم PID الهدف سليلة (تابعة، حفيدة، إلخ) لمساحة اسم PID الحالية للمتصل، أو مطابقة لها.

    لمزيد من التفاصيل حول مساحات أسماء PID، انظر pid_namespaces(7).

مساحات أسماء Cgroup
    من أجل إعادة ربط نفسها بمساحة اسم cgroup جديدة، يجب أن يمتلك المتصل القدرة CAP_SYS_ADMIN في كل من مساحة اسم المستخدم الخاصة به وفي مساحة اسم المستخدم التي تمتلك مساحة اسم cgroup الهدف.

    استخدام setns() لتغيير مساحة اسم cgroup للمتصل لا يغير عضويات cgroup الخاصة بالمتصل.

مساحات أسماء الوقت
    من أجل إعادة ربط نفسها بمساحة اسم وقت جديدة، يجب أن يمتلك المتصل القدرة CAP_SYS_ADMIN في كل من مساحة اسم المستخدم الخاصة به وفي مساحة اسم المستخدم التي تمتلك مساحة الاسم الهدف.

    لا يجوز لعملية متعددة الخيوط تغيير مساحة اسم الوقت باستخدام setns().

مساحات أسماء الشبكة و IPC و UTS
    من أجل إعادة ربط نفسها بمساحة اسم شبكة أو IPC أو وقت أو UTS جديدة، يجب أن يمتلك المتصل القدرة CAP_SYS_ADMIN في كل من مساحة اسم المستخدم الخاصة به وفي مساحة اسم المستخدم التي تمتلك مساحة الاسم الهدف.

قيمة الإرجاع
عند النجاح، تُرجع setns() 0. عند الفشل، تُرجع -1 ويُضبط errno للإشارة إلى الخطأ.

الأخطاء

EBADF
    fd ليس واصف ملف صالح.

EINVAL
    يشير fd إلى مساحة اسم لا يتطابق نوعها مع النوع المحدد في nstype.

EINVAL
    توجد مشكلة في إعادة ربط الخيط بمساحة الاسم المحددة.

EINVAL
    حاول المتصل الانضمام إلى مساحة اسم PID سلف (أصل، جد، وهكذا).

EINVAL
    حاول المتصل الانضمام إلى مساحة اسم المستخدم التي هو بالفعل عضو فيها.

EINVAL
    يشارك المتصل حالة نظام الملفات (CLONE_FS) (على وجه الخصوص، الدليل الجذر) مع عمليات أخرى وحاول الانضمام إلى مساحة اسم مستخدم جديدة.

EINVAL
    المستدعي متعدد الخيوط وحاول الانضمام إلى فضاء مستخدم جديد.

EINVAL
    fd هو واصف ملف PID و nstype غير صالح (مثلاً، قيمته 0).

ENOMEM
    لا يمكن تخصيص ذاكرة كافية لتغيير فضاء الأسماء المحدد.

EPERM
    لم تمتلك الخيط المستدعي الصلاحية المطلوبة لهذه العملية.

ESRCH
    fd هو واصف ملف PID ولكن العملية التي يشير إليها لم تعد موجودة (أي، أنها أنهيت وانتظر عليها).

المعايير
لينكس.

الإصدارات
لينكس 3.0، glibc 2.14.

ملاحظات
لمزيد من المعلومات حول الروابط السحرية /proc/pid/ns/، انظر namespaces(7).

لا يمكن تغيير جميع السمات التي يمكن مشاركتها عند إنشاء خيط جديد باستخدام clone(2) باستخدام setns().

أمثلة
البرنامج أدناه يأخذ وسيطين أو أكثر. تحدد الوسيطة الأولى مسار ملف فضاء أسماء في دليل /proc/pid/ns/ موجود. تحدد الوسائط المتبقية أمراً ووسائطه. يفتح البرنامج ملف فضاء الأسماء، وينضم إلى ذلك الفضاء باستخدام setns()، وينفذ الأمر المحدد داخل ذلك الفضاء.

توضح جلسة الصدفة التالية استخدام هذا البرنامج (المُجمّع كملف ثنائي باسم ns_exec) بالتزامن مع برنامج المثال CLONE_NEWUTS في صفحة الدليل clone(2) (المُجمّع كملف ثنائي باسم newuts).

نبدأ بتنفيذ البرنامج النموذجي الوارد في clone(2) في الخلفية. يقوم هذا البرنامج بإنشاء عملية فرعية في مساحة أسماء UTS منفصلة. تقوم العملية الفرعية بتغيير اسم المضيف في مساحة أسمائها، ثم تعرض كلتا العمليتين أسماء المضيفين في مساحات أسماء UTS الخاصة بهما، بحيث يمكننا ملاحظة اختلافهما.

    $ su;                   # Need privilege for namespace operations
    Password:
    # ./newuts bizarro &
    [1] 3549
    clone() returned 3550
    uts.nodename in child:  bizarro
    uts.nodename in parent: antero
    # uname -n;             # Verify hostname in the shell
    antero

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

    # ./ns_exec /proc/3550/ns/uts /bin/bash;
    # uname -n;             # Executed in shell started by ns_exec
    bizarro

  مصدر البرنامج
    #define _GNU_SOURCE
    #include <err.h>
    #include <fcntl.h>
    #include <sched.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    int
    main(int argc, char *argv[])
    {
        int fd;

        if (argc < 3) {
            fprintf(stderr, "%s /proc/PID/ns/FILE cmd args...\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        /* Get file descriptor for namespace; the file descriptor is opened
           with O_CLOEXEC so as to ensure that it is not inherited by the
           program that is later executed.  */

        fd = open(argv[1], O_RDONLY | O_CLOEXEC);
        if (fd == -1)
            err(EXIT_FAILURE, "open");

        if (setns(fd, 0) == -1)       /* Join that namespace */
            err(EXIT_FAILURE, "setns");

        execvp(argv[2], &argv[2]);    /* Execute a command in namespace */
        err(EXIT_FAILURE, "execvp");
    }

انظر أيضًا
nsenter(1), clone(2), fork(2), unshare(2), vfork(2), namespaces(7), unix(7)

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.