162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/anon_inodes.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Thanks to Arnd Bergmann for code review and suggestions. 862306a36Sopenharmony_ci * More changes for Thomas Gleixner suggestions. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/cred.h> 1362306a36Sopenharmony_ci#include <linux/file.h> 1462306a36Sopenharmony_ci#include <linux/poll.h> 1562306a36Sopenharmony_ci#include <linux/sched.h> 1662306a36Sopenharmony_ci#include <linux/init.h> 1762306a36Sopenharmony_ci#include <linux/fs.h> 1862306a36Sopenharmony_ci#include <linux/mount.h> 1962306a36Sopenharmony_ci#include <linux/module.h> 2062306a36Sopenharmony_ci#include <linux/kernel.h> 2162306a36Sopenharmony_ci#include <linux/magic.h> 2262306a36Sopenharmony_ci#include <linux/anon_inodes.h> 2362306a36Sopenharmony_ci#include <linux/pseudo_fs.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <linux/uaccess.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic struct vfsmount *anon_inode_mnt __read_mostly; 2862306a36Sopenharmony_cistatic struct inode *anon_inode_inode; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * anon_inodefs_dname() is called from d_path(). 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_cistatic char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci return dynamic_dname(buffer, buflen, "anon_inode:%s", 3662306a36Sopenharmony_ci dentry->d_name.name); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic const struct dentry_operations anon_inodefs_dentry_operations = { 4062306a36Sopenharmony_ci .d_dname = anon_inodefs_dname, 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic int anon_inodefs_init_fs_context(struct fs_context *fc) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci struct pseudo_fs_context *ctx = init_pseudo(fc, ANON_INODE_FS_MAGIC); 4662306a36Sopenharmony_ci if (!ctx) 4762306a36Sopenharmony_ci return -ENOMEM; 4862306a36Sopenharmony_ci ctx->dops = &anon_inodefs_dentry_operations; 4962306a36Sopenharmony_ci return 0; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic struct file_system_type anon_inode_fs_type = { 5362306a36Sopenharmony_ci .name = "anon_inodefs", 5462306a36Sopenharmony_ci .init_fs_context = anon_inodefs_init_fs_context, 5562306a36Sopenharmony_ci .kill_sb = kill_anon_super, 5662306a36Sopenharmony_ci}; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic struct inode *anon_inode_make_secure_inode( 5962306a36Sopenharmony_ci const char *name, 6062306a36Sopenharmony_ci const struct inode *context_inode) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct inode *inode; 6362306a36Sopenharmony_ci const struct qstr qname = QSTR_INIT(name, strlen(name)); 6462306a36Sopenharmony_ci int error; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); 6762306a36Sopenharmony_ci if (IS_ERR(inode)) 6862306a36Sopenharmony_ci return inode; 6962306a36Sopenharmony_ci inode->i_flags &= ~S_PRIVATE; 7062306a36Sopenharmony_ci error = security_inode_init_security_anon(inode, &qname, context_inode); 7162306a36Sopenharmony_ci if (error) { 7262306a36Sopenharmony_ci iput(inode); 7362306a36Sopenharmony_ci return ERR_PTR(error); 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci return inode; 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic struct file *__anon_inode_getfile(const char *name, 7962306a36Sopenharmony_ci const struct file_operations *fops, 8062306a36Sopenharmony_ci void *priv, int flags, 8162306a36Sopenharmony_ci const struct inode *context_inode, 8262306a36Sopenharmony_ci bool secure) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci struct inode *inode; 8562306a36Sopenharmony_ci struct file *file; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (fops->owner && !try_module_get(fops->owner)) 8862306a36Sopenharmony_ci return ERR_PTR(-ENOENT); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (secure) { 9162306a36Sopenharmony_ci inode = anon_inode_make_secure_inode(name, context_inode); 9262306a36Sopenharmony_ci if (IS_ERR(inode)) { 9362306a36Sopenharmony_ci file = ERR_CAST(inode); 9462306a36Sopenharmony_ci goto err; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci } else { 9762306a36Sopenharmony_ci inode = anon_inode_inode; 9862306a36Sopenharmony_ci if (IS_ERR(inode)) { 9962306a36Sopenharmony_ci file = ERR_PTR(-ENODEV); 10062306a36Sopenharmony_ci goto err; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci /* 10362306a36Sopenharmony_ci * We know the anon_inode inode count is always 10462306a36Sopenharmony_ci * greater than zero, so ihold() is safe. 10562306a36Sopenharmony_ci */ 10662306a36Sopenharmony_ci ihold(inode); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci file = alloc_file_pseudo(inode, anon_inode_mnt, name, 11062306a36Sopenharmony_ci flags & (O_ACCMODE | O_NONBLOCK), fops); 11162306a36Sopenharmony_ci if (IS_ERR(file)) 11262306a36Sopenharmony_ci goto err_iput; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci file->f_mapping = inode->i_mapping; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci file->private_data = priv; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci return file; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cierr_iput: 12162306a36Sopenharmony_ci iput(inode); 12262306a36Sopenharmony_cierr: 12362306a36Sopenharmony_ci module_put(fops->owner); 12462306a36Sopenharmony_ci return file; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/** 12862306a36Sopenharmony_ci * anon_inode_getfile - creates a new file instance by hooking it up to an 12962306a36Sopenharmony_ci * anonymous inode, and a dentry that describe the "class" 13062306a36Sopenharmony_ci * of the file 13162306a36Sopenharmony_ci * 13262306a36Sopenharmony_ci * @name: [in] name of the "class" of the new file 13362306a36Sopenharmony_ci * @fops: [in] file operations for the new file 13462306a36Sopenharmony_ci * @priv: [in] private data for the new file (will be file's private_data) 13562306a36Sopenharmony_ci * @flags: [in] flags 13662306a36Sopenharmony_ci * 13762306a36Sopenharmony_ci * Creates a new file by hooking it on a single inode. This is useful for files 13862306a36Sopenharmony_ci * that do not need to have a full-fledged inode in order to operate correctly. 13962306a36Sopenharmony_ci * All the files created with anon_inode_getfile() will share a single inode, 14062306a36Sopenharmony_ci * hence saving memory and avoiding code duplication for the file/inode/dentry 14162306a36Sopenharmony_ci * setup. Returns the newly created file* or an error pointer. 14262306a36Sopenharmony_ci */ 14362306a36Sopenharmony_cistruct file *anon_inode_getfile(const char *name, 14462306a36Sopenharmony_ci const struct file_operations *fops, 14562306a36Sopenharmony_ci void *priv, int flags) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci return __anon_inode_getfile(name, fops, priv, flags, NULL, false); 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(anon_inode_getfile); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci/** 15262306a36Sopenharmony_ci * anon_inode_getfile_secure - Like anon_inode_getfile(), but creates a new 15362306a36Sopenharmony_ci * !S_PRIVATE anon inode rather than reuse the 15462306a36Sopenharmony_ci * singleton anon inode and calls the 15562306a36Sopenharmony_ci * inode_init_security_anon() LSM hook. This 15662306a36Sopenharmony_ci * allows for both the inode to have its own 15762306a36Sopenharmony_ci * security context and for the LSM to enforce 15862306a36Sopenharmony_ci * policy on the inode's creation. 15962306a36Sopenharmony_ci * 16062306a36Sopenharmony_ci * @name: [in] name of the "class" of the new file 16162306a36Sopenharmony_ci * @fops: [in] file operations for the new file 16262306a36Sopenharmony_ci * @priv: [in] private data for the new file (will be file's private_data) 16362306a36Sopenharmony_ci * @flags: [in] flags 16462306a36Sopenharmony_ci * @context_inode: 16562306a36Sopenharmony_ci * [in] the logical relationship with the new inode (optional) 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * The LSM may use @context_inode in inode_init_security_anon(), but a 16862306a36Sopenharmony_ci * reference to it is not held. Returns the newly created file* or an error 16962306a36Sopenharmony_ci * pointer. See the anon_inode_getfile() documentation for more information. 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_cistruct file *anon_inode_getfile_secure(const char *name, 17262306a36Sopenharmony_ci const struct file_operations *fops, 17362306a36Sopenharmony_ci void *priv, int flags, 17462306a36Sopenharmony_ci const struct inode *context_inode) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci return __anon_inode_getfile(name, fops, priv, flags, 17762306a36Sopenharmony_ci context_inode, true); 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic int __anon_inode_getfd(const char *name, 18162306a36Sopenharmony_ci const struct file_operations *fops, 18262306a36Sopenharmony_ci void *priv, int flags, 18362306a36Sopenharmony_ci const struct inode *context_inode, 18462306a36Sopenharmony_ci bool secure) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci int error, fd; 18762306a36Sopenharmony_ci struct file *file; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci error = get_unused_fd_flags(flags); 19062306a36Sopenharmony_ci if (error < 0) 19162306a36Sopenharmony_ci return error; 19262306a36Sopenharmony_ci fd = error; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci file = __anon_inode_getfile(name, fops, priv, flags, context_inode, 19562306a36Sopenharmony_ci secure); 19662306a36Sopenharmony_ci if (IS_ERR(file)) { 19762306a36Sopenharmony_ci error = PTR_ERR(file); 19862306a36Sopenharmony_ci goto err_put_unused_fd; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci fd_install(fd, file); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return fd; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cierr_put_unused_fd: 20562306a36Sopenharmony_ci put_unused_fd(fd); 20662306a36Sopenharmony_ci return error; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/** 21062306a36Sopenharmony_ci * anon_inode_getfd - creates a new file instance by hooking it up to 21162306a36Sopenharmony_ci * an anonymous inode and a dentry that describe 21262306a36Sopenharmony_ci * the "class" of the file 21362306a36Sopenharmony_ci * 21462306a36Sopenharmony_ci * @name: [in] name of the "class" of the new file 21562306a36Sopenharmony_ci * @fops: [in] file operations for the new file 21662306a36Sopenharmony_ci * @priv: [in] private data for the new file (will be file's private_data) 21762306a36Sopenharmony_ci * @flags: [in] flags 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * Creates a new file by hooking it on a single inode. This is 22062306a36Sopenharmony_ci * useful for files that do not need to have a full-fledged inode in 22162306a36Sopenharmony_ci * order to operate correctly. All the files created with 22262306a36Sopenharmony_ci * anon_inode_getfd() will use the same singleton inode, reducing 22362306a36Sopenharmony_ci * memory use and avoiding code duplication for the file/inode/dentry 22462306a36Sopenharmony_ci * setup. Returns a newly created file descriptor or an error code. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ciint anon_inode_getfd(const char *name, const struct file_operations *fops, 22762306a36Sopenharmony_ci void *priv, int flags) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci return __anon_inode_getfd(name, fops, priv, flags, NULL, false); 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(anon_inode_getfd); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/** 23462306a36Sopenharmony_ci * anon_inode_getfd_secure - Like anon_inode_getfd(), but creates a new 23562306a36Sopenharmony_ci * !S_PRIVATE anon inode rather than reuse the singleton anon inode, and calls 23662306a36Sopenharmony_ci * the inode_init_security_anon() LSM hook. This allows the inode to have its 23762306a36Sopenharmony_ci * own security context and for a LSM to reject creation of the inode. 23862306a36Sopenharmony_ci * 23962306a36Sopenharmony_ci * @name: [in] name of the "class" of the new file 24062306a36Sopenharmony_ci * @fops: [in] file operations for the new file 24162306a36Sopenharmony_ci * @priv: [in] private data for the new file (will be file's private_data) 24262306a36Sopenharmony_ci * @flags: [in] flags 24362306a36Sopenharmony_ci * @context_inode: 24462306a36Sopenharmony_ci * [in] the logical relationship with the new inode (optional) 24562306a36Sopenharmony_ci * 24662306a36Sopenharmony_ci * The LSM may use @context_inode in inode_init_security_anon(), but a 24762306a36Sopenharmony_ci * reference to it is not held. 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_ciint anon_inode_getfd_secure(const char *name, const struct file_operations *fops, 25062306a36Sopenharmony_ci void *priv, int flags, 25162306a36Sopenharmony_ci const struct inode *context_inode) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci return __anon_inode_getfd(name, fops, priv, flags, context_inode, true); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(anon_inode_getfd_secure); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic int __init anon_inode_init(void) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci anon_inode_mnt = kern_mount(&anon_inode_fs_type); 26062306a36Sopenharmony_ci if (IS_ERR(anon_inode_mnt)) 26162306a36Sopenharmony_ci panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt)); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); 26462306a36Sopenharmony_ci if (IS_ERR(anon_inode_inode)) 26562306a36Sopenharmony_ci panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode)); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci return 0; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cifs_initcall(anon_inode_init); 27162306a36Sopenharmony_ci 272