LCOV - code coverage report
Current view: top level - fs - fs_struct.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 59 100 59.0 %
Date: 2023-07-31 20:08:12 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          64 : void set_fs_root(struct fs_struct *fs, const struct path *path)
      16             : {
      17          64 :         struct path old_root;
      18             : 
      19          64 :         path_get(path);
      20          64 :         spin_lock(&fs->lock);
      21          64 :         write_seqcount_begin(&fs->seq);
      22          64 :         old_root = fs->root;
      23          64 :         fs->root = *path;
      24          64 :         write_seqcount_end(&fs->seq);
      25          64 :         spin_unlock(&fs->lock);
      26          64 :         if (old_root.dentry)
      27          64 :                 path_put(&old_root);
      28          64 : }
      29             : 
      30             : /*
      31             :  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
      32             :  * It can block.
      33             :  */
      34   956177392 : void set_fs_pwd(struct fs_struct *fs, const struct path *path)
      35             : {
      36   956177392 :         struct path old_pwd;
      37             : 
      38   956177392 :         path_get(path);
      39   956737015 :         spin_lock(&fs->lock);
      40   956812684 :         write_seqcount_begin(&fs->seq);
      41   956748842 :         old_pwd = fs->pwd;
      42   956748842 :         fs->pwd = *path;
      43   956748842 :         write_seqcount_end(&fs->seq);
      44   956641436 :         spin_unlock(&fs->lock);
      45             : 
      46   957127391 :         if (old_pwd.dentry)
      47   957127391 :                 path_put(&old_pwd);
      48   956522274 : }
      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    45672854 : void free_fs_struct(struct fs_struct *fs)
      89             : {
      90    45672854 :         path_put(&fs->root);
      91    45673342 :         path_put(&fs->pwd);
      92    45675284 :         kmem_cache_free(fs_cachep, fs);
      93    45674322 : }
      94             : 
      95    80317887 : void exit_fs(struct task_struct *tsk)
      96             : {
      97    80317887 :         struct fs_struct *fs = tsk->fs;
      98             : 
      99    80317887 :         if (fs) {
     100    80317887 :                 int kill;
     101    80317887 :                 task_lock(tsk);
     102    80338390 :                 spin_lock(&fs->lock);
     103    80370024 :                 tsk->fs = NULL;
     104    80370024 :                 kill = !--fs->users;
     105    80370024 :                 spin_unlock(&fs->lock);
     106    80366377 :                 task_unlock(tsk);
     107    80365429 :                 if (kill)
     108    45676590 :                         free_fs_struct(fs);
     109             :         }
     110    80363303 : }
     111             : 
     112    45671288 : struct fs_struct *copy_fs_struct(struct fs_struct *old)
     113             : {
     114    45671288 :         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
     115             :         /* We don't need to lock fs - think why ;-) */
     116    45675531 :         if (fs) {
     117    45675531 :                 fs->users = 1;
     118    45675531 :                 fs->in_exec = 0;
     119    45675531 :                 spin_lock_init(&fs->lock);
     120    45675947 :                 seqcount_spinlock_init(&fs->seq, &fs->lock);
     121    45675947 :                 fs->umask = old->umask;
     122             : 
     123    45675947 :                 spin_lock(&old->lock);
     124    45675565 :                 fs->root = old->root;
     125    45675565 :                 path_get(&fs->root);
     126    45677408 :                 fs->pwd = old->pwd;
     127    45677408 :                 path_get(&fs->pwd);
     128    45677730 :                 spin_unlock(&old->lock);
     129             :         }
     130    45678025 :         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    81237849 : int current_umask(void)
     157             : {
     158    81237849 :         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