পাঠ ৪৮ · ৫৬-এর মধ্যে · মডিউল ১১
Home / Courses / Operating Systems (OS) / সিকিউরিটি ও প্রোটেকশন

প্রিভিলেজ লেভেল ও রিং প্রোটেকশন

Privilege levels & ring protection
৭ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • প্রিভিলেজ রিং কী এবং x86-এ রিং ০-৩ বাস্তবে কীভাবে ব্যবহৃত হয় (এবং কীভাবে হয় না)
  • রিং ০ ও রিং ৩-এর মধ্যে পার্থক্য এবং কেন বাইরের রিং থেকে প্রিভিলেজড অপারেশন সরাসরি সম্ভব নয়
  • সিস্টেম কল কীভাবে রিং-এর মধ্যে একটি নিয়ন্ত্রিত, নিরাপদ পারাপার তৈরি করে
  • Python দিয়ে একটি রিং-ভিত্তিক প্রিভিলেজ-চেকিং সিমুলেশন — সরাসরি প্রত্যাখ্যান বনাম সিস্টেম-কল-পথে সফল হওয়ার পার্থক্য বাস্তবে দেখা

১ · প্রিভিলেজ রিং — হার্ডওয়্যারে বলবৎ করা মোড

L03-এ আমরা দেখেছি OS দুটি মোডে চলে — ইউজার মোড (সীমাবদ্ধ) ও কার্নেল মোড (সম্পূর্ণ ক্ষমতা)। কিন্তু এই "মোড" ধারণাটি বাস্তবে হার্ডওয়্যারে কীভাবে প্রয়োগ হয়? উত্তর হলো প্রিভিলেজ রিংPrivilege RingCPU হার্ডওয়্যারে সংজ্ঞায়িত একাধিক সংখ্যায়িত প্রিভিলেজ স্তর, যেখানে নিম্ন সংখ্যা মানে বেশি ক্ষমতা।। বহু বাস্তব CPU আর্কিটেকচার (যেমন সুপরিচিত x86) একাধিক সংখ্যায়িত রিং সংজ্ঞায়িত করে — রিং ০ থেকে রিং ৩ পর্যন্ত।

একটি গুরুত্বপূর্ণ, বাস্তব খুঁটিনাটি — যদিও হার্ডওয়্যারে চারটি রিং আছে, বেশিরভাগ সাধারণ-উদ্দেশ্যের OS (Linux, Windows) বাস্তবে মাত্র দুটি ব্যবহার করে — রিং ০ (কার্নেল) ও রিং ৩ (ইউজার অ্যাপ্লিকেশন)। রিং ১ ও ২ হার্ডওয়্যারে বিদ্যমান কিন্তু মূলধারার OS ডিজাইনে ব্যাপকভাবে ব্যবহৃত হয় না।

রিং ০ · কার্নেল (সর্বোচ্চ ক্ষমতা) রিং ১-২ · হার্ডওয়্যারে আছে, প্রায় অব্যবহৃত রিং ৩ · ইউজার অ্যাপ্লিকেশন (সর্বনিম্ন ক্ষমতা) প্রিভিলেজড অপারেশনের চেষ্টা → হার্ডওয়্যার প্রোটেকশন ফল্ট
রিং ৩ থেকে সরাসরি প্রিভিলেজড অপারেশন করার চেষ্টা করলে হার্ডওয়্যার নিজেই তা আটকে দেয়।

২ · রিং ০ বনাম রিং ৩ — কে কী করতে পারে

রিং ০ · কার্নেল
সম্পূর্ণ, অনিয়ন্ত্রিত হার্ডওয়্যার অ্যাক্সেস — সরাসরি ডিভাইস নিয়ন্ত্রণ, মেমরি ম্যাপিং পরিবর্তন, CPU-এর নিজস্ব নিয়ন্ত্রণ রেজিস্টার পরিবর্তন — OS কার্নেল এখানেই চলে।
রিং ৩ · ইউজার অ্যাপ্লিকেশন
সবচেয়ে সীমাবদ্ধ — সরাসরি হার্ডওয়্যার অ্যাক্সেস নিষিদ্ধ। প্রিভিলেজড অপারেশনের প্রয়োজন হলে অবশ্যই একটি নিয়ন্ত্রিত পথ (সিস্টেম কল) দিয়ে যেতে হবে।
এখানেই L03-এর সিস্টেম কল বাস্তবে রূপ নেয়

