সরাসরি পর্বে যান
পর্ব ৪৭ · ৬৪-এর মধ্যে · মডিউল ৭

Linux-এ user, group আর permission — rwx, setuid আর sudo

Linux Users, Groups and Permissions — rwx, umask, setuid/setgid/sticky, sudo, Capabilities and ACLs

Taught in Bangla, this lesson teaches Linux users, groups and permissions hands-on in a live Linux terminal: the owner-group-other rwx model, chmod in symbolic and octal form, chown and chgrp, how the kernel checks permissions, umask, the setuid, setgid and sticky bits with real, effective and saved UIDs, sudo versus su, Linux capabilities, POSIX ACLs and common permission mistakes with safe fixes.

এই পর্বে যা শিখবেন

  • /etc/passwd, /etc/group, /etc/shadow-এর গঠন, আর root, সাধারণ user ও service account-এর পার্থক্য
  • ls -l-এর অনুমতি পড়া, symbolic আর octal chmod, chown/chgrp — 754, 640, 2775, 1777 নিজে রূপান্তর করা
  • Kernel-এর permission-যাচাইয়ের নিয়ম, ফাইল বনাম directory-তে rwx-এর অর্থ, আর umask-এর binary হিসাব
  • setuid, setgid, sticky bit; real, effective আর saved UID; setuid প্রোগ্রামের ঝুঁকি আর নিরীক্ষা
  • sudo বনাম su, sudoers আর visudo, Linux capability, POSIX ACL, সাধারণ ভুলের নিরাপদ সমাধান, আর Windows-এর সাথে তুলনা

১ · User আর group — OS আপনাকে কী নামে চেনে

একটি অফিস ভবনের কথা ভাবুন। গেটে দারোয়ান সবার নাম মনে রাখেন না — তিনি দেখেন গলায় ঝোলানো পরিচয়পত্রের নম্বর। হিসাব বিভাগের কার্ডে লেখা “Accounts”, তাই তিনি হিসাব বিভাগের ঘরে ঢুকতে পারেন। আর ভবনের মালিকের কাছে একটি মাস্টার চাবি আছে, যা সব দরজা খোলে।

Linux-এ ঠিক এই ব্যবস্থা। পর্ব ৪৬-এ দেখেছেন কে কী করতে পারবে তার তাত্ত্বিক ছবি — domain, access matrix. এই পর্বে দেখব Linux সেই তত্ত্বকে কত সরলভাবে বাস্তবে রূপ দিয়েছে। প্রতিটি মানুষ বা সার্ভিসের জন্য একটি user account, আর kernel-এর কাছে তার পরিচয় একটি সংখ্যা: UID (user ID). কয়েকজনকে একসাথে অনুমতি দিতে আছে group, যার সংখ্যা GID. প্রতিটি প্রসেস যে user-এর হয়ে চলে, তার UID আর GID-গুলো প্রসেসের সাথে লেগে থাকে (পর্ব ০৮-এর PCB-তে)। প্রতিটি ফাইলের inode-এ লেখা থাকে মালিকের UID আর একটি GID (পর্ব ৪১). Permission-যাচাই মানে এই দুই জোড়া সংখ্যার তুলনা।

/etc/passwd — account-এর তালিকা

নাম থেকে সংখ্যা আর সংখ্যা থেকে নামের অনুবাদ থাকে /etc/passwd ফাইলে। প্রতি লাইনে একটি account, সাতটি ঘর, মাঝে :. নিচের দুটি লাইন এই পাতার কোড-রানারের container থেকে নেওয়া: প্রথমটি root-এর, যা প্রায় সব Linux-এ হুবহু এমন; দ্বিতীয়টি আমাদের sandbox-এর user, যা অংশ ৬-এর কোডে নিজেই দেখবেন।

root:x:0:0:root:/root:/bin/bash
wandbox:x:999:999::/home/wandbox:/bin/sh
ঘরউদাহরণঅর্থ
১ · নামwandboxlogin-এর নাম; মানুষের জন্য
২ · পাসওয়ার্ডx“x” মানে আসল hash /etc/shadow-এ আছে
৩ · UID999kernel-এর কাছে আসল পরিচয়
৪ · প্রধান GID999নতুন ফাইল সাধারণত এই group পায়
৫ · মন্তব্য (GECOS)খালিপুরো নাম, ফোন ইত্যাদি
৬ · home/home/wandboxlogin-এর পর শুরুর directory
৭ · shell/bin/shlogin করলে কোন প্রোগ্রাম চলবে; /usr/sbin/nologin মানে login নিষেধ

অতিরিক্ত group-এর সদস্যপদ থাকে /etc/group-এ: নাম:x:GID:সদস্য১,সদস্য২. যেমন Ubuntu-তে sudo:x:27:ubuntu মানে “ubuntu” নামের user sudo group-এর সদস্য। একজন user-এর একটি প্রধান group আর কয়েকটি supplementary group থাকতে পারে; login-এর সময় সবগুলো প্রসেসের পরিচয়ে যোগ হয়। তাই কাউকে নতুন group-এ যোগ করলে নতুন login (বা নতুন session) না হওয়া পর্যন্ত চলমান shell-এ সেটি দেখা যায় না।

/etc/shadow — কেন আলাদা, কেন শুধু root

শুরুর দিকের Unix-এ পাসওয়ার্ডের hash /etc/passwd-এর দ্বিতীয় ঘরেই থাকত। কিন্তু /etc/passwd সবার পড়ার মতো হতেই হবে: ls -l যখন UID 999-কে “wandbox” লেখে, তখন যেকোনো user-এর প্রসেস এই ফাইল পড়ে। ফলে যে কেউ সবার hash কপি করে নিজের কম্পিউটারে বসে কোটি কোটি পাসওয়ার্ড অনুমান করে মিলিয়ে দেখতে পারত — একে বলে offline guessing, যেখানে login-এর ভুল-চেষ্টার সীমা কোনো কাজে আসে না। সমাধান ছিল ভাগ করা: নাম আর UID থাকুক সবার জন্য খোলা /etc/passwd-এ, আর password hash চলে যাক /etc/shadow-এ, যা শুধু root (আর Debian/Ubuntu-তে shadow group) পড়তে পারে।

rahim:$y$j9T$<salt>$<hash>:20387:0:99999:7:::
│     │  │    │      │       │     │ │     └ মেয়াদ শেষের কত দিন আগে সতর্ক করা হবে
│     │  │    │      │       │     │ └ সর্বোচ্চ কত দিন পর পাসওয়ার্ড বদলাতে হবে
│     │  │    │      │       │     └ বদলের পর অন্তত কত দিন অপেক্ষা
│     │  │    │      │       └ শেষ বদল: ১৯৭০-০১-০১ থেকে দিনের সংখ্যা
│     │  │    │      └ hash (একমুখী — এখান থেকে পাসওয়ার্ড ফেরত পাওয়া যায় না)
│     │  │    └ salt: প্রতি user-এ আলাদা এলোমেলো মান
│     │  └ পদ্ধতির পরামিতি
│     └ $y$ = yescrypt (নতুন Debian/Ubuntu), $6$ = SHA-512 crypt
└ নাম

দুটি জিনিস খেয়াল করুন। প্রথমত, এটি encryption নয় — একমুখী hash; সিস্টেম নিজেও আপনার পাসওয়ার্ড জানে না, login-এর সময় আপনার টাইপ করা লেখার hash বানিয়ে মিলিয়ে দেখে। দ্বিতীয়ত, প্রতি user-এর আলাদা salt থাকায় দুজনের একই পাসওয়ার্ড হলেও hash আলাদা হয়, আর yescrypt বা SHA-512 crypt-এর মতো পদ্ধতি ইচ্ছা করে ধীর, যাতে অনুমানের খরচ বাড়ে। দ্বিতীয় ঘরে ! বা * থাকলে পাসওয়ার্ড দিয়ে login বন্ধ — service account আর অনেক cloud সার্ভারের user এভাবেই থাকে (তারা SSH key দিয়ে ঢোকে)। Hash কীভাবে কাজ করে আর কেন ধীর hash নিরাপদ, তার বিস্তারিত পর্ব ৪৮-এ।

root, সাধারণ user আর service account

👑 root (UID 0)

Superuser. Kernel UID 0-কে বিশেষভাবে দেখে: ফাইলের r/w নিষেধ মানে না, অন্যের প্রসেসে signal পাঠাতে পারে, port 80 খুলতে পারে, kernel module লোড করতে পারে। নামটি “root” না হয়ে অন্য কিছু হলেও UID 0 হলে একই ক্ষমতা।

শুধু প্রশাসনের কাজে

⚙️ System/service account

System account: www-data, mysql, daemon — সাধারণত UID 1000-এর নিচে, shell nologin. প্রতিটি daemon নিজের account-এ চলে, যাতে একটি ভাঙলে অন্যগুলো নিরাপদ থাকে।

মানুষ login করে না

🧑 সাধারণ user

অধিকাংশ distro-তে UID 1000 থেকে শুরু (সীমাটি /etc/login.defs-এ)। নিজের home আর নিজের ফাইলে পূর্ণ অধিকার, বাকি সিস্টেমে প্রায় শুধু পড়া।

প্রতিদিনের কাজ

নিজের পরিচয় দেখার তিনটি কমান্ড: whoami (শুধু নাম), groups (group-গুলোর নাম), আর সবচেয়ে কাজের id — UID, প্রধান GID আর সব group, সংখ্যা ও নাম দুটোই। একটি সাধারণ Ubuntu ল্যাপটপে প্রথম user-এর id দেখতে এমন হতে পারে: uid=1000(rahim) gid=1000(rahim) groups=1000(rahim),4(adm),27(sudo). এখানে 27(sudo) group-এর সদস্যপদই তাকে sudo ব্যবহারের অধিকার দেয় (অংশ ৭)।

২ · Permission-এর মডেল — তিন শ্রেণি × তিন অধিকার

প্রতিটি ফাইলের inode-এ ১২টি অনুমতি-বিট থাকে (আর ধরন বোঝাতে আরও কয়েকটি)। নিচের ৯টি বিটই মূল: তিন শ্রেণির মানুষ — owner (u, user), group (g), other (o, বাকি সবাই) — আর প্রত্যেকের জন্য তিনটি অধিকার — r (read), w (write), x (execute). ওপরের ৩টি বিশেষ বিট (setuid, setgid, sticky) অংশ ৬-এ। ls -l-এর প্রথম কলামে file permission এভাবে পড়বেন:

-rwxr-x--- 1 rahim accounts 4096 salary.sh ভেঙে দেখা

type · owner · group · other

  1. ধরন-- ফাইল, d directory, l symlink
  2. owner (rahim)rwx৪+২+১ = ৭
  3. group (accounts)r-x৪+০+১ = ৫
  4. other---০
ছবি ৪৭.১ — একটি অক্ষর ধরন, তারপর তিনটি করে তিন শ্রেণির অধিকার। এই ফাইলের mode হলো 0750.

একই অক্ষর, ফাইলে এক অর্থ, directory-তে আরেক

পর্ব ৪২-এ দেখেছেন, directory আসলে নাম → inode নম্বরের একটি তালিকা। এটি মনে রাখলে directory-র অনুমতি আর ধাঁধা থাকে না:

বিটসাধারণ ফাইলেDirectory-তে
rবিষয়বস্তু পড়া (cat, cp)নামের তালিকা পড়া (ls) — শুধু নাম; প্রতিটি নামের inode দেখতে x-ও লাগে
wবিষয়বস্তু বদলানো, ছোট করাতালিকায় নাম যোগ, মোছা, নাম বদল — অর্থাৎ ভেতরের ফাইল তৈরি, মোছা, mv. কার্যকর হতে x-ও লাগে।
xপ্রোগ্রাম হিসেবে চালানো (execve); script-এ r-ও লাগে, কারণ interpreter ফাইলটি পড়েTraverse — directory-র “ভেতর দিয়ে যাওয়া”: cd, আর নাম জানা থাকলে ভেতরের ফাইল খোলা

সবচেয়ে চমকপ্রদ নিয়ম: একটি ফাইল মুছতে ফাইলটির ওপর কোনো অনুমতি লাগে না — লাগে তার directory-তে w আর x. কারণ মোছা মানে directory-র তালিকা থেকে একটি নাম কাটা (unlink), ফাইলটি বদলানো নয়। তাই একটি shared directory-তে সবার w থাকলে যে কেউ যে কারও ফাইল মুছে বা নাম বদলে ফেলতে পারে — যদি না sticky bit থাকে (অংশ ৬)। /tmp-এর drwxrwxrwt-এর শেষের t ঠিক এই সমস্যার সমাধান।

৩ · chmod, chown আর chgrp — অনুমতি বদলানো

