LCOV - code coverage report
Current view: top level - fs/sysfs - mount.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 38 46 82.6 %
Date: 2022-03-28 13:20:08 Functions: 4 5 80.0 %
Branches: 11 18 61.1 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * fs/sysfs/symlink.c - operations for initializing and mounting sysfs
       4                 :            :  *
       5                 :            :  * Copyright (c) 2001-3 Patrick Mochel
       6                 :            :  * Copyright (c) 2007 SUSE Linux Products GmbH
       7                 :            :  * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
       8                 :            :  *
       9                 :            :  * Please see Documentation/filesystems/sysfs.txt for more information.
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/fs.h>
      13                 :            : #include <linux/magic.h>
      14                 :            : #include <linux/mount.h>
      15                 :            : #include <linux/init.h>
      16                 :            : #include <linux/slab.h>
      17                 :            : #include <linux/user_namespace.h>
      18                 :            : #include <linux/fs_context.h>
      19                 :            : #include <net/net_namespace.h>
      20                 :            : 
      21                 :            : #include "sysfs.h"
      22                 :            : 
      23                 :            : static struct kernfs_root *sysfs_root;
      24                 :            : struct kernfs_node *sysfs_root_kn;
      25                 :            : 
      26                 :         60 : static int sysfs_get_tree(struct fs_context *fc)
      27                 :            : {
      28                 :         60 :         struct kernfs_fs_context *kfc = fc->fs_private;
      29                 :         60 :         int ret;
      30                 :            : 
      31                 :         60 :         ret = kernfs_get_tree(fc);
      32         [ +  - ]:         60 :         if (ret)
      33                 :            :                 return ret;
      34                 :            : 
      35         [ +  + ]:         60 :         if (kfc->new_sb_created)
      36                 :         30 :                 fc->root->d_sb->s_iflags |= SB_I_USERNS_VISIBLE;
      37                 :            :         return 0;
      38                 :            : }
      39                 :            : 
      40                 :         60 : static void sysfs_fs_context_free(struct fs_context *fc)
      41                 :            : {
      42                 :         60 :         struct kernfs_fs_context *kfc = fc->fs_private;
      43                 :            : 
      44         [ +  + ]:         60 :         if (kfc->ns_tag)
      45                 :         30 :                 kobj_ns_drop(KOBJ_NS_TYPE_NET, kfc->ns_tag);
      46                 :         60 :         kernfs_free_fs_context(fc);
      47                 :         60 :         kfree(kfc);
      48                 :         60 : }
      49                 :            : 
      50                 :            : static const struct fs_context_operations sysfs_fs_context_ops = {
      51                 :            :         .free           = sysfs_fs_context_free,
      52                 :            :         .get_tree       = sysfs_get_tree,
      53                 :            : };
      54                 :            : 
      55                 :         60 : static int sysfs_init_fs_context(struct fs_context *fc)
      56                 :            : {
      57                 :         60 :         struct kernfs_fs_context *kfc;
      58                 :         60 :         struct net *netns;
      59                 :            : 
      60         [ +  - ]:         60 :         if (!(fc->sb_flags & SB_KERNMOUNT)) {
      61         [ +  - ]:         60 :                 if (!kobj_ns_current_may_mount(KOBJ_NS_TYPE_NET))
      62                 :            :                         return -EPERM;
      63                 :            :         }
      64                 :            : 
      65                 :         60 :         kfc = kzalloc(sizeof(struct kernfs_fs_context), GFP_KERNEL);
      66         [ +  - ]:         60 :         if (!kfc)
      67                 :            :                 return -ENOMEM;
      68                 :            : 
      69                 :         60 :         kfc->ns_tag = netns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
      70                 :         60 :         kfc->root = sysfs_root;
      71                 :         60 :         kfc->magic = SYSFS_MAGIC;
      72                 :         60 :         fc->fs_private = kfc;
      73                 :         60 :         fc->ops = &sysfs_fs_context_ops;
      74         [ +  - ]:         60 :         if (netns) {
      75                 :         60 :                 put_user_ns(fc->user_ns);
      76                 :         60 :                 fc->user_ns = get_user_ns(netns->user_ns);
      77                 :            :         }
      78                 :         60 :         fc->global = true;
      79                 :         60 :         return 0;
      80                 :            : }
      81                 :            : 
      82                 :          0 : static void sysfs_kill_sb(struct super_block *sb)
      83                 :            : {
      84                 :          0 :         void *ns = (void *)kernfs_super_ns(sb);
      85                 :            : 
      86                 :          0 :         kernfs_kill_sb(sb);
      87                 :          0 :         kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
      88                 :          0 : }
      89                 :            : 
      90                 :            : static struct file_system_type sysfs_fs_type = {
      91                 :            :         .name                   = "sysfs",
      92                 :            :         .init_fs_context        = sysfs_init_fs_context,
      93                 :            :         .kill_sb                = sysfs_kill_sb,
      94                 :            :         .fs_flags               = FS_USERNS_MOUNT,
      95                 :            : };
      96                 :            : 
      97                 :         30 : int __init sysfs_init(void)
      98                 :            : {
      99                 :         30 :         int err;
     100                 :            : 
     101                 :         30 :         sysfs_root = kernfs_create_root(NULL, KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK,
     102                 :            :                                         NULL);
     103         [ -  + ]:         30 :         if (IS_ERR(sysfs_root))
     104                 :          0 :                 return PTR_ERR(sysfs_root);
     105                 :            : 
     106                 :         30 :         sysfs_root_kn = sysfs_root->kn;
     107                 :            : 
     108                 :         30 :         err = register_filesystem(&sysfs_fs_type);
     109         [ -  + ]:         30 :         if (err) {
     110                 :          0 :                 kernfs_destroy_root(sysfs_root);
     111                 :          0 :                 return err;
     112                 :            :         }
     113                 :            : 
     114                 :            :         return 0;
     115                 :            : }

Generated by: LCOV version 1.14