LCOV - code coverage report
Current view: top level - fs/sysfs - mount.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 38 46 82.6 %
Date: 2021-04-22 12:43:58 Functions: 4 5 80.0 %

          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.rst 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           2 : static int sysfs_get_tree(struct fs_context *fc)
      27             : {
      28           2 :         struct kernfs_fs_context *kfc = fc->fs_private;
      29           2 :         int ret;
      30             : 
      31           2 :         ret = kernfs_get_tree(fc);
      32           2 :         if (ret)
      33             :                 return ret;
      34             : 
      35           2 :         if (kfc->new_sb_created)
      36           1 :                 fc->root->d_sb->s_iflags |= SB_I_USERNS_VISIBLE;
      37             :         return 0;
      38             : }
      39             : 
      40           2 : static void sysfs_fs_context_free(struct fs_context *fc)
      41             : {
      42           2 :         struct kernfs_fs_context *kfc = fc->fs_private;
      43             : 
      44           2 :         if (kfc->ns_tag)
      45           1 :                 kobj_ns_drop(KOBJ_NS_TYPE_NET, kfc->ns_tag);
      46           2 :         kernfs_free_fs_context(fc);
      47           2 :         kfree(kfc);
      48           2 : }
      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           2 : static int sysfs_init_fs_context(struct fs_context *fc)
      56             : {
      57           2 :         struct kernfs_fs_context *kfc;
      58           2 :         struct net *netns;
      59             : 
      60           2 :         if (!(fc->sb_flags & SB_KERNMOUNT)) {
      61           2 :                 if (!kobj_ns_current_may_mount(KOBJ_NS_TYPE_NET))
      62             :                         return -EPERM;
      63             :         }
      64             : 
      65           2 :         kfc = kzalloc(sizeof(struct kernfs_fs_context), GFP_KERNEL);
      66           2 :         if (!kfc)
      67             :                 return -ENOMEM;
      68             : 
      69           2 :         kfc->ns_tag = netns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
      70           2 :         kfc->root = sysfs_root;
      71           2 :         kfc->magic = SYSFS_MAGIC;
      72           2 :         fc->fs_private = kfc;
      73           2 :         fc->ops = &sysfs_fs_context_ops;
      74           2 :         if (netns) {
      75           2 :                 put_user_ns(fc->user_ns);
      76           2 :                 fc->user_ns = get_user_ns(netns->user_ns);
      77             :         }
      78           2 :         fc->global = true;
      79           2 :         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           1 : int __init sysfs_init(void)
      98             : {
      99           1 :         int err;
     100             : 
     101           1 :         sysfs_root = kernfs_create_root(NULL, KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK,
     102             :                                         NULL);
     103           1 :         if (IS_ERR(sysfs_root))
     104           0 :                 return PTR_ERR(sysfs_root);
     105             : 
     106           1 :         sysfs_root_kn = sysfs_root->kn;
     107             : 
     108           1 :         err = register_filesystem(&sysfs_fs_type);
     109           1 :         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