LCOV - code coverage report
Current view: top level - fs - fs_struct.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 59 101 58.4 %
Date: 2022-04-01 14:35:51 Functions: 6 8 75.0 %
Branches: 8 32 25.0 %

           Branch data     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                 :        105 : void set_fs_root(struct fs_struct *fs, const struct path *path)
      16                 :            : {
      17                 :        105 :         struct path old_root;
      18                 :            : 
      19                 :        105 :         path_get(path);
      20                 :        105 :         spin_lock(&fs->lock);
      21                 :        105 :         write_seqcount_begin(&fs->seq);
      22                 :        105 :         old_root = fs->root;
      23                 :        105 :         fs->root = *path;
      24                 :        105 :         write_seqcount_end(&fs->seq);
      25                 :        105 :         spin_unlock(&fs->lock);
      26         [ +  + ]:        105 :         if (old_root.dentry)
      27                 :         84 :                 path_put(&old_root);
      28                 :        105 : }
      29                 :            : 
      30                 :            : /*
      31                 :            :  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
      32                 :            :  * It can block.
      33                 :            :  */
      34                 :      74256 : void set_fs_pwd(struct fs_struct *fs, const struct path *path)
      35                 :            : {
      36                 :      74256 :         struct path old_pwd;
      37                 :            : 
      38                 :      74256 :         path_get(path);
      39                 :      74256 :         spin_lock(&fs->lock);
      40                 :      74256 :         write_seqcount_begin(&fs->seq);
      41                 :      74256 :         old_pwd = fs->pwd;
      42                 :      74256 :         fs->pwd = *path;
      43                 :      74256 :         write_seqcount_end(&fs->seq);
      44                 :      74256 :         spin_unlock(&fs->lock);
      45                 :            : 
      46         [ +  + ]:      74256 :         if (old_pwd.dentry)
      47                 :      74235 :                 path_put(&old_pwd);
      48                 :      74256 : }
      49                 :            : 
      50                 :          0 : 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                 :      21021 : void free_fs_struct(struct fs_struct *fs)
      89                 :            : {
      90                 :      21021 :         path_put(&fs->root);
      91                 :      21021 :         path_put(&fs->pwd);
      92                 :      21021 :         kmem_cache_free(fs_cachep, fs);
      93                 :      21021 : }
      94                 :            : 
      95                 :      21546 : void exit_fs(struct task_struct *tsk)
      96                 :            : {
      97                 :      21546 :         struct fs_struct *fs = tsk->fs;
      98                 :            : 
      99         [ +  - ]:      21546 :         if (fs) {
     100                 :      21546 :                 int kill;
     101                 :      21546 :                 task_lock(tsk);
     102                 :      21546 :                 spin_lock(&fs->lock);
     103                 :      21546 :                 tsk->fs = NULL;
     104                 :      21546 :                 kill = !--fs->users;
     105                 :      21546 :                 spin_unlock(&fs->lock);
     106                 :      21546 :                 task_unlock(tsk);
     107         [ +  + ]:      21546 :                 if (kill)
     108                 :      21021 :                         free_fs_struct(fs);
     109                 :            :         }
     110                 :      21546 : }
     111                 :            : 
     112                 :      21504 : struct fs_struct *copy_fs_struct(struct fs_struct *old)
     113                 :            : {
     114                 :      21504 :         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
     115                 :            :         /* We don't need to lock fs - think why ;-) */
     116         [ +  - ]:      21504 :         if (fs) {
     117                 :      21504 :                 fs->users = 1;
     118                 :      21504 :                 fs->in_exec = 0;
     119                 :      21504 :                 spin_lock_init(&fs->lock);
     120                 :      21504 :                 seqcount_init(&fs->seq);
     121                 :      21504 :                 fs->umask = old->umask;
     122                 :            : 
     123                 :      21504 :                 spin_lock(&old->lock);
     124                 :      21504 :                 fs->root = old->root;
     125                 :      21504 :                 path_get(&fs->root);
     126                 :      21504 :                 fs->pwd = old->pwd;
     127                 :      21504 :                 path_get(&fs->pwd);
     128                 :      21504 :                 spin_unlock(&old->lock);
     129                 :            :         }
     130                 :      21504 :         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                 :      25872 : int current_umask(void)
     157                 :            : {
     158                 :      25872 :         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_ZERO(init_fs.seq),
     167                 :            :         .umask          = 0022,
     168                 :            : };

Generated by: LCOV version 1.14