]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/android/binder.c
Merge tag 'hwmon-for-v5.4-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/groec...
[linux.git] / drivers / android / binder.c
index dc1c83eafc225fdf00f0f3d9606652e3a9f3fb28..5b9ac2122e894558eea8e67353f981438283a2be 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/sched/signal.h>
 #include <linux/sched/mm.h>
 #include <linux/seq_file.h>
+#include <linux/string.h>
 #include <linux/uaccess.h>
 #include <linux/pid_namespace.h>
 #include <linux/security.h>
@@ -66,6 +67,7 @@
 #include <linux/task_work.h>
 
 #include <uapi/linux/android/binder.h>
+#include <uapi/linux/android/binderfs.h>
 
 #include <asm/cacheflush.h>
 
@@ -122,7 +124,7 @@ static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
        BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
 module_param_named(debug_mask, binder_debug_mask, uint, 0644);
 
-static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
+char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
 module_param_named(devices, binder_devices_param, charp, 0444);
 
 static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
@@ -196,30 +198,8 @@ static inline void binder_stats_created(enum binder_stat_types type)
        atomic_inc(&binder_stats.obj_created[type]);
 }
 
-struct binder_transaction_log_entry {
-       int debug_id;
-       int debug_id_done;
-       int call_type;
-       int from_proc;
-       int from_thread;
-       int target_handle;
-       int to_proc;
-       int to_thread;
-       int to_node;
-       int data_size;
-       int offsets_size;
-       int return_error_line;
-       uint32_t return_error;
-       uint32_t return_error_param;
-       const char *context_name;
-};
-struct binder_transaction_log {
-       atomic_t cur;
-       bool full;
-       struct binder_transaction_log_entry entry[32];
-};
-static struct binder_transaction_log binder_transaction_log;
-static struct binder_transaction_log binder_transaction_log_failed;
+struct binder_transaction_log binder_transaction_log;
+struct binder_transaction_log binder_transaction_log_failed;
 
 static struct binder_transaction_log_entry *binder_transaction_log_add(
        struct binder_transaction_log *log)
@@ -480,6 +460,7 @@ enum binder_deferred_state {
  * @inner_lock:           can nest under outer_lock and/or node lock
  * @outer_lock:           no nesting under innor or node lock
  *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
  *
  * Bookkeeping structure for binder processes
  */
@@ -509,6 +490,7 @@ struct binder_proc {
        struct binder_context *context;
        spinlock_t inner_lock;
        spinlock_t outer_lock;
+       struct dentry *binderfs_entry;
 };
 
 enum {
@@ -2896,7 +2878,7 @@ static void binder_transaction(struct binder_proc *proc,
        e->target_handle = tr->target.handle;
        e->data_size = tr->data_size;
        e->offsets_size = tr->offsets_size;
-       e->context_name = proc->context->name;
+       strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME);
 
        if (reply) {
                binder_inner_proc_lock(proc);
@@ -5230,6 +5212,8 @@ static int binder_open(struct inode *nodp, struct file *filp)
 {
        struct binder_proc *proc;
        struct binder_device *binder_dev;
+       struct binderfs_info *info;
+       struct dentry *binder_binderfs_dir_entry_proc = NULL;
 
        binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__,
                     current->group_leader->pid, current->pid);
@@ -5244,11 +5228,14 @@ static int binder_open(struct inode *nodp, struct file *filp)
        INIT_LIST_HEAD(&proc->todo);
        proc->default_priority = task_nice(current);
        /* binderfs stashes devices in i_private */
-       if (is_binderfs_device(nodp))
+       if (is_binderfs_device(nodp)) {
                binder_dev = nodp->i_private;
-       else
+               info = nodp->i_sb->s_fs_info;
+               binder_binderfs_dir_entry_proc = info->proc_log_dir;
+       } else {
                binder_dev = container_of(filp->private_data,
                                          struct binder_device, miscdev);
+       }
        proc->context = &binder_dev->context;
        binder_alloc_init(&proc->alloc);
 
@@ -5279,6 +5266,35 @@ static int binder_open(struct inode *nodp, struct file *filp)
                        &proc_fops);
        }
 
+       if (binder_binderfs_dir_entry_proc) {
+               char strbuf[11];
+               struct dentry *binderfs_entry;
+
+               snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
+               /*
+                * Similar to debugfs, the process specific log file is shared
+                * between contexts. If the file has already been created for a
+                * process, the following binderfs_create_file() call will
+                * fail with error code EEXIST if another context of the same
+                * process invoked binder_open(). This is ok since same as
+                * debugfs, the log file will contain information on all
+                * contexts of a given PID.
+                */
+               binderfs_entry = binderfs_create_file(binder_binderfs_dir_entry_proc,
+                       strbuf, &proc_fops, (void *)(unsigned long)proc->pid);
+               if (!IS_ERR(binderfs_entry)) {
+                       proc->binderfs_entry = binderfs_entry;
+               } else {
+                       int error;
+
+                       error = PTR_ERR(binderfs_entry);
+                       if (error != -EEXIST) {
+                               pr_warn("Unable to create file %s in binderfs (error %d)\n",
+                                       strbuf, error);
+                       }
+               }
+       }
+
        return 0;
 }
 
