aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authoreparis@redhat <eparis@redhat>2011-06-02 07:20:51 -0400
committerJames Morris <jmorris@namei.org>2011-06-08 21:59:53 -0400
commit2ce9738bac1b386f46e8478fd2c263460e7c2b09 (patch)
tree46b703439644693efb26239fc9c6278c85e7feb7 /kernel
parentf55cf3c76a3b2e4bdcfea4f95c9d527663b41ece (diff)
cgroupfs: use init_cred when populating new cgroupfs mount
We recently found that in some configurations SELinux was blocking the ability for cgroupfs to be mounted. The reason for this is because cgroupfs creates files and directories during the get_sb() call and also uses lookup_one_len() during that same get_sb() call. This is a problem since the security subsystem cannot initialize the superblock and the inodes in that filesystem until after the get_sb() call returns. Thus we leave the inodes in an unitialized state during get_sb(). For the vast majority of filesystems this is not an issue, but since cgroupfs uses lookup_on_len() it does search permission checks on the directories in the path it walks. Since the inode security state is not set up SELinux does these checks as if the inodes were 'unlabeled.' Many 'normal' userspace process do not have permission to interact with unlabeled inodes. The solution presented here is to do the permission checks of path walk and inode creation as the kernel rather than as the task that called mount. Since the kernel has permission to read/write/create unlabeled inodes the get_sb() call will complete successfully and the SELinux code will be able to initialize the superblock and those inodes created during the get_sb() call. This appears to be the same solution used by other filesystems such as devtmpfs to solve the same issue and should thus have no negative impact on other LSMs which currently work. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Paul Menage <menage@google.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 2731d115d725..81a867851fee 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -27,9 +27,11 @@
27 */ 27 */
28 28
29#include <linux/cgroup.h> 29#include <linux/cgroup.h>
30#include <linux/cred.h>
30#include <linux/ctype.h> 31#include <linux/ctype.h>
31#include <linux/errno.h> 32#include <linux/errno.h>
32#include <linux/fs.h> 33#include <linux/fs.h>
34#include <linux/init_task.h>
33#include <linux/kernel.h> 35#include <linux/kernel.h>
34#include <linux/list.h> 36#include <linux/list.h>
35#include <linux/mm.h> 37#include <linux/mm.h>
@@ -1514,6 +1516,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
1514 struct cgroup *root_cgrp = &root->top_cgroup; 1516 struct cgroup *root_cgrp = &root->top_cgroup;
1515 struct inode *inode; 1517 struct inode *inode;
1516 struct cgroupfs_root *existing_root; 1518 struct cgroupfs_root *existing_root;
1519 const struct cred *cred;
1517 int i; 1520 int i;
1518 1521
1519 BUG_ON(sb->s_root != NULL); 1522 BUG_ON(sb->s_root != NULL);
@@ -1593,7 +1596,9 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
1593 BUG_ON(!list_empty(&root_cgrp->children)); 1596 BUG_ON(!list_empty(&root_cgrp->children));
1594 BUG_ON(root->number_of_cgroups != 1); 1597 BUG_ON(root->number_of_cgroups != 1);
1595 1598
1599 cred = override_creds(&init_cred);
1596 cgroup_populate_dir(root_cgrp); 1600 cgroup_populate_dir(root_cgrp);
1601 revert_creds(cred);
1597 mutex_unlock(&cgroup_mutex); 1602 mutex_unlock(&cgroup_mutex);
1598 mutex_unlock(&inode->i_mutex); 1603 mutex_unlock(&inode->i_mutex);
1599 } else { 1604 } else {