chmod (change mode) দুইভাবে লেখা যায়। Symbolic রূপ পড়তে সহজ, আর শুধু যা বলবেন তা-ই বদলায়: u/g/o/a (all), তারপর + (যোগ), - (বাদ) বা = (ঠিক এটাই, বাকি মুছে), তারপর অধিকার। যেমন chmod g+w file, chmod o= file, chmod u+x,go-w file. Octal রূপে পুরো mode একবারে বসে: প্রতিটি শ্রেণির জন্য একটি অঙ্ক, যেখানে r = ৪, w = ২, x = ১ যোগ হয়। Octal মানে ৮-ভিত্তিক সংখ্যা, আর তিনটি বিট দিয়ে ঠিক ০ থেকে ৭ পর্যন্ত লেখা যায় — তাই তিন বিটের প্রতিটি দল একটি octal অঙ্ক (সংখ্যা-পদ্ধতির ঝালাই চাইলে Computer Fundamentals-এর সংখ্যা পদ্ধতি)।

চারটি রূপান্তর, হাতে-কলমে

Octalবিশেষ অঙ্কownergroupotherls -lকোথায় ব্যবহার
754(০) নেই৭ = ৪+২+১ = rwx৫ = ৪+১ = r-x৪ = r---rwxr-xr--দলের সবাই চালাবে, বাইরের লোক শুধু পড়বে এমন script
640(০) নেই৬ = ৪+২ = rw-৪ = r--০ = ----rw-r-----config ফাইল: মালিক লিখবে, সার্ভিসের group পড়বে, বাকিরা কিছুই না
2775২ = setgid৭ = rwx৭ = rwx, setgid → rws৫ = r-xdrwxrwsr-xদলের shared project directory (অংশ ৬)
1777১ = sticky৭ = rwx৭ = rwx৭ = rwx, sticky → rwtdrwxrwxrwt/tmp: সবাই লিখবে, কিন্তু শুধু নিজেরটা মুছবে

চার অঙ্কের mode-এ প্রথম অঙ্কটি বিশেষ বিটের: setuid = ৪, setgid = ২, sticky = ১. ls -l-এ এগুলোর আলাদা ঘর নেই, তাই x-এর জায়গায় বসে — setuid owner-এর x-এর জায়গায় s, setgid group-এর x-এর জায়গায় s, sticky other-এর x-এর জায়গায় t. নিচে x না থাকলে বড় হাতের S/T — প্রায় সবসময় একটি ভুলের চিহ্ন।

উল্টো দিকেও অভ্যাস করুন: -rw-r--r-- → rw- = ৬, r-- = ৪, r-- = ৪ → 644. drwx------ → 700. এবার নিচের কোডটি চালিয়ে দেখুন — এটি এই পাতার sandbox-এ সাধারণ (root নয়) user wandbox হিসেবে চলে, নিজের ফোল্ডারে ফাইল বানিয়ে দুই রূপের chmod প্রয়োগ করে, আর stat -c '%a %A' দিয়ে octal ও অক্ষর-রূপ পাশাপাশি দেখায়:

rm -rf lab && mkdir lab && cd lab
show() { stat -c '%a  %A  %n' "$@"; }
touch report.txt script.sh secret.txt
echo "-- new files (umask $(umask)):"; show report.txt
chmod u+x,g-r,o= report.txt        # symbolic: + adds, - removes, = sets exactly
echo "-- after chmod u+x,g-r,o= :"; show report.txt
chmod 754 script.sh                # 7=rwx 5=r-x 4=r--
chmod 640 secret.txt               # 6=rw- 4=r-- 0=---
echo "-- octal 754 and 640:"; show script.sh secret.txt
chmod a-w secret.txt               # a = all three classes
echo "-- after chmod a-w:"; show secret.txt
mkdir shared public
chmod 2775 shared                  # 2 = setgid on a directory
chmod 1777 public                  # 1 = sticky bit, like /tmp
echo "-- special bits on directories:"; show shared public /tmp
chmod u+s script.sh                # setuid where owner has x -> s
chmod u-x,u+s report.txt           # setuid where owner has no x -> S
echo "-- setuid: s (with x) vs S (without x):"; show script.sh report.txt
echo "-- the same, as ls -l shows it:"
ls -l script.sh report.txt | cut -c1-10

আসল রানের আউটপুট:

-- new files (umask 0022):
644  -rw-r--r--  report.txt
-- after chmod u+x,g-r,o= :
700  -rwx------  report.txt
-- octal 754 and 640:
754  -rwxr-xr--  script.sh
640  -rw-r-----  secret.txt
-- after chmod a-w:
440  -r--r-----  secret.txt
-- special bits on directories:
2775  drwxrwsr-x  shared
1777  drwxrwxrwt  public
1777  drwxrwxrwt  /tmp
-- setuid: s (with x) vs S (without x):
4754  -rwsr-xr--  script.sh
4600  -rwS------  report.txt
-- the same, as ls -l shows it:
-rwS------
-rwsr-xr--

(১) নতুন ফাইল 644 — কেন, তা অংশ ৫-এর umask বলবে। (২) u+x,g-r,o= তিনটি কাজ পরপর: 644 → owner-এ x যোগ (744) → group থেকে r বাদ (704) → other-এর সব মুছে (700). Symbolic রূপ শুধু উল্লেখ করা বিট ছোঁয়, তাই আগে থেকে কী ছিল তার ওপর ফল নির্ভর করে; octal রূপ সব বিট একবারে ঠিক করে দেয়। (৩) a-w-এর পর 640 হলো 440 — মালিক নিজেও আর লিখতে পারবেন না, যদিও মালিক হিসেবে আবার chmod করার অধিকার তাঁর সবসময় থাকে। (৪) Sandbox-এর /tmp-ও ঠিক 1777. (৫) s বনাম S: report.txt-এ owner-এর x নেই, তাই setuid থাকলেও তা অর্থহীন, দেখায় বড় হাতের S. আর একটি সতর্কতা: Linux shell script-এর setuid বিট উপেক্ষা করে (shebang দিয়ে শুরু ফাইলে) — script.sh-এ s দেখালেও এটি কখনো মালিকের ক্ষমতায় চলবে না। এটি ইচ্ছাকৃত নিরাপত্তা-নিয়ম, কারণ script-এর setuid বহু race আর পরিবেশ-চালাকির পথ খুলে দিত।

মালিক বদলানো — chown আর chgrp

chown rahim:accounts file একসাথে owner আর group বদলায়; chgrp accounts file শুধু group. নিয়মগুলো গুরুত্বপূর্ণ: Linux-এ একজন সাধারণ user নিজের ফাইলও অন্য কাউকে “দিয়ে দিতে” পারেন না — owner বদলানো শুধু root-এর (আরও নির্দিষ্টভাবে CAP_CHOWN ক্ষমতা যার আছে)। কারণ তা না হলে কেউ অন্যের নামে ফাইল রেখে disk quota এড়াতে পারত, বা অন্যের নামে ক্ষতিকর ফাইল রাখতে পারত। ফাইলের মালিক অবশ্য group বদলাতে পারেন, তবে শুধু সেই group-এ যার তিনি নিজে সদস্য। আর owner বা group বদলালে Linux সাধারণত setuid/setgid বিট মুছে দেয়, যাতে বদলানোর ফাঁকে কোনো বিশেষ ক্ষমতা অন্যের হাতে না যায়। পুরো একটি ফোল্ডারে প্রয়োগ করতে -R (recursive) — তবে অংশ ৯-এ দেখবেন, এই ছোট অক্ষরটি কত বড় দুর্ঘটনার উৎস।

৪ · Kernel কীভাবে সিদ্ধান্ত নেয় — permission-যাচাইয়ের নিয়ম

কোনো প্রসেস একটি ফাইল খুলতে (open), চালাতে (execve) বা path-এর একটি directory পেরোতে চাইলে kernel একটি সরল নিয়ম মানে। এখানে “আপনি” মানে প্রসেসের effective UID আর তার group-গুলো (অংশ ৬):

  1. আপনার UID কি ফাইলের owner-এর UID? হ্যাঁ হলে শুধু owner-এর তিনটি বিট দেখা হয় — এখানেই শেষ।
  2. না হলে: ফাইলের GID কি আপনার কোনো group-এর (প্রধান বা অতিরিক্ত) সাথে মেলে? হ্যাঁ হলে শুধু group-এর বিট.
  3. না হলে: other-এর বিট.
  4. যে শ্রেণি বাছা হলো, সেখানে চাওয়া প্রতিটি অধিকার (r, w বা x) থাকলে অনুমতি, একটিও না থাকলে EACCES — “Permission denied”.

খেয়াল করুন, শ্রেণিগুলো যোগ হয় না; প্রথম মিলটিই চূড়ান্ত। এর একটি অদ্ভুত ফল: owner-এর অধিকার group-এর চেয়ে কম হতে পারে, আর তখন মালিক নিজেই আটকে যান। Root-এর জন্য আলাদা নিয়ম, যা শেষ ধাপে দেখবেন। নিচের stepper-এ একটি ফাইল আর চারজন অনুরোধকারী:

ফাইল: -r--rw---- rahim accounts salary.xlsx (mode 0460) · UID কাল্পনিক
অনুরোধকারী
চাওয়া
owner মেলে?
group মেলে?
যে বিট দেখা হলো
ফল
  1. ফাইলটি। হিসাব বিভাগের বেতনের ফাইল, owner rahim, group accounts, mode 0460: owner শুধু পড়বেন (r--), group পড়বে ও লিখবে (rw-), বাকিরা কিছু নয় (---).
  2. rahim লিখতে চান। প্রথম প্রশ্ন: UID 1001 কি owner? হ্যাঁ। তাই শুধু owner-এর বিট r-- দেখা হলো, w নেই → EACCES. rahim নিজে accounts group-এর সদস্য, আর group-এর w আছে — কিন্তু group-এর বিট দেখাই হয় না। এটিই পরীক্ষায় প্রিয় “owner-এর অধিকার group-এর চেয়ে কম” ঘটনা। (মালিক হিসেবে rahim অবশ্য chmod u+w করে নিজের অধিকার ফিরিয়ে আনতে পারেন — mode বদলানোর অধিকার owner-এর, rwx বিটের ওপর নির্ভর করে না।)
  3. karim লিখতে চান। UID 1002 ≠ 1001, owner নন। তাঁর group-তালিকায় accounts আছে, ফাইলের group-ও accounts → group-এর বিট rw- দেখা হলো, w আছে → অনুমতি.
  4. sumi পড়তে চান। Owner নন, group-ও মেলে না (তাঁর group sumi আর staff) → other-এর বিট ---, r নেই → EACCES.
  5. root পড়তে চান। Owner, group, other — কোনোটাই root-কে আটকায় না। Linux-এ প্রথমে সাধারণ নিয়মে যাচাই হয় (root এখানে other শ্রেণিতে পড়েন, ---), ব্যর্থ হলে kernel দেখে প্রসেসের কাছে CAP_DAC_OVERRIDE ক্ষমতা আছে কি না; UID 0-এর প্রসেসে সাধারণত থাকে → অনুমতি. একটি ব্যতিক্রম মনে রাখুন: কোনো শ্রেণিতেই x নেই এমন সাধারণ ফাইল root-ও চালাতে পারেন না। আর ACL থাকলে (অংশ ৮) group-ধাপে ACL-এর নিয়মও মেলানো হয়।

একটি ফাইল খুলতে শুধু ফাইলটির অনুমতিই যথেষ্ট নয় — path-এর প্রতিটি directory-তে x লাগে। পর্ব ৪২-এর namei stepper-এ দেখেছেন, /home/rahim/docs/notes.txt খুলতে kernel /, /home, /home/rahim, docs — চারটিতে x যাচাই করে, তারপর ফাইলে r. তাই home directory 700 হলে ভেতরের কোনো ফাইল 644 হলেও অন্য user সেটি পড়তে পারবেন না; প্রথম দরজাতেই আটকে যাবেন।

static int acl_permission_check(struct inode *inode, int mask)
{
    unsigned int mode = inode->i_mode;

    if (uid_eq(current_fsuid(), inode->i_uid)) {   /* 1. owner? only owner bits */
        mode >>= 6;
    } else {
        if (IS_POSIXACL(inode) && (mode & S_IRWXG)) {
            int error = check_acl(inode, mask);      /* an ACL, if any, decides here */
            if (error != -EAGAIN)
                return error;
        }
        if (in_group_p(inode->i_gid))                /* 2. group member? group bits */
            mode >>= 3;
        /* 3. otherwise the lowest three bits: other */
    }
    if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
        return 0;                                    /* every wanted bit is present */
    return -EACCES;    /* generic_permission() then tries CAP_DAC_OVERRIDE etc. */
}

লক্ষ্য করুন mode >>= 6 আর mode >>= 3: owner-এর তিনটি বিট ৬ ঘর ডানে সরালে সবচেয়ে নিচের তিন ঘরে আসে, group-এর ৩ ঘর সরালে — তারপর একই mask & ~mode পরীক্ষা।

