diff options
author | John Johansen <john.johansen@canonical.com> | 2017-05-07 08:53:37 -0400 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2017-06-08 15:51:43 -0400 |
commit | 6623ec7c4dbe18a5a2878e2d888be70d08a91826 (patch) | |
tree | b0276f0c66e05836c58eb57b04a545f1dfd06260 /security/inode.c | |
parent | 4227c333f65cddc6c2f048e5b67cfe796b9df9a6 (diff) |
securityfs: add the ability to support symlinks
Signed-off-by: John Johansen <john.johansen@canonical.com>
Reviewed-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'security/inode.c')
-rw-r--r-- | security/inode.c | 144 |
1 files changed, 123 insertions, 21 deletions
diff --git a/security/inode.c b/security/inode.c index eccd58ef2ae8..8dd9ca8848e4 100644 --- a/security/inode.c +++ b/security/inode.c | |||
@@ -26,11 +26,31 @@ | |||
26 | static struct vfsmount *mount; | 26 | static struct vfsmount *mount; |
27 | static int mount_count; | 27 | static int mount_count; |
28 | 28 | ||
29 | static void securityfs_evict_inode(struct inode *inode) | ||
30 | { | ||
31 | truncate_inode_pages_final(&inode->i_data); | ||
32 | clear_inode(inode); | ||
33 | if (S_ISLNK(inode->i_mode)) | ||
34 | kfree(inode->i_link); | ||
35 | } | ||
36 | |||
37 | static const struct super_operations securityfs_super_operations = { | ||
38 | .statfs = simple_statfs, | ||
39 | .evict_inode = securityfs_evict_inode, | ||
40 | }; | ||
41 | |||
29 | static int fill_super(struct super_block *sb, void *data, int silent) | 42 | static int fill_super(struct super_block *sb, void *data, int silent) |
30 | { | 43 | { |
31 | static const struct tree_descr files[] = {{""}}; | 44 | static const struct tree_descr files[] = {{""}}; |
45 | int error; | ||
46 | |||
47 | error = simple_fill_super(sb, SECURITYFS_MAGIC, files); | ||
48 | if (error) | ||
49 | return error; | ||
50 | |||
51 | sb->s_op = &securityfs_super_operations; | ||
32 | 52 | ||
33 | return simple_fill_super(sb, SECURITYFS_MAGIC, files); | 53 | return 0; |
34 | } | 54 | } |
35 | 55 | ||
36 | static struct dentry *get_sb(struct file_system_type *fs_type, | 56 | static struct dentry *get_sb(struct file_system_type *fs_type, |
@@ -48,7 +68,7 @@ static struct file_system_type fs_type = { | |||
48 | }; | 68 | }; |
49 | 69 | ||
50 | /** | 70 | /** |
51 | * securityfs_create_file - create a file in the securityfs filesystem | 71 | * securityfs_create_dentry - create a dentry in the securityfs filesystem |
52 | * | 72 | * |
53 | * @name: a pointer to a string containing the name of the file to create. | 73 | * @name: a pointer to a string containing the name of the file to create. |
54 | * @mode: the permission that the file should have | 74 | * @mode: the permission that the file should have |
@@ -60,34 +80,35 @@ static struct file_system_type fs_type = { | |||
60 | * the open() call. | 80 | * the open() call. |
61 | * @fops: a pointer to a struct file_operations that should be used for | 81 | * @fops: a pointer to a struct file_operations that should be used for |
62 | * this file. | 82 | * this file. |
83 | * @iops: a point to a struct of inode_operations that should be used for | ||
84 | * this file/dir | ||
63 | * | 85 | * |
64 | * This is the basic "create a file" function for securityfs. It allows for a | 86 | * This is the basic "create a file/dir/symlink" function for |
65 | * wide range of flexibility in creating a file, or a directory (if you | 87 | * securityfs. It allows for a wide range of flexibility in creating |
66 | * want to create a directory, the securityfs_create_dir() function is | 88 | * a file, or a directory (if you want to create a directory, the |
67 | * recommended to be used instead). | 89 | * securityfs_create_dir() function is recommended to be used |
90 | * instead). | ||
68 | * | 91 | * |
69 | * This function returns a pointer to a dentry if it succeeds. This | 92 | * This function returns a pointer to a dentry if it succeeds. This |
70 | * pointer must be passed to the securityfs_remove() function when the file is | 93 | * pointer must be passed to the securityfs_remove() function when the |
71 | * to be removed (no automatic cleanup happens if your module is unloaded, | 94 | * file is to be removed (no automatic cleanup happens if your module |
72 | * you are responsible here). If an error occurs, the function will return | 95 | * is unloaded, you are responsible here). If an error occurs, the |
73 | * the error value (via ERR_PTR). | 96 | * function will return the error value (via ERR_PTR). |
74 | * | 97 | * |
75 | * If securityfs is not enabled in the kernel, the value %-ENODEV is | 98 | * If securityfs is not enabled in the kernel, the value %-ENODEV is |
76 | * returned. | 99 | * returned. |
77 | */ | 100 | */ |
78 | struct dentry *securityfs_create_file(const char *name, umode_t mode, | 101 | static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, |
79 | struct dentry *parent, void *data, | 102 | struct dentry *parent, void *data, |
80 | const struct file_operations *fops) | 103 | const struct file_operations *fops, |
104 | const struct inode_operations *iops) | ||
81 | { | 105 | { |
82 | struct dentry *dentry; | 106 | struct dentry *dentry; |
83 | int is_dir = S_ISDIR(mode); | ||
84 | struct inode *dir, *inode; | 107 | struct inode *dir, *inode; |
85 | int error; | 108 | int error; |
86 | 109 | ||
87 | if (!is_dir) { | 110 | if (!(mode & S_IFMT)) |
88 | BUG_ON(!fops); | ||
89 | mode = (mode & S_IALLUGO) | S_IFREG; | 111 | mode = (mode & S_IALLUGO) | S_IFREG; |
90 | } | ||
91 | 112 | ||
92 | pr_debug("securityfs: creating file '%s'\n",name); | 113 | pr_debug("securityfs: creating file '%s'\n",name); |
93 | 114 | ||
@@ -120,11 +141,14 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode, | |||
120 | inode->i_mode = mode; | 141 | inode->i_mode = mode; |
121 | inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); | 142 | inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); |
122 | inode->i_private = data; | 143 | inode->i_private = data; |
123 | if (is_dir) { | 144 | if (S_ISDIR(mode)) { |
124 | inode->i_op = &simple_dir_inode_operations; | 145 | inode->i_op = &simple_dir_inode_operations; |
125 | inode->i_fop = &simple_dir_operations; | 146 | inode->i_fop = &simple_dir_operations; |
126 | inc_nlink(inode); | 147 | inc_nlink(inode); |
127 | inc_nlink(dir); | 148 | inc_nlink(dir); |
149 | } else if (S_ISLNK(mode)) { | ||
150 | inode->i_op = iops ? iops : &simple_symlink_inode_operations; | ||
151 | inode->i_link = data; | ||
128 | } else { | 152 | } else { |
129 | inode->i_fop = fops; | 153 | inode->i_fop = fops; |
130 | } | 154 | } |
@@ -141,6 +165,38 @@ out: | |||
141 | simple_release_fs(&mount, &mount_count); | 165 | simple_release_fs(&mount, &mount_count); |
142 | return dentry; | 166 | return dentry; |
143 | } | 167 | } |
168 | |||
169 | /** | ||
170 | * securityfs_create_file - create a file in the securityfs filesystem | ||
171 | * | ||
172 | * @name: a pointer to a string containing the name of the file to create. | ||
173 | * @mode: the permission that the file should have | ||
174 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
175 | * directory dentry if set. If this parameter is %NULL, then the | ||
176 | * file will be created in the root of the securityfs filesystem. | ||
177 | * @data: a pointer to something that the caller will want to get to later | ||
178 | * on. The inode.i_private pointer will point to this value on | ||
179 | * the open() call. | ||
180 | * @fops: a pointer to a struct file_operations that should be used for | ||
181 | * this file. | ||
182 | * | ||
183 | * This function creates a file in securityfs with the given @name. | ||
184 | * | ||
185 | * This function returns a pointer to a dentry if it succeeds. This | ||
186 | * pointer must be passed to the securityfs_remove() function when the file is | ||
187 | * to be removed (no automatic cleanup happens if your module is unloaded, | ||
188 | * you are responsible here). If an error occurs, the function will return | ||
189 | * the error value (via ERR_PTR). | ||
190 | * | ||
191 | * If securityfs is not enabled in the kernel, the value %-ENODEV is | ||
192 | * returned. | ||
193 | */ | ||
194 | struct dentry *securityfs_create_file(const char *name, umode_t mode, | ||
195 | struct dentry *parent, void *data, | ||
196 | const struct file_operations *fops) | ||
197 | { | ||
198 | return securityfs_create_dentry(name, mode, parent, data, fops, NULL); | ||
199 | } | ||
144 | EXPORT_SYMBOL_GPL(securityfs_create_file); | 200 | EXPORT_SYMBOL_GPL(securityfs_create_file); |
145 | 201 | ||
146 | /** | 202 | /** |
@@ -165,13 +221,59 @@ EXPORT_SYMBOL_GPL(securityfs_create_file); | |||
165 | */ | 221 | */ |
166 | struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) | 222 | struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) |
167 | { | 223 | { |
168 | return securityfs_create_file(name, | 224 | return securityfs_create_file(name, S_IFDIR | 0755, parent, NULL, NULL); |
169 | S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, | ||
170 | parent, NULL, NULL); | ||
171 | } | 225 | } |
172 | EXPORT_SYMBOL_GPL(securityfs_create_dir); | 226 | EXPORT_SYMBOL_GPL(securityfs_create_dir); |
173 | 227 | ||
174 | /** | 228 | /** |
229 | * securityfs_create_symlink - create a symlink in the securityfs filesystem | ||
230 | * | ||
231 | * @name: a pointer to a string containing the name of the symlink to | ||
232 | * create. | ||
233 | * @parent: a pointer to the parent dentry for the symlink. This should be a | ||
234 | * directory dentry if set. If this parameter is %NULL, then the | ||
235 | * directory will be created in the root of the securityfs filesystem. | ||
236 | * @target: a pointer to a string containing the name of the symlink's target. | ||
237 | * If this parameter is %NULL, then the @iops parameter needs to be | ||
238 | * setup to handle .readlink and .get_link inode_operations. | ||
239 | * @iops: a pointer to the struct inode_operations to use for the symlink. If | ||
240 | * this parameter is %NULL, then the default simple_symlink_inode | ||
241 | * operations will be used. | ||
242 | * | ||
243 | * This function creates a symlink in securityfs with the given @name. | ||
244 | * | ||
245 | * This function returns a pointer to a dentry if it succeeds. This | ||
246 | * pointer must be passed to the securityfs_remove() function when the file is | ||
247 | * to be removed (no automatic cleanup happens if your module is unloaded, | ||
248 | * you are responsible here). If an error occurs, the function will return | ||
249 | * the error value (via ERR_PTR). | ||
250 | * | ||
251 | * If securityfs is not enabled in the kernel, the value %-ENODEV is | ||
252 | * returned. | ||
253 | */ | ||
254 | struct dentry *securityfs_create_symlink(const char *name, | ||
255 | struct dentry *parent, | ||
256 | const char *target, | ||
257 | const struct inode_operations *iops) | ||
258 | { | ||
259 | struct dentry *dent; | ||
260 | char *link = NULL; | ||
261 | |||
262 | if (target) { | ||
263 | link = kstrdup(target, GFP_KERNEL); | ||
264 | if (!link) | ||
265 | return ERR_PTR(-ENOMEM); | ||
266 | } | ||
267 | dent = securityfs_create_dentry(name, S_IFLNK | 0444, parent, | ||
268 | link, NULL, iops); | ||
269 | if (IS_ERR(dent)) | ||
270 | kfree(link); | ||
271 | |||
272 | return dent; | ||
273 | } | ||
274 | EXPORT_SYMBOL_GPL(securityfs_create_symlink); | ||
275 | |||
276 | /** | ||
175 | * securityfs_remove - removes a file or directory from the securityfs filesystem | 277 | * securityfs_remove - removes a file or directory from the securityfs filesystem |
176 | * | 278 | * |
177 | * @dentry: a pointer to a the dentry of the file or directory to be removed. | 279 | * @dentry: a pointer to a the dentry of the file or directory to be removed. |