GNU/Linux >> Belajar Linux >  >> Linux

Membangun wadah dengan tangan:Ruang nama PID

Melanjutkan seri ruang nama, artikel ini membahas PID ruang nama. Jika Anda ingin gambaran umum tentang semua ruang nama, lihat artikel pertama. Sebelumnya, Anda membuat mnt . baru ruang nama. Menariknya, seperti yang Anda temukan, bahkan setelah membuat mnt . baru namespace, Anda masih memiliki akses ke ID proses (PID) host asli. Saat Anda mencoba memasang /proc namespace, Anda menerima izin ditolak yang agak membingungkan kesalahan, seperti yang terlihat di bawah ini:

root@new-mnt$ mount -t proc proc /proc
mount: permission denied (are you root?)

root@new-mnt$ whoami
root

Meskipun Anda dapat membuat semua jenis mount di namespace mount baru, Anda tidak dapat berinteraksi atau mengubah /proc . Dalam artikel ini, saya melalui PID namespace dan tunjukkan bagaimana Anda dapat menggunakannya, bersama dengan mnt namespace, untuk mengamankan wadah pemula Anda lebih lanjut.

[ Pembaca juga menyukai: Cara kerja ruang nama PID Linux dengan container ]

Apa itu ID proses?

Sebelum melompat langsung ke PID namespace, menurut saya sebaiknya Anda memberikan sedikit latar belakang mengapa namespace ini penting.

Ketika sebuah proses dibuat pada sebagian besar sistem operasi mirip Unix, proses tersebut diberi pengenal numerik khusus yang disebut ID proses (PID). PID ini membantu mengidentifikasi proses secara unik bahkan jika ada dua proses yang memiliki nama yang sama yang dapat dibaca manusia. Misalnya, jika ada beberapa sesi ssh aktif pada sistem dan Anda perlu menutup koneksi tertentu, PID menyediakan cara bagi administrator untuk memastikan sesi yang benar ditutup.

Semua proses ini dilacak dalam sistem file khusus yang disebut procfs . Meskipun sistem file ini secara teknis dapat dipasang di mana saja, sebagian besar perkakas (dan konvensi) mengharapkan procfs untuk dipasang di bawah /proc . Jika Anda melakukan daftar /proc , Anda akan melihat folder untuk setiap proses yang sedang berjalan di sistem Anda. Di dalam folder ini terdapat semua jenis file khusus yang digunakan untuk melacak berbagai aspek proses. Untuk tujuan artikel ini, file-file ini tidak penting. Cukup mengetahui bahwa /proc adalah tempat sebagian besar sistem mirip Unix menyimpan informasi mengenai proses pada sistem yang sedang berjalan.

Ruang nama PID

Salah satu alasan utama PID namespace adalah untuk memungkinkan isolasi proses. Lebih khusus lagi, seperti yang dikatakan halaman manual:

Ruang nama PID mengisolasi ruang nomor ID proses, artinya proses di ruang nama PID yang berbeda dapat memiliki PID yang sama.

Ini penting karena ini berarti bahwa proses dapat dijamin tidak memiliki PID yang bertentangan dengan proses lainnya. Ketika mempertimbangkan satu sistem, tentu saja, tidak ada kemungkinan PID bertentangan karena sistem secara terus-menerus menambah nomor ID proses dan tidak pernah menetapkan nomor yang sama dua kali. Saat berhadapan dengan kontainer di beberapa mesin, masalah ini menjadi lebih menonjol. Seperti yang dijelaskan di halaman manual:

Ruang nama PID memungkinkan container menyediakan fungsionalitas seperti menangguhkan/melanjutkan rangkaian proses dalam container dan memigrasi container ke host baru sementara proses di dalam container mempertahankan PID yang sama.

Selain isolasi, sistem PID bekerja hampir identik dengan yang di luar namespace. ID proses di dalam namespace baru dimulai dari 1 , dengan proses pertama dianggap sebagai init proses. Inisi proses ditangani dengan sangat berbeda dari semua PID lain pada sebuah host. Ini memiliki implikasi khusus untuk sistem yang berjalan yang berada di luar cakupan seri ini. Jika Anda tertarik dengan informasi lebih lanjut, lihat bagian "Sinyal dan proses init" dari artikel Ruang Nama LWN.

