aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/inode.c191
1 files changed, 50 insertions, 141 deletions
diff --git a/security/inode.c b/security/inode.c
index 90a70a67d835..43ce6e19015f 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -25,100 +25,6 @@
25static struct vfsmount *mount; 25static struct vfsmount *mount;
26static int mount_count; 26static int mount_count;
27 27
28/*
29 * TODO:
30 * I think I can get rid of these default_file_ops, but not quite sure...
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 .llseek = noop_llseek,
57};
58
59static struct inode *get_inode(struct super_block *sb, umode_t mode, dev_t dev)
60{
61 struct inode *inode = new_inode(sb);
62
63 if (inode) {
64 inode->i_ino = get_next_ino();
65 inode->i_mode = mode;
66 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
67 switch (mode & S_IFMT) {
68 default:
69 init_special_inode(inode, mode, dev);
70 break;
71 case S_IFREG:
72 inode->i_fop = &default_file_ops;
73 break;
74 case S_IFDIR:
75 inode->i_op = &simple_dir_inode_operations;
76 inode->i_fop = &simple_dir_operations;
77
78 /* directory inodes start off with i_nlink == 2 (for "." entry) */
79 inc_nlink(inode);
80 break;
81 }
82 }
83 return inode;
84}
85
86/* SMP-safe */
87static int mknod(struct inode *dir, struct dentry *dentry,
88 umode_t mode, dev_t dev)
89{
90 struct inode *inode;
91 int error = -ENOMEM;
92
93 if (dentry->d_inode)
94 return -EEXIST;
95
96 inode = get_inode(dir->i_sb, mode, dev);
97 if (inode) {
98 d_instantiate(dentry, inode);
99 dget(dentry);
100 error = 0;
101 }
102 return error;
103}
104
105static int mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
106{
107 int res;
108
109 mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
110 res = mknod(dir, dentry, mode, 0);
111 if (!res)
112 inc_nlink(dir);
113 return res;
114}
115
116static int create(struct inode *dir, struct dentry *dentry, umode_t mode)
117{
118 mode = (mode & S_IALLUGO) | S_IFREG;
119 return mknod(dir, dentry, mode, 0);
120}
121
122static inline int positive(struct dentry *dentry) 28static inline int positive(struct dentry *dentry)
123{ 29{
124 return dentry->d_inode && !d_unhashed(dentry); 30 return dentry->d_inode && !d_unhashed(dentry);
@@ -145,38 +51,6 @@ static struct file_system_type fs_type = {
145 .kill_sb = kill_litter_super, 51 .kill_sb = kill_litter_super,
146}; 52};
147 53
148static int create_by_name(const char *name, umode_t mode,
149 struct dentry *parent,
150 struct dentry **dentry)
151{
152 int error = 0;
153
154 *dentry = NULL;
155
156 /* If the parent is not specified, we create it in the root.
157 * We need the root dentry to do this, which is in the super
158 * block. A pointer to that is in the struct vfsmount that we
159 * have around.
160 */
161 if (!parent)
162 parent = mount->mnt_root;
163
164 mutex_lock(&parent->d_inode->i_mutex);
165 *dentry = lookup_one_len(name, parent, strlen(name));
166 if (!IS_ERR(*dentry)) {
167 if (S_ISDIR(mode))
168 error = mkdir(parent->d_inode, *dentry, mode);
169 else
170 error = create(parent->d_inode, *dentry, mode);
171 if (error)
172 dput(*dentry);
173 } else
174 error = PTR_ERR(*dentry);
175 mutex_unlock(&parent->d_inode->i_mutex);
176
177 return error;
178}
179
180/** 54/**
181 * securityfs_create_file - create a file in the securityfs filesystem 55 * securityfs_create_file - create a file in the securityfs filesystem
182 * 56 *
@@ -209,31 +83,66 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode,
209 struct dentry *parent, void *data, 83 struct dentry *parent, void *data,
210 const struct file_operations *fops) 84 const struct file_operations *fops)
211{ 85{
212 struct dentry *dentry = NULL; 86 struct dentry *dentry;
87 int is_dir = S_ISDIR(mode);
88 struct inode *dir, *inode;
213 int error; 89 int error;
214 90
91 if (!is_dir) {
92 BUG_ON(!fops);
93 mode = (mode & S_IALLUGO) | S_IFREG;
94 }
95
215 pr_debug("securityfs: creating file '%s'\n",name); 96 pr_debug("securityfs: creating file '%s'\n",name);
216 97
217 error = simple_pin_fs(&fs_type, &mount, &mount_count); 98 error = simple_pin_fs(&fs_type, &mount, &mount_count);
218 if (error) { 99 if (error)
219 dentry = ERR_PTR(error); 100 return ERR_PTR(error);
220 goto exit; 101
102 if (!parent)
103 parent = mount->mnt_root;
104
105 dir = parent->d_inode;
106
107 mutex_lock(&dir->i_mutex);
108 dentry = lookup_one_len(name, parent, strlen(name));
109 if (IS_ERR(dentry))
110 goto out;
111
112 if (dentry->d_inode) {
113 error = -EEXIST;
114 goto out1;
221 } 115 }
222 116
223 error = create_by_name(name, mode, parent, &dentry); 117 inode = new_inode(dir->i_sb);
224 if (error) { 118 if (!inode) {
225 dentry = ERR_PTR(error); 119 error = -ENOMEM;
226 simple_release_fs(&mount, &mount_count); 120 goto out1;
227 goto exit;
228 } 121 }
229 122
230 if (dentry->d_inode) { 123 inode->i_ino = get_next_ino();
231 if (fops) 124 inode->i_mode = mode;
232 dentry->d_inode->i_fop = fops; 125 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
233 if (data) 126 inode->i_private = data;
234 dentry->d_inode->i_private = data; 127 if (is_dir) {
128 inode->i_op = &simple_dir_inode_operations;
129 inode->i_fop = &simple_dir_operations;
130 inc_nlink(inode);
131 inc_nlink(dir);
132 } else {
133 inode->i_fop = fops;
235 } 134 }
236exit: 135 d_instantiate(dentry, inode);
136 dget(dentry);
137 mutex_unlock(&dir->i_mutex);
138 return dentry;
139
140out1:
141 dput(dentry);
142 dentry = ERR_PTR(error);
143out:
144 mutex_unlock(&dir->i_mutex);
145 simple_release_fs(&mount, &mount_count);
237 return dentry; 146 return dentry;
238} 147}
239EXPORT_SYMBOL_GPL(securityfs_create_file); 148EXPORT_SYMBOL_GPL(securityfs_create_file);