322 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * fs/anon_inodes.c4 *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 27static struct vfsmount *anon_inode_mnt __ro_after_init;28static struct inode *anon_inode_inode __ro_after_init;29 30/*31 * anon_inodefs_dname() is called from d_path().32 */33static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)34{35 return dynamic_dname(buffer, buflen, "anon_inode:%s",36 dentry->d_name.name);37}38 39static const struct dentry_operations anon_inodefs_dentry_operations = {40 .d_dname = anon_inodefs_dname,41};42 43static int anon_inodefs_init_fs_context(struct fs_context *fc)44{45 struct pseudo_fs_context *ctx = init_pseudo(fc, ANON_INODE_FS_MAGIC);46 if (!ctx)47 return -ENOMEM;48 ctx->dops = &anon_inodefs_dentry_operations;49 return 0;50}51 52static 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 58static HWJS_SUSPENDS struct inode *anon_inode_make_secure_inode(59 const char *name,60 const struct inode *context_inode)61{62 struct inode *inode;63 const struct qstr qname = QSTR_INIT(name, strlen(name));64 int error;65 66 inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);67 if (IS_ERR(inode))68 return inode;69 inode->i_flags &= ~S_PRIVATE;70 error = security_inode_init_security_anon(inode, &qname, context_inode);71 if (error) {72 iput(inode);73 return ERR_PTR(error);74 }75 return inode;76}77 78static HWJS_SUSPENDS 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 make_inode)83{84 struct inode *inode;85 struct file *file;86 87 if (fops->owner && !try_module_get(fops->owner))88 return ERR_PTR(-ENOENT);89 90 if (make_inode) {91 inode = anon_inode_make_secure_inode(name, context_inode);92 if (IS_ERR(inode)) {93 file = ERR_CAST(inode);94 goto err;95 }96 } else {97 inode = anon_inode_inode;98 if (IS_ERR(inode)) {99 file = ERR_PTR(-ENODEV);100 goto err;101 }102 /*103 * We know the anon_inode inode count is always104 * greater than zero, so ihold() is safe.105 */106 ihold(inode);107 }108 109 file = alloc_file_pseudo(inode, anon_inode_mnt, name,110 flags & (O_ACCMODE | O_NONBLOCK), fops);111 if (IS_ERR(file))112 goto err_iput;113 114 file->f_mapping = inode->i_mapping;115 116 file->private_data = priv;117 118 return file;119 120err_iput:121 iput(inode);122err:123 module_put(fops->owner);124 return file;125}126 127/**128 * anon_inode_getfile - creates a new file instance by hooking it up to an129 * anonymous inode, and a dentry that describe the "class"130 * of the file131 *132 * @name: [in] name of the "class" of the new file133 * @fops: [in] file operations for the new file134 * @priv: [in] private data for the new file (will be file's private_data)135 * @flags: [in] flags136 *137 * Creates a new file by hooking it on a single inode. This is useful for files138 * 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/dentry141 * setup. Returns the newly created file* or an error pointer.142 */143struct file *anon_inode_getfile(const char *name,144 const struct file_operations *fops,145 void *priv, int flags)146{147 return __anon_inode_getfile(name, fops, priv, flags, NULL, false);148}149EXPORT_SYMBOL_GPL(anon_inode_getfile);150 151/**152 * anon_inode_getfile_fmode - creates a new file instance by hooking it up to an153 * anonymous inode, and a dentry that describe the "class"154 * of the file155 *156 * @name: [in] name of the "class" of the new file157 * @fops: [in] file operations for the new file158 * @priv: [in] private data for the new file (will be file's private_data)159 * @flags: [in] flags160 * @f_mode: [in] fmode161 *162 * Creates a new file by hooking it on a single inode. This is useful for files163 * that do not need to have a full-fledged inode in order to operate correctly.164 * All the files created with anon_inode_getfile() will share a single inode,165 * hence saving memory and avoiding code duplication for the file/inode/dentry166 * setup. Allows setting the fmode. Returns the newly created file* or an error167 * pointer.168 */169struct file *anon_inode_getfile_fmode(const char *name,170 const struct file_operations *fops,171 void *priv, int flags, fmode_t f_mode)172{173 struct file *file;174 175 file = __anon_inode_getfile(name, fops, priv, flags, NULL, false);176 if (!IS_ERR(file))177 file->f_mode |= f_mode;178 179 return file;180}181EXPORT_SYMBOL_GPL(anon_inode_getfile_fmode);182 183/**184 * anon_inode_create_getfile - Like anon_inode_getfile(), but creates a new185 * !S_PRIVATE anon inode rather than reuse the186 * singleton anon inode and calls the187 * inode_init_security_anon() LSM hook.188 *189 * @name: [in] name of the "class" of the new file190 * @fops: [in] file operations for the new file191 * @priv: [in] private data for the new file (will be file's private_data)192 * @flags: [in] flags193 * @context_inode:194 * [in] the logical relationship with the new inode (optional)195 *196 * Create a new anonymous inode and file pair. This can be done for two197 * reasons:198 *199 * - for the inode to have its own security context, so that LSMs can enforce200 * policy on the inode's creation;201 *202 * - if the caller needs a unique inode, for example in order to customize203 * the size returned by fstat()204 *205 * The LSM may use @context_inode in inode_init_security_anon(), but a206 * reference to it is not held.207 *208 * Returns the newly created file* or an error pointer.209 */210struct file *anon_inode_create_getfile(const char *name,211 const struct file_operations *fops,212 void *priv, int flags,213 const struct inode *context_inode)214{215 return __anon_inode_getfile(name, fops, priv, flags,216 context_inode, true);217}218EXPORT_SYMBOL_GPL(anon_inode_create_getfile);219 220static HWJS_SUSPENDS int __anon_inode_getfd(const char *name,221 const struct file_operations *fops,222 void *priv, int flags,223 const struct inode *context_inode,224 bool make_inode)225{226 int error, fd;227 struct file *file;228 229 error = get_unused_fd_flags(flags);230 if (error < 0)231 return error;232 fd = error;233 234 file = __anon_inode_getfile(name, fops, priv, flags, context_inode,235 make_inode);236 if (IS_ERR(file)) {237 error = PTR_ERR(file);238 goto err_put_unused_fd;239 }240 fd_install(fd, file);241 242 return fd;243 244err_put_unused_fd:245 put_unused_fd(fd);246 return error;247}248 249/**250 * anon_inode_getfd - creates a new file instance by hooking it up to251 * an anonymous inode and a dentry that describe252 * the "class" of the file253 *254 * @name: [in] name of the "class" of the new file255 * @fops: [in] file operations for the new file256 * @priv: [in] private data for the new file (will be file's private_data)257 * @flags: [in] flags258 *259 * Creates a new file by hooking it on a single inode. This is260 * useful for files that do not need to have a full-fledged inode in261 * order to operate correctly. All the files created with262 * anon_inode_getfd() will use the same singleton inode, reducing263 * memory use and avoiding code duplication for the file/inode/dentry264 * setup. Returns a newly created file descriptor or an error code.265 */266int anon_inode_getfd(const char *name, const struct file_operations *fops,267 void *priv, int flags)268{269 return __anon_inode_getfd(name, fops, priv, flags, NULL, false);270}271EXPORT_SYMBOL_GPL(anon_inode_getfd);272 273/**274 * anon_inode_create_getfd - Like anon_inode_getfd(), but creates a new275 * !S_PRIVATE anon inode rather than reuse the singleton anon inode, and calls276 * the inode_init_security_anon() LSM hook.277 *278 * @name: [in] name of the "class" of the new file279 * @fops: [in] file operations for the new file280 * @priv: [in] private data for the new file (will be file's private_data)281 * @flags: [in] flags282 * @context_inode:283 * [in] the logical relationship with the new inode (optional)284 *285 * Create a new anonymous inode and file pair. This can be done for two286 * reasons:287 *288 * - for the inode to have its own security context, so that LSMs can enforce289 * policy on the inode's creation;290 *291 * - if the caller needs a unique inode, for example in order to customize292 * the size returned by fstat()293 *294 * The LSM may use @context_inode in inode_init_security_anon(), but a295 * reference to it is not held.296 *297 * Returns a newly created file descriptor or an error code.298 */299int anon_inode_create_getfd(const char *name, const struct file_operations *fops,300 void *priv, int flags,301 const struct inode *context_inode)302{303 return __anon_inode_getfd(name, fops, priv, flags, context_inode, true);304}305 306 307static int __init anon_inode_init(void)308{309 anon_inode_mnt = kern_mount(&anon_inode_fs_type);310 if (IS_ERR(anon_inode_mnt))311 panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt));312 313 anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);314 if (IS_ERR(anon_inode_inode))315 panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode));316 317 return 0;318}319 320fs_initcall(anon_inode_init);321 322