brintos

brintos / linux-shallow public Read only

0
0
Text · 9.6 KiB · 7cf7d35 Raw
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