From 3af7d1793da5183f6e2cfa6f9006103144829b17 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 18 Aug 2017 10:18:45 +0200 Subject: [PATCH] binder: use own major number Signed-off-by: Christian Brauner --- kernel/binder/binder.c | 163 +++++++++++++++++++++++++++++++++-------- 1 file changed, 131 insertions(+), 32 deletions(-) diff --git a/kernel/binder/binder.c b/kernel/binder/binder.c index 59dd2405..425da2b1 100644 --- a/kernel/binder/binder.c +++ b/kernel/binder/binder.c @@ -18,12 +18,13 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include +#include #include #include #include #include #include -#include #include #include #include @@ -50,12 +51,20 @@ #define BINDER_IPC_32BIT 1 #endif +/* Until I upstream a better version of this patch choose an arbitrary major + * number in the high end spectrum that has not yet been given away and is + * unlikely to be given away in the near future. + */ +#define BINDER_DKMS_MAJOR 511 +#define BINDER_DKMS_MAX_MINOR 1024 + #include "binder.h" #include "binder_trace.h" static DEFINE_MUTEX(binder_main_lock); static DEFINE_MUTEX(binder_deferred_lock); static DEFINE_MUTEX(binder_mmap_lock); +static DEFINE_MUTEX(binder_devices_mtx); static HLIST_HEAD(binder_devices); static HLIST_HEAD(binder_procs); @@ -121,8 +130,8 @@ module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO); static bool binder_debug_no_lock; module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO); -static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES; -module_param_named(devices, binder_devices_param, charp, 0444); +static int binder_devices_param = 1; +module_param_named(num_devices, binder_devices_param, int, 0444); static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait); static int binder_stop_on_user_error; @@ -239,7 +248,8 @@ struct binder_context { struct binder_device { struct hlist_node hlist; - struct miscdevice miscdev; + struct cdev cdev; + struct device class_dev; struct binder_context context; }; @@ -3470,6 +3480,8 @@ err_bad_arg: static int binder_open(struct inode *nodp, struct file *filp) { + int minor = iminor(nodp); + struct hlist_node *tmp; struct binder_proc *proc; struct binder_device *binder_dev; @@ -3484,8 +3496,18 @@ static int binder_open(struct inode *nodp, struct file *filp) INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->wait); proc->default_priority = task_nice(current); - binder_dev = container_of(filp->private_data, struct binder_device, - miscdev); + + mutex_lock(&binder_devices_mtx); + hlist_for_each_entry_safe(binder_dev, tmp, &binder_devices, hlist) { + if (MINOR(binder_dev->cdev.dev) == minor) + break; + binder_dev = NULL; + } + mutex_unlock(&binder_devices_mtx); + if (!binder_dev) + BUG(); + + filp->private_data = &binder_dev->class_dev; proc->context = &binder_dev->context; binder_lock(__func__); @@ -4200,40 +4222,85 @@ BINDER_DEBUG_ENTRY(stats); BINDER_DEBUG_ENTRY(transactions); BINDER_DEBUG_ENTRY(transaction_log); -static int __init init_binder_device(const char *name) +static struct class *binder_class; + +static void binder_device_release(struct device *dev) +{ +} + +static int __init init_binder_device(int idx) { int ret; + char *name; + dev_t devnr; struct binder_device *binder_device; + /* strlen("binder") + * + + * maximum length of 64 bit int as string + */ + char numstr[6 + 21] = "binder"; binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL); if (!binder_device) return -ENOMEM; - binder_device->miscdev.fops = &binder_fops; - binder_device->miscdev.minor = MISC_DYNAMIC_MINOR; - binder_device->miscdev.name = name; + cdev_init(&binder_device->cdev, &binder_fops); + binder_device->cdev.owner = THIS_MODULE; - binder_device->context.binder_context_mgr_uid = INVALID_UID; + devnr = MKDEV(BINDER_DKMS_MAJOR, idx); + ret = cdev_add(&binder_device->cdev, devnr, 1); + if (ret) { + kfree(binder_device); + return ret; + } + + if (binder_devices_param > 1) + ret = snprintf(numstr, sizeof(numstr), "binder%d", idx); + if (ret < 0 || (size_t)ret >= sizeof(numstr)) { + cdev_del(&binder_device->cdev); + kfree(binder_device); + return -EIO; + } + + name = kzalloc(strlen(numstr) + 1, GFP_KERNEL); + if (!name) { + cdev_del(&binder_device->cdev); + kfree(binder_device); + return -ENOMEM; + } + strcpy(name, numstr); binder_device->context.name = name; + binder_device->context.binder_context_mgr_uid = INVALID_UID; - ret = misc_register(&binder_device->miscdev); - if (ret < 0) { + binder_device->class_dev.devt = binder_device->cdev.dev; + binder_device->class_dev.class = binder_class; + binder_device->class_dev.release = binder_device_release; + dev_set_name(&binder_device->class_dev, "%s", name); + ret = device_register(&binder_device->class_dev); + if (ret) { + cdev_del(&binder_device->cdev); kfree(binder_device); + kfree(name); return ret; } + mutex_lock(&binder_devices_mtx); hlist_add_head(&binder_device->hlist, &binder_devices); + mutex_unlock(&binder_devices_mtx); - return ret; + return 0; } static int __init binder_init(void) { - int ret; - char *device_name, *device_names; + int i, ret; struct binder_device *device; struct hlist_node *tmp; + if (binder_devices_param <= 0 || + binder_devices_param > BINDER_DKMS_MAX_MINOR) + return -EINVAL; + binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); if (binder_debugfs_dir_entry_root) binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", @@ -4267,19 +4334,17 @@ static int __init binder_init(void) &binder_transaction_log_fops); } - /* - * Copy the module_parameter string, because we don't want to - * tokenize it in-place. - */ - device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL); - if (!device_names) { - ret = -ENOMEM; - goto err_alloc_device_names_failed; - } - strcpy(device_names, binder_devices_param); + ret = register_chrdev_region(MKDEV(BINDER_DKMS_MAJOR, 0), + BINDER_DKMS_MAX_MINOR, "binder"); + if (ret) + goto on_error_remove_debugfs; + + binder_class = class_create(THIS_MODULE, "binder"); + if (IS_ERR(binder_class)) + goto on_error_unregister_chrdev_region; - while ((device_name = strsep(&device_names, ","))) { - ret = init_binder_device(device_name); + for (i = 0; i < binder_devices_param; i++) { + ret = init_binder_device(i); if (ret) goto err_init_binder_device_failed; } @@ -4287,18 +4352,52 @@ static int __init binder_init(void) return ret; err_init_binder_device_failed: + mutex_lock(&binder_devices_mtx); hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) { - misc_deregister(&device->miscdev); + cdev_del(&device->cdev); + device_unregister(&device->class_dev); + kfree(device->context.name); hlist_del(&device->hlist); kfree(device); } -err_alloc_device_names_failed: + mutex_unlock(&binder_devices_mtx); + class_destroy(binder_class); + +on_error_unregister_chrdev_region: + unregister_chrdev_region(MKDEV(BINDER_DKMS_MAJOR, 0), + BINDER_DKMS_MAX_MINOR); + +on_error_remove_debugfs: debugfs_remove_recursive(binder_debugfs_dir_entry_root); - return ret; + return -1; +} + +static void __exit binder_exit(void) +{ + struct binder_device *device; + struct hlist_node *tmp; + + mutex_lock(&binder_devices_mtx); + hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) { + cdev_del(&device->cdev); + device_unregister(&device->class_dev); + kfree(device->context.name); + hlist_del(&device->hlist); + kfree(device); + } + mutex_unlock(&binder_devices_mtx); + + class_destroy(binder_class); + + unregister_chrdev_region(MKDEV(BINDER_DKMS_MAJOR, 0), + BINDER_DKMS_MAX_MINOR); + + debugfs_remove_recursive(binder_debugfs_dir_entry_root); } -device_initcall(binder_init); +module_init(binder_init); +module_exit(binder_exit); #define CREATE_TRACE_POINTS #include "binder_trace.h" -- GitLab