From: Stephen Smalley This patch modifies tmpfs to call the inode_init_security LSM hook to set up the incore inode security state for new inodes before the inode becomes accessible via the dcache. As there is no underlying storage of security xattrs in this case, it is not necessary for the hook to return the (name, value, len) triple to the tmpfs code, so this patch also modifies the SELinux hook function to correctly handle the case where the (name, value, len) pointers are NULL. The hook call is needed in tmpfs in order to support proper security labeling of tmpfs inodes (e.g. for udev with tmpfs /dev in Fedora). With this change in place, we should then be able to remove the security_inode_post_create/mkdir/... hooks safely. Signed-off-by: Stephen Smalley Cc: Hugh Dickins Signed-off-by: Andrew Morton --- mm/shmem.c | 20 +++++++++++++++++++- security/selinux/hooks.c | 24 ++++++++++++++---------- 2 files changed, 33 insertions(+), 11 deletions(-) diff -puN mm/shmem.c~tmpfs-enable-atomic-inode-security mm/shmem.c --- devel/mm/shmem.c~tmpfs-enable-atomic-inode-security 2005-07-30 00:43:56.000000000 -0700 +++ devel-akpm/mm/shmem.c 2005-07-30 00:43:56.000000000 -0700 @@ -1607,6 +1607,15 @@ shmem_mknod(struct inode *dir, struct de int error = -ENOSPC; if (inode) { + error = security_inode_init_security(inode, dir, NULL, NULL, + NULL); + if (error) { + if (error != -EOPNOTSUPP) { + iput(inode); + return error; + } + error = 0; + } if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; if (S_ISDIR(mode)) @@ -1616,7 +1625,6 @@ shmem_mknod(struct inode *dir, struct de dir->i_ctime = dir->i_mtime = CURRENT_TIME; d_instantiate(dentry, inode); dget(dentry); /* Extra count - pin the dentry in core */ - error = 0; } return error; } @@ -1746,6 +1754,16 @@ static int shmem_symlink(struct inode *d if (!inode) return -ENOSPC; + error = security_inode_init_security(inode, dir, NULL, NULL, + NULL); + if (error) { + if (error != -EOPNOTSUPP) { + iput(inode); + return error; + } + error = 0; + } + info = SHMEM_I(inode); inode->i_size = len-1; if (len <= (char *)inode - (char *)info) { diff -puN security/selinux/hooks.c~tmpfs-enable-atomic-inode-security security/selinux/hooks.c --- devel/security/selinux/hooks.c~tmpfs-enable-atomic-inode-security 2005-07-30 00:43:56.000000000 -0700 +++ devel-akpm/security/selinux/hooks.c 2005-07-30 00:43:56.000000000 -0700 @@ -2034,7 +2034,7 @@ static int selinux_inode_init_security(s struct inode_security_struct *isec; u32 newsid; int rc; - char *namep, *context; + char *namep = NULL, *context; tsec = current->security; dsec = dir->i_security; @@ -2059,17 +2059,21 @@ static int selinux_inode_init_security(s inode_security_set_sid(inode, newsid); - namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); - if (!namep) - return -ENOMEM; - *name = namep; + if (name) { + namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); + if (!namep) + return -ENOMEM; + *name = namep; + } - rc = security_sid_to_context(newsid, &context, len); - if (rc) { - kfree(namep); - return rc; + if (value && len) { + rc = security_sid_to_context(newsid, &context, len); + if (rc) { + kfree(namep); + return rc; + } + *value = context; } - *value = context; isec->security_attr_init = 1; _