LCOV - code coverage report
Current view: top level - fs - fs_struct.c (source / functions) Hit Total Coverage
Test: Real Lines: 41 66 62.1 %
Date: 2020-10-17 15:46:16 Functions: 0 8 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 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                 :          3 : void set_fs_root(struct fs_struct *fs, const struct path *path)
      16                 :            : {
      17                 :            :         struct path old_root;
      18                 :            : 
      19                 :          3 :         path_get(path);
      20                 :            :         spin_lock(&fs->lock);
      21                 :            :         write_seqcount_begin(&fs->seq);
      22                 :          3 :         old_root = fs->root;
      23                 :          3 :         fs->root = *path;
      24                 :            :         write_seqcount_end(&fs->seq);
      25                 :            :         spin_unlock(&fs->lock);
      26                 :          3 :         if (old_root.dentry)
      27                 :          3 :                 path_put(&old_root);
      28                 :          3 : }
      29                 :            : 
      30                 :            : /*
      31                 :            :  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
      32                 :            :  * It can block.
      33                 :            :  */
      34                 :          3 : void set_fs_pwd(struct fs_struct *fs, const struct path *path)
      35                 :            : {
      36                 :            :         struct path old_pwd;
      37                 :            : 
      38                 :          3 :         path_get(path);
      39                 :            :         spin_lock(&fs->lock);
      40                 :            :         write_seqcount_begin(&fs->seq);
      41                 :          3 :         old_pwd = fs->pwd;
      42                 :          3 :         fs->pwd = *path;
      43                 :            :         write_seqcount_end(&fs->seq);
      44                 :            :         spin_unlock(&fs->lock);
      45                 :            : 
      46                 :          3 :         if (old_pwd.dentry)
      47                 :          3 :                 path_put(&old_pwd);
      48                 :          3 : }
      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                 :            :         return 1;
      56                 :            : }
      57                 :            : 
      58                 :          0 : void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
      59                 :            : {
      60                 :            :         struct task_struct *g, *p;
      61                 :            :         struct fs_struct *fs;
      62                 :            :         int count = 0;
      63                 :            : 
      64                 :          0 :         read_lock(&tasklist_lock);
      65                 :          0 :         do_each_thread(g, p) {
      66                 :            :                 task_lock(p);
      67                 :          0 :                 fs = p->fs;
      68                 :          0 :                 if (fs) {
      69                 :            :                         int hits = 0;
      70                 :            :                         spin_lock(&fs->lock);
      71                 :            :                         write_seqcount_begin(&fs->seq);
      72                 :            :                         hits += replace_path(&fs->root, old_root, new_root);
      73                 :          0 :                         hits += replace_path(&fs->pwd, old_root, new_root);
      74                 :            :                         write_seqcount_end(&fs->seq);
      75                 :          0 :                         while (hits--) {
      76                 :          0 :                                 count++;
      77                 :          0 :                                 path_get(new_root);
      78                 :            :                         }
      79                 :            :                         spin_unlock(&fs->lock);
      80                 :            :                 }
      81                 :            :                 task_unlock(p);
      82                 :          0 :         } while_each_thread(g, p);
      83                 :            :         read_unlock(&tasklist_lock);
      84                 :          0 :         while (count--)
      85                 :          0 :                 path_put(old_root);
      86                 :          0 : }
      87                 :            : 
      88                 :          3 : void free_fs_struct(struct fs_struct *fs)
      89                 :            : {
      90                 :          3 :         path_put(&fs->root);
      91                 :          3 :         path_put(&fs->pwd);
      92                 :          3 :         kmem_cache_free(fs_cachep, fs);
      93                 :          3 : }
      94                 :            : 
      95                 :          3 : void exit_fs(struct task_struct *tsk)
      96                 :            : {
      97                 :          3 :         struct fs_struct *fs = tsk->fs;
      98                 :            : 
      99                 :          3 :         if (fs) {
     100                 :            :                 int kill;
     101                 :            :                 task_lock(tsk);
     102                 :            :                 spin_lock(&fs->lock);
     103                 :          3 :                 tsk->fs = NULL;
     104                 :          3 :                 kill = !--fs->users;
     105                 :            :                 spin_unlock(&fs->lock);
     106                 :            :                 task_unlock(tsk);
     107                 :          3 :                 if (kill)
     108                 :          3 :                         free_fs_struct(fs);
     109                 :            :         }
     110                 :          3 : }
     111                 :            : 
     112                 :          3 : struct fs_struct *copy_fs_struct(struct fs_struct *old)
     113                 :            : {
     114                 :          3 :         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
     115                 :            :         /* We don't need to lock fs - think why ;-) */
     116                 :          3 :         if (fs) {
     117                 :          3 :                 fs->users = 1;
     118                 :          3 :                 fs->in_exec = 0;
     119                 :          3 :                 spin_lock_init(&fs->lock);
     120                 :            :                 seqcount_init(&fs->seq);
     121                 :          3 :                 fs->umask = old->umask;
     122                 :            : 
     123                 :            :                 spin_lock(&old->lock);
     124                 :          3 :                 fs->root = old->root;
     125                 :          3 :                 path_get(&fs->root);
     126                 :          3 :                 fs->pwd = old->pwd;
     127                 :          3 :                 path_get(&fs->pwd);
     128                 :            :                 spin_unlock(&old->lock);
     129                 :            :         }
     130                 :          3 :         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                 :            :         int kill;
     138                 :            : 
     139                 :          0 :         if (!new_fs)
     140                 :            :                 return -ENOMEM;
     141                 :            : 
     142                 :          0 :         task_lock(current);
     143                 :            :         spin_lock(&fs->lock);
     144                 :          0 :         kill = !--fs->users;
     145                 :          0 :         current->fs = new_fs;
     146                 :            :         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                 :          3 : int current_umask(void)
     157                 :            : {
     158                 :          3 :         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