SSD Nodes Learn 🎉 VPS $5.50/माह से
गाइड Matt Connorलेखक: Matt Connor

Linux में umask क्या है और यह कैसे काम करता है?

Linux में umask फाइल और डायरेक्टरी की परमिशन को कैसे नियंत्रित करता है, इसे समझें। अपना वर्तमान umask मान देखें और जानें कि क्यों root और सामान्य यूजर के लिए यह अलग होता है।

Linux पर umask क्या करता है

umask एक संख्या है जो Linux पर प्रत्येक process के साथ रहती है। यह उस process द्वारा बनाई गई प्रत्येक file और directory के mode (permissions) को निर्धारित करती है। कोई program creation के समय kernel से permissions का एक सेट मांगता है। kernel उस mask में नामित प्रत्येक bit को हटा देता है और जो बचता है उसे लागू करता है। umask कभी भी access प्रदान नहीं करता है। यह केवल बनाने वाले program द्वारा मांगी गई permissions से bits को हटाता है।

यह मान आपके distribution की विशेषता नहीं है। यह इस पर निर्भर करता है कि आप किस account का उपयोग कर रहे हैं और shell कैसे start किया गया था। एक ही machine पर, एक ही समय में, एक stock image पर भी ये दोनों उत्तर अलग-अलग हो सकते हैं। इसलिए पहला कदम manual में खोजना नहीं है। यह आपके सामने मौजूद machine पर इसका मापन करना है।

वर्तमान शेल में umask प्रिंट करें

umask
umask -S

पहला प्रारूप मास्क को octal में प्रिंट करता है। दूसरा प्रारूप उसी मास्क को उन अनुमतियों (permissions) के रूप में प्रिंट करता है जिनकी यह अनुमति देता है, जिसे chmod स्वीकार करता है। दोनों पंक्तियों को स्क्रीन पर रखें। नीचे दी गई हर चीज़ आपके शेल द्वारा अभी प्रिंट किए गए मानों के साथ एक तुलना है।

umask एक शेल builtin है, न कि डिस्क पर स्थित कोई प्रोग्राम। इसकी पुष्टि type umask के साथ करें। यह महत्वपूर्ण है, क्योंकि एक builtin स्वयं शेल प्रक्रिया को बदल देता है। एक अलग प्रोग्राम केवल अपनी प्रक्रिया को बदल सकता है, फिर समाप्त हो सकता है और बदलाव को अपने साथ ले जा सकता है।

एक फाइल और एक डायरेक्टरी बनाएँ, फिर उनके मोड्स (modes) को पढ़ें

cd "$(mktemp -d)"
touch probe.file
mkdir probe.dir
stat -c '%a %A %n' probe.file probe.dir

%a मोड को ऑक्टल (octal) में प्रिंट करता है और %A उसी मोड को उस drwxr-xr-x प्रारूप में प्रिंट करता है जिसका उपयोग ls -l करता है। दोनों पंक्तियों की तुलना उस मास्क (mask) से करें जिसे आपने अभी थोड़ी देर पहले प्रिंट किया था। मास्क में सेट की गई हर बिट मोड्स में गायब होती है, क्योंकि मास्क का एकमात्र काम उन बिट्स को क्लियर करना है। यदि %A कॉलम को पढ़ना अभी भी स्पष्ट नहीं है, तो drwxr-xr-x परमिशन स्ट्रिंग को समझना सबसे पहले जरूरी है।

फाइल और डायरेक्टरी एक-दूसरे से अलग हैं, और इसका कारण मास्क नहीं है। touch कर्नल से ओनर, ग्रुप और अन्य के लिए रीड और राइट की अनुमति मांगता है। mkdir तीनों के लिए रीड, राइट और एग्जीक्यूट की अनुमति मांगता है। एक ही मास्क को दो अलग-अलग अनुरोधों से घटाया जाता है। इसलिए touch द्वारा बनाई गई फाइल कभी भी एग्जीक्यूटेबल नहीं होती, चाहे मास्क में कुछ भी हो: एग्जीक्यूट बिट के लिए कभी अनुरोध ही नहीं किया गया था, और मास्क किसी बिट को वापस जोड़ नहीं सकता।