Directory-র অনুমতি হাতে-কলমে — x, w আর sticky bit

অংশ ২-এর টেবিলটি এবার পরীক্ষা করে দেখা যাক। নিচের কোড একটি box directory বানিয়ে তার mode বারবার বদলায়, আর প্রতিবার কয়েকটি কাজ চেষ্টা করে। try ফাংশনটি কমান্ড সফল হলে OK, ব্যর্থ হলে kernel-এর দেওয়া কারণ ছাপে। আমরা সবাই একই user (owner), তাই এখানে owner-এর বিটই কাজ করছে — কিন্তু নিয়ম group আর other-এর জন্যও একই।

rm -rf dl; mkdir dl && cd dl
mkdir box && echo "hello" > box/note.txt
try() {                         # run a command, print OK or the reason it failed
  printf '  %-26s' "$1"; shift
  if out=$("$@" 2>&1); then echo "OK ${out//$'\n'/ }"
  else err=${out%%$'\n'*}; echo "DENIED: ${err##*: }"; fi
}
mode() { echo "== box is $(stat -c '%A' box) ($1)"; }
chmod 600 box; mode "r and w, but no x"
try "ls box   (names only)" ls box
try "ls -l box (needs inodes)" ls -l box
try "cat box/note.txt" cat box/note.txt
try "cd box" cd box
chmod 100 box; mode "x only: traverse"
try "ls box" ls box
try "cat box/note.txt (known)" cat box/note.txt
chmod 200 box; mode "w without x"
try "touch box/new" touch box/new
chmod 300 box; mode "w and x"
try "touch box/new" touch box/new
chmod 500 box; mode "r and x, no w"
try "rm box/new" rm -f box/new
chmod 700 box; chmod 444 box/note.txt
echo "== note.txt is $(stat -c '%A' box/note.txt), box is $(stat -c '%A' box)"
try "rm read-only note.txt" rm -f box/note.txt
mkdir pub; chmod 1777 pub; touch pub/mine
echo "== pub is $(stat -c '%A' pub) (sticky, like /tmp)"
try "rm my own file in pub" rm pub/mine
chmod -R u+rwx box

আসল রানের আউটপুট:

== box is drw------- (r and w, but no x)
  ls box   (names only)     OK note.txt
  ls -l box (needs inodes)  DENIED: Permission denied
  cat box/note.txt          DENIED: Permission denied
  cd box                    DENIED: Permission denied
== box is d--x------ (x only: traverse)
  ls box                    DENIED: Permission denied
  cat box/note.txt (known)  OK hello
== box is d-w------- (w without x)
  touch box/new             DENIED: Permission denied
== box is d-wx------ (w and x)
  touch box/new             OK
== box is dr-x------ (r and x, no w)
  rm box/new                DENIED: Permission denied
== note.txt is -r--r--r--, box is drwx------
  rm read-only note.txt     OK
== pub is drwxrwxrwt (sticky, like /tmp)
  rm my own file in pub     OK 

লাইন ধরে: (১) r আছে, x নেই — নামের তালিকা পড়া গেল (note.txt), কিন্তু ls -l-কে প্রতিটি নামের inode দেখতে হয়, সেটি x ছাড়া হয় না; ভেতরের ফাইল পড়া আর cd-ও বন্ধ। (২) শুধু x — উল্টো ছবি: তালিকা দেখা যায় না, কিন্তু নাম জানা থাকলে ফাইল পড়া যায় (hello). (৩) w আছে, x নেই — ফাইল তৈরি হলো না; w একা অর্থহীন। (৪) w আর x — তৈরি হলো। (৫) w নেই — নিজের ফাইলও মোছা গেল না। (৬) সবচেয়ে শিক্ষণীয়: note.txt নিজে -r--r--r--, কেউ লিখতে পারে না, তবু মুছে গেল — কারণ মোছা directory-র কাজ, আর box-এ w ও x আছে। (৭) Sticky directory-তে নিজের ফাইল মোছা যায়।

যা এখানে দেখানো যায়নি: sticky bit-এর আসল কাজ অন্যের ফাইলে। এই sandbox-এ একজনই user, তাই নিচের মতো দুই-user-এর পরীক্ষা করতে নিজের Linux মেশিনে দুটি account লাগবে। pub-এর মতো drwxrwxrwt directory-তে karim-এর ফাইল sumi মুছতে চাইলে পাবেন rm: cannot remove 'pub/karim.txt': Operation not permitted; sticky bit না থাকলে (777) একই কমান্ড সফল হতো। Sticky directory-তে একটি ফাইল মুছতে বা নাম বদলাতে পারেন শুধু ফাইলের owner, directory-র owner, আর root. আরেকটি মজার বিষয়: Linux ৩.৬ থেকে fs.protected_symlinks আর ৪.১৯ থেকে fs.protected_regular নামের সুরক্ষা আছে, যা sticky, সবার-লেখা directory-তে অন্যের symlink অনুসরণ বা অন্যের ফাইল O_CREAT দিয়ে খোলা আটকায় — /tmp-এর পুরোনো ধরনের আক্রমণ বন্ধ করতে। এই sandbox-এ দুটোই চালু (মান যথাক্রমে ১ আর ২)।

৫ · umask — নতুন ফাইলের অনুমতি কে ঠিক করে

নতুন ফাইল তৈরির সময় প্রোগ্রাম open(path, O_CREAT, mode)-এ একটি mode চায়: সাধারণ ফাইলের জন্য প্রায় সব প্রোগ্রাম (editor, touch, shell redirection) চায় 0666, directory আর compiler-এর বানানো প্রোগ্রামের জন্য 0777. কিন্তু kernel সেটি হুবহু বসায় না — প্রসেসের umask-এ যে বিটগুলো ১, সেগুলো মুছে দেয়:

নতুন mode = চাওয়া mode & ~umask
ফাইল: 0666 & ~umask · directory: 0777 & ~umask

অর্থাৎ umask হলো একটি “ছাঁকনি” — যে বিট umask-এ আছে, নতুন ফাইলে তা থাকবে না। umask প্রসেসের একটি বৈশিষ্ট্য, child প্রসেস তা উত্তরাধিকারসূত্রে পায় (পর্ব ১০), আর umask কমান্ড shell-এর নিজেরটি দেখায় বা বদলায়। হিসাবটি binary-তে করলেই পরিষ্কার:

তিন বিটের দল: owner │ group │ other
umask
~umask
চাওয়া mode
AND-এর ফল
ls -l-এ
  1. umask 022 binary-তে। প্রতিটি octal অঙ্ক তিন বিট: ০ → 000, ২ → 010, ২ → 010. অর্থাৎ group আর other-এর w বিট (মাঝের বিট) ১ — “group আর other কখনো লিখতে পারবে না।” অনেক distro-তে সাধারণ user আর systemd সার্ভিসের ডিফল্ট এটিই (কিছু distro সাধারণ user-কে 002 দেয়)।
  2. ~umask — উল্টে দেওয়া। প্রতিটি বিট উল্টালে 111 │ 101 │ 101, octal-এ 755. এটিই “যা রাখা হবে” তার মুখোশ। (এখানে শুধু নিচের ৯টি বিট দেখানো হচ্ছে।)
  3. নতুন ফাইল। প্রোগ্রাম চাইল 0666 = 110 │ 110 │ 110. বিট ধরে AND: 110 & 111 = 110, 110 & 101 = 100, 110 & 101 = 100 → 110 │ 100 │ 100 = 644, -rw-r--r--. লক্ষ্য করুন, ফাইলে x আসেনি — কারণ চাওয়া mode-এই x ছিল না, umask কখনো বিট যোগ করে না।
  4. নতুন directory. mkdir চায় 0777 = 111 │ 111 │ 111; AND 111 │ 101 │ 101 → 755, drwxr-xr-x. Directory-তে x দরকার (traverse), তাই mkdir 0777 চায়।
  5. umask 027 — ফাইল। ২ → 010, ৭ → 111: group-এর w আর other-এর সব বিট মোছা হবে। ~027 = 111 │ 101 │ 000 (750). 0666-এর সাথে AND → 110 │ 100 │ 000 = 640, -rw-r-----. সার্ভারে সংবেদনশীল ডেটার জন্য জনপ্রিয় umask — group পড়বে, বাইরের কেউ কিছুই না।
  6. umask 027 — directory. 0777 & 750 = 750, drwxr-x---. মিলিয়ে নিন: 022 → 644/755, 027 → 640/750.
  7. ফাঁদ: বিয়োগ নয়। অনেকে শেখেন “666 থেকে umask বিয়োগ করুন।” umask 022-এ বিয়োগেও ঠিক উত্তর আসে, কারণ সেখানে umask-এর প্রতিটি ১-বিট চাওয়া mode-এ ১ ছিল (directory-র 0777-এ তো সব বিটই ১)। কিন্তু 027-এ ফাইলের জন্য 666 − 027 করতে গেলে other-এর ঘরে ৬ − ৭ — অর্থহীন। আর umask 033 ধরুন: বিয়োগে 666 − 033 = 633 (-rw--wx-wx) — x যোগ হয়ে গেল, যা অসম্ভব! সঠিক: ~033 = 111 │ 100 │ 100, 0666-এর সাথে AND = 110 │ 100 │ 100 = 644. সবসময় বিট ধরে AND করুন।

এবার একই হিসাব আসল kernel-এ — কয়েকটি umask-এ ফাইল আর directory বানিয়ে:

rm -rf um && mkdir um && cd um
echo "shell's umask now: $(umask)  (symbolic: $(umask -S))"
for m in 022 027 077 002; do
  ( umask "$m"                       # ( ) = subshell, so the change stays inside
    touch "f$m"; mkdir "d$m"
    printf 'umask %s -> new file %s   new dir %s\n' "$m" \
      "$(stat -c '%a %A' "f$m")" "$(stat -c '%a %A' "d$m")" )
done
echo "-- umask filters only at creation; a later chmod is not filtered:"
( umask 077; touch g; stat -c 'created: %a %A' g; chmod 644 g; stat -c 'chmod 644: %a %A' g )
echo "-- a program may ask for fewer bits (gcc asks 0777 for a.out, an editor 0666):"
( umask 022; printf 'int main(void){return 0;}\n' > t.c; gcc t.c -o t; stat -c '%a %A %n' t.c t )
echo "-- umask is inherited by child processes:"
( umask 027; bash -c 'echo "child bash sees umask $(umask)"' )

আসল রানের আউটপুট:

shell's umask now: 0022  (symbolic: u=rwx,g=rx,o=rx)
umask 022 -> new file 644 -rw-r--r--   new dir 755 drwxr-xr-x
umask 027 -> new file 640 -rw-r-----   new dir 750 drwxr-x---
umask 077 -> new file 600 -rw-------   new dir 700 drwx------
umask 002 -> new file 664 -rw-rw-r--   new dir 775 drwxrwxr-x
-- umask filters only at creation; a later chmod is not filtered:
created: 600 -rw-------
chmod 644: 644 -rw-r--r--
-- a program may ask for fewer bits (gcc asks 0777 for a.out, an editor 0666):
644 -rw-r--r-- t.c
755 -rwxr-xr-x t
-- umask is inherited by child processes:
child bash sees umask 0027

(১) Sandbox-এর shell-এর umask 0022; umask -S একই জিনিস উল্টো দিক থেকে বলে — “যা রাখা হবে”: u=rwx,g=rx,o=rx. (২) চারটি লাইন stepper-এর হিসাব হুবহু মিলিয়ে দিল: 022 → 644/755, 027 → 640/750, আর 077 → 600/700 — “শুধু আমি”, SSH key বা ব্যক্তিগত নোটের জন্য। 002 → 664/775 দলগত কাজের জন্য, যেখানে group-এর সবাই লিখবেন। (৩) umask শুধু তৈরির মুহূর্তে কাজ করে; পরে chmod 644 দিলে umask 077 থাকলেও 644-ই হয়। (৪) একই umask 022-এ t.c পেল 644 আর gcc-এর বানানো প্রোগ্রাম t পেল 755 — কারণ linker 0777 চায়, editor বা redirection 0666. (৫) ( ) subshell-এ বদলানো umask সেখানেই থাকে, কিন্তু তার child bash সেটি পেল — umask প্রসেসের উত্তরাধিকার।

umask স্থায়ীভাবে বদলাতে চাইলে নিজের ~/.bashrc বা ~/.profile-এ umask 027 লিখুন; পুরো সিস্টেমের ডিফল্ট সাধারণত /etc/login.defs-এর UMASK বা PAM-এর pam_umask ঠিক করে (distro-ভেদে আলাদা)। systemd সার্ভিসের জন্য unit ফাইলে UMask=0027. Directory-তে ডিফল্ট ACL (অংশ ৮) থাকলে নতুন ফাইলের অনুমতি সেখান থেকে আসে, তখন umask-এর ভূমিকা বদলে যায়।