Namun, yang perlu diperhatikan adalah proses mana pun yang memiliki PID 1 sangat penting untuk umur panjang namespace. Jika PID 1 dihentikan karena alasan apa pun, kernel akan mengirimkan SIGKILL ke semua proses yang tersisa di namespace, secara efektif mematikan namespace tersebut.

Menjelajahi ruang nama PID

Jika Anda bertanya-tanya, seperti saya, apakah Anda dapat membuat sarang PID namespaces, jawabannya adalah ya. Faktanya, kernel menyediakan ruang hingga 32 PID ruang nama. Ini dianggap sebagai hubungan satu arah. Itu berarti orang tua dapat melihat PID anak, cucu, dll. Namun, tidak dapat melihat PID leluhurnya. Pertimbangkan hal berikut:

[user@localhost ~] sudo unshare -fp /bin/bash
[root@localhost ~] sleep 90000 &

[root@localhost ~] ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
[truncated ]
.....
root       11627   11620  0 09:16 pts/0    00:00:00 sudo unshare -fp /bin/bash
root       11633   11627  0 09:17 pts/0    00:00:00 unshare -fp /bin/bash
root       11634   11633  0 09:17 pts/0    00:00:00 /bin/bash
root       11639   11634  0 09:17 pts/0    00:00:00 sleep 90000
root       11641   11634  0 09:17 pts/0    00:00:00 ps -ef

[root@localhost ~] sudo unshare -fp /bin/bash
[root@localhost ~] sleep 8000 &

[root@localhost ~] ps -ef
[truncated ]
.....

UID          PID    PPID  C STIME TTY          TIME CMD
root       11650   11634  0 09:17 pts/0    00:00:00 sudo unshare -fp /bin/bash
root       11654   11650  0 09:17 pts/0    00:00:00 unshare -fp /bin/bash
root       11655   11654  0 09:17 pts/0    00:00:00 /bin/bash
root       11661   11655  0 09:17 pts/0    00:00:00 sleep 8000
root       11671   11655  0 09:17 pts/0    00:00:00 ps -ef

Anda akan melihat bahwa saya memotong output karena PID namespace muncul untuk memiliki akses penuh ke semua PID di /proc . Amati apa yang terjadi jika Anda mencoba menghentikan proses yang ada di ancestor:

[root@localhost ~] kill -9 11361
bash: kill: (11361) - No such process

Kenapa ini? Sederhananya, alat tradisional seperti ps tidak mengetahui namespace dan benar-benar membaca dari /proc direktori. Jika Anda melakukan ls /proc , Anda masih akan melihat semua folder dan file sebelumnya karena, seperti yang dibahas dalam artikel terakhir, PID namespace mewarisi semua mnt pemasangan namespace. Saya mengatasi situasi ini nanti. Untuk saat ini, kembali ke contoh yang ada.

Di shell lain, identifikasi proses tidur:

[user@localhost ~] ps -ef |grep sleep
root       11639   11634  0 09:17 pts/0    00:00:00 sleep 90000
root       11661   11655  0 09:17 pts/0    00:00:00 sleep 8000

Jika Anda ingin memverifikasi bahwa proses ini berada di ruang nama yang berbeda, Anda harus menemukan bash proses PID. Ingat, karena Anda menjalankan sudo unshare -fp /bin/bash , bash proses adalah init proses di namespace baru. Oleh karena itu, PID-lah yang akan ditautkan ke ID namespace. Ayo ambil PIDnya:

[root@localhost ~] ps -ef |grep bash
root       11627   11620  0 09:16 pts/0    00:00:00 sudo unshare -fp /bin/bash
root       11633   11627  0 09:17 pts/0    00:00:00 unshare -fp /bin/bash
root       11634   11633  0 09:17 pts/0    00:00:00 /bin/bash
root       11650   11634  0 09:17 pts/0    00:00:00 sudo unshare -fp /bin/bash
root       11654   11650  0 09:17 pts/0    00:00:00 unshare -fp /bin/bash
root       11655   11654  0 09:17 pts/0    00:00:00 /bin/bash

Anda dapat melihat PID 11634 dan 11655 dalam keluaran. Jika Anda membandingkan ini dengan output lsns (daftar ruang nama), Anda akan melihat yang berikut:

[root@localhost ~] lsns |grep bash
        NS TYPE   NPROCS    PID USER             COMMAND
4026532952 pid         4 11634 root             /bin/bash
4026532954 pid         4 11655 root             /bin/bash

Seperti yang Anda lihat, ID namespace berbeda, dan dengan demikian proses berada di namespace yang berbeda.

Sekarang setelah Anda menetapkan namespace yang memang berbeda, mari kita lihat ancestry PID yang disebutkan sebelumnya. Anda dapat melakukannya dengan mengidentifikasi NSpid atribut dari PID tertentu di /proc direktori, seperti yang terlihat di bawah ini:

sudo cat /proc/11655/status |grep NSpid
NSpid:    11655    6    1

Kolom dibaca dari kiri ke kanan dan menunjukkan PID di ruang nama masing-masing. PID paling kiri adalah namespace utama atau root. Dalam hal ini, ia memiliki PID 11655 , PID sekunder 6 , dan PID tersier 1 . Karena ruang nama memiliki setiap turunan PID namespace, Anda dapat memikirkannya seperti ini:

  • Pada host, bash proses menjalankan sleep 8000 perintah memiliki PID 11655 .
  • Di dalam "wadah" pertama, bash proses menjalankan sleep 8000 perintah memiliki PID 6 .
  • Di dalam "wadah" kedua yang disarangkan, PIDnya adalah 1 . Ini adalah wadah yang sebenarnya meluncurkan proses.

Masing-masing dari bash ini perintah dibuat di dalam namespacenya sendiri tetapi dapat dilihat oleh induknya (dalam hal ini, root ruang nama).

/proc, PID, dan pengguna yang tidak memiliki hak istimewa

Pembaca yang cerdik akan memperhatikan bahwa, dalam dua artikel terakhir, pengguna biasa dapat membuat keduanya pengguna dan mnt ruang nama. Dalam artikel ini, saya telah menggunakan sudo memerintah. Ini karena Anda tidak dapat membuat PID namespace sendiri dengan pengguna yang tidak memiliki hak istimewa. Jawabannya adalah menggabungkan beberapa kreasi namespace menjadi satu acara. Ada beberapa solusi berbeda untuk memasang /proc sebagai pengguna yang tidak memiliki hak istimewa.

Jika Anda hanya mencoba membuat pengguna baru namespace, Anda akan mendapatkan hasil yang aneh:

[ user@localhost ~] unshare -Urp
-bash: fork: Cannot allocate memory
-bash-5.1# ps -ef
-bash: fork: Cannot allocate memory
-bash-5.1# ls
-bash: fork: Cannot allocate memory

Apa yang terjadi disini? Ingat bagaimana proses pertama di dalam PID baru namespace menjadi init proses? Dalam hal ini, shell saat ini tidak dapat memindahkan ruang nama. Itu ada di root namespace, dan saat Anda membuat PID . baru namespace, sistem tidak tahu bagaimana menanganinya. Solusi untuk ini adalah memiliki garpu proses itu sendiri. Ini memungkinkan shell saat ini menjadi proses anak dari unshare memerintah. Menggunakan -f tandai hasil di namespace yang sedang dibuat:

[ user@localhost ~] unshare -Urfp
[ root@localhost ~]

Namun, Anda masih melihat kontaminasi /proc titik pemasangan. Ada dua solusi untuk ini. Pertama, Anda dapat membuat mnt . baru namespace dan kemudian remount /proc sendiri:

[ user@localhost  ~]$ unshare -Urpmf
[ root@localhost ~]# mount -t proc proc /proc
[ root@localhost ~]# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:31 pts/0    00:00:00 -bash
root          10       1  0 09:31 pts/0    00:00:00 ps -ef

