:::: MENU ::::
Posts tagged with: selinux

SELinux entegrasyonu nasil yapilir?

SELinux çalışan bir Linux sistemini ayaga kaldırmak için gereken çalışmalar anlatılacaktır. 

Kernel seviyesinde SELinux

Kernel’in derleneceği toolchain, 2014-09 linaro arm-linux-gnueabihf’nin SELinux özelinde geliştirilmiş halidir. Repo adresi: https://github.com/eckucukoglu/arm-linux-gnueabihf

Kernel olarak 3.10.80 Linux kernel’i kullanılacaktır. 
omap2plus_defconfig ile konfigüre edilen kernelde, ardindan ethernet için usb, eger pandaboard es chipsee expansion board kullaniliyorsa, ekranı için chipsee dpi, input device için touchscreen ads7846 sürücüleri açılabilir.

CONFIG_USB_EHCI_HCD
CONFIG_USB_PHY
CONFIG_NOP_USB_XCEIV
CONFIG_PANEL_CHIPSEE_DPI
CONFIG_TOUCHSCREEN_ADS7846

Ardından SELinux için gerekli konfigurasyon ayarları açılmalıdır. Bunlar:

CONFIG_AUDIT
CONFIG_SECURITY_NETWORK
CONFIG_SECURITY_SELINUX
DEFAULT_SECURITY_SELINUX

Ayrıca kullanılan filesystem için ‘extended attribute’ desteği açılmalıdır. Bunlar ise (ext2 filesystem için):

CONFIG_EXT2_FS_XATTR
CONFIG_EXT2_FS_SECURITY

Diğer SELinux ayarları da incelenip, ihtiyaca göre kullanılabilinir. Bunlara ek olarak debug amaçlı low-level debugging özelliği de açılabilir.

CONFIG_DEBUG_LL
DEBUG_OMAP4UART3
CONFIG_EARLY_PRINTK

Userspace seviyesinde SELinux

Userspace’de selinux kütüphanelerini derledikten sonra rootfs içerisine koymalıyız. Fakat öncelikle buildroot ile ihtiyaç duyulan temel araçları içeren bir rootfs paketi cikartilabilinir.

Cikan rootfs icerisinde asagidaki degisiklikler, ihtiyaca gore, uygulanabilir:

  • NFS kullanildigi durumda, /etc/network/interfaces dosyasından dhcp servisi kapatılmalı, cihaz nfs kullanıyorsa network bilgileri girilmelidir.
  • auditd kullaniliyor ve baslatilmasinda sikinti varsa: /etc/audit/auditd.conf dosyasının owner’ı değiştirilmeli ve dispatcher adresi güncellenmeli. (audit deamon çalışması için yapılmaktadır. /etc/init.d/S01auditd start yazarak manuel başlatılarak, hata vermesi durumunda /var/log/messages kontrol edilebilinir.)
  • libpcre.so.3 (sistemdeki libpcre’e bağlanacak) symlink oluşturulmalı. (buildroot rootfs’lerinde karsilastigim bir hata, cozumunu bu sekilde sagliyorum.)
  • m4 binary’si /usr/bin içerisine atılacak. (refpolicy-arm için gerekli)

Bu işlemlerin ardından şu repodaki selinux derlenmelidir: https://github.com/eckucukoglu/selinux-arm
Derleme esnasında yine aynı toolchain kullanılacaktır. Çıkan dosyalar olduğu gibi rootfs içerisine kopyalanabilir.

Reference policy yükleme

Sistemimizde SELinux userspace kütüphaneleri ve araçları yer alıyorsa, bir sonraki aşamada SELinux reference policy project derlenerek sisteme yüklenmelidir. Bu policy içerisinde, gömülü bir sistemin ihtiyaçlarından çok fazlası yer almaktadır. Bu nedenle direkt olarak reference policy’nin kullanılması doğru değildir. Gömülü, mobil sistemlerin ihtiyaçları doğrultusunda aşamalı olarak kırpılması gerekmektedir.

Reference policy project için su repo kullanilmistir: https://github.com/eckucukoglu/refpolicy-arm

Burada önemli olan nokta contrib modülü (policy/modules/contrib) bir subproject olduğu için, proje clone’lanırken bu dizin içindeki dosyaların varlığı kontrol edilmelidir.