৬ · বিশেষ বিট — setuid, setgid, sticky আর তিন রকম UID

একটি ধাঁধা দিয়ে শুরু করি। পাসওয়ার্ড থাকে /etc/shadow-এ, যা শুধু root লিখতে পারে। অথচ যেকোনো সাধারণ user passwd কমান্ড দিয়ে নিজের পাসওয়ার্ড বদলাতে পারেন। কীভাবে? উত্তর হলো setuid বিট: /usr/bin/passwd ফাইলটির owner root, আর তার mode -rwsr-xr-x (4755). যে-ই এটি চালান, প্রোগ্রামটি চলার সময় ফাইলের মালিকের — অর্থাৎ root-এর — ক্ষমতা পায়।

এটি বুঝতে জানতে হবে, প্রতিটি প্রসেসের একটি নয়, তিনটি UID থাকে (GID-এরও তিনটি):

  • Real UID — কে আসলে প্রসেসটি চালিয়েছেন। getuid() এটি দেয়।
  • Effective UID — permission-যাচাইয়ে kernel কোনটি দেখবে। সাধারণত real-এর সমান; setuid প্রোগ্রাম exec করলে এটি ফাইলের owner হয়ে যায়। geteuid().
  • Saved set-user-ID — exec-এর সময় effective UID-এর একটি কপি। প্রোগ্রাম সাময়িকভাবে ক্ষমতা ছেড়ে (seteuid(real)) পরে আবার ফিরে পেতে পারে, কারণ saved-এ পুরোনো মানটি আছে।

Linux-এ চতুর্থ একটি filesystem UID-ও আছে (সাধারণত effective-এর সমান) — /proc/self/status-এর Uid: লাইনে এই চারটি ক্রমে দেখা যায়: real, effective, saved, filesystem. এবার passwd চালানোর সময় তিনটি UID কীভাবে বদলায়, দেখুন:

rahim (UID 1000) তাঁর পাসওয়ার্ড বদলাচ্ছেন · ফাইল: -rwsr-xr-x root root /usr/bin/passwd
এখন চলছে
real UID
effective UID
saved UID
/etc/shadow লেখা যাবে?
  1. শুরু। rahim-এর shell-এ তিনটি UID-ই 1000. /etc/shadow (-rw-r----- root shadow) তাঁর জন্য other শ্রেণি, ---. সরাসরি cat /etc/shadow দিলে Permission denied.
  2. execve("/usr/bin/passwd"). Kernel দেখে ফাইলে setuid বিট আছে আর owner UID 0. তাই নতুন প্রোগ্রামের effective UID = 0, আর saved UID-এ সেই 0 কপি হয়। Real UID বদলায় না — 1000-ই থাকে। (ফাইলটি nosuid option দিয়ে mount করা জায়গায় থাকলে kernel বিটটি উপেক্ষা করত।)
  3. কার পাসওয়ার্ড বদলাবে? প্রোগ্রাম getuid() ডেকে real UID 1000 পায়, তাই শুধু rahim-এর account-এ কাজ করবে। অন্য কারও নাম দিলে (passwd karim) সে নিজেই প্রত্যাখ্যান করে, কারণ real UID 0 নয়। আর পুরোনো পাসওয়ার্ড জিজ্ঞেস করে PAM-এর মাধ্যমে যাচাই করে। পুরো নিরাপত্তা এই প্রোগ্রামের সতর্ক কোডের ওপর নির্ভর করে — এজন্যই setuid প্রোগ্রাম বিপজ্জনক।
  4. সাময়িকভাবে ক্ষমতা ছাড়া। ভালোভাবে লেখা setuid প্রোগ্রাম যে কাজে root লাগে না (যেমন ইনপুট পড়া), তার আগে seteuid(1000) করে effective UID নামিয়ে আনতে পারে — saved-এ 0 থেকে যায়। এই কৌশলটি সাধারণ উদাহরণ হিসেবে দেখানো হলো; passwd-এর কোন সংস্করণ ঠিক কোথায় কী করে, তা implementation-ভেদে আলাদা।
  5. ক্ষমতা ফিরিয়ে লেখা। seteuid(0) অনুমোদিত, কারণ 0 saved UID-এ আছে — এজন্যই saved UID দরকার। নতুন hash লেখা হয় (সাধারণত একটি অস্থায়ী ফাইলে লিখে তারপর rename করে, যাতে মাঝপথে crash হলে /etc/shadow আধখানা না থাকে — পর্ব ৪৪-এর atomic rename).
  6. শেষ। passwd প্রসেস শেষ, shell আবার আগের মতো 1000/1000/1000. ক্ষমতা শুধু ঐ প্রোগ্রামের জীবনকালে, শুধু তার নিজের কোডের ভেতরে ছিল।

setgid — ফাইলে আর directory-তে দুই কাজ

Setgid বিট (২০০০) ফাইলে setuid-এর মতোই, শুধু group-এর জন্য: প্রোগ্রাম ফাইলের group-এর effective GID নিয়ে চলে। নিচের আউটপুটে দেখবেন unix_chkpwd হলো -rwxr-sr-x root:shadow — সে root নয়, শুধু shadow group-এর ক্ষমতায় চলে, তাই /etc/shadow পড়তে পারে কিন্তু লিখতে পারে না। পূর্ণ root না দিয়ে শুধু দরকারি অংশটুকু দেওয়া — least privilege-এর সুন্দর উদাহরণ।

Directory-তে setgid-এর অর্থ সম্পূর্ণ আলাদা এবং অত্যন্ত কাজের: ভেতরে নতুন তৈরি প্রতিটি ফাইল তৈরিকারীর প্রধান group না পেয়ে directory-র group পায়, আর নতুন subdirectory-ও setgid বিট পায়। ধরুন একটি সফটওয়্যার ফার্মে /srv/project ফোল্ডারটি dev group-এর, mode 2775 (বা গোপন রাখতে 2770). rahim যে ফাইলই বানান, তার group হবে dev, তাই দলের সবাই পড়তে পারবেন; সাথে umask 002 হলে লিখতেও পারবেন। Setgid না থাকলে ফাইলটি rahim-এর ব্যক্তিগত group পেত, আর অন্যরা বারবার “Permission denied” দেখতেন।

sticky bit — shared directory-র রক্ষাকবচ

শুরুর দিকের Unix-এ sticky bit প্রোগ্রাম ফাইলে বসত: “এই প্রোগ্রামের কোড চলার পরও swap-এ রেখে দেওয়া হোক”, যাতে বারবার চালানো প্রোগ্রাম দ্রুত খোলে — নামটি সেখান থেকে। আধুনিক Linux ফাইলে এই বিট উপেক্ষা করে। Directory-তে এর অর্থ অংশ ৪-এ দেখেছেন: ভেতরের ফাইল মুছতে বা নাম বদলাতে পারবেন শুধু ফাইলের owner, directory-র owner বা root. /tmp আর /var/tmp এজন্যই 1777.

নিজের পরিচয় দেখা আর setuid প্রোগ্রামের নিরীক্ষা

এবার এই পাতার sandbox-এ নিজের পরিচয়, account ফাইলগুলোর অনুমতি, setuid-এর কাজ আর একটি প্রতিরক্ষামূলক নিরীক্ষা — সিস্টেমে কোন কোন setuid/setgid প্রোগ্রাম আছে — একসাথে দেখা যাক:

echo "== who am I?"; id; echo "whoami: $(whoami)   groups: $(groups)"
echo "== this process: Uid/Gid = real effective saved filesystem"
grep -E '^(Uid|Gid):' /proc/self/status
echo "== my line in /etc/passwd (name:x:UID:GID:comment:home:shell)"
grep "^$(whoami):" /etc/passwd
echo "== who may read the account files?"
stat -c '%A %U:%G %n' /etc/passwd /etc/group /etc/shadow
if cat /etc/shadow > /dev/null 2>&1; then echo "shadow is readable?! fix it"
else echo "cat /etc/shadow -> Permission denied (as it should be)"; fi
echo "== yet the setuid-root passwd program may read it on my behalf"
stat -c '%A %U %n' /usr/bin/passwd
passwd -S "$(whoami)"
echo "== audit: setuid/setgid programs on this system"
find /usr/bin /usr/sbin -xdev -type f \( -perm -4000 -o -perm -2000 \) 2>/dev/null |
  sort | xargs stat -c '%A %U:%G %n'
echo "== can I use sudo?"
if command -v sudo > /dev/null 2>&1; then sudo -n -l 2>&1 | head -5
else echo "sudo is not installed in this sandbox - nothing to elevate to"; fi
echo "== my Linux capabilities (hex bitmask; 0 = none):"
grep -E '^Cap(Prm|Eff)' /proc/self/status

আসল রানের আউটপুট:

== who am I?
uid=999(wandbox) gid=999(wandbox) groups=999(wandbox)
whoami: wandbox   groups: wandbox
== this process: Uid/Gid = real effective saved filesystem
Uid:	999	999	999	999
Gid:	999	999	999	999
== my line in /etc/passwd (name:x:UID:GID:comment:home:shell)
wandbox:x:999:999::/home/wandbox:/bin/sh
== who may read the account files?
-rw-r--r-- root:root /etc/passwd
-rw-r--r-- root:root /etc/group
-rw-r----- root:shadow /etc/shadow
cat /etc/shadow -> Permission denied (as it should be)
== yet the setuid-root passwd program may read it on my behalf
-rwsr-xr-x root /usr/bin/passwd
wandbox L 2025-12-24 -1 -1 -1 -1
== audit: setuid/setgid programs on this system
-rwxr-sr-x root:shadow /usr/bin/chage
-rwsr-xr-x root:root /usr/bin/chfn
-rwsr-xr-x root:root /usr/bin/chsh
-rwxr-sr-x root:shadow /usr/bin/expiry
-rwsr-xr-x root:root /usr/bin/gpasswd
-rwsr-xr-x root:root /usr/bin/mount
-rwsr-xr-x root:root /usr/bin/newgrp
-rwsr-xr-x root:root /usr/bin/passwd
-rwsr-xr-x root:root /usr/bin/su
-rwsr-xr-x root:root /usr/bin/umount
-rwxr-sr-x root:shadow /usr/sbin/pam_extrausers_chkpwd
-rwxr-sr-x root:shadow /usr/sbin/unix_chkpwd
== can I use sudo?
sudo is not installed in this sandbox - nothing to elevate to
== my Linux capabilities (hex bitmask; 0 = none):
CapPrm:	0000000000000000
CapEff:	0000000000000000

(১) এই sandbox-এর user wandbox, UID 999 — ১০০০-এর নিচে, অর্থাৎ একটি system ধরনের account, একটিই group. (২) Uid: লাইনে চারটি সংখ্যাই 999: real = effective = saved = filesystem — কোনো setuid প্রোগ্রাম নয়, সাধারণ প্রসেস। (৩) /etc/passwd আর /etc/group সবার পড়ার মতো (644), /etc/shadow 640, owner root, group shadow — আমরা other, তাই ---, পড়া নিষেধ। (৪) তবু passwd -S আমাদের account-এর অবস্থা দেখাতে পারল: L মানে পাসওয়ার্ড locked (পাসওয়ার্ড দিয়ে login বন্ধ), তারপর শেষ বদলের তারিখ আর মেয়াদের ঘরগুলো। এই তথ্য আছে শুধু /etc/shadow-এ — অর্থাৎ setuid-root প্রোগ্রামটি আমাদের হয়ে ফাইলটি পড়েছে, কিন্তু শুধু তার নিজের সংকীর্ণ কাজের জন্য। (৫) নিরীক্ষায় ১২টি প্রোগ্রাম: ৮টি setuid-root (passwd, su, mount …), আর ৪টি শুধু setgid shadow — প্রতিটি এক একটি সম্ভাব্য দুর্বল জায়গা, তাই তালিকা ছোট রাখা আর চেনা থাকা জরুরি। (৬) sudo নেই, আর capability-র bitmask শূন্য — এই প্রসেসের কোনো বিশেষ ক্ষমতা নেই। (UID-এর সংখ্যা, তারিখ আর তালিকা অন্য মেশিনে আলাদা হবে।)

setuid কেন ঝুঁকিপূর্ণ, আর কীভাবে পাহারা দেবেন

একটি setuid-root প্রোগ্রাম মানে সাধারণ user-এর দেওয়া ইনপুট — আর্গুমেন্ট, environment variable, ফাইলের নাম — root-এর ক্ষমতায় চলা কোডে ঢুকছে। সেই কোডে একটি বাগ মানে সাধারণ user root হয়ে যাওয়ার পথ। ইতিহাসে এমন বহু ঘটনা আছে; যেমন ২০২২ সালের শুরুতে প্রকাশিত “PwnKit” (CVE-2021-4034) — polkit-এর setuid প্রোগ্রাম pkexec-এ একটি ত্রুটি, যা বহু বছর ধরে প্রায় সব বড় distro-তে ছিল। শিক্ষা একটাই: setuid প্রোগ্রাম যত কম, আক্রমণের জায়গা তত কম। প্রতিরক্ষার অভ্যাসগুলো:

