1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/module.h>
17#include <linux/fs.h>
18#include <linux/mount.h>
19#include <linux/pagemap.h>
20#include <linux/init.h>
21#include <linux/namei.h>
22#include <linux/security.h>
23#include <linux/magic.h>
24
25static struct vfsmount *mount;
26static int mount_count;
27
28
29
30
31
32static ssize_t default_read_file(struct file *file, char __user *buf,
33 size_t count, loff_t *ppos)
34{
35 return 0;
36}
37
38static ssize_t default_write_file(struct file *file, const char __user *buf,
39 size_t count, loff_t *ppos)
40{
41 return count;
42}
43
44static int default_open(struct inode *inode, struct file *file)
45{
46 if (inode->i_private)
47 file->private_data = inode->i_private;
48
49 return 0;
50}
51
52static const struct file_operations default_file_ops = {
53 .read = default_read_file,
54 .write = default_write_file,
55 .open = default_open,
56};
57
58static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
59{
60 struct inode *inode = new_inode(sb);
61
62 if (inode) {
63 inode->i_mode = mode;
64 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
65 switch (mode & S_IFMT) {
66 default:
67 init_special_inode(inode, mode, dev);
68 break;
69 case S_IFREG:
70 inode->i_fop = &default_file_ops;
71 break;
72 case S_IFDIR:
73 inode->i_op = &simple_dir_inode_operations;
74 inode->i_fop = &simple_dir_operations;
75
76
77 inc_nlink(inode);
78 break;
79 }
80 }
81 return inode;
82}
83
84
85static int mknod(struct inode *dir, struct dentry *dentry,
86 int mode, dev_t dev)
87{
88 struct inode *inode;
89 int error = -EPERM;
90
91 if (dentry->d_inode)
92 return -EEXIST;
93
94 inode = get_inode(dir->i_sb, mode, dev);
95 if (inode) {
96 d_instantiate(dentry, inode);
97 dget(dentry);
98 error = 0;
99 }
100 return error;
101}
102
103static int mkdir(struct inode *dir, struct dentry *dentry, int mode)
104{
105 int res;
106
107 mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
108 res = mknod(dir, dentry, mode, 0);
109 if (!res)
110 inc_nlink(dir);
111 return res;
112}
113
114static int create(struct inode *dir, struct dentry *dentry, int mode)
115{
116 mode = (mode & S_IALLUGO) | S_IFREG;
117 return mknod(dir, dentry, mode, 0);
118}
119
120static inline int positive(struct dentry *dentry)
121{
122 return dentry->d_inode && !d_unhashed(dentry);
123}
124
125static int fill_super(struct super_block *sb, void *data, int silent)
126{
127 static struct tree_descr files[] = {{""}};
128
129 return simple_fill_super(sb, SECURITYFS_MAGIC, files);
130}
131
132static int get_sb(struct file_system_type *fs_type,
133 int flags, const char *dev_name,
134 void *data, struct vfsmount *mnt)
135{
136 return get_sb_single(fs_type, flags, data, fill_super, mnt);
137}
138
139static struct file_system_type fs_type = {
140 .owner = THIS_MODULE,
141 .name = "securityfs",
142 .get_sb = get_sb,
143 .kill_sb = kill_litter_super,
144};
145
146static int create_by_name(const char *name, mode_t mode,
147 struct dentry *parent,
148 struct dentry **dentry)
149{
150 int error = 0;
151
152 *dentry = NULL;
153
154
155
156
157
158
159 if (!parent ) {
160 if (mount && mount->mnt_sb) {
161 parent = mount->mnt_sb->s_root;
162 }
163 }
164 if (!parent) {
165 pr_debug("securityfs: Ah! can not find a parent!\n");
166 return -EFAULT;
167 }
168
169 mutex_lock(&parent->d_inode->i_mutex);
170 *dentry = lookup_one_len(name, parent, strlen(name));
171 if (!IS_ERR(dentry)) {
172 if ((mode & S_IFMT) == S_IFDIR)
173 error = mkdir(parent->d_inode, *dentry, mode);
174 else
175 error = create(parent->d_inode, *dentry, mode);
176 } else
177 error = PTR_ERR(dentry);
178 mutex_unlock(&parent->d_inode->i_mutex);
179
180 return error;
181}
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211struct dentry *securityfs_create_file(const char *name, mode_t mode,
212 struct dentry *parent, void *data,
213 const struct file_operations *fops)
214{
215 struct dentry *dentry = NULL;
216 int error;
217
218 pr_debug("securityfs: creating file '%s'\n",name);
219
220 error = simple_pin_fs(&fs_type, &mount, &mount_count);
221 if (error) {
222 dentry = ERR_PTR(error);
223 goto exit;
224 }
225
226 error = create_by_name(name, mode, parent, &dentry);
227 if (error) {
228 dentry = ERR_PTR(error);
229 simple_release_fs(&mount, &mount_count);
230 goto exit;
231 }
232
233 if (dentry->d_inode) {
234 if (fops)
235 dentry->d_inode->i_fop = fops;
236 if (data)
237 dentry->d_inode->i_private = data;
238 }
239exit:
240 return dentry;
241}
242EXPORT_SYMBOL_GPL(securityfs_create_file);
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)
266{
267 return securityfs_create_file(name,
268 S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
269 parent, NULL, NULL);
270}
271EXPORT_SYMBOL_GPL(securityfs_create_dir);
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286void securityfs_remove(struct dentry *dentry)
287{
288 struct dentry *parent;
289
290 if (!dentry)
291 return;
292
293 parent = dentry->d_parent;
294 if (!parent || !parent->d_inode)
295 return;
296
297 mutex_lock(&parent->d_inode->i_mutex);
298 if (positive(dentry)) {
299 if (dentry->d_inode) {
300 if (S_ISDIR(dentry->d_inode->i_mode))
301 simple_rmdir(parent->d_inode, dentry);
302 else
303 simple_unlink(parent->d_inode, dentry);
304 dput(dentry);
305 }
306 }
307 mutex_unlock(&parent->d_inode->i_mutex);
308 simple_release_fs(&mount, &mount_count);
309}
310EXPORT_SYMBOL_GPL(securityfs_remove);
311
312static struct kobject *security_kobj;
313
314static int __init securityfs_init(void)
315{
316 int retval;
317
318 security_kobj = kobject_create_and_add("security", kernel_kobj);
319 if (!security_kobj)
320 return -EINVAL;
321
322 retval = register_filesystem(&fs_type);
323 if (retval)
324 kobject_put(security_kobj);
325 return retval;
326}
327
328core_initcall(securityfs_init);
329MODULE_LICENSE("GPL");
330
331