Smack updates for v6.9.

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().
 -----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCAA1FiEEC+9tH1YyUwIQzUIeOKUVfIxDyBEFAmXvWzgXHGNhc2V5QHNj
 aGF1Zmxlci1jYS5jb20ACgkQOKUVfIxDyBFAtRAAi1FWtSKnS9lekFqBwxl6RFzS
 W1cxnNJq0IMt0/f9Asd4aqPRbXA36dAF/MIwzwqkxZl3/FLy4XOb0NDRhBcSU5Jl
 Yf5uMXuDfj8VRTQlSl6gDCFH7uhSazggWZ1aN0gEz0F1++JagAnwB6vo0BVZO3Yv
 pkJAUy6sOMMuUKRDSOnffqABC2EBb82HzD/+13ts6HjOUF96AlPuWCnfy2SWBN7+
 ZiFZ8CR1EIVMXpeHLugwLrnQcDL9fmTIs8zOabh8c1QcZCKpSRsxgMcKwxU1mutf
 x6F+qBkMXQjFdFINtsYcwD1MCU2MWk32pzpei53HebNbMcs0rrik95PM/doxTIZI
 8n5Q9FKyCgezFbIWmeelPOhM8iEJ7UaJWFxy4wB486J66/dXG7zJA+fmkYAty3H/
 pmO4jfXFQ3PsB261cqut/A3Pxu44n3Kk2t24evoYWC72Zka6iJ5kgaaAQcnZF6S5
 L8K1+IGqXlvWOijOtdla4pZ54IZaKmh0LLgSruwOu+3U7qNQHXEwZujWbibK2aiE
 dxYT4EjHX8gK50kq8QBPtEJs5DXgnfXwh4Tp+ffNYik5U08U3hi/QQzLnpgy8ton
 XZZwMJUueBHpJywq0M3UGMpE5OfjTCiQ30zryld6TF8kl7k1IKP756RcXKXShBfj
 znQQvAFGxkzQvZv2FJM=
 =QDx7
 -----END PGP SIGNATURE-----

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()
This commit is contained in:
Linus Torvalds 2024-03-12 15:08:06 -07:00
commit 681ba318a6
2 changed files with 92 additions and 52 deletions

View File

@ -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 = {

View File

@ -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 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;
/*
* 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 = 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;
xattr_transmute->value_len = TRANS_TRUE_SIZE;
xattr_transmute->name = XATTR_SMACK_TRANSMUTE;
}
}
issp->smk_flags |= SMK_INODE_INSTANT;
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();
}
/*
* 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;
/*
* 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->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);