unshare(2)

الاسم
unshare - فصل أجزاء من سياق تنفيذ العملية

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

موجز
#define _GNU_SOURCE
#include <sched.h>

int unshare(int flags);

الوصف
تسمح unshare() لعملية (أو خيط) بفصل أجزاء من سياق تنفيذها المشترك حالياً مع عمليات (أو خيوط) أخرى. يُشارك جزء من سياق التنفيذ، مثل مساحة أسماء الوصل، ضمنياً عند إنشاء عملية جديدة باستخدام fork(2) أو vfork(2)، بينما قد تُشارك أجزاء أخرى، مثل الذاكرة الافتراضية، بطلب صريح عند إنشاء عملية أو خيط باستخدام clone(2).

الاستخدام الرئيسي لـ unshare() هو السماح لعملية بالتحكم في سياق تنفيذها المشترك دون إنشاء عملية جديدة.

وسيطة flags هي قناع بتات يحدد أي أجزاء من سياق التنفيذ يجب فصلها. تُحدد هذه الوسيطة بجمع (OR) صفر أو أكثر من الثوابت التالية:

CLONE_FILES
    يعكس تأثير علم clone(2) CLONE_FILES. يفصل جدول واصفات الملفات، بحيث لم تعد العملية المستدعية تشارك واصفات ملفاتها مع أي عملية أخرى.

CLONE_FS
    يعكس تأثير علم clone(2) CLONE_FS. يفصل سمات نظام الملفات، بحيث لم تعد العملية المستدعية تشارك دليلها الجذر (chroot(2))، أو دليلها الحالي (chdir(2))، أو سمات umask (umask(2)) مع أي عملية أخرى.

CLONE_NEWCGROUP (منذ لينكس 4.6)
    لهذا العلم نفس تأثير علم clone(2) CLONE_NEWCGROUP. يفصل مساحة أسماء cgroup. يتطلب استخدام CLONE_NEWCGROUP القدرة CAP_SYS_ADMIN.

CLONE_NEWIPC (منذ لينكس 2.6.19)
    لهذا العلم نفس تأثير علم clone(2) CLONE_NEWIPC. يفصل مساحة أسماء IPC، بحيث تحصل العملية المستدعية على نسخة خاصة من مساحة أسماء IPC لا تشاركها مع أي عملية أخرى. يستلزم تحديد هذا العلم آلياً CLONE_SYSVSEM أيضًا. يتطلب استخدام CLONE_NEWIPC القدرة CAP_SYS_ADMIN.

CLONE_NEWNET (منذ لينكس 2.6.24)
    لهذا العلم نفس تأثير علم clone(2) CLONE_NEWNET. يفصل مساحة أسماء الشبكة، بحيث تُنقل العملية المستدعية إلى مساحة أسماء شبكة جديدة لا تشاركها أي عملية موجودة سابقاً. يتطلب استخدام CLONE_NEWNET القدرة CAP_SYS_ADMIN.

CLONE_NEWNS
    لهذا العلم نفس تأثير علم clone(2) CLONE_NEWNS. يفصل مساحة أسماء الوصل، بحيث تحصل العملية المستدعية على نسخة خاصة من مساحة أسمائها لا تشاركها مع أي عملية أخرى. يستلزم تحديد هذا العلم آلياً CLONE_FS أيضًا. يتطلب استخدام CLONE_NEWNS القدرة CAP_SYS_ADMIN. لمزيد من المعلومات، انظر mount_namespaces(7).

CLONE_NEWPID (منذ لينكس 3.8)
    لهذا العلم نفس تأثير علم clone(2) CLONE_NEWPID. يفصل مساحة أسماء PID، بحيث تحصل العملية المستدعية على مساحة أسماء PID جديدة لأطفالها لا تشاركها أي عملية موجودة سابقاً. العملية المستدعية لا تُنقل إلى المساحة الجديدة. سيكون للطفل الأول الذي أنشأته العملية المستدعية معرف العملية 1 وسيتولى دور init(1) في المساحة الجديدة. يستلزم CLONE_NEWPID آلياً CLONE_THREAD أيضًا. يتطلب استخدام CLONE_NEWPID القدرة CAP_SYS_ADMIN. لمزيد من المعلومات، انظر pid_namespaces(7).

CLONE_NEWTIME (منذ Linux 5.6)
    يفصل مساحة أسماء الوقت، بحيث تحصل العملية المستدعية على مساحة أسماء وقت جديدة لأطفالها لا تشاركها أي عملية موجودة سابقاً. العملية المستدعية لا تُنقل إلى المساحة الجديدة. يتطلب استخدام CLONE_NEWTIME القدرة CAP_SYS_ADMIN. لمزيد من المعلومات، انظر time_namespaces(7).