রিং ৩-এ থাকা একটি প্রোগ্রাম সরাসরি হার্ডওয়্যার অ্যাক্সেসের চেষ্টা করলে হার্ডওয়্যার নিজেই একটি প্রোটেকশন ফল্ট শনাক্ত করে কার্নেলে (রিং ০) একটি নিয়ন্ত্রিত পারাপার ঘটায়। সিস্টেম কল ঠিক এই প্রক্রিয়াটিই ব্যবহার করে — এটিই একমাত্র নিরাপদ উপায় যাতে একটি রিং-৩ প্রোগ্রাম কার্নেলকে (রিং ০-এ চলা) তার হয়ে একটি প্রিভিলেজড কাজ করতে বলতে পারে।

৩ · একটি রিং-ভিত্তিক প্রিভিলেজ-চেকিং সিমুলেশন

নিচে প্রতিটি "প্রসেস"-এর একটি রিং লেভেল আছে (০=কার্নেল, ৩=ইউজার), এবং প্রতিটি অপারেশনের একটি ন্যূনতম প্রয়োজনীয় রিং আছে। নিয়ম সহজ — একটি অপারেশন তখনই চলতে পারে যখন প্রসেসের রিং সংখ্যা সেই অপারেশনের প্রয়োজনীয় রিং সংখ্যার চেয়ে কম বা সমান (মনে রাখবেন, কম সংখ্যা = বেশি ক্ষমতা)।

Python
# রিং-ভিত্তিক প্রিভিলেজ চেকিং সিমুলেশন -- বাস্তব CPU রিং নয়, শুধুই একটি ধারণাগত মডেল

operation_min_ring = {
    "modify_page_table": 0,   # শুধু কার্নেল করতে পারে
    "access_io_port":    0,   # শুধু কার্নেল করতে পারে
    "read_own_stack":    3,   # যেকোনো প্রসেস নিজের ডেটা পড়তে পারে
}

def attempt_operation(process_ring, operation, requirements):
    required_ring = requirements[operation]
    if process_ring <= required_ring:
        return True, f"সফল -- ring {process_ring} <= প্রয়োজনীয় ring {required_ring}"
    return False, f"প্রত্যাখ্যাত -- ring {process_ring} > প্রয়োজনীয় ring {required_ring} (প্রোটেকশন ফল্ট)"

def perform_via_syscall(process_ring, operation, requirements):
    print(f"  [সিস্টেম কল ট্র্যাপ] ring {process_ring} থেকে কার্নেলে (ring 0) নিয়ন্ত্রিত পারাপার...")
    elevated_ring = 0  # কার্নেল এখন প্রসেসের হয়ে কাজটি করছে
    ok, msg = attempt_operation(elevated_ring, operation, requirements)
    print(f"  [কার্নেলে সম্পন্ন] {msg}")
    print(f"  [ফিরে আসা] কার্নেল কাজ শেষে প্রসেসকে ring {process_ring}-এ ফিরিয়ে দিলো")
    return ok


kernel_process_ring = 0
user_process_ring = 3

print("--- সরাসরি চেষ্টা ---")
ok, msg = attempt_operation(kernel_process_ring, "modify_page_table", operation_min_ring)
print(f"কার্নেল প্রসেস সরাসরি modify_page_table: {msg}")

ok, msg = attempt_operation(user_process_ring, "modify_page_table", operation_min_ring)
print(f"ইউজার প্রসেস সরাসরি modify_page_table: {msg}")

