diff options
Diffstat (limited to 'drivers/android/binderfs.c')
-rw-r--r-- | drivers/android/binderfs.c | 282 |
1 files changed, 151 insertions, 131 deletions
diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index 7496b10532aa..6a2185eb66c5 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kdev_t.h> | 11 | #include <linux/kdev_t.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/list.h> | 13 | #include <linux/list.h> |
14 | #include <linux/namei.h> | ||
14 | #include <linux/magic.h> | 15 | #include <linux/magic.h> |
15 | #include <linux/major.h> | 16 | #include <linux/major.h> |
16 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
@@ -20,6 +21,7 @@ | |||
20 | #include <linux/parser.h> | 21 | #include <linux/parser.h> |
21 | #include <linux/radix-tree.h> | 22 | #include <linux/radix-tree.h> |
22 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | #include <linux/seq_file.h> | ||
23 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
24 | #include <linux/spinlock_types.h> | 26 | #include <linux/spinlock_types.h> |
25 | #include <linux/stddef.h> | 27 | #include <linux/stddef.h> |
@@ -30,7 +32,7 @@ | |||
30 | #include <linux/xarray.h> | 32 | #include <linux/xarray.h> |
31 | #include <uapi/asm-generic/errno-base.h> | 33 | #include <uapi/asm-generic/errno-base.h> |
32 | #include <uapi/linux/android/binder.h> | 34 | #include <uapi/linux/android/binder.h> |
33 | #include <uapi/linux/android/binder_ctl.h> | 35 | #include <uapi/linux/android/binderfs.h> |
34 | 36 | ||
35 | #include "binder_internal.h" | 37 | #include "binder_internal.h" |
36 | 38 | ||
@@ -39,14 +41,32 @@ | |||
39 | #define INODE_OFFSET 3 | 41 | #define INODE_OFFSET 3 |
40 | #define INTSTRLEN 21 | 42 | #define INTSTRLEN 21 |
41 | #define BINDERFS_MAX_MINOR (1U << MINORBITS) | 43 | #define BINDERFS_MAX_MINOR (1U << MINORBITS) |
42 | 44 | /* Ensure that the initial ipc namespace always has devices available. */ | |
43 | static struct vfsmount *binderfs_mnt; | 45 | #define BINDERFS_MAX_MINOR_CAPPED (BINDERFS_MAX_MINOR - 4) |
44 | 46 | ||
45 | static dev_t binderfs_dev; | 47 | static dev_t binderfs_dev; |
46 | static DEFINE_MUTEX(binderfs_minors_mutex); | 48 | static DEFINE_MUTEX(binderfs_minors_mutex); |
47 | static DEFINE_IDA(binderfs_minors); | 49 | static DEFINE_IDA(binderfs_minors); |
48 | 50 | ||
49 | /** | 51 | /** |
52 | * binderfs_mount_opts - mount options for binderfs | ||
53 | * @max: maximum number of allocatable binderfs binder devices | ||
54 | */ | ||
55 | struct binderfs_mount_opts { | ||
56 | int max; | ||
57 | }; | ||
58 | |||
59 | enum { | ||
60 | Opt_max, | ||
61 | Opt_err | ||
62 | }; | ||
63 | |||
64 | static const match_table_t tokens = { | ||
65 | { Opt_max, "max=%d" }, | ||
66 | { Opt_err, NULL } | ||
67 | }; | ||
68 | |||
69 | /** | ||
50 | * binderfs_info - information about a binderfs mount | 70 | * binderfs_info - information about a binderfs mount |
51 | * @ipc_ns: The ipc namespace the binderfs mount belongs to. | 71 | * @ipc_ns: The ipc namespace the binderfs mount belongs to. |
52 | * @control_dentry: This records the dentry of this binderfs mount | 72 | * @control_dentry: This records the dentry of this binderfs mount |
@@ -55,13 +75,16 @@ static DEFINE_IDA(binderfs_minors); | |||
55 | * created. | 75 | * created. |
56 | * @root_gid: gid that needs to be used when a new binder device is | 76 | * @root_gid: gid that needs to be used when a new binder device is |
57 | * created. | 77 | * created. |
78 | * @mount_opts: The mount options in use. | ||
79 | * @device_count: The current number of allocated binder devices. | ||
58 | */ | 80 | */ |
59 | struct binderfs_info { | 81 | struct binderfs_info { |
60 | struct ipc_namespace *ipc_ns; | 82 | struct ipc_namespace *ipc_ns; |
61 | struct dentry *control_dentry; | 83 | struct dentry *control_dentry; |
62 | kuid_t root_uid; | 84 | kuid_t root_uid; |
63 | kgid_t root_gid; | 85 | kgid_t root_gid; |
64 | 86 | struct binderfs_mount_opts mount_opts; | |
87 | int device_count; | ||
65 | }; | 88 | }; |
66 | 89 | ||
67 | static inline struct binderfs_info *BINDERFS_I(const struct inode *inode) | 90 | static inline struct binderfs_info *BINDERFS_I(const struct inode *inode) |
@@ -84,7 +107,7 @@ bool is_binderfs_device(const struct inode *inode) | |||
84 | * @userp: buffer to copy information about new device for userspace to | 107 | * @userp: buffer to copy information about new device for userspace to |
85 | * @req: struct binderfs_device as copied from userspace | 108 | * @req: struct binderfs_device as copied from userspace |
86 | * | 109 | * |
87 | * This function allocated a new binder_device and reserves a new minor | 110 | * This function allocates a new binder_device and reserves a new minor |
88 | * number for it. | 111 | * number for it. |
89 | * Minor numbers are limited and tracked globally in binderfs_minors. The | 112 | * Minor numbers are limited and tracked globally in binderfs_minors. The |
90 | * function will stash a struct binder_device for the specific binder | 113 | * function will stash a struct binder_device for the specific binder |
@@ -100,20 +123,34 @@ static int binderfs_binder_device_create(struct inode *ref_inode, | |||
100 | struct binderfs_device *req) | 123 | struct binderfs_device *req) |
101 | { | 124 | { |
102 | int minor, ret; | 125 | int minor, ret; |
103 | struct dentry *dentry, *dup, *root; | 126 | struct dentry *dentry, *root; |
104 | struct binder_device *device; | 127 | struct binder_device *device; |
105 | size_t name_len = BINDERFS_MAX_NAME + 1; | ||
106 | char *name = NULL; | 128 | char *name = NULL; |
129 | size_t name_len; | ||
107 | struct inode *inode = NULL; | 130 | struct inode *inode = NULL; |
108 | struct super_block *sb = ref_inode->i_sb; | 131 | struct super_block *sb = ref_inode->i_sb; |
109 | struct binderfs_info *info = sb->s_fs_info; | 132 | struct binderfs_info *info = sb->s_fs_info; |
133 | #if defined(CONFIG_IPC_NS) | ||
134 | bool use_reserve = (info->ipc_ns == &init_ipc_ns); | ||
135 | #else | ||
136 | bool use_reserve = true; | ||
137 | #endif | ||
110 | 138 | ||
111 | /* Reserve new minor number for the new device. */ | 139 | /* Reserve new minor number for the new device. */ |
112 | mutex_lock(&binderfs_minors_mutex); | 140 | mutex_lock(&binderfs_minors_mutex); |
113 | minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL); | 141 | if (++info->device_count <= info->mount_opts.max) |
114 | mutex_unlock(&binderfs_minors_mutex); | 142 | minor = ida_alloc_max(&binderfs_minors, |
115 | if (minor < 0) | 143 | use_reserve ? BINDERFS_MAX_MINOR : |
144 | BINDERFS_MAX_MINOR_CAPPED, | ||
145 | GFP_KERNEL); | ||
146 | else | ||
147 | minor = -ENOSPC; | ||
148 | if (minor < 0) { | ||
149 | --info->device_count; | ||
150 | mutex_unlock(&binderfs_minors_mutex); | ||
116 | return minor; | 151 | return minor; |
152 | } | ||
153 | mutex_unlock(&binderfs_minors_mutex); | ||
117 | 154 | ||
118 | ret = -ENOMEM; | 155 | ret = -ENOMEM; |
119 | device = kzalloc(sizeof(*device), GFP_KERNEL); | 156 | device = kzalloc(sizeof(*device), GFP_KERNEL); |
@@ -132,12 +169,13 @@ static int binderfs_binder_device_create(struct inode *ref_inode, | |||
132 | inode->i_uid = info->root_uid; | 169 | inode->i_uid = info->root_uid; |
133 | inode->i_gid = info->root_gid; | 170 | inode->i_gid = info->root_gid; |
134 | 171 | ||
135 | name = kmalloc(name_len, GFP_KERNEL); | 172 | req->name[BINDERFS_MAX_NAME] = '\0'; /* NUL-terminate */ |
173 | name_len = strlen(req->name); | ||
174 | /* Make sure to include terminating NUL byte */ | ||
175 | name = kmemdup(req->name, name_len + 1, GFP_KERNEL); | ||
136 | if (!name) | 176 | if (!name) |
137 | goto err; | 177 | goto err; |
138 | 178 | ||
139 | strscpy(name, req->name, name_len); | ||
140 | |||
141 | device->binderfs_inode = inode; | 179 | device->binderfs_inode = inode; |
142 | device->context.binder_context_mgr_uid = INVALID_UID; | 180 | device->context.binder_context_mgr_uid = INVALID_UID; |
143 | device->context.name = name; | 181 | device->context.name = name; |
@@ -156,28 +194,25 @@ static int binderfs_binder_device_create(struct inode *ref_inode, | |||
156 | 194 | ||
157 | root = sb->s_root; | 195 | root = sb->s_root; |
158 | inode_lock(d_inode(root)); | 196 | inode_lock(d_inode(root)); |
159 | dentry = d_alloc_name(root, name); | 197 | |
160 | if (!dentry) { | 198 | /* look it up */ |
199 | dentry = lookup_one_len(name, root, name_len); | ||
200 | if (IS_ERR(dentry)) { | ||
161 | inode_unlock(d_inode(root)); | 201 | inode_unlock(d_inode(root)); |
162 | ret = -ENOMEM; | 202 | ret = PTR_ERR(dentry); |
163 | goto err; | 203 | goto err; |
164 | } | 204 | } |
165 | 205 | ||
166 | /* Verify that the name userspace gave us is not already in use. */ | 206 | if (d_really_is_positive(dentry)) { |
167 | dup = d_lookup(root, &dentry->d_name); | 207 | /* already exists */ |
168 | if (dup) { | 208 | dput(dentry); |
169 | if (d_really_is_positive(dup)) { | 209 | inode_unlock(d_inode(root)); |
170 | dput(dup); | 210 | ret = -EEXIST; |
171 | dput(dentry); | 211 | goto err; |
172 | inode_unlock(d_inode(root)); | ||
173 | ret = -EEXIST; | ||
174 | goto err; | ||
175 | } | ||
176 | dput(dup); | ||
177 | } | 212 | } |
178 | 213 | ||
179 | inode->i_private = device; | 214 | inode->i_private = device; |
180 | d_add(dentry, inode); | 215 | d_instantiate(dentry, inode); |
181 | fsnotify_create(root->d_inode, dentry); | 216 | fsnotify_create(root->d_inode, dentry); |
182 | inode_unlock(d_inode(root)); | 217 | inode_unlock(d_inode(root)); |
183 | 218 | ||
@@ -187,6 +222,7 @@ err: | |||
187 | kfree(name); | 222 | kfree(name); |
188 | kfree(device); | 223 | kfree(device); |
189 | mutex_lock(&binderfs_minors_mutex); | 224 | mutex_lock(&binderfs_minors_mutex); |
225 | --info->device_count; | ||
190 | ida_free(&binderfs_minors, minor); | 226 | ida_free(&binderfs_minors, minor); |
191 | mutex_unlock(&binderfs_minors_mutex); | 227 | mutex_unlock(&binderfs_minors_mutex); |
192 | iput(inode); | 228 | iput(inode); |
@@ -232,6 +268,7 @@ static long binder_ctl_ioctl(struct file *file, unsigned int cmd, | |||
232 | static void binderfs_evict_inode(struct inode *inode) | 268 | static void binderfs_evict_inode(struct inode *inode) |
233 | { | 269 | { |
234 | struct binder_device *device = inode->i_private; | 270 | struct binder_device *device = inode->i_private; |
271 | struct binderfs_info *info = BINDERFS_I(inode); | ||
235 | 272 | ||
236 | clear_inode(inode); | 273 | clear_inode(inode); |
237 | 274 | ||
@@ -239,6 +276,7 @@ static void binderfs_evict_inode(struct inode *inode) | |||
239 | return; | 276 | return; |
240 | 277 | ||
241 | mutex_lock(&binderfs_minors_mutex); | 278 | mutex_lock(&binderfs_minors_mutex); |
279 | --info->device_count; | ||
242 | ida_free(&binderfs_minors, device->miscdev.minor); | 280 | ida_free(&binderfs_minors, device->miscdev.minor); |
243 | mutex_unlock(&binderfs_minors_mutex); | 281 | mutex_unlock(&binderfs_minors_mutex); |
244 | 282 | ||
@@ -246,43 +284,87 @@ static void binderfs_evict_inode(struct inode *inode) | |||
246 | kfree(device); | 284 | kfree(device); |
247 | } | 285 | } |
248 | 286 | ||
287 | /** | ||
288 | * binderfs_parse_mount_opts - parse binderfs mount options | ||
289 | * @data: options to set (can be NULL in which case defaults are used) | ||
290 | */ | ||
291 | static int binderfs_parse_mount_opts(char *data, | ||
292 | struct binderfs_mount_opts *opts) | ||
293 | { | ||
294 | char *p; | ||
295 | opts->max = BINDERFS_MAX_MINOR; | ||
296 | |||
297 | while ((p = strsep(&data, ",")) != NULL) { | ||
298 | substring_t args[MAX_OPT_ARGS]; | ||
299 | int token; | ||
300 | int max_devices; | ||
301 | |||
302 | if (!*p) | ||
303 | continue; | ||
304 | |||
305 | token = match_token(p, tokens, args); | ||
306 | switch (token) { | ||
307 | case Opt_max: | ||
308 | if (match_int(&args[0], &max_devices) || | ||
309 | (max_devices < 0 || | ||
310 | (max_devices > BINDERFS_MAX_MINOR))) | ||
311 | return -EINVAL; | ||
312 | |||
313 | opts->max = max_devices; | ||
314 | break; | ||
315 | default: | ||
316 | pr_err("Invalid mount options\n"); | ||
317 | return -EINVAL; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int binderfs_remount(struct super_block *sb, int *flags, char *data) | ||
325 | { | ||
326 | struct binderfs_info *info = sb->s_fs_info; | ||
327 | return binderfs_parse_mount_opts(data, &info->mount_opts); | ||
328 | } | ||
329 | |||
330 | static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root) | ||
331 | { | ||
332 | struct binderfs_info *info; | ||
333 | |||
334 | info = root->d_sb->s_fs_info; | ||
335 | if (info->mount_opts.max <= BINDERFS_MAX_MINOR) | ||
336 | seq_printf(seq, ",max=%d", info->mount_opts.max); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
249 | static const struct super_operations binderfs_super_ops = { | 341 | static const struct super_operations binderfs_super_ops = { |
250 | .statfs = simple_statfs, | 342 | .evict_inode = binderfs_evict_inode, |
251 | .evict_inode = binderfs_evict_inode, | 343 | .remount_fs = binderfs_remount, |
344 | .show_options = binderfs_show_mount_opts, | ||
345 | .statfs = simple_statfs, | ||
252 | }; | 346 | }; |
253 | 347 | ||
348 | static inline bool is_binderfs_control_device(const struct dentry *dentry) | ||
349 | { | ||
350 | struct binderfs_info *info = dentry->d_sb->s_fs_info; | ||
351 | return info->control_dentry == dentry; | ||
352 | } | ||
353 | |||
254 | static int binderfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 354 | static int binderfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
255 | struct inode *new_dir, struct dentry *new_dentry, | 355 | struct inode *new_dir, struct dentry *new_dentry, |
256 | unsigned int flags) | 356 | unsigned int flags) |
257 | { | 357 | { |
258 | struct inode *inode = d_inode(old_dentry); | 358 | if (is_binderfs_control_device(old_dentry) || |
259 | 359 | is_binderfs_control_device(new_dentry)) | |
260 | /* binderfs doesn't support directories. */ | ||
261 | if (d_is_dir(old_dentry)) | ||
262 | return -EPERM; | 360 | return -EPERM; |
263 | 361 | ||
264 | if (flags & ~RENAME_NOREPLACE) | 362 | return simple_rename(old_dir, old_dentry, new_dir, new_dentry, flags); |
265 | return -EINVAL; | ||
266 | |||
267 | if (!simple_empty(new_dentry)) | ||
268 | return -ENOTEMPTY; | ||
269 | |||
270 | if (d_really_is_positive(new_dentry)) | ||
271 | simple_unlink(new_dir, new_dentry); | ||
272 | |||
273 | old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime = | ||
274 | new_dir->i_mtime = inode->i_ctime = current_time(old_dir); | ||
275 | |||
276 | return 0; | ||
277 | } | 363 | } |
278 | 364 | ||
279 | static int binderfs_unlink(struct inode *dir, struct dentry *dentry) | 365 | static int binderfs_unlink(struct inode *dir, struct dentry *dentry) |
280 | { | 366 | { |
281 | /* | 367 | if (is_binderfs_control_device(dentry)) |
282 | * The control dentry is only ever touched during mount so checking it | ||
283 | * here should not require us to take lock. | ||
284 | */ | ||
285 | if (BINDERFS_I(dir)->control_dentry == dentry) | ||
286 | return -EPERM; | 368 | return -EPERM; |
287 | 369 | ||
288 | return simple_unlink(dir, dentry); | 370 | return simple_unlink(dir, dentry); |
@@ -318,8 +400,6 @@ static int binderfs_binder_ctl_create(struct super_block *sb) | |||
318 | if (!device) | 400 | if (!device) |
319 | return -ENOMEM; | 401 | return -ENOMEM; |
320 | 402 | ||
321 | inode_lock(d_inode(root)); | ||
322 | |||
323 | /* If we have already created a binder-control node, return. */ | 403 | /* If we have already created a binder-control node, return. */ |
324 | if (info->control_dentry) { | 404 | if (info->control_dentry) { |
325 | ret = 0; | 405 | ret = 0; |
@@ -358,12 +438,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb) | |||
358 | inode->i_private = device; | 438 | inode->i_private = device; |
359 | info->control_dentry = dentry; | 439 | info->control_dentry = dentry; |
360 | d_add(dentry, inode); | 440 | d_add(dentry, inode); |
361 | inode_unlock(d_inode(root)); | ||
362 | 441 | ||
363 | return 0; | 442 | return 0; |
364 | 443 | ||
365 | out: | 444 | out: |
366 | inode_unlock(d_inode(root)); | ||
367 | kfree(device); | 445 | kfree(device); |
368 | iput(inode); | 446 | iput(inode); |
369 | 447 | ||
@@ -378,12 +456,9 @@ static const struct inode_operations binderfs_dir_inode_operations = { | |||
378 | 456 | ||
379 | static int binderfs_fill_super(struct super_block *sb, void *data, int silent) | 457 | static int binderfs_fill_super(struct super_block *sb, void *data, int silent) |
380 | { | 458 | { |
459 | int ret; | ||
381 | struct binderfs_info *info; | 460 | struct binderfs_info *info; |
382 | int ret = -ENOMEM; | ||
383 | struct inode *inode = NULL; | 461 | struct inode *inode = NULL; |
384 | struct ipc_namespace *ipc_ns = sb->s_fs_info; | ||
385 | |||
386 | get_ipc_ns(ipc_ns); | ||
387 | 462 | ||
388 | sb->s_blocksize = PAGE_SIZE; | 463 | sb->s_blocksize = PAGE_SIZE; |
389 | sb->s_blocksize_bits = PAGE_SHIFT; | 464 | sb->s_blocksize_bits = PAGE_SHIFT; |
@@ -405,11 +480,17 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent) | |||
405 | sb->s_op = &binderfs_super_ops; | 480 | sb->s_op = &binderfs_super_ops; |
406 | sb->s_time_gran = 1; | 481 | sb->s_time_gran = 1; |
407 | 482 | ||
408 | info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL); | 483 | sb->s_fs_info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL); |
409 | if (!info) | 484 | if (!sb->s_fs_info) |
410 | goto err_without_dentry; | 485 | return -ENOMEM; |
486 | info = sb->s_fs_info; | ||
487 | |||
488 | info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns); | ||
489 | |||
490 | ret = binderfs_parse_mount_opts(data, &info->mount_opts); | ||
491 | if (ret) | ||
492 | return ret; | ||
411 | 493 | ||
412 | info->ipc_ns = ipc_ns; | ||
413 | info->root_gid = make_kgid(sb->s_user_ns, 0); | 494 | info->root_gid = make_kgid(sb->s_user_ns, 0); |
414 | if (!gid_valid(info->root_gid)) | 495 | if (!gid_valid(info->root_gid)) |
415 | info->root_gid = GLOBAL_ROOT_GID; | 496 | info->root_gid = GLOBAL_ROOT_GID; |
@@ -417,11 +498,9 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent) | |||
417 | if (!uid_valid(info->root_uid)) | 498 | if (!uid_valid(info->root_uid)) |
418 | info->root_uid = GLOBAL_ROOT_UID; | 499 | info->root_uid = GLOBAL_ROOT_UID; |
419 | 500 | ||
420 | sb->s_fs_info = info; | ||
421 | |||
422 | inode = new_inode(sb); | 501 | inode = new_inode(sb); |
423 | if (!inode) | 502 | if (!inode) |
424 | goto err_without_dentry; | 503 | return -ENOMEM; |
425 | 504 | ||
426 | inode->i_ino = FIRST_INODE; | 505 | inode->i_ino = FIRST_INODE; |
427 | inode->i_fop = &simple_dir_operations; | 506 | inode->i_fop = &simple_dir_operations; |
@@ -432,79 +511,28 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent) | |||
432 | 511 | ||
433 | sb->s_root = d_make_root(inode); | 512 | sb->s_root = d_make_root(inode); |
434 | if (!sb->s_root) | 513 | if (!sb->s_root) |
435 | goto err_without_dentry; | 514 | return -ENOMEM; |
436 | |||
437 | ret = binderfs_binder_ctl_create(sb); | ||
438 | if (ret) | ||
439 | goto err_with_dentry; | ||
440 | |||
441 | return 0; | ||
442 | |||
443 | err_with_dentry: | ||
444 | dput(sb->s_root); | ||
445 | sb->s_root = NULL; | ||
446 | |||
447 | err_without_dentry: | ||
448 | put_ipc_ns(ipc_ns); | ||
449 | iput(inode); | ||
450 | kfree(info); | ||
451 | |||
452 | return ret; | ||
453 | } | ||
454 | |||
455 | static int binderfs_test_super(struct super_block *sb, void *data) | ||
456 | { | ||
457 | struct binderfs_info *info = sb->s_fs_info; | ||
458 | |||
459 | if (info) | ||
460 | return info->ipc_ns == data; | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | 515 | ||
465 | static int binderfs_set_super(struct super_block *sb, void *data) | 516 | return binderfs_binder_ctl_create(sb); |
466 | { | ||
467 | sb->s_fs_info = data; | ||
468 | return set_anon_super(sb, NULL); | ||
469 | } | 517 | } |
470 | 518 | ||
471 | static struct dentry *binderfs_mount(struct file_system_type *fs_type, | 519 | static struct dentry *binderfs_mount(struct file_system_type *fs_type, |
472 | int flags, const char *dev_name, | 520 | int flags, const char *dev_name, |
473 | void *data) | 521 | void *data) |
474 | { | 522 | { |
475 | struct super_block *sb; | 523 | return mount_nodev(fs_type, flags, data, binderfs_fill_super); |
476 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; | ||
477 | |||
478 | if (!ns_capable(ipc_ns->user_ns, CAP_SYS_ADMIN)) | ||
479 | return ERR_PTR(-EPERM); | ||
480 | |||
481 | sb = sget_userns(fs_type, binderfs_test_super, binderfs_set_super, | ||
482 | flags, ipc_ns->user_ns, ipc_ns); | ||
483 | if (IS_ERR(sb)) | ||
484 | return ERR_CAST(sb); | ||
485 | |||
486 | if (!sb->s_root) { | ||
487 | int ret = binderfs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0); | ||
488 | if (ret) { | ||
489 | deactivate_locked_super(sb); | ||
490 | return ERR_PTR(ret); | ||
491 | } | ||
492 | |||
493 | sb->s_flags |= SB_ACTIVE; | ||
494 | } | ||
495 | |||
496 | return dget(sb->s_root); | ||
497 | } | 524 | } |
498 | 525 | ||
499 | static void binderfs_kill_super(struct super_block *sb) | 526 | static void binderfs_kill_super(struct super_block *sb) |
500 | { | 527 | { |
501 | struct binderfs_info *info = sb->s_fs_info; | 528 | struct binderfs_info *info = sb->s_fs_info; |
502 | 529 | ||
530 | kill_litter_super(sb); | ||
531 | |||
503 | if (info && info->ipc_ns) | 532 | if (info && info->ipc_ns) |
504 | put_ipc_ns(info->ipc_ns); | 533 | put_ipc_ns(info->ipc_ns); |
505 | 534 | ||
506 | kfree(info); | 535 | kfree(info); |
507 | kill_litter_super(sb); | ||
508 | } | 536 | } |
509 | 537 | ||
510 | static struct file_system_type binder_fs_type = { | 538 | static struct file_system_type binder_fs_type = { |
@@ -530,14 +558,6 @@ static int __init init_binderfs(void) | |||
530 | return ret; | 558 | return ret; |
531 | } | 559 | } |
532 | 560 | ||
533 | binderfs_mnt = kern_mount(&binder_fs_type); | ||
534 | if (IS_ERR(binderfs_mnt)) { | ||
535 | ret = PTR_ERR(binderfs_mnt); | ||
536 | binderfs_mnt = NULL; | ||
537 | unregister_filesystem(&binder_fs_type); | ||
538 | unregister_chrdev_region(binderfs_dev, BINDERFS_MAX_MINOR); | ||
539 | } | ||
540 | |||
541 | return ret; | 561 | return ret; |
542 | } | 562 | } |
543 | 563 | ||