Proje içinde çalışmaya başlamadan önce “make bare” diyerek olası ihtiyaç dışı dosyaları temizlemek gerekebilir.
Öncelikle build.conf dosyası aşağıdaki ayarlar geçerli olacak şekilde güncellenmiştir:

TYPE = standard 
NAME = targeted 
UNK_PERMS = deny 
DIRECT_INITRC = y 
MONOLITHIC = y/n /* monolithic vs modular secimi tercihe gore yapılmalıdır */
UBAC = n 
CUSTOM_BUILDOPT = 
MLS_SENS = 16 
MLS_CATS = 256 
MCS_CATS = 256 
QUIET = n

Ardından derleme işlemine geçmeden önce, sistemin ihtiyaç duyduğu libaudit.so desteği sağlanmalıdır. Eğer sistemde mevcut bir libaudit.so dosyası varsa, ihtiyaç duyulana linklenebilir. Örnek vermek gerekirse sistemde libaudit.so.0 aranıyor fakat libaudit.so.1 mevcut ise, şu şekilde bağlantı oluşturulabilinir:

ln -s libaudit.so.1 libaudit.so.0

modular seçim için:

Bu işlemlerin ardından rootfs içerisine, policy derleme ve yükleme işlemleri esnasında ihtiyaç duyulacak aşağıdaki uygulamalar derlenerek sistem içerisine atılmalıdır:

  • m4 (make conf esnasında kullanılır)
  • gawk (make base esnasında kullanılır)
  • make
  • python

İlerde çağrılacak komutlardan make conf için xml.dom.minidom paketi gerekmektedir. Bu sebeple python’un derlenirken içerisinde bu paketin ve bağlantılı paketlerin yer aldığından emin olmak gerekiyor.

Burada python için libtinfo, libssl, libcrypto kütüphaneleri sistemde hazır bulunmalıdır.

Bu işlemlerin ardından sırasıyla aşağıdaki komutlar çalıştırılacaktır. İşlevlerini öğrenmek için SELinux notebook sayfa 256-257’ye bakılabilir.

make conf
make base
make modules
make install
make load

monolithic seçim için:

Buildroot üzerinden  çıkartılan rootfs üzerine, (bu sistemde gawk, python, auditd, setools, make yüklü olmalidir) şu işlemler yapılmalıdır:

  • m4 sistem içerisine yüklenmelidir.
  • ardından refpolicy-arm içerisinde sırasıyla şu komutlar çalıştırılmalıdır:
make conf
make install

Reference policy işlemlerinin ardından /etc/selinux/config dosyasının aşağıdaki içerik ile oluşturulması gerekmektedir:

SELINUX=enforcing
SELINUXTYPE=targeted



SELinux mode configuration details

There exists some blog posts, articles about SELinux mode configuration already, which easily can be found by searching on google: “how to enable/disable selinux, how to configure selinux”. Moreover, The SELinux Notebook 4th edition has information about SELinux modes and global configuration files, respectively in chapter 2.15 and 3.2.1. However, I think, SELinux has some controversial issues about mode configuration and none of these resources are good enough to clear the mind about confusing SELinux mode configuration.
First of all, linux kernel has some configuration options which allows/disallows SELinux to be disabled/enabled. These options are:

  • CONFIG_SECURITY_SELINUX_BOOTPARAM: This option allows SELinux to be disabled at boot. If this option is selected, SELinux functionality can be disabled with selinux=0 on the kernel command line. Moreover, SELinux boot parameter default value can be changed by setting CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE to 0 or 1, respectively disabling or enabling SELinux at bootup.
  • CONFIG_SECURITY_SELINUX_DISABLE: This option enables writing to a selinuxfs node ‘disable’, which allows SELinux to be disabled at runtime prior to the policy load. That means, kernel will be “capable” to disable SELinux at runtime.  In here, Stephen Smalley claims that /sys/fs/selinux/disable can be triggered by setting SELINUX=disabled in /etc/selinux/config. However modifications on /etc/selinux/config file does not affect system until next boot-up. So that, it is the first confusing thing, since linux kernel commented on this option: “SELinux will remain disabled until the next boot”. I still do not know how to disable SELinux (disable, not permissive) at runtime by the help of this kernel configuration.
  • CONFIG_SECURITY_SELINUX_DEVELOP: With this option enabled, the kernel will start in permissive mode unless you specify enforcing=1 on the kernel command line.