( umask a=rwx; touch open.file; stat -c '%a %A %n' open.file )

वे कोष्ठक (parentheses) कमांड्स को एक सबशेल (subshell) में चलाते हैं, इसलिए बदलाव उसी के साथ समाप्त हो जाता है। मास्क अब किसी भी चीज को क्लियर करने के लिए नहीं कहता है, और stat अभी भी फाइल पर कोई एग्जीक्यूट बिट न होने की रिपोर्ट करता है। बाद में umask को फिर से चलाएँ और आपका मूल मान वापस आ जाएगा, जो यह दर्शाता है कि यह सेटिंग एक प्रोसेस के भीतर रहती है और बच्चों (children) द्वारा इनहेरिट की जाती है, न कि डिस्क पर कहीं स्टोर होती है।

डायरेक्टरीज में एग्जीक्यूट बिट के क्लियर होने का प्रभाव महसूस होता है।

( umask a=rw; mkdir noexec.dir; cd noexec.dir )

एक सामान्य यूजर के रूप में cd, bash: cd: noexec.dir: Permission denied के साथ विफल हो जाता है, क्योंकि मास्क ने उस एग्जीक्यूट बिट को क्लियर कर दिया था जिसे mkdir ने मांगा था, और बिना एग्जीक्यूट बिट वाली डायरेक्टरी में प्रवेश नहीं किया जा सकता है। Root इस जांच को छोड़ देता है, इसलिए यह केवल एक सामान्य अकाउंट पर ही दिखाई देता है।

root और आपके अपने user के लिए umask अलग क्यों दिखाई देता है

एक ही measurement को किसी दूसरे account के माध्यम से चलाएं, जिसे किसी अन्य तरीके से start किया गया हो, और दोनों outputs को साथ-साथ देखें।

umask
sudo -i umask

sudo -i root के login shell को start करता है और उसके भीतर builtin command को चलाता है, इसलिए यह एक अलग startup path के माध्यम से आने वाला एक अलग account है। stock Ubuntu और Debian server images पर ये दोनों lines अलग-अलग values print कर सकती हैं। दोनों lines सही हैं। प्रत्येक यह दर्शाती है कि उसके अपने startup path ने क्या produce किया है, और इस post का शेष भाग इसी बारे में है कि system के किस हिस्से ने इसे produce किया है।

आपकी image पर किस file ने value तय की

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'

यदि पहला grep कुछ भी print नहीं करता है, तो इसे ^ anchor के बिना फिर से चलाएँ: हो सकता है कि line comment की गई हो, और एक comment की गई line configuration के बजाय documentation होती है। तीसरा grep वह है जो लोगों को आश्चर्यचकित करता है। Debian और Ubuntu पर, प्रदान की गई /etc/profile file स्वयं mask set करने के बजाय अधिकतर PAM की ओर इशारा करती है, इसलिए जिस file को आपने जिम्मेदार माना था, वह अक्सर नहीं होती है। grep non-zero exit देता है जब उसे कुछ भी match नहीं मिलता, यही कारण है कि वह line || echo पर समाप्त होती है: ऐसी image पर जहाँ कोई startup file mask का उल्लेख नहीं करती है, आपको silence के बजाय message मिलता है, और वह message ही निष्कर्ष है।

/etc/login.defs एक मान (value) का विज्ञापन करता है और PAM एक अन्य मान लागू करता है

UMASK लाइन, जो /etc/login.defs में स्थित है, वह मान है जिसे अधिकांश गाइड उद्धृत करती हैं। न तो kernel और न ही shell इस फ़ाइल को पढ़ता है। इसे pam_umask द्वारा पढ़ा जाता है, जो एक PAM (pluggable authentication modules) मॉड्यूल है और session बनने पर चलता है। pam_umask उसे मिलने वाला पहला मान लेता है: उपयोगकर्ता के GECOS फ़ील्ड में एक umask= प्रविष्टि, फिर pam_umask.so लाइन पर ही लिखा गया एक umask= तर्क, और अंत में /etc/login.defs से UMASK। Linux distributions इस मॉड्यूल में बदलाव (patch) करते हैं, इसलिए अपनी image पर man pam_umask चलाएँ और वहाँ छपी प्राथमिकता का क्रम पढ़ें।

