]> git.baikalelectronics.ru Git - kernel.git/commitdiff
smack: Record transmuting in smk_transmuted
authorRoberto Sassu <roberto.sassu@huawei.com>
Mon, 8 May 2023 17:02:34 +0000 (19:02 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 6 Oct 2023 12:56:59 +0000 (14:56 +0200)
[ Upstream commit 2c085f3a8f23c9b444e8b99d93c15d7ce870fc4e ]

smack_dentry_create_files_as() determines whether transmuting should occur
based on the label of the parent directory the new inode will be added to,
and not the label of the directory where it is created.

This helps for example to do transmuting on overlayfs, since the latter
first creates the inode in the working directory, and then moves it to the
correct destination.

However, despite smack_dentry_create_files_as() provides the correct label,
smack_inode_init_security() does not know from passed information whether
or not transmuting occurred. Without this information,
smack_inode_init_security() cannot set SMK_INODE_CHANGED in smk_flags,
which will result in the SMACK64TRANSMUTE xattr not being set in
smack_d_instantiate().

Thus, add the smk_transmuted field to the task_smack structure, and set it
in smack_dentry_create_files_as() to smk_task if transmuting occurred. If
smk_task is equal to smk_transmuted in smack_inode_init_security(), act as
if transmuting was successful but without taking the label from the parent
directory (the inode label was already set correctly from the current
credentials in smack_inode_alloc_security()).

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
security/smack/smack.h
security/smack/smack_lsm.c

index e2239be7bd60a02836e6a31bbc7bbc888fe33aa8..aa15ff56ed6e717cf299a1d933f3f73d29bb0964 100644 (file)
@@ -120,6 +120,7 @@ struct inode_smack {
 struct task_smack {
        struct smack_known      *smk_task;      /* label for access control */
        struct smack_known      *smk_forked;    /* label when forked */
+       struct smack_known      *smk_transmuted;/* label when transmuted */
        struct list_head        smk_rules;      /* per task access rules */
        struct mutex            smk_rules_lock; /* lock for the rules */
        struct list_head        smk_relabel;    /* transit allowed labels */
index 67dcd31cd3f3da73a22545b66680d7056d49d767..1232c1d71d9f8830e77f98960bf35a0cbf17edb3 100644 (file)
@@ -999,8 +999,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
                                     const struct qstr *qstr, const char **name,
                                     void **value, size_t *len)
 {
+       struct task_smack *tsp = smack_cred(current_cred());
        struct inode_smack *issp = smack_inode(inode);
-       struct smack_known *skp = smk_of_current();
+       struct smack_known *skp = smk_of_task(tsp);
        struct smack_known *isp = smk_of_inode(inode);
        struct smack_known *dsp = smk_of_inode(dir);
        int may;
@@ -1009,20 +1010,34 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
                *name = XATTR_SMACK_SUFFIX;
 
        if (value && len) {
-               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();
+               }
 
                /*
-                * If the access rule allows transmutation and
-                * the directory requests transmutation then
-                * by all means 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.
                 */
-               if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
-                   smk_inode_transmutable(dir)) {
-                       isp = dsp;
+               if ((tsp->smk_task == tsp->smk_transmuted) ||
+                   (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
+                    smk_inode_transmutable(dir))) {
+                       /*
+                        * 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;
                        issp->smk_flags |= SMK_INODE_CHANGED;
                }
 
@@ -4750,8 +4765,10 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
                 * providing access is transmuting use the containing
                 * directory label instead of the process label.
                 */
-               if (may > 0 && (may & MAY_TRANSMUTE))
+               if (may > 0 && (may & MAY_TRANSMUTE)) {
                        ntsp->smk_task = isp->smk_inode;
+                       ntsp->smk_transmuted = ntsp->smk_task;
+               }
        }
        return 0;
 }