print("\n--- ইউজার প্রসেস এখন সিস্টেম কলের মাধ্যমে চেষ্টা করছে ---")
success = perform_via_syscall(user_process_ring, "modify_page_table", operation_min_ring)
print(f"চূড়ান্ত ফলাফল: {'সফল হয়েছে' if success else 'ব্যর্থ হয়েছে'}")

    
লক্ষ্য করুন — ইউজার প্রসেস (ring 3) modify_page_table-এর সরাসরি চেষ্টা করলে প্রত্যাখ্যাত হয় (৩ > ০), কিন্তু ঠিক একই কাজ যখন সিস্টেম-কল পথে যায়, ফাংশনটি সাময়িকভাবে elevated_ring = 0 ব্যবহার করে কার্নেলের হয়ে কাজটি সম্পন্ন করে, তারপর প্রসেসকে তার আসল রিং ৩-এ ফিরিয়ে দেয় — ঠিক L03-এর বর্ণিত মোড-সুইচ প্রক্রিয়ার একটি সরলীকৃত চিত্র।
M12-এর দিকে ইঙ্গিত

ভার্চুয়ালাইজেশনে হাইপারভাইজার (M12/L49) একটি গেস্ট OS-এর কার্নেলকেও নিয়ন্ত্রণ করতে হয় — এজন্য এটি ধারণাগতভাবে রিং ০-এরও "নিচে" একটি আরও প্রিভিলেজড স্তরে বসে (কখনো অনানুষ্ঠানিকভাবে "রিং -১" বলা হয়), যাতে একাধিক গেস্ট OS নিরাপদে হোস্ট করা যায় — প্রতিটি গেস্ট এখনও বিশ্বাস করে সে নিজেই রিং ০-এ চলছে।

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

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

প্র ০১ x86 হার্ডওয়্যারে চারটি রিং থাকা সত্ত্বেও বেশিরভাগ OS মাত্র দুটি (০ ও ৩) ব্যবহার করে কেন — মাঝের রিং ১-২ ব্যবহার করলে কী অতিরিক্ত সুবিধা হতো, আর কেন তা ব্যাপকভাবে গৃহীত হয়নি?

মাঝের রিং ব্যবহার করলে তাত্ত্বিকভাবে ডিভাইস ড্রাইভারের মতো কিছু কম্পোনেন্টকে সম্পূর্ণ কার্নেল প্রিভিলেজ না দিয়ে একটি মধ্যবর্তী স্তরে রাখা যেত (আরও সূক্ষ্ম ফল্ট-আইসোলেশন)। কিন্তু বাস্তবে বেশিরভাগ মূলধারার OS ডিজাইন (Unix-family, Windows) দুই-স্তরের (ইউজার/কার্নেল) মডেলের উপর তৈরি হয়েছিল, এবং OS-জুড়ে অতিরিক্ত রিং সমর্থন যোগ করা বড় স্থাপত্যগত পরিবর্তন দাবি করত — বাস্তব সুবিধা প্রয়োজনীয় পুনর্গঠনের তুলনায় যথেষ্ট আকর্ষণীয় মনে হয়নি, তাই সেগুলো হার্ডওয়্যারে থেকে গেলেও ব্যাপকভাবে অব্যবহৃত থেকে গেছে।

প্র ০২ একটি রিং-৩ প্রোগ্রাম যদি সরাসরি রিং-০ মেমরিতে লেখার চেষ্টা করে (সিস্টেম কল ছাড়াই), হার্ডওয়্যার এটি কীভাবে ধরে ফেলে? সফটওয়্যার নিজে থেকে এটি প্রতিরোধ করলে কী সমস্যা হতো?

CPU হার্ডওয়্যার নিজেই প্রতিটি মেমরি অ্যাক্সেসের সময় বর্তমান রিং লেভেল পরীক্ষা করে — একটি প্রিভিলেজড অপারেশনের চেষ্টা সনাক্ত হলে হার্ডওয়্যার সাথে সাথে একটি ফল্ট/ট্র্যাপ তৈরি করে কার্নেলে নিয়ন্ত্রণ দিয়ে দেয়, প্রোগ্রামের ইচ্ছার উপর নির্ভর না করেই। যদি এই প্রতিরোধ শুধু সফটওয়্যারে (OS নিজে) থাকত, তাহলে একটি পর্যাপ্ত সুবিধাবঞ্চিত/বাগযুক্ত প্রোগ্রাম কোনোভাবে সেই সফটওয়্যার-চেক এড়িয়ে সরাসরি হার্ডওয়্যারে পৌঁছাতে পারত — নিরাপত্তা হার্ডওয়্যারে বলবৎ হওয়াটাই এটিকে সত্যিকারের অলঙ্ঘনীয় করে তোলে।

