Tetsuo Handa
from-****@I-lov*****
Wed Dec 1 22:43:16 JST 2010
Since TOMOYO/AKARI depend that operations are allowed to sleep, they cannot deal with operations which are not allowed to sleep. Sending signals (kill) and accessing other processes (ptrace) are examples of such operations. I'm trying to protect qemu-kvm process invoked by libvirtd using TOMOYO/AKARI. Unfortunately, all qemu-kvm processes run with the same user id. This means that qemu-kvm process can attack other qemu-kvm processes. I tried to run each qemu-kvm process with different user id (like Android) by inserting TOMOYO/AKARI's execute handler functionality into between qemu-kvm and libvirtd. But that attempt was not successful because libvirtd asks qemu-kvm process to access files after changing ownership of the files. I have to ask libvirtd to change the user id of files to that of each qemu-kvm process. That's beyond what I can control with security driver modules for libvirtd. Then, I browsed security driver module for SELinux. It seems that SELinux isolates each qemu-kvm process using MCS category labels randomly chosen upon runtime. TOMOYO/AKARI do not have MCS category labels. Therefore, I've just wrote a LSM module which assigns security context on processes in order to restrict inter-process operations. This module is intended for preventing qemu-kvm process from attacking other processes. But this module can be applied for generic purpose. Comments/suggestions are welcome. This module should work on all 2.6 kernels (2.6.0 - 2.6.37-rc4) but I haven't tested. (This module is named UUID because I thought I need to use UUID assigned to each virtual machine. But currently this module is not using UUID at all.) Source code: http://sourceforge.jp/projects/akari/svn/view/branches/uuid.c?view=markup&revision=105&root=akari Description of source code: This LSM module isolates processes by comparing session id (which is associated with processes by this module) from LSM hooks which take "struct task_struct *" in their arguments. There are two id named 'id1' and 'id2'. 'id2' cannot be obtained before obtaining 'id1'. Any process is classified as one of three states listed below. "unrestricted" state holds neither 'id1' nor 'id2'. "half-restricted" state holds only 'id1'. "restricted" state holds both 'id1' and 'id2'. Operations (e.g. ptrace()) on objective thread by subjective thread are granted in below rules. | Subjective | unrestricted | half restricted | restricted ----------+-----------------+--------------+-----------------+------------- Objective | unrestricted | always | always | never | half restricted | always | same id1 | same id1 | restricted | always | same id1 | same id1/id2 A process is permitted to obtain 'id1' (if not yet obtained one) by opening /proc/uuid1 interface (e.g. doing ": < /proc/uuid1" from bash). If 'id1' was successfully obtained, the process transits from "unrestricted" state to "half restricted" state. Likewise, a process is permitted to obtain 'id2' (if not yet obtained one) by opening /proc/uuid2 interface (e.g. doing ": < /proc/uuid2" from bash). If 'id2' was successfully obtained, the process transits from "half restricted" state to "restricted" state. The 'id1'/'id2' cannot be changed after once obtained and are automatically inherited to child processes created afterward. To compile, put this file on some directory under kernel's source directory (e.g. uuid/ directory) and do "echo 'obj-m := uuid.o' > uuid/Makefile" and do "make -s SUBDIRS=uuid modules modules_install".