LCOV - code coverage report
Current view: top level - fs - fs_struct.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 59 100 59.0 %
Date: 2023-07-31 20:08:17 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           4 : void set_fs_root(struct fs_struct *fs, const struct path *path)
      16             : {
      17           4 :         struct path old_root;
      18             : 
      19           4 :         path_get(path);
      20           4 :         spin_lock(&fs->lock);
      21           4 :         write_seqcount_begin(&fs->seq);
      22           4 :         old_root = fs->root;
      23           4 :         fs->root = *path;
      24           4 :         write_seqcount_end(&fs->seq);
      25           4 :         spin_unlock(&fs->lock);
      26           4 :         if (old_root.dentry)
      27           4 :                 path_put(&old_root);
      28           4 : }
      29             : 
      30             : /*
      31             :  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
      32             :  * It can block.
      33             :  */
      34   259290993 : void set_fs_pwd(struct fs_struct *fs, const struct path *path)
      35             : {
      36   259290993 :         struct path old_pwd;
      37             : 
      38   259290993 :         path_get(path);
      39   259301212 :         spin_lock(&fs->lock);
      40   259308497 :         write_seqcount_begin(&fs->seq);
      41   259308460 :         old_pwd = fs->pwd;
      42   259308460 :         fs->pwd = *path;
      43   259308460 :         write_seqcount_end(&fs->seq);
      44   259308380 :         spin_unlock(&fs->lock);
      45             : 
      46   259300526 :         if (old_pwd.dentry)
      47   259300526 :                 path_put(&old_pwd);
      48   259274635 : }
      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    14069006 : void free_fs_struct(struct fs_struct *fs)
      89             : {
      90    14069006 :         path_put(&fs->root);
      91    14068781 :         path_put(&fs->pwd);
      92    14069080 :         kmem_cache_free(fs_cachep, fs);
      93    14068768 : }
      94             : 
      95    28092936 : void exit_fs(struct task_struct *tsk)
      96             : {
      97    28092936 :         struct fs_struct *fs = tsk->fs;
      98             : 
      99    28092936 :         if (fs) {
     100    28092936 :                 int kill;
     101    28092936 :                 task_lock(tsk);
     102    28097097 :                 spin_lock(&fs->lock);
     103    28096889 :                 tsk->fs = NULL;
     104    28096889 :                 kill = !--fs->users;
     105    28096889 :                 spin_unlock(&fs->lock);
     106    28096743 :                 task_unlock(tsk);
     107    28096349 :                 if (kill)
     108    14069355 :                         free_fs_struct(fs);
     109             :         }
     110    28095425 : }
     111             : 
     112    14069433 : struct fs_struct *copy_fs_struct(struct fs_struct *old)
     113             : {
     114    14069433 :         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
     115             :         /* We don't need to lock fs - think why ;-) */
     116    14069378 :         if (fs) {
     117    14069378 :                 fs->users = 1;
     118    14069378 :                 fs->in_exec = 0;
     119    14069378 :                 spin_lock_init(&fs->lock);
     120    14069285 :                 seqcount_spinlock_init(&fs->seq, &fs->lock);
     121    14069285 :                 fs->umask = old->umask;
     122             : 
     123    14069285 :                 spin_lock(&old->lock);
     124    14069335 :                 fs->root = old->root;
     125    14069335 :                 path_get(&fs->root);
     126    14069533 :                 fs->pwd = old->pwd;
     127    14069533 :                 path_get(&fs->pwd);
     128    14069597 :                 spin_unlock(&old->lock);
     129             :         }
     130    14069633 :         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    19650909 : int current_umask(void)
     157             : {
     158    19650909 :         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