৭ · sudo আর su — কখন, কীভাবে, কতটুকু ক্ষমতা

প্রশাসনের কাজ — প্যাকেজ ইনস্টল, সার্ভিস restart, অন্যের ফাইল ঠিক করা — root ছাড়া হয় না। দুটি পথ:

🔑 su (substitute user)

su: su - লিখে লক্ষ্য user-এর (সাধারণত root-এর) পাসওয়ার্ড দিলে একটি পুরো root shell খোলে। একাধিক প্রশাসক থাকলে সবাইকে root-এর পাসওয়ার্ড জানতে হয়, আর লগে থাকে শুধু কে কখন root হলেন; এরপর root shell-এ কোন কমান্ড দিলেন, তা আলাদা করা কঠিন।

সব ক্ষমতা, পুরো সময়

🛡️ sudo

sudo কমান্ড লিখে নিজের পাসওয়ার্ড দিলে শুধু সেই একটি কমান্ড root হিসেবে চলে — যদি sudoers নীতি অনুমতি দেয়। প্রতিটি ব্যবহার লগ হয়: কে, কখন, কোন directory থেকে, কোন কমান্ড।

নির্দিষ্ট ক্ষমতা, লগসহ

Ubuntu-র মতো অনেক distro-তে root-এর কোনো ব্যবহারযোগ্য পাসওয়ার্ডই থাকে না; প্রথম user sudo group-এ থাকেন (Fedora/RHEL-এ সমতুল্য group wheel). sudo পাসওয়ার্ড একবার যাচাই করার পর কিছুক্ষণ মনে রাখে (মূল sudo-র ডিফল্ট ৫ মিনিট; কিছু distro-তে বেশি, যেমন Ubuntu-তে ১৫ মিনিট বলে প্রচলিত; নীতিতে timestamp_timeout দিয়ে বদলানো যায়)। sudo -l দেখায় আপনাকে কী কী অনুমতি দেওয়া আছে — অচেনা সার্ভারে ঢুকে প্রথমেই এটি দেখা ভালো অভ্যাস।

sudoers — নীতি লেখা, visudo দিয়ে

নীতি থাকে /etc/sudoers আর /etc/sudoers.d/-এর ফাইলগুলোতে। এগুলো কখনো সাধারণ editor-এ খুলবেন না — সবসময় visudo (বা visudo -f /etc/sudoers.d/ফাইল)। visudo ফাইলটি lock করে, সংরক্ষণের আগে ব্যাকরণ যাচাই করে, আর ভুল থাকলে সতর্ক করে — কারণ sudoers-এ একটি ভুল মানে কেউ আর sudo ব্যবহার করতে পারবেন না, আর root পাসওয়ার্ড না থাকলে নিজের সার্ভার থেকে নিজেই বাইরে।

# Format:  WHO   HOST=(RUN-AS)   COMMANDS
# Full admin (on Ubuntu this line already exists for the sudo group):
%sudo      ALL=(ALL:ALL) ALL

# Least privilege: the web team may only restart or reload nginx, nothing else.
%webteam   ALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx

# A deploy account may run exactly one script as the app user (not root), no password.
deploy     ALL=(appuser) NOPASSWD: /opt/app/bin/deploy.sh