CLONE_NEWUSER (منذ لينكس 3.8)
    لهذا العلم نفس تأثير علم clone(2) CLONE_NEWUSER. يفصل مساحة أسماء المستخدم، بحيث تُنقل العملية المستدعية إلى مساحة أسماء مستخدم جديدة لا تشاركها أي عملية موجودة سابقاً. كما هو الحال مع العملية الطفل التي أنشأتها clone(2) مع علم CLONE_NEWUSER، يحصل المستدعي على مجموعة كاملة من القدرات في المساحة الجديدة.

    يتطلب CLONE_NEWUSER ألا تكون العملية المستدعية مُخيطة؛ يستلزم تحديد CLONE_NEWUSER آلياً CLONE_THREAD. منذ Linux 3.9، يستلزم CLONE_NEWUSER أيضًا آلياً CLONE_FS. يتطلب CLONE_NEWUSER أن يكون معرف المستخدم ومعرف المجموعة للعملية المستدعية مُعيّنين إلى معرفات مستخدمين ومعرفات مجموعات في مساحة أسماء المستخدم للعملية المستدعية وقت الاستدعاء.

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

CLONE_NEWUTS (منذ لينكس 2.6.19)
    لهذا العلم نفس تأثير علم clone(2) CLONE_NEWUTS. يفصل مساحة أسماء UTS IPC، بحيث تحصل العملية المستدعية على نسخة خاصة من مساحة أسماء UTS لا تشاركها مع أي عملية أخرى. يتطلب استخدام CLONE_NEWUTS القدرة CAP_SYS_ADMIN.

CLONE_SYSVSEM (منذ Linux 2.6.26)
    يعكس هذا العلم تأثير علم clone(2) CLONE_SYSVSEM. يفصل قيم ضبط سيمافور System V (semadj)، بحيث تحصل العملية المستدعية على قائمة semadj جديدة فارغة لا تشاركها مع أي عملية أخرى. إذا كانت هذه آخر عملية لديها مرجع إلى قائمة semadj الحالية للعملية، فتُطبق التعديلات في تلك القائمة على السيمافورات المقابلة، كما هو موصوف في semop(2).

بالإضافة إلى ذلك، يمكن تحديد CLONE_THREAD و CLONE_SIGHAND و CLONE_VM في flags إذا كان المستدعي أحادي الخيط (أي لا يشارك مساحة عنوانه مع عملية أو خيط آخر). في هذه الحالة، ليس لهذه الأعلام أي تأثير. (لاحظ أيضًا أن تحديد CLONE_THREAD يستلزم آلياً CLONE_VM، وتحديد CLONE_VM يستلزم آلياً CLONE_SIGHAND.) إذا كانت العملية متعددة الخيوط، فإن استخدام هذه الأعلام يؤدي إلى خطأ.

إذا حُددت flags بصفر، فإن unshare() تكون عملية عدمية؛ لا تُجرى أي تغييرات على سياق تنفيذ العملية المستدعية.

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

الأخطاء

EINVAL
    حُدد بت غير صالح في flags.

EINVAL
    حُدد CLONE_THREAD أو CLONE_SIGHAND أو CLONE_VM في flags، والمستدعي متعدد الخيوط.

EINVAL
    حُدد CLONE_NEWIPC في flags، لكن النواة لم تُهيأ بخياري CONFIG_SYSVIPC و CONFIG_IPC_NS.

EINVAL
    حُدد CLONE_NEWNET في flags، لكن النواة لم تُهيأ بخيار CONFIG_NET_NS.

EINVAL
    حُدد CLONE_NEWPID في flags، لكن النواة لم تُهيأ بخيار CONFIG_PID_NS.

EINVAL
    تم تحديد CLONE_NEWUSER في flags، لكن النواة لم تُهيأ بخيار CONFIG_USER_NS.

EINVAL
    تم تحديد CLONE_NEWUTS في flags، لكن النواة لم تُهيأ بخيار CONFIG_UTS_NS.

EINVAL
    تم تحديد CLONE_NEWPID في flags، لكن العملية استدعت سابقًا unshare() مع علم CLONE_NEWPID.

ENOMEM
    لا يمكن تخصيص ذاكرة كافية لنسخ أجزاء من سياق المستدعي التي تحتاج إلى إلغاء المشاركة.

ENOSPC (منذ لينكس 3.7)
    تم تحديد CLONE_NEWPID في الأعلام، لكن الحد الأقصى لعمق تداخل مساحات أسماء PID كان سيتجاوز؛ انظر pid_namespaces(7).

ENOSPC (منذ لينكس 4.9؛ قبله EUSERS)
    تم تحديد CLONE_NEWUSER في flags، وكان الاستدعاء سيتسبب في تجاوز الحد الأقصى لعدد مساحات أسماء المستخدم المتداخلة. انظر user_namespaces(7).

    من لينكس 3.11 إلى لينكس 4.8، كان الخطأ الذي يُشخص في هذه الحالة هو EUSERS.

ENOSPC (منذ لينكس 4.9)
    أحد القيم في flags حدد إنشاء مساحة اسم مستخدم جديدة، لكن فعل ذلك كان سيتسبب في تجاوز الحد المحدد بواسطة الملف المقابل في /proc/sys/user. لمزيد من التفاصيل، انظر namespaces(7).

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

