LCOV - code coverage report
Current view: top level - fs - anon_inodes.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 38 72 52.8 %
Date: 2021-04-22 12:43:58 Functions: 6 9 66.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  *  fs/anon_inodes.c
       4             :  *
       5             :  *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
       6             :  *
       7             :  *  Thanks to Arnd Bergmann for code review and suggestions.
       8             :  *  More changes for Thomas Gleixner suggestions.
       9             :  *
      10             :  */
      11             : 
      12             : #include <linux/cred.h>
      13             : #include <linux/file.h>
      14             : #include <linux/poll.h>
      15             : #include <linux/sched.h>
      16             : #include <linux/init.h>
      17             : #include <linux/fs.h>
      18             : #include <linux/mount.h>
      19             : #include <linux/module.h>
      20             : #include <linux/kernel.h>
      21             : #include <linux/magic.h>
      22             : #include <linux/anon_inodes.h>
      23             : #include <linux/pseudo_fs.h>
      24             : 
      25             : #include <linux/uaccess.h>
      26             : 
      27             : static struct vfsmount *anon_inode_mnt __read_mostly;
      28             : static struct inode *anon_inode_inode;
      29             : 
      30             : /*
      31             :  * anon_inodefs_dname() is called from d_path().
      32             :  */
      33           0 : static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)
      34             : {
      35           0 :         return dynamic_dname(dentry, buffer, buflen, "anon_inode:%s",
      36             :                                 dentry->d_name.name);
      37             : }
      38             : 
      39             : static const struct dentry_operations anon_inodefs_dentry_operations = {
      40             :         .d_dname        = anon_inodefs_dname,
      41             : };
      42             : 
      43           1 : static int anon_inodefs_init_fs_context(struct fs_context *fc)
      44             : {
      45           1 :         struct pseudo_fs_context *ctx = init_pseudo(fc, ANON_INODE_FS_MAGIC);
      46           1 :         if (!ctx)
      47             :                 return -ENOMEM;
      48           1 :         ctx->dops = &anon_inodefs_dentry_operations;
      49           1 :         return 0;
      50             : }
      51             : 
      52             : static struct file_system_type anon_inode_fs_type = {
      53             :         .name           = "anon_inodefs",
      54             :         .init_fs_context = anon_inodefs_init_fs_context,
      55             :         .kill_sb        = kill_anon_super,
      56             : };
      57             : 
      58           0 : static struct inode *anon_inode_make_secure_inode(
      59             :         const char *name,
      60             :         const struct inode *context_inode)
      61             : {
      62           0 :         struct inode *inode;
      63           0 :         const struct qstr qname = QSTR_INIT(name, strlen(name));
      64           0 :         int error;
      65             : 
      66           0 :         inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
      67           0 :         if (IS_ERR(inode))
      68             :                 return inode;
      69           0 :         inode->i_flags &= ~S_PRIVATE;
      70           0 :         error = security_inode_init_security_anon(inode, &qname, context_inode);
      71           0 :         if (error) {
      72           0 :                 iput(inode);
      73           0 :                 return ERR_PTR(error);
      74             :         }
      75             :         return inode;
      76             : }
      77             : 
      78         170 : static struct file *__anon_inode_getfile(const char *name,
      79             :                                          const struct file_operations *fops,
      80             :                                          void *priv, int flags,
      81             :                                          const struct inode *context_inode,
      82             :                                          bool secure)
      83             : {
      84         170 :         struct inode *inode;
      85         170 :         struct file *file;
      86             : 
      87         170 :         if (fops->owner && !try_module_get(fops->owner))
      88             :                 return ERR_PTR(-ENOENT);
      89             : 
      90         170 :         if (secure) {
      91           0 :                 inode = anon_inode_make_secure_inode(name, context_inode);
      92           0 :                 if (IS_ERR(inode)) {
      93           0 :                         file = ERR_CAST(inode);
      94           0 :                         goto err;
      95             :                 }
      96             :         } else {
      97         170 :                 inode = anon_inode_inode;
      98         170 :                 if (IS_ERR(inode)) {
      99           0 :                         file = ERR_PTR(-ENODEV);
     100           0 :                         goto err;
     101             :                 }
     102             :                 /*
     103             :                  * We know the anon_inode inode count is always
     104             :                  * greater than zero, so ihold() is safe.
     105             :                  */
     106         170 :                 ihold(inode);
     107             :         }
     108             : 
     109         170 :         file = alloc_file_pseudo(inode, anon_inode_mnt, name,
     110             :                                  flags & (O_ACCMODE | O_NONBLOCK), fops);
     111         170 :         if (IS_ERR(file))
     112           0 :                 goto err_iput;
     113             : 
     114         170 :         file->f_mapping = inode->i_mapping;
     115             : 
     116         170 :         file->private_data = priv;
     117             : 
     118         170 :         return file;
     119             : 
     120           0 : err_iput:
     121           0 :         iput(inode);
     122           0 : err:
     123           0 :         module_put(fops->owner);
     124           0 :         return file;
     125             : }
     126             : 
     127             : /**
     128             :  * anon_inode_getfile - creates a new file instance by hooking it up to an
     129             :  *                      anonymous inode, and a dentry that describe the "class"
     130             :  *                      of the file
     131             :  *
     132             :  * @name:    [in]    name of the "class" of the new file
     133             :  * @fops:    [in]    file operations for the new file
     134             :  * @priv:    [in]    private data for the new file (will be file's private_data)
     135             :  * @flags:   [in]    flags
     136             :  *
     137             :  * Creates a new file by hooking it on a single inode. This is useful for files
     138             :  * that do not need to have a full-fledged inode in order to operate correctly.
     139             :  * All the files created with anon_inode_getfile() will share a single inode,
     140             :  * hence saving memory and avoiding code duplication for the file/inode/dentry
     141             :  * setup.  Returns the newly created file* or an error pointer.
     142             :  */
     143          26 : struct file *anon_inode_getfile(const char *name,
     144             :                                 const struct file_operations *fops,
     145             :                                 void *priv, int flags)
     146             : {
     147          26 :         return __anon_inode_getfile(name, fops, priv, flags, NULL, false);
     148             : }
     149             : EXPORT_SYMBOL_GPL(anon_inode_getfile);
     150             : 
     151         144 : static int __anon_inode_getfd(const char *name,
     152             :                               const struct file_operations *fops,
     153             :                               void *priv, int flags,
     154             :                               const struct inode *context_inode,
     155             :                               bool secure)
     156             : {
     157         144 :         int error, fd;
     158         144 :         struct file *file;
     159             : 
     160         144 :         error = get_unused_fd_flags(flags);
     161         144 :         if (error < 0)
     162             :                 return error;
     163         144 :         fd = error;
     164             : 
     165         144 :         file = __anon_inode_getfile(name, fops, priv, flags, context_inode,
     166             :                                     secure);
     167         144 :         if (IS_ERR(file)) {
     168           0 :                 error = PTR_ERR(file);
     169           0 :                 goto err_put_unused_fd;
     170             :         }
     171         144 :         fd_install(fd, file);
     172             : 
     173         144 :         return fd;
     174             : 
     175           0 : err_put_unused_fd:
     176           0 :         put_unused_fd(fd);
     177           0 :         return error;
     178             : }
     179             : 
     180             : /**
     181             :  * anon_inode_getfd - creates a new file instance by hooking it up to
     182             :  *                    an anonymous inode and a dentry that describe
     183             :  *                    the "class" of the file
     184             :  *
     185             :  * @name:    [in]    name of the "class" of the new file
     186             :  * @fops:    [in]    file operations for the new file
     187             :  * @priv:    [in]    private data for the new file (will be file's private_data)
     188             :  * @flags:   [in]    flags
     189             :  *
     190             :  * Creates a new file by hooking it on a single inode. This is
     191             :  * useful for files that do not need to have a full-fledged inode in
     192             :  * order to operate correctly.  All the files created with
     193             :  * anon_inode_getfd() will use the same singleton inode, reducing
     194             :  * memory use and avoiding code duplication for the file/inode/dentry
     195             :  * setup.  Returns a newly created file descriptor or an error code.
     196             :  */
     197         144 : int anon_inode_getfd(const char *name, const struct file_operations *fops,
     198             :                      void *priv, int flags)
     199             : {
     200         144 :         return __anon_inode_getfd(name, fops, priv, flags, NULL, false);
     201             : }
     202             : EXPORT_SYMBOL_GPL(anon_inode_getfd);
     203             : 
     204             : /**
     205             :  * anon_inode_getfd_secure - Like anon_inode_getfd(), but creates a new
     206             :  * !S_PRIVATE anon inode rather than reuse the singleton anon inode, and calls
     207             :  * the inode_init_security_anon() LSM hook. This allows the inode to have its
     208             :  * own security context and for a LSM to reject creation of the inode.
     209             :  *
     210             :  * @name:    [in]    name of the "class" of the new file
     211             :  * @fops:    [in]    file operations for the new file
     212             :  * @priv:    [in]    private data for the new file (will be file's private_data)
     213             :  * @flags:   [in]    flags
     214             :  * @context_inode:
     215             :  *           [in]    the logical relationship with the new inode (optional)
     216             :  *
     217             :  * The LSM may use @context_inode in inode_init_security_anon(), but a
     218             :  * reference to it is not held.
     219             :  */
     220           0 : int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
     221             :                             void *priv, int flags,
     222             :                             const struct inode *context_inode)
     223             : {
     224           0 :         return __anon_inode_getfd(name, fops, priv, flags, context_inode, true);
     225             : }
     226             : EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
     227             : 
     228           1 : static int __init anon_inode_init(void)
     229             : {
     230           1 :         anon_inode_mnt = kern_mount(&anon_inode_fs_type);
     231           1 :         if (IS_ERR(anon_inode_mnt))
     232           0 :                 panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt));
     233             : 
     234           1 :         anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
     235           1 :         if (IS_ERR(anon_inode_inode))
     236           0 :                 panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode));
     237             : 
     238           1 :         return 0;
     239             : }
     240             : 
     241             : fs_initcall(anon_inode_init);
     242             : 

Generated by: LCOV version 1.14