# Let editors open the config safely: sudoedit runs the editor as YOU on a temp copy.
%webteam   ALL=(root) sudoedit /etc/nginx/sites-available/*

নিয়ম লেখার সময় তিনটি ফাঁদ মনে রাখুন। (১) কমান্ডের পুরো path দিন (/usr/bin/systemctl), শুধু নাম নয়। (২) Shell-এ বেরোনো যায় এমন প্রোগ্রাম — editor (vim, nano), pager (less), find, tar, script-ভাষার interpreter — sudo-তে দিলে কার্যত পুরো root দেওয়া হয়ে যায়, কারণ এগুলোর ভেতর থেকে অন্য কমান্ড চালানো যায়; ফাইল সম্পাদনার জন্য sudoedit ব্যবহার করুন। (৩) Wildcard আর লেখা-যায় এমন script সাবধানে: deploy.sh যদি deploy user নিজেই বদলাতে পারেন, তাহলে নিয়মটি “যেকোনো কিছু চালানো যাবে” হয়ে গেল — script-টি root-এর মালিকানায়, 755 রাখুন। এবার দুটি নমুনা আউটপুট:

$ sudo -l
User rahim may run the following commands on web01:
    (root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx
    (root) sudoedit /etc/nginx/sites-available/*

$ sudo systemctl restart nginx          # allowed, and logged
$ sudo bash
Sorry, user rahim is not allowed to execute '/usr/bin/bash' as root on web01.

$ sudo grep sudo /var/log/auth.log | tail -2      # (RHEL: /var/log/secure, or journalctl)
... sudo:    rahim : TTY=pts/0 ; PWD=/home/rahim ; USER=root ; COMMAND=/usr/bin/systemctl restart nginx
... sudo:    rahim : command not allowed ; TTY=pts/0 ; PWD=/home/rahim ; USER=root ; COMMAND=/usr/bin/bash

কেন সব কাজ root হিসেবে নয়

“প্রতিবার sudo লেখা বিরক্তিকর, root হয়েই থাকি” — এই অভ্যাসের তিনটি দাম। প্রথমত, ভুলের ক্ষতি অসীম: একটি ভুল জায়গায় স্পেস দেওয়া rm -rf সাধারণ user-এ নিজের কিছু ফাইল মোছে, root-এ পুরো সিস্টেম। দ্বিতীয়ত, প্রতিটি প্রোগ্রাম root-এর ক্ষমতা পায়: ব্রাউজার, ইন্টারনেট থেকে নামানো script, AI-এর দেওয়া কমান্ড — যেকোনো একটিতে ক্ষতিকর কিছু থাকলে সে আর কোনো বাধা পায় না। তৃতীয়ত, জবাবদিহি হারায়: লগে শুধু “root” দেখা যায়। এজন্যই নীতিটির নাম least privilege — প্রতিটি মানুষ ও প্রোগ্রাম ঠিক ততটুকু ক্ষমতা পাবে, যতটুকু তার কাজের জন্য দরকার, আর ঠিক ততক্ষণ।

৮ · Root-কে টুকরো করা, ACL আর অন্য OS-এর মডেল

Linux capability — পুরো মাস্টার চাবি নয়, একটি চাবি

পুরোনো Unix-এ ক্ষমতা ছিল দুই রকম: UID 0 হলে সব, না হলে প্রায় কিছুই নয়। Linux ২.২ (১৯৯৯) থেকে root-এর ক্ষমতাকে কয়েক ডজন আলাদা টুকরোয় ভাগ করেছে, যাদের বলে Linux capability: CAP_NET_BIND_SERVICE (১০২৪-এর নিচের port খোলা), CAP_CHOWN, CAP_DAC_OVERRIDE (ফাইলের অনুমতি উপেক্ষা), CAP_SYS_ADMIN (অনেক কিছুর মিশ্রণ — প্রায় root-এর সমান, এড়িয়ে চলুন) ইত্যাদি। নাম এক হলেও এটি পর্ব ৪৬-এর তাত্ত্বিক “capability list” (প্রতিটি বস্তুর জন্য টিকিট) থেকে আলাদা জিনিস — Linux-এরটি আসলে root-এর বিশেষ অধিকারের ভাগ।

সবচেয়ে পরিচিত প্রয়োজন: একটি Node.js বা Go ওয়েব সার্ভারকে port 80-এ চালানো। Linux-এ ১০২৪-এর নিচের port খুলতে বিশেষ অধিকার লাগে, তাই অনেকে পুরো সার্ভারটিই root হিসেবে চালান — তখন সার্ভারের একটি বাগ মানে পুরো মেশিন। নিরাপদ বিকল্পগুলো:

$ sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myserver
$ getcap /usr/local/bin/myserver
/usr/local/bin/myserver cap_net_bind_service=ep
# now an ordinary user (e.g. "web") can run it and bind port 80 - nothing more

# with systemd, prefer giving the capability to the service instead of the file:
#   [Service]
#   User=web
#   AmbientCapabilities=CAP_NET_BIND_SERVICE
#   CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#   NoNewPrivileges=yes

ফাইলের capability থাকে ফাইলের extended attribute-এ, আর getcap -r / দিয়ে setuid-এর মতোই নিরীক্ষা করা যায় (এই পাতার sandbox-এ getcap -r /usr/bin /usr/sbin কিছুই দেখায়নি)। আরেকটি বিকল্প হলো reverse proxy (nginx port 80-এ, আপনার অ্যাপ 8080-এ), বা net.ipv4.ip_unprivileged_port_start sysctl দিয়ে সীমাটিই নামানো। Capability তত্ত্বের সাথে কীভাবে মেলে, তা পর্ব ৪৬-এ; আর seccomp, SELinux দিয়ে প্রোগ্রামকে আরও বেঁধে রাখার কথা পর্ব ৪৯-এ।

POSIX ACL — তিন শ্রেণির বাইরে একজনকে অনুমতি

তিন শ্রেণির মডেলের সীমা: ফাইলটি accounts group-এর, কিন্তু অডিট বিভাগের শুধু sumi-কে পড়ার অনুমতি দিতে চান — sumi-কে accounts-এ ঢোকালে তিনি সব ফাইলে লেখার অধিকার পেয়ে যাবেন। সমাধান ACL (access control list), পর্ব ৪৬-এর access matrix-এর “কলাম” ধরে রাখা রূপ:

$ setfacl -m u:sumi:r salary.xlsx        # one extra user, read only
$ ls -l salary.xlsx
-rw-rw----+ 1 rahim accounts 18230 Oct 26 10:02 salary.xlsx     # "+" = an ACL exists
$ getfacl salary.xlsx
# file: salary.xlsx
# owner: rahim
# group: accounts
user::rw-
user:sumi:r--
group::rw-
mask::rw-
other::---
$ setfacl -d -m g:dev:rwX /srv/project   # default ACL: inherited by new files

ACL থাকলে ls -l-এর শেষে + চিহ্ন আসে — এটি দেখলে মনে রাখবেন, ৯টি বিটই পুরো গল্প নয়। mask হলো নামধারী user আর group-এর সর্বোচ্চ সীমা, আর ACL-যুক্ত ফাইলে chmod g=… আসলে mask বদলায়। ACL বেশিরভাগ Linux file system (ext4, XFS, Btrfs) সমর্থন করে; ভেতরের তত্ত্ব আর capability-র সাথে তুলনা পর্ব ৪৬-এ।

Windows আর macOS-এর সাথে তুলনা

Windows-এর মডেল শুরু থেকেই ভিন্ন। NTFS-এর প্রতিটি ফাইল ও ফোল্ডারে একটি পূর্ণ ACL (DACL) থাকে: অনেকগুলো entry (ACE), প্রতিটিতে একটি user বা group-এর পরিচয় (SID, যেমন S-1-5-32-544 = Administrators) আর অনুমতি — Full control, Modify, Read & execute ইত্যাদি, অনুমতি দেওয়া (Allow) বা স্পষ্টভাবে নিষেধ (Deny). মা-ফোল্ডার থেকে অনুমতি উত্তরাধিকারসূত্রে আসে। অর্থাৎ Linux-এর ৯ বিট + ঐচ্ছিক ACL-এর বদলে Windows-এ ACL-ই প্রধান মডেল।

PS C:\> icacls C:\Data\salary.xlsx
C:\Data\salary.xlsx BUILTIN\Administrators:(I)(F)
                    NT AUTHORITY\SYSTEM:(I)(F)
                    DHAKA-PC\rahim:(I)(M)
                    BUILTIN\Users:(I)(RX)
Successfully processed 1 files; Failed processing 0 files
# (I) = inherited from the parent folder, F = full, M = modify, RX = read & execute

Root-এর সমতুল্য Administrators group, আর তার চেয়েও বেশি ক্ষমতার SYSTEM account. sudo-র কাছাকাছি ধারণা হলো UAC (User Account Control, Windows Vista থেকে): Administrators-এর সদস্য হলেও আপনার প্রোগ্রাম সাধারণত একটি “ছাঁটা” token নিয়ে, সাধারণ user-এর অধিকারে চলে; কোনো কাজে পূর্ণ অধিকার লাগলে পর্দা অন্ধকার করে “Do you want to allow this app to make changes?” জিজ্ঞাসা আসে, তারপর শুধু সেই প্রোগ্রামটি পূর্ণ token পায়। পার্থক্যও আছে: sudo একটি স্পষ্ট নীতি-ফাইল আর প্রতি-কমান্ড লগ দিয়ে চলে, UAC মূলত একটি সম্মতির ধাপ, আর Microsoft নিজেও UAC-কে কঠোর নিরাপত্তা-সীমানা হিসেবে নয় বরং সুবিধা ও সতর্কতার ব্যবস্থা হিসেবে বর্ণনা করেছে বলে জানা যায়। Windows-এ setuid-এর সরাসরি সমতুল্য নেই; বিশেষ ক্ষমতার কাজ সাধারণত একটি সার্ভিস (SYSTEM হিসেবে চলে) করে দেয়।

macOS Unix-ভিত্তিক, তাই ls -l, chmod, setuid, sudo — সব এই পর্বের মতোই, সাথে NFSv4 ধাঁচের ACL (ls -le দিয়ে দেখা যায়)। তার ওপর System Integrity Protection (SIP) নামের একটি স্তর আছে, যা কিছু সিস্টেম ফোল্ডার root-এর কাছ থেকেও রক্ষা করে — অর্থাৎ সেখানে “root মানেই সব” আর সত্য নয়, যে ধারণা পর্ব ৪৯-এর mandatory access control-এর সাথে মেলে।

আরও গভীরে: Linux-এ permission-যাচাই fs/namei.c-এর generic_permission()-এ হয়: অংশ ৪-এর acl_permission_check() ব্যর্থ হলে সে CAP_DAC_READ_SEARCH (পড়া আর directory traverse) আর CAP_DAC_OVERRIDE দেখে, আর x-এর জন্য অন্তত একটি x বিট থাকার শর্তও সেখানেই। UID-গুলো kernel-এ struct cred-এ থাকে (uid, euid, suid, fsuid আর capability-র সেট), যা copy-on-write ধাঁচে বদলায় — একটি thread-এর পরিচয় বদলাতে নতুন cred বানিয়ে পুরোনোটি বদলে দেওয়া হয়। User namespace-এ (পর্ব ৫১) একই ফাইলের UID ভেতরে-বাইরে আলাদা সংখ্যায় map হয় — এই পাতার sandbox-ও একটি rootless container-এ চলে; আর Linux ৫.১২-এর idmapped mount একটি mount-এর জন্যই UID map বদলাতে দেয়। SELinux-এর মতো mandatory access control এই সব যাচাইয়ের পরে LSM hook-এ আরেকটি স্বাধীন সিদ্ধান্ত যোগ করে (পর্ব ৪৯)।

৯ · সাধারণ ভুল আর তাদের নিরাপদ সমাধান

ভুলকেন বিপজ্জনকনিরাপদ সমাধান
chmod -R 777 “Permission denied” দূর করতেযেকোনো user ও প্রসেস সব ফাইল বদলাতে, মুছতে, কোড ঢোকাতে পারে; সব ফাইলে x-ও এসে যায়কে (কোন UID-এ চলা প্রসেস) কী চাইছে বুঝুন, তারপর owner/group ঠিক করে ন্যূনতম বিট: ফাইল 644 বা 640, directory 755 বা 750
World-writable ফাইল বা sticky-হীন directoryঅন্য user বা হ্যাক হওয়া সার্ভিস সেখানে বদল করে অন্যের কাজে ক্ষতিকর কিছু ঢোকাতে পারেখুঁজুন: find / -xdev -type f -perm -0002 আর find / -xdev -type d -perm -0002 ! -perm -1000; তারপর chmod o-w বা sticky
ওয়েব root-এর সব ফাইলের owner www-dataওয়েব অ্যাপে একটি ত্রুটি দিয়ে আক্রমণকারী নিজের কোডই বদলে ফেলতে পারেকোড deploy user-এর, group www-data, ফাইল 640/644, directory 750/755; লেখার অনুমতি শুধু upload বা cache ফোল্ডারে, সেখানে PHP-র মতো কোড চালানো বন্ধ
SSH: ~/.ssh বা authorized_keys group/other-এর লেখার মতোঅন্য কেউ নিজের key বসিয়ে আপনার account-এ ঢুকতে পারতchmod 700 ~/.ssh, chmod 600 ~/.ssh/authorized_keys, home-এ group/other-এর w বাদ
Private key 644একই মেশিনের অন্য user key পড়ে আপনার পরিচয়ে অন্য সার্ভারে ঢুকতে পারেনchmod 600 ~/.ssh/id_ed25519; .pub ফাইল 644 রাখা যায়
Script চালাতে sudoScript-এর প্রতিটি লাইন, এমনকি ভুলটিও, root হিসেবেনিজের ফাইলে chmod u+x (পর্ব ০৩); root লাগলে শুধু সেই এক কমান্ড, বা নির্দিষ্ট sudo নিয়ম

SSH-এর বিষয়টি একটু খুলে বলি। OpenSSH সার্ভারের sshd_config-এ StrictModes নামের option ডিফল্টে yes থাকে: login গ্রহণের আগে sshd user-এর home, ~/.ssh আর authorized_keys-এর মালিকানা আর অনুমতি দেখে, আর অন্যদের লেখার মতো হলে key-ভিত্তিক login প্রত্যাখ্যান করে — ঠিক কোন অনুমতিতে আপত্তি করবে তা সংস্করণ-ভেদে সামান্য আলাদা হতে পারে, আর কারণটি সার্ভারের লগে (যেমন Authentication refused: bad ownership or modes) লেখা থাকে। Client দিকেও ssh খুব খোলা private key ব্যবহার করতে অস্বীকার করে: “WARNING: UNPROTECTED PRIVATE KEY FILE! … Permissions 0644 … are too open.” তখন StrictModes বন্ধ করা নয়, অনুমতি ঠিক করাই সমাধান।

নিরাপদে ঠিক করার ধাপ

কেউ একটি ফোল্ডারে ভুল করে chmod -R 777 চালিয়ে ফেললে আবার -R দিয়ে একটি সংখ্যা বসানো আরেকটি ভুল — কারণ ফাইল আর directory-র দরকার আলাদা (ফাইলে x চাই না, directory-তে চাই)। নিরাপদ পদ্ধতি: আগে দেখুন (find dir -perm -0002 | head), তারপর আলাদা করে ঠিক করুন:

$ sudo chown -R deploy:www-data /var/www/shop
$ sudo find /var/www/shop -type d -exec chmod 750 {} +    # directories: rwxr-x---
$ sudo find /var/www/shop -type f -exec chmod 640 {} +    # files: rw-r-----
$ sudo chmod 2770 /var/www/shop/uploads                   # only here may the server write
$ sudo find /var/www/shop -perm -0002                     # verify: should print nothing

অথবা symbolic রূপের একটি সুন্দর কৌশল: chmod -R u=rwX,g=rX,o= dir — বড় হাতের X মানে “শুধু directory-তে, বা আগে থেকে কারও x আছে এমন ফাইলে x দেওয়া হবে।” প্রতিটি পরিবর্তনের পর যাচাই করুন, আর বড় পরিবর্তনের আগে getfacl -R dir > perms.bak দিয়ে বর্তমান অবস্থা সংরক্ষণ করে রাখুন — দরকারে setfacl --restore=perms.bak.

পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:

  • chmod 755 আর 644-এর অর্থ? — 755 = rwxr-xr-x (directory ও প্রোগ্রাম), 644 = rw-r--r-- (সাধারণ ফাইল); r = ৪, w = ২, x = ১ যোগ করে প্রতি শ্রেণির অঙ্ক।
  • umask 027 হলে নতুন ফাইল ও directory-র mode? — 0666 & ~027 = 640, 0777 & ~027 = 750; বিয়োগ নয়, বিট ধরে AND.
  • Setuid কী, একটি উদাহরণ? — exec-এর সময় effective UID ফাইলের owner হয়ে যায়; passwd এভাবে root-এর ফাইল /etc/shadow বদলায়, real UID দিয়ে বোঝে কার পাসওয়ার্ড।
  • /tmp-এ সবাই লিখতে পারে, তবু অন্যের ফাইল মুছতে পারে না কেন? — sticky bit (1777): sticky directory-তে শুধু ফাইলের owner, directory-র owner বা root মুছতে পারেন।
  • /etc/shadow কেন আলাদা আর শুধু root-এর? — /etc/passwd নাম↔UID-এর জন্য সবার পড়ার মতো হতে হয়; hash সেখানে থাকলে যে কেউ কপি করে offline অনুমান চালাতে পারত।

১০ · AI-এর যুগে permission — দ্রুত সমাধানের ফাঁদ

“Permission denied” হলো এমন একটি error, যেখানে AI সবচেয়ে বেশি বিপজ্জনক “সমাধান” দেয় — কারণ chmod 777 বা sudo প্রায় সবসময় error-টি সরিয়ে দেয়, আর AI-এর লক্ষ্য প্রায়ই error সরানো, নিরাপত্তা নয়। আপনার কাজ হলো প্রশ্নটি এমনভাবে করা, যাতে উত্তর কারণ খোঁজে, আর উত্তর নিজে যাচাই করা।

AI প্রায়ই যা বলেসমস্যাযা করবেন
“sudo chmod -R 777 /var/www চালান”পুরো ওয়েবসাইট সবার লেখার মতো, ফাইলে অকারণ xls -l, id, ps -o user দিয়ে কে কাকে আটকাচ্ছে বের করুন; owner/group ঠিক করুন
“umask 022 মানে 666 − 022 = 644”অন্য umask-এ ভুল উত্তর (033 → 633)binary-তে AND করে নিজে মেলান, ছোট পরীক্ষা চালান
“sudoers ফাইলে nano দিয়ে লাইন যোগ করুন”ব্যাকরণ-ভুল হলে sudo-ই বন্ধসবসময় visudo; আলাদা ফাইল /etc/sudoers.d/-এ
অন্য distro-র কমান্ড বা group (wheel বনাম sudo, /var/log/secure বনাম auth.log)কমান্ড ব্যর্থ বা ভুল জায়গায় খোঁজাপ্রশ্নে distro আর সংস্করণ লিখুন; cat /etc/os-release
“Port 80-এর জন্য অ্যাপ root হিসেবে চালান”অ্যাপের যেকোনো বাগ = পুরো মেশিনcapability, systemd-এর AmbientCapabilities বা reverse proxy
“SSH কাজ না করলে StrictModes no দিন”সুরক্ষা বন্ধ করে আসল ভুল লুকানো~/.ssh 700, key 600; সার্ভারের লগ পড়ুন

Permission-এর সমস্যায় AI-কে এভাবে প্রশ্ন করুন — পরিবেশ জানিয়ে, প্রমাণসহ, আর নিরাপত্তার শর্ত বেঁধে দিয়ে:

আমি Ubuntu 24.04 সার্ভারে nginx + PHP-FPM চালাই। /var/www/shop/uploads ফোল্ডারে ছবি আপলোড করলে "Permission denied" আসছে। নিচে দিলাম: - ls -ld /var/www/shop /var/www/shop/uploads এর আউটপুট - ps -o user,group,comm -C php-fpm8.3 এর আউটপুট - error log-এর লাইনটি [এখানে পেস্ট করো] ১. কোন প্রসেস কোন user/group হিসেবে কোন ফাইলে কী অধিকার চাইছে, আর kernel-এর owner → group → other নিয়মে কোথায় আটকাচ্ছে, ধাপে ধাপে বলো। ২. chmod 777, chmod -R বা পুরো সার্ভিস root হিসেবে চালানোর কোনো সমাধান দিও না। ন্যূনতম পরিবর্তন দাও। ৩. প্রতিটি কমান্ডের পর কী দিয়ে যাচাই করব (ls -l, stat, sudo -u www-data test), সেটাও বলো।

AI-এর দেওয়া permission-পরামর্শ চালানোর আগে — চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১Multics-এ পূর্ণ ACL ছিল, তবু Unix মাত্র ৯টি বিট বেছে নিল কেন? আজ সেই সিদ্ধান্ত কতটা টিকে আছে?

Ken Thompson আর Dennis Ritchie Bell Labs-এ Unix শুরু করেন Multics প্রকল্প থেকে Bell Labs সরে আসার পর (১৯৬৯)। Multics ছিল নিরাপত্তায় অগ্রগামী — প্রতিটি segment-এ ACL, ring-ভিত্তিক সুরক্ষা — কিন্তু বিশাল আর জটিল। Unix-এর দর্শন ছিল উল্টো: ছোট, সরল, যথেষ্ট ভালো। Owner, group, other × rwx — ৯টি বিট inode-এর একটি ছোট ঘরে ধরে যায়, যাচাই মাত্র তিনটি তুলনা (অংশ ৪-এর kernel কোড), আর একজন নতুন user-ও কয়েক মিনিটে বুঝে ফেলেন।

দাম দিতে হয়েছে নমনীয়তায়। “accounts group পড়বে, তার সাথে শুধু sumi” — এমন নিয়ম ৯ বিটে লেখা যায় না; group-এর সংখ্যা বাড়িয়ে কাজ চালাতে হয়, যা বড় প্রতিষ্ঠানে বিশৃঙ্খল হয়ে ওঠে। ১৯৯০-এর দশকে POSIX-এ ACL মানসম্মত করার চেষ্টা (POSIX.1e খসড়া) হয়, কিন্তু খসড়াটি শেষ পর্যন্ত আনুষ্ঠানিক মান হিসেবে গৃহীত না হয়ে প্রত্যাহার হয়। তবু Linux, FreeBSD আর অন্যরা সেই খসড়ার আদলেই ACL বাস্তবায়ন করে — আজকের setfacl/getfacl সেই উত্তরাধিকার। NFSv4 আরেক ধরনের, Windows-এর কাছাকাছি ACL আনে, যা macOS আর ZFS-এ ব্যবহৃত।

লক্ষ্য করার মতো বিষয় হলো, অর্ধশতাব্দী পরেও ৯ বিটই প্রধান। ACL আছে, কিন্তু বেশিরভাগ ফাইলে নেই; অধিকাংশ সার্ভার, container image আর Android-এর অ্যাপ-বিচ্ছিন্নতার ভিত্তিও এই সরল মডেল (Android প্রতিটি অ্যাপকে আলাদা Linux UID দেয়)। জটিল নীতির প্রয়োজন মেটানো হয়েছে মডেল বদলে নয়, ওপরে স্তর যোগ করে: ACL, capability, SELinux/AppArmor, namespace.

মূল উপলব্ধি: একটি সরল, সবার বোঝার মতো মডেল প্রায়ই একটি নিখুঁত কিন্তু জটিল মডেলের চেয়ে বেশি নিরাপত্তা দেয় — কারণ নিরাপত্তার বেশিরভাগ ব্যর্থতা ভুল কনফিগারেশন থেকে আসে। সরল ভিত্তি রেখে প্রয়োজনমতো স্তর যোগ করা Unix-এর টেকসই কৌশল।

প্র ০২Setuid ছিল একটি পেটেন্ট-করা আবিষ্কার, যা পরে সবার জন্য খুলে দেওয়া হয়। এটি এত চতুর অথচ এত বিপজ্জনক কেন?

Setuid-এর ধারণা Dennis Ritchie-এর। Bell Labs এর ওপর একটি মার্কিন পেটেন্ট নিয়েছিল (US 4,135,240, “Protection of data file contents”, ১৯৭৯ সালে মঞ্জুর) — software ধারণার প্রথম দিকের পেটেন্টগুলোর একটি হিসেবে এটি প্রায়ই উল্লেখ করা হয়। পরে Bell Labs এটিকে সবার ব্যবহারের জন্য উন্মুক্ত করে দেয়, যাতে Unix-এর সব সংস্করণে এটি ছড়িয়ে পড়ে।

চাতুর্যটা এখানে: kernel-কে প্রতিটি বিশেষ কাজের নিয়ম জানতে হয় না। “নিজের পাসওয়ার্ড বদলাতে পারবেন, অন্যেরটা নয়” — এই সূক্ষ্ম নীতি kernel-এ লেখার বদলে একটি সাধারণ প্রোগ্রামে লেখা হলো, আর kernel শুধু বলল: এই প্রোগ্রাম চলার সময় তার মালিকের ক্ষমতা পাবে। ফলে নতুন নীতি যোগ করতে kernel বদলাতে হয় না — নতুন একটি ছোট প্রোগ্রাম লিখলেই হয়। ছোট kernel, নমনীয় নীতি।

বিপদটাও ঠিক সেখানে। নীতির পুরো ভার এখন একটি user-space প্রোগ্রামের কোডে, আর সেই প্রোগ্রাম এমন পরিবেশে চলে যার প্রায় সবকিছু আক্রমণকারী ঠিক করে দিতে পারেন: আর্গুমেন্ট, environment variable (PATH, locale, library path), খোলা file descriptor, signal, এমনকি resource limit. একটি অসতর্ক system() call, একটি buffer overflow, একটি race condition — যেকোনোটি root পর্যন্ত সিঁড়ি। এজন্যই kernel আর C library সময়ের সাথে বহু সুরক্ষা যোগ করেছে: setuid প্রোগ্রামে বিপজ্জনক environment variable উপেক্ষা (glibc-এর “secure mode”), script-এর setuid উপেক্ষা, nosuid mount, আর NoNewPrivileges flag যা একবার দিলে প্রসেস আর কখনো exec দিয়ে বাড়তি ক্ষমতা পায় না।

আধুনিক প্রবণতা হলো setuid যতটা সম্ভব কমানো: capability দিয়ে শুধু দরকারি টুকরো দেওয়া, বিশেষ কাজ একটি আলাদা privileged সার্ভিসকে দিয়ে করানো (যেখানে সাধারণ প্রোগ্রাম IPC দিয়ে অনুরোধ পাঠায়, আর সার্ভিস নিজে নীতি যাচাই করে), আর নিয়মিত নিরীক্ষা। অংশ ৬-এর find -perm -4000 তালিকাটি তাই প্রতিটি প্রশাসকের নিয়মিত কাজের অংশ।

মূল উপলব্ধি: ক্ষমতা ধার দেওয়ার যেকোনো কৌশল নিরাপত্তার ভার সরিয়ে দেয় সেই কোডে, যে ধার নেয়। তাই সেই কোড যত ছোট, যত কম, যত বেশি যাচাই-করা, সিস্টেম তত নিরাপদ।

প্র ০৩sudo নিজেও তো একটি setuid-root প্রোগ্রাম। তাহলে sudo ব্যবহার কি সত্যিই root হিসেবে login করার চেয়ে নিরাপদ?

প্রশ্নটি ন্যায্য। sudo-র শুরু ১৯৮০ সালের দিকে State University of New York at Buffalo-তে (Bob Coggeshall আর Cliff Spencer-এর কাজ বলে উল্লেখিত), আর ১৯৯০-এর দশক থেকে বহু বছর ধরে এর প্রধান রক্ষণাবেক্ষণকারী Todd C. Miller. এটি একটি বড়, জটিল setuid-root প্রোগ্রাম, আর জটিল কোডে বাগ থাকেই। ২০২১ সালের জানুয়ারিতে প্রকাশিত “Baron Samedit” (CVE-2021-3156) ছিল sudo-র ভেতরে প্রায় এক দশক ধরে থাকা একটি heap overflow, যা যেকোনো স্থানীয় user-কে — এমনকি sudoers-এ না থাকলেও — root হওয়ার সুযোগ দিত। সমাধান ছিল দ্রুত আপডেট।

তবু তুলনাটি “sudo বনাম কিছুই না” নয়, “sudo বনাম সারাক্ষণ root”. সারাক্ষণ root থাকলে প্রতিটি টাইপো, প্রতিটি ব্রাউজার-ট্যাব, প্রতিটি নামানো script পূর্ণ ক্ষমতায় চলে — কোনো বাগেরও দরকার নেই। sudo-তে ক্ষমতা শুধু নির্দিষ্ট কমান্ডের মুহূর্তে, নীতি দিয়ে সীমিত, আর লগে নাম-ধরে লেখা। নিরীক্ষার (audit) দিক থেকে, কোন কমান্ডে কী ঘটেছিল তা পরে খুঁজে পাওয়া যায়।

sudo-র নিজের ঝুঁকি কমানোর উপায়ও আছে: প্যাকেজ আপডেট রাখা, sudoers ছোট ও নির্দিষ্ট রাখা, পূর্ণ ALL শুধু সত্যিকারের প্রশাসকদের, আর সার্ভারে যারা কখনো প্রশাসন করেন না তাঁদের sudo group থেকে বাদ দেওয়া। কিছু সংস্থা বিকল্পও দেখে — যেমন OpenBSD-র ছোট doas, যার কোড অনেক ছোট; সম্প্রতি কিছু Linux distro sudo-র memory-safe ভাষায় লেখা পুনর্বাস্তবায়ন নিয়েও কাজ করছে। প্রশ্ন সবসময় একই: কতটুকু কোড root হিসেবে বিশ্বাস করতে হচ্ছে।

মূল উপলব্ধি: নিরাপত্তা নিখুঁত টুল নয়, ঝুঁকির তুলনা। একটি সক্রিয়ভাবে রক্ষণাবেক্ষিত, সংকীর্ণ নীতির, লগ-করা ক্ষমতা-বৃদ্ধি সবসময়-খোলা মাস্টার চাবির চেয়ে অনেক কম বিপজ্জনক — যদি আপনি সেটি আপডেট রাখেন।

প্র ০৪Directory-তে w থাকলে অন্যের ফাইল মোছা যায় — এটি কি নকশার ভুল? sticky bit-এর পরও /tmp কেন বছরের পর বছর আক্রমণের জায়গা ছিল?

নকশার দিক থেকে এটি ভুল নয়, যুক্তিসংগত পরিণতি। Unix-এ ফাইলের নাম ফাইলের অংশ নয় — নাম থাকে directory-তে, ফাইল (inode) আলাদা, আর একটি inode-এর একাধিক নামও থাকতে পারে (পর্ব ৪২-এর hard link). “মোছা” মানে একটি directory থেকে একটি নাম কাটা; ফাইলের ডেটা মুছে যায় কেবল যখন আর কোনো নাম ও খোলা fd থাকে না। তাই মোছার অনুমতি directory-র মালিকানার প্রশ্ন, ফাইলের নয় — ঠিক যেমন অফিসের নোটিশবোর্ডের দায়িত্বে থাকা ব্যক্তি যেকোনো নোটিশ নামাতে পারেন, নোটিশটি যিনিই লিখুন।

সমস্যা দেখা দেয় shared directory-তে, যেখানে সবাই লিখবে। এজন্য sticky bit-এর পুরোনো “swap-এ রেখে দেওয়া হোক” অর্থ বাদ দিয়ে BSD-ধারার Unix-এ directory-র জন্য নতুন অর্থ দেওয়া হয় — “নিজেরটা ছাড়া মুছতে পারবেন না।” কিন্তু /tmp-এর বিপদ মোছার চেয়ে সূক্ষ্ম। ধরুন একটি root-এর script প্রতিবার /tmp/report.txt-এ লেখে। অন্য একজন user আগেভাগে সেই নামে একটি symlink বানিয়ে রাখলেন, যা /etc/-এর কোনো গুরুত্বপূর্ণ ফাইল দেখায় — root-এর script তখন না জেনে সেই ফাইলটিই নষ্ট করে। এটি একটি time-of-check-to-time-of-use ধরনের সমস্যা (পর্ব ২২-এর race condition-এর আত্মীয়)।

প্রতিরক্ষা এসেছে কয়েক দিক থেকে। প্রোগ্রামের দিকে: অনুমানযোগ্য নাম নয়, mkstemp()/mktemp দিয়ে এলোমেলো নামে O_CREAT | O_EXCL সহ ফাইল তৈরি, যাতে আগে থেকে কিছু থাকলে ব্যর্থ হয়। Kernel-এর দিকে: Linux ৩.৬ (২০১২) থেকে protected_symlinks আর protected_hardlinks, ৪.১৯ থেকে protected_regular ও protected_fifos — অংশ ৪-এর sandbox-এ এগুলো চালু দেখেছেন। সিস্টেমের দিকে: systemd-এর PrivateTmp=yes প্রতিটি সার্ভিসকে নিজস্ব আলাদা /tmp দেয় (mount namespace দিয়ে), ফলে সার্ভিসগুলো একে অপরের অস্থায়ী ফাইল দেখতেই পায় না।

মূল উপলব্ধি: একটি সরল নিয়ম (নাম directory-র সম্পত্তি) থেকে অপ্রত্যাশিত পরিণতি আসতে পারে, বিশেষত যখন অনেকে একটি জায়গা ভাগ করেন। নিরাপত্তা আসে স্তরে স্তরে — অনুমতির বিট, kernel-এর বাড়তি নিয়ম, আর প্রোগ্রামের সতর্ক অভ্যাস একসাথে।

প্র ০৫Container-এর ভেতরে id লিখলে প্রায়ই uid=0(root) দেখায়। সেটি কি host মেশিনের আসল root? এই পাতার sandbox আমাদের কী শেখায়?

Container-এর root আর host-এর root এক কি না, তা নির্ভর করে container কীভাবে চালানো হয়েছে তার ওপর। পুরোনো ও এখনো প্রচলিত ধাঁচে (rootful Docker, user namespace ছাড়া) container-এর UID 0 আসলে host-এরও UID 0 — শুধু namespace, cgroup, capability ছাঁটাই আর seccomp দিয়ে তাকে বেঁধে রাখা হয়। এই বাঁধন কোনোভাবে ভাঙলে (container escape) সে host-এ পূর্ণ root. এজন্যই নিরাপত্তা-নির্দেশিকা বলে: container-এর ভেতরেও অ্যাপ non-root user হিসেবে চালান (Dockerfile-এ USER), আর --privileged এড়িয়ে চলুন।

দ্বিতীয় ধাঁচ হলো user namespace. সেখানে container-এর ভেতরের UID 0-কে host-এর একটি সাধারণ, অধিকারহীন UID-এ map করা হয় (যেমন ভেতরের 0 → বাইরের 100000). ভেতরে সে root-এর মতো আচরণ করে — নিজের namespace-এ ফাইলের মালিক বদলায়, প্যাকেজ ইনস্টল করে — কিন্তু host-এর কোনো ফাইলে তার ক্ষমতা একজন সাধারণ user-এর চেয়ে বেশি নয়। Podman-এর rootless mode আর Docker-এর rootless mode এই নীতিতে চলে।

এই পাতার কোড-রানারটি একটি চমৎকার বাস্তব উদাহরণ। অংশ ৬-এর আউটপুটে দেখেছেন: আমরা root নই, UID 999, কোনো capability নেই (CapEff শূন্য), sudo নেই। আর রানারের mount তথ্য (এই পাতায় দেখানো হয়নি) ইঙ্গিত দেয় যে এটি একটি rootless container-এ চলে। দুই স্তরের সুরক্ষা: ভেতরে আমরা অধিকারহীন user, আর পুরো container-টিই host-এ একজন অধিকারহীন user-এর অধীনে। এমনকি ভেতরে কেউ root হয়ে গেলেও host-এর root হবেন না।

তবে user namespace-এর নিজস্ব ঝুঁকিও আছে: এটি সাধারণ user-কে kernel-এর এমন অনেক অংশে পৌঁছাতে দেয় যা আগে শুধু root-এর ছিল, ফলে kernel-এর বাগ খুঁজে পাওয়ার সুযোগ বাড়ে। তাই কিছু distro এর ব্যবহার সীমিত করার option রাখে। বিস্তারিত পর্ব ৫১-এ।

মূল উপলব্ধি: “root” একটি নাম নয়, একটি প্রসঙ্গ-নির্ভর ক্ষমতা। প্রশ্ন সবসময়: কোন namespace-এ, কোন capability-সহ, কোন সীমানার ভেতরে? একটি সংখ্যা (UID 0) দেখে সিদ্ধান্ত নেওয়া যায় না।

অনুশীলন

প্রথমে নিজে চেষ্টা করুন, তারপর উত্তর মিলিয়ে নিন।

  1. হিসাব (হাতে করুন): (ক) rwxr-x--x-এর octal কত? (খ) 2770 একটি directory-তে ls -l-এ কেমন দেখাবে? (গ) umask 026 হলে নতুন ফাইল আর directory-র mode? (ঘ) umask 033 হলে নতুন directory-র mode, আর বিয়োগ করলে কোন ভুল উত্তর আসত?

    (ক) rwx = ৪+২+১ = ৭, r-x = ৪+১ = ৫, --x = ১ → 751.

    (খ) বিশেষ অঙ্ক ২ = setgid; ৭ = rwx, ৭ = rwx (group-এর x-এর জায়গায় s), ০ = --- → drwxrws---.

    (গ) 026 = 000 │ 010 │ 110, ~026 = 111 │ 101 │ 001. ফাইল: 110 │ 110 │ 110 AND → 110 │ 100 │ 000 = 640. Directory: 111 │ 111 │ 111 AND → 111 │ 101 │ 001 = 751.

    (ঘ) ~033 = 111 │ 100 │ 100. Directory: 0777 AND → 744 (drwxr--r--) — group আর other নাম পড়তে পারবে কিন্তু ভেতরে যেতে পারবে না, যা প্রায়ই অর্থহীন। ফাইলের জন্য বিয়োগে 666 − 033 = 633 আসত (ভুল; সঠিক 644). Directory-তে বিয়োগে 777 − 033 = 744 ঘটনাচক্রে মিলে যায়, কারণ 777-এর সব বিটই ১.

  2. আউটপুট অনুমান করুন: /proj directory drwxr-x--- karim dev, ভেতরে plan.txt হলো -rw-r----- karim dev. sumi-র id: uid=1003(sumi) gid=1003(sumi) groups=1003(sumi),1500(dev); tanvir কোনো group-এ নেই। নিচের চারটি কমান্ডে কী হবে? (১) sumi: cat /proj/plan.txt (২) sumi: echo x >> /proj/plan.txt (৩) sumi: rm /proj/plan.txt (৪) tanvir: ls /proj

    (১) সফল। sumi owner নন, কিন্তু dev group-এ আছেন → /proj-এ group r-x (x দিয়ে ভেতরে যাওয়া যায়), ফাইলে group r-- → পড়া চলবে।

    (২) Permission denied. ফাইলে group-এর w নেই।

    (৩) rm: cannot remove '/proj/plan.txt': Permission denied. মোছা directory-র কাজ, আর /proj-এ group-এর w নেই। (একটি সূক্ষ্মতা: ফাইলটি sumi-র জন্য লেখা-নিষিদ্ধ, তাই rm প্রথমে “remove write-protected regular file?” জিজ্ঞেস করতে পারে; হ্যাঁ বললেও শেষে directory-র অনুমতিতে ব্যর্থ।)

    (৪) ls: cannot open directory '/proj': Permission denied. tanvir other শ্রেণিতে, /proj-এ other ---.

  3. কমান্ড লিখুন: একটি সার্ভারে dev group-এর জন্য /srv/project নামে একটি shared folder বানাতে হবে: dev-এর সবাই পড়বেন, লিখবেন, নতুন ফাইল আপনাআপনি dev group পাবে, বাইরের কেউ কিছুই দেখবেন না। rahim আর karim-কে group-এ যোগ করুন। প্রয়োজনীয় কমান্ড আর যাচাইয়ের উপায় লিখুন।
    sudo groupadd dev
    sudo usermod -aG dev rahim          # -a = append; without it other groups are removed!
    sudo usermod -aG dev karim
    sudo mkdir -p /srv/project
    sudo chown root:dev /srv/project
    sudo chmod 2770 /srv/project        # setgid: new files get group dev; others: nothing
    # so that group members can also WRITE each other's new files, either:
    #   umask 002 in each member's ~/.profile, or a default ACL:
    sudo setfacl -d -m g:dev:rwX /srv/project
    # verify (rahim's already-open shells see the new group only after a new login):
    ls -ld /srv/project                 # drwxrws---+ root dev
    id rahim                            # reads /etc/group: ... ,NNNN(dev)
    sudo -u rahim touch /srv/project/a; stat -c '%A %U:%G %n' /srv/project/a

    শেষ লাইনে ফাইলের group dev আসা উচিত (setgid-এর কাজ)। usermod-এ -a ভুলে যাওয়া একটি পরিচিত দুর্ঘটনা — user বাকি সব অতিরিক্ত group, এমনকি sudo, হারান। আর group যোগের পর নতুন login না করা পর্যন্ত চলমান session-এ নতুন group কাজ করে না।

  4. নিরীক্ষা করুন: নিজের Linux মেশিনে (বা WSL-এ) তিনটি নিরীক্ষা চালান: (ক) setuid/setgid প্রোগ্রামের তালিকা, (খ) সবার-লেখা ফাইল, (গ) sticky-হীন সবার-লেখা directory. ফলাফল কীভাবে বিচার করবেন?
    find / -xdev -type f \( -perm -4000 -o -perm -2000 \) -ls 2>/dev/null     # (a)
    find / -xdev -type f -perm -0002 -ls 2>/dev/null                         # (b)
    find / -xdev -type d -perm -0002 ! -perm -1000 -ls 2>/dev/null           # (c)

    (ক) অংশ ৬-এর sandbox-এর মতো ১০–৩০টি চেনা নাম (passwd, su, sudo, mount, chsh …) স্বাভাবিক। প্রতিটির package যাচাই করুন (dpkg -S /usr/bin/xyz বা rpm -qf); home, /tmp বা /opt-এ অচেনা setuid ফাইল, বা package-বিহীন ফাইল গুরুতর সতর্কসংকেত। (খ) সাধারণত কিছুই আসা উচিত নয় (/proc, /sys -xdev-এর কারণে বাদ)। কিছু এলে কে বানিয়েছে, কেন, দেখে chmod o-w. (গ) /tmp, /var/tmp আর /dev/shm sticky বলে এই তালিকায় আসবে না; অন্য কোনো directory এলে তা ঠিক করুন।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকজন সাধারণ user passwd দিয়ে নিজের পাসওয়ার্ড বদলাচ্ছেন — ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. Shell (real = effective UID 1000) /usr/bin/passwd-কে exec করে
  2. Kernel setuid বিট দেখে effective আর saved UID 0 করে, real UID 1000-ই রাখে
  3. passwd real UID দেখে বোঝে কার পাসওয়ার্ড, আর পুরোনো পাসওয়ার্ড যাচাই করে
  4. Effective UID 0 থাকায় নতুন hash /etc/shadow-এ লেখা যায়
  5. প্রোগ্রাম শেষ, shell আবার UID 1000-এ — কোনো বাড়তি ক্ষমতা থেকে যায় না

একটি ফাইল -r--rw---- rahim accounts. rahim নিজে accounts group-এর সদস্য। rahim ফাইলটিতে লিখতে চাইলে কী হবে?

  • সফল, কারণ group-এর w আছে আর rahim group-এর সদস্য
  • Permission denied, কারণ owner মিলে গেলে শুধু owner-এর বিট দেখা হয়
  • সফল, কারণ kernel তিন শ্রেণির মধ্যে সবচেয়ে উদারটি বেছে নেয়
  • Permission denied, কারণ other-এর বিট ---

umask 027. একটি editor নতুন ফাইল তৈরিতে mode 0666 চাইল। ফাইলটির mode কত হবে?

  • 644
  • 750
  • 640
  • 639

একটি directory-তে chmod 2775 shared দেওয়া হলো। এর প্রধান ফল কী?

  • ভেতরে নতুন তৈরি ফাইল directory-র group পায়; mode দেখায় drwxrwsr-x
  • ভেতরে শুধু ফাইলের মালিকই নিজের ফাইল মুছতে পারেন
  • ভেতরের সব প্রোগ্রাম root হিসেবে চলে
  • সবাই ভেতরে লিখতে পারে, other-ও

/tmp-এর mode drwxrwxrwt. sumi সেখানে karim-এর ফাইল /tmp/k.txt (-rw-rw-rw- karim) মুছতে চাইলেন। কী হবে?

  • মুছে যাবে, কারণ /tmp-এ সবার w আছে
  • মুছে যাবে, কারণ ফাইলটি নিজেও সবার লেখার মতো
  • মোছা যাবে না, কারণ sumi-র ফাইলে r অধিকার নেই
  • মোছা যাবে না — sticky bit-এর কারণে শুধু ফাইলের owner, directory-র owner বা root মুছতে পারেন

UID 1000-এর একজন user setuid-root প্রোগ্রাম /usr/bin/passwd চালালেন। প্রোগ্রাম চলাকালীন তার real আর effective UID কত?

  • real 1000, effective 1000
  • real 1000, effective 0
  • real 0, effective 0
  • real 0, effective 1000

একটি সাধারণ user হিসেবে চলা ওয়েব সার্ভারকে port 80-এ চালাতে হবে। সবচেয়ে কম ক্ষমতা দেয় এমন সমাধান কোনটি?

  • সার্ভারটি sudo দিয়ে root হিসেবে চালানো
  • প্রোগ্রামের owner root করে chmod 4755 দেওয়া
  • setcap 'cap_net_bind_service=+ep' দিয়ে শুধু নিচের port খোলার capability দেওয়া
  • প্রোগ্রাম ফাইলে chmod 777 দেওয়া

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Kernel চেনে UID আর GID; নাম থাকে সবার-পড়ার /etc/passwd-এ, hash শুধু root-এর /etc/shadow-এ। UID 0 = root.
  2. owner → group → other, প্রথম মিলটিই চূড়ান্ত; r = ৪, w = ২, x = ১. Directory-তে x = traverse, w (+x) = নাম যোগ-মোছা।
  3. নতুন mode = চাওয়া mode & ~umask: 022 → 644/755, 027 → 640/750 — বিয়োগ নয়।
  4. setuid (৪) effective UID বদলায়, setgid (২) directory-তে group উত্তরাধিকার দেয়, sticky (১) shared directory-তে অন্যের ফাইল মোছা আটকায়; setuid তালিকা নিয়মিত নিরীক্ষা করুন।
  5. সারাক্ষণ root নয়: নির্দিষ্ট sudo নিয়ম (visudo), capability, দরকারে ACL — আর কখনো chmod 777 নয়।

পরের পর্বে: অনুমতির নিয়ম তখনই কাজ করে, যখন OS জানে আপনি সত্যিই কে — পাসওয়ার্ড, hash আর বহু-স্তরের authentication; আর CPU-র privilege ring, ASLR, DEP-এর মতো memory-সুরক্ষা কীভাবে kernel-কে নিজেকে রক্ষা করতে সাহায্য করে।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান