Skip to content

Commit 6d9d88d

Browse files
Jarkko Sakkinentorvalds
authored andcommitted
tmpfs: security xattr setting on inode creation
Adds to generic xattr support introduced in Linux 3.0 by implementing initxattrs callback. This enables consulting of security attributes from LSM and EVM when inode is created. [hughd@google.com: moved under CONFIG_TMPFS_XATTR, with memcpy in shmem_xattr_alloc] Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com> Reviewed-by: James Morris <james.l.morris@oracle.com> Signed-off-by: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 08ab9b1 commit 6d9d88d

File tree

1 file changed

+72
-16
lines changed

1 file changed

+72
-16
lines changed

mm/shmem.c

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,12 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
11781178
static const struct inode_operations shmem_symlink_inode_operations;
11791179
static const struct inode_operations shmem_short_symlink_operations;
11801180

1181+
#ifdef CONFIG_TMPFS_XATTR
1182+
static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
1183+
#else
1184+
#define shmem_initxattrs NULL
1185+
#endif
1186+
11811187
static int
11821188
shmem_write_begin(struct file *file, struct address_space *mapping,
11831189
loff_t pos, unsigned len, unsigned flags,
@@ -1490,7 +1496,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
14901496
if (inode) {
14911497
error = security_inode_init_security(inode, dir,
14921498
&dentry->d_name,
1493-
NULL, NULL);
1499+
shmem_initxattrs, NULL);
14941500
if (error) {
14951501
if (error != -EOPNOTSUPP) {
14961502
iput(inode);
@@ -1630,7 +1636,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
16301636
return -ENOSPC;
16311637

16321638
error = security_inode_init_security(inode, dir, &dentry->d_name,
1633-
NULL, NULL);
1639+
shmem_initxattrs, NULL);
16341640
if (error) {
16351641
if (error != -EOPNOTSUPP) {
16361642
iput(inode);
@@ -1704,6 +1710,66 @@ static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *co
17041710
* filesystem level, though.
17051711
*/
17061712

1713+
/*
1714+
* Allocate new xattr and copy in the value; but leave the name to callers.
1715+
*/
1716+
static struct shmem_xattr *shmem_xattr_alloc(const void *value, size_t size)
1717+
{
1718+
struct shmem_xattr *new_xattr;
1719+
size_t len;
1720+
1721+
/* wrap around? */
1722+
len = sizeof(*new_xattr) + size;
1723+
if (len <= sizeof(*new_xattr))
1724+
return NULL;
1725+
1726+
new_xattr = kmalloc(len, GFP_KERNEL);
1727+
if (!new_xattr)
1728+
return NULL;
1729+
1730+
new_xattr->size = size;
1731+
memcpy(new_xattr->value, value, size);
1732+
return new_xattr;
1733+
}
1734+
1735+
/*
1736+
* Callback for security_inode_init_security() for acquiring xattrs.
1737+
*/
1738+
static int shmem_initxattrs(struct inode *inode,
1739+
const struct xattr *xattr_array,
1740+
void *fs_info)
1741+
{
1742+
struct shmem_inode_info *info = SHMEM_I(inode);
1743+
const struct xattr *xattr;
1744+
struct shmem_xattr *new_xattr;
1745+
size_t len;
1746+
1747+
for (xattr = xattr_array; xattr->name != NULL; xattr++) {
1748+
new_xattr = shmem_xattr_alloc(xattr->value, xattr->value_len);
1749+
if (!new_xattr)
1750+
return -ENOMEM;
1751+
1752+
len = strlen(xattr->name) + 1;
1753+
new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
1754+
GFP_KERNEL);
1755+
if (!new_xattr->name) {
1756+
kfree(new_xattr);
1757+
return -ENOMEM;
1758+
}
1759+
1760+
memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
1761+
XATTR_SECURITY_PREFIX_LEN);
1762+
memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
1763+
xattr->name, len);
1764+
1765+
spin_lock(&info->lock);
1766+
list_add(&new_xattr->list, &info->xattr_list);
1767+
spin_unlock(&info->lock);
1768+
}
1769+
1770+
return 0;
1771+
}
1772+
17071773
static int shmem_xattr_get(struct dentry *dentry, const char *name,
17081774
void *buffer, size_t size)
17091775
{
@@ -1731,24 +1797,17 @@ static int shmem_xattr_get(struct dentry *dentry, const char *name,
17311797
return ret;
17321798
}
17331799

1734-
static int shmem_xattr_set(struct dentry *dentry, const char *name,
1800+
static int shmem_xattr_set(struct inode *inode, const char *name,
17351801
const void *value, size_t size, int flags)
17361802
{
1737-
struct inode *inode = dentry->d_inode;
17381803
struct shmem_inode_info *info = SHMEM_I(inode);
17391804
struct shmem_xattr *xattr;
17401805
struct shmem_xattr *new_xattr = NULL;
1741-
size_t len;
17421806
int err = 0;
17431807

17441808
/* value == NULL means remove */
17451809
if (value) {
1746-
/* wrap around? */
1747-
len = sizeof(*new_xattr) + size;
1748-
if (len <= sizeof(*new_xattr))
1749-
return -ENOMEM;
1750-
1751-
new_xattr = kmalloc(len, GFP_KERNEL);
1810+
new_xattr = shmem_xattr_alloc(value, size);
17521811
if (!new_xattr)
17531812
return -ENOMEM;
17541813

@@ -1757,9 +1816,6 @@ static int shmem_xattr_set(struct dentry *dentry, const char *name,
17571816
kfree(new_xattr);
17581817
return -ENOMEM;
17591818
}
1760-
1761-
new_xattr->size = size;
1762-
memcpy(new_xattr->value, value, size);
17631819
}
17641820

17651821
spin_lock(&info->lock);
@@ -1858,7 +1914,7 @@ static int shmem_setxattr(struct dentry *dentry, const char *name,
18581914
if (size == 0)
18591915
value = ""; /* empty EA, do not remove */
18601916

1861-
return shmem_xattr_set(dentry, name, value, size, flags);
1917+
return shmem_xattr_set(dentry->d_inode, name, value, size, flags);
18621918

18631919
}
18641920

@@ -1878,7 +1934,7 @@ static int shmem_removexattr(struct dentry *dentry, const char *name)
18781934
if (err)
18791935
return err;
18801936

1881-
return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
1937+
return shmem_xattr_set(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
18821938
}
18831939

18841940
static bool xattr_is_trusted(const char *name)

0 commit comments

Comments
 (0)