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, ...@@ -102,11 +102,20 @@ ramfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
int error = -ENOSPC; int error = -ENOSPC;
if (inode) { if (inode) {
error = security_inode_init_security(inode, dir,
&dentry->d_name, NULL,
NULL);
if (error) {
iput(inode);
goto out;
}
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */ dget(dentry); /* Extra count - pin the dentry in core */
error = 0; error = 0;
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
} }
out:
return error; return error;
} }
...@@ -134,6 +143,15 @@ static int ramfs_symlink(struct mnt_idmap *idmap, struct inode *dir, ...@@ -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); inode = ramfs_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0);
if (inode) { if (inode) {
int l = strlen(symname)+1; 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); error = page_symlink(inode, symname, l);
if (!error) { if (!error) {
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
...@@ -143,6 +161,7 @@ static int ramfs_symlink(struct mnt_idmap *idmap, struct inode *dir, ...@@ -143,6 +161,7 @@ static int ramfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
} else } else
iput(inode); iput(inode);
} }
out:
return error; return error;
} }
...@@ -150,12 +169,23 @@ static int ramfs_tmpfile(struct mnt_idmap *idmap, ...@@ -150,12 +169,23 @@ static int ramfs_tmpfile(struct mnt_idmap *idmap,
struct inode *dir, struct file *file, umode_t mode) struct inode *dir, struct file *file, umode_t mode)
{ {
struct inode *inode; struct inode *inode;
int error;
inode = ramfs_get_inode(dir->i_sb, dir, mode, 0); inode = ramfs_get_inode(dir->i_sb, dir, mode, 0);
if (!inode) if (!inode)
return -ENOSPC; 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); 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 = { 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, ...@@ -994,57 +994,62 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
struct xattr *xattrs, int *xattr_count) struct xattr *xattrs, int *xattr_count)
{ {
struct task_smack *tsp = smack_cred(current_cred()); 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 *skp = smk_of_task(tsp);
struct smack_known *isp = smk_of_inode(inode); struct smack_known *isp = smk_of_inode(inode);
struct smack_known *dsp = smk_of_inode(dir); struct smack_known *dsp = smk_of_inode(dir);
struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count); struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
int may; int may;
if (xattr) { /*
/* * If equal, transmuting already occurred in
* If equal, transmuting already occurred in * smack_dentry_create_files_as(). No need to check again.
* smack_dentry_create_files_as(). No need to check again. */
*/ if (tsp->smk_task != tsp->smk_transmuted) {
if (tsp->smk_task != tsp->smk_transmuted) { rcu_read_lock();
rcu_read_lock(); may = smk_access_entry(skp->smk_known, dsp->smk_known,
may = smk_access_entry(skp->smk_known, dsp->smk_known, &skp->smk_rules);
&skp->smk_rules); rcu_read_unlock();
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, * The caller of smack_dentry_create_files_as()
* if the access rule allows transmutation and the directory * should have overridden the current cred, so the
* requests transmutation then by all means transmute. * inode label was already set correctly in
* Mark the inode as changed. * smack_inode_alloc_security().
*/ */
if ((tsp->smk_task == tsp->smk_transmuted) || if (tsp->smk_task != tsp->smk_transmuted)
(may > 0 && ((may & MAY_TRANSMUTE) != 0) && isp = issp->smk_inode = dsp;
smk_inode_transmutable(dir))) {
struct xattr *xattr_transmute; 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;
/* xattr_transmute->value_len = TRANS_TRUE_SIZE;
* The caller of smack_dentry_create_files_as() xattr_transmute->name = XATTR_SMACK_TRANSMUTE;
* 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;
}
} }
}
issp->smk_flags |= SMK_INODE_INSTANT;
if (xattr) {
xattr->value = kstrdup(isp->smk_known, GFP_NOFS); xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
if (!xattr->value) if (!xattr->value)
return -ENOMEM; return -ENOMEM;
...@@ -1314,7 +1319,8 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap, ...@@ -1314,7 +1319,8 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
check_star = 1; check_star = 1;
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
check_priv = 1; 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) strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
rc = -EINVAL; rc = -EINVAL;
} else } else
...@@ -2095,12 +2101,7 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) ...@@ -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 *old_tsp = smack_cred(old);
struct task_smack *new_tsp = smack_cred(new); struct task_smack *new_tsp = smack_cred(new);
new_tsp->smk_task = old_tsp->smk_task; init_task_smack(new_tsp, old_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 */
} }
/** /**
...@@ -2855,6 +2856,15 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, ...@@ -2855,6 +2856,15 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
if (value == NULL || size > SMK_LONGLABEL || size == 0) if (value == NULL || size > SMK_LONGLABEL || size == 0)
return -EINVAL; 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); skp = smk_import_entry(value, size);
if (IS_ERR(skp)) if (IS_ERR(skp))
return PTR_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