Memang, selama bertahun-tahun ini adalah satu-satunya pilihan tetapi, sebuah flag --mount-proc telah dibuat beberapa waktu lalu untuk melakukan ini dalam satu langkah. Halaman manual berbunyi:

Tepat sebelum menjalankan program, mount sistem file proc di mountpoint (defaultnya adalah /proc). Ini berguna saat membuat namespace PID baru. Ini juga berarti membuat namespace mount baru karena /proc mount akan mengacaukan program yang ada di sistem. Sistem file proc baru secara eksplisit dipasang sebagai pribadi (dengan MS_PRIVATE|MS_REC).

Jadi, oleh karena itu, Anda mungkin melihat referensi ke perintah berikut:

unshare -Urpf --mount-proc

Ini menciptakan mnt . baru namespace saat memasang /proc untukmu.

Memasukkan namespace

Untuk mengurangi kerumitan, saya telah keluar dari ruang nama yang dibuat sebelumnya. Saya telah membuat namespace baru dengan perintah berikut:

unshare -Urfp --mount-proc

Saya juga telah membuat berbeda sleep proses hanya untuk membantu mengidentifikasi namespace. Karena saya hanya memiliki satu namespace baru, saya dapat menggunakan lsns perintah untuk menentukan PID yang benar:

[ user@localhost  ~]$ lsns |grep bash
4026532965 pid         2 13142 user -bash

Kemudian jalankan nsenter perintah:

sudo nsenter -t 13142 -a

-a flag memberitahu nsenter perintah untuk memasukkan semua ruang nama PID itu. sudo diperlukan dengan -a bendera, atau Anda tidak akan dapat mengubah ke semua ruang nama yang sesuai. Anda sekarang dapat membuat daftar semua PIDS di NS ini:

[ root@localhost  ~]$ ps -ef

UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:54 pts/0    00:00:00 -bash
root           8       1  0 09:54 pts/0    00:00:00 sleep 99999
root          25       0  0 10:15 pts/1    00:00:00 -bash
root          31      25  0 10:15 pts/1    00:00:00 ps -ef

[ Pelajari dasar-dasar penggunaan Kubernetes di lembar contekan gratis ini. ] 

Menutup

PID namespace adalah salah satu yang penting dalam hal membangun lingkungan yang terisolasi. Hal ini memungkinkan proses untuk memiliki PID mereka sendiri terlepas dari sistem host. Di dunia di mana banyak host mungkin terlibat dalam mengatur lingkungan yang terisolasi (kontainer), menjadi penting untuk memiliki fasilitas yang menjamin PID unik saat membekukan dan memigrasikan proses. Selain itu, untuk alasan keamanan, jika Anda menjalankan ruang nama untuk isolasi aplikasi, PID namespace sangat penting untuk mencegah kebocoran informasi melalui proses yang mungkin dijalankan oleh host.

Saat digabungkan dengan pengguna dan mnt ruang nama, PID namespace memberikan banyak perlindungan tanpa memerlukan hak akses root. Peramban modern seperti Firefox dan Vivaldi menggunakan ruang nama untuk menyediakan kotak pasir peramban. Di artikel berikutnya, saya akan mendemonstrasikan net namespace dan lihat bagaimana Anda dapat terus membuat container secara manual dengan menambahkan komponen jaringan terpisah.


Linux
  1. Nilai Maksimum Id Proses?

  2. Linux – Menemukan Pid Proses Menggunakan Port Tertentu?

  3. Proses Yang Memiliki Pid 0?

  1. Membangun Awan Pajak

  2. Bagaimana cara menghitung penggunaan CPU dari suatu proses oleh PID di Linux dari C?

  3. Periksa batas FD terbuka untuk proses tertentu di Linux

  1. Apa PID di host, dari proses yang berjalan di dalam container Docker?

  2. Menentukan prosesor tertentu di mana proses sedang berjalan

  3. Cara menemukan file .pid untuk proses tertentu