यही कारण है कि /etc/login.defs एक मान का विज्ञापन कर सकता है जबकि आपका session किसी अन्य मान के साथ समाप्त होता है, और किसी भी तरफ कोई चेतावनी नहीं दी जाती है। Grep कमांड आपको बताते हैं कि आप किस स्थिति में हैं। यदि pam_umask.so लाइन में अपना स्वयं का umask= तर्क मौजूद है, तो login.defs की लाइन प्रभावी नहीं रहती है।

USERGROUPS_ENAB और root अपवाद

id -un
id -gn

यदि वे दोनों एक ही नाम प्रिंट करते हैं, तो आपके पास एक user private group है: खाता उसी के नाम पर रखे गए एक समूह के साथ बनाया गया था। pam_umask में एक usergroups व्यवहार होता है, जो /etc/login.defs में USERGROUPS_ENAB द्वारा नियंत्रित होता है। जब यह चालू होता है, और खाता root नहीं होता है, और प्राथमिक समूह का नाम उपयोगकर्ता के नाम से मेल खाता है, तो मॉड्यूल mask के owner digit को group digit में कॉपी कर देता है। सत्र का अंत एक ऐसे mask के साथ होता है जो उस खाते द्वारा बनाई गई हर चीज़ पर group bits को खुला छोड़ देता है। Root को मॉड्यूल द्वारा स्वयं बाहर रखा गया है, और यह अपवाद ही सबसे आम कारण है कि एक सर्वर पर दो shells अलग-अलग masks प्रिंट करते हैं।

इस नियम के पीछे का तर्क यह है कि एक private group में केवल एक ही सदस्य होता है, इसलिए group-writable का अर्थ owner-writable ही होता है और कुछ नहीं। यह तब तक बना रहता है जब तक कोई उस समूह में दूसरा सदस्य नहीं जोड़ देता। उस क्षण से, खाते द्वारा बनाई गई हर फ़ाइल नए सदस्य के लिए writable हो जाती है, और उन फ़ाइलों पर ऐसा करने के लिए कोई command नहीं चलाई गई थी। प्रत्येक service को उसका अपना least-privilege user account दें और वह समूह जानबूझकर एक का समूह बना रहेगा।

Login shell, non-login shell और non-interactive shell

umask
bash -lc 'umask'
bash -c 'umask'

जब कोई session बनाया जाता है, तब PAM चलता है: login console पर, sshd, su, sudo -i। जब एक shell किसी दूसरी shell को start करती है, तब यह नहीं चलता। bash -l एक login shell है, इसलिए यह /etc/profile और ~/.profile को पढ़ती है, लेकिन यह कभी pam_umask को call नहीं करती, क्योंकि कोई session नहीं बनाया गया था। bash -c न तो कोई file पढ़ती है और न ही उसे, बल्कि यह उस process का mask inherit करती है जिसने इसे start किया था। एक cron job, एक git hook और एक service manager द्वारा start किया गया program, ये सभी इसी अंतिम स्थिति में आते हैं, इसलिए उनका mask वही होता है जो उनके parent process का था।

यही कारण है कि "मैंने इसे /etc/profile में set किया है और service अभी भी गलत mode में लिख रही है" एक आम शिकायत है। service ने वह file कभी पढ़ी ही नहीं।

इसे कहाँ सेट करें ताकि यह सुरक्षित रहे

mask को वहाँ सेट करें जहाँ workload वास्तव में शुरू होता है, क्योंकि प्रत्येक start path एक अलग file को पढ़ता है।

  1. login करने वाले accounts के लिए: UMASK को /etc/login.defs में सेट करें, जिसे pam_umask द्वारा machine के प्रत्येक session पर लागू किया जाता है। यह machine-wide है, इसलिए यह एक साथ सभी accounts को प्रभावित करता है।
  2. एक account के लिए: pam_umask.so line पर umask= argument भी machine-wide होता है, इसलिए per-user value उस user के GECOS field में, या login shells के लिए ~/.profile में और interactive shells के लिए ~/.bashrc में होनी चाहिए।
  3. systemd के अंतर्गत daemon के लिए: unit के [Service] section में UMask= का उपयोग करें। एक unit को service manager द्वारा शुरू किया जाता है, इसलिए /etc/profile कभी नहीं पढ़ा जाता और pam_umask कभी run नहीं होता। unit file ही एकमात्र ऐसी जगह है जो daemon तक पहुँचती है।
  4. cron या hook द्वारा शुरू की गई script के लिए: script द्वारा कुछ भी create करने से पहले, पहली line पर एक स्पष्ट umask का उपयोग करें।
