هر فایل در درون یک فایل سیستم یونیکس -- و این(فایل) هر چیزی را که میتواند در سیستم فایل یونیکس باشد، شامل میشود: فایلها، دایرکتوریها، لولههای بانام، سوکتها، دستگاههای بلوکی و کاراکتری، و پیوندهای نمادین -- دارای یک مالک، گروه، و مجموعهای از مجوزها میباشد.
در اصلیترین سطح، مجوزهای یک فایل به این طریق عمل میکنند:
griffon:~$ ls -l .bashrc -rw-r--r-- 1 greg greg 856 2004-09-06 15:26 .bashrc ^\_/\_/\_/ | | | | | | | +----- سه کاراکتر انتهایی مجوزهای تمام کاربران دیگر را نشان میدهد | | | | | +-------- سه کاراکتر بعدی مجوزهای گروه فایل را نشان میدهد | | | +----------- سه کاراکتر اول مجوزهای مالک فایل را نشان میدهد | +------------- خط تیره در ابتدا یعنی یک فایل معمولی است
این فایل .bashrc مالکی به نام "greg" وگروه "greg" دارد، اندازه آن 856 بایت است، آخرین ویرایش آن به تاریخ 2004-09-06 ساعت 15:26 بوده، و دارای یک پیوند(همان که ما در حال دیدنش هستیم) میباشد. یک فایل معمولی است(کاراکتر خط تیره- در ستون اول)، دارای مجوز "rw-"(خواندن و نوشتن اما اجرا خیر) برای مالک میباشد، دارای مجوز "r--" (خواندن، اما نوشتن و اجرا خیر) برای گروهش، و مجوز "r--"(فقط خواندنی) برای سایر کاربران سیستم است.
این دیدگاهی سطحی است. در حقیقت فایلها در مالکیت نامهایی مانند "greg" نیستند. آنها توسط شماره UID (شماره شناسایی کاربر) به تملک در میآیند، و ls(1) آن شماره شناساییهای کاربری(UID) را از طریق فراخوانهای کتابخانه استاندارد C از قبیل getpwuid(3) به نامهای قابل خواندن انسان، مانند "greg" ارتباط میدهد. در مثال نشان داده شده فوق، "greg" به طور محلی در فایل /etc/passwd تعریف میشود، و موقعی که فرمانls با گزینه -l اجرا میشود، فایل passwd را سطر به سطر میخواند تا سطری با UID مالک فایل در فیلد سوم را پیدا کند. همچنین، فایلها در حقیقت با نام به گروه تعلق نمیگیرند، آنها با شماره GID(شماره شناسایی گروه) به گروه تعلق میگیرند، و ls نام متناظر با آن را از بانک اطلاعات گروه سیستم که به طور نوعی /etc/group است، بیرون میکشد. نامهای کاربر و گروه همچنین میتواند از NIS، LDAP، یا سایر بانکهای اطلاعاتی اخذ گردد، اما این موضوع خارج از حوزه این مقاله میباشد. نکته آنست که در حقیقت همه چیز در باب اعداد است.
این هم همان فایل بدون تبدیل «عدد به نام»:
griffon:~$ ls -ln .bashrc -rw-r--r-- 1 1000 1000 856 2004-09-06 15:26 .bashrc
کاربر "greg" در واقع شماره 1000 است، و گروه "greg" نیز شماره 1000 است. گزینه -n تبدیل معمول اعداد به نامها را موقوف میکند.
به همین نحو،واقعاً محلی در سیستم فایل وجود ندارد که در آنجا رشته "rw-r--r--" برای این فایل ذخیره بشود. این درست روش قابل خواندن انسانی ls است برای نمایش اعدادی که مجوزهای فایل را ذخیره میکنند. حال بیایید نگاه نزدیکتری به این قسمت داشته باشیم.
هر کاراکتر در رشته "rw-r--r--" یا یک حرف است یا خط تیره. اگر ما مجوز اجرا را (با chmod +x .bashrc) اضافه میکردیم، آنوقت فایل این طور دیده میشد:
griffon:~$ chmod +x .bashrc; ls -l .bashrc -rwxr-xr-x 1 greg greg 856 2004-09-06 15:26 .bashrc*
کاراکتر * در انتها به علت این واقعیت است که در حقیقت ls یک مستعار یا تابع پوسته است که گزینه -F را به /bin/ls اضافه میکند(مترجم: در سیستم شما میتواند اینطور نباشد). میتوانید فعلاً از آن صرفنظر کنید.
موقعی که مجوز اجرا را اضافه میکنیم، رشته جدید "rwxr-xr-x" برای مجوزهای فایل نمایش داده میشود. به طوری که شاید حدس بزنید، این رشته یعنی ما دارای مجوز "rwx" (خواندن، نوشتن و اجرا)برای مالک فایل، "r-x" (خواندن و اجرا، اما نوشتن خیر) برای اعضای گروه فایل، و "r-x" (خواند و اجرا) برای سایر کاربران میباشیم. بعضی از خط تیرهها با حروف جایگزین شدهاند. سایر خط تیرهها به طور غیر فعال، برای نشان دادن آنکه مجوزهای متناظرشان(مجوز نوشتن گروه و سایرین) برای این فایل فعال نگردیدهاند، باقی میمانند.
در واقع، رشته مجوز که ls در خروجی مینویسد، همیشه حداقل برای وضعیتهای معمولی دارای همان نشانهها در همان موقعیتها میباشد. (موارد استثنا را بعداً خواهیم دید.) .در حقیقت ضرورتی برای قرار دادن یک r به جای یک w وجود ندارد. به سادگی به واسطه محل حرف میتوانستیم بگوییم که کدام مجوز فعال است. استفاده از یک "r" به جای یک "x" در ستون اول واقعاً سهولتی برای آسانتر خواندن فراهم میکند.
بیایید به جای نوشتن یک حرف، یک "1" بنویسیم. اجازه بدهید به جای نوشتن خط تیره یک "0" بگذاریم. اکنون رشته مجوز "rwxr-xr-x" اینطور خواهد شد:
rwxr-xr-x 111101101
این یک نمایش باینری(مبنای 2) یک عدد است، و در واقع این عدد است که برای نگهداری مجوزهای این فایل در سیستم فایل ذخیره میشود. ls این عدد را از فایلسیستم به دست میآورد(با استفاده از فراخوان سیستمی stat(2)) و سپس آنرا به رشتهای که شما در نمایشگر میبینید تبدیل میکند.
متأسفانه برای ما انسانها، کار کردن با اعداد باینری خیلی خوشآیند نیست. آنها واقعاً طویل هستند و موقعی که تعداد زیادی از آنها همراه یکدیگر در یکجا قرار دارند، شمارش آنها به آسانی اشتباه میشود، به طوری که ممکن است به طور اتفاقی اشتباه بشوند. میتوانستید از کاما در میان آنها استفاده کنید،مشابه وقتی که عدد "1,000,000" را برای نمایش یک میلیون مینویسیم(مطابق عرفUSA)، اما حقیقتاً روش مناسبتری برای مدیریت اعداد باینری موجود است. ما آنها را به اکتال(مبنای 8) یا هگزادسیمال(مبنای 16) تبدیل میکنیم.
موقعی که یک عدد دودویی را به هگزادسیمال تبدیل میکنید، در حقیقت کاری که انجام میدهید، گروهبندی چهار بیت(bit) در یک مرحله و تعویض هر گروه چهار رقمی دودویی با یک رقم «هگزا» است، که یک عدد از 0-9 یا یک حرف از A-F میباشد. این کار برای برخی مقاصد بسیار خوب است، اما برای این وظیفه،نتیجه شده که اکتال بیشتر مناسب میباشد.
وقتی یک عدد دودویی را به اکتال تبدیل میکنید، در یک مرحله سه بیت را گروهبندی مینمایید. هر گروه از سه بیت با یک رقم اکتال از 0 تا 7 تعویض میگردد. این رقم به طور مطلق برای رشته مجوزهای ما ارجح است، زیرا آنها به طور طبیعی از قبل در سه گروه سهرقمی گروهبندی میشوند. بنابراین بیایید دوباره به رشته مجوز نگاه کنیم، اما این دفعه آنها را به اکتال تبدیل خواهیم نمود:
rwxr-xr-x 111101101 \_/\_/\_/ | | | | | | | +--+------است 5 یا 4 + 0 + 1 (دو دویی) 101 | | | +------------است 7 یا 4 + 2 + 1 (دو دویی) 111
بنابراین "rwxr-xr-x" معادل عدد اکتال "755" میباشد. علاوه براین، هر رقم در این عدد اکتال دقیقاً با یک گروه از مجوزها همخوانی دارد -- مالک، گروه، و دیگران. اگر ما فرمان chmod 740 filename را دیده بودیم، اکنون بلادرنگ، حتی بدون نگاه کردن به دو رقم دیگر میدانستیم که مجوزهای مالک فایل "rwx" (7) میشود.
یک لحظه تأمل نیز به شما اجازه میدهد تعیین کنید سایر بیتهای مجوز به چه موردی تنظیم خواهند شد. یک "r" همیشه با یک 4 مطابقت دارد، "w" همیشه 2 است، و "x" همیشه 1 است. شما به سادگی میتوانید آنها را برای بدست آوردن عدد اکتال جمع کنید، یا میتوانید عدد اکتال را برای به دست آوردن حروف، در ذهن خود به نماینده دو دویی آن تجزیه کنید. پس از اینکه چند بار این کار را انجام بدهید، تقریباً خودکار خواهد شد.
این هم جدولی برای کمک به شما جهت استخراج اعداد:
rwx 7 (4 + 2 + 1) rw- 6 (4 + 2) r-x 5 (4 + 1) r-- 4 -wx 3 (2 + 1) -w- 2 --x 1 --- 0
با استفاده از این جدول، میتوانیم ببینیم که chmod 740 به معنی آن است که مجوزهای حاصل rwx، سپس ،r--، بعد ---، یا rwxr----- خواهند شد، یعنی مجوزهای کامل برای مالک، فقط خواندن برای گروه، و برای سایر کاربران هیچ.
اکنون بیایید نگاهی به umask داشته باشیم. در واقع umask عددی است که به کرنل میگوید موقع ایجاد یک فایل جدید، شما میخواهید کدام بیتهای مجوز فعال نگردد. هر پردازش دارای یک عدد umask است که بخشی از محیط آن میباشد. این عدد از والد به فرزند به ارث میرسد، بنابراین یکبار که شما umask خود را در پوستهای تنظیم کنید، هر برنامهای که از آن پوسته اجرا نمایید آنرا به ارث میبرد، و بر آن برنامه تأثیر میکند.
یک umask نوعی میتواند 022 باشد، که ما آن را به صورت ----w--w- معنی میکنیم، یا «نوشتن گروه و نوشتن سایرین». اگر ما umask خود را به 022 تنظیم کنیم، یعنی به کرنل میگوییم که هر وقت ما فایل جدیدی ایجاد میکنیم، ما نمیخواهیم به طور پیشفرض برای گروه یا همگان قابل نوشتن باشد. در اینجا مثالی با استفاده از فرمان خارجی touch(1) آوردهایم. به خاطر داشته باشید که touch از umask پوسته، هر نوبت که ایجاد میشود ارث میبرد.
griffon:~$ umask 022; touch testfile griffon:~$ ls -l testfile -rw-r--r-- 1 greg greg 0 2005-03-11 09:54 testfile
وقتی touch فایلی را ایجاد میکند(چون در مثال ما testfile هنوز وجود نداشت)، به کرنل میگوید با کاربرد مجوز اکتال 666 (یا rw-rw-rw-) فایل را open(2) نماید. اما کرنل بیتهایی را که در umask معین شدهاند، حذف میکند، بنابراین نتیجه آنست که بالا دیدیم. این هم یک نگاه نزدیکتر به آن:
griffon:~$ rm testfile griffon:~$ strace -eopen touch testfile open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 open("/lib/libc.so.6", O_RDONLY) = 3 open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3 open("testfile", O_WRONLY|O_NONBLOCK|O_CREAT|O_NOCTTY|O_LARGEFILE, 0666) = 3
چند سطر اول را چشمپوشی کنید، زیرا فقط مربوط به کتابخانهها هستند. ما به سطر آخر توجه میکنیم، که در آن "testfile" با مجوز 0666 باز میشود. (اعداد اکتال در زبان C برای متمایز نمودن آنها از اعداد معمولی مبنای10 با یک 0 مقدم نوشته میشوند). فرمان touch مجوز 0666 را درخواست میکند، اما کرنل 0022 را که ما در umask تعیین کردهایم از آن حذف نموده، و نتیجه به جای 0666 برابر 0644 (rw-r--r--) گردیده است.
(به اشتباه فکر نکنید که کرنل این کار را با تفریق 022 از 666 انجام میدهد. عملیات واقعی با منطق بیتی انجام میگردد. بهتر است اینطور در نظر بگیرید که تمام بیتهای umask، اگر در عدد اصلی وجود داشته باشند، «قلم خورده» میشوند.)
اکنون بیایید فرض کنیم کاربر بدگمانی داریم که میخواهد هرگز هیچ شخص دیگری فایلهایش را نخواند. او umask خود را به 077 تنظیم کرده است. در آن حالت این چیزی است که ما میبینیم:
griffon:~$ rm testfile griffon:~$ umask 077; strace -eopen touch testfile 2>&1 | tail -1; ls -l testfile open("testfile", O_WRONLY|O_NONBLOCK|O_CREAT|O_NOCTTY|O_LARGEFILE, 0666) = 3 -rw------- 1 greg greg 0 2005-03-11 10:01 testfile
مانند قبل، touch نگران مقدار umask نیست. دقیقاً open(2) را با مجوزهای مطلوب 0666 فرا میخواند، و کرنل umask را اِعمال میکند. در این حالت umask ما برابر 0077 یا ---rwxrwx است، بنابراین آنها مجوزهایی هستند که ما خط میزنیم. تمام آنچه باقی میماند rw- برای مالک فایل است، مجوزهای گروه و سایرین همگی حذف شدهاند، و ما rw------- (0600) را داریم.
همین روشهای اجرایی برای دایرکتوریها به کار میرود. تنها تفاوت آن است که دایرکتوریها به طور پیشفرض با مجوزهای اجرا(0777 به جای 0666) ایجاد میشوند. بیایید نگاهی به این مورد داشته باشیم:
griffon:~$ umask 022; strace -emkdir mkdir testdir; ls -ld testdir mkdir("testdir", 0777) = 0 drwxr-xr-x 2 greg greg 512 2005-03-11 10:05 testdir/
در این مثال چند مورد جدید وجود دارد، بنابراین اجازه دهید به هر یک از آنها بپردازیم. اول آنست که ما از فرمان mkdir(1) استفاده کردیم که سپس فراخوان سیستم mkdir(2) را برای کرنل به کار میبرد. چنانکه گفتیم strace(1) برای نشان دادن آن فراخوان سیستم به ما میباشد. بعد، میبینیم که mkdir (فرمان) به کرنل گفت این دایرکتوری را بامجوز 0777 ( که rwxrwxrwx خواهد شد)، mkdir(فراخوان سیستم) نماید. اما کرنل بیتهای umask را حدف نمود، به طوری که به rwxr-xr-x (0755) منجر گردید. سرانجام، ما از گزینه -d برای آن استفاده کردیم که به ls بگوییم خود دایرکتوری را به ما نشان بدهد نه محتویات آن را، آنطور که وقتی به طور معمول به ls میگویید یک دایرکتوری را لیست کند، انجام میدهد. ستون اول خروجی به جای خط تیره یک d است، به علت آنکه این یک دایرکتوری است و نه یک فایل معمولی. کاراکتر
اینجا همان مثال است با یک umask متفاوت:
griffon:~$ rmdir testdir griffon:~$ umask 027; mkdir testdir; ls -ld testdir drwxr-x--- 2 greg greg 512 2005-03-11 10:09 testdir/
این اولین بار است که دیدهایم مجوزهای گروه با مجوزهای سایر کاربران تفاوت دارد. یک umask برابر 027 به معنی آنست که «ما میخواهیم گروه ما مجوز نوشتن نداشته باشد، اما بتواند بخواند و اجرا کند، هر کاربر دیگر هیچ مجوزی نداشته باشد». و آنچه واقعاً در انتها میبینیم این است: rwxr-x---، یا 0750.
اما مطلب دیگری هست که لازم است شما در باره دایرکتوریها بدانید،که مطلبی آشکار یا مشهود نیست. بیتهای مجوز در دایرکتوریها، به طور دقیق به همان معنی که در فایلهای معمولی هستند، نمیباشند.
مجوز خواندن در دایرکتوریها به ما اجازه لیست گرفتن از فایلهای داخل دایرکتوری را میدهد، نه چیزی غیر از این. به هر حال، به طور شگفتآوری، دبیان کاملاً همان نتایج برخی سیستمهای دیگر را نمیدهد. بیایید مثالی از این مورد را تنظیم کنیم(ولو اینکه در واقع غیر محتمل است هرگز در زندگی واقعی با چنین موردی روبرو شویم):
pegasus:~$ uname -a OpenBSD pegasus 3.6 PEGASUS#1 i386 pegasus:~$ mkdir testdir; echo s3kr3tdata > testdir/secret; chmod 400 testdir pegasus:~$ ls -ld testdir dr-------- 2 greg greg 512 Mar 11 10:19 testdir/ pegasus:~$ ls testdir pegasus:~$ echo testdir/* testdir/secret pegasus:~$ ls -l testdir/* ls: testdir/secret: Permission denied pegasus:~$ cat testdir/secret cat: testdir/secret: Permission denied
این است چگونگی رفتار یک یونیکس سنتی با خواندن، اما نه اجرای دایرکتوریها. پوسته میتواند فایل داخل دایرکتوری را «ببیند»، زیرا قادر است نام فایل را با خواندن دایرکتوری به طریق واقعی، به دست آورد. (یک دایرکتوری دقیقاً لیستی از نام فایلها و شمارههای زیرنویس 1 inode آنها میباشد). اما نمیتواند کاری روی فایلهای آن دایرکتوری انجام بدهد -- نمیتواند آنها را باز کند، و نمیتواند اطلاعات آنها را نمایش بدهد. بنابراین ls -l شکست میخورد(نمیتواند اطلاعات آنرا نمایش دهد)، و cat موفق نمیشود(نمیتواند باز کند).
این هم همان تنظیم، روی یک سیستم دبیان است. من باید برای این مثال به دایرکتوری /tmp تغییر مکان بدهم، زیرا نتایجی که در دایرکتوری خانگی خود به دست آوردم غیر عادی بود(به علت اینکه دایرکتوری خانگی من به NFS متصل --mount-- میشود، نه یک فایل سیستم محلی).
griffon:/tmp$ uname -a Linux griffon 2.4.28 #1 Thu Jan 6 08:29:18 EST 2005 i686 GNU/Linux griffon:/tmp$ mkdir testdir; echo s3kr3tdata > testdir/secret; chmod 400 testdir griffon:/tmp$ ls testdir ls: testdir/secret: Permission denied griffon:/tmp$ echo testdir/* testdir/secret griffon:/tmp$ ls -l testdir ls: testdir/secret: Permission denied total 0
اساساً همان نتایج را میبینیم، غیر از آنکه ls قدری تفصیلیتر است. ما یک پیغام خطای اضافی در نمونه اول به دست آوردهایم، و یک total 0 اضافی در دومی. اما همان رفتار اصولی رخ میدهد: میتوانیم نام فایلها در دایرکتوری فقط خواندنی را ببینیم، اما نمیتوانیم آن را باز کنیم یا اطلاعات آن را نمایش بدهیم.
مجوز نوشتن یک دایرکتوری به شما اجازه میدهد در آن دایرکتوری فایلها را ایجاد کنید، تغییر نام داده یا حذف نمایید(با یک استثنا، بعداً نشان داده میشود).
به من اجازه بدهید برای کسانی که خیلی به سرعت میخوانند یک بار بیشتر بگویم. مجوز نوشتن یک دایرکتوری به شما اجازه میدهد فایلها را از دایرکتوری حذف کنید. با یک استثنا که من بعداً نشان خواهم داد. من چیزی در مورد مالکیت یا حتی مجوز خود فایل نگفتم. آنها مطرح نیستند.
این هم یک مثال:
griffon:~$ mkdir testdir; sudo touch testdir/foo; ls -la testdir total 20 drwxr-xr-x 2 greg greg 512 2005-03-11 10:29 ./ drwxr-xr-x 150 greg greg 19456 2005-03-11 10:29 ../ -rw-r--r-- 1 root greg 0 2005-03-11 10:29 foo griffon:~$ rm testdir/foo rm: remove write-protected regular empty file `testdir/foo'? y griffon:~$ ls -la testdir total 20 drwxr-xr-x 2 greg greg 512 2005-03-11 10:29 ./ drwxr-xr-x 150 greg greg 19456 2005-03-11 10:29 ../
آن فایل در مالکیت Root است، اما کاربر greg قادر به حذف آن بود. چرا؟ به دلیل آنکه greg در آن دایرکتوری که بود، دارای مجوز نوشتن در آن بود. این حقیقت که فایل در مالکیت root بود، فقط باعث آن گردید که rm(1) برای تایید از ما سؤال کند، اما ما را از انجام آن باز نمیدارد. اگر میخواستیم از مرحله تأیید عبور کنیم، میتوانستیم گزینه -f (force) را به فرمان rm عبور بدهیم، و فایل بدون سر و صدا حذف میگردید.
آخرین اما نه کمترین، مجوز اجرای یک دایرکتوری به شما اجازه میدهد به آن دایرکتوری chdir(2) (تعویض دایرکتوری) نمایید، و همچنین اجازه میدهد فایلهای آنجا را باز کنیم یا اطلاعات آنها را نمایش دهیم. باز کردن یک فایل به مجوزهای مقتضی خود فایل نیز احتیاج دارد. در عمل، تقریبا هرگز شما دایرکتوری که مجوز خواندن برای برخی کاربران را داشته باشد، اما بیت متناسب اجرا را نداشته باشد، نخواهید دید. برای مقاصد عملی، همواره باید اطمینان حاصل کنید دایرکتوری که دارای "r" هست، دارای "x" نیز باشد -- در غیر اینصورت، به طوری که قبلاً دیدیم، "r" تنها خیلی خوب برای ما کار نمیکند.
آیا هرگز جایی هست که شما بخواهید یک دایرکتوری "x" داشته باشد اما "r" نداشته باشد؟ بلی. این مورد موقعی سودمند واقع میشود که شما میخواهید به اشخاص اجازه بدهید در صورتیکه نام فایلهایی در دایرکتوری را میدانند به آنها برسند، اما قادر به پی بردن به نام فایلها نباشند. همچنین، اگر شما یک محل ناشناس ارسال فایل(upload) را تنظیم نمودهاید، و نمیخواهید اشخاص قادر به دیدن فایلهایی باشند که دیگران به آنجا ارسال نمودهاند، تا فرصت از فیلتر عبور دادن فایلهای نامطلوب را داشته باشید، میتواند سودمند باشد.
اما رایجترین موردی که شما یک "x" روی دایرکتوری بدون داشتن "r" میبینید، وقتی است که کاربری دارای یک پایگاه اینترنتی تنظیم شده روی دایرکتوری ~/public_html خود میباشد، اما نمیخواهد دایرکتوری خانگیاش به طور کامل برای جهان قابل رؤیت باشد. برای آپاچی(Apache) جهت به دست آوردن فایلها در public_html، دایرکتوری خانگیاش باید "x" (قابل اجرا) برای تمام کاربران باشد، و همچنان برای خود public_html . بنابراین شاید او تنظیمی به این صورت داشته باشد:
drwxr-x--x 150 jane jane 19456 2005-03-11 10:29 /home/jane drwxr-x--x 14 jane jane 5632 2005-02-11 08:48 /home/jane/public_html -rw-r--r-- 1 jane jane 1226 2004-11-04 10:05 /home/jane/public_html/index.html
اکنون سایر کاربران سیستم( خارج از گروه "jane" ) نمیتوانند ببینند jane چه فایلهایی در دایرکتوری خانگی خود دارد، و آنها نمیتوانند آنچه او در دایرکتوری public_html خود دارد را ببینند، اما آپاچی میتواند فایل index.html را باز کند. (آپاچی به مجوز "x" برای تمام دایرکتوریهای منجر به فایل index.html، نیاز دارد و به مجوز "r" برای خود فایل به منظور باز کردن و خواندن آن احتیاج دارد.)
این به طور واقعی فایلهای jane را از چشمان کنجکاو، اگر که آنها اتفاقاً نام فایل را بدانند، محافظت نمیکند. به عنوان مثال، شاید john بخواهد ببیند jane چه مستعارهایی استفاده میکند، بنابراین شاید از cat ~jane/.bashrc استفاده کند و امیدوار باشد که او یک فایل .bashrc داشته باشد که او میتواند از آن متوجه شود. اگر jane یک فایل .bashrc دارد، و آن برای همگان قابل خواندن است، آنوقت john ، حتی اگر نتواند یک فرمان ls -l روی آن اجرا کند، قادر به خواندن آن خواهد بود. اگر jane میخواهد در حالیکه بازهم دایرکتوری public_html را برای استفاده آپاچی حفظ میکند، محتویات فایلهایش به خوبی نامها مخفی باشد، آنوقت او مجوزهای دیگران برای خود فایلها را باید حذف کند. این به معنای آن است که احتمالاً میخواهد از umask برابر 027 استفاده کند. تنها موضوع باقیمانده برای jane آن است که هر وقت فایل جدیدی به دایرکتوری public_html اضافه میکند، باید آن را برای آپاچی قابل خواندن همگانی کند. متأسفانه راهی برای jane وجود ندارد که یک umask برابر 022 برای ~/public_html و یک umask معادل 027 برای تمام دایرکتوریهای دیگر تنظیم کند. umaskها «یک بر پردازش» هستند نه «یک بر دایرکتوری».
سرانجام، سه بیت مجوز اضافه وجود دارد که هنوز بررسی نکردهایم، و هر کدام از آنها یک هدف خاص دارد (حتی گاهی اوقات بیش از یک هدف).ما به ترتیب به آنها میپردازیم.
اولین مورد از این بیتهای ویژه "sticky bit" نامیده میشود، که یک نام تاریخی است و چیزی در مورد آنچه واقعاً این بیت انجام میدهد به شما نمیگوید. تقریباً تنها زمانی که آن را روی یک سیستم دبیان خواهید دید موقعی است که مجوزهای دایرکتوری /tmp را مشاهده میکنید:
griffon:~$ ls -ld /tmp drwxrwxrwt 14 root root 4096 2005-03-11 10:06 /tmp/
حرف "t" در انتهای رشته مجوز(به جای "x" که انتظار داشتیم ببینیم) به معنای آن است که بیت sticky این دایرکتوری روشن شده. وقتی یک دایرکتوری بیت sticky روشن شده دارد، هیچکس نمیتواند فایلهای شخص دیگری را از آن دایرکتوری حذف کند یا تغییر نام بدهد، ولو اینکه مجوز نوشتن در آن دایرکتوری را داشته باشد. به خاطر میاورید که greg فایلی در مالکیت root را حذف نمود؟ او همان کار را نمیتواند در دایرکتوری /tmp انجام بدهد:
griffon:/tmp$ sudo touch foo; ls -ld . foo drwxrwxrwt 14 root root 4096 2005-03-11 10:46 ./ -rw-r--r-- 1 root root 0 2005-03-11 10:46 foo griffon:/tmp$ rm -f foo rm: cannot remove `foo': Operation not permitted
با وجود داشتن مجوز نوشتن در /tmp (و بنابراین توانایی ایجاد فایلها در آنجا)، greg نمیتواند فایل root را حذف کند، این به علت روشن بودن بیت sticky در /tmp است. این مطلب اهمیت دارد، زیرا ما نمیخواهیم کاربران قادر به حذف فایلهای موقتی سایر اشخاص باشند و برنامههای آنها را که به استفاده از آن فایلها نیاز دارند، سر در گم نمایند.
منشاء مفهوم "sticky bit" به روزهای اولیه یونیکس باز میگردد، زمانی که مطالبه سطح بالای الگوریتمهای صفحهبندی برای مدیریت حافظه نداشتیم. یک پردازش یا میتوانست در حافظه باشد، یا در حافظه نباشد. اگر کرنل به حافظه اضافی برای پردازش جدیدی نیاز داشت، به جای صفحات انتخابی از پردازش ، میبایست پردازش کامل را برای ایجاد فضا، با دیسک مبادله کند(swap). همچنین موقعی که اجرای برنامههامتوقف میشد، تصویر کامل برنامه در حافظه از بین میرفت( نه فقط قطعه دادههای آن). بنابراین در آن سیستمهای قدیمی، بیت "sticky" روی یک فایل برنامه(نه دایرکتوری) به معنای آن بود که کد برنامه پس از اتمام اجرای آن میباید در حافظه رها میشد، زیرا محتمل بود به زودی دوباره درخواست بشود. مثال کلاسیک یک برنامه sticky فایل /bin/ls بود، که در تمام اوقات همه به کار میبردند. نگهداری آن در حافظه کارایی سیستم را روی هم رفته بالا برده بود. اگرچه نگهداری مورد تنومندی همچون مترجم C در حافظه، به کارایی در آن سیستمهای قدیمیتر آسیب میرساند، زیرا آنها حافظه زیادی برای چشمپوشی نداشتند. به هر حال این هیچ در مورد سیستم دبیان صدق نمیکند. این پاراگراف تنها به واسطه اشاره تاریخی در اینجا آورده شد.
سپس، دو بیت وجود دارد که باعث میشوند برنامهها با امتیازات متفاوتی نسبت به حق ویژه شخصی که آنها را راهاندازی نموده، اجرا گردند. این بیتها "setuid" و "setgid" میباشند، و با کاربر و گروه برنامه همخوانی دارند. یک برنامه با بیت setuid فعال شده، به عنوان مالک برنامه اجرا میشود، مهم نیست چه شخصی آن را راهاندازی میکند . یک برنامه با بیت setgid فعال شده، به عنوان برنامه گروه اجرا میگردد.
بهترین مثال یک برنامه setuid فرمان passwd(1) است که به کاربران اجازه میدهد کلمه عبورشان را تغییر بدهند. این برنامه باید قادر باشد محتویات فایل /etc/passwd را ویرایش کند، اما به طور حتم ما نمیخواهیم کاربران عادی این توانایی را داشته باشند! از اینرو برنامه passwd به طور بسیار با دقتی نوشته شده است، به طوری که فقط انجام حداقل تغییر ضروری را به کاربر جهت تغییر کلمه عبور خودش اجازه میدهد. پس بیت setuid فعال شده است، به طوری که قدرت انجام آن تغییر را دارد.
griffon:~$ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 26616 2004-07-27 10:39 /usr/bin/passwd*
حرف "s" در جایی که ما انتظار دیدن یک "x" برای مجوز مالک داشتیم به معنای آن است که این برنامه دارای هر دو بیت تنظیم شده اجرا و setuid میباشد. موقعی که greg کلمه "passwd" را تایپ میکند، برنامه passwd به جای greg به عنوان root اجرا میشود.
به همچنین، برنامههای setgid به جای شماره شناسایی گروه شخصی که برنامه را راهاندازی میکند، با شماره شناسایی گروه مالک گروهشان اجرا میشوند. یک مثال خوب xterm(1) است:
-rwxr-sr-x 1 root utmp 263736 2004-12-15 14:19 /usr/bin/X11/xterm*
xterm به عنوان عضوی از گروه "utmp" اجرا میشود، به طوری که میتواند یک مدخل در فایل utmp(5) بنویسد:
-rw-rw-r-- 1 root utmp 11904 2005-03-11 08:09 /var/run/utmp
این فایل توسط برنامه who(1) و سایر برنامهها برای نگهداری یک رکورد از شخصی که به سیستم متصل گردیده، مورد استفاده قرار میگیرد. وقتی یک xterm با نشانههای معین اجرا میشود، یک مدخل در داخل این فایل مینویسد، بنابراین، افرادی که از طریق شبکه به وسیله اجرای یک xterm و تعدادی برنامه داخل آن به سیستم متصل میشوند، را در خروجی برنامه "who" نمایش خواهد داد. (این یک توضیح بسیار ضعیف و سادهسازی شده از چگونگی عملکرد utmp است، اما این صفحه تا اینجا هم بیش از اندازه حجیم شده است.)
عاقبت، یک نکته نهایی، و به پایان خواهیم برد. بیت setuid روی دایرکتوری مصداق ندارد(در دبیان)، اما بیت setgid دارد. به معنای آن است که فایلهای ایجاد شده در آن دایرکتوری به جای GID شخصی که آنها را ایجاد میکند از مالک گروه دایرکتوری ارث میبرند.موقعی که این بیت با یک umask که امتیاز نوشتن گروه را مجاز میکند(از قبیل 002) ترکیب میشود، این مورد در برقراری حوزهای که گروهی از کاربران میتوانند با یکدیگر کار کنند سودمند میشود. برای مثال:
drwxrwsr-x 15 root src 4096 2005-01-06 08:52 /usr/src
دایرکتوری /usr/src توسط اعضای گروه "src" قابل نوشتن است، و همچنین دارای بیت setgid فعال شده است(نشان داده شده به صورت یک "s")، بنابراین هر فایل ایجاد شده در آن نیز به گروه "src" تعلق دارد. اگر ما دارای دو کاربر در گروه "src" باشیم (فرض کنید، john و jane)، و اگر آنها هر دو umask خود را به 002 یا 007 تنظیم کنند(حداقل در حالیکه در آن دایرکتوری کار میکنند)، آنوقت هرچه آنها در اینجا ایجاد کنند نیز برای گروه src قابل نوشتن خواهد بود:
drwxrwsr-x 15 root src 4096 2005-01-06 08:52 /usr/src -rw-rw---- 1 jane src 856 2004-09-06 15:26 /usr/src/foo.c -rw-rw-r-- 1 john src 952 2004-09-03 13:21 /usr/src/bar.c
در این مثال کاملاً ساختگی، jane در حالیکه در اینجا مشغول به کار است از umask برابر 007 در حال استفاده است، یا از chmod(1) برای انجام همان عمل استفاده نموده است. john از یک umask برابر 002 (یا chmod) استفاده میکند. سایر کاربران سیستم قادر خواهند بود کد john را بخوانند، اما کد jane را خیر. اما بخش مهم آن است که آنها میتوانند هر یک از فایلهای دیگر را هم بخوانند و هم در آنها بنویسند . البته این جایگزین برای یک سیستم کنترل نگارش با انضباط نیست، بلکه رایجترین مورد استفاده از بیت setgid برای یک دایرکتوری را تشریح میکند.
در برخی سیستمها(از جمله دبیان با coreutils نگارش 6.0 یا بالاتر)، فرمانchmod موقعی که در وضعیت اکتال استفاده میشود، بیتهای setuid و setgid را از دایرکتوری پاک نمیکند. در سایر سیستمها chmod 755 همیشه مجوزهای دایرکتوری را به صورت drwxr-xr-x تنظیم میکند، و نه مورد دیگری. بنابراین اگر در وضعیتی قرار گرفتید که آنجا فرمان chmod 755 somedir در پاک کردن بیت setuid یا setgid ناموفق شد، شما باید از symbolic mode( مترجم: استفاده از حروف مربوطه rwx ) برای بیان صریح مقاصد خود استفاده نمایید. برای توضیحات بیشتر صفحات man سیستم خود را ببینید.
مجوزها (آخرین ویرایش 2011-06-27 17:47:07 توسط GreyCat)