Cara Semak dan Faham Nilai umask dalam Linux
Ketahui cara umask menentukan keizinan fail dan direktori anda. Gunakan arahan umask untuk melihat perbezaan antara pengguna biasa dan root serta kesan bit oktal tersebut.
Fungsi umask pada Linux
Umask ialah nombor yang dibawa oleh setiap proses pada Linux, dan ia menentukan mod bagi setiap fail serta direktori yang dicipta oleh proses tersebut. Sesebuah program meminta set keizinan daripada kernel semasa penciptaan. Kernel akan memadamkan setiap bit yang dinamakan oleh mask dan menggunakan baki yang tinggal. Umask tidak pernah memberikan akses. Ia hanya membuang bit daripada apa yang diminta oleh program pencipta.
Nilai ini bukanlah sifat bagi pengedaran (distribution) anda. Ia bergantung pada akaun yang anda gunakan, dan cara shell dimulakan. Kedua-dua jawapan tersebut boleh berbeza pada satu mesin, pada saat yang sama, dalam imej stok. Jadi, langkah pertama bukanlah mencari dalam manual. Ia adalah pengukuran pada kotak di hadapan anda.
Cetak umask dalam shell yang sedang digunakan
umask
umask -SBentuk pertama mencetak mask dalam format oktal. Bentuk kedua mencetak mask yang sama sebagai kebenaran (permissions) yang dibenarkannya, dalam bentuk simbolik yang diterima oleh chmod. Pastikan kedua-dua baris dipaparkan pada skrin. Segala maklumat di bawah adalah perbandingan terhadap apa yang baru sahaja dicetak oleh shell anda.
umask ialah builtin shell dan bukannya program pada cakera. Sahkan perkara ini dengan type umask. Ini penting kerana builtin mengubah proses shell itu sendiri. Program berasingan hanya boleh mengubah prosesnya sendiri, kemudian keluar dan membatalkan perubahan tersebut.
Cipta fail dan direktori, kemudian baca modnya semula
cd "$(mktemp -d)"
touch probe.file
mkdir probe.dir
stat -c '%a %A %n' probe.file probe.dir%a mencetak mod dalam bentuk oktal dan %A mencetak mod yang sama dalam bentuk drwxr-xr-x yang digunakan oleh ls -l. Bandingkan kedua-dua baris tersebut dengan mask yang anda cetak sebentar tadi. Setiap bit yang ditetapkan dalam mask tiada dalam mod tersebut, kerana membersihkan bit tersebut adalah satu-satunya fungsi mask. Jika lajur %A belum jelas untuk dibaca, rentetan keizinan drwxr-xr-x adalah perkara yang perlu difahami terlebih dahulu.
Fail dan direktori berbeza antara satu sama lain, dan mask bukanlah punca perbezaan tersebut. touch meminta kernel untuk keizinan baca dan tulis bagi pemilik, kumpulan, dan lain-lain. mkdir meminta keizinan baca, tulis, dan laksana untuk ketiga-tiganya. Mask yang sama ditolak daripada dua permintaan yang berbeza. Oleh itu, fail yang dicipta oleh touch tidak akan boleh dilaksanakan, walau apa pun nilai dalam mask: bit laksana tidak pernah diminta, dan mask tidak boleh menambah semula bit tersebut.
( umask a=rwx; touch open.file; stat -c '%a %A %n' open.file )Tanda kurungan tersebut menjalankan arahan dalam subshell, jadi perubahan itu tamat bersamanya. Mask kini meminta supaya tiada apa-apa yang dibersihkan, dan stat masih melaporkan tiada bit laksana pada fail tersebut. Jalankan umask semula selepas itu dan nilai asal anda akan kembali, yang menunjukkan tetapan tersebut wujud di dalam proses dan diwarisi oleh proses anak, bukannya disimpan di mana-mana pada cakera.
Direktori adalah tempat di mana bit laksana yang dibersihkan akan dirasai kesannya.
( umask a=rw; mkdir noexec.dir; cd noexec.dir )Sebagai pengguna biasa, cd gagal dengan bash: cd: noexec.dir: Permission denied, kerana mask telah membersihkan bit laksana yang diminta oleh mkdir, dan direktori tanpa bit laksana tidak boleh dimasuki. Root melangkau semakan tersebut, jadi perkara ini hanya kelihatan pada akaun biasa.
Mengapa root dan pengguna anda melihat umask yang berbeza
Jalankan ukuran yang sama melalui akaun lain, dimulakan dengan cara yang berbeza, dan baca kedua-dua output secara bersebelahan.
umask
sudo -i umasksudo -i memulakan shell log masuk root dan menjalankan builtin di dalamnya, jadi ini adalah akaun berbeza yang tiba melalui laluan permulaan yang berbeza. Pada imej pelayan Ubuntu dan Debian standard, kedua-dua baris tersebut boleh mencetak nilai yang berbeza. Kedua-dua baris adalah betul. Setiap satu menunjukkan apa yang dihasilkan oleh laluan permulaannya sendiri, dan bahagian seterusnya dalam catatan ini adalah mengenai bahagian sistem yang menghasilkannya.
Fail mana pada imej anda yang menentukan nilai tersebut
grep -nE '^(UMASK|USERGROUPS_ENAB)' /etc/login.defs
grep -rn pam_umask /etc/pam.d/
grep -rn umask /etc/profile /etc/profile.d/ /etc/bash.bashrc ~/.profile ~/.bashrc 2>/dev/null || echo 'no umask line in the shell startup files'Jika arahan grep pertama tidak memaparkan apa-apa, jalankannya semula tanpa anchor ^: baris tersebut mungkin telah dikomen, dan baris yang dikomen adalah dokumentasi, bukannya konfigurasi. Arahan grep ketiga adalah yang sering mengejutkan pengguna. Pada Debian dan Ubuntu, fail /etc/profile yang dibekalkan kebanyakannya menghala ke PAM dan bukannya menetapkan mask itu sendiri, jadi fail yang anda sangka bertanggungjawab sebenarnya tidak. grep akan keluar dengan status bukan sifar apabila ia tidak menemui padanan, itulah sebabnya baris tersebut berakhir dengan || echo: pada imej di mana tiada fail permulaan yang menyebut tentang mask, anda akan menerima mesej tersebut dan bukannya senyap, dan mesej itu adalah penemuan anda.
/etc/login.defs mengiklankan nilai dan PAM menggunakan satu nilai
Baris UMASK dalam /etc/login.defs ialah nilai yang dipetik oleh kebanyakan panduan. Kernel mahupun shell tidak membaca fail tersebut. Fail itu dibaca oleh pam_umask, iaitu modul PAM (pluggable authentication modules) yang berjalan apabila sesi dicipta. pam_umask mengambil nilai pertama yang ditemuinya: entri umask= dalam medan GECOS pengguna, kemudian argumen umask= yang ditulis pada baris pam_umask.so itu sendiri, dan seterusnya UMASK daripada /etc/login.defs. Pengedaran Linux menampal modul ini, jadi jalankan man pam_umask pada imej anda sendiri dan baca urutan yang dipaparkan di situ.
Begitulah cara /etc/login.defs boleh mengiklankan satu nilai sementara sesi anda berakhir dengan nilai yang lain, tanpa sebarang amaran dipaparkan pada kedua-dua pihak. Arahan grep memberitahu anda situasi yang sedang berlaku. Jika baris pam_umask.so membawa argumen umask= miliknya sendiri, nilai dalam login.defs tidak akan digunakan.
USERGROUPS_ENAB dan pengecualian root
id -un
id -gnJika kedua-dua arahan tersebut memaparkan nama yang sama, anda mempunyai kumpulan peribadi pengguna (user private group): akaun tersebut dicipta dengan kumpulannya sendiri yang dinamakan sempena nama akaun itu. pam_umask mempunyai gelagat usergroups yang dikawal oleh USERGROUPS_ENAB dalam /etc/login.defs. Apabila ia diaktifkan dan akaun tersebut bukan root, serta nama kumpulan utama sepadan dengan nama pengguna, modul tersebut akan menyalin digit pemilik daripada mask ke dalam digit kumpulan. Sesi tersebut kemudian berakhir dengan mask yang membiarkan bit kumpulan terbuka pada setiap fail yang dicipta oleh akaun itu. Root dikecualikan oleh modul itu sendiri, dan pengecualian tersebut merupakan punca paling lazim mengapa dua shell pada satu pelayan memaparkan mask yang berbeza.
Sebab di sebalik peraturan ini ialah kumpulan peribadi hanya mempunyai seorang ahli, jadi boleh tulis kumpulan (group-writable) bermaksud boleh tulis pemilik (owner-writable) dan tiada yang lain. Keadaan ini kekal sehingga seseorang menambah ahli kedua ke dalam kumpulan tersebut. Sejak saat itu, setiap fail yang pernah dicipta oleh akaun tersebut boleh ditulis oleh ahli baharu itu, dan tiada arahan yang dijalankan pada fail-fail tersebut untuk menjadikannya sedemikian. Berikan setiap servis akaun pengguna dengan keistimewaan paling rendah (least-privilege) sendiri dan kumpulan itu akan kekal sebagai kumpulan seorang ahli secara sengaja.
Login shell, non-login shell dan non-interactive shell
umask
bash -lc 'umask'
bash -c 'umask'PAM dijalankan apabila sesi dicipta: login pada konsol, sshd, su, sudo -i. Ia tidak dijalankan apabila satu shell memulakan shell yang lain. bash -l ialah login shell, jadi ia membaca /etc/profile dan ~/.profile, tetapi ia tidak pernah memanggil pam_umask kerana tiada sesi yang dicipta. bash -c tidak membaca kedua-dua fail tersebut dan mewarisi mask daripada proses yang memulakannya. Kerja cron, git hook dan program yang dimulakan oleh pengurus servis semuanya berada dalam kategori terakhir ini, jadi mask mereka adalah mengikut apa sahaja yang dimiliki oleh proses induknya.
Inilah sebabnya "Saya telah menetapkannya dalam /etc/profile tetapi servis masih menulis mod yang salah" merupakan laporan yang sangat biasa. Servis tersebut tidak pernah membaca fail itu.
Tempat untuk menetapkannya supaya ia kekal
Tetapkan mask di tempat beban kerja bermula, kerana setiap laluan permulaan membaca fail yang berbeza.
- Untuk akaun yang log masuk:
UMASKdalam/etc/login.defs, digunakan oleh pam_umask pada setiap sesi di mesin tersebut. Ia meliputi seluruh mesin, jadi ia mengubah setiap akaun serentak. - Untuk satu akaun: argumen
umask=pada barispam_umask.sojuga meliputi seluruh mesin, jadi nilai khusus pengguna perlu diletakkan dalam medan GECOS pengguna tersebut, atau dalam~/.profileuntuk shell log masuk dan~/.bashrcuntuk shell interaktif. - Untuk daemon di bawah systemd:
UMask=dalam bahagian[Service]unit tersebut. Unit dimulakan oleh pengurus servis, jadi/etc/profiletidak pernah dibaca dan pam_umask tidak pernah dijalankan. Fail unit adalah satu-satunya fail dalam senarai ini yang memberi kesan kepada daemon. - Untuk skrip yang dimulakan oleh cron atau hook:
umaskeksplisit pada baris pertama, sebelum skrip mencipta sebarang fail.
[Service]
UMask=<the octal mask you chose>Kemudian, sahkan daripada permulaan baharu laluan yang sama, dan jangan sekali-kali daripada shell tempat anda menyunting fail tersebut. Shell semasa anda sudah memegang masknya sendiri, dan menyunting fail konfigurasi tidak akan mengubah proses yang sedang berjalan.
bash -lc 'umask'
sudo -i umaskMengapa chmod selepas itu bukan penyelesaian yang sama
chmod membaiki fail yang sedia ada. Mask menentukan mod bagi fail yang belum wujud. Jalankan chmod -R pada direktori dan fail seterusnya yang ditulis oleh servis akan tiba dengan mod lama semula, kerana mod tersebut datang daripada proses penciptaan dan tiada apa-apa pada direktori yang mengubahnya.
Terdapat juga satu tempoh masa. Antara saat fail dicipta dan saat chmod dijalankan, fail tersebut berada pada cakera dengan mod yang lebih luas, dan mana-mana proses yang boleh membaca direktori tersebut boleh membukanya. Bagi kunci peribadi atau arkib sandaran, tempoh masa itu adalah risiko yang anda cuba hapuskan.
Tetapkan mod semasa penciptaan sebaliknya. install -m u=rw,go= newfile /etc/app/newfile menulis destinasi dengan mod yang eksplisit, dan mkdir -m melakukan perkara yang sama untuk direktori. Kedua-duanya mengambil mod yang anda namakan dan mengabaikan mask. ssh-keygen menetapkan mod pada kunci peribadi yang ditulisnya, itulah sebabnya satu fail itu sering kali betul pada mesin di mana fail lain tidak betul.
Mangsa yang biasa ialah SSH. ~/.ssh yang dibuat dengan mkdir biasa, atau authorized_keys yang ditambah dengan cat >>, mengambil mask shell anda. Dengan StrictModes diaktifkan, sshd enggan membaca fail kunci daripada direktori yang boleh ditulis oleh kumpulan. Klien diberitahu Permission denied (publickey) manakala /var/log/auth.log pelayan merekodkan punca sebenar:
Authentication refused: bad ownership or modes for directory /home/deploy/.sshPemeriksaan itu adalah sengaja, dan pengukuhan SSH pada VPS bergantung pada ketetapannya. Ukur mask pada pelayan baharu sebelum anda mencipta akaun yang akan menggunakannya, bersama-sama dengan sepuluh minit pertama pada VPS baharu, dan mod setiap fail yang ditulis oleh akaun tersebut ditetapkan lebih awal.
Salinan dan arkib mengabaikan mask
cp -p dan rsync -a memulihkan mod yang direkodkan pada fail sumber, jadi mask tidak mempengaruhi hasil tersebut. tar melakukan perkara yang sama apabila ia mengekstrak sebagai root, atau sebagai pengguna biasa dengan -p. Fail yang dipulihkan daripada sandaran mengekalkan mod yang dimilikinya semasa sandaran dibuat. Semak perkara itu sebelum anda membuat kesimpulan bahawa mask yang betul sedang diabaikan: bagi data yang dipulihkan, ia tidak pernah dirujuk.
FAQ
Mengapakah cron job saya mencipta fail dengan mod yang berbeza daripada sesi ssh saya?
Cron job bukanlah sesi log masuk, jadi /etc/profile tidak pernah dijalankan untuknya, dan ia tidak membaca /etc/profile mahupun ~/.profile. Ia mewarisi mask daripada proses yang memulakannya. Letakkan umask secara eksplisit pada baris pertama skrip, sebelum ia mencipta sebarang fail, dan cetak mask tersebut sekali dari dalam job supaya anda boleh melihat nilai sebenar yang dimiliki oleh job tersebut dan bukannya nilai shell anda sendiri.
Mengapakah /etc/login.defs menyatakan satu perkara tetapi shell saya memaparkan perkara lain?
UMASK dalam /etc/login.defs hanyalah sandaran terakhir untuk pam_umask. Modul ini lebih mengutamakan entri umask= dalam medan GECOS pengguna, kemudian argumen umask= pada baris pam_umask.so dalam /etc/pam.d/. Gelagat usergroups, yang diaktifkan oleh USERGROUPS_ENAB, kemudian menulis semula digit kumpulan bagi mana-mana akaun bukan root yang kumpulan utamanya dinamakan sempena nama pengguna tersebut. Jalankan grep -rn pam_umask /etc/pam.d/ dan id -un; id -gn untuk melihat yang mana satu terpakai untuk akaun anda.
Bolehkah umask menjadikan fail boleh laku (executable)?
Tidak. Mask hanya boleh memadamkan bit daripada apa yang diminta oleh program pencipta. touch tidak pernah meminta bit laku, jadi tiada mask yang akan menghasilkan fail boleh laku. Sahkan perkara ini dalam direktori sementara dengan ( umask a=rwx; touch f; stat -c '%a %A' f ). Untuk mendapatkan bit laku, anda memerlukan chmod, atau program seperti install -m yang memintanya semasa penciptaan.
Di manakah saya menetapkan umask untuk servis systemd?
Dalam unit, dengan UMask= di dalam bahagian [Service]. Servis dimulakan oleh pengurus servis dan bukannya melalui log masuk, jadi fail permulaan shell tidak pernah dibaca dan pam_umask tidak pernah dijalankan untuknya. Selepas systemctl daemon-reload dan memulakan semula unit tersebut, sahkan dari luar: biarkan servis mencipta fail, kemudian baca hasilnya dengan stat -c '%a %n'.
Adakah mask lalai yang boleh ditulis oleh kumpulan (group-writable) selamat?
Ia selamat selagi kumpulan tersebut mempunyai tepat satu ahli, yang merupakan andaian di sebalik skim kumpulan peribadi pengguna (user private group). Tambahkan akaun kedua ke dalam kumpulan tersebut dan setiap fail yang dicipta oleh akaun pertama akan terus boleh ditulis oleh ahli baharu itu serta-merta, tanpa perlu menjalankan sebarang arahan pada fail tersebut. Jalankan id -un dan id -gn: jika nama yang dicetak adalah sama, bermakna anda berada dalam kumpulan peribadi. Jika anda berkongsi kumpulan antara akaun, tetapkan mask yang memadamkan bit tulis kumpulan, kemudian cipta fail dan baca stat -c '%a %n' untuk membuktikan perubahan tersebut telah berkuat kuasa.