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