[Service]
UMask=<the octal mask you chose>

इसके बाद उसी path को नए सिरे से शुरू करके verify करें, न कि उस shell से जहाँ आपने file edit की थी। आपके वर्तमान shell में पहले से ही उसका mask मौजूद है, और config file को edit करने से वह चल रही process में वापस लागू नहीं होता है।

bash -lc 'umask'
sudo -i umask

बाद में chmod करना एक ही समाधान क्यों नहीं है

chmod उन फाइलों को ठीक करता है जो पहले से मौजूद हैं। umask यह तय करता है कि जो फाइलें अभी तक नहीं बनी हैं, उनका मोड क्या होगा। यदि आप किसी डायरेक्टरी पर chmod -R चलाते हैं, तो सर्विस द्वारा लिखी जाने वाली अगली फाइल फिर से पुराने मोड के साथ ही आएगी, क्योंकि वह मोड फाइल बनाने वाली प्रक्रिया से आता है और डायरेक्टरी में किया गया कोई भी बदलाव उसे प्रभावित नहीं करता।

इसके अलावा, एक समय अंतराल भी होता है। फाइल बनने के क्षण और chmod के चलने के क्षण के बीच, फाइल डिस्क पर अधिक खुले मोड (wider mode) के साथ रहती है, और कोई भी प्रक्रिया जो उस डायरेक्टरी को पढ़ सकती है, उसे खोल सकती है। प्राइवेट की (private key) या बैकअप आर्काइव के लिए, वह अंतराल ही वह जोखिम है जिसे आप हटाना चाह रहे थे।

इसके बजाय, फाइल बनाते समय ही मोड सेट करें। install -m u=rw,go= newfile /etc/app/newfile डेस्टिनेशन फाइल को एक स्पष्ट मोड के साथ लिखता है, और mkdir -m डायरेक्टरी के लिए भी यही करता है। दोनों आपके द्वारा दिए गए मोड को अपनाते हैं और umask को अनदेखा कर देते हैं। ssh-keygen अपनी लिखी गई प्राइवेट की पर मोड सेट करता है, यही कारण है कि वह एक फाइल अक्सर उस मशीन पर सही होती है जहाँ बाकी सब गलत होता है।

इसका सबसे आम शिकार SSH होता है। एक ~/.ssh जिसे साधारण mkdir से बनाया गया हो, या एक authorized_keys जिसे cat >> के साथ अपेंड किया गया हो, वह आपके शेल के umask को अपना लेता है। StrictModes ऑन होने पर, sshd किसी ऐसी की फाइल को पढ़ने से इनकार कर देता है जो ग्रुप-राइटेबल डायरेक्टरी में हो। क्लाइंट को Permission denied (publickey) का संदेश मिलता है, जबकि सर्वर का /var/log/auth.log वास्तविक कारण रिकॉर्ड करता है:

Authentication refused: bad ownership or modes for directory /home/deploy/.ssh

यह जाँच जानबूझकर की जाती है, और VPS पर SSH को सुरक्षित करना इसी के बने रहने पर निर्भर करता है। नए सर्वर पर अकाउंट बनाने से पहले umask को मापें, साथ ही नए VPS पर पहले दस मिनट का पालन करें, और उन अकाउंट्स द्वारा लिखी जाने वाली हर फाइल का मोड पहले से ही निर्धारित हो जाएगा।

कॉपी और आर्काइव मास्क (mask) को अनदेखा करते हैं