প্র ০৩ উপরের কোড সেলে যদি operation_min_ring["modify_page_table"] ১ করা হতো (০ নয়), তাহলে ইউজার প্রসেসের সরাসরি চেষ্টার ফলাফল কি পাল্টাতো? সিস্টেম-কল পথের ফলাফল কি পাল্টাতো?

ইউজার প্রসেসের সরাসরি চেষ্টা (ring 3) এখনও প্রত্যাখ্যাত হতো, কারণ ৩ > ১ এখনও সত্য — ফলাফল একই থাকত। সিস্টেম-কল পথেও কোনো পার্থক্য হতো না, কারণ perform_via_syscall সবসময় elevated_ring = 0 ব্যবহার করে, এবং ০ <= ১ সবসময় সত্য। তবে যদি প্রয়োজনীয় রিং ৪ বা তার বেশি (এই সিমুলেশনে অসম্ভব, যেহেতু সর্বোচ্চ প্রিভিলেজ রিং ০-ই) হতো, তাহলেই একমাত্র উভয় পথ ব্যর্থ হতো — এটি দেখায় সিস্টেম-কল পথ কেবল তখনই কাজ করে যখন কার্নেলের নিজস্ব রিং (০) সেই অপারেশনের জন্য যথেষ্ট প্রিভিলেজড।

অনুশীলন

  1. পরীক্ষা করুন: উপরের কোড সেলে operation_min_ring-এ একটি নতুন এন্ট্রি "send_network_packet": 0 যোগ করে, ইউজার প্রসেসের সরাসরি চেষ্টা ও সিস্টেম-কল পথ উভয়ই পরীক্ষা করে দেখুন ফলাফল কী আসে।

    সরাসরি চেষ্টা (ring 3, প্রয়োজন ring 0) প্রত্যাখ্যাত হবে, ঠিক modify_page_table-এর মতোই — কারণ ৩ > ০। সিস্টেম-কল পথে perform_via_syscall কল করলে এটি সফল হবে, কারণ কার্নেল (elevated_ring=0) এর হয়ে কাজটি করছে। এটি দেখায় যে যেকোনো নতুন প্রিভিলেজড অপারেশনের জন্যই একই প্যাটার্ন প্রযোজ্য — সরাসরি না, শুধু সিস্টেম কলের মাধ্যমেই সম্ভব।

  2. চিন্তা করুন: যদি হার্ডওয়্যারে কোনো রিং প্রোটেকশনই না থাকত (সব প্রসেস কল্পনাযোগ্য সর্বোচ্চ প্রিভিলেজে চলত), তাহলে L17-M5-এর সিনক্রোনাইজেশন সমস্যাগুলোর পাশাপাশি কী অতিরিক্ত ঝুঁকি তৈরি হতো?

    M5-এর রেস কন্ডিশন সমস্যাগুলো শেয়ার্ড ডেটার উপর দুই প্রসেসের প্রতিযোগিতা নিয়ে — কিন্তু রিং প্রোটেকশন ছাড়া, যেকোনো বাগযুক্ত বা ক্ষতিকর প্রসেস সরাসরি অন্য প্রসেসের মেমরি, এমনকি কার্নেলের নিজস্ব ডেটা স্ট্রাকচারও (যেমন পেজ টেবিল, M7) পরিবর্তন করে দিতে পারত — শুধু ভুল ফলাফল নয়, বরং সম্পূর্ণ সিস্টেম ক্র্যাশ বা নিরাপত্তা লঙ্ঘনের ঝুঁকি তৈরি হতো। রিং প্রোটেকশন এই সবচেয়ে মৌলিক নিরাপত্তা সীমারেখাটি হার্ডওয়্যার-স্তরে নিশ্চিত করে দেয়।

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

আগের পাঠ
L47 · অথেন্টিকেশন ও অ্যাক্সেস কন্ট্রোল বেসিকস