Commit 681ba318 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'Smack-for-6.9' of https://github.com/cschaufler/smack-next

Pull smack updates from Casey Schaufler:

 - Improvements to the initialization of in-memory inodes

 - A fix in ramfs to propery ensure the initialization of in-memory
   inodes

 - Removal of duplicated code in smack_cred_transfer()

* tag 'Smack-for-6.9' of https://github.com/cschaufler/smack-next:
  Smack: use init_task_smack() in smack_cred_transfer()
  ramfs: Initialize security of in-memory inodes
  smack: Initialize the in-memory inode in smack_inode_init_security()
  smack: Always determine inode labels in smack_inode_init_security()
  smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity()
  smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr()
parents 7f1a2774 69b6d710
......@@ -102,11 +102,20 @@ ramfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
int error = -ENOSPC;
if (inode) {
error = security_inode_init_security(inode, dir,
&dentry->d_name, NULL,
NULL);
if (error) {
iput(inode);
goto out;
}
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
error = 0;
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
}
out:
return error;
}
......@@ -134,6 +143,15 @@ static int ramfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
inode = ramfs_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0);
if (inode) {
int l = strlen(symname)+1;
error = security_inode_init_security(inode, dir,
&dentry->d_name, NULL,
NULL);
if (error) {
iput(inode);
goto out;
}
error = page_symlink(inode, symname, l);
if (!error) {
d_instantiate(dentry, inode);
......@@ -143,6 +161,7 @@ static int ramfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
} else
iput(inode);
}
out:
return error;
}
......@@ -150,12 +169,23 @@ static int ramfs_tmpfile(struct mnt_idmap *idmap,
struct inode *dir, struct file *file, umode_t mode)
{
struct inode *inode;
int error;
inode = ramfs_get_inode(dir->i_sb, dir, mode, 0);
if (!inode)
return -ENOSPC;
error = security_inode_init_security(inode, dir,
&file_dentry(file)->d_name, NULL,
NULL);
if (error) {
iput(inode);
goto out;
}
d_tmpfile(file, inode);
return finish_open_simple(file, 0);
out:
return finish_open_simple(file, error);
}
static const struct inode_operations ramfs_dir_inode_operations = {
......
......@@ -994,57 +994,62 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
struct xattr *xattrs, int *xattr_count)
{
struct task_smack *tsp = smack_cred(current_cred());
struct inode_smack *issp = smack_inode(inode);
struct smack_known *skp = smk_of_task(tsp);
struct smack_known *isp = smk_of_inode(inode);
struct smack_known *dsp = smk_of_inode(dir);
struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
int may;
if (xattr) {
/*
* If equal, transmuting already occurred in
* smack_dentry_create_files_as(). No need to check again.
*/
if (tsp->smk_task != tsp->smk_transmuted) {
rcu_read_lock();
may = smk_access_entry(skp->smk_known, dsp->smk_known,
&skp->smk_rules);
rcu_read_unlock();
}
/*
* If equal, transmuting already occurred in
* smack_dentry_create_files_as(). No need to check again.
*/
if (tsp->smk_task != tsp->smk_transmuted) {
rcu_read_lock();
may = smk_access_entry(skp->smk_known, dsp->smk_known,
&skp->smk_rules);
rcu_read_unlock();
}
/*
* In addition to having smk_task equal to smk_transmuted,
* if the access rule allows transmutation and the directory
* requests transmutation then by all means transmute.
* Mark the inode as changed.
*/
if ((tsp->smk_task == tsp->smk_transmuted) ||
(may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
smk_inode_transmutable(dir))) {
struct xattr *xattr_transmute;
/*
* In addition to having smk_task equal to smk_transmuted,
* if the access rule allows transmutation and the directory
* requests transmutation then by all means transmute.
* Mark the inode as changed.
* The caller of smack_dentry_create_files_as()
* should have overridden the current cred, so the
* inode label was already set correctly in
* smack_inode_alloc_security().
*/
if ((tsp->smk_task == tsp->smk_transmuted) ||
(may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
smk_inode_transmutable(dir))) {
struct xattr *xattr_transmute;
if (tsp->smk_task != tsp->smk_transmuted)
isp = issp->smk_inode = dsp;
issp->smk_flags |= SMK_INODE_TRANSMUTE;
xattr_transmute = lsm_get_xattr_slot(xattrs,
xattr_count);
if (xattr_transmute) {
xattr_transmute->value = kmemdup(TRANS_TRUE,
TRANS_TRUE_SIZE,
GFP_NOFS);
if (!xattr_transmute->value)
return -ENOMEM;
/*
* The caller of smack_dentry_create_files_as()
* should have overridden the current cred, so the
* inode label was already set correctly in
* smack_inode_alloc_security().
*/
if (tsp->smk_task != tsp->smk_transmuted)
isp = dsp;
xattr_transmute = lsm_get_xattr_slot(xattrs,
xattr_count);
if (xattr_transmute) {
xattr_transmute->value = kmemdup(TRANS_TRUE,
TRANS_TRUE_SIZE,
GFP_NOFS);
if (!xattr_transmute->value)
return -ENOMEM;
xattr_transmute->value_len = TRANS_TRUE_SIZE;
xattr_transmute->name = XATTR_SMACK_TRANSMUTE;
}
xattr_transmute->value_len = TRANS_TRUE_SIZE;
xattr_transmute->name = XATTR_SMACK_TRANSMUTE;
}
}
issp->smk_flags |= SMK_INODE_INSTANT;
if (xattr) {
xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
if (!xattr->value)
return -ENOMEM;
......@@ -1314,7 +1319,8 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
check_star = 1;
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
check_priv = 1;
if (size != TRANS_TRUE_SIZE ||
if (!S_ISDIR(d_backing_inode(dentry)->i_mode) ||
size != TRANS_TRUE_SIZE ||
strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
rc = -EINVAL;
} else
......@@ -2095,12 +2101,7 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old)
struct task_smack *old_tsp = smack_cred(old);
struct task_smack *new_tsp = smack_cred(new);
new_tsp->smk_task = old_tsp->smk_task;
new_tsp->smk_forked = old_tsp->smk_task;
mutex_init(&new_tsp->smk_rules_lock);
INIT_LIST_HEAD(&new_tsp->smk_rules);
/* cbs copy rule list */
init_task_smack(new_tsp, old_tsp->smk_task, old_tsp->smk_task);
}
/**
......@@ -2855,6 +2856,15 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
if (value == NULL || size > SMK_LONGLABEL || size == 0)
return -EINVAL;
if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) {
if (!S_ISDIR(inode->i_mode) || size != TRANS_TRUE_SIZE ||
strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
return -EINVAL;
nsp->smk_flags |= SMK_INODE_TRANSMUTE;
return 0;
}
skp = smk_import_entry(value, size);
if (IS_ERR(skp))
return PTR_ERR(skp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment