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