@@ -5318,6 +5334,12 @@ static int binder_release(struct inode *nodp, struct file *filp)
        struct binder_proc *proc = filp->private_data;
 
        debugfs_remove(proc->debugfs_entry);
+
+       if (proc->binderfs_entry) {
+               binderfs_remove_file(proc->binderfs_entry);
+               proc->binderfs_entry = NULL;
+       }
+
        binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
 
        return 0;
@@ -5907,7 +5929,7 @@ static void print_binder_proc_stats(struct seq_file *m,
 }
 
 
-static int state_show(struct seq_file *m, void *unused)
+int binder_state_show(struct seq_file *m, void *unused)
 {
        struct binder_proc *proc;
        struct binder_node *node;
@@ -5946,7 +5968,7 @@ static int state_show(struct seq_file *m, void *unused)
        return 0;
 }
 
-static int stats_show(struct seq_file *m, void *unused)
+int binder_stats_show(struct seq_file *m, void *unused)
 {
        struct binder_proc *proc;
 
@@ -5962,7 +5984,7 @@ static int stats_show(struct seq_file *m, void *unused)
        return 0;
 }
 
-static int transactions_show(struct seq_file *m, void *unused)
+int binder_transactions_show(struct seq_file *m, void *unused)
 {
        struct binder_proc *proc;
 
@@ -6018,7 +6040,7 @@ static void print_binder_transaction_log_entry(struct seq_file *m,
                        "\n" : " (incomplete)\n");
 }
 
-static int transaction_log_show(struct seq_file *m, void *unused)
+int binder_transaction_log_show(struct seq_file *m, void *unused)
 {
        struct binder_transaction_log *log = m->private;
        unsigned int log_cur = atomic_read(&log->cur);
@@ -6050,11 +6072,6 @@ const struct file_operations binder_fops = {
        .release = binder_release,
 };
 
-DEFINE_SHOW_ATTRIBUTE(state);
-DEFINE_SHOW_ATTRIBUTE(stats);
-DEFINE_SHOW_ATTRIBUTE(transactions);
-DEFINE_SHOW_ATTRIBUTE(transaction_log);
-
 static int __init init_binder_device(const char *name)
 {
        int ret;
@@ -6108,30 +6125,31 @@ static int __init binder_init(void)
                                    0444,
                                    binder_debugfs_dir_entry_root,
                                    NULL,
-                                   &state_fops);
+                                   &binder_state_fops);
                debugfs_create_file("stats",
                                    0444,
                                    binder_debugfs_dir_entry_root,
                                    NULL,
-                                   &stats_fops);
+                                   &binder_stats_fops);
                debugfs_create_file("transactions",
                                    0444,
                                    binder_debugfs_dir_entry_root,
                                    NULL,
-                                   &transactions_fops);
+                                   &binder_transactions_fops);
                debugfs_create_file("transaction_log",
                                    0444,
                                    binder_debugfs_dir_entry_root,
                                    &binder_transaction_log,
-                                   &transaction_log_fops);
+                                   &binder_transaction_log_fops);
                debugfs_create_file("failed_transaction_log",
                                    0444,
                                    binder_debugfs_dir_entry_root,
                                    &binder_transaction_log_failed,
-                                   &transaction_log_fops);
+                                   &binder_transaction_log_fops);
        }
 
-       if (strcmp(binder_devices_param, "") != 0) {
+       if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) &&
+           strcmp(binder_devices_param, "") != 0) {
                /*
                * Copy the module_parameter string, because we don't want to
                * tokenize it in-place.