SELinux Management Guide#
Dokumentasi operasional pengelolaan SELinux — mental model, tooling harian, dan workflow troubleshooting.
1. Mental Model: Label-Based, Bukan Path-Based#
Permission Linux biasa (DAC — Discretionary Access Control) menjawab: user ini boleh akses file ini atau tidak?
SELinux (MAC — Mandatory Access Control) menjawab pertanyaan berbeda: proses jenis ini boleh akses objek jenis ini atau tidak?
Semua entitas di sistem punya label (context) dengan format:
user:role:type:level
system_u:object_r:mssql_db_t:s0Bagian yang paling relevan untuk operasional sehari-hari adalah type (berakhiran _t). Model dominannya disebut type enforcement:
| Konsep | Penjelasan | Contoh |
|---|---|---|
| Domain | Type yang melekat pada proses | httpd_t, mssql_server_t, smbd_t |
| Object type | Type yang melekat pada file/dir/port/socket | httpd_sys_content_t, cifs_t, http_port_t |
| Allow rule | Rule di policy yang mengizinkan akses | allow httpd_t httpd_sys_content_t : file { read open getattr }; |
Prinsip utama: default deny. Kalau tidak ada allow rule yang match, akses ditolak — walaupun DAC (chmod/chown) sudah 777. DAC dan SELinux adalah dua layer independen dan keduanya harus lolos.
Contoh nyata:
mssql_server_ttidak punya allow rule kecifs_t, sehingga SQL Server on Linux ditolak membaca CIFS mount walaupun permission POSIX-nya sudah benar.
2. Mode Operasi#
getenforce # Enforcing / Permissive / Disabled
setenforce 0 # permissive (runtime, tidak persist)
setenforce 1 # enforcingKonfigurasi persist ada di /etc/selinux/config.
| Mode | Perilaku |
|---|---|
| Enforcing | Denial diblokir dan dilog |
| Permissive | Denial dilog tapi tidak diblokir — mode diagnosa, bukan “SELinux mati” |
| Disabled | Hindari. File baru dibuat tanpa label; saat dinyalakan kembali butuh full relabel (touch /.autorelabel && reboot) |
Kolom permissive=0/1 di AVC log menunjukkan mode saat denial terjadi.
Permissive per-domain (lebih presisi)#
Daripada permissive seluruh sistem, buat satu domain saja yang permissive:
semanage permissive -a mssql_server_t # hanya domain ini yang tidak di-enforce
semanage permissive -d mssql_server_t # kembalikan ke enforcing
semanage permissive -l # list domain permissiveKenapa: proteksi domain lain tetap jalan, dan semua denial dari satu service terkumpul sekaligus. Dalam mode enforcing, denial muncul satu per satu karena proses berhenti di denial pertama.
3. Membaca Denial (AVC)#
Semua denial masuk ke audit log:
ausearch -m avc -ts recent # 10 menit terakhir
ausearch -m avc -ts today
sealert -a /var/log/audit/audit.log # butuh paket setroubleshoot-server; memberi saran solusiAnatomi AVC#
avc: denied { read } ← permission yang ditolak
pid=20317 comm="\SystemRoot\Sys" ← proses
scontext=...:mssql_server_t:s0 ← SOURCE: domain proses
tcontext=...:cifs_t:s0 ← TARGET: type objek
tclass=dir ← class objek (dir/file/tcp_socket/dll)Cara membacanya selalu: “domain X minta permission Y ke type Z, class W — dan tidak ada rule yang mengizinkan.”
Empat kemungkinan solusi (urutan prioritas)#
- Label objek salah → perbaiki label (~70% kasus)
- Ada boolean yang meng-cover use case → nyalakan boolean
- Memang butuh rule baru → custom policy module
- Memang serangan/bug → biarkan diblokir; SELinux sedang bekerja
4. Mengelola Label File#
Melihat label#
ls -Z file # label file
ls -Zd /dir # label directory-nya sendiri
ps -eZ | grep mssql # domain proses
id -Z # context shell saat iniDua tempat label “hidup”#
- Label aktual — disimpan di extended attribute tiap file
- File context database — daftar mapping regex path → label default (policy + local customization)
chcon -t httpd_sys_content_t /web/file # ubah label AKTUAL saja
semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?" # ubah DATABASE
restorecon -Rv /web # apply database → label aktualJebakan umum:
chconsaja tidak cukup.restoreconatau relabel apapun akan me-reset label aktual kembali sesuai database. Workflow yang benar:semanage fcontextdulu, lalurestorecon. Gunakanchconhanya untuk eksperimen cepat.
Command pendukung#
semanage fcontext -l | grep httpd # cari type yang tepat dari mapping existing
matchpathcon /some/path # "path ini seharusnya label apa?"
restorecon -Rvn /dir # dry-run: preview perubahan tanpa mengubahPengecualian: network filesystem (CIFS / sebagian NFS)#
Network filesystem tidak menyimpan xattr SELinux per-file. Seluruh mount mendapat satu label dari mount option. chcon/restorecon tidak berpengaruh — satu-satunya kontrol lewat opsi context= di mount/fstab:
//nas-ip/share /Public cifs credentials=/root/.smbcreds,uid=mssql,gid=mssql,file_mode=0770,dir_mode=0770,context="system_u:object_r:mssql_db_t:s0" 0 0Pilih type yang memang sudah diizinkan untuk domain yang butuh akses (contoh: mssql_db_t untuk mssql_server_t), sehingga tidak perlu custom rule.
5. Booleans — Tombol On/Off Policy#
Policy writer sudah mengantisipasi banyak use case umum dalam bentuk toggle:
getsebool -a # semua boolean
getsebool -a | grep httpd # filter
semanage boolean -l # sama, plus deskripsi singkat
setsebool httpd_can_network_connect on # runtime saja
setsebool -P httpd_can_network_connect on # -P = persistContoh klasik: reverse proxy nginx/httpd ke backend gagal dengan connect() permission denied → bukan bug, tapi httpd_can_network_connect default off.
Selalu cek boolean sebelum membuat custom rule — boolean sudah di-review scope-nya oleh policy maintainer.
Contoh boolean terkait network filesystem:
setsebool -P samba_export_all_rw on # Samba boleh export semua path (longgar)
setsebool -P httpd_use_cifs on # Apache boleh baca CIFS mount
setsebool -P virt_use_samba on # virt/container boleh akses CIFS6. Port Labels#
Service hanya boleh bind ke port dengan type yang sesuai domain-nya:
semanage port -l | grep http
# http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
# izinkan nginx listen di 8888:
semanage port -a -t http_port_t -p tcp 8888
# kalau port sudah punya type lain, gunakan -m (modify), bukan -a
semanage port -m -t http_port_t -p tcp 8888Gejala khas: service gagal start dengan bind: permission denied padahal port kosong. Cek AVC — tclass=tcp_socket.
7. Custom Policy Module — Jalan Terakhir#
Gunakan hanya jika label sudah benar dan tidak ada boolean yang cocok:
# kumpulkan denial (idealnya dalam mode permissive agar lengkap), lalu:
ausearch -m avc -ts recent | audit2allow -M mymodule
cat mymodule.te # BACA DULU sebelum install!
semodule -i mymodule.pp # install
semodule -l | grep mymodule # verifikasi
semodule -r mymodule # removeKenapa harus dibaca dulu:
audit2allowmembuat rule yang persis mengizinkan apa yang ditolak, tanpa mempertimbangkan scope. Kalau denial-nyahttpd_tmembacashadow_t, dia akan membuatkan rule-nya — dan web server jadi boleh membaca/etc/shadow. Kalau.teyang dihasilkan terlihat terlalu lebar, mundur dan tanya: “apa sebenarnya label yang salah?”
audit2why menjelaskan kenapa akses ditolak dan kadang menunjuk boolean yang relevan:
ausearch -m avc -ts recent | audit2why8. Workflow Troubleshooting Standar#
1. Service error aneh → curiga SELinux?
ausearch -m avc -ts recent
2. Tidak ada AVC tapi masih curiga?
→ kemungkinan dontaudit rule menyembunyikan denial:
semodule -DB # disable dontaudit, semua denial terlihat
(reproduce masalah)
semodule -B # kembalikan
3. Ada AVC → baca scontext / tcontext / tclass
→ target type terlihat "generik" (default_t, cifs_t,
user_home_t di tempat aneh)?
→ masalah LABEL → semanage fcontext + restorecon,
atau context= di mount option (network fs)
→ audit2why menyebut boolean?
→ setsebool -P <boolean> on
→ keduanya tidak?
→ audit2allow, REVIEW .te, semodule -i
4. Verifikasi: reproduce masalah, pastikan AVC bersih9. Kenapa Tidak setenforce 0 Permanen#
SELinux adalah containment layer. Kalau service (SQL Server, nginx, dll) kena RCE, attacker hanya bisa bergerak sebatas allow rule domain tersebut — tidak bisa membaca SSH key, menulis ke /etc, atau pivot ke service lain.
setenforce 0 permanen = membuka semua pintu karena satu kunci macet. Perbaiki labelnya, bukan matikan sistemnya.
Cheat Sheet#
| Tujuan | Command |
|---|---|
| Cek mode | getenforce |
| Lihat denial terbaru | ausearch -m avc -ts recent |
| Lihat label file/dir | ls -Z file / ls -Zd /dir |
| Lihat domain proses | ps -eZ | grep <svc> |
| Label seharusnya | matchpathcon /path |
| Set label persist | semanage fcontext -a -t <type> "/path(/.*)?" lalu restorecon -Rv /path |
| Cari boolean | semanage boolean -l | grep <kw> |
| Set boolean persist | setsebool -P <bool> on |
| Izinkan port baru | semanage port -a -t <type> -p tcp <port> |
| Permissive satu domain | semanage permissive -a <domain_t> |
| Penjelasan denial | ausearch -m avc -ts recent | audit2why |
| Custom module | audit2allow -M mod → review .te → semodule -i mod.pp |
| Tampilkan denial tersembunyi | semodule -DB (kembalikan: semodule -B) |