Ketika CPU dalam mode pengguna, CPU tidak dapat menjalankan instruksi yang diistimewakan dan tidak dapat mengakses memori ruang kernel.
Dan ketika CPU dalam mode kernel, CPU dapat menjalankan semua instruksi dan dapat mengakses semua memori.
Sekarang di Linux, program mode pengguna dapat mengakses semua memori (menggunakan /dev/mem
) dan dapat menjalankan dua instruksi istimewa IN
dan OUT
(menggunakan iopl()
saya pikir).
Jadi program mode pengguna di Linux dapat melakukan banyak hal (saya pikir sebagian besar hal) yang dapat dilakukan dalam mode kernel.
Tidak memungkinkan program mode pengguna untuk memiliki semua kekuatan ini mengalahkan tujuan memiliki mode CPU?
iopl
tidak mengizinkan semua instruksi istimewa, jadi masih berguna untuk memastikan program ruang pengguna buggy tidak sengaja dijalankaninvd
dengan melompat melalui pointer fungsi yang rusak yang menunjuk pada memori yang dapat dieksekusi dimulai dengan0F 08
byte. Saya menambahkan jawaban dengan beberapa alasan non-keamanan mengapa bermanfaat jika proses ruang pengguna meningkatkan hak istimewa mereka.Hanya dengan cara yang sama yang
modprobe
"mengalahkan" keamanan dengan memuat kode baru ke dalam kernel.Karena berbagai alasan, kadang-kadang lebih masuk akal untuk memiliki kode semi-privilege (seperti driver grafis di dalam server X) yang berjalan di ruang pengguna daripada thread kernel.
kill
dengan lebih mudah, kecuali itu mengunci HW.Itu tidak melakukan banyak untuk keamanan, tetapi ada keandalan besar dan keunggulan arsitektur perangkat lunak.
Memanggang driver grafis ke dalam kernel dapat mengurangi switch konteks antara klien X dan server X, seperti hanya satu pengguna-> kernel-> pengguna daripada harus memasukkan data ke proses penggunaan-ruang lain, tetapi server X secara historis terlalu besar dan terlalu bermasalah. ingin mereka sepenuhnya di kernel.
Ya, kode jahat dengan privs ini dapat mengambil alih kernel jika diinginkan, gunakan
/dev/mem
untuk mengubah kode kernel.Atau pada x86 misalnya, jalankan
cli
instruksi untuk menonaktifkan interupsi pada inti tersebut setelah melakukaniopl
pemanggilan sistem untuk mengatur tingkat hak istimewa IO untuk berdering 0.Tetapi bahkan x86
iopl
"only" memberikan akses ke beberapa instruksi : in / out (dan versi string sel / out), dan cli / sti. Itu tidak membiarkan Anda menggunakanrdmsr
atauwrmsr
membaca atau menulis "register model spesifik" (mis.IA32_LSTAR
Yang menetapkan alamat titik entri kernel untuksyscall
instruksi x86-64 ), atau digunakanlidt
untuk mengganti tabel interrupt-descriptor (yang akan membuat Anda benar-benar mengambil melalui mesin dari kernel yang ada, setidaknya pada inti itu.)Anda bahkan tidak dapat membaca register kontrol (seperti CR3 yang menyimpan alamat fisik direktori-halaman tingkat atas, yang mana suatu proses serangan mungkin berguna sebagai pengimbang
/dev/mem
untuk memodifikasi tabel halamannya sendiri sebagai alternatif untuk mengambilmmap
lebih banyak/dev/mem
. )invd
(batalkan semua cache tanpa write-back !! ( use case = BIOS awal sebelum RAM dikonfigurasi)) adalah kesenangan lain yang selalu membutuhkan CPL 0 penuh (level privilege saat ini), bukan hanya IOPL. Bahkanwbinvd
istimewa karena sangat lambat (dan tidak terputus), dan harus mem - flush semua cache di semua core. (Lihat Apakah ada cara untuk menyiram seluruh cache CPU yang terkait dengan suatu program? Dan penggunaan instruksi WBINVD )Bug yang mengakibatkan lompatan ke alamat yang buruk menjalankan data sebagai kode sehingga tidak bisa menjalankan instruksi ini secara tidak sengaja di server X ruang pengguna.
Level privilege saat ini (dalam mode terlindungi dan panjang) adalah 2 bit rendah
cs
(pemilih segmen kode) .mov eax, cs
/and eax, 3
Bekerja dalam mode apa pun untuk membaca tingkat hak istimewa.Untuk menulis level privilege, Anda melakukan
jmp far
ataucall far
untuk mengaturCS:RIP
(tetapi entri GDT / LDT untuk segmen target dapat membatasinya berdasarkan level privilege lama, itulah sebabnya ruang pengguna tidak dapat melakukan ini untuk meningkatkan dirinya sendiri). Atau Anda menggunakanint
atausyscall
untuk beralih ke dering 0 pada titik masuk kernel.sumber