David Howells wrote: > Separate the task security context from task_struct. At this point, the > security data is temporarily embedded in the task_struct with two pointers > pointing to it. This patch degrades performance of the kernel in general. This is because accessing the security data (UID, GID, groups list, LSM security pointer, etc) requires an extra dereference (eg: task->uid => task->act_as->uid). I've done some benchmarking to attempt to determine what the degradation is. Firstly, the setup: my test machine has a Core 2 Duo CPU and a gig of RAM. The system is running as limited a set of daemons as I can get away with - this means no syslogd, no klogd - as these can make the timings unstable. Basically, init, mgetty, sshd and auditd are it. On the test machines's disk is a test partition with 266 directories and 19255 files distributed across those directories. For each test, the system is rebooted, then the test partition is mounted: mount /dev/sda6 /var/fscache/ -o user_xattr,noatime,ro and the test program attached is run a couple of times to make sure that the disk backing that partition need not be touched again (the whole metadata fits in RAM): time /tmp/openit /var/fscache Then the program is run nine times in succession and the 'real' values emitted by the time program are averaged. The program stats and opens each regular file and directory in the tree, reading and recursing into each directory. It does not read any data from the regular files as this is likely to swamp the variance due to this security patch. So, I did five runs with different sets of patches and configurations: (1) SELinux enabled, none of the security patches: (gdb) p (1.119+1.110+1.104+1.106+1.095+1.112+1.094+1.091+1.112)/9 $3 = 1.104777777777777 (2) SELinux enabled, all the security patches: (gdb) p (1.204+1.190+1.182+1.190+1.200+1.205+1.199+1.197+1.209)/9 $2 = 1.1973333333333329 The percentage degradation is: (gdb) p 1.1973333333333329/1.104777777777777 $4 = 1.0837775319320126 or about 8.4%. I then created a performance improvement patch (attached) to reduce the number of times current->act_as was calculated and applied that: (3) SELinux enabled, all the security patches plus performance patch: (gdb) p (1.212+1.161+1.202+1.205+1.203+1.151+1.195+1.205+1.186)/9 $2 = 1.1911111111111106 The percentage degradation is (gdb) p 1.1911111111111106/1.104777777777777 $3 = 1.0781454289449866 about 7.8%. I then turned SELinux off to see how much of a difference that made: (4) LSM/SELinux disabled, none of the security patches: (gdb) p (1.121+1.136+1.137+1.121+1.122+1.131+1.121+1.131+1.118)/9 $7 = 1.1264444444444437 (5) LSM/SELinux disabled, all the security patches: (gdb) p (1.120+1.129+1.116+1.115+1.114+1.129+1.127+1.124+1.128)/9 $6 = 1.1224444444444437 This resulted in an improvement, which is slightly odd: (gdb) p 1.1224444444444437/1.1264444444444437 $8 = 0.99644900374827372 or about -0.4%. For some reason the results returned by the time program are quite variable, but I'm not sure why. I suspect that with SELinux off, the difference in times is within the variance of the results. The performance improvement patch can probably be itself improved by passing the calculated value of current->act_as down into LSM hooks instead of current if the former is available. Similarly, passing this into capable() or similar could probably improve things too, but there are a couple of problems there as the auditing code in SELinux's task_has_capability() wants to access the task_struct for pid and comm:-/ David