cp -p और rsync -a सोर्स फाइल पर रिकॉर्ड किए गए मोड (mode) को रिस्टोर करते हैं, इसलिए परिणाम में मास्क की कोई भूमिका नहीं होती। जब tar रूट के रूप में, या -p के साथ एक सामान्य उपयोगकर्ता के रूप में एक्सट्रैक्ट करता है, तो वह भी ऐसा ही करता है। बैकअप से रिस्टोर की गई फाइल उसी मोड को बनाए रखती है जो बैकअप बनाते समय था। यह निष्कर्ष निकालने से पहले कि सही मास्क को अनदेखा किया जा रहा है, इसकी जांच कर लें: रिस्टोर किए गए डेटा के लिए मास्क का उपयोग कभी नहीं किया गया था।

FAQ

मेरा cron job ssh session से अलग mode वाली फाइलें क्यों बनाता है?

Cron job एक login session नहीं है, इसलिए इसके लिए pam_umask कभी नहीं चलता है और यह न तो /etc/profile को पढ़ता है और न ही ~/.profile को। यह उस process का mask inherit करता है जिसने इसे शुरू किया है। स्क्रिप्ट की पहली लाइन में, कुछ भी बनाने से पहले, एक स्पष्ट umask डालें। जॉब के अंदर से एक बार mask को print करें ताकि आप देख सकें कि उस जॉब का वास्तविक mask क्या है, न कि वह जो आपके shell का है।

/etc/login.defs कुछ और क्यों कहता है और मेरा shell कुछ और क्यों print करता है?

/etc/login.defs में UMASK केवल pam_umask के लिए अंतिम fallback है। यह module उपयोगकर्ता के GECOS field में umask= entry को प्राथमिकता देता है, उसके बाद /etc/pam.d/ में pam_umask.so लाइन पर umask= argument को। USERGROUPS_ENAB द्वारा सक्षम किया गया usergroups व्यवहार, किसी भी non-root account के लिए group digit को फिर से लिख देता है जिसका primary group उसी के नाम पर है। यह देखने के लिए कि आपके account पर इनमें से क्या लागू होता है, grep -rn pam_umask /etc/pam.d/ और id -un; id -gn चलाएं।

क्या umask किसी फाइल को executable बना सकता है?

नहीं। एक mask केवल उन bits को हटा सकता है जिन्हें बनाने वाले प्रोग्राम ने मांगा है। touch कभी भी execute bit के लिए नहीं कहता है, इसलिए कोई भी mask executable फाइल नहीं बनाता है। इसे एक throwaway directory में ( umask a=rwx; touch f; stat -c '%a %A' f ) के साथ जांचें। execute bit प्राप्त करने के लिए आपको chmod की आवश्यकता है, या install -m जैसे प्रोग्राम की जो निर्माण के समय इसकी मांग करता है।

मैं systemd service के लिए umask कहाँ सेट करूँ?

Unit में, [Service] section के भीतर UMask= के साथ। एक service को login के बजाय service manager द्वारा शुरू किया जाता है, इसलिए shell startup फाइलें कभी नहीं पढ़ी जाती हैं और pam_umask इसके लिए कभी नहीं चलता है। systemctl daemon-reload और unit को restart करने के बाद, बाहर से पुष्टि करें: service को एक फाइल बनाने दें, फिर stat -c '%a %n' के साथ परिणाम पढ़ें।

क्या group-writable default mask सुरक्षित है?

यह तब तक सुरक्षित है जब तक group में केवल एक ही सदस्य हो, जो user private group scheme के पीछे की धारणा है। उस group में दूसरा account जोड़ें और पहली account द्वारा बनाई गई हर फाइल तुरंत नए सदस्य के लिए writable हो जाती है, बिना उन फाइलों पर कोई कमांड चलाए। id -un और id -gn चलाएं: एक ही नाम print होने का मतलब है कि आप एक private group पर हैं। यदि आप accounts के बीच एक group साझा करते हैं, तो एक ऐसा mask सेट करें जो group write bit को हटा दे, फिर एक फाइल बनाएं और बदलाव के प्रभावी होने की पुष्टि करने के लिए stat -c '%a %n' पढ़ें।

#umask#permissions#pam#login-defs#linux