EPERM
    تم تحديد CLONE_NEWUSER في flags، لكن إما معرف المستخدم الفعال أو معرف المجموعة الفعال للمستدعي ليس له تعيين في مساحة الاسم الأصلية (انظر user_namespaces(7)).

EPERM (منذ لينكس 3.9)
    تم تحديد CLONE_NEWUSER في flags والمستدعي في بيئة chroot (أي، دليل الجذر للمستدعي لا يطابق دليل الجذر لمساحة اسم التثبيت التي يوجد فيها).

EUSERS (من لينكس 3.11 إلى لينكس 4.8)
    تم تحديد CLONE_NEWUSER في flags، وكان الحد الأقصى لعدد مساحات أسماء المستخدم المتداخلة سيتجاوز. انظر مناقشة خطأ ENOSPC أعلاه.

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

التاريخ
لينكس 2.6.16.

ملاحظات
ليست كل سمات العملية التي يمكن مشاركتها عند إنشاء عملية جديدة باستخدام clone(2) يمكن إلغاء مشاركتها باستخدام unshare(). على وجه الخصوص، اعتبارًا من النواة 3.8، لا تنفذ unshare() أعلامًا تعكس تأثيرات CLONE_SIGHAND أو CLONE_THREAD أو CLONE_VM. قد تُضاف هذه الوظيفة في المستقبل، إذا لزم الأمر.

يتطلب إنشاء جميع أنواع مساحات الأسماء، باستثناء مساحات أسماء المستخدم، القدرة CAP_SYS_ADMIN. ومع ذلك، نظرًا لأن إنشاء مساحة اسم مستخدم يمنح آليًا مجموعة كاملة من القدرات، فإن إنشاء كل من مساحة اسم مستخدم وأي نوع آخر من مساحات الأسماء في نفس استدعاء unshare() لا يتطلب القدرة CAP_SYS_ADMIN في مساحة الاسم الأصلية.

أمثلة
البرنامج أدناه يوفر تنفيذًا بسيطًا لأمر unshare(1)، الذي يلغي مشاركة مساحة اسم واحدة أو أكثر وينفذ الأمر المقدم في وسائط سطر الأوامر. إليك مثال على استخدام هذا البرنامج، تشغيل شل في مساحة اسم تثبيت جديدة، والتحقق من أن الشل الأصلية والشل الجديدة في مساحات اسم تثبيت منفصلة:

    $ readlink /proc/$$/ns/mnt;
    mnt:[4026531840]
    $ sudo ./unshare -m /bin/bash;
    # readlink /proc/$$/ns/mnt;
    mnt:[4026532325]

المخرجات المختلفة لأمرَي readlink(1) تظهر أن الشلّين في مساحتي اسم تثبيت مختلفتين.

  مصدر البرنامج
    /* unshare.c

       A simple implementation of the unshare(1) command: unshare
       namespaces and execute a command.
    */
    #define _GNU_SOURCE
    #include <err.h>
    #include <sched.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    static void
    usage(char *pname)
    {
        fprintf(stderr, "Usage: %s [options] program [arg...]\n", pname);
        fprintf(stderr, "Options can be:\n");
        fprintf(stderr, "    -C   unshare cgroup namespace\n");
        fprintf(stderr, "    -i   unshare IPC namespace\n");
        fprintf(stderr, "    -m   unshare mount namespace\n");
        fprintf(stderr, "    -n   unshare network namespace\n");
        fprintf(stderr, "    -p   unshare PID namespace\n");
        fprintf(stderr, "    -t   unshare time namespace\n");
        fprintf(stderr, "    -u   unshare UTS namespace\n");
        fprintf(stderr, "    -U   unshare user namespace\n");
        exit(EXIT_FAILURE);
    }

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

        flags = 0;

        while ((opt = getopt(argc, argv, "CimnptuU")) != -1) {
            switch (opt) {
            case 'C': flags |= CLONE_NEWCGROUP;     break;
            case 'i': flags |= CLONE_NEWIPC;        break;
            case 'm': flags |= CLONE_NEWNS;         break;
            case 'n': flags |= CLONE_NEWNET;        break;
            case 'p': flags |= CLONE_NEWPID;        break;
            case 't': flags |= CLONE_NEWTIME;       break;
            case 'u': flags |= CLONE_NEWUTS;        break;
            case 'U': flags |= CLONE_NEWUSER;       break;
            default:  usage(argv[0]);
            }
        }

        if (optind >= argc)
            usage(argv[0]);

        if (unshare(flags) == -1)
            err(EXIT_FAILURE, "unshare");

        execvp(argv[optind], &argv[optind]);
        err(EXIT_FAILURE, "execvp");
    }

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

Documentation/userspace-api/unshare.rst في شجرة مصدر نواة لينكس

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

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

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