LCOV - code coverage report
Current view: top level - fs - anon_inodes.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 27 71 38.0 %
Date: 2023-07-31 20:08:34 Functions: 4 10 40.0 %

          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(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           0 : static int anon_inodefs_init_fs_context(struct fs_context *fc)
      44             : {
      45           0 :         struct pseudo_fs_context *ctx = init_pseudo(fc, ANON_INODE_FS_MAGIC);
      46           0 :         if (!ctx)
      47             :                 return -ENOMEM;
      48           0 :         ctx->dops = &anon_inodefs_dentry_operations;
      49           0 :         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             :                 iput(inode);
      73             :                 return ERR_PTR(error);
      74             :         }
      75           0 :         return inode;
      76             : }
      77             : 
      78     1032847 : 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     1032847 :         struct inode *inode;
      85     1032847 :         struct file *file;
      86             : 
      87     1032847 :         if (fops->owner && !try_module_get(fops->owner))
      88             :                 return ERR_PTR(-ENOENT);
      89             : 
      90     1032847 :         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     1032847 :                 inode = anon_inode_inode;
      98     1032847 :                 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     1032847 :                 ihold(inode);
     107             :         }
     108             : 
     109     1032874 :         file = alloc_file_pseudo(inode, anon_inode_mnt, name,
     110             :                                  flags & (O_ACCMODE | O_NONBLOCK), fops);
     111     1032894 :         if (IS_ERR(file))
     112           0 :                 goto err_iput;
     113             : 
     114     1032894 :         file->f_mapping = inode->i_mapping;
     115             : 
     116     1032894 :         file->private_data = priv;
     117             : 
     118     1032894 :         return file;
     119             : 
     120             : 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      494650 : struct file *anon_inode_getfile(const char *name,
     144             :                                 const struct file_operations *fops,
     145             :                                 void *priv, int flags)
     146             : {
     147      494650 :         return __anon_inode_getfile(name, fops, priv, flags, NULL, false);
     148             : }
     149             : EXPORT_SYMBOL_GPL(anon_inode_getfile);
     150             : 
     151             : /**
     152             :  * anon_inode_getfile_secure - Like anon_inode_getfile(), but creates a new
     153             :  *                             !S_PRIVATE anon inode rather than reuse the
     154             :  *                             singleton anon inode and calls the
     155             :  *                             inode_init_security_anon() LSM hook.  This
     156             :  *                             allows for both the inode to have its own
     157             :  *                             security context and for the LSM to enforce
     158             :  *                             policy on the inode's creation.
     159             :  *
     160             :  * @name:    [in]    name of the "class" of the new file
     161             :  * @fops:    [in]    file operations for the new file
     162             :  * @priv:    [in]    private data for the new file (will be file's private_data)
     163             :  * @flags:   [in]    flags
     164             :  * @context_inode:
     165             :  *           [in]    the logical relationship with the new inode (optional)
     166             :  *
     167             :  * The LSM may use @context_inode in inode_init_security_anon(), but a
     168             :  * reference to it is not held.  Returns the newly created file* or an error
     169             :  * pointer.  See the anon_inode_getfile() documentation for more information.
     170             :  */
     171           0 : struct file *anon_inode_getfile_secure(const char *name,
     172             :                                        const struct file_operations *fops,
     173             :                                        void *priv, int flags,
     174             :                                        const struct inode *context_inode)
     175             : {
     176           0 :         return __anon_inode_getfile(name, fops, priv, flags,
     177             :                                     context_inode, true);
     178             : }
     179             : 
     180      538210 : static int __anon_inode_getfd(const char *name,
     181             :                               const struct file_operations *fops,
     182             :                               void *priv, int flags,
     183             :                               const struct inode *context_inode,
     184             :                               bool secure)
     185             : {
     186      538210 :         int error, fd;
     187      538210 :         struct file *file;
     188             : 
     189      538210 :         error = get_unused_fd_flags(flags);
     190      538247 :         if (error < 0)
     191             :                 return error;
     192      538247 :         fd = error;
     193             : 
     194      538247 :         file = __anon_inode_getfile(name, fops, priv, flags, context_inode,
     195             :                                     secure);
     196      538252 :         if (IS_ERR(file)) {
     197           0 :                 error = PTR_ERR(file);
     198           0 :                 goto err_put_unused_fd;
     199             :         }
     200      538252 :         fd_install(fd, file);
     201             : 
     202      538252 :         return fd;
     203             : 
     204             : err_put_unused_fd:
     205           0 :         put_unused_fd(fd);
     206           0 :         return error;
     207             : }
     208             : 
     209             : /**
     210             :  * anon_inode_getfd - creates a new file instance by hooking it up to
     211             :  *                    an anonymous inode and a dentry that describe
     212             :  *                    the "class" of the file
     213             :  *
     214             :  * @name:    [in]    name of the "class" of the new file
     215             :  * @fops:    [in]    file operations for the new file
     216             :  * @priv:    [in]    private data for the new file (will be file's private_data)
     217             :  * @flags:   [in]    flags
     218             :  *
     219             :  * Creates a new file by hooking it on a single inode. This is
     220             :  * useful for files that do not need to have a full-fledged inode in
     221             :  * order to operate correctly.  All the files created with
     222             :  * anon_inode_getfd() will use the same singleton inode, reducing
     223             :  * memory use and avoiding code duplication for the file/inode/dentry
     224             :  * setup.  Returns a newly created file descriptor or an error code.
     225             :  */
     226      538245 : int anon_inode_getfd(const char *name, const struct file_operations *fops,
     227             :                      void *priv, int flags)
     228             : {
     229      538245 :         return __anon_inode_getfd(name, fops, priv, flags, NULL, false);
     230             : }
     231             : EXPORT_SYMBOL_GPL(anon_inode_getfd);
     232             : 
     233             : /**
     234             :  * anon_inode_getfd_secure - Like anon_inode_getfd(), but creates a new
     235             :  * !S_PRIVATE anon inode rather than reuse the singleton anon inode, and calls
     236             :  * the inode_init_security_anon() LSM hook. This allows the inode to have its
     237             :  * own security context and for a LSM to reject creation of the inode.
     238             :  *
     239             :  * @name:    [in]    name of the "class" of the new file
     240             :  * @fops:    [in]    file operations for the new file
     241             :  * @priv:    [in]    private data for the new file (will be file's private_data)
     242             :  * @flags:   [in]    flags
     243             :  * @context_inode:
     244             :  *           [in]    the logical relationship with the new inode (optional)
     245             :  *
     246             :  * The LSM may use @context_inode in inode_init_security_anon(), but a
     247             :  * reference to it is not held.
     248             :  */
     249           0 : int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
     250             :                             void *priv, int flags,
     251             :                             const struct inode *context_inode)
     252             : {
     253           0 :         return __anon_inode_getfd(name, fops, priv, flags, context_inode, true);
     254             : }
     255             : EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
     256             : 
     257           0 : static int __init anon_inode_init(void)
     258             : {
     259           0 :         anon_inode_mnt = kern_mount(&anon_inode_fs_type);
     260           0 :         if (IS_ERR(anon_inode_mnt))
     261           0 :                 panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt));
     262             : 
     263           0 :         anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
     264           0 :         if (IS_ERR(anon_inode_inode))
     265           0 :                 panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode));
     266             : 
     267           0 :         return 0;
     268             : }
     269             : 
     270             : fs_initcall(anon_inode_init);
     271             : 

Generated by: LCOV version 1.14