So far, we know that these arguments can be passed to kernel:

  • selinux=1 /* enabled */
  • selinux=0 /* disabled */
  • enforcing=1 /* enabled & enforcing */
  • enforcing=0 /* enabled & permissive */

Additionally, from Dan Walsh’s blogpost, there is also

  • autorelabel=1

boot argument to relabel the system with exact security contexts.
Furthermore, another way to configure SELinux modes is global configuration file: /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.

According to these options, SELinux modes can be changed. However which option overrides the other one is confusing.

Temporarily switching between permissive and enforcing

Two way to switch between permissive and enforcing at runtime. Note that after reboot these options will be overriden by the system defaults. Moreover, switching to permissive/enforcing mode is only applicable unless selinux is disabled.

  • Using selinuxfx
# switching to enforcing
echo 1 > /sys/fs/selinux/enforce
# switching to permissive
echo 0 > /sys/fs/selinux/enforce
  • Using setenforce utility
# switching to enforcing
setenforce 1 /* or setenforce Enforcing */
# switching to permissive
setenforce 0 /* or setenforce Permissive */

Permanently switching SELinux modes

The second confusing thing about SELinux mode configuration is that even though kernel boot parameters override the config file, the exact opposite of this action is also possible. To clarify this options, I have made some tests on my running ARM platform. Note that, I compiled kernel with these configs:

CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_SECURITY_SELINUX_DEVELOP=y
CONFIG_SECURITY_SELINUX_AVC_STATS=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
  • No boot parameters and no config file exists, then system boots at Permissive mode. CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE & CONFIG_SECURITY_SELINUX_DEVELOP configurations are the reason of that. In fact, selinux=1 is passed as default.
  • None or selinux=1 as boot parameters and SELINUX=enforcing in config file, then system boots at Enforcing.
  • None or selinux=1 as boot parameters and SELINUX=permissive in config file, then system boots at Permissive.
  • None or selinux=1 as boot parameters and SELINUX=disabled in config file, SELinux:  Disabled at runtime.
  • If selinux=0 passed as kernel boot parameter, then SELinux will be disabled whatever passed in config file. However, it is not recommended.
  • enforcing=0 as boot parameter, SELINUX=enforcing in config file, then system boots at Permissive mode.
  • enforcing=0 as boot parameter, SELINUX=disabled in config file, then SELinux:  Disabled at runtime.
  • enforcing=1 passed as boot parameter, SELINUX=permissive in config file, then system boots at Enforcing mode.
  • enforcing=1 passed as boot parameter, SELINUX=disabled in config file, then unexpectedly: SELinux:  Disabled at runtime and kernel panic occurs since can’t load SELinux Policy. I do not know the exact reason of this error. I actually tried to relabel filesystem before enforcing the system, so expected result of this action should be Enforcing system boot-up.

So, boot argument selinux=0 overrides /etc/config/selinux, however selinux=1 does not overrides. Moreover, while passing enforcing=0, even though in /etc/selinux/config includes SELINUX=enforcing, system starts w/ permissive mode. However if config file includes SELINUX=disabled, system starts w/o SELinux. I think this is confusing and kind of inconsistent but there should be a good rationale for that. Most people hardly ever get confronted with these situations.

Switching from disabled to enabled

As mentioned gentoo:selinux tutorials and here, If system booted with SELinux disabled, we need to relabel filesystem to enable again SELinux. After disabling SELinux, switching back to enforcing mode causes kernel crash, since relabeling can not be possible in enforcing mode. So that, switching from disabled to enabled mode is only possible in permissive mode. After booting in permissive mode:

fixfiles relabel

can be used to relabel filesystem. Also, kernel boot parameter

autorelabel=1

will force the system to relabel, too. In my experiments, after disabling SELinux, passing enforcing=1 as kernel parameters causes kernel panic (as expected). Here the logs:

[ 8.245513] SELinux: Disabled at runtime.
[ 8.474853] type=1404 audit(946686015.345:2): selinux=0 auid=4294967295 ses=4294967295
can't load SELinux Policy. Machine is in enforcing mode. Halting now.

So, what’s the conclusion?

If your intention is to disable SELinux permanently, and never ever want to be enabled again, even though it is not recommended, passing selinux=0 as kernel boot parameter is the best option. For this case, kernel boot argument overrides options in /etc/selinux/config. However, unless SELinux is intented to be disabled, passing selinux=1 or none as kernel boot parameter and modifying /etc/selinux/config file, according to intention, will be proper action.