LCOV - code coverage report
Current view: top level - fs - fs_struct.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 59 100 59.0 %
Date: 2023-07-31 20:08:34 Functions: 6 8 75.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : #include <linux/export.h>
       3             : #include <linux/sched/signal.h>
       4             : #include <linux/sched/task.h>
       5             : #include <linux/fs.h>
       6             : #include <linux/path.h>
       7             : #include <linux/slab.h>
       8             : #include <linux/fs_struct.h>
       9             : #include "internal.h"
      10             : 
      11             : /*
      12             :  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
      13             :  * It can block.
      14             :  */
      15          91 : void set_fs_root(struct fs_struct *fs, const struct path *path)
      16             : {
      17          91 :         struct path old_root;
      18             : 
      19          91 :         path_get(path);
      20          91 :         spin_lock(&fs->lock);
      21          91 :         write_seqcount_begin(&fs->seq);
      22          91 :         old_root = fs->root;
      23          91 :         fs->root = *path;
      24          91 :         write_seqcount_end(&fs->seq);
      25          91 :         spin_unlock(&fs->lock);
      26          91 :         if (old_root.dentry)
      27          91 :                 path_put(&old_root);
      28          91 : }
      29             : 
      30             : /*
      31             :  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
      32             :  * It can block.
      33             :  */
      34  1031261588 : void set_fs_pwd(struct fs_struct *fs, const struct path *path)
      35             : {
      36  1031261588 :         struct path old_pwd;
      37             : 
      38  1031261588 :         path_get(path);
      39  1032451410 :         spin_lock(&fs->lock);
      40  1032707555 :         write_seqcount_begin(&fs->seq);
      41  1032644920 :         old_pwd = fs->pwd;
      42  1032644920 :         fs->pwd = *path;
      43  1032644920 :         write_seqcount_end(&fs->seq);
      44  1032491557 :         spin_unlock(&fs->lock);
      45             : 
      46  1033013118 :         if (old_pwd.dentry)
      47  1033013118 :                 path_put(&old_pwd);
      48  1032263574 : }
      49             : 
      50             : static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
      51             : {
      52           0 :         if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
      53             :                 return 0;
      54           0 :         *p = *new;
      55           0 :         return 1;
      56             : }
      57             : 
      58           0 : void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
      59             : {
      60           0 :         struct task_struct *g, *p;
      61           0 :         struct fs_struct *fs;
      62           0 :         int count = 0;
      63             : 
      64           0 :         read_lock(&tasklist_lock);
      65           0 :         do_each_thread(g, p) {
      66           0 :                 task_lock(p);
      67           0 :                 fs = p->fs;
      68           0 :                 if (fs) {
      69           0 :                         int hits = 0;
      70           0 :                         spin_lock(&fs->lock);
      71           0 :                         write_seqcount_begin(&fs->seq);
      72           0 :                         hits += replace_path(&fs->root, old_root, new_root);
      73           0 :                         hits += replace_path(&fs->pwd, old_root, new_root);
      74           0 :                         write_seqcount_end(&fs->seq);
      75           0 :                         while (hits--) {
      76           0 :                                 count++;
      77           0 :                                 path_get(new_root);
      78             :                         }
      79           0 :                         spin_unlock(&fs->lock);
      80             :                 }
      81           0 :                 task_unlock(p);
      82           0 :         } while_each_thread(g, p);
      83           0 :         read_unlock(&tasklist_lock);
      84           0 :         while (count--)
      85           0 :                 path_put(old_root);
      86           0 : }
      87             : 
      88    51858834 : void free_fs_struct(struct fs_struct *fs)
      89             : {
      90    51858834 :         path_put(&fs->root);
      91    51859915 :         path_put(&fs->pwd);
      92    51862978 :         kmem_cache_free(fs_cachep, fs);
      93    51861811 : }
      94             : 
      95    93542802 : void exit_fs(struct task_struct *tsk)
      96             : {
      97    93542802 :         struct fs_struct *fs = tsk->fs;
      98             : 
      99    93542802 :         if (fs) {
     100    93542802 :                 int kill;
     101    93542802 :                 task_lock(tsk);
     102    93581055 :                 spin_lock(&fs->lock);
     103    93621362 :                 tsk->fs = NULL;
     104    93621362 :                 kill = !--fs->users;
     105    93621362 :                 spin_unlock(&fs->lock);
     106    93617211 :                 task_unlock(tsk);
     107    93618756 :                 if (kill)
     108    51864466 :                         free_fs_struct(fs);
     109             :         }
     110    93616076 : }
     111             : 
     112    51857745 : struct fs_struct *copy_fs_struct(struct fs_struct *old)
     113             : {
     114    51857745 :         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
     115             :         /* We don't need to lock fs - think why ;-) */
     116    51863285 :         if (fs) {
     117    51863285 :                 fs->users = 1;
     118    51863285 :                 fs->in_exec = 0;
     119    51863285 :                 spin_lock_init(&fs->lock);
     120    51863812 :                 seqcount_spinlock_init(&fs->seq, &fs->lock);
     121    51863812 :                 fs->umask = old->umask;
     122             : 
     123    51863812 :                 spin_lock(&old->lock);
     124    51862901 :                 fs->root = old->root;
     125    51862901 :                 path_get(&fs->root);
     126    51865995 :                 fs->pwd = old->pwd;
     127    51865995 :                 path_get(&fs->pwd);
     128    51866323 :                 spin_unlock(&old->lock);
     129             :         }
     130    51866358 :         return fs;
     131             : }
     132             : 
     133           0 : int unshare_fs_struct(void)
     134             : {
     135           0 :         struct fs_struct *fs = current->fs;
     136           0 :         struct fs_struct *new_fs = copy_fs_struct(fs);
     137           0 :         int kill;
     138             : 
     139           0 :         if (!new_fs)
     140             :                 return -ENOMEM;
     141             : 
     142           0 :         task_lock(current);
     143           0 :         spin_lock(&fs->lock);
     144           0 :         kill = !--fs->users;
     145           0 :         current->fs = new_fs;
     146           0 :         spin_unlock(&fs->lock);
     147           0 :         task_unlock(current);
     148             : 
     149           0 :         if (kill)
     150           0 :                 free_fs_struct(fs);
     151             : 
     152             :         return 0;
     153             : }
     154             : EXPORT_SYMBOL_GPL(unshare_fs_struct);
     155             : 
     156    88910070 : int current_umask(void)
     157             : {
     158    88910070 :         return current->fs->umask;
     159             : }
     160             : EXPORT_SYMBOL(current_umask);
     161             : 
     162             : /* to be mentioned only in INIT_TASK */
     163             : struct fs_struct init_fs = {
     164             :         .users          = 1,
     165             :         .lock           = __SPIN_LOCK_UNLOCKED(init_fs.lock),
     166             :         .seq            = SEQCNT_SPINLOCK_ZERO(init_fs.seq, &init_fs.lock),
     167             :         .umask          = 0022,
     168             : };

Generated by: LCOV version 1.14