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