chroot gagal di OpenVPN: aturan AppArmor atau kapabilitas?
Menambahkan jalur ke profil AppArmor tidak pernah memberikan CAP_SYS_CHROOT, dan chroot yang ditolak bisa berasal dari tiga lapisan terpisah. Tentukan lapisan mana yang perlu diubah.
Daemon mencatat kegagalan chroot dan profilnya sudah tampak longgar, jadi perbaikan yang menggiurkan adalah memperlebar aturan jalur dan memulai ulang. Biasanya itu tidak mengubah apa pun, karena chroot dijaga oleh hak istimewa yang tidak pernah bisa diberikan profil tersebut. Memutuskan lapisan mana yang perlu disentuh memerlukan tiga pemeriksaan, dan semuanya murah: apa yang boleh dipegang proses, apa yang diizinkan kebijakan, dan apa yang sudah dihapus peluncur sebelum keduanya sempat berarti.
Dua gerbang terpisah, dan hanya satu milik AppArmor
chroot membutuhkan CAP_SYS_CHROOT di ruang nama pengguna tempat proses berjalan. Itu hak istimewa Linux biasa, dan kernel memeriksanya sebelum panggilan melakukan apa pun dengan jalur. Secara terpisah, profil AppArmor yang menegakkan aturan dapat menolak kapabilitas itu walaupun proses memilikinya, karena kebijakan wajib diperiksa sebagai tambahan atas kredensial, bukan sebagai penggantinya. Perbedaan ini penting dalam praktik: kedua lapisan hidup di berkas berbeda dan biasanya dirawat oleh orang berbeda.
Kedua gerbang itu gagal dengan errno yang sama. Keduanya menghasilkan EPERM, dan keduanya muncul sebagai keluhan izin umum di log daemon, itulah sebabnya menebak isi profil membuang begitu banyak waktu. Aturan jalur yang hendak Anda tambahkan mengatur akses berkas setelah chroot berhasil; ia tidak berpengaruh pada apakah operasi itu diizinkan sama sekali.
Gerbang ketiga berada di hulu keduanya. Jika manajer layanan atau pembungkus menjalankan proses tanpa kapabilitas itu di himpunan batasnya, tidak ada perubahan AppArmor yang bisa mengembalikannya, dan menambahkan kapabilitas ke profil hanya mendokumentasikan niat yang tidak akan dihormati kernel.
Baca keadaan hak istimewa sebelum menyunting kebijakan
Mulailah dari proses yang berjalan, bukan dari konfigurasi yang Anda anggap aktif. Berkas status menampilkan lima masker kapabilitas dan flag no-new-privileges, dan semuanya menjawab pertanyaan berbeda:
grep -E '^(CapInh|CapPrm|CapEff|CapBnd|CapAmb|NoNewPrivs):' /proc/$(pidof openvpn)/status
sudo aa-status | grep -i openvpnCapEff adalah himpunan yang penting bagi panggilan: kapabilitas yang ada di CapBnd tetapi tidak ada di CapEff diizinkan oleh batas atas dan tidak sedang dipegang. CapAmb penting ketika biner tidak berhak istimewa dalam arti setuid yang lazim, karena kapabilitas ambient adalah cara layanan mempertahankan hak istimewa melewati exec tanpa kapabilitas berkas. CapInh menyimpan bit yang dapat diwariskan melewati exec, tetapi hanya bila himpunan warisan berkas yang dieksekusi mengizinkannya, jadi satu bit di sana tidak memberi apa pun dengan sendirinya.
Lalu pastikan profil mana yang benar-benar terpasang. Sebuah proses bisa dibatasi oleh nama profil yang tidak Anda duga, terutama ketika distribusi mengirim berkas unit dan profilnya bersamaan, dan membaca /proc/PID/attr/current menyelesaikannya dalam satu baris. Membandingkan berkas yang Anda sunting dengan profil yang dilaporkan kernel adalah perbedaan antara memperbaiki penyebab dan menyunting berkas yang tidak dimuat siapa pun.
Tambahkan aturan kapabilitas hanya bila jejak audit mengatakannya
Catatan kernel dan audit menyebutkan lapisan yang menolak. Carilah penolakan yang membawa operasi capable dan nama sys_chroot, bersama profil yang menghasilkannya. Jika catatan itu ada, proses sudah memegang kapabilitasnya dan AppArmor menolaknya, dan perubahan yang tepat sasaran adalah aturan kapabilitas di dalam profil yang sebenarnya:
capability sys_chroot,Simpan sebagai fragmen di profil yang benar-benar terpasang, dan periksa kata kuncinya terhadap referensi profil apparmor.d alih-alih menyalin aturan dari tutorial yang tidak berkaitan. Menempatkannya di include bersama memberikannya kepada setiap program terbatas yang menarik berkas itu, dan mengalihkan profil ke mode keluhan menyembunyikan penolakan berikutnya alih-alih menyelesaikan yang ini. Aturan profil menghapus penolakan kebijakan; ia tidak menciptakan hak istimewa, jadi proses yang tidak pernah memiliki CAP_SYS_CHROOT di himpunan efektifnya tetap akan gagal meski aturannya ada.
Jika catatan audit tidak menunjukkan penolakan AppArmor sama sekali, berhentilah menyunting profil. Anda menghadapi masalah kredensial, dan sisa pekerjaannya ada di berkas unit atau proses induk, bukan di bahasa kebijakan.
Manajer layanan punya batas atasnya sendiri
systemd menetapkan himpunan batas kapabilitas untuk setiap layanan, dan secara default himpunan itu sempit. Apa pun yang dikecualikan di sana tidak tersedia bagi proses, apa pun kata profil, itulah sebabnya unit yang dikeraskan bisa gagal pada operasi yang berhasil ketika daemon dijalankan dengan tangan. Direktif terkait mudah dibaca di unit dan mudah terlewat ketika aplikasi melaporkan kegagalannya. Drop-in yang dikirim paket distribusi adalah sumber lazim batas atas yang tidak diingat siapa pun pernah mengonfigurasinya.
Menaikkan batas atas dan memberikan kapabilitas adalah dua perubahan, bukan satu. Entri di himpunan batas mengatakan proses boleh memegang kapabilitas itu; entri itu tidak menambahkannya ke himpunan efektif, dan NoNewPrivs dapat mencegah peningkatan berikutnya berhasil bahkan ketika semua hal lain cocok. Tambahkan hanya yang dibutuhkan operasi, biarkan bagian pengerasan lainnya utuh, dan tolak jalan pintas memberikan semua kapabilitas agar satu panggilan lolos.
Urutan juga penting di sini. Ubah dulu batas atas unit, pastikan CapEff kini memuat bit itu, dan baru setelah itu putuskan apakah AppArmor masih menolak. Melakukan kedua perubahan sekaligus membuat Anda menebak lagi bila kegagalan berlanjut.
Setelah penolakan hilang, periksa kurungannya sendiri
chroot yang berhasil memindahkan akar, jadi setiap jalur yang disentuh daemon sesudahnya diselesaikan di dalam pohon baru. Konfigurasi yang hilang, simpul perangkat yang tidak ada, atau direktori sertifikat yang tidak tersalin kini akan muncul sebagai galat berkas, dan galat itu masalah tata letak, bukan kapabilitas. Baca peristiwa berikutnya alih-alih menambahkan izin luas lagi. Pemindahan itu juga mengubah arti jalur relatif, itulah sebabnya panduan pengerasan menuntut jalur absolut dalam konfigurasi daemon.
Berguna juga mengingat apa yang tidak dilakukan chroot. Ia adalah batas jalur, bukan kotak pasir: proses yang mempertahankan hak istimewa dapat lolos darinya, itulah sebabnya kapabilitas biasanya dilepas setelah panggilan dan itulah sebabnya pembatasan harus tetap ada di sekitar daemon. Mempertahankan profil AppArmor, himpunan batas kapabilitas, dan pembatasan sistem berkas bersama-sama adalah inti latihan ini, bukan sisa yang dibuang begitu layanan menyala.
Aturan keputusannya singkat. Jika catatan audit menyebut AppArmor, tambahkan satu aturan kapabilitas ke profil yang terpasang. Jika himpunan efektif kosong, perbaiki batas atas unit dan urutan pelepasan hak istimewa. Jika profilnya bukan yang Anda sunting, berhenti menyunting dan temukan yang sebenarnya.