hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/android/binderfs.c
....@@ -1,4 +1,4 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
1
+// SPDX-License-Identifier: GPL-2.0
22
33 #include <linux/compiler_types.h>
44 #include <linux/errno.h>
....@@ -18,7 +18,7 @@
1818 #include <linux/module.h>
1919 #include <linux/mutex.h>
2020 #include <linux/mount.h>
21
-#include <linux/parser.h>
21
+#include <linux/fs_parser.h>
2222 #include <linux/radix-tree.h>
2323 #include <linux/sched.h>
2424 #include <linux/seq_file.h>
....@@ -48,26 +48,30 @@
4848 static DEFINE_MUTEX(binderfs_minors_mutex);
4949 static DEFINE_IDA(binderfs_minors);
5050
51
-enum {
51
+enum binderfs_param {
5252 Opt_max,
5353 Opt_stats_mode,
54
- Opt_err
5554 };
5655
5756 enum binderfs_stats_mode {
58
- STATS_NONE,
59
- STATS_GLOBAL,
57
+ binderfs_stats_mode_unset,
58
+ binderfs_stats_mode_global,
6059 };
6160
62
-static const match_table_t tokens = {
63
- { Opt_max, "max=%d" },
64
- { Opt_stats_mode, "stats=%s" },
65
- { Opt_err, NULL }
61
+static const struct constant_table binderfs_param_stats[] = {
62
+ { "global", binderfs_stats_mode_global },
63
+ {}
6664 };
6765
68
-static inline struct binderfs_info *BINDERFS_I(const struct inode *inode)
66
+static const struct fs_parameter_spec binderfs_fs_parameters[] = {
67
+ fsparam_u32("max", Opt_max),
68
+ fsparam_enum("stats", Opt_stats_mode, binderfs_param_stats),
69
+ {}
70
+};
71
+
72
+static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
6973 {
70
- return inode->i_sb->s_fs_info;
74
+ return sb->s_fs_info;
7175 }
7276
7377 bool is_binderfs_device(const struct inode *inode)
....@@ -246,7 +250,7 @@
246250 static void binderfs_evict_inode(struct inode *inode)
247251 {
248252 struct binder_device *device = inode->i_private;
249
- struct binderfs_info *info = BINDERFS_I(inode);
253
+ struct binderfs_info *info = BINDERFS_SB(inode->i_sb);
250254
251255 clear_inode(inode);
252256
....@@ -264,102 +268,90 @@
264268 }
265269 }
266270
267
-/**
268
- * binderfs_parse_mount_opts - parse binderfs mount options
269
- * @data: options to set (can be NULL in which case defaults are used)
270
- */
271
-static int binderfs_parse_mount_opts(char *data,
272
- struct binderfs_mount_opts *opts)
271
+static int binderfs_fs_context_parse_param(struct fs_context *fc,
272
+ struct fs_parameter *param)
273273 {
274
- char *p, *stats;
275
- opts->max = BINDERFS_MAX_MINOR;
276
- opts->stats_mode = STATS_NONE;
274
+ int opt;
275
+ struct binderfs_mount_opts *ctx = fc->fs_private;
276
+ struct fs_parse_result result;
277277
278
- while ((p = strsep(&data, ",")) != NULL) {
279
- substring_t args[MAX_OPT_ARGS];
280
- int token;
281
- int max_devices;
278
+ opt = fs_parse(fc, binderfs_fs_parameters, param, &result);
279
+ if (opt < 0)
280
+ return opt;
282281
283
- if (!*p)
284
- continue;
282
+ switch (opt) {
283
+ case Opt_max:
284
+ if (result.uint_32 > BINDERFS_MAX_MINOR)
285
+ return invalfc(fc, "Bad value for '%s'", param->key);
285286
286
- token = match_token(p, tokens, args);
287
- switch (token) {
288
- case Opt_max:
289
- if (match_int(&args[0], &max_devices) ||
290
- (max_devices < 0 ||
291
- (max_devices > BINDERFS_MAX_MINOR)))
292
- return -EINVAL;
287
+ ctx->max = result.uint_32;
288
+ break;
289
+ case Opt_stats_mode:
290
+ if (!capable(CAP_SYS_ADMIN))
291
+ return -EPERM;
293292
294
- opts->max = max_devices;
295
- break;
296
- case Opt_stats_mode:
297
- if (!capable(CAP_SYS_ADMIN))
298
- return -EINVAL;
299
-
300
- stats = match_strdup(&args[0]);
301
- if (!stats)
302
- return -ENOMEM;
303
-
304
- if (strcmp(stats, "global") != 0) {
305
- kfree(stats);
306
- return -EINVAL;
307
- }
308
-
309
- opts->stats_mode = STATS_GLOBAL;
310
- kfree(stats);
311
- break;
312
- default:
313
- pr_err("Invalid mount options\n");
314
- return -EINVAL;
315
- }
293
+ ctx->stats_mode = result.uint_32;
294
+ break;
295
+ default:
296
+ return invalfc(fc, "Unsupported parameter '%s'", param->key);
316297 }
317298
318299 return 0;
319300 }
320301
321
-static int binderfs_remount(struct super_block *sb, int *flags, char *data)
302
+static int binderfs_fs_context_reconfigure(struct fs_context *fc)
322303 {
323
- int prev_stats_mode, ret;
324
- struct binderfs_info *info = sb->s_fs_info;
304
+ struct binderfs_mount_opts *ctx = fc->fs_private;
305
+ struct binderfs_info *info = BINDERFS_SB(fc->root->d_sb);
325306
326
- prev_stats_mode = info->mount_opts.stats_mode;
327
- ret = binderfs_parse_mount_opts(data, &info->mount_opts);
328
- if (ret)
329
- return ret;
307
+ if (info->mount_opts.stats_mode != ctx->stats_mode)
308
+ return invalfc(fc, "Binderfs stats mode cannot be changed during a remount");
330309
331
- if (prev_stats_mode != info->mount_opts.stats_mode) {
332
- pr_err("Binderfs stats mode cannot be changed during a remount\n");
333
- info->mount_opts.stats_mode = prev_stats_mode;
334
- return -EINVAL;
335
- }
336
-
310
+ info->mount_opts.stats_mode = ctx->stats_mode;
311
+ info->mount_opts.max = ctx->max;
337312 return 0;
338313 }
339314
340
-static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root)
315
+static int binderfs_show_options(struct seq_file *seq, struct dentry *root)
341316 {
342
- struct binderfs_info *info;
317
+ struct binderfs_info *info = BINDERFS_SB(root->d_sb);
343318
344
- info = root->d_sb->s_fs_info;
345319 if (info->mount_opts.max <= BINDERFS_MAX_MINOR)
346320 seq_printf(seq, ",max=%d", info->mount_opts.max);
347
- if (info->mount_opts.stats_mode == STATS_GLOBAL)
321
+
322
+ switch (info->mount_opts.stats_mode) {
323
+ case binderfs_stats_mode_unset:
324
+ break;
325
+ case binderfs_stats_mode_global:
348326 seq_printf(seq, ",stats=global");
327
+ break;
328
+ }
349329
350330 return 0;
331
+}
332
+
333
+static void binderfs_put_super(struct super_block *sb)
334
+{
335
+ struct binderfs_info *info = sb->s_fs_info;
336
+
337
+ if (info && info->ipc_ns)
338
+ put_ipc_ns(info->ipc_ns);
339
+
340
+ kfree(info);
341
+ sb->s_fs_info = NULL;
351342 }
352343
353344 static const struct super_operations binderfs_super_ops = {
354345 .evict_inode = binderfs_evict_inode,
355
- .remount_fs = binderfs_remount,
356
- .show_options = binderfs_show_mount_opts,
346
+ .show_options = binderfs_show_options,
357347 .statfs = simple_statfs,
348
+ .put_super = binderfs_put_super,
358349 };
359350
360351 static inline bool is_binderfs_control_device(const struct dentry *dentry)
361352 {
362353 struct binderfs_info *info = dentry->d_sb->s_fs_info;
354
+
363355 return info->control_dentry == dentry;
364356 }
365357
....@@ -592,6 +584,7 @@
592584 static int init_binder_logs(struct super_block *sb)
593585 {
594586 struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
587
+ const struct binder_debugfs_entry *db_entry;
595588 struct binderfs_info *info;
596589 int ret = 0;
597590
....@@ -602,43 +595,15 @@
602595 goto out;
603596 }
604597
605
- dentry = binderfs_create_file(binder_logs_root_dir, "stats",
606
- &binder_stats_fops, NULL);
607
- if (IS_ERR(dentry)) {
608
- ret = PTR_ERR(dentry);
609
- goto out;
610
- }
611
-
612
- dentry = binderfs_create_file(binder_logs_root_dir, "state",
613
- &binder_state_fops, NULL);
614
- if (IS_ERR(dentry)) {
615
- ret = PTR_ERR(dentry);
616
- goto out;
617
- }
618
-
619
- dentry = binderfs_create_file(binder_logs_root_dir, "transactions",
620
- &binder_transactions_fops, NULL);
621
- if (IS_ERR(dentry)) {
622
- ret = PTR_ERR(dentry);
623
- goto out;
624
- }
625
-
626
- dentry = binderfs_create_file(binder_logs_root_dir,
627
- "transaction_log",
628
- &binder_transaction_log_fops,
629
- &binder_transaction_log);
630
- if (IS_ERR(dentry)) {
631
- ret = PTR_ERR(dentry);
632
- goto out;
633
- }
634
-
635
- dentry = binderfs_create_file(binder_logs_root_dir,
636
- "failed_transaction_log",
637
- &binder_transaction_log_fops,
638
- &binder_transaction_log_failed);
639
- if (IS_ERR(dentry)) {
640
- ret = PTR_ERR(dentry);
641
- goto out;
598
+ binder_for_each_debugfs_entry(db_entry) {
599
+ dentry = binderfs_create_file(binder_logs_root_dir,
600
+ db_entry->name,
601
+ db_entry->fops,
602
+ db_entry->data);
603
+ if (IS_ERR(dentry)) {
604
+ ret = PTR_ERR(dentry);
605
+ goto out;
606
+ }
642607 }
643608
644609 proc_log_dir = binderfs_create_dir(binder_logs_root_dir, "proc");
....@@ -653,12 +618,13 @@
653618 return ret;
654619 }
655620
656
-static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
621
+static int binderfs_fill_super(struct super_block *sb, struct fs_context *fc)
657622 {
658623 int ret;
659624 struct binderfs_info *info;
625
+ struct binderfs_mount_opts *ctx = fc->fs_private;
660626 struct inode *inode = NULL;
661
- struct binderfs_device device_info = { 0 };
627
+ struct binderfs_device device_info = {};
662628 const char *name;
663629 size_t len;
664630
....@@ -689,16 +655,14 @@
689655
690656 info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
691657
692
- ret = binderfs_parse_mount_opts(data, &info->mount_opts);
693
- if (ret)
694
- return ret;
695
-
696658 info->root_gid = make_kgid(sb->s_user_ns, 0);
697659 if (!gid_valid(info->root_gid))
698660 info->root_gid = GLOBAL_ROOT_GID;
699661 info->root_uid = make_kuid(sb->s_user_ns, 0);
700662 if (!uid_valid(info->root_uid))
701663 info->root_uid = GLOBAL_ROOT_UID;
664
+ info->mount_opts.max = ctx->max;
665
+ info->mount_opts.stats_mode = ctx->stats_mode;
702666
703667 inode = new_inode(sb);
704668 if (!inode)
....@@ -730,36 +694,54 @@
730694 name++;
731695 }
732696
733
- if (info->mount_opts.stats_mode == STATS_GLOBAL)
697
+ if (info->mount_opts.stats_mode == binderfs_stats_mode_global)
734698 return init_binder_logs(sb);
735699
736700 return 0;
737701 }
738702
739
-static struct dentry *binderfs_mount(struct file_system_type *fs_type,
740
- int flags, const char *dev_name,
741
- void *data)
703
+static int binderfs_fs_context_get_tree(struct fs_context *fc)
742704 {
743
- return mount_nodev(fs_type, flags, data, binderfs_fill_super);
705
+ return get_tree_nodev(fc, binderfs_fill_super);
744706 }
745707
746
-static void binderfs_kill_super(struct super_block *sb)
708
+static void binderfs_fs_context_free(struct fs_context *fc)
747709 {
748
- struct binderfs_info *info = sb->s_fs_info;
710
+ struct binderfs_mount_opts *ctx = fc->fs_private;
749711
750
- kill_litter_super(sb);
712
+ kfree(ctx);
713
+}
751714
752
- if (info && info->ipc_ns)
753
- put_ipc_ns(info->ipc_ns);
715
+static const struct fs_context_operations binderfs_fs_context_ops = {
716
+ .free = binderfs_fs_context_free,
717
+ .get_tree = binderfs_fs_context_get_tree,
718
+ .parse_param = binderfs_fs_context_parse_param,
719
+ .reconfigure = binderfs_fs_context_reconfigure,
720
+};
754721
755
- kfree(info);
722
+static int binderfs_init_fs_context(struct fs_context *fc)
723
+{
724
+ struct binderfs_mount_opts *ctx;
725
+
726
+ ctx = kzalloc(sizeof(struct binderfs_mount_opts), GFP_KERNEL);
727
+ if (!ctx)
728
+ return -ENOMEM;
729
+
730
+ ctx->max = BINDERFS_MAX_MINOR;
731
+ ctx->stats_mode = binderfs_stats_mode_unset;
732
+
733
+ fc->fs_private = ctx;
734
+ fc->ops = &binderfs_fs_context_ops;
735
+
736
+ return 0;
756737 }
757738
758739 static struct file_system_type binder_fs_type = {
759
- .name = "binder",
760
- .mount = binderfs_mount,
761
- .kill_sb = binderfs_kill_super,
762
- .fs_flags = FS_USERNS_MOUNT,
740
+ .name = "binder",
741
+ .init_fs_context = binderfs_init_fs_context,
742
+ .parameters = binderfs_fs_parameters,
743
+ .kill_sb = kill_litter_super,
744
+ .fs_flags = FS_USERNS_MOUNT,
763745 };
764746
765747 int __init init_binderfs(void)