162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* binder.c 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Android IPC Subsystem 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2007-2008 Google, Inc. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/* 1062306a36Sopenharmony_ci * Locking overview 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * There are 3 main spinlocks which must be acquired in the 1362306a36Sopenharmony_ci * order shown: 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * 1) proc->outer_lock : protects binder_ref 1662306a36Sopenharmony_ci * binder_proc_lock() and binder_proc_unlock() are 1762306a36Sopenharmony_ci * used to acq/rel. 1862306a36Sopenharmony_ci * 2) node->lock : protects most fields of binder_node. 1962306a36Sopenharmony_ci * binder_node_lock() and binder_node_unlock() are 2062306a36Sopenharmony_ci * used to acq/rel 2162306a36Sopenharmony_ci * 3) proc->inner_lock : protects the thread and node lists 2262306a36Sopenharmony_ci * (proc->threads, proc->waiting_threads, proc->nodes) 2362306a36Sopenharmony_ci * and all todo lists associated with the binder_proc 2462306a36Sopenharmony_ci * (proc->todo, thread->todo, proc->delivered_death and 2562306a36Sopenharmony_ci * node->async_todo), as well as thread->transaction_stack 2662306a36Sopenharmony_ci * binder_inner_proc_lock() and binder_inner_proc_unlock() 2762306a36Sopenharmony_ci * are used to acq/rel 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Any lock under procA must never be nested under any lock at the same 3062306a36Sopenharmony_ci * level or below on procB. 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * Functions that require a lock held on entry indicate which lock 3362306a36Sopenharmony_ci * in the suffix of the function name: 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * foo_olocked() : requires node->outer_lock 3662306a36Sopenharmony_ci * foo_nlocked() : requires node->lock 3762306a36Sopenharmony_ci * foo_ilocked() : requires proc->inner_lock 3862306a36Sopenharmony_ci * foo_oilocked(): requires proc->outer_lock and proc->inner_lock 3962306a36Sopenharmony_ci * foo_nilocked(): requires node->lock and proc->inner_lock 4062306a36Sopenharmony_ci * ... 4162306a36Sopenharmony_ci */ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#include <linux/fdtable.h> 4662306a36Sopenharmony_ci#include <linux/file.h> 4762306a36Sopenharmony_ci#include <linux/freezer.h> 4862306a36Sopenharmony_ci#include <linux/fs.h> 4962306a36Sopenharmony_ci#include <linux/list.h> 5062306a36Sopenharmony_ci#include <linux/miscdevice.h> 5162306a36Sopenharmony_ci#include <linux/module.h> 5262306a36Sopenharmony_ci#include <linux/mutex.h> 5362306a36Sopenharmony_ci#include <linux/nsproxy.h> 5462306a36Sopenharmony_ci#include <linux/poll.h> 5562306a36Sopenharmony_ci#include <linux/debugfs.h> 5662306a36Sopenharmony_ci#include <linux/rbtree.h> 5762306a36Sopenharmony_ci#include <linux/sched/signal.h> 5862306a36Sopenharmony_ci#include <linux/sched/mm.h> 5962306a36Sopenharmony_ci#include <linux/seq_file.h> 6062306a36Sopenharmony_ci#include <linux/string.h> 6162306a36Sopenharmony_ci#include <linux/uaccess.h> 6262306a36Sopenharmony_ci#include <linux/pid_namespace.h> 6362306a36Sopenharmony_ci#include <linux/security.h> 6462306a36Sopenharmony_ci#include <linux/spinlock.h> 6562306a36Sopenharmony_ci#include <linux/ratelimit.h> 6662306a36Sopenharmony_ci#include <linux/syscalls.h> 6762306a36Sopenharmony_ci#include <linux/task_work.h> 6862306a36Sopenharmony_ci#include <linux/sizes.h> 6962306a36Sopenharmony_ci#include <linux/ktime.h> 7062306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 7162306a36Sopenharmony_ci#include <linux/trace_clock.h> 7262306a36Sopenharmony_ci#include <linux/proc_fs.h> 7362306a36Sopenharmony_ci#endif 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#include <uapi/linux/android/binder.h> 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#include <linux/cacheflush.h> 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#include "binder_internal.h" 8062306a36Sopenharmony_ci#include "binder_trace.h" 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic HLIST_HEAD(binder_deferred_list); 8362306a36Sopenharmony_cistatic DEFINE_MUTEX(binder_deferred_lock); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic HLIST_HEAD(binder_devices); 8662306a36Sopenharmony_cistatic HLIST_HEAD(binder_procs); 8762306a36Sopenharmony_cistatic DEFINE_MUTEX(binder_procs_lock); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic HLIST_HEAD(binder_dead_nodes); 9062306a36Sopenharmony_cistatic DEFINE_SPINLOCK(binder_dead_nodes_lock); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic struct dentry *binder_debugfs_dir_entry_root; 9362306a36Sopenharmony_cistatic struct dentry *binder_debugfs_dir_entry_proc; 9462306a36Sopenharmony_cistatic atomic_t binder_last_id; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic int proc_show(struct seq_file *m, void *unused); 9762306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(proc); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 10062306a36Sopenharmony_cistatic int binder_transaction_proc_show(struct seq_file *m, void *unused); 10162306a36Sopenharmony_ciDEFINE_PROC_SHOW_ATTRIBUTE(binder_transaction_proc); 10262306a36Sopenharmony_ci#endif 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define FORBIDDEN_MMAP_FLAGS (VM_WRITE) 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#ifdef CONFIG_ACCESS_TOKENID 10762306a36Sopenharmony_ci#define ENABLE_ACCESS_TOKENID 1 10862306a36Sopenharmony_ci#else 10962306a36Sopenharmony_ci#define ENABLE_ACCESS_TOKENID 0 11062306a36Sopenharmony_ci#endif /* CONFIG_ACCESS_TOKENID */ 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#ifdef CONFIG_BINDER_SENDER_INFO 11362306a36Sopenharmony_ci#define ENABLE_BINDER_SENDER_INFO 1 11462306a36Sopenharmony_ci#else 11562306a36Sopenharmony_ci#define ENABLE_BINDER_SENDER_INFO 0 11662306a36Sopenharmony_ci#endif /* CONFIG_BINDER_SENDER_INFO */ 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define ACCESS_TOKENID_FEATURE_VALUE (ENABLE_ACCESS_TOKENID << 0) 11962306a36Sopenharmony_ci#define BINDER_SENDER_INFO_FEATURE_VALUE (ENABLE_BINDER_SENDER_INFO << 2) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#define BINDER_CURRENT_FEATURE_SET (ACCESS_TOKENID_FEATURE_VALUE | BINDER_SENDER_INFO_FEATURE_VALUE) 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cienum { 12462306a36Sopenharmony_ci BINDER_DEBUG_USER_ERROR = 1U << 0, 12562306a36Sopenharmony_ci BINDER_DEBUG_FAILED_TRANSACTION = 1U << 1, 12662306a36Sopenharmony_ci BINDER_DEBUG_DEAD_TRANSACTION = 1U << 2, 12762306a36Sopenharmony_ci BINDER_DEBUG_OPEN_CLOSE = 1U << 3, 12862306a36Sopenharmony_ci BINDER_DEBUG_DEAD_BINDER = 1U << 4, 12962306a36Sopenharmony_ci BINDER_DEBUG_DEATH_NOTIFICATION = 1U << 5, 13062306a36Sopenharmony_ci BINDER_DEBUG_READ_WRITE = 1U << 6, 13162306a36Sopenharmony_ci BINDER_DEBUG_USER_REFS = 1U << 7, 13262306a36Sopenharmony_ci BINDER_DEBUG_THREADS = 1U << 8, 13362306a36Sopenharmony_ci BINDER_DEBUG_TRANSACTION = 1U << 9, 13462306a36Sopenharmony_ci BINDER_DEBUG_TRANSACTION_COMPLETE = 1U << 10, 13562306a36Sopenharmony_ci BINDER_DEBUG_FREE_BUFFER = 1U << 11, 13662306a36Sopenharmony_ci BINDER_DEBUG_INTERNAL_REFS = 1U << 12, 13762306a36Sopenharmony_ci BINDER_DEBUG_PRIORITY_CAP = 1U << 13, 13862306a36Sopenharmony_ci BINDER_DEBUG_SPINLOCKS = 1U << 14, 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_cistatic uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR | 14162306a36Sopenharmony_ci BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION; 14262306a36Sopenharmony_cimodule_param_named(debug_mask, binder_debug_mask, uint, 0644); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cichar *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES; 14562306a36Sopenharmony_cimodule_param_named(devices, binder_devices_param, charp, 0444); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait); 14862306a36Sopenharmony_cistatic int binder_stop_on_user_error; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic int binder_set_stop_on_user_error(const char *val, 15162306a36Sopenharmony_ci const struct kernel_param *kp) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci int ret; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci ret = param_set_int(val, kp); 15662306a36Sopenharmony_ci if (binder_stop_on_user_error < 2) 15762306a36Sopenharmony_ci wake_up(&binder_user_error_wait); 15862306a36Sopenharmony_ci return ret; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_cimodule_param_call(stop_on_user_error, binder_set_stop_on_user_error, 16162306a36Sopenharmony_ci param_get_int, &binder_stop_on_user_error, 0644); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic __printf(2, 3) void binder_debug(int mask, const char *format, ...) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct va_format vaf; 16662306a36Sopenharmony_ci va_list args; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (binder_debug_mask & mask) { 16962306a36Sopenharmony_ci va_start(args, format); 17062306a36Sopenharmony_ci vaf.va = &args; 17162306a36Sopenharmony_ci vaf.fmt = format; 17262306a36Sopenharmony_ci pr_info_ratelimited("%pV", &vaf); 17362306a36Sopenharmony_ci va_end(args); 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci#define binder_txn_error(x...) \ 17862306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, x) 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic __printf(1, 2) void binder_user_error(const char *format, ...) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci struct va_format vaf; 18362306a36Sopenharmony_ci va_list args; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (binder_debug_mask & BINDER_DEBUG_USER_ERROR) { 18662306a36Sopenharmony_ci va_start(args, format); 18762306a36Sopenharmony_ci vaf.va = &args; 18862306a36Sopenharmony_ci vaf.fmt = format; 18962306a36Sopenharmony_ci pr_info_ratelimited("%pV", &vaf); 19062306a36Sopenharmony_ci va_end(args); 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (binder_stop_on_user_error) 19462306a36Sopenharmony_ci binder_stop_on_user_error = 2; 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci#define binder_set_extended_error(ee, _id, _command, _param) \ 19862306a36Sopenharmony_ci do { \ 19962306a36Sopenharmony_ci (ee)->id = _id; \ 20062306a36Sopenharmony_ci (ee)->command = _command; \ 20162306a36Sopenharmony_ci (ee)->param = _param; \ 20262306a36Sopenharmony_ci } while (0) 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci#define to_flat_binder_object(hdr) \ 20562306a36Sopenharmony_ci container_of(hdr, struct flat_binder_object, hdr) 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#define to_binder_fd_object(hdr) container_of(hdr, struct binder_fd_object, hdr) 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#define to_binder_buffer_object(hdr) \ 21062306a36Sopenharmony_ci container_of(hdr, struct binder_buffer_object, hdr) 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci#define to_binder_fd_array_object(hdr) \ 21362306a36Sopenharmony_ci container_of(hdr, struct binder_fd_array_object, hdr) 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic struct binder_stats binder_stats; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic inline void binder_stats_deleted(enum binder_stat_types type) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci atomic_inc(&binder_stats.obj_deleted[type]); 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic inline void binder_stats_created(enum binder_stat_types type) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci atomic_inc(&binder_stats.obj_created[type]); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistruct binder_transaction_log_entry { 22862306a36Sopenharmony_ci int debug_id; 22962306a36Sopenharmony_ci int debug_id_done; 23062306a36Sopenharmony_ci int call_type; 23162306a36Sopenharmony_ci int from_proc; 23262306a36Sopenharmony_ci int from_thread; 23362306a36Sopenharmony_ci int target_handle; 23462306a36Sopenharmony_ci int to_proc; 23562306a36Sopenharmony_ci int to_thread; 23662306a36Sopenharmony_ci int to_node; 23762306a36Sopenharmony_ci int data_size; 23862306a36Sopenharmony_ci int offsets_size; 23962306a36Sopenharmony_ci int return_error_line; 24062306a36Sopenharmony_ci uint32_t return_error; 24162306a36Sopenharmony_ci uint32_t return_error_param; 24262306a36Sopenharmony_ci char context_name[BINDERFS_MAX_NAME + 1]; 24362306a36Sopenharmony_ci}; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistruct binder_transaction_log { 24662306a36Sopenharmony_ci atomic_t cur; 24762306a36Sopenharmony_ci bool full; 24862306a36Sopenharmony_ci struct binder_transaction_log_entry entry[32]; 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic struct binder_transaction_log binder_transaction_log; 25262306a36Sopenharmony_cistatic struct binder_transaction_log binder_transaction_log_failed; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic struct binder_transaction_log_entry *binder_transaction_log_add( 25562306a36Sopenharmony_ci struct binder_transaction_log *log) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci struct binder_transaction_log_entry *e; 25862306a36Sopenharmony_ci unsigned int cur = atomic_inc_return(&log->cur); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci if (cur >= ARRAY_SIZE(log->entry)) 26162306a36Sopenharmony_ci log->full = true; 26262306a36Sopenharmony_ci e = &log->entry[cur % ARRAY_SIZE(log->entry)]; 26362306a36Sopenharmony_ci WRITE_ONCE(e->debug_id_done, 0); 26462306a36Sopenharmony_ci /* 26562306a36Sopenharmony_ci * write-barrier to synchronize access to e->debug_id_done. 26662306a36Sopenharmony_ci * We make sure the initialized 0 value is seen before 26762306a36Sopenharmony_ci * memset() other fields are zeroed by memset. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci smp_wmb(); 27062306a36Sopenharmony_ci memset(e, 0, sizeof(*e)); 27162306a36Sopenharmony_ci return e; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cienum binder_deferred_state { 27562306a36Sopenharmony_ci BINDER_DEFERRED_FLUSH = 0x01, 27662306a36Sopenharmony_ci BINDER_DEFERRED_RELEASE = 0x02, 27762306a36Sopenharmony_ci}; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cienum { 28062306a36Sopenharmony_ci BINDER_LOOPER_STATE_REGISTERED = 0x01, 28162306a36Sopenharmony_ci BINDER_LOOPER_STATE_ENTERED = 0x02, 28262306a36Sopenharmony_ci BINDER_LOOPER_STATE_EXITED = 0x04, 28362306a36Sopenharmony_ci BINDER_LOOPER_STATE_INVALID = 0x08, 28462306a36Sopenharmony_ci BINDER_LOOPER_STATE_WAITING = 0x10, 28562306a36Sopenharmony_ci BINDER_LOOPER_STATE_POLL = 0x20, 28662306a36Sopenharmony_ci}; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/** 28962306a36Sopenharmony_ci * binder_proc_lock() - Acquire outer lock for given binder_proc 29062306a36Sopenharmony_ci * @proc: struct binder_proc to acquire 29162306a36Sopenharmony_ci * 29262306a36Sopenharmony_ci * Acquires proc->outer_lock. Used to protect binder_ref 29362306a36Sopenharmony_ci * structures associated with the given proc. 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_ci#define binder_proc_lock(proc) _binder_proc_lock(proc, __LINE__) 29662306a36Sopenharmony_cistatic void 29762306a36Sopenharmony_ci_binder_proc_lock(struct binder_proc *proc, int line) 29862306a36Sopenharmony_ci __acquires(&proc->outer_lock) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_SPINLOCKS, 30162306a36Sopenharmony_ci "%s: line=%d\n", __func__, line); 30262306a36Sopenharmony_ci spin_lock(&proc->outer_lock); 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci/** 30662306a36Sopenharmony_ci * binder_proc_unlock() - Release spinlock for given binder_proc 30762306a36Sopenharmony_ci * @proc: struct binder_proc to acquire 30862306a36Sopenharmony_ci * 30962306a36Sopenharmony_ci * Release lock acquired via binder_proc_lock() 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_ci#define binder_proc_unlock(proc) _binder_proc_unlock(proc, __LINE__) 31262306a36Sopenharmony_cistatic void 31362306a36Sopenharmony_ci_binder_proc_unlock(struct binder_proc *proc, int line) 31462306a36Sopenharmony_ci __releases(&proc->outer_lock) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_SPINLOCKS, 31762306a36Sopenharmony_ci "%s: line=%d\n", __func__, line); 31862306a36Sopenharmony_ci spin_unlock(&proc->outer_lock); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/** 32262306a36Sopenharmony_ci * binder_inner_proc_lock() - Acquire inner lock for given binder_proc 32362306a36Sopenharmony_ci * @proc: struct binder_proc to acquire 32462306a36Sopenharmony_ci * 32562306a36Sopenharmony_ci * Acquires proc->inner_lock. Used to protect todo lists 32662306a36Sopenharmony_ci */ 32762306a36Sopenharmony_ci#define binder_inner_proc_lock(proc) _binder_inner_proc_lock(proc, __LINE__) 32862306a36Sopenharmony_cistatic void 32962306a36Sopenharmony_ci_binder_inner_proc_lock(struct binder_proc *proc, int line) 33062306a36Sopenharmony_ci __acquires(&proc->inner_lock) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_SPINLOCKS, 33362306a36Sopenharmony_ci "%s: line=%d\n", __func__, line); 33462306a36Sopenharmony_ci spin_lock(&proc->inner_lock); 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/** 33862306a36Sopenharmony_ci * binder_inner_proc_unlock() - Release inner lock for given binder_proc 33962306a36Sopenharmony_ci * @proc: struct binder_proc to acquire 34062306a36Sopenharmony_ci * 34162306a36Sopenharmony_ci * Release lock acquired via binder_inner_proc_lock() 34262306a36Sopenharmony_ci */ 34362306a36Sopenharmony_ci#define binder_inner_proc_unlock(proc) _binder_inner_proc_unlock(proc, __LINE__) 34462306a36Sopenharmony_cistatic void 34562306a36Sopenharmony_ci_binder_inner_proc_unlock(struct binder_proc *proc, int line) 34662306a36Sopenharmony_ci __releases(&proc->inner_lock) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_SPINLOCKS, 34962306a36Sopenharmony_ci "%s: line=%d\n", __func__, line); 35062306a36Sopenharmony_ci spin_unlock(&proc->inner_lock); 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/** 35462306a36Sopenharmony_ci * binder_node_lock() - Acquire spinlock for given binder_node 35562306a36Sopenharmony_ci * @node: struct binder_node to acquire 35662306a36Sopenharmony_ci * 35762306a36Sopenharmony_ci * Acquires node->lock. Used to protect binder_node fields 35862306a36Sopenharmony_ci */ 35962306a36Sopenharmony_ci#define binder_node_lock(node) _binder_node_lock(node, __LINE__) 36062306a36Sopenharmony_cistatic void 36162306a36Sopenharmony_ci_binder_node_lock(struct binder_node *node, int line) 36262306a36Sopenharmony_ci __acquires(&node->lock) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_SPINLOCKS, 36562306a36Sopenharmony_ci "%s: line=%d\n", __func__, line); 36662306a36Sopenharmony_ci spin_lock(&node->lock); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci/** 37062306a36Sopenharmony_ci * binder_node_unlock() - Release spinlock for given binder_proc 37162306a36Sopenharmony_ci * @node: struct binder_node to acquire 37262306a36Sopenharmony_ci * 37362306a36Sopenharmony_ci * Release lock acquired via binder_node_lock() 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci#define binder_node_unlock(node) _binder_node_unlock(node, __LINE__) 37662306a36Sopenharmony_cistatic void 37762306a36Sopenharmony_ci_binder_node_unlock(struct binder_node *node, int line) 37862306a36Sopenharmony_ci __releases(&node->lock) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_SPINLOCKS, 38162306a36Sopenharmony_ci "%s: line=%d\n", __func__, line); 38262306a36Sopenharmony_ci spin_unlock(&node->lock); 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/** 38662306a36Sopenharmony_ci * binder_node_inner_lock() - Acquire node and inner locks 38762306a36Sopenharmony_ci * @node: struct binder_node to acquire 38862306a36Sopenharmony_ci * 38962306a36Sopenharmony_ci * Acquires node->lock. If node->proc also acquires 39062306a36Sopenharmony_ci * proc->inner_lock. Used to protect binder_node fields 39162306a36Sopenharmony_ci */ 39262306a36Sopenharmony_ci#define binder_node_inner_lock(node) _binder_node_inner_lock(node, __LINE__) 39362306a36Sopenharmony_cistatic void 39462306a36Sopenharmony_ci_binder_node_inner_lock(struct binder_node *node, int line) 39562306a36Sopenharmony_ci __acquires(&node->lock) __acquires(&node->proc->inner_lock) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_SPINLOCKS, 39862306a36Sopenharmony_ci "%s: line=%d\n", __func__, line); 39962306a36Sopenharmony_ci spin_lock(&node->lock); 40062306a36Sopenharmony_ci if (node->proc) 40162306a36Sopenharmony_ci binder_inner_proc_lock(node->proc); 40262306a36Sopenharmony_ci else 40362306a36Sopenharmony_ci /* annotation for sparse */ 40462306a36Sopenharmony_ci __acquire(&node->proc->inner_lock); 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci/** 40862306a36Sopenharmony_ci * binder_node_inner_unlock() - Release node and inner locks 40962306a36Sopenharmony_ci * @node: struct binder_node to acquire 41062306a36Sopenharmony_ci * 41162306a36Sopenharmony_ci * Release lock acquired via binder_node_lock() 41262306a36Sopenharmony_ci */ 41362306a36Sopenharmony_ci#define binder_node_inner_unlock(node) _binder_node_inner_unlock(node, __LINE__) 41462306a36Sopenharmony_cistatic void 41562306a36Sopenharmony_ci_binder_node_inner_unlock(struct binder_node *node, int line) 41662306a36Sopenharmony_ci __releases(&node->lock) __releases(&node->proc->inner_lock) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci struct binder_proc *proc = node->proc; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_SPINLOCKS, 42162306a36Sopenharmony_ci "%s: line=%d\n", __func__, line); 42262306a36Sopenharmony_ci if (proc) 42362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 42462306a36Sopenharmony_ci else 42562306a36Sopenharmony_ci /* annotation for sparse */ 42662306a36Sopenharmony_ci __release(&node->proc->inner_lock); 42762306a36Sopenharmony_ci spin_unlock(&node->lock); 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic bool binder_worklist_empty_ilocked(struct list_head *list) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci return list_empty(list); 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci/** 43662306a36Sopenharmony_ci * binder_worklist_empty() - Check if no items on the work list 43762306a36Sopenharmony_ci * @proc: binder_proc associated with list 43862306a36Sopenharmony_ci * @list: list to check 43962306a36Sopenharmony_ci * 44062306a36Sopenharmony_ci * Return: true if there are no items on list, else false 44162306a36Sopenharmony_ci */ 44262306a36Sopenharmony_cistatic bool binder_worklist_empty(struct binder_proc *proc, 44362306a36Sopenharmony_ci struct list_head *list) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci bool ret; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci binder_inner_proc_lock(proc); 44862306a36Sopenharmony_ci ret = binder_worklist_empty_ilocked(list); 44962306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 45062306a36Sopenharmony_ci return ret; 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci/** 45462306a36Sopenharmony_ci * binder_enqueue_work_ilocked() - Add an item to the work list 45562306a36Sopenharmony_ci * @work: struct binder_work to add to list 45662306a36Sopenharmony_ci * @target_list: list to add work to 45762306a36Sopenharmony_ci * 45862306a36Sopenharmony_ci * Adds the work to the specified list. Asserts that work 45962306a36Sopenharmony_ci * is not already on a list. 46062306a36Sopenharmony_ci * 46162306a36Sopenharmony_ci * Requires the proc->inner_lock to be held. 46262306a36Sopenharmony_ci */ 46362306a36Sopenharmony_cistatic void 46462306a36Sopenharmony_cibinder_enqueue_work_ilocked(struct binder_work *work, 46562306a36Sopenharmony_ci struct list_head *target_list) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci BUG_ON(target_list == NULL); 46862306a36Sopenharmony_ci BUG_ON(work->entry.next && !list_empty(&work->entry)); 46962306a36Sopenharmony_ci list_add_tail(&work->entry, target_list); 47062306a36Sopenharmony_ci} 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci/** 47362306a36Sopenharmony_ci * binder_enqueue_deferred_thread_work_ilocked() - Add deferred thread work 47462306a36Sopenharmony_ci * @thread: thread to queue work to 47562306a36Sopenharmony_ci * @work: struct binder_work to add to list 47662306a36Sopenharmony_ci * 47762306a36Sopenharmony_ci * Adds the work to the todo list of the thread. Doesn't set the process_todo 47862306a36Sopenharmony_ci * flag, which means that (if it wasn't already set) the thread will go to 47962306a36Sopenharmony_ci * sleep without handling this work when it calls read. 48062306a36Sopenharmony_ci * 48162306a36Sopenharmony_ci * Requires the proc->inner_lock to be held. 48262306a36Sopenharmony_ci */ 48362306a36Sopenharmony_cistatic void 48462306a36Sopenharmony_cibinder_enqueue_deferred_thread_work_ilocked(struct binder_thread *thread, 48562306a36Sopenharmony_ci struct binder_work *work) 48662306a36Sopenharmony_ci{ 48762306a36Sopenharmony_ci WARN_ON(!list_empty(&thread->waiting_thread_node)); 48862306a36Sopenharmony_ci binder_enqueue_work_ilocked(work, &thread->todo); 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci/** 49262306a36Sopenharmony_ci * binder_enqueue_thread_work_ilocked() - Add an item to the thread work list 49362306a36Sopenharmony_ci * @thread: thread to queue work to 49462306a36Sopenharmony_ci * @work: struct binder_work to add to list 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * Adds the work to the todo list of the thread, and enables processing 49762306a36Sopenharmony_ci * of the todo queue. 49862306a36Sopenharmony_ci * 49962306a36Sopenharmony_ci * Requires the proc->inner_lock to be held. 50062306a36Sopenharmony_ci */ 50162306a36Sopenharmony_cistatic void 50262306a36Sopenharmony_cibinder_enqueue_thread_work_ilocked(struct binder_thread *thread, 50362306a36Sopenharmony_ci struct binder_work *work) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci WARN_ON(!list_empty(&thread->waiting_thread_node)); 50662306a36Sopenharmony_ci binder_enqueue_work_ilocked(work, &thread->todo); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* (e)poll-based threads require an explicit wakeup signal when 50962306a36Sopenharmony_ci * queuing their own work; they rely on these events to consume 51062306a36Sopenharmony_ci * messages without I/O block. Without it, threads risk waiting 51162306a36Sopenharmony_ci * indefinitely without handling the work. 51262306a36Sopenharmony_ci */ 51362306a36Sopenharmony_ci if (thread->looper & BINDER_LOOPER_STATE_POLL && 51462306a36Sopenharmony_ci thread->pid == current->pid && !thread->process_todo) 51562306a36Sopenharmony_ci wake_up_interruptible_sync(&thread->wait); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci thread->process_todo = true; 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci/** 52162306a36Sopenharmony_ci * binder_enqueue_thread_work() - Add an item to the thread work list 52262306a36Sopenharmony_ci * @thread: thread to queue work to 52362306a36Sopenharmony_ci * @work: struct binder_work to add to list 52462306a36Sopenharmony_ci * 52562306a36Sopenharmony_ci * Adds the work to the todo list of the thread, and enables processing 52662306a36Sopenharmony_ci * of the todo queue. 52762306a36Sopenharmony_ci */ 52862306a36Sopenharmony_cistatic void 52962306a36Sopenharmony_cibinder_enqueue_thread_work(struct binder_thread *thread, 53062306a36Sopenharmony_ci struct binder_work *work) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 53362306a36Sopenharmony_ci binder_enqueue_thread_work_ilocked(thread, work); 53462306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic void 53862306a36Sopenharmony_cibinder_dequeue_work_ilocked(struct binder_work *work) 53962306a36Sopenharmony_ci{ 54062306a36Sopenharmony_ci list_del_init(&work->entry); 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci/** 54462306a36Sopenharmony_ci * binder_dequeue_work() - Removes an item from the work list 54562306a36Sopenharmony_ci * @proc: binder_proc associated with list 54662306a36Sopenharmony_ci * @work: struct binder_work to remove from list 54762306a36Sopenharmony_ci * 54862306a36Sopenharmony_ci * Removes the specified work item from whatever list it is on. 54962306a36Sopenharmony_ci * Can safely be called if work is not on any list. 55062306a36Sopenharmony_ci */ 55162306a36Sopenharmony_cistatic void 55262306a36Sopenharmony_cibinder_dequeue_work(struct binder_proc *proc, struct binder_work *work) 55362306a36Sopenharmony_ci{ 55462306a36Sopenharmony_ci binder_inner_proc_lock(proc); 55562306a36Sopenharmony_ci binder_dequeue_work_ilocked(work); 55662306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_cistatic struct binder_work *binder_dequeue_work_head_ilocked( 56062306a36Sopenharmony_ci struct list_head *list) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci struct binder_work *w; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci w = list_first_entry_or_null(list, struct binder_work, entry); 56562306a36Sopenharmony_ci if (w) 56662306a36Sopenharmony_ci list_del_init(&w->entry); 56762306a36Sopenharmony_ci return w; 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_cistatic void 57162306a36Sopenharmony_cibinder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); 57262306a36Sopenharmony_cistatic void binder_free_thread(struct binder_thread *thread); 57362306a36Sopenharmony_cistatic void binder_free_proc(struct binder_proc *proc); 57462306a36Sopenharmony_cistatic void binder_inc_node_tmpref_ilocked(struct binder_node *node); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 57762306a36Sopenharmony_cistatic inline u64 binder_clock(void) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci#ifdef CONFIG_TRACE_CLOCK 58062306a36Sopenharmony_ci return trace_clock_local(); 58162306a36Sopenharmony_ci#endif 58262306a36Sopenharmony_ci return 0; 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci#endif 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_cistatic bool binder_has_work_ilocked(struct binder_thread *thread, 58762306a36Sopenharmony_ci bool do_proc_work) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci return thread->process_todo || 59062306a36Sopenharmony_ci thread->looper_need_return || 59162306a36Sopenharmony_ci (do_proc_work && 59262306a36Sopenharmony_ci !binder_worklist_empty_ilocked(&thread->proc->todo)); 59362306a36Sopenharmony_ci} 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cistatic bool binder_has_work(struct binder_thread *thread, bool do_proc_work) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci bool has_work; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 60062306a36Sopenharmony_ci has_work = binder_has_work_ilocked(thread, do_proc_work); 60162306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci return has_work; 60462306a36Sopenharmony_ci} 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_cistatic bool binder_available_for_proc_work_ilocked(struct binder_thread *thread) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci return !thread->transaction_stack && 60962306a36Sopenharmony_ci binder_worklist_empty_ilocked(&thread->todo) && 61062306a36Sopenharmony_ci (thread->looper & (BINDER_LOOPER_STATE_ENTERED | 61162306a36Sopenharmony_ci BINDER_LOOPER_STATE_REGISTERED)); 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc, 61562306a36Sopenharmony_ci bool sync) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci struct rb_node *n; 61862306a36Sopenharmony_ci struct binder_thread *thread; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { 62162306a36Sopenharmony_ci thread = rb_entry(n, struct binder_thread, rb_node); 62262306a36Sopenharmony_ci if (thread->looper & BINDER_LOOPER_STATE_POLL && 62362306a36Sopenharmony_ci binder_available_for_proc_work_ilocked(thread)) { 62462306a36Sopenharmony_ci if (sync) 62562306a36Sopenharmony_ci wake_up_interruptible_sync(&thread->wait); 62662306a36Sopenharmony_ci else 62762306a36Sopenharmony_ci wake_up_interruptible(&thread->wait); 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci} 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci/** 63362306a36Sopenharmony_ci * binder_select_thread_ilocked() - selects a thread for doing proc work. 63462306a36Sopenharmony_ci * @proc: process to select a thread from 63562306a36Sopenharmony_ci * 63662306a36Sopenharmony_ci * Note that calling this function moves the thread off the waiting_threads 63762306a36Sopenharmony_ci * list, so it can only be woken up by the caller of this function, or a 63862306a36Sopenharmony_ci * signal. Therefore, callers *should* always wake up the thread this function 63962306a36Sopenharmony_ci * returns. 64062306a36Sopenharmony_ci * 64162306a36Sopenharmony_ci * Return: If there's a thread currently waiting for process work, 64262306a36Sopenharmony_ci * returns that thread. Otherwise returns NULL. 64362306a36Sopenharmony_ci */ 64462306a36Sopenharmony_cistatic struct binder_thread * 64562306a36Sopenharmony_cibinder_select_thread_ilocked(struct binder_proc *proc) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci struct binder_thread *thread; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci assert_spin_locked(&proc->inner_lock); 65062306a36Sopenharmony_ci thread = list_first_entry_or_null(&proc->waiting_threads, 65162306a36Sopenharmony_ci struct binder_thread, 65262306a36Sopenharmony_ci waiting_thread_node); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci if (thread) 65562306a36Sopenharmony_ci list_del_init(&thread->waiting_thread_node); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci return thread; 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci/** 66162306a36Sopenharmony_ci * binder_wakeup_thread_ilocked() - wakes up a thread for doing proc work. 66262306a36Sopenharmony_ci * @proc: process to wake up a thread in 66362306a36Sopenharmony_ci * @thread: specific thread to wake-up (may be NULL) 66462306a36Sopenharmony_ci * @sync: whether to do a synchronous wake-up 66562306a36Sopenharmony_ci * 66662306a36Sopenharmony_ci * This function wakes up a thread in the @proc process. 66762306a36Sopenharmony_ci * The caller may provide a specific thread to wake-up in 66862306a36Sopenharmony_ci * the @thread parameter. If @thread is NULL, this function 66962306a36Sopenharmony_ci * will wake up threads that have called poll(). 67062306a36Sopenharmony_ci * 67162306a36Sopenharmony_ci * Note that for this function to work as expected, callers 67262306a36Sopenharmony_ci * should first call binder_select_thread() to find a thread 67362306a36Sopenharmony_ci * to handle the work (if they don't have a thread already), 67462306a36Sopenharmony_ci * and pass the result into the @thread parameter. 67562306a36Sopenharmony_ci */ 67662306a36Sopenharmony_cistatic void binder_wakeup_thread_ilocked(struct binder_proc *proc, 67762306a36Sopenharmony_ci struct binder_thread *thread, 67862306a36Sopenharmony_ci bool sync) 67962306a36Sopenharmony_ci{ 68062306a36Sopenharmony_ci assert_spin_locked(&proc->inner_lock); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if (thread) { 68362306a36Sopenharmony_ci if (sync) 68462306a36Sopenharmony_ci wake_up_interruptible_sync(&thread->wait); 68562306a36Sopenharmony_ci else 68662306a36Sopenharmony_ci wake_up_interruptible(&thread->wait); 68762306a36Sopenharmony_ci return; 68862306a36Sopenharmony_ci } 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* Didn't find a thread waiting for proc work; this can happen 69162306a36Sopenharmony_ci * in two scenarios: 69262306a36Sopenharmony_ci * 1. All threads are busy handling transactions 69362306a36Sopenharmony_ci * In that case, one of those threads should call back into 69462306a36Sopenharmony_ci * the kernel driver soon and pick up this work. 69562306a36Sopenharmony_ci * 2. Threads are using the (e)poll interface, in which case 69662306a36Sopenharmony_ci * they may be blocked on the waitqueue without having been 69762306a36Sopenharmony_ci * added to waiting_threads. For this case, we just iterate 69862306a36Sopenharmony_ci * over all threads not handling transaction work, and 69962306a36Sopenharmony_ci * wake them all up. We wake all because we don't know whether 70062306a36Sopenharmony_ci * a thread that called into (e)poll is handling non-binder 70162306a36Sopenharmony_ci * work currently. 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_ci binder_wakeup_poll_threads_ilocked(proc, sync); 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic void binder_wakeup_proc_ilocked(struct binder_proc *proc) 70762306a36Sopenharmony_ci{ 70862306a36Sopenharmony_ci struct binder_thread *thread = binder_select_thread_ilocked(proc); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci binder_wakeup_thread_ilocked(proc, thread, /* sync = */false); 71162306a36Sopenharmony_ci} 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic void binder_set_nice(long nice) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci long min_nice; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci if (can_nice(current, nice)) { 71862306a36Sopenharmony_ci set_user_nice(current, nice); 71962306a36Sopenharmony_ci return; 72062306a36Sopenharmony_ci } 72162306a36Sopenharmony_ci min_nice = rlimit_to_nice(rlimit(RLIMIT_NICE)); 72262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_PRIORITY_CAP, 72362306a36Sopenharmony_ci "%d: nice value %ld not allowed use %ld instead\n", 72462306a36Sopenharmony_ci current->pid, nice, min_nice); 72562306a36Sopenharmony_ci set_user_nice(current, min_nice); 72662306a36Sopenharmony_ci if (min_nice <= MAX_NICE) 72762306a36Sopenharmony_ci return; 72862306a36Sopenharmony_ci binder_user_error("%d RLIMIT_NICE not set\n", current->pid); 72962306a36Sopenharmony_ci} 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_cistatic struct binder_node *binder_get_node_ilocked(struct binder_proc *proc, 73262306a36Sopenharmony_ci binder_uintptr_t ptr) 73362306a36Sopenharmony_ci{ 73462306a36Sopenharmony_ci struct rb_node *n = proc->nodes.rb_node; 73562306a36Sopenharmony_ci struct binder_node *node; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci assert_spin_locked(&proc->inner_lock); 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci while (n) { 74062306a36Sopenharmony_ci node = rb_entry(n, struct binder_node, rb_node); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (ptr < node->ptr) 74362306a36Sopenharmony_ci n = n->rb_left; 74462306a36Sopenharmony_ci else if (ptr > node->ptr) 74562306a36Sopenharmony_ci n = n->rb_right; 74662306a36Sopenharmony_ci else { 74762306a36Sopenharmony_ci /* 74862306a36Sopenharmony_ci * take an implicit weak reference 74962306a36Sopenharmony_ci * to ensure node stays alive until 75062306a36Sopenharmony_ci * call to binder_put_node() 75162306a36Sopenharmony_ci */ 75262306a36Sopenharmony_ci binder_inc_node_tmpref_ilocked(node); 75362306a36Sopenharmony_ci return node; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci return NULL; 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_cistatic struct binder_node *binder_get_node(struct binder_proc *proc, 76062306a36Sopenharmony_ci binder_uintptr_t ptr) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci struct binder_node *node; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci binder_inner_proc_lock(proc); 76562306a36Sopenharmony_ci node = binder_get_node_ilocked(proc, ptr); 76662306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 76762306a36Sopenharmony_ci return node; 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_cistatic struct binder_node *binder_init_node_ilocked( 77162306a36Sopenharmony_ci struct binder_proc *proc, 77262306a36Sopenharmony_ci struct binder_node *new_node, 77362306a36Sopenharmony_ci struct flat_binder_object *fp) 77462306a36Sopenharmony_ci{ 77562306a36Sopenharmony_ci struct rb_node **p = &proc->nodes.rb_node; 77662306a36Sopenharmony_ci struct rb_node *parent = NULL; 77762306a36Sopenharmony_ci struct binder_node *node; 77862306a36Sopenharmony_ci binder_uintptr_t ptr = fp ? fp->binder : 0; 77962306a36Sopenharmony_ci binder_uintptr_t cookie = fp ? fp->cookie : 0; 78062306a36Sopenharmony_ci __u32 flags = fp ? fp->flags : 0; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci assert_spin_locked(&proc->inner_lock); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci while (*p) { 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci parent = *p; 78762306a36Sopenharmony_ci node = rb_entry(parent, struct binder_node, rb_node); 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci if (ptr < node->ptr) 79062306a36Sopenharmony_ci p = &(*p)->rb_left; 79162306a36Sopenharmony_ci else if (ptr > node->ptr) 79262306a36Sopenharmony_ci p = &(*p)->rb_right; 79362306a36Sopenharmony_ci else { 79462306a36Sopenharmony_ci /* 79562306a36Sopenharmony_ci * A matching node is already in 79662306a36Sopenharmony_ci * the rb tree. Abandon the init 79762306a36Sopenharmony_ci * and return it. 79862306a36Sopenharmony_ci */ 79962306a36Sopenharmony_ci binder_inc_node_tmpref_ilocked(node); 80062306a36Sopenharmony_ci return node; 80162306a36Sopenharmony_ci } 80262306a36Sopenharmony_ci } 80362306a36Sopenharmony_ci node = new_node; 80462306a36Sopenharmony_ci binder_stats_created(BINDER_STAT_NODE); 80562306a36Sopenharmony_ci node->tmp_refs++; 80662306a36Sopenharmony_ci rb_link_node(&node->rb_node, parent, p); 80762306a36Sopenharmony_ci rb_insert_color(&node->rb_node, &proc->nodes); 80862306a36Sopenharmony_ci node->debug_id = atomic_inc_return(&binder_last_id); 80962306a36Sopenharmony_ci node->proc = proc; 81062306a36Sopenharmony_ci node->ptr = ptr; 81162306a36Sopenharmony_ci node->cookie = cookie; 81262306a36Sopenharmony_ci node->work.type = BINDER_WORK_NODE; 81362306a36Sopenharmony_ci node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK; 81462306a36Sopenharmony_ci node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); 81562306a36Sopenharmony_ci node->txn_security_ctx = !!(flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX); 81662306a36Sopenharmony_ci spin_lock_init(&node->lock); 81762306a36Sopenharmony_ci INIT_LIST_HEAD(&node->work.entry); 81862306a36Sopenharmony_ci INIT_LIST_HEAD(&node->async_todo); 81962306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_INTERNAL_REFS, 82062306a36Sopenharmony_ci "%d:%d node %d u%016llx c%016llx created\n", 82162306a36Sopenharmony_ci proc->pid, current->pid, node->debug_id, 82262306a36Sopenharmony_ci (u64)node->ptr, (u64)node->cookie); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci return node; 82562306a36Sopenharmony_ci} 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_cistatic struct binder_node *binder_new_node(struct binder_proc *proc, 82862306a36Sopenharmony_ci struct flat_binder_object *fp) 82962306a36Sopenharmony_ci{ 83062306a36Sopenharmony_ci struct binder_node *node; 83162306a36Sopenharmony_ci struct binder_node *new_node = kzalloc(sizeof(*node), GFP_KERNEL); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci if (!new_node) 83462306a36Sopenharmony_ci return NULL; 83562306a36Sopenharmony_ci binder_inner_proc_lock(proc); 83662306a36Sopenharmony_ci node = binder_init_node_ilocked(proc, new_node, fp); 83762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 83862306a36Sopenharmony_ci if (node != new_node) 83962306a36Sopenharmony_ci /* 84062306a36Sopenharmony_ci * The node was already added by another thread 84162306a36Sopenharmony_ci */ 84262306a36Sopenharmony_ci kfree(new_node); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci return node; 84562306a36Sopenharmony_ci} 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_cistatic void binder_free_node(struct binder_node *node) 84862306a36Sopenharmony_ci{ 84962306a36Sopenharmony_ci kfree(node); 85062306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_NODE); 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_cistatic int binder_inc_node_nilocked(struct binder_node *node, int strong, 85462306a36Sopenharmony_ci int internal, 85562306a36Sopenharmony_ci struct list_head *target_list) 85662306a36Sopenharmony_ci{ 85762306a36Sopenharmony_ci struct binder_proc *proc = node->proc; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci assert_spin_locked(&node->lock); 86062306a36Sopenharmony_ci if (proc) 86162306a36Sopenharmony_ci assert_spin_locked(&proc->inner_lock); 86262306a36Sopenharmony_ci if (strong) { 86362306a36Sopenharmony_ci if (internal) { 86462306a36Sopenharmony_ci if (target_list == NULL && 86562306a36Sopenharmony_ci node->internal_strong_refs == 0 && 86662306a36Sopenharmony_ci !(node->proc && 86762306a36Sopenharmony_ci node == node->proc->context->binder_context_mgr_node && 86862306a36Sopenharmony_ci node->has_strong_ref)) { 86962306a36Sopenharmony_ci pr_err("invalid inc strong node for %d\n", 87062306a36Sopenharmony_ci node->debug_id); 87162306a36Sopenharmony_ci return -EINVAL; 87262306a36Sopenharmony_ci } 87362306a36Sopenharmony_ci node->internal_strong_refs++; 87462306a36Sopenharmony_ci } else 87562306a36Sopenharmony_ci node->local_strong_refs++; 87662306a36Sopenharmony_ci if (!node->has_strong_ref && target_list) { 87762306a36Sopenharmony_ci struct binder_thread *thread = container_of(target_list, 87862306a36Sopenharmony_ci struct binder_thread, todo); 87962306a36Sopenharmony_ci binder_dequeue_work_ilocked(&node->work); 88062306a36Sopenharmony_ci BUG_ON(&thread->todo != target_list); 88162306a36Sopenharmony_ci binder_enqueue_deferred_thread_work_ilocked(thread, 88262306a36Sopenharmony_ci &node->work); 88362306a36Sopenharmony_ci } 88462306a36Sopenharmony_ci } else { 88562306a36Sopenharmony_ci if (!internal) 88662306a36Sopenharmony_ci node->local_weak_refs++; 88762306a36Sopenharmony_ci if (!node->has_weak_ref && list_empty(&node->work.entry)) { 88862306a36Sopenharmony_ci if (target_list == NULL) { 88962306a36Sopenharmony_ci pr_err("invalid inc weak node for %d\n", 89062306a36Sopenharmony_ci node->debug_id); 89162306a36Sopenharmony_ci return -EINVAL; 89262306a36Sopenharmony_ci } 89362306a36Sopenharmony_ci /* 89462306a36Sopenharmony_ci * See comment above 89562306a36Sopenharmony_ci */ 89662306a36Sopenharmony_ci binder_enqueue_work_ilocked(&node->work, target_list); 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci } 89962306a36Sopenharmony_ci return 0; 90062306a36Sopenharmony_ci} 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_cistatic int binder_inc_node(struct binder_node *node, int strong, int internal, 90362306a36Sopenharmony_ci struct list_head *target_list) 90462306a36Sopenharmony_ci{ 90562306a36Sopenharmony_ci int ret; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci binder_node_inner_lock(node); 90862306a36Sopenharmony_ci ret = binder_inc_node_nilocked(node, strong, internal, target_list); 90962306a36Sopenharmony_ci binder_node_inner_unlock(node); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci return ret; 91262306a36Sopenharmony_ci} 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cistatic bool binder_dec_node_nilocked(struct binder_node *node, 91562306a36Sopenharmony_ci int strong, int internal) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci struct binder_proc *proc = node->proc; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci assert_spin_locked(&node->lock); 92062306a36Sopenharmony_ci if (proc) 92162306a36Sopenharmony_ci assert_spin_locked(&proc->inner_lock); 92262306a36Sopenharmony_ci if (strong) { 92362306a36Sopenharmony_ci if (internal) 92462306a36Sopenharmony_ci node->internal_strong_refs--; 92562306a36Sopenharmony_ci else 92662306a36Sopenharmony_ci node->local_strong_refs--; 92762306a36Sopenharmony_ci if (node->local_strong_refs || node->internal_strong_refs) 92862306a36Sopenharmony_ci return false; 92962306a36Sopenharmony_ci } else { 93062306a36Sopenharmony_ci if (!internal) 93162306a36Sopenharmony_ci node->local_weak_refs--; 93262306a36Sopenharmony_ci if (node->local_weak_refs || node->tmp_refs || 93362306a36Sopenharmony_ci !hlist_empty(&node->refs)) 93462306a36Sopenharmony_ci return false; 93562306a36Sopenharmony_ci } 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci if (proc && (node->has_strong_ref || node->has_weak_ref)) { 93862306a36Sopenharmony_ci if (list_empty(&node->work.entry)) { 93962306a36Sopenharmony_ci binder_enqueue_work_ilocked(&node->work, &proc->todo); 94062306a36Sopenharmony_ci binder_wakeup_proc_ilocked(proc); 94162306a36Sopenharmony_ci } 94262306a36Sopenharmony_ci } else { 94362306a36Sopenharmony_ci if (hlist_empty(&node->refs) && !node->local_strong_refs && 94462306a36Sopenharmony_ci !node->local_weak_refs && !node->tmp_refs) { 94562306a36Sopenharmony_ci if (proc) { 94662306a36Sopenharmony_ci binder_dequeue_work_ilocked(&node->work); 94762306a36Sopenharmony_ci rb_erase(&node->rb_node, &proc->nodes); 94862306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_INTERNAL_REFS, 94962306a36Sopenharmony_ci "refless node %d deleted\n", 95062306a36Sopenharmony_ci node->debug_id); 95162306a36Sopenharmony_ci } else { 95262306a36Sopenharmony_ci BUG_ON(!list_empty(&node->work.entry)); 95362306a36Sopenharmony_ci spin_lock(&binder_dead_nodes_lock); 95462306a36Sopenharmony_ci /* 95562306a36Sopenharmony_ci * tmp_refs could have changed so 95662306a36Sopenharmony_ci * check it again 95762306a36Sopenharmony_ci */ 95862306a36Sopenharmony_ci if (node->tmp_refs) { 95962306a36Sopenharmony_ci spin_unlock(&binder_dead_nodes_lock); 96062306a36Sopenharmony_ci return false; 96162306a36Sopenharmony_ci } 96262306a36Sopenharmony_ci hlist_del(&node->dead_node); 96362306a36Sopenharmony_ci spin_unlock(&binder_dead_nodes_lock); 96462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_INTERNAL_REFS, 96562306a36Sopenharmony_ci "dead node %d deleted\n", 96662306a36Sopenharmony_ci node->debug_id); 96762306a36Sopenharmony_ci } 96862306a36Sopenharmony_ci return true; 96962306a36Sopenharmony_ci } 97062306a36Sopenharmony_ci } 97162306a36Sopenharmony_ci return false; 97262306a36Sopenharmony_ci} 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_cistatic void binder_dec_node(struct binder_node *node, int strong, int internal) 97562306a36Sopenharmony_ci{ 97662306a36Sopenharmony_ci bool free_node; 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci binder_node_inner_lock(node); 97962306a36Sopenharmony_ci free_node = binder_dec_node_nilocked(node, strong, internal); 98062306a36Sopenharmony_ci binder_node_inner_unlock(node); 98162306a36Sopenharmony_ci if (free_node) 98262306a36Sopenharmony_ci binder_free_node(node); 98362306a36Sopenharmony_ci} 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_cistatic void binder_inc_node_tmpref_ilocked(struct binder_node *node) 98662306a36Sopenharmony_ci{ 98762306a36Sopenharmony_ci /* 98862306a36Sopenharmony_ci * No call to binder_inc_node() is needed since we 98962306a36Sopenharmony_ci * don't need to inform userspace of any changes to 99062306a36Sopenharmony_ci * tmp_refs 99162306a36Sopenharmony_ci */ 99262306a36Sopenharmony_ci node->tmp_refs++; 99362306a36Sopenharmony_ci} 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci/** 99662306a36Sopenharmony_ci * binder_inc_node_tmpref() - take a temporary reference on node 99762306a36Sopenharmony_ci * @node: node to reference 99862306a36Sopenharmony_ci * 99962306a36Sopenharmony_ci * Take reference on node to prevent the node from being freed 100062306a36Sopenharmony_ci * while referenced only by a local variable. The inner lock is 100162306a36Sopenharmony_ci * needed to serialize with the node work on the queue (which 100262306a36Sopenharmony_ci * isn't needed after the node is dead). If the node is dead 100362306a36Sopenharmony_ci * (node->proc is NULL), use binder_dead_nodes_lock to protect 100462306a36Sopenharmony_ci * node->tmp_refs against dead-node-only cases where the node 100562306a36Sopenharmony_ci * lock cannot be acquired (eg traversing the dead node list to 100662306a36Sopenharmony_ci * print nodes) 100762306a36Sopenharmony_ci */ 100862306a36Sopenharmony_cistatic void binder_inc_node_tmpref(struct binder_node *node) 100962306a36Sopenharmony_ci{ 101062306a36Sopenharmony_ci binder_node_lock(node); 101162306a36Sopenharmony_ci if (node->proc) 101262306a36Sopenharmony_ci binder_inner_proc_lock(node->proc); 101362306a36Sopenharmony_ci else 101462306a36Sopenharmony_ci spin_lock(&binder_dead_nodes_lock); 101562306a36Sopenharmony_ci binder_inc_node_tmpref_ilocked(node); 101662306a36Sopenharmony_ci if (node->proc) 101762306a36Sopenharmony_ci binder_inner_proc_unlock(node->proc); 101862306a36Sopenharmony_ci else 101962306a36Sopenharmony_ci spin_unlock(&binder_dead_nodes_lock); 102062306a36Sopenharmony_ci binder_node_unlock(node); 102162306a36Sopenharmony_ci} 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci/** 102462306a36Sopenharmony_ci * binder_dec_node_tmpref() - remove a temporary reference on node 102562306a36Sopenharmony_ci * @node: node to reference 102662306a36Sopenharmony_ci * 102762306a36Sopenharmony_ci * Release temporary reference on node taken via binder_inc_node_tmpref() 102862306a36Sopenharmony_ci */ 102962306a36Sopenharmony_cistatic void binder_dec_node_tmpref(struct binder_node *node) 103062306a36Sopenharmony_ci{ 103162306a36Sopenharmony_ci bool free_node; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci binder_node_inner_lock(node); 103462306a36Sopenharmony_ci if (!node->proc) 103562306a36Sopenharmony_ci spin_lock(&binder_dead_nodes_lock); 103662306a36Sopenharmony_ci else 103762306a36Sopenharmony_ci __acquire(&binder_dead_nodes_lock); 103862306a36Sopenharmony_ci node->tmp_refs--; 103962306a36Sopenharmony_ci BUG_ON(node->tmp_refs < 0); 104062306a36Sopenharmony_ci if (!node->proc) 104162306a36Sopenharmony_ci spin_unlock(&binder_dead_nodes_lock); 104262306a36Sopenharmony_ci else 104362306a36Sopenharmony_ci __release(&binder_dead_nodes_lock); 104462306a36Sopenharmony_ci /* 104562306a36Sopenharmony_ci * Call binder_dec_node() to check if all refcounts are 0 104662306a36Sopenharmony_ci * and cleanup is needed. Calling with strong=0 and internal=1 104762306a36Sopenharmony_ci * causes no actual reference to be released in binder_dec_node(). 104862306a36Sopenharmony_ci * If that changes, a change is needed here too. 104962306a36Sopenharmony_ci */ 105062306a36Sopenharmony_ci free_node = binder_dec_node_nilocked(node, 0, 1); 105162306a36Sopenharmony_ci binder_node_inner_unlock(node); 105262306a36Sopenharmony_ci if (free_node) 105362306a36Sopenharmony_ci binder_free_node(node); 105462306a36Sopenharmony_ci} 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_cistatic void binder_put_node(struct binder_node *node) 105762306a36Sopenharmony_ci{ 105862306a36Sopenharmony_ci binder_dec_node_tmpref(node); 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_cistatic struct binder_ref *binder_get_ref_olocked(struct binder_proc *proc, 106262306a36Sopenharmony_ci u32 desc, bool need_strong_ref) 106362306a36Sopenharmony_ci{ 106462306a36Sopenharmony_ci struct rb_node *n = proc->refs_by_desc.rb_node; 106562306a36Sopenharmony_ci struct binder_ref *ref; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci while (n) { 106862306a36Sopenharmony_ci ref = rb_entry(n, struct binder_ref, rb_node_desc); 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci if (desc < ref->data.desc) { 107162306a36Sopenharmony_ci n = n->rb_left; 107262306a36Sopenharmony_ci } else if (desc > ref->data.desc) { 107362306a36Sopenharmony_ci n = n->rb_right; 107462306a36Sopenharmony_ci } else if (need_strong_ref && !ref->data.strong) { 107562306a36Sopenharmony_ci binder_user_error("tried to use weak ref as strong ref\n"); 107662306a36Sopenharmony_ci return NULL; 107762306a36Sopenharmony_ci } else { 107862306a36Sopenharmony_ci return ref; 107962306a36Sopenharmony_ci } 108062306a36Sopenharmony_ci } 108162306a36Sopenharmony_ci return NULL; 108262306a36Sopenharmony_ci} 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci/** 108562306a36Sopenharmony_ci * binder_get_ref_for_node_olocked() - get the ref associated with given node 108662306a36Sopenharmony_ci * @proc: binder_proc that owns the ref 108762306a36Sopenharmony_ci * @node: binder_node of target 108862306a36Sopenharmony_ci * @new_ref: newly allocated binder_ref to be initialized or %NULL 108962306a36Sopenharmony_ci * 109062306a36Sopenharmony_ci * Look up the ref for the given node and return it if it exists 109162306a36Sopenharmony_ci * 109262306a36Sopenharmony_ci * If it doesn't exist and the caller provides a newly allocated 109362306a36Sopenharmony_ci * ref, initialize the fields of the newly allocated ref and insert 109462306a36Sopenharmony_ci * into the given proc rb_trees and node refs list. 109562306a36Sopenharmony_ci * 109662306a36Sopenharmony_ci * Return: the ref for node. It is possible that another thread 109762306a36Sopenharmony_ci * allocated/initialized the ref first in which case the 109862306a36Sopenharmony_ci * returned ref would be different than the passed-in 109962306a36Sopenharmony_ci * new_ref. new_ref must be kfree'd by the caller in 110062306a36Sopenharmony_ci * this case. 110162306a36Sopenharmony_ci */ 110262306a36Sopenharmony_cistatic struct binder_ref *binder_get_ref_for_node_olocked( 110362306a36Sopenharmony_ci struct binder_proc *proc, 110462306a36Sopenharmony_ci struct binder_node *node, 110562306a36Sopenharmony_ci struct binder_ref *new_ref) 110662306a36Sopenharmony_ci{ 110762306a36Sopenharmony_ci struct binder_context *context = proc->context; 110862306a36Sopenharmony_ci struct rb_node **p = &proc->refs_by_node.rb_node; 110962306a36Sopenharmony_ci struct rb_node *parent = NULL; 111062306a36Sopenharmony_ci struct binder_ref *ref; 111162306a36Sopenharmony_ci struct rb_node *n; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci while (*p) { 111462306a36Sopenharmony_ci parent = *p; 111562306a36Sopenharmony_ci ref = rb_entry(parent, struct binder_ref, rb_node_node); 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci if (node < ref->node) 111862306a36Sopenharmony_ci p = &(*p)->rb_left; 111962306a36Sopenharmony_ci else if (node > ref->node) 112062306a36Sopenharmony_ci p = &(*p)->rb_right; 112162306a36Sopenharmony_ci else 112262306a36Sopenharmony_ci return ref; 112362306a36Sopenharmony_ci } 112462306a36Sopenharmony_ci if (!new_ref) 112562306a36Sopenharmony_ci return NULL; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci binder_stats_created(BINDER_STAT_REF); 112862306a36Sopenharmony_ci new_ref->data.debug_id = atomic_inc_return(&binder_last_id); 112962306a36Sopenharmony_ci new_ref->proc = proc; 113062306a36Sopenharmony_ci new_ref->node = node; 113162306a36Sopenharmony_ci rb_link_node(&new_ref->rb_node_node, parent, p); 113262306a36Sopenharmony_ci rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node); 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1; 113562306a36Sopenharmony_ci for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { 113662306a36Sopenharmony_ci ref = rb_entry(n, struct binder_ref, rb_node_desc); 113762306a36Sopenharmony_ci if (ref->data.desc > new_ref->data.desc) 113862306a36Sopenharmony_ci break; 113962306a36Sopenharmony_ci new_ref->data.desc = ref->data.desc + 1; 114062306a36Sopenharmony_ci } 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci p = &proc->refs_by_desc.rb_node; 114362306a36Sopenharmony_ci while (*p) { 114462306a36Sopenharmony_ci parent = *p; 114562306a36Sopenharmony_ci ref = rb_entry(parent, struct binder_ref, rb_node_desc); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci if (new_ref->data.desc < ref->data.desc) 114862306a36Sopenharmony_ci p = &(*p)->rb_left; 114962306a36Sopenharmony_ci else if (new_ref->data.desc > ref->data.desc) 115062306a36Sopenharmony_ci p = &(*p)->rb_right; 115162306a36Sopenharmony_ci else 115262306a36Sopenharmony_ci BUG(); 115362306a36Sopenharmony_ci } 115462306a36Sopenharmony_ci rb_link_node(&new_ref->rb_node_desc, parent, p); 115562306a36Sopenharmony_ci rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci binder_node_lock(node); 115862306a36Sopenharmony_ci hlist_add_head(&new_ref->node_entry, &node->refs); 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_INTERNAL_REFS, 116162306a36Sopenharmony_ci "%d new ref %d desc %d for node %d\n", 116262306a36Sopenharmony_ci proc->pid, new_ref->data.debug_id, new_ref->data.desc, 116362306a36Sopenharmony_ci node->debug_id); 116462306a36Sopenharmony_ci binder_node_unlock(node); 116562306a36Sopenharmony_ci return new_ref; 116662306a36Sopenharmony_ci} 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_cistatic void binder_cleanup_ref_olocked(struct binder_ref *ref) 116962306a36Sopenharmony_ci{ 117062306a36Sopenharmony_ci bool delete_node = false; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_INTERNAL_REFS, 117362306a36Sopenharmony_ci "%d delete ref %d desc %d for node %d\n", 117462306a36Sopenharmony_ci ref->proc->pid, ref->data.debug_id, ref->data.desc, 117562306a36Sopenharmony_ci ref->node->debug_id); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc); 117862306a36Sopenharmony_ci rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node); 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci binder_node_inner_lock(ref->node); 118162306a36Sopenharmony_ci if (ref->data.strong) 118262306a36Sopenharmony_ci binder_dec_node_nilocked(ref->node, 1, 1); 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci hlist_del(&ref->node_entry); 118562306a36Sopenharmony_ci delete_node = binder_dec_node_nilocked(ref->node, 0, 1); 118662306a36Sopenharmony_ci binder_node_inner_unlock(ref->node); 118762306a36Sopenharmony_ci /* 118862306a36Sopenharmony_ci * Clear ref->node unless we want the caller to free the node 118962306a36Sopenharmony_ci */ 119062306a36Sopenharmony_ci if (!delete_node) { 119162306a36Sopenharmony_ci /* 119262306a36Sopenharmony_ci * The caller uses ref->node to determine 119362306a36Sopenharmony_ci * whether the node needs to be freed. Clear 119462306a36Sopenharmony_ci * it since the node is still alive. 119562306a36Sopenharmony_ci */ 119662306a36Sopenharmony_ci ref->node = NULL; 119762306a36Sopenharmony_ci } 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci if (ref->death) { 120062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_BINDER, 120162306a36Sopenharmony_ci "%d delete ref %d desc %d has death notification\n", 120262306a36Sopenharmony_ci ref->proc->pid, ref->data.debug_id, 120362306a36Sopenharmony_ci ref->data.desc); 120462306a36Sopenharmony_ci binder_dequeue_work(ref->proc, &ref->death->work); 120562306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_DEATH); 120662306a36Sopenharmony_ci } 120762306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_REF); 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci/** 121162306a36Sopenharmony_ci * binder_inc_ref_olocked() - increment the ref for given handle 121262306a36Sopenharmony_ci * @ref: ref to be incremented 121362306a36Sopenharmony_ci * @strong: if true, strong increment, else weak 121462306a36Sopenharmony_ci * @target_list: list to queue node work on 121562306a36Sopenharmony_ci * 121662306a36Sopenharmony_ci * Increment the ref. @ref->proc->outer_lock must be held on entry 121762306a36Sopenharmony_ci * 121862306a36Sopenharmony_ci * Return: 0, if successful, else errno 121962306a36Sopenharmony_ci */ 122062306a36Sopenharmony_cistatic int binder_inc_ref_olocked(struct binder_ref *ref, int strong, 122162306a36Sopenharmony_ci struct list_head *target_list) 122262306a36Sopenharmony_ci{ 122362306a36Sopenharmony_ci int ret; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci if (strong) { 122662306a36Sopenharmony_ci if (ref->data.strong == 0) { 122762306a36Sopenharmony_ci ret = binder_inc_node(ref->node, 1, 1, target_list); 122862306a36Sopenharmony_ci if (ret) 122962306a36Sopenharmony_ci return ret; 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci ref->data.strong++; 123262306a36Sopenharmony_ci } else { 123362306a36Sopenharmony_ci if (ref->data.weak == 0) { 123462306a36Sopenharmony_ci ret = binder_inc_node(ref->node, 0, 1, target_list); 123562306a36Sopenharmony_ci if (ret) 123662306a36Sopenharmony_ci return ret; 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci ref->data.weak++; 123962306a36Sopenharmony_ci } 124062306a36Sopenharmony_ci return 0; 124162306a36Sopenharmony_ci} 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci/** 124462306a36Sopenharmony_ci * binder_dec_ref_olocked() - dec the ref for given handle 124562306a36Sopenharmony_ci * @ref: ref to be decremented 124662306a36Sopenharmony_ci * @strong: if true, strong decrement, else weak 124762306a36Sopenharmony_ci * 124862306a36Sopenharmony_ci * Decrement the ref. 124962306a36Sopenharmony_ci * 125062306a36Sopenharmony_ci * Return: %true if ref is cleaned up and ready to be freed. 125162306a36Sopenharmony_ci */ 125262306a36Sopenharmony_cistatic bool binder_dec_ref_olocked(struct binder_ref *ref, int strong) 125362306a36Sopenharmony_ci{ 125462306a36Sopenharmony_ci if (strong) { 125562306a36Sopenharmony_ci if (ref->data.strong == 0) { 125662306a36Sopenharmony_ci binder_user_error("%d invalid dec strong, ref %d desc %d s %d w %d\n", 125762306a36Sopenharmony_ci ref->proc->pid, ref->data.debug_id, 125862306a36Sopenharmony_ci ref->data.desc, ref->data.strong, 125962306a36Sopenharmony_ci ref->data.weak); 126062306a36Sopenharmony_ci return false; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci ref->data.strong--; 126362306a36Sopenharmony_ci if (ref->data.strong == 0) 126462306a36Sopenharmony_ci binder_dec_node(ref->node, strong, 1); 126562306a36Sopenharmony_ci } else { 126662306a36Sopenharmony_ci if (ref->data.weak == 0) { 126762306a36Sopenharmony_ci binder_user_error("%d invalid dec weak, ref %d desc %d s %d w %d\n", 126862306a36Sopenharmony_ci ref->proc->pid, ref->data.debug_id, 126962306a36Sopenharmony_ci ref->data.desc, ref->data.strong, 127062306a36Sopenharmony_ci ref->data.weak); 127162306a36Sopenharmony_ci return false; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci ref->data.weak--; 127462306a36Sopenharmony_ci } 127562306a36Sopenharmony_ci if (ref->data.strong == 0 && ref->data.weak == 0) { 127662306a36Sopenharmony_ci binder_cleanup_ref_olocked(ref); 127762306a36Sopenharmony_ci return true; 127862306a36Sopenharmony_ci } 127962306a36Sopenharmony_ci return false; 128062306a36Sopenharmony_ci} 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci/** 128362306a36Sopenharmony_ci * binder_get_node_from_ref() - get the node from the given proc/desc 128462306a36Sopenharmony_ci * @proc: proc containing the ref 128562306a36Sopenharmony_ci * @desc: the handle associated with the ref 128662306a36Sopenharmony_ci * @need_strong_ref: if true, only return node if ref is strong 128762306a36Sopenharmony_ci * @rdata: the id/refcount data for the ref 128862306a36Sopenharmony_ci * 128962306a36Sopenharmony_ci * Given a proc and ref handle, return the associated binder_node 129062306a36Sopenharmony_ci * 129162306a36Sopenharmony_ci * Return: a binder_node or NULL if not found or not strong when strong required 129262306a36Sopenharmony_ci */ 129362306a36Sopenharmony_cistatic struct binder_node *binder_get_node_from_ref( 129462306a36Sopenharmony_ci struct binder_proc *proc, 129562306a36Sopenharmony_ci u32 desc, bool need_strong_ref, 129662306a36Sopenharmony_ci struct binder_ref_data *rdata) 129762306a36Sopenharmony_ci{ 129862306a36Sopenharmony_ci struct binder_node *node; 129962306a36Sopenharmony_ci struct binder_ref *ref; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci binder_proc_lock(proc); 130262306a36Sopenharmony_ci ref = binder_get_ref_olocked(proc, desc, need_strong_ref); 130362306a36Sopenharmony_ci if (!ref) 130462306a36Sopenharmony_ci goto err_no_ref; 130562306a36Sopenharmony_ci node = ref->node; 130662306a36Sopenharmony_ci /* 130762306a36Sopenharmony_ci * Take an implicit reference on the node to ensure 130862306a36Sopenharmony_ci * it stays alive until the call to binder_put_node() 130962306a36Sopenharmony_ci */ 131062306a36Sopenharmony_ci binder_inc_node_tmpref(node); 131162306a36Sopenharmony_ci if (rdata) 131262306a36Sopenharmony_ci *rdata = ref->data; 131362306a36Sopenharmony_ci binder_proc_unlock(proc); 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci return node; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_cierr_no_ref: 131862306a36Sopenharmony_ci binder_proc_unlock(proc); 131962306a36Sopenharmony_ci return NULL; 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci/** 132362306a36Sopenharmony_ci * binder_free_ref() - free the binder_ref 132462306a36Sopenharmony_ci * @ref: ref to free 132562306a36Sopenharmony_ci * 132662306a36Sopenharmony_ci * Free the binder_ref. Free the binder_node indicated by ref->node 132762306a36Sopenharmony_ci * (if non-NULL) and the binder_ref_death indicated by ref->death. 132862306a36Sopenharmony_ci */ 132962306a36Sopenharmony_cistatic void binder_free_ref(struct binder_ref *ref) 133062306a36Sopenharmony_ci{ 133162306a36Sopenharmony_ci if (ref->node) 133262306a36Sopenharmony_ci binder_free_node(ref->node); 133362306a36Sopenharmony_ci kfree(ref->death); 133462306a36Sopenharmony_ci kfree(ref); 133562306a36Sopenharmony_ci} 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci/** 133862306a36Sopenharmony_ci * binder_update_ref_for_handle() - inc/dec the ref for given handle 133962306a36Sopenharmony_ci * @proc: proc containing the ref 134062306a36Sopenharmony_ci * @desc: the handle associated with the ref 134162306a36Sopenharmony_ci * @increment: true=inc reference, false=dec reference 134262306a36Sopenharmony_ci * @strong: true=strong reference, false=weak reference 134362306a36Sopenharmony_ci * @rdata: the id/refcount data for the ref 134462306a36Sopenharmony_ci * 134562306a36Sopenharmony_ci * Given a proc and ref handle, increment or decrement the ref 134662306a36Sopenharmony_ci * according to "increment" arg. 134762306a36Sopenharmony_ci * 134862306a36Sopenharmony_ci * Return: 0 if successful, else errno 134962306a36Sopenharmony_ci */ 135062306a36Sopenharmony_cistatic int binder_update_ref_for_handle(struct binder_proc *proc, 135162306a36Sopenharmony_ci uint32_t desc, bool increment, bool strong, 135262306a36Sopenharmony_ci struct binder_ref_data *rdata) 135362306a36Sopenharmony_ci{ 135462306a36Sopenharmony_ci int ret = 0; 135562306a36Sopenharmony_ci struct binder_ref *ref; 135662306a36Sopenharmony_ci bool delete_ref = false; 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci binder_proc_lock(proc); 135962306a36Sopenharmony_ci ref = binder_get_ref_olocked(proc, desc, strong); 136062306a36Sopenharmony_ci if (!ref) { 136162306a36Sopenharmony_ci ret = -EINVAL; 136262306a36Sopenharmony_ci goto err_no_ref; 136362306a36Sopenharmony_ci } 136462306a36Sopenharmony_ci if (increment) 136562306a36Sopenharmony_ci ret = binder_inc_ref_olocked(ref, strong, NULL); 136662306a36Sopenharmony_ci else 136762306a36Sopenharmony_ci delete_ref = binder_dec_ref_olocked(ref, strong); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci if (rdata) 137062306a36Sopenharmony_ci *rdata = ref->data; 137162306a36Sopenharmony_ci binder_proc_unlock(proc); 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci if (delete_ref) 137462306a36Sopenharmony_ci binder_free_ref(ref); 137562306a36Sopenharmony_ci return ret; 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_cierr_no_ref: 137862306a36Sopenharmony_ci binder_proc_unlock(proc); 137962306a36Sopenharmony_ci return ret; 138062306a36Sopenharmony_ci} 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci/** 138362306a36Sopenharmony_ci * binder_dec_ref_for_handle() - dec the ref for given handle 138462306a36Sopenharmony_ci * @proc: proc containing the ref 138562306a36Sopenharmony_ci * @desc: the handle associated with the ref 138662306a36Sopenharmony_ci * @strong: true=strong reference, false=weak reference 138762306a36Sopenharmony_ci * @rdata: the id/refcount data for the ref 138862306a36Sopenharmony_ci * 138962306a36Sopenharmony_ci * Just calls binder_update_ref_for_handle() to decrement the ref. 139062306a36Sopenharmony_ci * 139162306a36Sopenharmony_ci * Return: 0 if successful, else errno 139262306a36Sopenharmony_ci */ 139362306a36Sopenharmony_cistatic int binder_dec_ref_for_handle(struct binder_proc *proc, 139462306a36Sopenharmony_ci uint32_t desc, bool strong, struct binder_ref_data *rdata) 139562306a36Sopenharmony_ci{ 139662306a36Sopenharmony_ci return binder_update_ref_for_handle(proc, desc, false, strong, rdata); 139762306a36Sopenharmony_ci} 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci/** 140162306a36Sopenharmony_ci * binder_inc_ref_for_node() - increment the ref for given proc/node 140262306a36Sopenharmony_ci * @proc: proc containing the ref 140362306a36Sopenharmony_ci * @node: target node 140462306a36Sopenharmony_ci * @strong: true=strong reference, false=weak reference 140562306a36Sopenharmony_ci * @target_list: worklist to use if node is incremented 140662306a36Sopenharmony_ci * @rdata: the id/refcount data for the ref 140762306a36Sopenharmony_ci * 140862306a36Sopenharmony_ci * Given a proc and node, increment the ref. Create the ref if it 140962306a36Sopenharmony_ci * doesn't already exist 141062306a36Sopenharmony_ci * 141162306a36Sopenharmony_ci * Return: 0 if successful, else errno 141262306a36Sopenharmony_ci */ 141362306a36Sopenharmony_cistatic int binder_inc_ref_for_node(struct binder_proc *proc, 141462306a36Sopenharmony_ci struct binder_node *node, 141562306a36Sopenharmony_ci bool strong, 141662306a36Sopenharmony_ci struct list_head *target_list, 141762306a36Sopenharmony_ci struct binder_ref_data *rdata) 141862306a36Sopenharmony_ci{ 141962306a36Sopenharmony_ci struct binder_ref *ref; 142062306a36Sopenharmony_ci struct binder_ref *new_ref = NULL; 142162306a36Sopenharmony_ci int ret = 0; 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci binder_proc_lock(proc); 142462306a36Sopenharmony_ci ref = binder_get_ref_for_node_olocked(proc, node, NULL); 142562306a36Sopenharmony_ci if (!ref) { 142662306a36Sopenharmony_ci binder_proc_unlock(proc); 142762306a36Sopenharmony_ci new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); 142862306a36Sopenharmony_ci if (!new_ref) 142962306a36Sopenharmony_ci return -ENOMEM; 143062306a36Sopenharmony_ci binder_proc_lock(proc); 143162306a36Sopenharmony_ci ref = binder_get_ref_for_node_olocked(proc, node, new_ref); 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci ret = binder_inc_ref_olocked(ref, strong, target_list); 143462306a36Sopenharmony_ci *rdata = ref->data; 143562306a36Sopenharmony_ci if (ret && ref == new_ref) { 143662306a36Sopenharmony_ci /* 143762306a36Sopenharmony_ci * Cleanup the failed reference here as the target 143862306a36Sopenharmony_ci * could now be dead and have already released its 143962306a36Sopenharmony_ci * references by now. Calling on the new reference 144062306a36Sopenharmony_ci * with strong=0 and a tmp_refs will not decrement 144162306a36Sopenharmony_ci * the node. The new_ref gets kfree'd below. 144262306a36Sopenharmony_ci */ 144362306a36Sopenharmony_ci binder_cleanup_ref_olocked(new_ref); 144462306a36Sopenharmony_ci ref = NULL; 144562306a36Sopenharmony_ci } 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci binder_proc_unlock(proc); 144862306a36Sopenharmony_ci if (new_ref && ref != new_ref) 144962306a36Sopenharmony_ci /* 145062306a36Sopenharmony_ci * Another thread created the ref first so 145162306a36Sopenharmony_ci * free the one we allocated 145262306a36Sopenharmony_ci */ 145362306a36Sopenharmony_ci kfree(new_ref); 145462306a36Sopenharmony_ci return ret; 145562306a36Sopenharmony_ci} 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_cistatic void binder_pop_transaction_ilocked(struct binder_thread *target_thread, 145862306a36Sopenharmony_ci struct binder_transaction *t) 145962306a36Sopenharmony_ci{ 146062306a36Sopenharmony_ci BUG_ON(!target_thread); 146162306a36Sopenharmony_ci assert_spin_locked(&target_thread->proc->inner_lock); 146262306a36Sopenharmony_ci BUG_ON(target_thread->transaction_stack != t); 146362306a36Sopenharmony_ci BUG_ON(target_thread->transaction_stack->from != target_thread); 146462306a36Sopenharmony_ci target_thread->transaction_stack = 146562306a36Sopenharmony_ci target_thread->transaction_stack->from_parent; 146662306a36Sopenharmony_ci t->from = NULL; 146762306a36Sopenharmony_ci} 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci/** 147062306a36Sopenharmony_ci * binder_thread_dec_tmpref() - decrement thread->tmp_ref 147162306a36Sopenharmony_ci * @thread: thread to decrement 147262306a36Sopenharmony_ci * 147362306a36Sopenharmony_ci * A thread needs to be kept alive while being used to create or 147462306a36Sopenharmony_ci * handle a transaction. binder_get_txn_from() is used to safely 147562306a36Sopenharmony_ci * extract t->from from a binder_transaction and keep the thread 147662306a36Sopenharmony_ci * indicated by t->from from being freed. When done with that 147762306a36Sopenharmony_ci * binder_thread, this function is called to decrement the 147862306a36Sopenharmony_ci * tmp_ref and free if appropriate (thread has been released 147962306a36Sopenharmony_ci * and no transaction being processed by the driver) 148062306a36Sopenharmony_ci */ 148162306a36Sopenharmony_cistatic void binder_thread_dec_tmpref(struct binder_thread *thread) 148262306a36Sopenharmony_ci{ 148362306a36Sopenharmony_ci /* 148462306a36Sopenharmony_ci * atomic is used to protect the counter value while 148562306a36Sopenharmony_ci * it cannot reach zero or thread->is_dead is false 148662306a36Sopenharmony_ci */ 148762306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 148862306a36Sopenharmony_ci atomic_dec(&thread->tmp_ref); 148962306a36Sopenharmony_ci if (thread->is_dead && !atomic_read(&thread->tmp_ref)) { 149062306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 149162306a36Sopenharmony_ci binder_free_thread(thread); 149262306a36Sopenharmony_ci return; 149362306a36Sopenharmony_ci } 149462306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 149562306a36Sopenharmony_ci} 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci/** 149862306a36Sopenharmony_ci * binder_proc_dec_tmpref() - decrement proc->tmp_ref 149962306a36Sopenharmony_ci * @proc: proc to decrement 150062306a36Sopenharmony_ci * 150162306a36Sopenharmony_ci * A binder_proc needs to be kept alive while being used to create or 150262306a36Sopenharmony_ci * handle a transaction. proc->tmp_ref is incremented when 150362306a36Sopenharmony_ci * creating a new transaction or the binder_proc is currently in-use 150462306a36Sopenharmony_ci * by threads that are being released. When done with the binder_proc, 150562306a36Sopenharmony_ci * this function is called to decrement the counter and free the 150662306a36Sopenharmony_ci * proc if appropriate (proc has been released, all threads have 150762306a36Sopenharmony_ci * been released and not currenly in-use to process a transaction). 150862306a36Sopenharmony_ci */ 150962306a36Sopenharmony_cistatic void binder_proc_dec_tmpref(struct binder_proc *proc) 151062306a36Sopenharmony_ci{ 151162306a36Sopenharmony_ci binder_inner_proc_lock(proc); 151262306a36Sopenharmony_ci proc->tmp_ref--; 151362306a36Sopenharmony_ci if (proc->is_dead && RB_EMPTY_ROOT(&proc->threads) && 151462306a36Sopenharmony_ci !proc->tmp_ref) { 151562306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 151662306a36Sopenharmony_ci binder_free_proc(proc); 151762306a36Sopenharmony_ci return; 151862306a36Sopenharmony_ci } 151962306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 152062306a36Sopenharmony_ci} 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci/** 152362306a36Sopenharmony_ci * binder_get_txn_from() - safely extract the "from" thread in transaction 152462306a36Sopenharmony_ci * @t: binder transaction for t->from 152562306a36Sopenharmony_ci * 152662306a36Sopenharmony_ci * Atomically return the "from" thread and increment the tmp_ref 152762306a36Sopenharmony_ci * count for the thread to ensure it stays alive until 152862306a36Sopenharmony_ci * binder_thread_dec_tmpref() is called. 152962306a36Sopenharmony_ci * 153062306a36Sopenharmony_ci * Return: the value of t->from 153162306a36Sopenharmony_ci */ 153262306a36Sopenharmony_cistatic struct binder_thread *binder_get_txn_from( 153362306a36Sopenharmony_ci struct binder_transaction *t) 153462306a36Sopenharmony_ci{ 153562306a36Sopenharmony_ci struct binder_thread *from; 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci spin_lock(&t->lock); 153862306a36Sopenharmony_ci from = t->from; 153962306a36Sopenharmony_ci if (from) 154062306a36Sopenharmony_ci atomic_inc(&from->tmp_ref); 154162306a36Sopenharmony_ci spin_unlock(&t->lock); 154262306a36Sopenharmony_ci return from; 154362306a36Sopenharmony_ci} 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ci/** 154662306a36Sopenharmony_ci * binder_get_txn_from_and_acq_inner() - get t->from and acquire inner lock 154762306a36Sopenharmony_ci * @t: binder transaction for t->from 154862306a36Sopenharmony_ci * 154962306a36Sopenharmony_ci * Same as binder_get_txn_from() except it also acquires the proc->inner_lock 155062306a36Sopenharmony_ci * to guarantee that the thread cannot be released while operating on it. 155162306a36Sopenharmony_ci * The caller must call binder_inner_proc_unlock() to release the inner lock 155262306a36Sopenharmony_ci * as well as call binder_dec_thread_txn() to release the reference. 155362306a36Sopenharmony_ci * 155462306a36Sopenharmony_ci * Return: the value of t->from 155562306a36Sopenharmony_ci */ 155662306a36Sopenharmony_cistatic struct binder_thread *binder_get_txn_from_and_acq_inner( 155762306a36Sopenharmony_ci struct binder_transaction *t) 155862306a36Sopenharmony_ci __acquires(&t->from->proc->inner_lock) 155962306a36Sopenharmony_ci{ 156062306a36Sopenharmony_ci struct binder_thread *from; 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci from = binder_get_txn_from(t); 156362306a36Sopenharmony_ci if (!from) { 156462306a36Sopenharmony_ci __acquire(&from->proc->inner_lock); 156562306a36Sopenharmony_ci return NULL; 156662306a36Sopenharmony_ci } 156762306a36Sopenharmony_ci binder_inner_proc_lock(from->proc); 156862306a36Sopenharmony_ci if (t->from) { 156962306a36Sopenharmony_ci BUG_ON(from != t->from); 157062306a36Sopenharmony_ci return from; 157162306a36Sopenharmony_ci } 157262306a36Sopenharmony_ci binder_inner_proc_unlock(from->proc); 157362306a36Sopenharmony_ci __acquire(&from->proc->inner_lock); 157462306a36Sopenharmony_ci binder_thread_dec_tmpref(from); 157562306a36Sopenharmony_ci return NULL; 157662306a36Sopenharmony_ci} 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci/** 157962306a36Sopenharmony_ci * binder_free_txn_fixups() - free unprocessed fd fixups 158062306a36Sopenharmony_ci * @t: binder transaction for t->from 158162306a36Sopenharmony_ci * 158262306a36Sopenharmony_ci * If the transaction is being torn down prior to being 158362306a36Sopenharmony_ci * processed by the target process, free all of the 158462306a36Sopenharmony_ci * fd fixups and fput the file structs. It is safe to 158562306a36Sopenharmony_ci * call this function after the fixups have been 158662306a36Sopenharmony_ci * processed -- in that case, the list will be empty. 158762306a36Sopenharmony_ci */ 158862306a36Sopenharmony_cistatic void binder_free_txn_fixups(struct binder_transaction *t) 158962306a36Sopenharmony_ci{ 159062306a36Sopenharmony_ci struct binder_txn_fd_fixup *fixup, *tmp; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci list_for_each_entry_safe(fixup, tmp, &t->fd_fixups, fixup_entry) { 159362306a36Sopenharmony_ci fput(fixup->file); 159462306a36Sopenharmony_ci if (fixup->target_fd >= 0) 159562306a36Sopenharmony_ci put_unused_fd(fixup->target_fd); 159662306a36Sopenharmony_ci list_del(&fixup->fixup_entry); 159762306a36Sopenharmony_ci kfree(fixup); 159862306a36Sopenharmony_ci } 159962306a36Sopenharmony_ci} 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_cistatic void binder_txn_latency_free(struct binder_transaction *t) 160262306a36Sopenharmony_ci{ 160362306a36Sopenharmony_ci int from_proc, from_thread, to_proc, to_thread; 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci spin_lock(&t->lock); 160662306a36Sopenharmony_ci from_proc = t->from ? t->from->proc->pid : 0; 160762306a36Sopenharmony_ci from_thread = t->from ? t->from->pid : 0; 160862306a36Sopenharmony_ci to_proc = t->to_proc ? t->to_proc->pid : 0; 160962306a36Sopenharmony_ci to_thread = t->to_thread ? t->to_thread->pid : 0; 161062306a36Sopenharmony_ci spin_unlock(&t->lock); 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread); 161362306a36Sopenharmony_ci} 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_cistatic void binder_free_transaction(struct binder_transaction *t) 161662306a36Sopenharmony_ci{ 161762306a36Sopenharmony_ci struct binder_proc *target_proc = t->to_proc; 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci if (target_proc) { 162062306a36Sopenharmony_ci binder_inner_proc_lock(target_proc); 162162306a36Sopenharmony_ci target_proc->outstanding_txns--; 162262306a36Sopenharmony_ci if (target_proc->outstanding_txns < 0) 162362306a36Sopenharmony_ci pr_warn("%s: Unexpected outstanding_txns %d\n", 162462306a36Sopenharmony_ci __func__, target_proc->outstanding_txns); 162562306a36Sopenharmony_ci if (!target_proc->outstanding_txns && target_proc->is_frozen) 162662306a36Sopenharmony_ci wake_up_interruptible_all(&target_proc->freeze_wait); 162762306a36Sopenharmony_ci if (t->buffer) 162862306a36Sopenharmony_ci t->buffer->transaction = NULL; 162962306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 163062306a36Sopenharmony_ci } 163162306a36Sopenharmony_ci if (trace_binder_txn_latency_free_enabled()) 163262306a36Sopenharmony_ci binder_txn_latency_free(t); 163362306a36Sopenharmony_ci /* 163462306a36Sopenharmony_ci * If the transaction has no target_proc, then 163562306a36Sopenharmony_ci * t->buffer->transaction has already been cleared. 163662306a36Sopenharmony_ci */ 163762306a36Sopenharmony_ci binder_free_txn_fixups(t); 163862306a36Sopenharmony_ci kfree(t); 163962306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_TRANSACTION); 164062306a36Sopenharmony_ci} 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_cistatic void binder_send_failed_reply(struct binder_transaction *t, 164362306a36Sopenharmony_ci uint32_t error_code) 164462306a36Sopenharmony_ci{ 164562306a36Sopenharmony_ci struct binder_thread *target_thread; 164662306a36Sopenharmony_ci struct binder_transaction *next; 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci BUG_ON(t->flags & TF_ONE_WAY); 164962306a36Sopenharmony_ci while (1) { 165062306a36Sopenharmony_ci target_thread = binder_get_txn_from_and_acq_inner(t); 165162306a36Sopenharmony_ci if (target_thread) { 165262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, 165362306a36Sopenharmony_ci "send failed reply for transaction %d to %d:%d\n", 165462306a36Sopenharmony_ci t->debug_id, 165562306a36Sopenharmony_ci target_thread->proc->pid, 165662306a36Sopenharmony_ci target_thread->pid); 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci binder_pop_transaction_ilocked(target_thread, t); 165962306a36Sopenharmony_ci if (target_thread->reply_error.cmd == BR_OK) { 166062306a36Sopenharmony_ci target_thread->reply_error.cmd = error_code; 166162306a36Sopenharmony_ci binder_enqueue_thread_work_ilocked( 166262306a36Sopenharmony_ci target_thread, 166362306a36Sopenharmony_ci &target_thread->reply_error.work); 166462306a36Sopenharmony_ci wake_up_interruptible(&target_thread->wait); 166562306a36Sopenharmony_ci } else { 166662306a36Sopenharmony_ci /* 166762306a36Sopenharmony_ci * Cannot get here for normal operation, but 166862306a36Sopenharmony_ci * we can if multiple synchronous transactions 166962306a36Sopenharmony_ci * are sent without blocking for responses. 167062306a36Sopenharmony_ci * Just ignore the 2nd error in this case. 167162306a36Sopenharmony_ci */ 167262306a36Sopenharmony_ci pr_warn("Unexpected reply error: %u\n", 167362306a36Sopenharmony_ci target_thread->reply_error.cmd); 167462306a36Sopenharmony_ci } 167562306a36Sopenharmony_ci binder_inner_proc_unlock(target_thread->proc); 167662306a36Sopenharmony_ci binder_thread_dec_tmpref(target_thread); 167762306a36Sopenharmony_ci binder_free_transaction(t); 167862306a36Sopenharmony_ci return; 167962306a36Sopenharmony_ci } 168062306a36Sopenharmony_ci __release(&target_thread->proc->inner_lock); 168162306a36Sopenharmony_ci next = t->from_parent; 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, 168462306a36Sopenharmony_ci "send failed reply for transaction %d, target dead\n", 168562306a36Sopenharmony_ci t->debug_id); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci binder_free_transaction(t); 168862306a36Sopenharmony_ci if (next == NULL) { 168962306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_BINDER, 169062306a36Sopenharmony_ci "reply failed, no target thread at root\n"); 169162306a36Sopenharmony_ci return; 169262306a36Sopenharmony_ci } 169362306a36Sopenharmony_ci t = next; 169462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_BINDER, 169562306a36Sopenharmony_ci "reply failed, no target thread -- retry %d\n", 169662306a36Sopenharmony_ci t->debug_id); 169762306a36Sopenharmony_ci } 169862306a36Sopenharmony_ci} 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci/** 170162306a36Sopenharmony_ci * binder_cleanup_transaction() - cleans up undelivered transaction 170262306a36Sopenharmony_ci * @t: transaction that needs to be cleaned up 170362306a36Sopenharmony_ci * @reason: reason the transaction wasn't delivered 170462306a36Sopenharmony_ci * @error_code: error to return to caller (if synchronous call) 170562306a36Sopenharmony_ci */ 170662306a36Sopenharmony_cistatic void binder_cleanup_transaction(struct binder_transaction *t, 170762306a36Sopenharmony_ci const char *reason, 170862306a36Sopenharmony_ci uint32_t error_code) 170962306a36Sopenharmony_ci{ 171062306a36Sopenharmony_ci if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) { 171162306a36Sopenharmony_ci binder_send_failed_reply(t, error_code); 171262306a36Sopenharmony_ci } else { 171362306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, 171462306a36Sopenharmony_ci "undelivered transaction %d, %s\n", 171562306a36Sopenharmony_ci t->debug_id, reason); 171662306a36Sopenharmony_ci binder_free_transaction(t); 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci} 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci/** 172162306a36Sopenharmony_ci * binder_get_object() - gets object and checks for valid metadata 172262306a36Sopenharmony_ci * @proc: binder_proc owning the buffer 172362306a36Sopenharmony_ci * @u: sender's user pointer to base of buffer 172462306a36Sopenharmony_ci * @buffer: binder_buffer that we're parsing. 172562306a36Sopenharmony_ci * @offset: offset in the @buffer at which to validate an object. 172662306a36Sopenharmony_ci * @object: struct binder_object to read into 172762306a36Sopenharmony_ci * 172862306a36Sopenharmony_ci * Copy the binder object at the given offset into @object. If @u is 172962306a36Sopenharmony_ci * provided then the copy is from the sender's buffer. If not, then 173062306a36Sopenharmony_ci * it is copied from the target's @buffer. 173162306a36Sopenharmony_ci * 173262306a36Sopenharmony_ci * Return: If there's a valid metadata object at @offset, the 173362306a36Sopenharmony_ci * size of that object. Otherwise, it returns zero. The object 173462306a36Sopenharmony_ci * is read into the struct binder_object pointed to by @object. 173562306a36Sopenharmony_ci */ 173662306a36Sopenharmony_cistatic size_t binder_get_object(struct binder_proc *proc, 173762306a36Sopenharmony_ci const void __user *u, 173862306a36Sopenharmony_ci struct binder_buffer *buffer, 173962306a36Sopenharmony_ci unsigned long offset, 174062306a36Sopenharmony_ci struct binder_object *object) 174162306a36Sopenharmony_ci{ 174262306a36Sopenharmony_ci size_t read_size; 174362306a36Sopenharmony_ci struct binder_object_header *hdr; 174462306a36Sopenharmony_ci size_t object_size = 0; 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); 174762306a36Sopenharmony_ci if (offset > buffer->data_size || read_size < sizeof(*hdr)) 174862306a36Sopenharmony_ci return 0; 174962306a36Sopenharmony_ci if (u) { 175062306a36Sopenharmony_ci if (copy_from_user(object, u + offset, read_size)) 175162306a36Sopenharmony_ci return 0; 175262306a36Sopenharmony_ci } else { 175362306a36Sopenharmony_ci if (binder_alloc_copy_from_buffer(&proc->alloc, object, buffer, 175462306a36Sopenharmony_ci offset, read_size)) 175562306a36Sopenharmony_ci return 0; 175662306a36Sopenharmony_ci } 175762306a36Sopenharmony_ci 175862306a36Sopenharmony_ci /* Ok, now see if we read a complete object. */ 175962306a36Sopenharmony_ci hdr = &object->hdr; 176062306a36Sopenharmony_ci switch (hdr->type) { 176162306a36Sopenharmony_ci case BINDER_TYPE_BINDER: 176262306a36Sopenharmony_ci case BINDER_TYPE_WEAK_BINDER: 176362306a36Sopenharmony_ci case BINDER_TYPE_HANDLE: 176462306a36Sopenharmony_ci case BINDER_TYPE_WEAK_HANDLE: 176562306a36Sopenharmony_ci object_size = sizeof(struct flat_binder_object); 176662306a36Sopenharmony_ci break; 176762306a36Sopenharmony_ci case BINDER_TYPE_FD: 176862306a36Sopenharmony_ci object_size = sizeof(struct binder_fd_object); 176962306a36Sopenharmony_ci break; 177062306a36Sopenharmony_ci case BINDER_TYPE_PTR: 177162306a36Sopenharmony_ci object_size = sizeof(struct binder_buffer_object); 177262306a36Sopenharmony_ci break; 177362306a36Sopenharmony_ci case BINDER_TYPE_FDA: 177462306a36Sopenharmony_ci object_size = sizeof(struct binder_fd_array_object); 177562306a36Sopenharmony_ci break; 177662306a36Sopenharmony_ci default: 177762306a36Sopenharmony_ci return 0; 177862306a36Sopenharmony_ci } 177962306a36Sopenharmony_ci if (offset <= buffer->data_size - object_size && 178062306a36Sopenharmony_ci buffer->data_size >= object_size) 178162306a36Sopenharmony_ci return object_size; 178262306a36Sopenharmony_ci else 178362306a36Sopenharmony_ci return 0; 178462306a36Sopenharmony_ci} 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci/** 178762306a36Sopenharmony_ci * binder_validate_ptr() - validates binder_buffer_object in a binder_buffer. 178862306a36Sopenharmony_ci * @proc: binder_proc owning the buffer 178962306a36Sopenharmony_ci * @b: binder_buffer containing the object 179062306a36Sopenharmony_ci * @object: struct binder_object to read into 179162306a36Sopenharmony_ci * @index: index in offset array at which the binder_buffer_object is 179262306a36Sopenharmony_ci * located 179362306a36Sopenharmony_ci * @start_offset: points to the start of the offset array 179462306a36Sopenharmony_ci * @object_offsetp: offset of @object read from @b 179562306a36Sopenharmony_ci * @num_valid: the number of valid offsets in the offset array 179662306a36Sopenharmony_ci * 179762306a36Sopenharmony_ci * Return: If @index is within the valid range of the offset array 179862306a36Sopenharmony_ci * described by @start and @num_valid, and if there's a valid 179962306a36Sopenharmony_ci * binder_buffer_object at the offset found in index @index 180062306a36Sopenharmony_ci * of the offset array, that object is returned. Otherwise, 180162306a36Sopenharmony_ci * %NULL is returned. 180262306a36Sopenharmony_ci * Note that the offset found in index @index itself is not 180362306a36Sopenharmony_ci * verified; this function assumes that @num_valid elements 180462306a36Sopenharmony_ci * from @start were previously verified to have valid offsets. 180562306a36Sopenharmony_ci * If @object_offsetp is non-NULL, then the offset within 180662306a36Sopenharmony_ci * @b is written to it. 180762306a36Sopenharmony_ci */ 180862306a36Sopenharmony_cistatic struct binder_buffer_object *binder_validate_ptr( 180962306a36Sopenharmony_ci struct binder_proc *proc, 181062306a36Sopenharmony_ci struct binder_buffer *b, 181162306a36Sopenharmony_ci struct binder_object *object, 181262306a36Sopenharmony_ci binder_size_t index, 181362306a36Sopenharmony_ci binder_size_t start_offset, 181462306a36Sopenharmony_ci binder_size_t *object_offsetp, 181562306a36Sopenharmony_ci binder_size_t num_valid) 181662306a36Sopenharmony_ci{ 181762306a36Sopenharmony_ci size_t object_size; 181862306a36Sopenharmony_ci binder_size_t object_offset; 181962306a36Sopenharmony_ci unsigned long buffer_offset; 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci if (index >= num_valid) 182262306a36Sopenharmony_ci return NULL; 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci buffer_offset = start_offset + sizeof(binder_size_t) * index; 182562306a36Sopenharmony_ci if (binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, 182662306a36Sopenharmony_ci b, buffer_offset, 182762306a36Sopenharmony_ci sizeof(object_offset))) 182862306a36Sopenharmony_ci return NULL; 182962306a36Sopenharmony_ci object_size = binder_get_object(proc, NULL, b, object_offset, object); 183062306a36Sopenharmony_ci if (!object_size || object->hdr.type != BINDER_TYPE_PTR) 183162306a36Sopenharmony_ci return NULL; 183262306a36Sopenharmony_ci if (object_offsetp) 183362306a36Sopenharmony_ci *object_offsetp = object_offset; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci return &object->bbo; 183662306a36Sopenharmony_ci} 183762306a36Sopenharmony_ci 183862306a36Sopenharmony_ci/** 183962306a36Sopenharmony_ci * binder_validate_fixup() - validates pointer/fd fixups happen in order. 184062306a36Sopenharmony_ci * @proc: binder_proc owning the buffer 184162306a36Sopenharmony_ci * @b: transaction buffer 184262306a36Sopenharmony_ci * @objects_start_offset: offset to start of objects buffer 184362306a36Sopenharmony_ci * @buffer_obj_offset: offset to binder_buffer_object in which to fix up 184462306a36Sopenharmony_ci * @fixup_offset: start offset in @buffer to fix up 184562306a36Sopenharmony_ci * @last_obj_offset: offset to last binder_buffer_object that we fixed 184662306a36Sopenharmony_ci * @last_min_offset: minimum fixup offset in object at @last_obj_offset 184762306a36Sopenharmony_ci * 184862306a36Sopenharmony_ci * Return: %true if a fixup in buffer @buffer at offset @offset is 184962306a36Sopenharmony_ci * allowed. 185062306a36Sopenharmony_ci * 185162306a36Sopenharmony_ci * For safety reasons, we only allow fixups inside a buffer to happen 185262306a36Sopenharmony_ci * at increasing offsets; additionally, we only allow fixup on the last 185362306a36Sopenharmony_ci * buffer object that was verified, or one of its parents. 185462306a36Sopenharmony_ci * 185562306a36Sopenharmony_ci * Example of what is allowed: 185662306a36Sopenharmony_ci * 185762306a36Sopenharmony_ci * A 185862306a36Sopenharmony_ci * B (parent = A, offset = 0) 185962306a36Sopenharmony_ci * C (parent = A, offset = 16) 186062306a36Sopenharmony_ci * D (parent = C, offset = 0) 186162306a36Sopenharmony_ci * E (parent = A, offset = 32) // min_offset is 16 (C.parent_offset) 186262306a36Sopenharmony_ci * 186362306a36Sopenharmony_ci * Examples of what is not allowed: 186462306a36Sopenharmony_ci * 186562306a36Sopenharmony_ci * Decreasing offsets within the same parent: 186662306a36Sopenharmony_ci * A 186762306a36Sopenharmony_ci * C (parent = A, offset = 16) 186862306a36Sopenharmony_ci * B (parent = A, offset = 0) // decreasing offset within A 186962306a36Sopenharmony_ci * 187062306a36Sopenharmony_ci * Referring to a parent that wasn't the last object or any of its parents: 187162306a36Sopenharmony_ci * A 187262306a36Sopenharmony_ci * B (parent = A, offset = 0) 187362306a36Sopenharmony_ci * C (parent = A, offset = 0) 187462306a36Sopenharmony_ci * C (parent = A, offset = 16) 187562306a36Sopenharmony_ci * D (parent = B, offset = 0) // B is not A or any of A's parents 187662306a36Sopenharmony_ci */ 187762306a36Sopenharmony_cistatic bool binder_validate_fixup(struct binder_proc *proc, 187862306a36Sopenharmony_ci struct binder_buffer *b, 187962306a36Sopenharmony_ci binder_size_t objects_start_offset, 188062306a36Sopenharmony_ci binder_size_t buffer_obj_offset, 188162306a36Sopenharmony_ci binder_size_t fixup_offset, 188262306a36Sopenharmony_ci binder_size_t last_obj_offset, 188362306a36Sopenharmony_ci binder_size_t last_min_offset) 188462306a36Sopenharmony_ci{ 188562306a36Sopenharmony_ci if (!last_obj_offset) { 188662306a36Sopenharmony_ci /* Nothing to fix up in */ 188762306a36Sopenharmony_ci return false; 188862306a36Sopenharmony_ci } 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci while (last_obj_offset != buffer_obj_offset) { 189162306a36Sopenharmony_ci unsigned long buffer_offset; 189262306a36Sopenharmony_ci struct binder_object last_object; 189362306a36Sopenharmony_ci struct binder_buffer_object *last_bbo; 189462306a36Sopenharmony_ci size_t object_size = binder_get_object(proc, NULL, b, 189562306a36Sopenharmony_ci last_obj_offset, 189662306a36Sopenharmony_ci &last_object); 189762306a36Sopenharmony_ci if (object_size != sizeof(*last_bbo)) 189862306a36Sopenharmony_ci return false; 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci last_bbo = &last_object.bbo; 190162306a36Sopenharmony_ci /* 190262306a36Sopenharmony_ci * Safe to retrieve the parent of last_obj, since it 190362306a36Sopenharmony_ci * was already previously verified by the driver. 190462306a36Sopenharmony_ci */ 190562306a36Sopenharmony_ci if ((last_bbo->flags & BINDER_BUFFER_FLAG_HAS_PARENT) == 0) 190662306a36Sopenharmony_ci return false; 190762306a36Sopenharmony_ci last_min_offset = last_bbo->parent_offset + sizeof(uintptr_t); 190862306a36Sopenharmony_ci buffer_offset = objects_start_offset + 190962306a36Sopenharmony_ci sizeof(binder_size_t) * last_bbo->parent; 191062306a36Sopenharmony_ci if (binder_alloc_copy_from_buffer(&proc->alloc, 191162306a36Sopenharmony_ci &last_obj_offset, 191262306a36Sopenharmony_ci b, buffer_offset, 191362306a36Sopenharmony_ci sizeof(last_obj_offset))) 191462306a36Sopenharmony_ci return false; 191562306a36Sopenharmony_ci } 191662306a36Sopenharmony_ci return (fixup_offset >= last_min_offset); 191762306a36Sopenharmony_ci} 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci/** 192062306a36Sopenharmony_ci * struct binder_task_work_cb - for deferred close 192162306a36Sopenharmony_ci * 192262306a36Sopenharmony_ci * @twork: callback_head for task work 192362306a36Sopenharmony_ci * @fd: fd to close 192462306a36Sopenharmony_ci * 192562306a36Sopenharmony_ci * Structure to pass task work to be handled after 192662306a36Sopenharmony_ci * returning from binder_ioctl() via task_work_add(). 192762306a36Sopenharmony_ci */ 192862306a36Sopenharmony_cistruct binder_task_work_cb { 192962306a36Sopenharmony_ci struct callback_head twork; 193062306a36Sopenharmony_ci struct file *file; 193162306a36Sopenharmony_ci}; 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_ci/** 193462306a36Sopenharmony_ci * binder_do_fd_close() - close list of file descriptors 193562306a36Sopenharmony_ci * @twork: callback head for task work 193662306a36Sopenharmony_ci * 193762306a36Sopenharmony_ci * It is not safe to call ksys_close() during the binder_ioctl() 193862306a36Sopenharmony_ci * function if there is a chance that binder's own file descriptor 193962306a36Sopenharmony_ci * might be closed. This is to meet the requirements for using 194062306a36Sopenharmony_ci * fdget() (see comments for __fget_light()). Therefore use 194162306a36Sopenharmony_ci * task_work_add() to schedule the close operation once we have 194262306a36Sopenharmony_ci * returned from binder_ioctl(). This function is a callback 194362306a36Sopenharmony_ci * for that mechanism and does the actual ksys_close() on the 194462306a36Sopenharmony_ci * given file descriptor. 194562306a36Sopenharmony_ci */ 194662306a36Sopenharmony_cistatic void binder_do_fd_close(struct callback_head *twork) 194762306a36Sopenharmony_ci{ 194862306a36Sopenharmony_ci struct binder_task_work_cb *twcb = container_of(twork, 194962306a36Sopenharmony_ci struct binder_task_work_cb, twork); 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci fput(twcb->file); 195262306a36Sopenharmony_ci kfree(twcb); 195362306a36Sopenharmony_ci} 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci/** 195662306a36Sopenharmony_ci * binder_deferred_fd_close() - schedule a close for the given file-descriptor 195762306a36Sopenharmony_ci * @fd: file-descriptor to close 195862306a36Sopenharmony_ci * 195962306a36Sopenharmony_ci * See comments in binder_do_fd_close(). This function is used to schedule 196062306a36Sopenharmony_ci * a file-descriptor to be closed after returning from binder_ioctl(). 196162306a36Sopenharmony_ci */ 196262306a36Sopenharmony_cistatic void binder_deferred_fd_close(int fd) 196362306a36Sopenharmony_ci{ 196462306a36Sopenharmony_ci struct binder_task_work_cb *twcb; 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci twcb = kzalloc(sizeof(*twcb), GFP_KERNEL); 196762306a36Sopenharmony_ci if (!twcb) 196862306a36Sopenharmony_ci return; 196962306a36Sopenharmony_ci init_task_work(&twcb->twork, binder_do_fd_close); 197062306a36Sopenharmony_ci twcb->file = close_fd_get_file(fd); 197162306a36Sopenharmony_ci if (twcb->file) { 197262306a36Sopenharmony_ci // pin it until binder_do_fd_close(); see comments there 197362306a36Sopenharmony_ci get_file(twcb->file); 197462306a36Sopenharmony_ci filp_close(twcb->file, current->files); 197562306a36Sopenharmony_ci task_work_add(current, &twcb->twork, TWA_RESUME); 197662306a36Sopenharmony_ci } else { 197762306a36Sopenharmony_ci kfree(twcb); 197862306a36Sopenharmony_ci } 197962306a36Sopenharmony_ci} 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_cistatic void binder_transaction_buffer_release(struct binder_proc *proc, 198262306a36Sopenharmony_ci struct binder_thread *thread, 198362306a36Sopenharmony_ci struct binder_buffer *buffer, 198462306a36Sopenharmony_ci binder_size_t off_end_offset, 198562306a36Sopenharmony_ci bool is_failure) 198662306a36Sopenharmony_ci{ 198762306a36Sopenharmony_ci int debug_id = buffer->debug_id; 198862306a36Sopenharmony_ci binder_size_t off_start_offset, buffer_offset; 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 199162306a36Sopenharmony_ci "%d buffer release %d, size %zd-%zd, failed at %llx\n", 199262306a36Sopenharmony_ci proc->pid, buffer->debug_id, 199362306a36Sopenharmony_ci buffer->data_size, buffer->offsets_size, 199462306a36Sopenharmony_ci (unsigned long long)off_end_offset); 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci if (buffer->target_node) 199762306a36Sopenharmony_ci binder_dec_node(buffer->target_node, 1, 0); 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci off_start_offset = ALIGN(buffer->data_size, sizeof(void *)); 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_ci for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; 200262306a36Sopenharmony_ci buffer_offset += sizeof(binder_size_t)) { 200362306a36Sopenharmony_ci struct binder_object_header *hdr; 200462306a36Sopenharmony_ci size_t object_size = 0; 200562306a36Sopenharmony_ci struct binder_object object; 200662306a36Sopenharmony_ci binder_size_t object_offset; 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, 200962306a36Sopenharmony_ci buffer, buffer_offset, 201062306a36Sopenharmony_ci sizeof(object_offset))) 201162306a36Sopenharmony_ci object_size = binder_get_object(proc, NULL, buffer, 201262306a36Sopenharmony_ci object_offset, &object); 201362306a36Sopenharmony_ci if (object_size == 0) { 201462306a36Sopenharmony_ci pr_err("transaction release %d bad object at offset %lld, size %zd\n", 201562306a36Sopenharmony_ci debug_id, (u64)object_offset, buffer->data_size); 201662306a36Sopenharmony_ci continue; 201762306a36Sopenharmony_ci } 201862306a36Sopenharmony_ci hdr = &object.hdr; 201962306a36Sopenharmony_ci switch (hdr->type) { 202062306a36Sopenharmony_ci case BINDER_TYPE_BINDER: 202162306a36Sopenharmony_ci case BINDER_TYPE_WEAK_BINDER: { 202262306a36Sopenharmony_ci struct flat_binder_object *fp; 202362306a36Sopenharmony_ci struct binder_node *node; 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci fp = to_flat_binder_object(hdr); 202662306a36Sopenharmony_ci node = binder_get_node(proc, fp->binder); 202762306a36Sopenharmony_ci if (node == NULL) { 202862306a36Sopenharmony_ci pr_err("transaction release %d bad node %016llx\n", 202962306a36Sopenharmony_ci debug_id, (u64)fp->binder); 203062306a36Sopenharmony_ci break; 203162306a36Sopenharmony_ci } 203262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 203362306a36Sopenharmony_ci " node %d u%016llx\n", 203462306a36Sopenharmony_ci node->debug_id, (u64)node->ptr); 203562306a36Sopenharmony_ci binder_dec_node(node, hdr->type == BINDER_TYPE_BINDER, 203662306a36Sopenharmony_ci 0); 203762306a36Sopenharmony_ci binder_put_node(node); 203862306a36Sopenharmony_ci } break; 203962306a36Sopenharmony_ci case BINDER_TYPE_HANDLE: 204062306a36Sopenharmony_ci case BINDER_TYPE_WEAK_HANDLE: { 204162306a36Sopenharmony_ci struct flat_binder_object *fp; 204262306a36Sopenharmony_ci struct binder_ref_data rdata; 204362306a36Sopenharmony_ci int ret; 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci fp = to_flat_binder_object(hdr); 204662306a36Sopenharmony_ci ret = binder_dec_ref_for_handle(proc, fp->handle, 204762306a36Sopenharmony_ci hdr->type == BINDER_TYPE_HANDLE, &rdata); 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci if (ret) { 205062306a36Sopenharmony_ci pr_err("transaction release %d bad handle %d, ret = %d\n", 205162306a36Sopenharmony_ci debug_id, fp->handle, ret); 205262306a36Sopenharmony_ci break; 205362306a36Sopenharmony_ci } 205462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 205562306a36Sopenharmony_ci " ref %d desc %d\n", 205662306a36Sopenharmony_ci rdata.debug_id, rdata.desc); 205762306a36Sopenharmony_ci } break; 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci case BINDER_TYPE_FD: { 206062306a36Sopenharmony_ci /* 206162306a36Sopenharmony_ci * No need to close the file here since user-space 206262306a36Sopenharmony_ci * closes it for successfully delivered 206362306a36Sopenharmony_ci * transactions. For transactions that weren't 206462306a36Sopenharmony_ci * delivered, the new fd was never allocated so 206562306a36Sopenharmony_ci * there is no need to close and the fput on the 206662306a36Sopenharmony_ci * file is done when the transaction is torn 206762306a36Sopenharmony_ci * down. 206862306a36Sopenharmony_ci */ 206962306a36Sopenharmony_ci } break; 207062306a36Sopenharmony_ci case BINDER_TYPE_PTR: 207162306a36Sopenharmony_ci /* 207262306a36Sopenharmony_ci * Nothing to do here, this will get cleaned up when the 207362306a36Sopenharmony_ci * transaction buffer gets freed 207462306a36Sopenharmony_ci */ 207562306a36Sopenharmony_ci break; 207662306a36Sopenharmony_ci case BINDER_TYPE_FDA: { 207762306a36Sopenharmony_ci struct binder_fd_array_object *fda; 207862306a36Sopenharmony_ci struct binder_buffer_object *parent; 207962306a36Sopenharmony_ci struct binder_object ptr_object; 208062306a36Sopenharmony_ci binder_size_t fda_offset; 208162306a36Sopenharmony_ci size_t fd_index; 208262306a36Sopenharmony_ci binder_size_t fd_buf_size; 208362306a36Sopenharmony_ci binder_size_t num_valid; 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci if (is_failure) { 208662306a36Sopenharmony_ci /* 208762306a36Sopenharmony_ci * The fd fixups have not been applied so no 208862306a36Sopenharmony_ci * fds need to be closed. 208962306a36Sopenharmony_ci */ 209062306a36Sopenharmony_ci continue; 209162306a36Sopenharmony_ci } 209262306a36Sopenharmony_ci 209362306a36Sopenharmony_ci num_valid = (buffer_offset - off_start_offset) / 209462306a36Sopenharmony_ci sizeof(binder_size_t); 209562306a36Sopenharmony_ci fda = to_binder_fd_array_object(hdr); 209662306a36Sopenharmony_ci parent = binder_validate_ptr(proc, buffer, &ptr_object, 209762306a36Sopenharmony_ci fda->parent, 209862306a36Sopenharmony_ci off_start_offset, 209962306a36Sopenharmony_ci NULL, 210062306a36Sopenharmony_ci num_valid); 210162306a36Sopenharmony_ci if (!parent) { 210262306a36Sopenharmony_ci pr_err("transaction release %d bad parent offset\n", 210362306a36Sopenharmony_ci debug_id); 210462306a36Sopenharmony_ci continue; 210562306a36Sopenharmony_ci } 210662306a36Sopenharmony_ci fd_buf_size = sizeof(u32) * fda->num_fds; 210762306a36Sopenharmony_ci if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { 210862306a36Sopenharmony_ci pr_err("transaction release %d invalid number of fds (%lld)\n", 210962306a36Sopenharmony_ci debug_id, (u64)fda->num_fds); 211062306a36Sopenharmony_ci continue; 211162306a36Sopenharmony_ci } 211262306a36Sopenharmony_ci if (fd_buf_size > parent->length || 211362306a36Sopenharmony_ci fda->parent_offset > parent->length - fd_buf_size) { 211462306a36Sopenharmony_ci /* No space for all file descriptors here. */ 211562306a36Sopenharmony_ci pr_err("transaction release %d not enough space for %lld fds in buffer\n", 211662306a36Sopenharmony_ci debug_id, (u64)fda->num_fds); 211762306a36Sopenharmony_ci continue; 211862306a36Sopenharmony_ci } 211962306a36Sopenharmony_ci /* 212062306a36Sopenharmony_ci * the source data for binder_buffer_object is visible 212162306a36Sopenharmony_ci * to user-space and the @buffer element is the user 212262306a36Sopenharmony_ci * pointer to the buffer_object containing the fd_array. 212362306a36Sopenharmony_ci * Convert the address to an offset relative to 212462306a36Sopenharmony_ci * the base of the transaction buffer. 212562306a36Sopenharmony_ci */ 212662306a36Sopenharmony_ci fda_offset = 212762306a36Sopenharmony_ci (parent->buffer - (uintptr_t)buffer->user_data) + 212862306a36Sopenharmony_ci fda->parent_offset; 212962306a36Sopenharmony_ci for (fd_index = 0; fd_index < fda->num_fds; 213062306a36Sopenharmony_ci fd_index++) { 213162306a36Sopenharmony_ci u32 fd; 213262306a36Sopenharmony_ci int err; 213362306a36Sopenharmony_ci binder_size_t offset = fda_offset + 213462306a36Sopenharmony_ci fd_index * sizeof(fd); 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_ci err = binder_alloc_copy_from_buffer( 213762306a36Sopenharmony_ci &proc->alloc, &fd, buffer, 213862306a36Sopenharmony_ci offset, sizeof(fd)); 213962306a36Sopenharmony_ci WARN_ON(err); 214062306a36Sopenharmony_ci if (!err) { 214162306a36Sopenharmony_ci binder_deferred_fd_close(fd); 214262306a36Sopenharmony_ci /* 214362306a36Sopenharmony_ci * Need to make sure the thread goes 214462306a36Sopenharmony_ci * back to userspace to complete the 214562306a36Sopenharmony_ci * deferred close 214662306a36Sopenharmony_ci */ 214762306a36Sopenharmony_ci if (thread) 214862306a36Sopenharmony_ci thread->looper_need_return = true; 214962306a36Sopenharmony_ci } 215062306a36Sopenharmony_ci } 215162306a36Sopenharmony_ci } break; 215262306a36Sopenharmony_ci default: 215362306a36Sopenharmony_ci pr_err("transaction release %d bad object type %x\n", 215462306a36Sopenharmony_ci debug_id, hdr->type); 215562306a36Sopenharmony_ci break; 215662306a36Sopenharmony_ci } 215762306a36Sopenharmony_ci } 215862306a36Sopenharmony_ci} 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_ci/* Clean up all the objects in the buffer */ 216162306a36Sopenharmony_cistatic inline void binder_release_entire_buffer(struct binder_proc *proc, 216262306a36Sopenharmony_ci struct binder_thread *thread, 216362306a36Sopenharmony_ci struct binder_buffer *buffer, 216462306a36Sopenharmony_ci bool is_failure) 216562306a36Sopenharmony_ci{ 216662306a36Sopenharmony_ci binder_size_t off_end_offset; 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci off_end_offset = ALIGN(buffer->data_size, sizeof(void *)); 216962306a36Sopenharmony_ci off_end_offset += buffer->offsets_size; 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci binder_transaction_buffer_release(proc, thread, buffer, 217262306a36Sopenharmony_ci off_end_offset, is_failure); 217362306a36Sopenharmony_ci} 217462306a36Sopenharmony_ci 217562306a36Sopenharmony_cistatic int binder_translate_binder(struct flat_binder_object *fp, 217662306a36Sopenharmony_ci struct binder_transaction *t, 217762306a36Sopenharmony_ci struct binder_thread *thread) 217862306a36Sopenharmony_ci{ 217962306a36Sopenharmony_ci struct binder_node *node; 218062306a36Sopenharmony_ci struct binder_proc *proc = thread->proc; 218162306a36Sopenharmony_ci struct binder_proc *target_proc = t->to_proc; 218262306a36Sopenharmony_ci struct binder_ref_data rdata; 218362306a36Sopenharmony_ci int ret = 0; 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci node = binder_get_node(proc, fp->binder); 218662306a36Sopenharmony_ci if (!node) { 218762306a36Sopenharmony_ci node = binder_new_node(proc, fp); 218862306a36Sopenharmony_ci if (!node) 218962306a36Sopenharmony_ci return -ENOMEM; 219062306a36Sopenharmony_ci } 219162306a36Sopenharmony_ci if (fp->cookie != node->cookie) { 219262306a36Sopenharmony_ci binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n", 219362306a36Sopenharmony_ci proc->pid, thread->pid, (u64)fp->binder, 219462306a36Sopenharmony_ci node->debug_id, (u64)fp->cookie, 219562306a36Sopenharmony_ci (u64)node->cookie); 219662306a36Sopenharmony_ci ret = -EINVAL; 219762306a36Sopenharmony_ci goto done; 219862306a36Sopenharmony_ci } 219962306a36Sopenharmony_ci if (security_binder_transfer_binder(proc->cred, target_proc->cred)) { 220062306a36Sopenharmony_ci ret = -EPERM; 220162306a36Sopenharmony_ci goto done; 220262306a36Sopenharmony_ci } 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_ci ret = binder_inc_ref_for_node(target_proc, node, 220562306a36Sopenharmony_ci fp->hdr.type == BINDER_TYPE_BINDER, 220662306a36Sopenharmony_ci &thread->todo, &rdata); 220762306a36Sopenharmony_ci if (ret) 220862306a36Sopenharmony_ci goto done; 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci if (fp->hdr.type == BINDER_TYPE_BINDER) 221162306a36Sopenharmony_ci fp->hdr.type = BINDER_TYPE_HANDLE; 221262306a36Sopenharmony_ci else 221362306a36Sopenharmony_ci fp->hdr.type = BINDER_TYPE_WEAK_HANDLE; 221462306a36Sopenharmony_ci fp->binder = 0; 221562306a36Sopenharmony_ci fp->handle = rdata.desc; 221662306a36Sopenharmony_ci fp->cookie = 0; 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_ci trace_binder_transaction_node_to_ref(t, node, &rdata); 221962306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 222062306a36Sopenharmony_ci " node %d u%016llx -> ref %d desc %d\n", 222162306a36Sopenharmony_ci node->debug_id, (u64)node->ptr, 222262306a36Sopenharmony_ci rdata.debug_id, rdata.desc); 222362306a36Sopenharmony_cidone: 222462306a36Sopenharmony_ci binder_put_node(node); 222562306a36Sopenharmony_ci return ret; 222662306a36Sopenharmony_ci} 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_cistatic int binder_translate_handle(struct flat_binder_object *fp, 222962306a36Sopenharmony_ci struct binder_transaction *t, 223062306a36Sopenharmony_ci struct binder_thread *thread) 223162306a36Sopenharmony_ci{ 223262306a36Sopenharmony_ci struct binder_proc *proc = thread->proc; 223362306a36Sopenharmony_ci struct binder_proc *target_proc = t->to_proc; 223462306a36Sopenharmony_ci struct binder_node *node; 223562306a36Sopenharmony_ci struct binder_ref_data src_rdata; 223662306a36Sopenharmony_ci int ret = 0; 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci node = binder_get_node_from_ref(proc, fp->handle, 223962306a36Sopenharmony_ci fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata); 224062306a36Sopenharmony_ci if (!node) { 224162306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid handle, %d\n", 224262306a36Sopenharmony_ci proc->pid, thread->pid, fp->handle); 224362306a36Sopenharmony_ci return -EINVAL; 224462306a36Sopenharmony_ci } 224562306a36Sopenharmony_ci if (security_binder_transfer_binder(proc->cred, target_proc->cred)) { 224662306a36Sopenharmony_ci ret = -EPERM; 224762306a36Sopenharmony_ci goto done; 224862306a36Sopenharmony_ci } 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci binder_node_lock(node); 225162306a36Sopenharmony_ci if (node->proc == target_proc) { 225262306a36Sopenharmony_ci if (fp->hdr.type == BINDER_TYPE_HANDLE) 225362306a36Sopenharmony_ci fp->hdr.type = BINDER_TYPE_BINDER; 225462306a36Sopenharmony_ci else 225562306a36Sopenharmony_ci fp->hdr.type = BINDER_TYPE_WEAK_BINDER; 225662306a36Sopenharmony_ci fp->binder = node->ptr; 225762306a36Sopenharmony_ci fp->cookie = node->cookie; 225862306a36Sopenharmony_ci if (node->proc) 225962306a36Sopenharmony_ci binder_inner_proc_lock(node->proc); 226062306a36Sopenharmony_ci else 226162306a36Sopenharmony_ci __acquire(&node->proc->inner_lock); 226262306a36Sopenharmony_ci binder_inc_node_nilocked(node, 226362306a36Sopenharmony_ci fp->hdr.type == BINDER_TYPE_BINDER, 226462306a36Sopenharmony_ci 0, NULL); 226562306a36Sopenharmony_ci if (node->proc) 226662306a36Sopenharmony_ci binder_inner_proc_unlock(node->proc); 226762306a36Sopenharmony_ci else 226862306a36Sopenharmony_ci __release(&node->proc->inner_lock); 226962306a36Sopenharmony_ci trace_binder_transaction_ref_to_node(t, node, &src_rdata); 227062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 227162306a36Sopenharmony_ci " ref %d desc %d -> node %d u%016llx\n", 227262306a36Sopenharmony_ci src_rdata.debug_id, src_rdata.desc, node->debug_id, 227362306a36Sopenharmony_ci (u64)node->ptr); 227462306a36Sopenharmony_ci binder_node_unlock(node); 227562306a36Sopenharmony_ci } else { 227662306a36Sopenharmony_ci struct binder_ref_data dest_rdata; 227762306a36Sopenharmony_ci 227862306a36Sopenharmony_ci binder_node_unlock(node); 227962306a36Sopenharmony_ci ret = binder_inc_ref_for_node(target_proc, node, 228062306a36Sopenharmony_ci fp->hdr.type == BINDER_TYPE_HANDLE, 228162306a36Sopenharmony_ci NULL, &dest_rdata); 228262306a36Sopenharmony_ci if (ret) 228362306a36Sopenharmony_ci goto done; 228462306a36Sopenharmony_ci 228562306a36Sopenharmony_ci fp->binder = 0; 228662306a36Sopenharmony_ci fp->handle = dest_rdata.desc; 228762306a36Sopenharmony_ci fp->cookie = 0; 228862306a36Sopenharmony_ci trace_binder_transaction_ref_to_ref(t, node, &src_rdata, 228962306a36Sopenharmony_ci &dest_rdata); 229062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 229162306a36Sopenharmony_ci " ref %d desc %d -> ref %d desc %d (node %d)\n", 229262306a36Sopenharmony_ci src_rdata.debug_id, src_rdata.desc, 229362306a36Sopenharmony_ci dest_rdata.debug_id, dest_rdata.desc, 229462306a36Sopenharmony_ci node->debug_id); 229562306a36Sopenharmony_ci } 229662306a36Sopenharmony_cidone: 229762306a36Sopenharmony_ci binder_put_node(node); 229862306a36Sopenharmony_ci return ret; 229962306a36Sopenharmony_ci} 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_cistatic int binder_translate_fd(u32 fd, binder_size_t fd_offset, 230262306a36Sopenharmony_ci struct binder_transaction *t, 230362306a36Sopenharmony_ci struct binder_thread *thread, 230462306a36Sopenharmony_ci struct binder_transaction *in_reply_to) 230562306a36Sopenharmony_ci{ 230662306a36Sopenharmony_ci struct binder_proc *proc = thread->proc; 230762306a36Sopenharmony_ci struct binder_proc *target_proc = t->to_proc; 230862306a36Sopenharmony_ci struct binder_txn_fd_fixup *fixup; 230962306a36Sopenharmony_ci struct file *file; 231062306a36Sopenharmony_ci int ret = 0; 231162306a36Sopenharmony_ci bool target_allows_fd; 231262306a36Sopenharmony_ci 231362306a36Sopenharmony_ci if (in_reply_to) 231462306a36Sopenharmony_ci target_allows_fd = !!(in_reply_to->flags & TF_ACCEPT_FDS); 231562306a36Sopenharmony_ci else 231662306a36Sopenharmony_ci target_allows_fd = t->buffer->target_node->accept_fds; 231762306a36Sopenharmony_ci if (!target_allows_fd) { 231862306a36Sopenharmony_ci binder_user_error("%d:%d got %s with fd, %d, but target does not allow fds\n", 231962306a36Sopenharmony_ci proc->pid, thread->pid, 232062306a36Sopenharmony_ci in_reply_to ? "reply" : "transaction", 232162306a36Sopenharmony_ci fd); 232262306a36Sopenharmony_ci ret = -EPERM; 232362306a36Sopenharmony_ci goto err_fd_not_accepted; 232462306a36Sopenharmony_ci } 232562306a36Sopenharmony_ci 232662306a36Sopenharmony_ci file = fget(fd); 232762306a36Sopenharmony_ci if (!file) { 232862306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid fd, %d\n", 232962306a36Sopenharmony_ci proc->pid, thread->pid, fd); 233062306a36Sopenharmony_ci ret = -EBADF; 233162306a36Sopenharmony_ci goto err_fget; 233262306a36Sopenharmony_ci } 233362306a36Sopenharmony_ci ret = security_binder_transfer_file(proc->cred, target_proc->cred, file); 233462306a36Sopenharmony_ci if (ret < 0) { 233562306a36Sopenharmony_ci ret = -EPERM; 233662306a36Sopenharmony_ci goto err_security; 233762306a36Sopenharmony_ci } 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci /* 234062306a36Sopenharmony_ci * Add fixup record for this transaction. The allocation 234162306a36Sopenharmony_ci * of the fd in the target needs to be done from a 234262306a36Sopenharmony_ci * target thread. 234362306a36Sopenharmony_ci */ 234462306a36Sopenharmony_ci fixup = kzalloc(sizeof(*fixup), GFP_KERNEL); 234562306a36Sopenharmony_ci if (!fixup) { 234662306a36Sopenharmony_ci ret = -ENOMEM; 234762306a36Sopenharmony_ci goto err_alloc; 234862306a36Sopenharmony_ci } 234962306a36Sopenharmony_ci fixup->file = file; 235062306a36Sopenharmony_ci fixup->offset = fd_offset; 235162306a36Sopenharmony_ci fixup->target_fd = -1; 235262306a36Sopenharmony_ci trace_binder_transaction_fd_send(t, fd, fixup->offset); 235362306a36Sopenharmony_ci list_add_tail(&fixup->fixup_entry, &t->fd_fixups); 235462306a36Sopenharmony_ci 235562306a36Sopenharmony_ci return ret; 235662306a36Sopenharmony_ci 235762306a36Sopenharmony_cierr_alloc: 235862306a36Sopenharmony_cierr_security: 235962306a36Sopenharmony_ci fput(file); 236062306a36Sopenharmony_cierr_fget: 236162306a36Sopenharmony_cierr_fd_not_accepted: 236262306a36Sopenharmony_ci return ret; 236362306a36Sopenharmony_ci} 236462306a36Sopenharmony_ci 236562306a36Sopenharmony_ci/** 236662306a36Sopenharmony_ci * struct binder_ptr_fixup - data to be fixed-up in target buffer 236762306a36Sopenharmony_ci * @offset offset in target buffer to fixup 236862306a36Sopenharmony_ci * @skip_size bytes to skip in copy (fixup will be written later) 236962306a36Sopenharmony_ci * @fixup_data data to write at fixup offset 237062306a36Sopenharmony_ci * @node list node 237162306a36Sopenharmony_ci * 237262306a36Sopenharmony_ci * This is used for the pointer fixup list (pf) which is created and consumed 237362306a36Sopenharmony_ci * during binder_transaction() and is only accessed locally. No 237462306a36Sopenharmony_ci * locking is necessary. 237562306a36Sopenharmony_ci * 237662306a36Sopenharmony_ci * The list is ordered by @offset. 237762306a36Sopenharmony_ci */ 237862306a36Sopenharmony_cistruct binder_ptr_fixup { 237962306a36Sopenharmony_ci binder_size_t offset; 238062306a36Sopenharmony_ci size_t skip_size; 238162306a36Sopenharmony_ci binder_uintptr_t fixup_data; 238262306a36Sopenharmony_ci struct list_head node; 238362306a36Sopenharmony_ci}; 238462306a36Sopenharmony_ci 238562306a36Sopenharmony_ci/** 238662306a36Sopenharmony_ci * struct binder_sg_copy - scatter-gather data to be copied 238762306a36Sopenharmony_ci * @offset offset in target buffer 238862306a36Sopenharmony_ci * @sender_uaddr user address in source buffer 238962306a36Sopenharmony_ci * @length bytes to copy 239062306a36Sopenharmony_ci * @node list node 239162306a36Sopenharmony_ci * 239262306a36Sopenharmony_ci * This is used for the sg copy list (sgc) which is created and consumed 239362306a36Sopenharmony_ci * during binder_transaction() and is only accessed locally. No 239462306a36Sopenharmony_ci * locking is necessary. 239562306a36Sopenharmony_ci * 239662306a36Sopenharmony_ci * The list is ordered by @offset. 239762306a36Sopenharmony_ci */ 239862306a36Sopenharmony_cistruct binder_sg_copy { 239962306a36Sopenharmony_ci binder_size_t offset; 240062306a36Sopenharmony_ci const void __user *sender_uaddr; 240162306a36Sopenharmony_ci size_t length; 240262306a36Sopenharmony_ci struct list_head node; 240362306a36Sopenharmony_ci}; 240462306a36Sopenharmony_ci 240562306a36Sopenharmony_ci/** 240662306a36Sopenharmony_ci * binder_do_deferred_txn_copies() - copy and fixup scatter-gather data 240762306a36Sopenharmony_ci * @alloc: binder_alloc associated with @buffer 240862306a36Sopenharmony_ci * @buffer: binder buffer in target process 240962306a36Sopenharmony_ci * @sgc_head: list_head of scatter-gather copy list 241062306a36Sopenharmony_ci * @pf_head: list_head of pointer fixup list 241162306a36Sopenharmony_ci * 241262306a36Sopenharmony_ci * Processes all elements of @sgc_head, applying fixups from @pf_head 241362306a36Sopenharmony_ci * and copying the scatter-gather data from the source process' user 241462306a36Sopenharmony_ci * buffer to the target's buffer. It is expected that the list creation 241562306a36Sopenharmony_ci * and processing all occurs during binder_transaction() so these lists 241662306a36Sopenharmony_ci * are only accessed in local context. 241762306a36Sopenharmony_ci * 241862306a36Sopenharmony_ci * Return: 0=success, else -errno 241962306a36Sopenharmony_ci */ 242062306a36Sopenharmony_cistatic int binder_do_deferred_txn_copies(struct binder_alloc *alloc, 242162306a36Sopenharmony_ci struct binder_buffer *buffer, 242262306a36Sopenharmony_ci struct list_head *sgc_head, 242362306a36Sopenharmony_ci struct list_head *pf_head) 242462306a36Sopenharmony_ci{ 242562306a36Sopenharmony_ci int ret = 0; 242662306a36Sopenharmony_ci struct binder_sg_copy *sgc, *tmpsgc; 242762306a36Sopenharmony_ci struct binder_ptr_fixup *tmppf; 242862306a36Sopenharmony_ci struct binder_ptr_fixup *pf = 242962306a36Sopenharmony_ci list_first_entry_or_null(pf_head, struct binder_ptr_fixup, 243062306a36Sopenharmony_ci node); 243162306a36Sopenharmony_ci 243262306a36Sopenharmony_ci list_for_each_entry_safe(sgc, tmpsgc, sgc_head, node) { 243362306a36Sopenharmony_ci size_t bytes_copied = 0; 243462306a36Sopenharmony_ci 243562306a36Sopenharmony_ci while (bytes_copied < sgc->length) { 243662306a36Sopenharmony_ci size_t copy_size; 243762306a36Sopenharmony_ci size_t bytes_left = sgc->length - bytes_copied; 243862306a36Sopenharmony_ci size_t offset = sgc->offset + bytes_copied; 243962306a36Sopenharmony_ci 244062306a36Sopenharmony_ci /* 244162306a36Sopenharmony_ci * We copy up to the fixup (pointed to by pf) 244262306a36Sopenharmony_ci */ 244362306a36Sopenharmony_ci copy_size = pf ? min(bytes_left, (size_t)pf->offset - offset) 244462306a36Sopenharmony_ci : bytes_left; 244562306a36Sopenharmony_ci if (!ret && copy_size) 244662306a36Sopenharmony_ci ret = binder_alloc_copy_user_to_buffer( 244762306a36Sopenharmony_ci alloc, buffer, 244862306a36Sopenharmony_ci offset, 244962306a36Sopenharmony_ci sgc->sender_uaddr + bytes_copied, 245062306a36Sopenharmony_ci copy_size); 245162306a36Sopenharmony_ci bytes_copied += copy_size; 245262306a36Sopenharmony_ci if (copy_size != bytes_left) { 245362306a36Sopenharmony_ci BUG_ON(!pf); 245462306a36Sopenharmony_ci /* we stopped at a fixup offset */ 245562306a36Sopenharmony_ci if (pf->skip_size) { 245662306a36Sopenharmony_ci /* 245762306a36Sopenharmony_ci * we are just skipping. This is for 245862306a36Sopenharmony_ci * BINDER_TYPE_FDA where the translated 245962306a36Sopenharmony_ci * fds will be fixed up when we get 246062306a36Sopenharmony_ci * to target context. 246162306a36Sopenharmony_ci */ 246262306a36Sopenharmony_ci bytes_copied += pf->skip_size; 246362306a36Sopenharmony_ci } else { 246462306a36Sopenharmony_ci /* apply the fixup indicated by pf */ 246562306a36Sopenharmony_ci if (!ret) 246662306a36Sopenharmony_ci ret = binder_alloc_copy_to_buffer( 246762306a36Sopenharmony_ci alloc, buffer, 246862306a36Sopenharmony_ci pf->offset, 246962306a36Sopenharmony_ci &pf->fixup_data, 247062306a36Sopenharmony_ci sizeof(pf->fixup_data)); 247162306a36Sopenharmony_ci bytes_copied += sizeof(pf->fixup_data); 247262306a36Sopenharmony_ci } 247362306a36Sopenharmony_ci list_del(&pf->node); 247462306a36Sopenharmony_ci kfree(pf); 247562306a36Sopenharmony_ci pf = list_first_entry_or_null(pf_head, 247662306a36Sopenharmony_ci struct binder_ptr_fixup, node); 247762306a36Sopenharmony_ci } 247862306a36Sopenharmony_ci } 247962306a36Sopenharmony_ci list_del(&sgc->node); 248062306a36Sopenharmony_ci kfree(sgc); 248162306a36Sopenharmony_ci } 248262306a36Sopenharmony_ci list_for_each_entry_safe(pf, tmppf, pf_head, node) { 248362306a36Sopenharmony_ci BUG_ON(pf->skip_size == 0); 248462306a36Sopenharmony_ci list_del(&pf->node); 248562306a36Sopenharmony_ci kfree(pf); 248662306a36Sopenharmony_ci } 248762306a36Sopenharmony_ci BUG_ON(!list_empty(sgc_head)); 248862306a36Sopenharmony_ci 248962306a36Sopenharmony_ci return ret > 0 ? -EINVAL : ret; 249062306a36Sopenharmony_ci} 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ci/** 249362306a36Sopenharmony_ci * binder_cleanup_deferred_txn_lists() - free specified lists 249462306a36Sopenharmony_ci * @sgc_head: list_head of scatter-gather copy list 249562306a36Sopenharmony_ci * @pf_head: list_head of pointer fixup list 249662306a36Sopenharmony_ci * 249762306a36Sopenharmony_ci * Called to clean up @sgc_head and @pf_head if there is an 249862306a36Sopenharmony_ci * error. 249962306a36Sopenharmony_ci */ 250062306a36Sopenharmony_cistatic void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head, 250162306a36Sopenharmony_ci struct list_head *pf_head) 250262306a36Sopenharmony_ci{ 250362306a36Sopenharmony_ci struct binder_sg_copy *sgc, *tmpsgc; 250462306a36Sopenharmony_ci struct binder_ptr_fixup *pf, *tmppf; 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci list_for_each_entry_safe(sgc, tmpsgc, sgc_head, node) { 250762306a36Sopenharmony_ci list_del(&sgc->node); 250862306a36Sopenharmony_ci kfree(sgc); 250962306a36Sopenharmony_ci } 251062306a36Sopenharmony_ci list_for_each_entry_safe(pf, tmppf, pf_head, node) { 251162306a36Sopenharmony_ci list_del(&pf->node); 251262306a36Sopenharmony_ci kfree(pf); 251362306a36Sopenharmony_ci } 251462306a36Sopenharmony_ci} 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci/** 251762306a36Sopenharmony_ci * binder_defer_copy() - queue a scatter-gather buffer for copy 251862306a36Sopenharmony_ci * @sgc_head: list_head of scatter-gather copy list 251962306a36Sopenharmony_ci * @offset: binder buffer offset in target process 252062306a36Sopenharmony_ci * @sender_uaddr: user address in source process 252162306a36Sopenharmony_ci * @length: bytes to copy 252262306a36Sopenharmony_ci * 252362306a36Sopenharmony_ci * Specify a scatter-gather block to be copied. The actual copy must 252462306a36Sopenharmony_ci * be deferred until all the needed fixups are identified and queued. 252562306a36Sopenharmony_ci * Then the copy and fixups are done together so un-translated values 252662306a36Sopenharmony_ci * from the source are never visible in the target buffer. 252762306a36Sopenharmony_ci * 252862306a36Sopenharmony_ci * We are guaranteed that repeated calls to this function will have 252962306a36Sopenharmony_ci * monotonically increasing @offset values so the list will naturally 253062306a36Sopenharmony_ci * be ordered. 253162306a36Sopenharmony_ci * 253262306a36Sopenharmony_ci * Return: 0=success, else -errno 253362306a36Sopenharmony_ci */ 253462306a36Sopenharmony_cistatic int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset, 253562306a36Sopenharmony_ci const void __user *sender_uaddr, size_t length) 253662306a36Sopenharmony_ci{ 253762306a36Sopenharmony_ci struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL); 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci if (!bc) 254062306a36Sopenharmony_ci return -ENOMEM; 254162306a36Sopenharmony_ci 254262306a36Sopenharmony_ci bc->offset = offset; 254362306a36Sopenharmony_ci bc->sender_uaddr = sender_uaddr; 254462306a36Sopenharmony_ci bc->length = length; 254562306a36Sopenharmony_ci INIT_LIST_HEAD(&bc->node); 254662306a36Sopenharmony_ci 254762306a36Sopenharmony_ci /* 254862306a36Sopenharmony_ci * We are guaranteed that the deferred copies are in-order 254962306a36Sopenharmony_ci * so just add to the tail. 255062306a36Sopenharmony_ci */ 255162306a36Sopenharmony_ci list_add_tail(&bc->node, sgc_head); 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_ci return 0; 255462306a36Sopenharmony_ci} 255562306a36Sopenharmony_ci 255662306a36Sopenharmony_ci/** 255762306a36Sopenharmony_ci * binder_add_fixup() - queue a fixup to be applied to sg copy 255862306a36Sopenharmony_ci * @pf_head: list_head of binder ptr fixup list 255962306a36Sopenharmony_ci * @offset: binder buffer offset in target process 256062306a36Sopenharmony_ci * @fixup: bytes to be copied for fixup 256162306a36Sopenharmony_ci * @skip_size: bytes to skip when copying (fixup will be applied later) 256262306a36Sopenharmony_ci * 256362306a36Sopenharmony_ci * Add the specified fixup to a list ordered by @offset. When copying 256462306a36Sopenharmony_ci * the scatter-gather buffers, the fixup will be copied instead of 256562306a36Sopenharmony_ci * data from the source buffer. For BINDER_TYPE_FDA fixups, the fixup 256662306a36Sopenharmony_ci * will be applied later (in target process context), so we just skip 256762306a36Sopenharmony_ci * the bytes specified by @skip_size. If @skip_size is 0, we copy the 256862306a36Sopenharmony_ci * value in @fixup. 256962306a36Sopenharmony_ci * 257062306a36Sopenharmony_ci * This function is called *mostly* in @offset order, but there are 257162306a36Sopenharmony_ci * exceptions. Since out-of-order inserts are relatively uncommon, 257262306a36Sopenharmony_ci * we insert the new element by searching backward from the tail of 257362306a36Sopenharmony_ci * the list. 257462306a36Sopenharmony_ci * 257562306a36Sopenharmony_ci * Return: 0=success, else -errno 257662306a36Sopenharmony_ci */ 257762306a36Sopenharmony_cistatic int binder_add_fixup(struct list_head *pf_head, binder_size_t offset, 257862306a36Sopenharmony_ci binder_uintptr_t fixup, size_t skip_size) 257962306a36Sopenharmony_ci{ 258062306a36Sopenharmony_ci struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL); 258162306a36Sopenharmony_ci struct binder_ptr_fixup *tmppf; 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci if (!pf) 258462306a36Sopenharmony_ci return -ENOMEM; 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci pf->offset = offset; 258762306a36Sopenharmony_ci pf->fixup_data = fixup; 258862306a36Sopenharmony_ci pf->skip_size = skip_size; 258962306a36Sopenharmony_ci INIT_LIST_HEAD(&pf->node); 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci /* Fixups are *mostly* added in-order, but there are some 259262306a36Sopenharmony_ci * exceptions. Look backwards through list for insertion point. 259362306a36Sopenharmony_ci */ 259462306a36Sopenharmony_ci list_for_each_entry_reverse(tmppf, pf_head, node) { 259562306a36Sopenharmony_ci if (tmppf->offset < pf->offset) { 259662306a36Sopenharmony_ci list_add(&pf->node, &tmppf->node); 259762306a36Sopenharmony_ci return 0; 259862306a36Sopenharmony_ci } 259962306a36Sopenharmony_ci } 260062306a36Sopenharmony_ci /* 260162306a36Sopenharmony_ci * if we get here, then the new offset is the lowest so 260262306a36Sopenharmony_ci * insert at the head 260362306a36Sopenharmony_ci */ 260462306a36Sopenharmony_ci list_add(&pf->node, pf_head); 260562306a36Sopenharmony_ci return 0; 260662306a36Sopenharmony_ci} 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_cistatic int binder_translate_fd_array(struct list_head *pf_head, 260962306a36Sopenharmony_ci struct binder_fd_array_object *fda, 261062306a36Sopenharmony_ci const void __user *sender_ubuffer, 261162306a36Sopenharmony_ci struct binder_buffer_object *parent, 261262306a36Sopenharmony_ci struct binder_buffer_object *sender_uparent, 261362306a36Sopenharmony_ci struct binder_transaction *t, 261462306a36Sopenharmony_ci struct binder_thread *thread, 261562306a36Sopenharmony_ci struct binder_transaction *in_reply_to) 261662306a36Sopenharmony_ci{ 261762306a36Sopenharmony_ci binder_size_t fdi, fd_buf_size; 261862306a36Sopenharmony_ci binder_size_t fda_offset; 261962306a36Sopenharmony_ci const void __user *sender_ufda_base; 262062306a36Sopenharmony_ci struct binder_proc *proc = thread->proc; 262162306a36Sopenharmony_ci int ret; 262262306a36Sopenharmony_ci 262362306a36Sopenharmony_ci if (fda->num_fds == 0) 262462306a36Sopenharmony_ci return 0; 262562306a36Sopenharmony_ci 262662306a36Sopenharmony_ci fd_buf_size = sizeof(u32) * fda->num_fds; 262762306a36Sopenharmony_ci if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { 262862306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid number of fds (%lld)\n", 262962306a36Sopenharmony_ci proc->pid, thread->pid, (u64)fda->num_fds); 263062306a36Sopenharmony_ci return -EINVAL; 263162306a36Sopenharmony_ci } 263262306a36Sopenharmony_ci if (fd_buf_size > parent->length || 263362306a36Sopenharmony_ci fda->parent_offset > parent->length - fd_buf_size) { 263462306a36Sopenharmony_ci /* No space for all file descriptors here. */ 263562306a36Sopenharmony_ci binder_user_error("%d:%d not enough space to store %lld fds in buffer\n", 263662306a36Sopenharmony_ci proc->pid, thread->pid, (u64)fda->num_fds); 263762306a36Sopenharmony_ci return -EINVAL; 263862306a36Sopenharmony_ci } 263962306a36Sopenharmony_ci /* 264062306a36Sopenharmony_ci * the source data for binder_buffer_object is visible 264162306a36Sopenharmony_ci * to user-space and the @buffer element is the user 264262306a36Sopenharmony_ci * pointer to the buffer_object containing the fd_array. 264362306a36Sopenharmony_ci * Convert the address to an offset relative to 264462306a36Sopenharmony_ci * the base of the transaction buffer. 264562306a36Sopenharmony_ci */ 264662306a36Sopenharmony_ci fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) + 264762306a36Sopenharmony_ci fda->parent_offset; 264862306a36Sopenharmony_ci sender_ufda_base = (void __user *)(uintptr_t)sender_uparent->buffer + 264962306a36Sopenharmony_ci fda->parent_offset; 265062306a36Sopenharmony_ci 265162306a36Sopenharmony_ci if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32)) || 265262306a36Sopenharmony_ci !IS_ALIGNED((unsigned long)sender_ufda_base, sizeof(u32))) { 265362306a36Sopenharmony_ci binder_user_error("%d:%d parent offset not aligned correctly.\n", 265462306a36Sopenharmony_ci proc->pid, thread->pid); 265562306a36Sopenharmony_ci return -EINVAL; 265662306a36Sopenharmony_ci } 265762306a36Sopenharmony_ci ret = binder_add_fixup(pf_head, fda_offset, 0, fda->num_fds * sizeof(u32)); 265862306a36Sopenharmony_ci if (ret) 265962306a36Sopenharmony_ci return ret; 266062306a36Sopenharmony_ci 266162306a36Sopenharmony_ci for (fdi = 0; fdi < fda->num_fds; fdi++) { 266262306a36Sopenharmony_ci u32 fd; 266362306a36Sopenharmony_ci binder_size_t offset = fda_offset + fdi * sizeof(fd); 266462306a36Sopenharmony_ci binder_size_t sender_uoffset = fdi * sizeof(fd); 266562306a36Sopenharmony_ci 266662306a36Sopenharmony_ci ret = copy_from_user(&fd, sender_ufda_base + sender_uoffset, sizeof(fd)); 266762306a36Sopenharmony_ci if (!ret) 266862306a36Sopenharmony_ci ret = binder_translate_fd(fd, offset, t, thread, 266962306a36Sopenharmony_ci in_reply_to); 267062306a36Sopenharmony_ci if (ret) 267162306a36Sopenharmony_ci return ret > 0 ? -EINVAL : ret; 267262306a36Sopenharmony_ci } 267362306a36Sopenharmony_ci return 0; 267462306a36Sopenharmony_ci} 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_cistatic int binder_fixup_parent(struct list_head *pf_head, 267762306a36Sopenharmony_ci struct binder_transaction *t, 267862306a36Sopenharmony_ci struct binder_thread *thread, 267962306a36Sopenharmony_ci struct binder_buffer_object *bp, 268062306a36Sopenharmony_ci binder_size_t off_start_offset, 268162306a36Sopenharmony_ci binder_size_t num_valid, 268262306a36Sopenharmony_ci binder_size_t last_fixup_obj_off, 268362306a36Sopenharmony_ci binder_size_t last_fixup_min_off) 268462306a36Sopenharmony_ci{ 268562306a36Sopenharmony_ci struct binder_buffer_object *parent; 268662306a36Sopenharmony_ci struct binder_buffer *b = t->buffer; 268762306a36Sopenharmony_ci struct binder_proc *proc = thread->proc; 268862306a36Sopenharmony_ci struct binder_proc *target_proc = t->to_proc; 268962306a36Sopenharmony_ci struct binder_object object; 269062306a36Sopenharmony_ci binder_size_t buffer_offset; 269162306a36Sopenharmony_ci binder_size_t parent_offset; 269262306a36Sopenharmony_ci 269362306a36Sopenharmony_ci if (!(bp->flags & BINDER_BUFFER_FLAG_HAS_PARENT)) 269462306a36Sopenharmony_ci return 0; 269562306a36Sopenharmony_ci 269662306a36Sopenharmony_ci parent = binder_validate_ptr(target_proc, b, &object, bp->parent, 269762306a36Sopenharmony_ci off_start_offset, &parent_offset, 269862306a36Sopenharmony_ci num_valid); 269962306a36Sopenharmony_ci if (!parent) { 270062306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid parent offset or type\n", 270162306a36Sopenharmony_ci proc->pid, thread->pid); 270262306a36Sopenharmony_ci return -EINVAL; 270362306a36Sopenharmony_ci } 270462306a36Sopenharmony_ci 270562306a36Sopenharmony_ci if (!binder_validate_fixup(target_proc, b, off_start_offset, 270662306a36Sopenharmony_ci parent_offset, bp->parent_offset, 270762306a36Sopenharmony_ci last_fixup_obj_off, 270862306a36Sopenharmony_ci last_fixup_min_off)) { 270962306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n", 271062306a36Sopenharmony_ci proc->pid, thread->pid); 271162306a36Sopenharmony_ci return -EINVAL; 271262306a36Sopenharmony_ci } 271362306a36Sopenharmony_ci 271462306a36Sopenharmony_ci if (parent->length < sizeof(binder_uintptr_t) || 271562306a36Sopenharmony_ci bp->parent_offset > parent->length - sizeof(binder_uintptr_t)) { 271662306a36Sopenharmony_ci /* No space for a pointer here! */ 271762306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid parent offset\n", 271862306a36Sopenharmony_ci proc->pid, thread->pid); 271962306a36Sopenharmony_ci return -EINVAL; 272062306a36Sopenharmony_ci } 272162306a36Sopenharmony_ci buffer_offset = bp->parent_offset + 272262306a36Sopenharmony_ci (uintptr_t)parent->buffer - (uintptr_t)b->user_data; 272362306a36Sopenharmony_ci return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0); 272462306a36Sopenharmony_ci} 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci/** 272762306a36Sopenharmony_ci * binder_can_update_transaction() - Can a txn be superseded by an updated one? 272862306a36Sopenharmony_ci * @t1: the pending async txn in the frozen process 272962306a36Sopenharmony_ci * @t2: the new async txn to supersede the outdated pending one 273062306a36Sopenharmony_ci * 273162306a36Sopenharmony_ci * Return: true if t2 can supersede t1 273262306a36Sopenharmony_ci * false if t2 can not supersede t1 273362306a36Sopenharmony_ci */ 273462306a36Sopenharmony_cistatic bool binder_can_update_transaction(struct binder_transaction *t1, 273562306a36Sopenharmony_ci struct binder_transaction *t2) 273662306a36Sopenharmony_ci{ 273762306a36Sopenharmony_ci if ((t1->flags & t2->flags & (TF_ONE_WAY | TF_UPDATE_TXN)) != 273862306a36Sopenharmony_ci (TF_ONE_WAY | TF_UPDATE_TXN) || !t1->to_proc || !t2->to_proc) 273962306a36Sopenharmony_ci return false; 274062306a36Sopenharmony_ci if (t1->to_proc->tsk == t2->to_proc->tsk && t1->code == t2->code && 274162306a36Sopenharmony_ci t1->flags == t2->flags && t1->buffer->pid == t2->buffer->pid && 274262306a36Sopenharmony_ci t1->buffer->target_node->ptr == t2->buffer->target_node->ptr && 274362306a36Sopenharmony_ci t1->buffer->target_node->cookie == t2->buffer->target_node->cookie) 274462306a36Sopenharmony_ci return true; 274562306a36Sopenharmony_ci return false; 274662306a36Sopenharmony_ci} 274762306a36Sopenharmony_ci 274862306a36Sopenharmony_ci/** 274962306a36Sopenharmony_ci * binder_find_outdated_transaction_ilocked() - Find the outdated transaction 275062306a36Sopenharmony_ci * @t: new async transaction 275162306a36Sopenharmony_ci * @target_list: list to find outdated transaction 275262306a36Sopenharmony_ci * 275362306a36Sopenharmony_ci * Return: the outdated transaction if found 275462306a36Sopenharmony_ci * NULL if no outdated transacton can be found 275562306a36Sopenharmony_ci * 275662306a36Sopenharmony_ci * Requires the proc->inner_lock to be held. 275762306a36Sopenharmony_ci */ 275862306a36Sopenharmony_cistatic struct binder_transaction * 275962306a36Sopenharmony_cibinder_find_outdated_transaction_ilocked(struct binder_transaction *t, 276062306a36Sopenharmony_ci struct list_head *target_list) 276162306a36Sopenharmony_ci{ 276262306a36Sopenharmony_ci struct binder_work *w; 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci list_for_each_entry(w, target_list, entry) { 276562306a36Sopenharmony_ci struct binder_transaction *t_queued; 276662306a36Sopenharmony_ci 276762306a36Sopenharmony_ci if (w->type != BINDER_WORK_TRANSACTION) 276862306a36Sopenharmony_ci continue; 276962306a36Sopenharmony_ci t_queued = container_of(w, struct binder_transaction, work); 277062306a36Sopenharmony_ci if (binder_can_update_transaction(t_queued, t)) 277162306a36Sopenharmony_ci return t_queued; 277262306a36Sopenharmony_ci } 277362306a36Sopenharmony_ci return NULL; 277462306a36Sopenharmony_ci} 277562306a36Sopenharmony_ci 277662306a36Sopenharmony_ci/** 277762306a36Sopenharmony_ci * binder_proc_transaction() - sends a transaction to a process and wakes it up 277862306a36Sopenharmony_ci * @t: transaction to send 277962306a36Sopenharmony_ci * @proc: process to send the transaction to 278062306a36Sopenharmony_ci * @thread: thread in @proc to send the transaction to (may be NULL) 278162306a36Sopenharmony_ci * 278262306a36Sopenharmony_ci * This function queues a transaction to the specified process. It will try 278362306a36Sopenharmony_ci * to find a thread in the target process to handle the transaction and 278462306a36Sopenharmony_ci * wake it up. If no thread is found, the work is queued to the proc 278562306a36Sopenharmony_ci * waitqueue. 278662306a36Sopenharmony_ci * 278762306a36Sopenharmony_ci * If the @thread parameter is not NULL, the transaction is always queued 278862306a36Sopenharmony_ci * to the waitlist of that specific thread. 278962306a36Sopenharmony_ci * 279062306a36Sopenharmony_ci * Return: 0 if the transaction was successfully queued 279162306a36Sopenharmony_ci * BR_DEAD_REPLY if the target process or thread is dead 279262306a36Sopenharmony_ci * BR_FROZEN_REPLY if the target process or thread is frozen and 279362306a36Sopenharmony_ci * the sync transaction was rejected 279462306a36Sopenharmony_ci * BR_TRANSACTION_PENDING_FROZEN if the target process is frozen 279562306a36Sopenharmony_ci * and the async transaction was successfully queued 279662306a36Sopenharmony_ci */ 279762306a36Sopenharmony_cistatic int binder_proc_transaction(struct binder_transaction *t, 279862306a36Sopenharmony_ci struct binder_proc *proc, 279962306a36Sopenharmony_ci struct binder_thread *thread) 280062306a36Sopenharmony_ci{ 280162306a36Sopenharmony_ci struct binder_node *node = t->buffer->target_node; 280262306a36Sopenharmony_ci bool oneway = !!(t->flags & TF_ONE_WAY); 280362306a36Sopenharmony_ci bool pending_async = false; 280462306a36Sopenharmony_ci struct binder_transaction *t_outdated = NULL; 280562306a36Sopenharmony_ci bool frozen = false; 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_ci BUG_ON(!node); 280862306a36Sopenharmony_ci binder_node_lock(node); 280962306a36Sopenharmony_ci if (oneway) { 281062306a36Sopenharmony_ci BUG_ON(thread); 281162306a36Sopenharmony_ci if (node->has_async_transaction) 281262306a36Sopenharmony_ci pending_async = true; 281362306a36Sopenharmony_ci else 281462306a36Sopenharmony_ci node->has_async_transaction = true; 281562306a36Sopenharmony_ci } 281662306a36Sopenharmony_ci 281762306a36Sopenharmony_ci binder_inner_proc_lock(proc); 281862306a36Sopenharmony_ci if (proc->is_frozen) { 281962306a36Sopenharmony_ci frozen = true; 282062306a36Sopenharmony_ci proc->sync_recv |= !oneway; 282162306a36Sopenharmony_ci proc->async_recv |= oneway; 282262306a36Sopenharmony_ci } 282362306a36Sopenharmony_ci 282462306a36Sopenharmony_ci if ((frozen && !oneway) || proc->is_dead || 282562306a36Sopenharmony_ci (thread && thread->is_dead)) { 282662306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 282762306a36Sopenharmony_ci binder_node_unlock(node); 282862306a36Sopenharmony_ci return frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY; 282962306a36Sopenharmony_ci } 283062306a36Sopenharmony_ci 283162306a36Sopenharmony_ci if (!thread && !pending_async) 283262306a36Sopenharmony_ci thread = binder_select_thread_ilocked(proc); 283362306a36Sopenharmony_ci 283462306a36Sopenharmony_ci if (thread) { 283562306a36Sopenharmony_ci binder_enqueue_thread_work_ilocked(thread, &t->work); 283662306a36Sopenharmony_ci } else if (!pending_async) { 283762306a36Sopenharmony_ci binder_enqueue_work_ilocked(&t->work, &proc->todo); 283862306a36Sopenharmony_ci } else { 283962306a36Sopenharmony_ci if ((t->flags & TF_UPDATE_TXN) && frozen) { 284062306a36Sopenharmony_ci t_outdated = binder_find_outdated_transaction_ilocked(t, 284162306a36Sopenharmony_ci &node->async_todo); 284262306a36Sopenharmony_ci if (t_outdated) { 284362306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 284462306a36Sopenharmony_ci "txn %d supersedes %d\n", 284562306a36Sopenharmony_ci t->debug_id, t_outdated->debug_id); 284662306a36Sopenharmony_ci list_del_init(&t_outdated->work.entry); 284762306a36Sopenharmony_ci proc->outstanding_txns--; 284862306a36Sopenharmony_ci } 284962306a36Sopenharmony_ci } 285062306a36Sopenharmony_ci binder_enqueue_work_ilocked(&t->work, &node->async_todo); 285162306a36Sopenharmony_ci } 285262306a36Sopenharmony_ci 285362306a36Sopenharmony_ci if (!pending_async) 285462306a36Sopenharmony_ci binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_ci proc->outstanding_txns++; 285762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 285862306a36Sopenharmony_ci binder_node_unlock(node); 285962306a36Sopenharmony_ci 286062306a36Sopenharmony_ci /* 286162306a36Sopenharmony_ci * To reduce potential contention, free the outdated transaction and 286262306a36Sopenharmony_ci * buffer after releasing the locks. 286362306a36Sopenharmony_ci */ 286462306a36Sopenharmony_ci if (t_outdated) { 286562306a36Sopenharmony_ci struct binder_buffer *buffer = t_outdated->buffer; 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci t_outdated->buffer = NULL; 286862306a36Sopenharmony_ci buffer->transaction = NULL; 286962306a36Sopenharmony_ci trace_binder_transaction_update_buffer_release(buffer); 287062306a36Sopenharmony_ci binder_release_entire_buffer(proc, NULL, buffer, false); 287162306a36Sopenharmony_ci binder_alloc_free_buf(&proc->alloc, buffer); 287262306a36Sopenharmony_ci kfree(t_outdated); 287362306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_TRANSACTION); 287462306a36Sopenharmony_ci } 287562306a36Sopenharmony_ci 287662306a36Sopenharmony_ci if (oneway && frozen) 287762306a36Sopenharmony_ci return BR_TRANSACTION_PENDING_FROZEN; 287862306a36Sopenharmony_ci 287962306a36Sopenharmony_ci return 0; 288062306a36Sopenharmony_ci} 288162306a36Sopenharmony_ci 288262306a36Sopenharmony_ci/** 288362306a36Sopenharmony_ci * binder_get_node_refs_for_txn() - Get required refs on node for txn 288462306a36Sopenharmony_ci * @node: struct binder_node for which to get refs 288562306a36Sopenharmony_ci * @procp: returns @node->proc if valid 288662306a36Sopenharmony_ci * @error: if no @procp then returns BR_DEAD_REPLY 288762306a36Sopenharmony_ci * 288862306a36Sopenharmony_ci * User-space normally keeps the node alive when creating a transaction 288962306a36Sopenharmony_ci * since it has a reference to the target. The local strong ref keeps it 289062306a36Sopenharmony_ci * alive if the sending process dies before the target process processes 289162306a36Sopenharmony_ci * the transaction. If the source process is malicious or has a reference 289262306a36Sopenharmony_ci * counting bug, relying on the local strong ref can fail. 289362306a36Sopenharmony_ci * 289462306a36Sopenharmony_ci * Since user-space can cause the local strong ref to go away, we also take 289562306a36Sopenharmony_ci * a tmpref on the node to ensure it survives while we are constructing 289662306a36Sopenharmony_ci * the transaction. We also need a tmpref on the proc while we are 289762306a36Sopenharmony_ci * constructing the transaction, so we take that here as well. 289862306a36Sopenharmony_ci * 289962306a36Sopenharmony_ci * Return: The target_node with refs taken or NULL if no @node->proc is NULL. 290062306a36Sopenharmony_ci * Also sets @procp if valid. If the @node->proc is NULL indicating that the 290162306a36Sopenharmony_ci * target proc has died, @error is set to BR_DEAD_REPLY. 290262306a36Sopenharmony_ci */ 290362306a36Sopenharmony_cistatic struct binder_node *binder_get_node_refs_for_txn( 290462306a36Sopenharmony_ci struct binder_node *node, 290562306a36Sopenharmony_ci struct binder_proc **procp, 290662306a36Sopenharmony_ci uint32_t *error) 290762306a36Sopenharmony_ci{ 290862306a36Sopenharmony_ci struct binder_node *target_node = NULL; 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_ci binder_node_inner_lock(node); 291162306a36Sopenharmony_ci if (node->proc) { 291262306a36Sopenharmony_ci target_node = node; 291362306a36Sopenharmony_ci binder_inc_node_nilocked(node, 1, 0, NULL); 291462306a36Sopenharmony_ci binder_inc_node_tmpref_ilocked(node); 291562306a36Sopenharmony_ci node->proc->tmp_ref++; 291662306a36Sopenharmony_ci *procp = node->proc; 291762306a36Sopenharmony_ci } else 291862306a36Sopenharmony_ci *error = BR_DEAD_REPLY; 291962306a36Sopenharmony_ci binder_node_inner_unlock(node); 292062306a36Sopenharmony_ci 292162306a36Sopenharmony_ci return target_node; 292262306a36Sopenharmony_ci} 292362306a36Sopenharmony_ci 292462306a36Sopenharmony_cistatic void binder_set_txn_from_error(struct binder_transaction *t, int id, 292562306a36Sopenharmony_ci uint32_t command, int32_t param) 292662306a36Sopenharmony_ci{ 292762306a36Sopenharmony_ci struct binder_thread *from = binder_get_txn_from_and_acq_inner(t); 292862306a36Sopenharmony_ci 292962306a36Sopenharmony_ci if (!from) { 293062306a36Sopenharmony_ci /* annotation for sparse */ 293162306a36Sopenharmony_ci __release(&from->proc->inner_lock); 293262306a36Sopenharmony_ci return; 293362306a36Sopenharmony_ci } 293462306a36Sopenharmony_ci 293562306a36Sopenharmony_ci /* don't override existing errors */ 293662306a36Sopenharmony_ci if (from->ee.command == BR_OK) 293762306a36Sopenharmony_ci binder_set_extended_error(&from->ee, id, command, param); 293862306a36Sopenharmony_ci binder_inner_proc_unlock(from->proc); 293962306a36Sopenharmony_ci binder_thread_dec_tmpref(from); 294062306a36Sopenharmony_ci} 294162306a36Sopenharmony_ci 294262306a36Sopenharmony_cistatic void binder_transaction(struct binder_proc *proc, 294362306a36Sopenharmony_ci struct binder_thread *thread, 294462306a36Sopenharmony_ci struct binder_transaction_data *tr, int reply, 294562306a36Sopenharmony_ci binder_size_t extra_buffers_size) 294662306a36Sopenharmony_ci{ 294762306a36Sopenharmony_ci int ret; 294862306a36Sopenharmony_ci struct binder_transaction *t; 294962306a36Sopenharmony_ci struct binder_work *w; 295062306a36Sopenharmony_ci struct binder_work *tcomplete; 295162306a36Sopenharmony_ci binder_size_t buffer_offset = 0; 295262306a36Sopenharmony_ci binder_size_t off_start_offset, off_end_offset; 295362306a36Sopenharmony_ci binder_size_t off_min; 295462306a36Sopenharmony_ci binder_size_t sg_buf_offset, sg_buf_end_offset; 295562306a36Sopenharmony_ci binder_size_t user_offset = 0; 295662306a36Sopenharmony_ci struct binder_proc *target_proc = NULL; 295762306a36Sopenharmony_ci struct binder_thread *target_thread = NULL; 295862306a36Sopenharmony_ci struct binder_node *target_node = NULL; 295962306a36Sopenharmony_ci struct binder_transaction *in_reply_to = NULL; 296062306a36Sopenharmony_ci struct binder_transaction_log_entry *e; 296162306a36Sopenharmony_ci uint32_t return_error = 0; 296262306a36Sopenharmony_ci uint32_t return_error_param = 0; 296362306a36Sopenharmony_ci uint32_t return_error_line = 0; 296462306a36Sopenharmony_ci binder_size_t last_fixup_obj_off = 0; 296562306a36Sopenharmony_ci binder_size_t last_fixup_min_off = 0; 296662306a36Sopenharmony_ci struct binder_context *context = proc->context; 296762306a36Sopenharmony_ci int t_debug_id = atomic_inc_return(&binder_last_id); 296862306a36Sopenharmony_ci ktime_t t_start_time = ktime_get(); 296962306a36Sopenharmony_ci char *secctx = NULL; 297062306a36Sopenharmony_ci u32 secctx_sz = 0; 297162306a36Sopenharmony_ci struct list_head sgc_head; 297262306a36Sopenharmony_ci struct list_head pf_head; 297362306a36Sopenharmony_ci const void __user *user_buffer = (const void __user *) 297462306a36Sopenharmony_ci (uintptr_t)tr->data.ptr.buffer; 297562306a36Sopenharmony_ci INIT_LIST_HEAD(&sgc_head); 297662306a36Sopenharmony_ci INIT_LIST_HEAD(&pf_head); 297762306a36Sopenharmony_ci 297862306a36Sopenharmony_ci e = binder_transaction_log_add(&binder_transaction_log); 297962306a36Sopenharmony_ci e->debug_id = t_debug_id; 298062306a36Sopenharmony_ci e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY); 298162306a36Sopenharmony_ci e->from_proc = proc->pid; 298262306a36Sopenharmony_ci e->from_thread = thread->pid; 298362306a36Sopenharmony_ci e->target_handle = tr->target.handle; 298462306a36Sopenharmony_ci e->data_size = tr->data_size; 298562306a36Sopenharmony_ci e->offsets_size = tr->offsets_size; 298662306a36Sopenharmony_ci strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME); 298762306a36Sopenharmony_ci 298862306a36Sopenharmony_ci binder_inner_proc_lock(proc); 298962306a36Sopenharmony_ci binder_set_extended_error(&thread->ee, t_debug_id, BR_OK, 0); 299062306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 299162306a36Sopenharmony_ci 299262306a36Sopenharmony_ci if (reply) { 299362306a36Sopenharmony_ci binder_inner_proc_lock(proc); 299462306a36Sopenharmony_ci in_reply_to = thread->transaction_stack; 299562306a36Sopenharmony_ci if (in_reply_to == NULL) { 299662306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 299762306a36Sopenharmony_ci binder_user_error("%d:%d got reply transaction with no transaction stack\n", 299862306a36Sopenharmony_ci proc->pid, thread->pid); 299962306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 300062306a36Sopenharmony_ci return_error_param = -EPROTO; 300162306a36Sopenharmony_ci return_error_line = __LINE__; 300262306a36Sopenharmony_ci goto err_empty_call_stack; 300362306a36Sopenharmony_ci } 300462306a36Sopenharmony_ci if (in_reply_to->to_thread != thread) { 300562306a36Sopenharmony_ci spin_lock(&in_reply_to->lock); 300662306a36Sopenharmony_ci binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n", 300762306a36Sopenharmony_ci proc->pid, thread->pid, in_reply_to->debug_id, 300862306a36Sopenharmony_ci in_reply_to->to_proc ? 300962306a36Sopenharmony_ci in_reply_to->to_proc->pid : 0, 301062306a36Sopenharmony_ci in_reply_to->to_thread ? 301162306a36Sopenharmony_ci in_reply_to->to_thread->pid : 0); 301262306a36Sopenharmony_ci spin_unlock(&in_reply_to->lock); 301362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 301462306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 301562306a36Sopenharmony_ci return_error_param = -EPROTO; 301662306a36Sopenharmony_ci return_error_line = __LINE__; 301762306a36Sopenharmony_ci in_reply_to = NULL; 301862306a36Sopenharmony_ci goto err_bad_call_stack; 301962306a36Sopenharmony_ci } 302062306a36Sopenharmony_ci thread->transaction_stack = in_reply_to->to_parent; 302162306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 302262306a36Sopenharmony_ci binder_set_nice(in_reply_to->saved_priority); 302362306a36Sopenharmony_ci target_thread = binder_get_txn_from_and_acq_inner(in_reply_to); 302462306a36Sopenharmony_ci if (target_thread == NULL) { 302562306a36Sopenharmony_ci /* annotation for sparse */ 302662306a36Sopenharmony_ci __release(&target_thread->proc->inner_lock); 302762306a36Sopenharmony_ci binder_txn_error("%d:%d reply target not found\n", 302862306a36Sopenharmony_ci thread->pid, proc->pid); 302962306a36Sopenharmony_ci return_error = BR_DEAD_REPLY; 303062306a36Sopenharmony_ci return_error_line = __LINE__; 303162306a36Sopenharmony_ci goto err_dead_binder; 303262306a36Sopenharmony_ci } 303362306a36Sopenharmony_ci if (target_thread->transaction_stack != in_reply_to) { 303462306a36Sopenharmony_ci binder_user_error("%d:%d got reply transaction with bad target transaction stack %d, expected %d\n", 303562306a36Sopenharmony_ci proc->pid, thread->pid, 303662306a36Sopenharmony_ci target_thread->transaction_stack ? 303762306a36Sopenharmony_ci target_thread->transaction_stack->debug_id : 0, 303862306a36Sopenharmony_ci in_reply_to->debug_id); 303962306a36Sopenharmony_ci binder_inner_proc_unlock(target_thread->proc); 304062306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 304162306a36Sopenharmony_ci return_error_param = -EPROTO; 304262306a36Sopenharmony_ci return_error_line = __LINE__; 304362306a36Sopenharmony_ci in_reply_to = NULL; 304462306a36Sopenharmony_ci target_thread = NULL; 304562306a36Sopenharmony_ci goto err_dead_binder; 304662306a36Sopenharmony_ci } 304762306a36Sopenharmony_ci target_proc = target_thread->proc; 304862306a36Sopenharmony_ci target_proc->tmp_ref++; 304962306a36Sopenharmony_ci binder_inner_proc_unlock(target_thread->proc); 305062306a36Sopenharmony_ci } else { 305162306a36Sopenharmony_ci if (tr->target.handle) { 305262306a36Sopenharmony_ci struct binder_ref *ref; 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_ci /* 305562306a36Sopenharmony_ci * There must already be a strong ref 305662306a36Sopenharmony_ci * on this node. If so, do a strong 305762306a36Sopenharmony_ci * increment on the node to ensure it 305862306a36Sopenharmony_ci * stays alive until the transaction is 305962306a36Sopenharmony_ci * done. 306062306a36Sopenharmony_ci */ 306162306a36Sopenharmony_ci binder_proc_lock(proc); 306262306a36Sopenharmony_ci ref = binder_get_ref_olocked(proc, tr->target.handle, 306362306a36Sopenharmony_ci true); 306462306a36Sopenharmony_ci if (ref) { 306562306a36Sopenharmony_ci target_node = binder_get_node_refs_for_txn( 306662306a36Sopenharmony_ci ref->node, &target_proc, 306762306a36Sopenharmony_ci &return_error); 306862306a36Sopenharmony_ci } else { 306962306a36Sopenharmony_ci binder_user_error("%d:%d got transaction to invalid handle, %u\n", 307062306a36Sopenharmony_ci proc->pid, thread->pid, tr->target.handle); 307162306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 307262306a36Sopenharmony_ci } 307362306a36Sopenharmony_ci binder_proc_unlock(proc); 307462306a36Sopenharmony_ci } else { 307562306a36Sopenharmony_ci mutex_lock(&context->context_mgr_node_lock); 307662306a36Sopenharmony_ci target_node = context->binder_context_mgr_node; 307762306a36Sopenharmony_ci if (target_node) 307862306a36Sopenharmony_ci target_node = binder_get_node_refs_for_txn( 307962306a36Sopenharmony_ci target_node, &target_proc, 308062306a36Sopenharmony_ci &return_error); 308162306a36Sopenharmony_ci else 308262306a36Sopenharmony_ci return_error = BR_DEAD_REPLY; 308362306a36Sopenharmony_ci mutex_unlock(&context->context_mgr_node_lock); 308462306a36Sopenharmony_ci if (target_node && target_proc->pid == proc->pid) { 308562306a36Sopenharmony_ci binder_user_error("%d:%d got transaction to context manager from process owning it\n", 308662306a36Sopenharmony_ci proc->pid, thread->pid); 308762306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 308862306a36Sopenharmony_ci return_error_param = -EINVAL; 308962306a36Sopenharmony_ci return_error_line = __LINE__; 309062306a36Sopenharmony_ci goto err_invalid_target_handle; 309162306a36Sopenharmony_ci } 309262306a36Sopenharmony_ci } 309362306a36Sopenharmony_ci if (!target_node) { 309462306a36Sopenharmony_ci binder_txn_error("%d:%d cannot find target node\n", 309562306a36Sopenharmony_ci thread->pid, proc->pid); 309662306a36Sopenharmony_ci /* 309762306a36Sopenharmony_ci * return_error is set above 309862306a36Sopenharmony_ci */ 309962306a36Sopenharmony_ci return_error_param = -EINVAL; 310062306a36Sopenharmony_ci return_error_line = __LINE__; 310162306a36Sopenharmony_ci goto err_dead_binder; 310262306a36Sopenharmony_ci } 310362306a36Sopenharmony_ci e->to_node = target_node->debug_id; 310462306a36Sopenharmony_ci if (WARN_ON(proc == target_proc)) { 310562306a36Sopenharmony_ci binder_txn_error("%d:%d self transactions not allowed\n", 310662306a36Sopenharmony_ci thread->pid, proc->pid); 310762306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 310862306a36Sopenharmony_ci return_error_param = -EINVAL; 310962306a36Sopenharmony_ci return_error_line = __LINE__; 311062306a36Sopenharmony_ci goto err_invalid_target_handle; 311162306a36Sopenharmony_ci } 311262306a36Sopenharmony_ci if (security_binder_transaction(proc->cred, 311362306a36Sopenharmony_ci target_proc->cred) < 0) { 311462306a36Sopenharmony_ci binder_txn_error("%d:%d transaction credentials failed\n", 311562306a36Sopenharmony_ci thread->pid, proc->pid); 311662306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 311762306a36Sopenharmony_ci return_error_param = -EPERM; 311862306a36Sopenharmony_ci return_error_line = __LINE__; 311962306a36Sopenharmony_ci goto err_invalid_target_handle; 312062306a36Sopenharmony_ci } 312162306a36Sopenharmony_ci binder_inner_proc_lock(proc); 312262306a36Sopenharmony_ci 312362306a36Sopenharmony_ci w = list_first_entry_or_null(&thread->todo, 312462306a36Sopenharmony_ci struct binder_work, entry); 312562306a36Sopenharmony_ci if (!(tr->flags & TF_ONE_WAY) && w && 312662306a36Sopenharmony_ci w->type == BINDER_WORK_TRANSACTION) { 312762306a36Sopenharmony_ci /* 312862306a36Sopenharmony_ci * Do not allow new outgoing transaction from a 312962306a36Sopenharmony_ci * thread that has a transaction at the head of 313062306a36Sopenharmony_ci * its todo list. Only need to check the head 313162306a36Sopenharmony_ci * because binder_select_thread_ilocked picks a 313262306a36Sopenharmony_ci * thread from proc->waiting_threads to enqueue 313362306a36Sopenharmony_ci * the transaction, and nothing is queued to the 313462306a36Sopenharmony_ci * todo list while the thread is on waiting_threads. 313562306a36Sopenharmony_ci */ 313662306a36Sopenharmony_ci binder_user_error("%d:%d new transaction not allowed when there is a transaction on thread todo\n", 313762306a36Sopenharmony_ci proc->pid, thread->pid); 313862306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 313962306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 314062306a36Sopenharmony_ci return_error_param = -EPROTO; 314162306a36Sopenharmony_ci return_error_line = __LINE__; 314262306a36Sopenharmony_ci goto err_bad_todo_list; 314362306a36Sopenharmony_ci } 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) { 314662306a36Sopenharmony_ci struct binder_transaction *tmp; 314762306a36Sopenharmony_ci 314862306a36Sopenharmony_ci tmp = thread->transaction_stack; 314962306a36Sopenharmony_ci if (tmp->to_thread != thread) { 315062306a36Sopenharmony_ci spin_lock(&tmp->lock); 315162306a36Sopenharmony_ci binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n", 315262306a36Sopenharmony_ci proc->pid, thread->pid, tmp->debug_id, 315362306a36Sopenharmony_ci tmp->to_proc ? tmp->to_proc->pid : 0, 315462306a36Sopenharmony_ci tmp->to_thread ? 315562306a36Sopenharmony_ci tmp->to_thread->pid : 0); 315662306a36Sopenharmony_ci spin_unlock(&tmp->lock); 315762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 315862306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 315962306a36Sopenharmony_ci return_error_param = -EPROTO; 316062306a36Sopenharmony_ci return_error_line = __LINE__; 316162306a36Sopenharmony_ci goto err_bad_call_stack; 316262306a36Sopenharmony_ci } 316362306a36Sopenharmony_ci while (tmp) { 316462306a36Sopenharmony_ci struct binder_thread *from; 316562306a36Sopenharmony_ci 316662306a36Sopenharmony_ci spin_lock(&tmp->lock); 316762306a36Sopenharmony_ci from = tmp->from; 316862306a36Sopenharmony_ci if (from && from->proc == target_proc) { 316962306a36Sopenharmony_ci atomic_inc(&from->tmp_ref); 317062306a36Sopenharmony_ci target_thread = from; 317162306a36Sopenharmony_ci spin_unlock(&tmp->lock); 317262306a36Sopenharmony_ci break; 317362306a36Sopenharmony_ci } 317462306a36Sopenharmony_ci spin_unlock(&tmp->lock); 317562306a36Sopenharmony_ci tmp = tmp->from_parent; 317662306a36Sopenharmony_ci } 317762306a36Sopenharmony_ci } 317862306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 317962306a36Sopenharmony_ci } 318062306a36Sopenharmony_ci if (target_thread) 318162306a36Sopenharmony_ci e->to_thread = target_thread->pid; 318262306a36Sopenharmony_ci e->to_proc = target_proc->pid; 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ci /* TODO: reuse incoming transaction for reply */ 318562306a36Sopenharmony_ci t = kzalloc(sizeof(*t), GFP_KERNEL); 318662306a36Sopenharmony_ci if (t == NULL) { 318762306a36Sopenharmony_ci binder_txn_error("%d:%d cannot allocate transaction\n", 318862306a36Sopenharmony_ci thread->pid, proc->pid); 318962306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 319062306a36Sopenharmony_ci return_error_param = -ENOMEM; 319162306a36Sopenharmony_ci return_error_line = __LINE__; 319262306a36Sopenharmony_ci goto err_alloc_t_failed; 319362306a36Sopenharmony_ci } 319462306a36Sopenharmony_ci INIT_LIST_HEAD(&t->fd_fixups); 319562306a36Sopenharmony_ci binder_stats_created(BINDER_STAT_TRANSACTION); 319662306a36Sopenharmony_ci spin_lock_init(&t->lock); 319762306a36Sopenharmony_ci 319862306a36Sopenharmony_ci tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); 319962306a36Sopenharmony_ci if (tcomplete == NULL) { 320062306a36Sopenharmony_ci binder_txn_error("%d:%d cannot allocate work for transaction\n", 320162306a36Sopenharmony_ci thread->pid, proc->pid); 320262306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 320362306a36Sopenharmony_ci return_error_param = -ENOMEM; 320462306a36Sopenharmony_ci return_error_line = __LINE__; 320562306a36Sopenharmony_ci goto err_alloc_tcomplete_failed; 320662306a36Sopenharmony_ci } 320762306a36Sopenharmony_ci binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE); 320862306a36Sopenharmony_ci 320962306a36Sopenharmony_ci t->debug_id = t_debug_id; 321062306a36Sopenharmony_ci t->start_time = t_start_time; 321162306a36Sopenharmony_ci 321262306a36Sopenharmony_ci if (reply) 321362306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 321462306a36Sopenharmony_ci "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n", 321562306a36Sopenharmony_ci proc->pid, thread->pid, t->debug_id, 321662306a36Sopenharmony_ci target_proc->pid, target_thread->pid, 321762306a36Sopenharmony_ci (u64)tr->data.ptr.buffer, 321862306a36Sopenharmony_ci (u64)tr->data.ptr.offsets, 321962306a36Sopenharmony_ci (u64)tr->data_size, (u64)tr->offsets_size, 322062306a36Sopenharmony_ci (u64)extra_buffers_size); 322162306a36Sopenharmony_ci else 322262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 322362306a36Sopenharmony_ci "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n", 322462306a36Sopenharmony_ci proc->pid, thread->pid, t->debug_id, 322562306a36Sopenharmony_ci target_proc->pid, target_node->debug_id, 322662306a36Sopenharmony_ci (u64)tr->data.ptr.buffer, 322762306a36Sopenharmony_ci (u64)tr->data.ptr.offsets, 322862306a36Sopenharmony_ci (u64)tr->data_size, (u64)tr->offsets_size, 322962306a36Sopenharmony_ci (u64)extra_buffers_size); 323062306a36Sopenharmony_ci 323162306a36Sopenharmony_ci if (!reply && !(tr->flags & TF_ONE_WAY)) { 323262306a36Sopenharmony_ci t->from = thread; 323362306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 323462306a36Sopenharmony_ci t->from_pid = -1; 323562306a36Sopenharmony_ci t->from_tid = -1; 323662306a36Sopenharmony_ci#endif 323762306a36Sopenharmony_ci } else { 323862306a36Sopenharmony_ci t->from = NULL; 323962306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 324062306a36Sopenharmony_ci t->from_pid = thread->proc->pid; 324162306a36Sopenharmony_ci t->from_tid = thread->pid; 324262306a36Sopenharmony_ci#endif 324362306a36Sopenharmony_ci } 324462306a36Sopenharmony_ci 324562306a36Sopenharmony_ci t->sender_euid = task_euid(proc->tsk); 324662306a36Sopenharmony_ci#ifdef CONFIG_ACCESS_TOKENID 324762306a36Sopenharmony_ci t->sender_tokenid = current->token; 324862306a36Sopenharmony_ci t->first_tokenid = current->ftoken; 324962306a36Sopenharmony_ci#endif /* CONFIG_ACCESS_TOKENID */ 325062306a36Sopenharmony_ci t->to_proc = target_proc; 325162306a36Sopenharmony_ci t->to_thread = target_thread; 325262306a36Sopenharmony_ci t->code = tr->code; 325362306a36Sopenharmony_ci t->flags = tr->flags; 325462306a36Sopenharmony_ci t->priority = task_nice(current); 325562306a36Sopenharmony_ci 325662306a36Sopenharmony_ci if (target_node && target_node->txn_security_ctx) { 325762306a36Sopenharmony_ci u32 secid; 325862306a36Sopenharmony_ci size_t added_size; 325962306a36Sopenharmony_ci 326062306a36Sopenharmony_ci security_cred_getsecid(proc->cred, &secid); 326162306a36Sopenharmony_ci ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); 326262306a36Sopenharmony_ci if (ret) { 326362306a36Sopenharmony_ci binder_txn_error("%d:%d failed to get security context\n", 326462306a36Sopenharmony_ci thread->pid, proc->pid); 326562306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 326662306a36Sopenharmony_ci return_error_param = ret; 326762306a36Sopenharmony_ci return_error_line = __LINE__; 326862306a36Sopenharmony_ci goto err_get_secctx_failed; 326962306a36Sopenharmony_ci } 327062306a36Sopenharmony_ci added_size = ALIGN(secctx_sz, sizeof(u64)); 327162306a36Sopenharmony_ci extra_buffers_size += added_size; 327262306a36Sopenharmony_ci if (extra_buffers_size < added_size) { 327362306a36Sopenharmony_ci binder_txn_error("%d:%d integer overflow of extra_buffers_size\n", 327462306a36Sopenharmony_ci thread->pid, proc->pid); 327562306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 327662306a36Sopenharmony_ci return_error_param = -EINVAL; 327762306a36Sopenharmony_ci return_error_line = __LINE__; 327862306a36Sopenharmony_ci goto err_bad_extra_size; 327962306a36Sopenharmony_ci } 328062306a36Sopenharmony_ci } 328162306a36Sopenharmony_ci 328262306a36Sopenharmony_ci trace_binder_transaction(reply, t, target_node); 328362306a36Sopenharmony_ci 328462306a36Sopenharmony_ci t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size, 328562306a36Sopenharmony_ci tr->offsets_size, extra_buffers_size, 328662306a36Sopenharmony_ci !reply && (t->flags & TF_ONE_WAY), current->tgid); 328762306a36Sopenharmony_ci if (IS_ERR(t->buffer)) { 328862306a36Sopenharmony_ci char *s; 328962306a36Sopenharmony_ci 329062306a36Sopenharmony_ci ret = PTR_ERR(t->buffer); 329162306a36Sopenharmony_ci s = (ret == -ESRCH) ? ": vma cleared, target dead or dying" 329262306a36Sopenharmony_ci : (ret == -ENOSPC) ? ": no space left" 329362306a36Sopenharmony_ci : (ret == -ENOMEM) ? ": memory allocation failed" 329462306a36Sopenharmony_ci : ""; 329562306a36Sopenharmony_ci binder_txn_error("cannot allocate buffer%s", s); 329662306a36Sopenharmony_ci 329762306a36Sopenharmony_ci return_error_param = PTR_ERR(t->buffer); 329862306a36Sopenharmony_ci return_error = return_error_param == -ESRCH ? 329962306a36Sopenharmony_ci BR_DEAD_REPLY : BR_FAILED_REPLY; 330062306a36Sopenharmony_ci return_error_line = __LINE__; 330162306a36Sopenharmony_ci t->buffer = NULL; 330262306a36Sopenharmony_ci goto err_binder_alloc_buf_failed; 330362306a36Sopenharmony_ci } 330462306a36Sopenharmony_ci if (secctx) { 330562306a36Sopenharmony_ci int err; 330662306a36Sopenharmony_ci size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) + 330762306a36Sopenharmony_ci ALIGN(tr->offsets_size, sizeof(void *)) + 330862306a36Sopenharmony_ci ALIGN(extra_buffers_size, sizeof(void *)) - 330962306a36Sopenharmony_ci ALIGN(secctx_sz, sizeof(u64)); 331062306a36Sopenharmony_ci 331162306a36Sopenharmony_ci t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset; 331262306a36Sopenharmony_ci err = binder_alloc_copy_to_buffer(&target_proc->alloc, 331362306a36Sopenharmony_ci t->buffer, buf_offset, 331462306a36Sopenharmony_ci secctx, secctx_sz); 331562306a36Sopenharmony_ci if (err) { 331662306a36Sopenharmony_ci t->security_ctx = 0; 331762306a36Sopenharmony_ci WARN_ON(1); 331862306a36Sopenharmony_ci } 331962306a36Sopenharmony_ci security_release_secctx(secctx, secctx_sz); 332062306a36Sopenharmony_ci secctx = NULL; 332162306a36Sopenharmony_ci } 332262306a36Sopenharmony_ci t->buffer->debug_id = t->debug_id; 332362306a36Sopenharmony_ci t->buffer->transaction = t; 332462306a36Sopenharmony_ci t->buffer->target_node = target_node; 332562306a36Sopenharmony_ci t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF); 332662306a36Sopenharmony_ci trace_binder_transaction_alloc_buf(t->buffer); 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_ci if (binder_alloc_copy_user_to_buffer( 332962306a36Sopenharmony_ci &target_proc->alloc, 333062306a36Sopenharmony_ci t->buffer, 333162306a36Sopenharmony_ci ALIGN(tr->data_size, sizeof(void *)), 333262306a36Sopenharmony_ci (const void __user *) 333362306a36Sopenharmony_ci (uintptr_t)tr->data.ptr.offsets, 333462306a36Sopenharmony_ci tr->offsets_size)) { 333562306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid offsets ptr\n", 333662306a36Sopenharmony_ci proc->pid, thread->pid); 333762306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 333862306a36Sopenharmony_ci return_error_param = -EFAULT; 333962306a36Sopenharmony_ci return_error_line = __LINE__; 334062306a36Sopenharmony_ci goto err_copy_data_failed; 334162306a36Sopenharmony_ci } 334262306a36Sopenharmony_ci if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) { 334362306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n", 334462306a36Sopenharmony_ci proc->pid, thread->pid, (u64)tr->offsets_size); 334562306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 334662306a36Sopenharmony_ci return_error_param = -EINVAL; 334762306a36Sopenharmony_ci return_error_line = __LINE__; 334862306a36Sopenharmony_ci goto err_bad_offset; 334962306a36Sopenharmony_ci } 335062306a36Sopenharmony_ci if (!IS_ALIGNED(extra_buffers_size, sizeof(u64))) { 335162306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with unaligned buffers size, %lld\n", 335262306a36Sopenharmony_ci proc->pid, thread->pid, 335362306a36Sopenharmony_ci (u64)extra_buffers_size); 335462306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 335562306a36Sopenharmony_ci return_error_param = -EINVAL; 335662306a36Sopenharmony_ci return_error_line = __LINE__; 335762306a36Sopenharmony_ci goto err_bad_offset; 335862306a36Sopenharmony_ci } 335962306a36Sopenharmony_ci off_start_offset = ALIGN(tr->data_size, sizeof(void *)); 336062306a36Sopenharmony_ci buffer_offset = off_start_offset; 336162306a36Sopenharmony_ci off_end_offset = off_start_offset + tr->offsets_size; 336262306a36Sopenharmony_ci sg_buf_offset = ALIGN(off_end_offset, sizeof(void *)); 336362306a36Sopenharmony_ci sg_buf_end_offset = sg_buf_offset + extra_buffers_size - 336462306a36Sopenharmony_ci ALIGN(secctx_sz, sizeof(u64)); 336562306a36Sopenharmony_ci off_min = 0; 336662306a36Sopenharmony_ci for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; 336762306a36Sopenharmony_ci buffer_offset += sizeof(binder_size_t)) { 336862306a36Sopenharmony_ci struct binder_object_header *hdr; 336962306a36Sopenharmony_ci size_t object_size; 337062306a36Sopenharmony_ci struct binder_object object; 337162306a36Sopenharmony_ci binder_size_t object_offset; 337262306a36Sopenharmony_ci binder_size_t copy_size; 337362306a36Sopenharmony_ci 337462306a36Sopenharmony_ci if (binder_alloc_copy_from_buffer(&target_proc->alloc, 337562306a36Sopenharmony_ci &object_offset, 337662306a36Sopenharmony_ci t->buffer, 337762306a36Sopenharmony_ci buffer_offset, 337862306a36Sopenharmony_ci sizeof(object_offset))) { 337962306a36Sopenharmony_ci binder_txn_error("%d:%d copy offset from buffer failed\n", 338062306a36Sopenharmony_ci thread->pid, proc->pid); 338162306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 338262306a36Sopenharmony_ci return_error_param = -EINVAL; 338362306a36Sopenharmony_ci return_error_line = __LINE__; 338462306a36Sopenharmony_ci goto err_bad_offset; 338562306a36Sopenharmony_ci } 338662306a36Sopenharmony_ci 338762306a36Sopenharmony_ci /* 338862306a36Sopenharmony_ci * Copy the source user buffer up to the next object 338962306a36Sopenharmony_ci * that will be processed. 339062306a36Sopenharmony_ci */ 339162306a36Sopenharmony_ci copy_size = object_offset - user_offset; 339262306a36Sopenharmony_ci if (copy_size && (user_offset > object_offset || 339362306a36Sopenharmony_ci binder_alloc_copy_user_to_buffer( 339462306a36Sopenharmony_ci &target_proc->alloc, 339562306a36Sopenharmony_ci t->buffer, user_offset, 339662306a36Sopenharmony_ci user_buffer + user_offset, 339762306a36Sopenharmony_ci copy_size))) { 339862306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid data ptr\n", 339962306a36Sopenharmony_ci proc->pid, thread->pid); 340062306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 340162306a36Sopenharmony_ci return_error_param = -EFAULT; 340262306a36Sopenharmony_ci return_error_line = __LINE__; 340362306a36Sopenharmony_ci goto err_copy_data_failed; 340462306a36Sopenharmony_ci } 340562306a36Sopenharmony_ci object_size = binder_get_object(target_proc, user_buffer, 340662306a36Sopenharmony_ci t->buffer, object_offset, &object); 340762306a36Sopenharmony_ci if (object_size == 0 || object_offset < off_min) { 340862306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n", 340962306a36Sopenharmony_ci proc->pid, thread->pid, 341062306a36Sopenharmony_ci (u64)object_offset, 341162306a36Sopenharmony_ci (u64)off_min, 341262306a36Sopenharmony_ci (u64)t->buffer->data_size); 341362306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 341462306a36Sopenharmony_ci return_error_param = -EINVAL; 341562306a36Sopenharmony_ci return_error_line = __LINE__; 341662306a36Sopenharmony_ci goto err_bad_offset; 341762306a36Sopenharmony_ci } 341862306a36Sopenharmony_ci /* 341962306a36Sopenharmony_ci * Set offset to the next buffer fragment to be 342062306a36Sopenharmony_ci * copied 342162306a36Sopenharmony_ci */ 342262306a36Sopenharmony_ci user_offset = object_offset + object_size; 342362306a36Sopenharmony_ci 342462306a36Sopenharmony_ci hdr = &object.hdr; 342562306a36Sopenharmony_ci off_min = object_offset + object_size; 342662306a36Sopenharmony_ci switch (hdr->type) { 342762306a36Sopenharmony_ci case BINDER_TYPE_BINDER: 342862306a36Sopenharmony_ci case BINDER_TYPE_WEAK_BINDER: { 342962306a36Sopenharmony_ci struct flat_binder_object *fp; 343062306a36Sopenharmony_ci 343162306a36Sopenharmony_ci fp = to_flat_binder_object(hdr); 343262306a36Sopenharmony_ci ret = binder_translate_binder(fp, t, thread); 343362306a36Sopenharmony_ci 343462306a36Sopenharmony_ci if (ret < 0 || 343562306a36Sopenharmony_ci binder_alloc_copy_to_buffer(&target_proc->alloc, 343662306a36Sopenharmony_ci t->buffer, 343762306a36Sopenharmony_ci object_offset, 343862306a36Sopenharmony_ci fp, sizeof(*fp))) { 343962306a36Sopenharmony_ci binder_txn_error("%d:%d translate binder failed\n", 344062306a36Sopenharmony_ci thread->pid, proc->pid); 344162306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 344262306a36Sopenharmony_ci return_error_param = ret; 344362306a36Sopenharmony_ci return_error_line = __LINE__; 344462306a36Sopenharmony_ci goto err_translate_failed; 344562306a36Sopenharmony_ci } 344662306a36Sopenharmony_ci } break; 344762306a36Sopenharmony_ci case BINDER_TYPE_HANDLE: 344862306a36Sopenharmony_ci case BINDER_TYPE_WEAK_HANDLE: { 344962306a36Sopenharmony_ci struct flat_binder_object *fp; 345062306a36Sopenharmony_ci 345162306a36Sopenharmony_ci fp = to_flat_binder_object(hdr); 345262306a36Sopenharmony_ci ret = binder_translate_handle(fp, t, thread); 345362306a36Sopenharmony_ci if (ret < 0 || 345462306a36Sopenharmony_ci binder_alloc_copy_to_buffer(&target_proc->alloc, 345562306a36Sopenharmony_ci t->buffer, 345662306a36Sopenharmony_ci object_offset, 345762306a36Sopenharmony_ci fp, sizeof(*fp))) { 345862306a36Sopenharmony_ci binder_txn_error("%d:%d translate handle failed\n", 345962306a36Sopenharmony_ci thread->pid, proc->pid); 346062306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 346162306a36Sopenharmony_ci return_error_param = ret; 346262306a36Sopenharmony_ci return_error_line = __LINE__; 346362306a36Sopenharmony_ci goto err_translate_failed; 346462306a36Sopenharmony_ci } 346562306a36Sopenharmony_ci } break; 346662306a36Sopenharmony_ci 346762306a36Sopenharmony_ci case BINDER_TYPE_FD: { 346862306a36Sopenharmony_ci struct binder_fd_object *fp = to_binder_fd_object(hdr); 346962306a36Sopenharmony_ci binder_size_t fd_offset = object_offset + 347062306a36Sopenharmony_ci (uintptr_t)&fp->fd - (uintptr_t)fp; 347162306a36Sopenharmony_ci int ret = binder_translate_fd(fp->fd, fd_offset, t, 347262306a36Sopenharmony_ci thread, in_reply_to); 347362306a36Sopenharmony_ci 347462306a36Sopenharmony_ci fp->pad_binder = 0; 347562306a36Sopenharmony_ci if (ret < 0 || 347662306a36Sopenharmony_ci binder_alloc_copy_to_buffer(&target_proc->alloc, 347762306a36Sopenharmony_ci t->buffer, 347862306a36Sopenharmony_ci object_offset, 347962306a36Sopenharmony_ci fp, sizeof(*fp))) { 348062306a36Sopenharmony_ci binder_txn_error("%d:%d translate fd failed\n", 348162306a36Sopenharmony_ci thread->pid, proc->pid); 348262306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 348362306a36Sopenharmony_ci return_error_param = ret; 348462306a36Sopenharmony_ci return_error_line = __LINE__; 348562306a36Sopenharmony_ci goto err_translate_failed; 348662306a36Sopenharmony_ci } 348762306a36Sopenharmony_ci } break; 348862306a36Sopenharmony_ci case BINDER_TYPE_FDA: { 348962306a36Sopenharmony_ci struct binder_object ptr_object; 349062306a36Sopenharmony_ci binder_size_t parent_offset; 349162306a36Sopenharmony_ci struct binder_object user_object; 349262306a36Sopenharmony_ci size_t user_parent_size; 349362306a36Sopenharmony_ci struct binder_fd_array_object *fda = 349462306a36Sopenharmony_ci to_binder_fd_array_object(hdr); 349562306a36Sopenharmony_ci size_t num_valid = (buffer_offset - off_start_offset) / 349662306a36Sopenharmony_ci sizeof(binder_size_t); 349762306a36Sopenharmony_ci struct binder_buffer_object *parent = 349862306a36Sopenharmony_ci binder_validate_ptr(target_proc, t->buffer, 349962306a36Sopenharmony_ci &ptr_object, fda->parent, 350062306a36Sopenharmony_ci off_start_offset, 350162306a36Sopenharmony_ci &parent_offset, 350262306a36Sopenharmony_ci num_valid); 350362306a36Sopenharmony_ci if (!parent) { 350462306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid parent offset or type\n", 350562306a36Sopenharmony_ci proc->pid, thread->pid); 350662306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 350762306a36Sopenharmony_ci return_error_param = -EINVAL; 350862306a36Sopenharmony_ci return_error_line = __LINE__; 350962306a36Sopenharmony_ci goto err_bad_parent; 351062306a36Sopenharmony_ci } 351162306a36Sopenharmony_ci if (!binder_validate_fixup(target_proc, t->buffer, 351262306a36Sopenharmony_ci off_start_offset, 351362306a36Sopenharmony_ci parent_offset, 351462306a36Sopenharmony_ci fda->parent_offset, 351562306a36Sopenharmony_ci last_fixup_obj_off, 351662306a36Sopenharmony_ci last_fixup_min_off)) { 351762306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n", 351862306a36Sopenharmony_ci proc->pid, thread->pid); 351962306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 352062306a36Sopenharmony_ci return_error_param = -EINVAL; 352162306a36Sopenharmony_ci return_error_line = __LINE__; 352262306a36Sopenharmony_ci goto err_bad_parent; 352362306a36Sopenharmony_ci } 352462306a36Sopenharmony_ci /* 352562306a36Sopenharmony_ci * We need to read the user version of the parent 352662306a36Sopenharmony_ci * object to get the original user offset 352762306a36Sopenharmony_ci */ 352862306a36Sopenharmony_ci user_parent_size = 352962306a36Sopenharmony_ci binder_get_object(proc, user_buffer, t->buffer, 353062306a36Sopenharmony_ci parent_offset, &user_object); 353162306a36Sopenharmony_ci if (user_parent_size != sizeof(user_object.bbo)) { 353262306a36Sopenharmony_ci binder_user_error("%d:%d invalid ptr object size: %zd vs %zd\n", 353362306a36Sopenharmony_ci proc->pid, thread->pid, 353462306a36Sopenharmony_ci user_parent_size, 353562306a36Sopenharmony_ci sizeof(user_object.bbo)); 353662306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 353762306a36Sopenharmony_ci return_error_param = -EINVAL; 353862306a36Sopenharmony_ci return_error_line = __LINE__; 353962306a36Sopenharmony_ci goto err_bad_parent; 354062306a36Sopenharmony_ci } 354162306a36Sopenharmony_ci ret = binder_translate_fd_array(&pf_head, fda, 354262306a36Sopenharmony_ci user_buffer, parent, 354362306a36Sopenharmony_ci &user_object.bbo, t, 354462306a36Sopenharmony_ci thread, in_reply_to); 354562306a36Sopenharmony_ci if (!ret) 354662306a36Sopenharmony_ci ret = binder_alloc_copy_to_buffer(&target_proc->alloc, 354762306a36Sopenharmony_ci t->buffer, 354862306a36Sopenharmony_ci object_offset, 354962306a36Sopenharmony_ci fda, sizeof(*fda)); 355062306a36Sopenharmony_ci if (ret) { 355162306a36Sopenharmony_ci binder_txn_error("%d:%d translate fd array failed\n", 355262306a36Sopenharmony_ci thread->pid, proc->pid); 355362306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 355462306a36Sopenharmony_ci return_error_param = ret > 0 ? -EINVAL : ret; 355562306a36Sopenharmony_ci return_error_line = __LINE__; 355662306a36Sopenharmony_ci goto err_translate_failed; 355762306a36Sopenharmony_ci } 355862306a36Sopenharmony_ci last_fixup_obj_off = parent_offset; 355962306a36Sopenharmony_ci last_fixup_min_off = 356062306a36Sopenharmony_ci fda->parent_offset + sizeof(u32) * fda->num_fds; 356162306a36Sopenharmony_ci } break; 356262306a36Sopenharmony_ci case BINDER_TYPE_PTR: { 356362306a36Sopenharmony_ci struct binder_buffer_object *bp = 356462306a36Sopenharmony_ci to_binder_buffer_object(hdr); 356562306a36Sopenharmony_ci size_t buf_left = sg_buf_end_offset - sg_buf_offset; 356662306a36Sopenharmony_ci size_t num_valid; 356762306a36Sopenharmony_ci 356862306a36Sopenharmony_ci if (bp->length > buf_left) { 356962306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with too large buffer\n", 357062306a36Sopenharmony_ci proc->pid, thread->pid); 357162306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 357262306a36Sopenharmony_ci return_error_param = -EINVAL; 357362306a36Sopenharmony_ci return_error_line = __LINE__; 357462306a36Sopenharmony_ci goto err_bad_offset; 357562306a36Sopenharmony_ci } 357662306a36Sopenharmony_ci ret = binder_defer_copy(&sgc_head, sg_buf_offset, 357762306a36Sopenharmony_ci (const void __user *)(uintptr_t)bp->buffer, 357862306a36Sopenharmony_ci bp->length); 357962306a36Sopenharmony_ci if (ret) { 358062306a36Sopenharmony_ci binder_txn_error("%d:%d deferred copy failed\n", 358162306a36Sopenharmony_ci thread->pid, proc->pid); 358262306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 358362306a36Sopenharmony_ci return_error_param = ret; 358462306a36Sopenharmony_ci return_error_line = __LINE__; 358562306a36Sopenharmony_ci goto err_translate_failed; 358662306a36Sopenharmony_ci } 358762306a36Sopenharmony_ci /* Fixup buffer pointer to target proc address space */ 358862306a36Sopenharmony_ci bp->buffer = (uintptr_t) 358962306a36Sopenharmony_ci t->buffer->user_data + sg_buf_offset; 359062306a36Sopenharmony_ci sg_buf_offset += ALIGN(bp->length, sizeof(u64)); 359162306a36Sopenharmony_ci 359262306a36Sopenharmony_ci num_valid = (buffer_offset - off_start_offset) / 359362306a36Sopenharmony_ci sizeof(binder_size_t); 359462306a36Sopenharmony_ci ret = binder_fixup_parent(&pf_head, t, 359562306a36Sopenharmony_ci thread, bp, 359662306a36Sopenharmony_ci off_start_offset, 359762306a36Sopenharmony_ci num_valid, 359862306a36Sopenharmony_ci last_fixup_obj_off, 359962306a36Sopenharmony_ci last_fixup_min_off); 360062306a36Sopenharmony_ci if (ret < 0 || 360162306a36Sopenharmony_ci binder_alloc_copy_to_buffer(&target_proc->alloc, 360262306a36Sopenharmony_ci t->buffer, 360362306a36Sopenharmony_ci object_offset, 360462306a36Sopenharmony_ci bp, sizeof(*bp))) { 360562306a36Sopenharmony_ci binder_txn_error("%d:%d failed to fixup parent\n", 360662306a36Sopenharmony_ci thread->pid, proc->pid); 360762306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 360862306a36Sopenharmony_ci return_error_param = ret; 360962306a36Sopenharmony_ci return_error_line = __LINE__; 361062306a36Sopenharmony_ci goto err_translate_failed; 361162306a36Sopenharmony_ci } 361262306a36Sopenharmony_ci last_fixup_obj_off = object_offset; 361362306a36Sopenharmony_ci last_fixup_min_off = 0; 361462306a36Sopenharmony_ci } break; 361562306a36Sopenharmony_ci default: 361662306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid object type, %x\n", 361762306a36Sopenharmony_ci proc->pid, thread->pid, hdr->type); 361862306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 361962306a36Sopenharmony_ci return_error_param = -EINVAL; 362062306a36Sopenharmony_ci return_error_line = __LINE__; 362162306a36Sopenharmony_ci goto err_bad_object_type; 362262306a36Sopenharmony_ci } 362362306a36Sopenharmony_ci } 362462306a36Sopenharmony_ci /* Done processing objects, copy the rest of the buffer */ 362562306a36Sopenharmony_ci if (binder_alloc_copy_user_to_buffer( 362662306a36Sopenharmony_ci &target_proc->alloc, 362762306a36Sopenharmony_ci t->buffer, user_offset, 362862306a36Sopenharmony_ci user_buffer + user_offset, 362962306a36Sopenharmony_ci tr->data_size - user_offset)) { 363062306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid data ptr\n", 363162306a36Sopenharmony_ci proc->pid, thread->pid); 363262306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 363362306a36Sopenharmony_ci return_error_param = -EFAULT; 363462306a36Sopenharmony_ci return_error_line = __LINE__; 363562306a36Sopenharmony_ci goto err_copy_data_failed; 363662306a36Sopenharmony_ci } 363762306a36Sopenharmony_ci 363862306a36Sopenharmony_ci ret = binder_do_deferred_txn_copies(&target_proc->alloc, t->buffer, 363962306a36Sopenharmony_ci &sgc_head, &pf_head); 364062306a36Sopenharmony_ci if (ret) { 364162306a36Sopenharmony_ci binder_user_error("%d:%d got transaction with invalid offsets ptr\n", 364262306a36Sopenharmony_ci proc->pid, thread->pid); 364362306a36Sopenharmony_ci return_error = BR_FAILED_REPLY; 364462306a36Sopenharmony_ci return_error_param = ret; 364562306a36Sopenharmony_ci return_error_line = __LINE__; 364662306a36Sopenharmony_ci goto err_copy_data_failed; 364762306a36Sopenharmony_ci } 364862306a36Sopenharmony_ci if (t->buffer->oneway_spam_suspect) 364962306a36Sopenharmony_ci tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT; 365062306a36Sopenharmony_ci else 365162306a36Sopenharmony_ci tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; 365262306a36Sopenharmony_ci t->work.type = BINDER_WORK_TRANSACTION; 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_ci if (reply) { 365562306a36Sopenharmony_ci binder_enqueue_thread_work(thread, tcomplete); 365662306a36Sopenharmony_ci binder_inner_proc_lock(target_proc); 365762306a36Sopenharmony_ci if (target_thread->is_dead) { 365862306a36Sopenharmony_ci return_error = BR_DEAD_REPLY; 365962306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 366062306a36Sopenharmony_ci goto err_dead_proc_or_thread; 366162306a36Sopenharmony_ci } 366262306a36Sopenharmony_ci BUG_ON(t->buffer->async_transaction != 0); 366362306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 366462306a36Sopenharmony_ci t->timestamp = in_reply_to->timestamp; 366562306a36Sopenharmony_ci#endif 366662306a36Sopenharmony_ci binder_pop_transaction_ilocked(target_thread, in_reply_to); 366762306a36Sopenharmony_ci binder_enqueue_thread_work_ilocked(target_thread, &t->work); 366862306a36Sopenharmony_ci target_proc->outstanding_txns++; 366962306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 367062306a36Sopenharmony_ci wake_up_interruptible_sync(&target_thread->wait); 367162306a36Sopenharmony_ci binder_free_transaction(in_reply_to); 367262306a36Sopenharmony_ci } else if (!(t->flags & TF_ONE_WAY)) { 367362306a36Sopenharmony_ci BUG_ON(t->buffer->async_transaction != 0); 367462306a36Sopenharmony_ci binder_inner_proc_lock(proc); 367562306a36Sopenharmony_ci /* 367662306a36Sopenharmony_ci * Defer the TRANSACTION_COMPLETE, so we don't return to 367762306a36Sopenharmony_ci * userspace immediately; this allows the target process to 367862306a36Sopenharmony_ci * immediately start processing this transaction, reducing 367962306a36Sopenharmony_ci * latency. We will then return the TRANSACTION_COMPLETE when 368062306a36Sopenharmony_ci * the target replies (or there is an error). 368162306a36Sopenharmony_ci */ 368262306a36Sopenharmony_ci binder_enqueue_deferred_thread_work_ilocked(thread, tcomplete); 368362306a36Sopenharmony_ci t->need_reply = 1; 368462306a36Sopenharmony_ci t->from_parent = thread->transaction_stack; 368562306a36Sopenharmony_ci thread->transaction_stack = t; 368662306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 368762306a36Sopenharmony_ci t->timestamp = binder_clock(); 368862306a36Sopenharmony_ci#endif 368962306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 369062306a36Sopenharmony_ci return_error = binder_proc_transaction(t, 369162306a36Sopenharmony_ci target_proc, target_thread); 369262306a36Sopenharmony_ci if (return_error) { 369362306a36Sopenharmony_ci binder_inner_proc_lock(proc); 369462306a36Sopenharmony_ci binder_pop_transaction_ilocked(thread, t); 369562306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 369662306a36Sopenharmony_ci goto err_dead_proc_or_thread; 369762306a36Sopenharmony_ci } 369862306a36Sopenharmony_ci } else { 369962306a36Sopenharmony_ci BUG_ON(target_node == NULL); 370062306a36Sopenharmony_ci BUG_ON(t->buffer->async_transaction != 1); 370162306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 370262306a36Sopenharmony_ci t->timestamp = binder_clock(); 370362306a36Sopenharmony_ci#endif 370462306a36Sopenharmony_ci return_error = binder_proc_transaction(t, target_proc, NULL); 370562306a36Sopenharmony_ci /* 370662306a36Sopenharmony_ci * Let the caller know when async transaction reaches a frozen 370762306a36Sopenharmony_ci * process and is put in a pending queue, waiting for the target 370862306a36Sopenharmony_ci * process to be unfrozen. 370962306a36Sopenharmony_ci */ 371062306a36Sopenharmony_ci if (return_error == BR_TRANSACTION_PENDING_FROZEN) 371162306a36Sopenharmony_ci tcomplete->type = BINDER_WORK_TRANSACTION_PENDING; 371262306a36Sopenharmony_ci binder_enqueue_thread_work(thread, tcomplete); 371362306a36Sopenharmony_ci if (return_error && 371462306a36Sopenharmony_ci return_error != BR_TRANSACTION_PENDING_FROZEN) 371562306a36Sopenharmony_ci goto err_dead_proc_or_thread; 371662306a36Sopenharmony_ci } 371762306a36Sopenharmony_ci if (target_thread) 371862306a36Sopenharmony_ci binder_thread_dec_tmpref(target_thread); 371962306a36Sopenharmony_ci binder_proc_dec_tmpref(target_proc); 372062306a36Sopenharmony_ci if (target_node) 372162306a36Sopenharmony_ci binder_dec_node_tmpref(target_node); 372262306a36Sopenharmony_ci /* 372362306a36Sopenharmony_ci * write barrier to synchronize with initialization 372462306a36Sopenharmony_ci * of log entry 372562306a36Sopenharmony_ci */ 372662306a36Sopenharmony_ci smp_wmb(); 372762306a36Sopenharmony_ci WRITE_ONCE(e->debug_id_done, t_debug_id); 372862306a36Sopenharmony_ci return; 372962306a36Sopenharmony_ci 373062306a36Sopenharmony_cierr_dead_proc_or_thread: 373162306a36Sopenharmony_ci binder_txn_error("%d:%d dead process or thread\n", 373262306a36Sopenharmony_ci thread->pid, proc->pid); 373362306a36Sopenharmony_ci return_error_line = __LINE__; 373462306a36Sopenharmony_ci binder_dequeue_work(proc, tcomplete); 373562306a36Sopenharmony_cierr_translate_failed: 373662306a36Sopenharmony_cierr_bad_object_type: 373762306a36Sopenharmony_cierr_bad_offset: 373862306a36Sopenharmony_cierr_bad_parent: 373962306a36Sopenharmony_cierr_copy_data_failed: 374062306a36Sopenharmony_ci binder_cleanup_deferred_txn_lists(&sgc_head, &pf_head); 374162306a36Sopenharmony_ci binder_free_txn_fixups(t); 374262306a36Sopenharmony_ci trace_binder_transaction_failed_buffer_release(t->buffer); 374362306a36Sopenharmony_ci binder_transaction_buffer_release(target_proc, NULL, t->buffer, 374462306a36Sopenharmony_ci buffer_offset, true); 374562306a36Sopenharmony_ci if (target_node) 374662306a36Sopenharmony_ci binder_dec_node_tmpref(target_node); 374762306a36Sopenharmony_ci target_node = NULL; 374862306a36Sopenharmony_ci t->buffer->transaction = NULL; 374962306a36Sopenharmony_ci binder_alloc_free_buf(&target_proc->alloc, t->buffer); 375062306a36Sopenharmony_cierr_binder_alloc_buf_failed: 375162306a36Sopenharmony_cierr_bad_extra_size: 375262306a36Sopenharmony_ci if (secctx) 375362306a36Sopenharmony_ci security_release_secctx(secctx, secctx_sz); 375462306a36Sopenharmony_cierr_get_secctx_failed: 375562306a36Sopenharmony_ci kfree(tcomplete); 375662306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); 375762306a36Sopenharmony_cierr_alloc_tcomplete_failed: 375862306a36Sopenharmony_ci if (trace_binder_txn_latency_free_enabled()) 375962306a36Sopenharmony_ci binder_txn_latency_free(t); 376062306a36Sopenharmony_ci kfree(t); 376162306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_TRANSACTION); 376262306a36Sopenharmony_cierr_alloc_t_failed: 376362306a36Sopenharmony_cierr_bad_todo_list: 376462306a36Sopenharmony_cierr_bad_call_stack: 376562306a36Sopenharmony_cierr_empty_call_stack: 376662306a36Sopenharmony_cierr_dead_binder: 376762306a36Sopenharmony_cierr_invalid_target_handle: 376862306a36Sopenharmony_ci if (target_node) { 376962306a36Sopenharmony_ci binder_dec_node(target_node, 1, 0); 377062306a36Sopenharmony_ci binder_dec_node_tmpref(target_node); 377162306a36Sopenharmony_ci } 377262306a36Sopenharmony_ci 377362306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, 377462306a36Sopenharmony_ci "%d:%d transaction %s to %d:%d failed %d/%d/%d, size %lld-%lld line %d\n", 377562306a36Sopenharmony_ci proc->pid, thread->pid, reply ? "reply" : 377662306a36Sopenharmony_ci (tr->flags & TF_ONE_WAY ? "async" : "call"), 377762306a36Sopenharmony_ci target_proc ? target_proc->pid : 0, 377862306a36Sopenharmony_ci target_thread ? target_thread->pid : 0, 377962306a36Sopenharmony_ci t_debug_id, return_error, return_error_param, 378062306a36Sopenharmony_ci (u64)tr->data_size, (u64)tr->offsets_size, 378162306a36Sopenharmony_ci return_error_line); 378262306a36Sopenharmony_ci 378362306a36Sopenharmony_ci if (target_thread) 378462306a36Sopenharmony_ci binder_thread_dec_tmpref(target_thread); 378562306a36Sopenharmony_ci if (target_proc) 378662306a36Sopenharmony_ci binder_proc_dec_tmpref(target_proc); 378762306a36Sopenharmony_ci 378862306a36Sopenharmony_ci { 378962306a36Sopenharmony_ci struct binder_transaction_log_entry *fe; 379062306a36Sopenharmony_ci 379162306a36Sopenharmony_ci e->return_error = return_error; 379262306a36Sopenharmony_ci e->return_error_param = return_error_param; 379362306a36Sopenharmony_ci e->return_error_line = return_error_line; 379462306a36Sopenharmony_ci fe = binder_transaction_log_add(&binder_transaction_log_failed); 379562306a36Sopenharmony_ci *fe = *e; 379662306a36Sopenharmony_ci /* 379762306a36Sopenharmony_ci * write barrier to synchronize with initialization 379862306a36Sopenharmony_ci * of log entry 379962306a36Sopenharmony_ci */ 380062306a36Sopenharmony_ci smp_wmb(); 380162306a36Sopenharmony_ci WRITE_ONCE(e->debug_id_done, t_debug_id); 380262306a36Sopenharmony_ci WRITE_ONCE(fe->debug_id_done, t_debug_id); 380362306a36Sopenharmony_ci } 380462306a36Sopenharmony_ci 380562306a36Sopenharmony_ci BUG_ON(thread->return_error.cmd != BR_OK); 380662306a36Sopenharmony_ci if (in_reply_to) { 380762306a36Sopenharmony_ci binder_set_txn_from_error(in_reply_to, t_debug_id, 380862306a36Sopenharmony_ci return_error, return_error_param); 380962306a36Sopenharmony_ci thread->return_error.cmd = BR_TRANSACTION_COMPLETE; 381062306a36Sopenharmony_ci binder_enqueue_thread_work(thread, &thread->return_error.work); 381162306a36Sopenharmony_ci binder_send_failed_reply(in_reply_to, return_error); 381262306a36Sopenharmony_ci } else { 381362306a36Sopenharmony_ci binder_inner_proc_lock(proc); 381462306a36Sopenharmony_ci binder_set_extended_error(&thread->ee, t_debug_id, 381562306a36Sopenharmony_ci return_error, return_error_param); 381662306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 381762306a36Sopenharmony_ci thread->return_error.cmd = return_error; 381862306a36Sopenharmony_ci binder_enqueue_thread_work(thread, &thread->return_error.work); 381962306a36Sopenharmony_ci } 382062306a36Sopenharmony_ci} 382162306a36Sopenharmony_ci 382262306a36Sopenharmony_ci/** 382362306a36Sopenharmony_ci * binder_free_buf() - free the specified buffer 382462306a36Sopenharmony_ci * @proc: binder proc that owns buffer 382562306a36Sopenharmony_ci * @buffer: buffer to be freed 382662306a36Sopenharmony_ci * @is_failure: failed to send transaction 382762306a36Sopenharmony_ci * 382862306a36Sopenharmony_ci * If buffer for an async transaction, enqueue the next async 382962306a36Sopenharmony_ci * transaction from the node. 383062306a36Sopenharmony_ci * 383162306a36Sopenharmony_ci * Cleanup buffer and free it. 383262306a36Sopenharmony_ci */ 383362306a36Sopenharmony_cistatic void 383462306a36Sopenharmony_cibinder_free_buf(struct binder_proc *proc, 383562306a36Sopenharmony_ci struct binder_thread *thread, 383662306a36Sopenharmony_ci struct binder_buffer *buffer, bool is_failure) 383762306a36Sopenharmony_ci{ 383862306a36Sopenharmony_ci binder_inner_proc_lock(proc); 383962306a36Sopenharmony_ci if (buffer->transaction) { 384062306a36Sopenharmony_ci buffer->transaction->buffer = NULL; 384162306a36Sopenharmony_ci buffer->transaction = NULL; 384262306a36Sopenharmony_ci } 384362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 384462306a36Sopenharmony_ci if (buffer->async_transaction && buffer->target_node) { 384562306a36Sopenharmony_ci struct binder_node *buf_node; 384662306a36Sopenharmony_ci struct binder_work *w; 384762306a36Sopenharmony_ci 384862306a36Sopenharmony_ci buf_node = buffer->target_node; 384962306a36Sopenharmony_ci binder_node_inner_lock(buf_node); 385062306a36Sopenharmony_ci BUG_ON(!buf_node->has_async_transaction); 385162306a36Sopenharmony_ci BUG_ON(buf_node->proc != proc); 385262306a36Sopenharmony_ci w = binder_dequeue_work_head_ilocked( 385362306a36Sopenharmony_ci &buf_node->async_todo); 385462306a36Sopenharmony_ci if (!w) { 385562306a36Sopenharmony_ci buf_node->has_async_transaction = false; 385662306a36Sopenharmony_ci } else { 385762306a36Sopenharmony_ci binder_enqueue_work_ilocked( 385862306a36Sopenharmony_ci w, &proc->todo); 385962306a36Sopenharmony_ci binder_wakeup_proc_ilocked(proc); 386062306a36Sopenharmony_ci } 386162306a36Sopenharmony_ci binder_node_inner_unlock(buf_node); 386262306a36Sopenharmony_ci } 386362306a36Sopenharmony_ci trace_binder_transaction_buffer_release(buffer); 386462306a36Sopenharmony_ci binder_release_entire_buffer(proc, thread, buffer, is_failure); 386562306a36Sopenharmony_ci binder_alloc_free_buf(&proc->alloc, buffer); 386662306a36Sopenharmony_ci} 386762306a36Sopenharmony_ci 386862306a36Sopenharmony_cistatic int binder_thread_write(struct binder_proc *proc, 386962306a36Sopenharmony_ci struct binder_thread *thread, 387062306a36Sopenharmony_ci binder_uintptr_t binder_buffer, size_t size, 387162306a36Sopenharmony_ci binder_size_t *consumed) 387262306a36Sopenharmony_ci{ 387362306a36Sopenharmony_ci uint32_t cmd; 387462306a36Sopenharmony_ci struct binder_context *context = proc->context; 387562306a36Sopenharmony_ci void __user *buffer = (void __user *)(uintptr_t)binder_buffer; 387662306a36Sopenharmony_ci void __user *ptr = buffer + *consumed; 387762306a36Sopenharmony_ci void __user *end = buffer + size; 387862306a36Sopenharmony_ci 387962306a36Sopenharmony_ci while (ptr < end && thread->return_error.cmd == BR_OK) { 388062306a36Sopenharmony_ci int ret; 388162306a36Sopenharmony_ci 388262306a36Sopenharmony_ci if (get_user(cmd, (uint32_t __user *)ptr)) 388362306a36Sopenharmony_ci return -EFAULT; 388462306a36Sopenharmony_ci ptr += sizeof(uint32_t); 388562306a36Sopenharmony_ci trace_binder_command(cmd); 388662306a36Sopenharmony_ci if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) { 388762306a36Sopenharmony_ci atomic_inc(&binder_stats.bc[_IOC_NR(cmd)]); 388862306a36Sopenharmony_ci atomic_inc(&proc->stats.bc[_IOC_NR(cmd)]); 388962306a36Sopenharmony_ci atomic_inc(&thread->stats.bc[_IOC_NR(cmd)]); 389062306a36Sopenharmony_ci } 389162306a36Sopenharmony_ci switch (cmd) { 389262306a36Sopenharmony_ci case BC_INCREFS: 389362306a36Sopenharmony_ci case BC_ACQUIRE: 389462306a36Sopenharmony_ci case BC_RELEASE: 389562306a36Sopenharmony_ci case BC_DECREFS: { 389662306a36Sopenharmony_ci uint32_t target; 389762306a36Sopenharmony_ci const char *debug_string; 389862306a36Sopenharmony_ci bool strong = cmd == BC_ACQUIRE || cmd == BC_RELEASE; 389962306a36Sopenharmony_ci bool increment = cmd == BC_INCREFS || cmd == BC_ACQUIRE; 390062306a36Sopenharmony_ci struct binder_ref_data rdata; 390162306a36Sopenharmony_ci 390262306a36Sopenharmony_ci if (get_user(target, (uint32_t __user *)ptr)) 390362306a36Sopenharmony_ci return -EFAULT; 390462306a36Sopenharmony_ci 390562306a36Sopenharmony_ci ptr += sizeof(uint32_t); 390662306a36Sopenharmony_ci ret = -1; 390762306a36Sopenharmony_ci if (increment && !target) { 390862306a36Sopenharmony_ci struct binder_node *ctx_mgr_node; 390962306a36Sopenharmony_ci 391062306a36Sopenharmony_ci mutex_lock(&context->context_mgr_node_lock); 391162306a36Sopenharmony_ci ctx_mgr_node = context->binder_context_mgr_node; 391262306a36Sopenharmony_ci if (ctx_mgr_node) { 391362306a36Sopenharmony_ci if (ctx_mgr_node->proc == proc) { 391462306a36Sopenharmony_ci binder_user_error("%d:%d context manager tried to acquire desc 0\n", 391562306a36Sopenharmony_ci proc->pid, thread->pid); 391662306a36Sopenharmony_ci mutex_unlock(&context->context_mgr_node_lock); 391762306a36Sopenharmony_ci return -EINVAL; 391862306a36Sopenharmony_ci } 391962306a36Sopenharmony_ci ret = binder_inc_ref_for_node( 392062306a36Sopenharmony_ci proc, ctx_mgr_node, 392162306a36Sopenharmony_ci strong, NULL, &rdata); 392262306a36Sopenharmony_ci } 392362306a36Sopenharmony_ci mutex_unlock(&context->context_mgr_node_lock); 392462306a36Sopenharmony_ci } 392562306a36Sopenharmony_ci if (ret) 392662306a36Sopenharmony_ci ret = binder_update_ref_for_handle( 392762306a36Sopenharmony_ci proc, target, increment, strong, 392862306a36Sopenharmony_ci &rdata); 392962306a36Sopenharmony_ci if (!ret && rdata.desc != target) { 393062306a36Sopenharmony_ci binder_user_error("%d:%d tried to acquire reference to desc %d, got %d instead\n", 393162306a36Sopenharmony_ci proc->pid, thread->pid, 393262306a36Sopenharmony_ci target, rdata.desc); 393362306a36Sopenharmony_ci } 393462306a36Sopenharmony_ci switch (cmd) { 393562306a36Sopenharmony_ci case BC_INCREFS: 393662306a36Sopenharmony_ci debug_string = "IncRefs"; 393762306a36Sopenharmony_ci break; 393862306a36Sopenharmony_ci case BC_ACQUIRE: 393962306a36Sopenharmony_ci debug_string = "Acquire"; 394062306a36Sopenharmony_ci break; 394162306a36Sopenharmony_ci case BC_RELEASE: 394262306a36Sopenharmony_ci debug_string = "Release"; 394362306a36Sopenharmony_ci break; 394462306a36Sopenharmony_ci case BC_DECREFS: 394562306a36Sopenharmony_ci default: 394662306a36Sopenharmony_ci debug_string = "DecRefs"; 394762306a36Sopenharmony_ci break; 394862306a36Sopenharmony_ci } 394962306a36Sopenharmony_ci if (ret) { 395062306a36Sopenharmony_ci binder_user_error("%d:%d %s %d refcount change on invalid ref %d ret %d\n", 395162306a36Sopenharmony_ci proc->pid, thread->pid, debug_string, 395262306a36Sopenharmony_ci strong, target, ret); 395362306a36Sopenharmony_ci break; 395462306a36Sopenharmony_ci } 395562306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_USER_REFS, 395662306a36Sopenharmony_ci "%d:%d %s ref %d desc %d s %d w %d\n", 395762306a36Sopenharmony_ci proc->pid, thread->pid, debug_string, 395862306a36Sopenharmony_ci rdata.debug_id, rdata.desc, rdata.strong, 395962306a36Sopenharmony_ci rdata.weak); 396062306a36Sopenharmony_ci break; 396162306a36Sopenharmony_ci } 396262306a36Sopenharmony_ci case BC_INCREFS_DONE: 396362306a36Sopenharmony_ci case BC_ACQUIRE_DONE: { 396462306a36Sopenharmony_ci binder_uintptr_t node_ptr; 396562306a36Sopenharmony_ci binder_uintptr_t cookie; 396662306a36Sopenharmony_ci struct binder_node *node; 396762306a36Sopenharmony_ci bool free_node; 396862306a36Sopenharmony_ci 396962306a36Sopenharmony_ci if (get_user(node_ptr, (binder_uintptr_t __user *)ptr)) 397062306a36Sopenharmony_ci return -EFAULT; 397162306a36Sopenharmony_ci ptr += sizeof(binder_uintptr_t); 397262306a36Sopenharmony_ci if (get_user(cookie, (binder_uintptr_t __user *)ptr)) 397362306a36Sopenharmony_ci return -EFAULT; 397462306a36Sopenharmony_ci ptr += sizeof(binder_uintptr_t); 397562306a36Sopenharmony_ci node = binder_get_node(proc, node_ptr); 397662306a36Sopenharmony_ci if (node == NULL) { 397762306a36Sopenharmony_ci binder_user_error("%d:%d %s u%016llx no match\n", 397862306a36Sopenharmony_ci proc->pid, thread->pid, 397962306a36Sopenharmony_ci cmd == BC_INCREFS_DONE ? 398062306a36Sopenharmony_ci "BC_INCREFS_DONE" : 398162306a36Sopenharmony_ci "BC_ACQUIRE_DONE", 398262306a36Sopenharmony_ci (u64)node_ptr); 398362306a36Sopenharmony_ci break; 398462306a36Sopenharmony_ci } 398562306a36Sopenharmony_ci if (cookie != node->cookie) { 398662306a36Sopenharmony_ci binder_user_error("%d:%d %s u%016llx node %d cookie mismatch %016llx != %016llx\n", 398762306a36Sopenharmony_ci proc->pid, thread->pid, 398862306a36Sopenharmony_ci cmd == BC_INCREFS_DONE ? 398962306a36Sopenharmony_ci "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", 399062306a36Sopenharmony_ci (u64)node_ptr, node->debug_id, 399162306a36Sopenharmony_ci (u64)cookie, (u64)node->cookie); 399262306a36Sopenharmony_ci binder_put_node(node); 399362306a36Sopenharmony_ci break; 399462306a36Sopenharmony_ci } 399562306a36Sopenharmony_ci binder_node_inner_lock(node); 399662306a36Sopenharmony_ci if (cmd == BC_ACQUIRE_DONE) { 399762306a36Sopenharmony_ci if (node->pending_strong_ref == 0) { 399862306a36Sopenharmony_ci binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", 399962306a36Sopenharmony_ci proc->pid, thread->pid, 400062306a36Sopenharmony_ci node->debug_id); 400162306a36Sopenharmony_ci binder_node_inner_unlock(node); 400262306a36Sopenharmony_ci binder_put_node(node); 400362306a36Sopenharmony_ci break; 400462306a36Sopenharmony_ci } 400562306a36Sopenharmony_ci node->pending_strong_ref = 0; 400662306a36Sopenharmony_ci } else { 400762306a36Sopenharmony_ci if (node->pending_weak_ref == 0) { 400862306a36Sopenharmony_ci binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", 400962306a36Sopenharmony_ci proc->pid, thread->pid, 401062306a36Sopenharmony_ci node->debug_id); 401162306a36Sopenharmony_ci binder_node_inner_unlock(node); 401262306a36Sopenharmony_ci binder_put_node(node); 401362306a36Sopenharmony_ci break; 401462306a36Sopenharmony_ci } 401562306a36Sopenharmony_ci node->pending_weak_ref = 0; 401662306a36Sopenharmony_ci } 401762306a36Sopenharmony_ci free_node = binder_dec_node_nilocked(node, 401862306a36Sopenharmony_ci cmd == BC_ACQUIRE_DONE, 0); 401962306a36Sopenharmony_ci WARN_ON(free_node); 402062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_USER_REFS, 402162306a36Sopenharmony_ci "%d:%d %s node %d ls %d lw %d tr %d\n", 402262306a36Sopenharmony_ci proc->pid, thread->pid, 402362306a36Sopenharmony_ci cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", 402462306a36Sopenharmony_ci node->debug_id, node->local_strong_refs, 402562306a36Sopenharmony_ci node->local_weak_refs, node->tmp_refs); 402662306a36Sopenharmony_ci binder_node_inner_unlock(node); 402762306a36Sopenharmony_ci binder_put_node(node); 402862306a36Sopenharmony_ci break; 402962306a36Sopenharmony_ci } 403062306a36Sopenharmony_ci case BC_ATTEMPT_ACQUIRE: 403162306a36Sopenharmony_ci pr_err("BC_ATTEMPT_ACQUIRE not supported\n"); 403262306a36Sopenharmony_ci return -EINVAL; 403362306a36Sopenharmony_ci case BC_ACQUIRE_RESULT: 403462306a36Sopenharmony_ci pr_err("BC_ACQUIRE_RESULT not supported\n"); 403562306a36Sopenharmony_ci return -EINVAL; 403662306a36Sopenharmony_ci 403762306a36Sopenharmony_ci case BC_FREE_BUFFER: { 403862306a36Sopenharmony_ci binder_uintptr_t data_ptr; 403962306a36Sopenharmony_ci struct binder_buffer *buffer; 404062306a36Sopenharmony_ci 404162306a36Sopenharmony_ci if (get_user(data_ptr, (binder_uintptr_t __user *)ptr)) 404262306a36Sopenharmony_ci return -EFAULT; 404362306a36Sopenharmony_ci ptr += sizeof(binder_uintptr_t); 404462306a36Sopenharmony_ci 404562306a36Sopenharmony_ci buffer = binder_alloc_prepare_to_free(&proc->alloc, 404662306a36Sopenharmony_ci data_ptr); 404762306a36Sopenharmony_ci if (IS_ERR_OR_NULL(buffer)) { 404862306a36Sopenharmony_ci if (PTR_ERR(buffer) == -EPERM) { 404962306a36Sopenharmony_ci binder_user_error( 405062306a36Sopenharmony_ci "%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n", 405162306a36Sopenharmony_ci proc->pid, thread->pid, 405262306a36Sopenharmony_ci (u64)data_ptr); 405362306a36Sopenharmony_ci } else { 405462306a36Sopenharmony_ci binder_user_error( 405562306a36Sopenharmony_ci "%d:%d BC_FREE_BUFFER u%016llx no match\n", 405662306a36Sopenharmony_ci proc->pid, thread->pid, 405762306a36Sopenharmony_ci (u64)data_ptr); 405862306a36Sopenharmony_ci } 405962306a36Sopenharmony_ci break; 406062306a36Sopenharmony_ci } 406162306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_FREE_BUFFER, 406262306a36Sopenharmony_ci "%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n", 406362306a36Sopenharmony_ci proc->pid, thread->pid, (u64)data_ptr, 406462306a36Sopenharmony_ci buffer->debug_id, 406562306a36Sopenharmony_ci buffer->transaction ? "active" : "finished"); 406662306a36Sopenharmony_ci binder_free_buf(proc, thread, buffer, false); 406762306a36Sopenharmony_ci break; 406862306a36Sopenharmony_ci } 406962306a36Sopenharmony_ci 407062306a36Sopenharmony_ci case BC_TRANSACTION_SG: 407162306a36Sopenharmony_ci case BC_REPLY_SG: { 407262306a36Sopenharmony_ci struct binder_transaction_data_sg tr; 407362306a36Sopenharmony_ci 407462306a36Sopenharmony_ci if (copy_from_user(&tr, ptr, sizeof(tr))) 407562306a36Sopenharmony_ci return -EFAULT; 407662306a36Sopenharmony_ci ptr += sizeof(tr); 407762306a36Sopenharmony_ci binder_transaction(proc, thread, &tr.transaction_data, 407862306a36Sopenharmony_ci cmd == BC_REPLY_SG, tr.buffers_size); 407962306a36Sopenharmony_ci break; 408062306a36Sopenharmony_ci } 408162306a36Sopenharmony_ci case BC_TRANSACTION: 408262306a36Sopenharmony_ci case BC_REPLY: { 408362306a36Sopenharmony_ci struct binder_transaction_data tr; 408462306a36Sopenharmony_ci 408562306a36Sopenharmony_ci if (copy_from_user(&tr, ptr, sizeof(tr))) 408662306a36Sopenharmony_ci return -EFAULT; 408762306a36Sopenharmony_ci ptr += sizeof(tr); 408862306a36Sopenharmony_ci binder_transaction(proc, thread, &tr, 408962306a36Sopenharmony_ci cmd == BC_REPLY, 0); 409062306a36Sopenharmony_ci break; 409162306a36Sopenharmony_ci } 409262306a36Sopenharmony_ci 409362306a36Sopenharmony_ci case BC_REGISTER_LOOPER: 409462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_THREADS, 409562306a36Sopenharmony_ci "%d:%d BC_REGISTER_LOOPER\n", 409662306a36Sopenharmony_ci proc->pid, thread->pid); 409762306a36Sopenharmony_ci binder_inner_proc_lock(proc); 409862306a36Sopenharmony_ci if (thread->looper & BINDER_LOOPER_STATE_ENTERED) { 409962306a36Sopenharmony_ci thread->looper |= BINDER_LOOPER_STATE_INVALID; 410062306a36Sopenharmony_ci binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n", 410162306a36Sopenharmony_ci proc->pid, thread->pid); 410262306a36Sopenharmony_ci } else if (proc->requested_threads == 0) { 410362306a36Sopenharmony_ci thread->looper |= BINDER_LOOPER_STATE_INVALID; 410462306a36Sopenharmony_ci binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called without request\n", 410562306a36Sopenharmony_ci proc->pid, thread->pid); 410662306a36Sopenharmony_ci } else { 410762306a36Sopenharmony_ci proc->requested_threads--; 410862306a36Sopenharmony_ci proc->requested_threads_started++; 410962306a36Sopenharmony_ci } 411062306a36Sopenharmony_ci thread->looper |= BINDER_LOOPER_STATE_REGISTERED; 411162306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 411262306a36Sopenharmony_ci break; 411362306a36Sopenharmony_ci case BC_ENTER_LOOPER: 411462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_THREADS, 411562306a36Sopenharmony_ci "%d:%d BC_ENTER_LOOPER\n", 411662306a36Sopenharmony_ci proc->pid, thread->pid); 411762306a36Sopenharmony_ci if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) { 411862306a36Sopenharmony_ci thread->looper |= BINDER_LOOPER_STATE_INVALID; 411962306a36Sopenharmony_ci binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n", 412062306a36Sopenharmony_ci proc->pid, thread->pid); 412162306a36Sopenharmony_ci } 412262306a36Sopenharmony_ci thread->looper |= BINDER_LOOPER_STATE_ENTERED; 412362306a36Sopenharmony_ci break; 412462306a36Sopenharmony_ci case BC_EXIT_LOOPER: 412562306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_THREADS, 412662306a36Sopenharmony_ci "%d:%d BC_EXIT_LOOPER\n", 412762306a36Sopenharmony_ci proc->pid, thread->pid); 412862306a36Sopenharmony_ci thread->looper |= BINDER_LOOPER_STATE_EXITED; 412962306a36Sopenharmony_ci break; 413062306a36Sopenharmony_ci 413162306a36Sopenharmony_ci case BC_REQUEST_DEATH_NOTIFICATION: 413262306a36Sopenharmony_ci case BC_CLEAR_DEATH_NOTIFICATION: { 413362306a36Sopenharmony_ci uint32_t target; 413462306a36Sopenharmony_ci binder_uintptr_t cookie; 413562306a36Sopenharmony_ci struct binder_ref *ref; 413662306a36Sopenharmony_ci struct binder_ref_death *death = NULL; 413762306a36Sopenharmony_ci 413862306a36Sopenharmony_ci if (get_user(target, (uint32_t __user *)ptr)) 413962306a36Sopenharmony_ci return -EFAULT; 414062306a36Sopenharmony_ci ptr += sizeof(uint32_t); 414162306a36Sopenharmony_ci if (get_user(cookie, (binder_uintptr_t __user *)ptr)) 414262306a36Sopenharmony_ci return -EFAULT; 414362306a36Sopenharmony_ci ptr += sizeof(binder_uintptr_t); 414462306a36Sopenharmony_ci if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { 414562306a36Sopenharmony_ci /* 414662306a36Sopenharmony_ci * Allocate memory for death notification 414762306a36Sopenharmony_ci * before taking lock 414862306a36Sopenharmony_ci */ 414962306a36Sopenharmony_ci death = kzalloc(sizeof(*death), GFP_KERNEL); 415062306a36Sopenharmony_ci if (death == NULL) { 415162306a36Sopenharmony_ci WARN_ON(thread->return_error.cmd != 415262306a36Sopenharmony_ci BR_OK); 415362306a36Sopenharmony_ci thread->return_error.cmd = BR_ERROR; 415462306a36Sopenharmony_ci binder_enqueue_thread_work( 415562306a36Sopenharmony_ci thread, 415662306a36Sopenharmony_ci &thread->return_error.work); 415762306a36Sopenharmony_ci binder_debug( 415862306a36Sopenharmony_ci BINDER_DEBUG_FAILED_TRANSACTION, 415962306a36Sopenharmony_ci "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", 416062306a36Sopenharmony_ci proc->pid, thread->pid); 416162306a36Sopenharmony_ci break; 416262306a36Sopenharmony_ci } 416362306a36Sopenharmony_ci } 416462306a36Sopenharmony_ci binder_proc_lock(proc); 416562306a36Sopenharmony_ci ref = binder_get_ref_olocked(proc, target, false); 416662306a36Sopenharmony_ci if (ref == NULL) { 416762306a36Sopenharmony_ci binder_user_error("%d:%d %s invalid ref %d\n", 416862306a36Sopenharmony_ci proc->pid, thread->pid, 416962306a36Sopenharmony_ci cmd == BC_REQUEST_DEATH_NOTIFICATION ? 417062306a36Sopenharmony_ci "BC_REQUEST_DEATH_NOTIFICATION" : 417162306a36Sopenharmony_ci "BC_CLEAR_DEATH_NOTIFICATION", 417262306a36Sopenharmony_ci target); 417362306a36Sopenharmony_ci binder_proc_unlock(proc); 417462306a36Sopenharmony_ci kfree(death); 417562306a36Sopenharmony_ci break; 417662306a36Sopenharmony_ci } 417762306a36Sopenharmony_ci 417862306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, 417962306a36Sopenharmony_ci "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n", 418062306a36Sopenharmony_ci proc->pid, thread->pid, 418162306a36Sopenharmony_ci cmd == BC_REQUEST_DEATH_NOTIFICATION ? 418262306a36Sopenharmony_ci "BC_REQUEST_DEATH_NOTIFICATION" : 418362306a36Sopenharmony_ci "BC_CLEAR_DEATH_NOTIFICATION", 418462306a36Sopenharmony_ci (u64)cookie, ref->data.debug_id, 418562306a36Sopenharmony_ci ref->data.desc, ref->data.strong, 418662306a36Sopenharmony_ci ref->data.weak, ref->node->debug_id); 418762306a36Sopenharmony_ci 418862306a36Sopenharmony_ci binder_node_lock(ref->node); 418962306a36Sopenharmony_ci if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { 419062306a36Sopenharmony_ci if (ref->death) { 419162306a36Sopenharmony_ci binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", 419262306a36Sopenharmony_ci proc->pid, thread->pid); 419362306a36Sopenharmony_ci binder_node_unlock(ref->node); 419462306a36Sopenharmony_ci binder_proc_unlock(proc); 419562306a36Sopenharmony_ci kfree(death); 419662306a36Sopenharmony_ci break; 419762306a36Sopenharmony_ci } 419862306a36Sopenharmony_ci binder_stats_created(BINDER_STAT_DEATH); 419962306a36Sopenharmony_ci INIT_LIST_HEAD(&death->work.entry); 420062306a36Sopenharmony_ci death->cookie = cookie; 420162306a36Sopenharmony_ci ref->death = death; 420262306a36Sopenharmony_ci if (ref->node->proc == NULL) { 420362306a36Sopenharmony_ci ref->death->work.type = BINDER_WORK_DEAD_BINDER; 420462306a36Sopenharmony_ci 420562306a36Sopenharmony_ci binder_inner_proc_lock(proc); 420662306a36Sopenharmony_ci binder_enqueue_work_ilocked( 420762306a36Sopenharmony_ci &ref->death->work, &proc->todo); 420862306a36Sopenharmony_ci binder_wakeup_proc_ilocked(proc); 420962306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 421062306a36Sopenharmony_ci } 421162306a36Sopenharmony_ci } else { 421262306a36Sopenharmony_ci if (ref->death == NULL) { 421362306a36Sopenharmony_ci binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", 421462306a36Sopenharmony_ci proc->pid, thread->pid); 421562306a36Sopenharmony_ci binder_node_unlock(ref->node); 421662306a36Sopenharmony_ci binder_proc_unlock(proc); 421762306a36Sopenharmony_ci break; 421862306a36Sopenharmony_ci } 421962306a36Sopenharmony_ci death = ref->death; 422062306a36Sopenharmony_ci if (death->cookie != cookie) { 422162306a36Sopenharmony_ci binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n", 422262306a36Sopenharmony_ci proc->pid, thread->pid, 422362306a36Sopenharmony_ci (u64)death->cookie, 422462306a36Sopenharmony_ci (u64)cookie); 422562306a36Sopenharmony_ci binder_node_unlock(ref->node); 422662306a36Sopenharmony_ci binder_proc_unlock(proc); 422762306a36Sopenharmony_ci break; 422862306a36Sopenharmony_ci } 422962306a36Sopenharmony_ci ref->death = NULL; 423062306a36Sopenharmony_ci binder_inner_proc_lock(proc); 423162306a36Sopenharmony_ci if (list_empty(&death->work.entry)) { 423262306a36Sopenharmony_ci death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; 423362306a36Sopenharmony_ci if (thread->looper & 423462306a36Sopenharmony_ci (BINDER_LOOPER_STATE_REGISTERED | 423562306a36Sopenharmony_ci BINDER_LOOPER_STATE_ENTERED)) 423662306a36Sopenharmony_ci binder_enqueue_thread_work_ilocked( 423762306a36Sopenharmony_ci thread, 423862306a36Sopenharmony_ci &death->work); 423962306a36Sopenharmony_ci else { 424062306a36Sopenharmony_ci binder_enqueue_work_ilocked( 424162306a36Sopenharmony_ci &death->work, 424262306a36Sopenharmony_ci &proc->todo); 424362306a36Sopenharmony_ci binder_wakeup_proc_ilocked( 424462306a36Sopenharmony_ci proc); 424562306a36Sopenharmony_ci } 424662306a36Sopenharmony_ci } else { 424762306a36Sopenharmony_ci BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER); 424862306a36Sopenharmony_ci death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; 424962306a36Sopenharmony_ci } 425062306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 425162306a36Sopenharmony_ci } 425262306a36Sopenharmony_ci binder_node_unlock(ref->node); 425362306a36Sopenharmony_ci binder_proc_unlock(proc); 425462306a36Sopenharmony_ci } break; 425562306a36Sopenharmony_ci case BC_DEAD_BINDER_DONE: { 425662306a36Sopenharmony_ci struct binder_work *w; 425762306a36Sopenharmony_ci binder_uintptr_t cookie; 425862306a36Sopenharmony_ci struct binder_ref_death *death = NULL; 425962306a36Sopenharmony_ci 426062306a36Sopenharmony_ci if (get_user(cookie, (binder_uintptr_t __user *)ptr)) 426162306a36Sopenharmony_ci return -EFAULT; 426262306a36Sopenharmony_ci 426362306a36Sopenharmony_ci ptr += sizeof(cookie); 426462306a36Sopenharmony_ci binder_inner_proc_lock(proc); 426562306a36Sopenharmony_ci list_for_each_entry(w, &proc->delivered_death, 426662306a36Sopenharmony_ci entry) { 426762306a36Sopenharmony_ci struct binder_ref_death *tmp_death = 426862306a36Sopenharmony_ci container_of(w, 426962306a36Sopenharmony_ci struct binder_ref_death, 427062306a36Sopenharmony_ci work); 427162306a36Sopenharmony_ci 427262306a36Sopenharmony_ci if (tmp_death->cookie == cookie) { 427362306a36Sopenharmony_ci death = tmp_death; 427462306a36Sopenharmony_ci break; 427562306a36Sopenharmony_ci } 427662306a36Sopenharmony_ci } 427762306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_BINDER, 427862306a36Sopenharmony_ci "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n", 427962306a36Sopenharmony_ci proc->pid, thread->pid, (u64)cookie, 428062306a36Sopenharmony_ci death); 428162306a36Sopenharmony_ci if (death == NULL) { 428262306a36Sopenharmony_ci binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n", 428362306a36Sopenharmony_ci proc->pid, thread->pid, (u64)cookie); 428462306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 428562306a36Sopenharmony_ci break; 428662306a36Sopenharmony_ci } 428762306a36Sopenharmony_ci binder_dequeue_work_ilocked(&death->work); 428862306a36Sopenharmony_ci if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) { 428962306a36Sopenharmony_ci death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; 429062306a36Sopenharmony_ci if (thread->looper & 429162306a36Sopenharmony_ci (BINDER_LOOPER_STATE_REGISTERED | 429262306a36Sopenharmony_ci BINDER_LOOPER_STATE_ENTERED)) 429362306a36Sopenharmony_ci binder_enqueue_thread_work_ilocked( 429462306a36Sopenharmony_ci thread, &death->work); 429562306a36Sopenharmony_ci else { 429662306a36Sopenharmony_ci binder_enqueue_work_ilocked( 429762306a36Sopenharmony_ci &death->work, 429862306a36Sopenharmony_ci &proc->todo); 429962306a36Sopenharmony_ci binder_wakeup_proc_ilocked(proc); 430062306a36Sopenharmony_ci } 430162306a36Sopenharmony_ci } 430262306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 430362306a36Sopenharmony_ci } break; 430462306a36Sopenharmony_ci 430562306a36Sopenharmony_ci default: 430662306a36Sopenharmony_ci pr_err("%d:%d unknown command %u\n", 430762306a36Sopenharmony_ci proc->pid, thread->pid, cmd); 430862306a36Sopenharmony_ci return -EINVAL; 430962306a36Sopenharmony_ci } 431062306a36Sopenharmony_ci *consumed = ptr - buffer; 431162306a36Sopenharmony_ci } 431262306a36Sopenharmony_ci return 0; 431362306a36Sopenharmony_ci} 431462306a36Sopenharmony_ci 431562306a36Sopenharmony_cistatic void binder_stat_br(struct binder_proc *proc, 431662306a36Sopenharmony_ci struct binder_thread *thread, uint32_t cmd) 431762306a36Sopenharmony_ci{ 431862306a36Sopenharmony_ci trace_binder_return(cmd); 431962306a36Sopenharmony_ci if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) { 432062306a36Sopenharmony_ci atomic_inc(&binder_stats.br[_IOC_NR(cmd)]); 432162306a36Sopenharmony_ci atomic_inc(&proc->stats.br[_IOC_NR(cmd)]); 432262306a36Sopenharmony_ci atomic_inc(&thread->stats.br[_IOC_NR(cmd)]); 432362306a36Sopenharmony_ci } 432462306a36Sopenharmony_ci} 432562306a36Sopenharmony_ci 432662306a36Sopenharmony_cistatic int binder_put_node_cmd(struct binder_proc *proc, 432762306a36Sopenharmony_ci struct binder_thread *thread, 432862306a36Sopenharmony_ci void __user **ptrp, 432962306a36Sopenharmony_ci binder_uintptr_t node_ptr, 433062306a36Sopenharmony_ci binder_uintptr_t node_cookie, 433162306a36Sopenharmony_ci int node_debug_id, 433262306a36Sopenharmony_ci uint32_t cmd, const char *cmd_name) 433362306a36Sopenharmony_ci{ 433462306a36Sopenharmony_ci void __user *ptr = *ptrp; 433562306a36Sopenharmony_ci 433662306a36Sopenharmony_ci if (put_user(cmd, (uint32_t __user *)ptr)) 433762306a36Sopenharmony_ci return -EFAULT; 433862306a36Sopenharmony_ci ptr += sizeof(uint32_t); 433962306a36Sopenharmony_ci 434062306a36Sopenharmony_ci if (put_user(node_ptr, (binder_uintptr_t __user *)ptr)) 434162306a36Sopenharmony_ci return -EFAULT; 434262306a36Sopenharmony_ci ptr += sizeof(binder_uintptr_t); 434362306a36Sopenharmony_ci 434462306a36Sopenharmony_ci if (put_user(node_cookie, (binder_uintptr_t __user *)ptr)) 434562306a36Sopenharmony_ci return -EFAULT; 434662306a36Sopenharmony_ci ptr += sizeof(binder_uintptr_t); 434762306a36Sopenharmony_ci 434862306a36Sopenharmony_ci binder_stat_br(proc, thread, cmd); 434962306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_USER_REFS, "%d:%d %s %d u%016llx c%016llx\n", 435062306a36Sopenharmony_ci proc->pid, thread->pid, cmd_name, node_debug_id, 435162306a36Sopenharmony_ci (u64)node_ptr, (u64)node_cookie); 435262306a36Sopenharmony_ci 435362306a36Sopenharmony_ci *ptrp = ptr; 435462306a36Sopenharmony_ci return 0; 435562306a36Sopenharmony_ci} 435662306a36Sopenharmony_ci 435762306a36Sopenharmony_cistatic int binder_wait_for_work(struct binder_thread *thread, 435862306a36Sopenharmony_ci bool do_proc_work) 435962306a36Sopenharmony_ci{ 436062306a36Sopenharmony_ci DEFINE_WAIT(wait); 436162306a36Sopenharmony_ci struct binder_proc *proc = thread->proc; 436262306a36Sopenharmony_ci int ret = 0; 436362306a36Sopenharmony_ci 436462306a36Sopenharmony_ci binder_inner_proc_lock(proc); 436562306a36Sopenharmony_ci for (;;) { 436662306a36Sopenharmony_ci prepare_to_wait(&thread->wait, &wait, TASK_INTERRUPTIBLE|TASK_FREEZABLE); 436762306a36Sopenharmony_ci if (binder_has_work_ilocked(thread, do_proc_work)) 436862306a36Sopenharmony_ci break; 436962306a36Sopenharmony_ci if (do_proc_work) 437062306a36Sopenharmony_ci list_add(&thread->waiting_thread_node, 437162306a36Sopenharmony_ci &proc->waiting_threads); 437262306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 437362306a36Sopenharmony_ci schedule(); 437462306a36Sopenharmony_ci binder_inner_proc_lock(proc); 437562306a36Sopenharmony_ci list_del_init(&thread->waiting_thread_node); 437662306a36Sopenharmony_ci if (signal_pending(current)) { 437762306a36Sopenharmony_ci ret = -EINTR; 437862306a36Sopenharmony_ci break; 437962306a36Sopenharmony_ci } 438062306a36Sopenharmony_ci } 438162306a36Sopenharmony_ci finish_wait(&thread->wait, &wait); 438262306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 438362306a36Sopenharmony_ci 438462306a36Sopenharmony_ci return ret; 438562306a36Sopenharmony_ci} 438662306a36Sopenharmony_ci 438762306a36Sopenharmony_ci/** 438862306a36Sopenharmony_ci * binder_apply_fd_fixups() - finish fd translation 438962306a36Sopenharmony_ci * @proc: binder_proc associated @t->buffer 439062306a36Sopenharmony_ci * @t: binder transaction with list of fd fixups 439162306a36Sopenharmony_ci * 439262306a36Sopenharmony_ci * Now that we are in the context of the transaction target 439362306a36Sopenharmony_ci * process, we can allocate and install fds. Process the 439462306a36Sopenharmony_ci * list of fds to translate and fixup the buffer with the 439562306a36Sopenharmony_ci * new fds first and only then install the files. 439662306a36Sopenharmony_ci * 439762306a36Sopenharmony_ci * If we fail to allocate an fd, skip the install and release 439862306a36Sopenharmony_ci * any fds that have already been allocated. 439962306a36Sopenharmony_ci */ 440062306a36Sopenharmony_cistatic int binder_apply_fd_fixups(struct binder_proc *proc, 440162306a36Sopenharmony_ci struct binder_transaction *t) 440262306a36Sopenharmony_ci{ 440362306a36Sopenharmony_ci struct binder_txn_fd_fixup *fixup, *tmp; 440462306a36Sopenharmony_ci int ret = 0; 440562306a36Sopenharmony_ci 440662306a36Sopenharmony_ci list_for_each_entry(fixup, &t->fd_fixups, fixup_entry) { 440762306a36Sopenharmony_ci int fd = get_unused_fd_flags(O_CLOEXEC); 440862306a36Sopenharmony_ci 440962306a36Sopenharmony_ci if (fd < 0) { 441062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 441162306a36Sopenharmony_ci "failed fd fixup txn %d fd %d\n", 441262306a36Sopenharmony_ci t->debug_id, fd); 441362306a36Sopenharmony_ci ret = -ENOMEM; 441462306a36Sopenharmony_ci goto err; 441562306a36Sopenharmony_ci } 441662306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 441762306a36Sopenharmony_ci "fd fixup txn %d fd %d\n", 441862306a36Sopenharmony_ci t->debug_id, fd); 441962306a36Sopenharmony_ci trace_binder_transaction_fd_recv(t, fd, fixup->offset); 442062306a36Sopenharmony_ci fixup->target_fd = fd; 442162306a36Sopenharmony_ci if (binder_alloc_copy_to_buffer(&proc->alloc, t->buffer, 442262306a36Sopenharmony_ci fixup->offset, &fd, 442362306a36Sopenharmony_ci sizeof(u32))) { 442462306a36Sopenharmony_ci ret = -EINVAL; 442562306a36Sopenharmony_ci goto err; 442662306a36Sopenharmony_ci } 442762306a36Sopenharmony_ci } 442862306a36Sopenharmony_ci list_for_each_entry_safe(fixup, tmp, &t->fd_fixups, fixup_entry) { 442962306a36Sopenharmony_ci fd_install(fixup->target_fd, fixup->file); 443062306a36Sopenharmony_ci list_del(&fixup->fixup_entry); 443162306a36Sopenharmony_ci kfree(fixup); 443262306a36Sopenharmony_ci } 443362306a36Sopenharmony_ci 443462306a36Sopenharmony_ci return ret; 443562306a36Sopenharmony_ci 443662306a36Sopenharmony_cierr: 443762306a36Sopenharmony_ci binder_free_txn_fixups(t); 443862306a36Sopenharmony_ci return ret; 443962306a36Sopenharmony_ci} 444062306a36Sopenharmony_ci 444162306a36Sopenharmony_cistatic int binder_thread_read(struct binder_proc *proc, 444262306a36Sopenharmony_ci struct binder_thread *thread, 444362306a36Sopenharmony_ci binder_uintptr_t binder_buffer, size_t size, 444462306a36Sopenharmony_ci binder_size_t *consumed, int non_block) 444562306a36Sopenharmony_ci{ 444662306a36Sopenharmony_ci void __user *buffer = (void __user *)(uintptr_t)binder_buffer; 444762306a36Sopenharmony_ci void __user *ptr = buffer + *consumed; 444862306a36Sopenharmony_ci void __user *end = buffer + size; 444962306a36Sopenharmony_ci 445062306a36Sopenharmony_ci int ret = 0; 445162306a36Sopenharmony_ci int wait_for_proc_work; 445262306a36Sopenharmony_ci 445362306a36Sopenharmony_ci if (*consumed == 0) { 445462306a36Sopenharmony_ci if (put_user(BR_NOOP, (uint32_t __user *)ptr)) 445562306a36Sopenharmony_ci return -EFAULT; 445662306a36Sopenharmony_ci ptr += sizeof(uint32_t); 445762306a36Sopenharmony_ci } 445862306a36Sopenharmony_ci 445962306a36Sopenharmony_ciretry: 446062306a36Sopenharmony_ci binder_inner_proc_lock(proc); 446162306a36Sopenharmony_ci wait_for_proc_work = binder_available_for_proc_work_ilocked(thread); 446262306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 446362306a36Sopenharmony_ci 446462306a36Sopenharmony_ci thread->looper |= BINDER_LOOPER_STATE_WAITING; 446562306a36Sopenharmony_ci 446662306a36Sopenharmony_ci trace_binder_wait_for_work(wait_for_proc_work, 446762306a36Sopenharmony_ci !!thread->transaction_stack, 446862306a36Sopenharmony_ci !binder_worklist_empty(proc, &thread->todo)); 446962306a36Sopenharmony_ci if (wait_for_proc_work) { 447062306a36Sopenharmony_ci if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | 447162306a36Sopenharmony_ci BINDER_LOOPER_STATE_ENTERED))) { 447262306a36Sopenharmony_ci binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n", 447362306a36Sopenharmony_ci proc->pid, thread->pid, thread->looper); 447462306a36Sopenharmony_ci wait_event_interruptible(binder_user_error_wait, 447562306a36Sopenharmony_ci binder_stop_on_user_error < 2); 447662306a36Sopenharmony_ci } 447762306a36Sopenharmony_ci binder_set_nice(proc->default_priority); 447862306a36Sopenharmony_ci } 447962306a36Sopenharmony_ci 448062306a36Sopenharmony_ci if (non_block) { 448162306a36Sopenharmony_ci if (!binder_has_work(thread, wait_for_proc_work)) 448262306a36Sopenharmony_ci ret = -EAGAIN; 448362306a36Sopenharmony_ci } else { 448462306a36Sopenharmony_ci ret = binder_wait_for_work(thread, wait_for_proc_work); 448562306a36Sopenharmony_ci } 448662306a36Sopenharmony_ci 448762306a36Sopenharmony_ci thread->looper &= ~BINDER_LOOPER_STATE_WAITING; 448862306a36Sopenharmony_ci 448962306a36Sopenharmony_ci if (ret) 449062306a36Sopenharmony_ci return ret; 449162306a36Sopenharmony_ci 449262306a36Sopenharmony_ci while (1) { 449362306a36Sopenharmony_ci uint32_t cmd; 449462306a36Sopenharmony_ci struct binder_transaction_data_secctx tr; 449562306a36Sopenharmony_ci struct binder_transaction_data *trd = &tr.transaction_data; 449662306a36Sopenharmony_ci struct binder_work *w = NULL; 449762306a36Sopenharmony_ci struct list_head *list = NULL; 449862306a36Sopenharmony_ci struct binder_transaction *t = NULL; 449962306a36Sopenharmony_ci struct binder_thread *t_from; 450062306a36Sopenharmony_ci size_t trsize = sizeof(*trd); 450162306a36Sopenharmony_ci 450262306a36Sopenharmony_ci binder_inner_proc_lock(proc); 450362306a36Sopenharmony_ci if (!binder_worklist_empty_ilocked(&thread->todo)) 450462306a36Sopenharmony_ci list = &thread->todo; 450562306a36Sopenharmony_ci else if (!binder_worklist_empty_ilocked(&proc->todo) && 450662306a36Sopenharmony_ci wait_for_proc_work) 450762306a36Sopenharmony_ci list = &proc->todo; 450862306a36Sopenharmony_ci else { 450962306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 451062306a36Sopenharmony_ci 451162306a36Sopenharmony_ci /* no data added */ 451262306a36Sopenharmony_ci if (ptr - buffer == 4 && !thread->looper_need_return) 451362306a36Sopenharmony_ci goto retry; 451462306a36Sopenharmony_ci break; 451562306a36Sopenharmony_ci } 451662306a36Sopenharmony_ci 451762306a36Sopenharmony_ci if (end - ptr < sizeof(tr) + 4) { 451862306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 451962306a36Sopenharmony_ci break; 452062306a36Sopenharmony_ci } 452162306a36Sopenharmony_ci w = binder_dequeue_work_head_ilocked(list); 452262306a36Sopenharmony_ci if (binder_worklist_empty_ilocked(&thread->todo)) 452362306a36Sopenharmony_ci thread->process_todo = false; 452462306a36Sopenharmony_ci 452562306a36Sopenharmony_ci switch (w->type) { 452662306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION: { 452762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 452862306a36Sopenharmony_ci t = container_of(w, struct binder_transaction, work); 452962306a36Sopenharmony_ci } break; 453062306a36Sopenharmony_ci case BINDER_WORK_RETURN_ERROR: { 453162306a36Sopenharmony_ci struct binder_error *e = container_of( 453262306a36Sopenharmony_ci w, struct binder_error, work); 453362306a36Sopenharmony_ci 453462306a36Sopenharmony_ci WARN_ON(e->cmd == BR_OK); 453562306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 453662306a36Sopenharmony_ci if (put_user(e->cmd, (uint32_t __user *)ptr)) 453762306a36Sopenharmony_ci return -EFAULT; 453862306a36Sopenharmony_ci cmd = e->cmd; 453962306a36Sopenharmony_ci e->cmd = BR_OK; 454062306a36Sopenharmony_ci ptr += sizeof(uint32_t); 454162306a36Sopenharmony_ci 454262306a36Sopenharmony_ci binder_stat_br(proc, thread, cmd); 454362306a36Sopenharmony_ci } break; 454462306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION_COMPLETE: 454562306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION_PENDING: 454662306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: { 454762306a36Sopenharmony_ci if (proc->oneway_spam_detection_enabled && 454862306a36Sopenharmony_ci w->type == BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT) 454962306a36Sopenharmony_ci cmd = BR_ONEWAY_SPAM_SUSPECT; 455062306a36Sopenharmony_ci else if (w->type == BINDER_WORK_TRANSACTION_PENDING) 455162306a36Sopenharmony_ci cmd = BR_TRANSACTION_PENDING_FROZEN; 455262306a36Sopenharmony_ci else 455362306a36Sopenharmony_ci cmd = BR_TRANSACTION_COMPLETE; 455462306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 455562306a36Sopenharmony_ci kfree(w); 455662306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); 455762306a36Sopenharmony_ci if (put_user(cmd, (uint32_t __user *)ptr)) 455862306a36Sopenharmony_ci return -EFAULT; 455962306a36Sopenharmony_ci ptr += sizeof(uint32_t); 456062306a36Sopenharmony_ci 456162306a36Sopenharmony_ci binder_stat_br(proc, thread, cmd); 456262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE, 456362306a36Sopenharmony_ci "%d:%d BR_TRANSACTION_COMPLETE\n", 456462306a36Sopenharmony_ci proc->pid, thread->pid); 456562306a36Sopenharmony_ci } break; 456662306a36Sopenharmony_ci case BINDER_WORK_NODE: { 456762306a36Sopenharmony_ci struct binder_node *node = container_of(w, struct binder_node, work); 456862306a36Sopenharmony_ci int strong, weak; 456962306a36Sopenharmony_ci binder_uintptr_t node_ptr = node->ptr; 457062306a36Sopenharmony_ci binder_uintptr_t node_cookie = node->cookie; 457162306a36Sopenharmony_ci int node_debug_id = node->debug_id; 457262306a36Sopenharmony_ci int has_weak_ref; 457362306a36Sopenharmony_ci int has_strong_ref; 457462306a36Sopenharmony_ci void __user *orig_ptr = ptr; 457562306a36Sopenharmony_ci 457662306a36Sopenharmony_ci BUG_ON(proc != node->proc); 457762306a36Sopenharmony_ci strong = node->internal_strong_refs || 457862306a36Sopenharmony_ci node->local_strong_refs; 457962306a36Sopenharmony_ci weak = !hlist_empty(&node->refs) || 458062306a36Sopenharmony_ci node->local_weak_refs || 458162306a36Sopenharmony_ci node->tmp_refs || strong; 458262306a36Sopenharmony_ci has_strong_ref = node->has_strong_ref; 458362306a36Sopenharmony_ci has_weak_ref = node->has_weak_ref; 458462306a36Sopenharmony_ci 458562306a36Sopenharmony_ci if (weak && !has_weak_ref) { 458662306a36Sopenharmony_ci node->has_weak_ref = 1; 458762306a36Sopenharmony_ci node->pending_weak_ref = 1; 458862306a36Sopenharmony_ci node->local_weak_refs++; 458962306a36Sopenharmony_ci } 459062306a36Sopenharmony_ci if (strong && !has_strong_ref) { 459162306a36Sopenharmony_ci node->has_strong_ref = 1; 459262306a36Sopenharmony_ci node->pending_strong_ref = 1; 459362306a36Sopenharmony_ci node->local_strong_refs++; 459462306a36Sopenharmony_ci } 459562306a36Sopenharmony_ci if (!strong && has_strong_ref) 459662306a36Sopenharmony_ci node->has_strong_ref = 0; 459762306a36Sopenharmony_ci if (!weak && has_weak_ref) 459862306a36Sopenharmony_ci node->has_weak_ref = 0; 459962306a36Sopenharmony_ci if (!weak && !strong) { 460062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_INTERNAL_REFS, 460162306a36Sopenharmony_ci "%d:%d node %d u%016llx c%016llx deleted\n", 460262306a36Sopenharmony_ci proc->pid, thread->pid, 460362306a36Sopenharmony_ci node_debug_id, 460462306a36Sopenharmony_ci (u64)node_ptr, 460562306a36Sopenharmony_ci (u64)node_cookie); 460662306a36Sopenharmony_ci rb_erase(&node->rb_node, &proc->nodes); 460762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 460862306a36Sopenharmony_ci binder_node_lock(node); 460962306a36Sopenharmony_ci /* 461062306a36Sopenharmony_ci * Acquire the node lock before freeing the 461162306a36Sopenharmony_ci * node to serialize with other threads that 461262306a36Sopenharmony_ci * may have been holding the node lock while 461362306a36Sopenharmony_ci * decrementing this node (avoids race where 461462306a36Sopenharmony_ci * this thread frees while the other thread 461562306a36Sopenharmony_ci * is unlocking the node after the final 461662306a36Sopenharmony_ci * decrement) 461762306a36Sopenharmony_ci */ 461862306a36Sopenharmony_ci binder_node_unlock(node); 461962306a36Sopenharmony_ci binder_free_node(node); 462062306a36Sopenharmony_ci } else 462162306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 462262306a36Sopenharmony_ci 462362306a36Sopenharmony_ci if (weak && !has_weak_ref) 462462306a36Sopenharmony_ci ret = binder_put_node_cmd( 462562306a36Sopenharmony_ci proc, thread, &ptr, node_ptr, 462662306a36Sopenharmony_ci node_cookie, node_debug_id, 462762306a36Sopenharmony_ci BR_INCREFS, "BR_INCREFS"); 462862306a36Sopenharmony_ci if (!ret && strong && !has_strong_ref) 462962306a36Sopenharmony_ci ret = binder_put_node_cmd( 463062306a36Sopenharmony_ci proc, thread, &ptr, node_ptr, 463162306a36Sopenharmony_ci node_cookie, node_debug_id, 463262306a36Sopenharmony_ci BR_ACQUIRE, "BR_ACQUIRE"); 463362306a36Sopenharmony_ci if (!ret && !strong && has_strong_ref) 463462306a36Sopenharmony_ci ret = binder_put_node_cmd( 463562306a36Sopenharmony_ci proc, thread, &ptr, node_ptr, 463662306a36Sopenharmony_ci node_cookie, node_debug_id, 463762306a36Sopenharmony_ci BR_RELEASE, "BR_RELEASE"); 463862306a36Sopenharmony_ci if (!ret && !weak && has_weak_ref) 463962306a36Sopenharmony_ci ret = binder_put_node_cmd( 464062306a36Sopenharmony_ci proc, thread, &ptr, node_ptr, 464162306a36Sopenharmony_ci node_cookie, node_debug_id, 464262306a36Sopenharmony_ci BR_DECREFS, "BR_DECREFS"); 464362306a36Sopenharmony_ci if (orig_ptr == ptr) 464462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_INTERNAL_REFS, 464562306a36Sopenharmony_ci "%d:%d node %d u%016llx c%016llx state unchanged\n", 464662306a36Sopenharmony_ci proc->pid, thread->pid, 464762306a36Sopenharmony_ci node_debug_id, 464862306a36Sopenharmony_ci (u64)node_ptr, 464962306a36Sopenharmony_ci (u64)node_cookie); 465062306a36Sopenharmony_ci if (ret) 465162306a36Sopenharmony_ci return ret; 465262306a36Sopenharmony_ci } break; 465362306a36Sopenharmony_ci case BINDER_WORK_DEAD_BINDER: 465462306a36Sopenharmony_ci case BINDER_WORK_DEAD_BINDER_AND_CLEAR: 465562306a36Sopenharmony_ci case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { 465662306a36Sopenharmony_ci struct binder_ref_death *death; 465762306a36Sopenharmony_ci uint32_t cmd; 465862306a36Sopenharmony_ci binder_uintptr_t cookie; 465962306a36Sopenharmony_ci 466062306a36Sopenharmony_ci death = container_of(w, struct binder_ref_death, work); 466162306a36Sopenharmony_ci if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) 466262306a36Sopenharmony_ci cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE; 466362306a36Sopenharmony_ci else 466462306a36Sopenharmony_ci cmd = BR_DEAD_BINDER; 466562306a36Sopenharmony_ci cookie = death->cookie; 466662306a36Sopenharmony_ci 466762306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, 466862306a36Sopenharmony_ci "%d:%d %s %016llx\n", 466962306a36Sopenharmony_ci proc->pid, thread->pid, 467062306a36Sopenharmony_ci cmd == BR_DEAD_BINDER ? 467162306a36Sopenharmony_ci "BR_DEAD_BINDER" : 467262306a36Sopenharmony_ci "BR_CLEAR_DEATH_NOTIFICATION_DONE", 467362306a36Sopenharmony_ci (u64)cookie); 467462306a36Sopenharmony_ci if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { 467562306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 467662306a36Sopenharmony_ci kfree(death); 467762306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_DEATH); 467862306a36Sopenharmony_ci } else { 467962306a36Sopenharmony_ci binder_enqueue_work_ilocked( 468062306a36Sopenharmony_ci w, &proc->delivered_death); 468162306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 468262306a36Sopenharmony_ci } 468362306a36Sopenharmony_ci if (put_user(cmd, (uint32_t __user *)ptr)) 468462306a36Sopenharmony_ci return -EFAULT; 468562306a36Sopenharmony_ci ptr += sizeof(uint32_t); 468662306a36Sopenharmony_ci if (put_user(cookie, 468762306a36Sopenharmony_ci (binder_uintptr_t __user *)ptr)) 468862306a36Sopenharmony_ci return -EFAULT; 468962306a36Sopenharmony_ci ptr += sizeof(binder_uintptr_t); 469062306a36Sopenharmony_ci binder_stat_br(proc, thread, cmd); 469162306a36Sopenharmony_ci if (cmd == BR_DEAD_BINDER) 469262306a36Sopenharmony_ci goto done; /* DEAD_BINDER notifications can cause transactions */ 469362306a36Sopenharmony_ci } break; 469462306a36Sopenharmony_ci default: 469562306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 469662306a36Sopenharmony_ci pr_err("%d:%d: bad work type %d\n", 469762306a36Sopenharmony_ci proc->pid, thread->pid, w->type); 469862306a36Sopenharmony_ci break; 469962306a36Sopenharmony_ci } 470062306a36Sopenharmony_ci 470162306a36Sopenharmony_ci if (!t) 470262306a36Sopenharmony_ci continue; 470362306a36Sopenharmony_ci 470462306a36Sopenharmony_ci BUG_ON(t->buffer == NULL); 470562306a36Sopenharmony_ci if (t->buffer->target_node) { 470662306a36Sopenharmony_ci struct binder_node *target_node = t->buffer->target_node; 470762306a36Sopenharmony_ci 470862306a36Sopenharmony_ci trd->target.ptr = target_node->ptr; 470962306a36Sopenharmony_ci trd->cookie = target_node->cookie; 471062306a36Sopenharmony_ci t->saved_priority = task_nice(current); 471162306a36Sopenharmony_ci if (t->priority < target_node->min_priority && 471262306a36Sopenharmony_ci !(t->flags & TF_ONE_WAY)) 471362306a36Sopenharmony_ci binder_set_nice(t->priority); 471462306a36Sopenharmony_ci else if (!(t->flags & TF_ONE_WAY) || 471562306a36Sopenharmony_ci t->saved_priority > target_node->min_priority) 471662306a36Sopenharmony_ci binder_set_nice(target_node->min_priority); 471762306a36Sopenharmony_ci cmd = BR_TRANSACTION; 471862306a36Sopenharmony_ci } else { 471962306a36Sopenharmony_ci trd->target.ptr = 0; 472062306a36Sopenharmony_ci trd->cookie = 0; 472162306a36Sopenharmony_ci cmd = BR_REPLY; 472262306a36Sopenharmony_ci } 472362306a36Sopenharmony_ci trd->code = t->code; 472462306a36Sopenharmony_ci trd->flags = t->flags; 472562306a36Sopenharmony_ci trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid); 472662306a36Sopenharmony_ci 472762306a36Sopenharmony_ci t_from = binder_get_txn_from(t); 472862306a36Sopenharmony_ci if (t_from) { 472962306a36Sopenharmony_ci struct task_struct *sender = t_from->proc->tsk; 473062306a36Sopenharmony_ci 473162306a36Sopenharmony_ci trd->sender_pid = 473262306a36Sopenharmony_ci task_tgid_nr_ns(sender, 473362306a36Sopenharmony_ci task_active_pid_ns(current)); 473462306a36Sopenharmony_ci#ifdef CONFIG_BINDER_SENDER_INFO 473562306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 473662306a36Sopenharmony_ci thread->sender_pid_nr = task_tgid_nr(sender); 473762306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 473862306a36Sopenharmony_ci#endif 473962306a36Sopenharmony_ci } else { 474062306a36Sopenharmony_ci trd->sender_pid = 0; 474162306a36Sopenharmony_ci#ifdef CONFIG_BINDER_SENDER_INFO 474262306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 474362306a36Sopenharmony_ci thread->sender_pid_nr = 0; 474462306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 474562306a36Sopenharmony_ci#endif 474662306a36Sopenharmony_ci } 474762306a36Sopenharmony_ci 474862306a36Sopenharmony_ci ret = binder_apply_fd_fixups(proc, t); 474962306a36Sopenharmony_ci if (ret) { 475062306a36Sopenharmony_ci struct binder_buffer *buffer = t->buffer; 475162306a36Sopenharmony_ci bool oneway = !!(t->flags & TF_ONE_WAY); 475262306a36Sopenharmony_ci int tid = t->debug_id; 475362306a36Sopenharmony_ci 475462306a36Sopenharmony_ci if (t_from) 475562306a36Sopenharmony_ci binder_thread_dec_tmpref(t_from); 475662306a36Sopenharmony_ci buffer->transaction = NULL; 475762306a36Sopenharmony_ci binder_cleanup_transaction(t, "fd fixups failed", 475862306a36Sopenharmony_ci BR_FAILED_REPLY); 475962306a36Sopenharmony_ci binder_free_buf(proc, thread, buffer, true); 476062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, 476162306a36Sopenharmony_ci "%d:%d %stransaction %d fd fixups failed %d/%d, line %d\n", 476262306a36Sopenharmony_ci proc->pid, thread->pid, 476362306a36Sopenharmony_ci oneway ? "async " : 476462306a36Sopenharmony_ci (cmd == BR_REPLY ? "reply " : ""), 476562306a36Sopenharmony_ci tid, BR_FAILED_REPLY, ret, __LINE__); 476662306a36Sopenharmony_ci if (cmd == BR_REPLY) { 476762306a36Sopenharmony_ci cmd = BR_FAILED_REPLY; 476862306a36Sopenharmony_ci if (put_user(cmd, (uint32_t __user *)ptr)) 476962306a36Sopenharmony_ci return -EFAULT; 477062306a36Sopenharmony_ci ptr += sizeof(uint32_t); 477162306a36Sopenharmony_ci binder_stat_br(proc, thread, cmd); 477262306a36Sopenharmony_ci break; 477362306a36Sopenharmony_ci } 477462306a36Sopenharmony_ci continue; 477562306a36Sopenharmony_ci } 477662306a36Sopenharmony_ci trd->data_size = t->buffer->data_size; 477762306a36Sopenharmony_ci trd->offsets_size = t->buffer->offsets_size; 477862306a36Sopenharmony_ci trd->data.ptr.buffer = (uintptr_t)t->buffer->user_data; 477962306a36Sopenharmony_ci trd->data.ptr.offsets = trd->data.ptr.buffer + 478062306a36Sopenharmony_ci ALIGN(t->buffer->data_size, 478162306a36Sopenharmony_ci sizeof(void *)); 478262306a36Sopenharmony_ci 478362306a36Sopenharmony_ci tr.secctx = t->security_ctx; 478462306a36Sopenharmony_ci if (t->security_ctx) { 478562306a36Sopenharmony_ci cmd = BR_TRANSACTION_SEC_CTX; 478662306a36Sopenharmony_ci trsize = sizeof(tr); 478762306a36Sopenharmony_ci } 478862306a36Sopenharmony_ci if (put_user(cmd, (uint32_t __user *)ptr)) { 478962306a36Sopenharmony_ci if (t_from) 479062306a36Sopenharmony_ci binder_thread_dec_tmpref(t_from); 479162306a36Sopenharmony_ci 479262306a36Sopenharmony_ci binder_cleanup_transaction(t, "put_user failed", 479362306a36Sopenharmony_ci BR_FAILED_REPLY); 479462306a36Sopenharmony_ci 479562306a36Sopenharmony_ci return -EFAULT; 479662306a36Sopenharmony_ci } 479762306a36Sopenharmony_ci ptr += sizeof(uint32_t); 479862306a36Sopenharmony_ci if (copy_to_user(ptr, &tr, trsize)) { 479962306a36Sopenharmony_ci if (t_from) 480062306a36Sopenharmony_ci binder_thread_dec_tmpref(t_from); 480162306a36Sopenharmony_ci 480262306a36Sopenharmony_ci binder_cleanup_transaction(t, "copy_to_user failed", 480362306a36Sopenharmony_ci BR_FAILED_REPLY); 480462306a36Sopenharmony_ci 480562306a36Sopenharmony_ci return -EFAULT; 480662306a36Sopenharmony_ci } 480762306a36Sopenharmony_ci ptr += trsize; 480862306a36Sopenharmony_ci 480962306a36Sopenharmony_ci trace_binder_transaction_received(t); 481062306a36Sopenharmony_ci binder_stat_br(proc, thread, cmd); 481162306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_TRANSACTION, 481262306a36Sopenharmony_ci "%d:%d %s %d %d:%d, cmd %u size %zd-%zd ptr %016llx-%016llx\n", 481362306a36Sopenharmony_ci proc->pid, thread->pid, 481462306a36Sopenharmony_ci (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : 481562306a36Sopenharmony_ci (cmd == BR_TRANSACTION_SEC_CTX) ? 481662306a36Sopenharmony_ci "BR_TRANSACTION_SEC_CTX" : "BR_REPLY", 481762306a36Sopenharmony_ci t->debug_id, t_from ? t_from->proc->pid : 0, 481862306a36Sopenharmony_ci t_from ? t_from->pid : 0, cmd, 481962306a36Sopenharmony_ci t->buffer->data_size, t->buffer->offsets_size, 482062306a36Sopenharmony_ci (u64)trd->data.ptr.buffer, 482162306a36Sopenharmony_ci (u64)trd->data.ptr.offsets); 482262306a36Sopenharmony_ci 482362306a36Sopenharmony_ci if (t_from) 482462306a36Sopenharmony_ci binder_thread_dec_tmpref(t_from); 482562306a36Sopenharmony_ci t->buffer->allow_user_free = 1; 482662306a36Sopenharmony_ci#ifdef CONFIG_ACCESS_TOKENID 482762306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 482862306a36Sopenharmony_ci thread->tokens.sender_tokenid = t->sender_tokenid; 482962306a36Sopenharmony_ci thread->tokens.first_tokenid = t->first_tokenid; 483062306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 483162306a36Sopenharmony_ci#endif /* CONFIG_ACCESS_TOKENID */ 483262306a36Sopenharmony_ci if (cmd != BR_REPLY && !(t->flags & TF_ONE_WAY)) { 483362306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 483462306a36Sopenharmony_ci t->to_parent = thread->transaction_stack; 483562306a36Sopenharmony_ci t->to_thread = thread; 483662306a36Sopenharmony_ci thread->transaction_stack = t; 483762306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 483862306a36Sopenharmony_ci } else { 483962306a36Sopenharmony_ci binder_free_transaction(t); 484062306a36Sopenharmony_ci } 484162306a36Sopenharmony_ci break; 484262306a36Sopenharmony_ci } 484362306a36Sopenharmony_ci 484462306a36Sopenharmony_cidone: 484562306a36Sopenharmony_ci 484662306a36Sopenharmony_ci *consumed = ptr - buffer; 484762306a36Sopenharmony_ci binder_inner_proc_lock(proc); 484862306a36Sopenharmony_ci if (proc->requested_threads == 0 && 484962306a36Sopenharmony_ci list_empty(&thread->proc->waiting_threads) && 485062306a36Sopenharmony_ci proc->requested_threads_started < proc->max_threads && 485162306a36Sopenharmony_ci (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | 485262306a36Sopenharmony_ci BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */ 485362306a36Sopenharmony_ci /*spawn a new thread if we leave this out */) { 485462306a36Sopenharmony_ci proc->requested_threads++; 485562306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 485662306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_THREADS, 485762306a36Sopenharmony_ci "%d:%d BR_SPAWN_LOOPER\n", 485862306a36Sopenharmony_ci proc->pid, thread->pid); 485962306a36Sopenharmony_ci if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer)) 486062306a36Sopenharmony_ci return -EFAULT; 486162306a36Sopenharmony_ci binder_stat_br(proc, thread, BR_SPAWN_LOOPER); 486262306a36Sopenharmony_ci } else 486362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 486462306a36Sopenharmony_ci return 0; 486562306a36Sopenharmony_ci} 486662306a36Sopenharmony_ci 486762306a36Sopenharmony_cistatic void binder_release_work(struct binder_proc *proc, 486862306a36Sopenharmony_ci struct list_head *list) 486962306a36Sopenharmony_ci{ 487062306a36Sopenharmony_ci struct binder_work *w; 487162306a36Sopenharmony_ci enum binder_work_type wtype; 487262306a36Sopenharmony_ci 487362306a36Sopenharmony_ci while (1) { 487462306a36Sopenharmony_ci binder_inner_proc_lock(proc); 487562306a36Sopenharmony_ci w = binder_dequeue_work_head_ilocked(list); 487662306a36Sopenharmony_ci wtype = w ? w->type : 0; 487762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 487862306a36Sopenharmony_ci if (!w) 487962306a36Sopenharmony_ci return; 488062306a36Sopenharmony_ci 488162306a36Sopenharmony_ci switch (wtype) { 488262306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION: { 488362306a36Sopenharmony_ci struct binder_transaction *t; 488462306a36Sopenharmony_ci 488562306a36Sopenharmony_ci t = container_of(w, struct binder_transaction, work); 488662306a36Sopenharmony_ci 488762306a36Sopenharmony_ci binder_cleanup_transaction(t, "process died.", 488862306a36Sopenharmony_ci BR_DEAD_REPLY); 488962306a36Sopenharmony_ci } break; 489062306a36Sopenharmony_ci case BINDER_WORK_RETURN_ERROR: { 489162306a36Sopenharmony_ci struct binder_error *e = container_of( 489262306a36Sopenharmony_ci w, struct binder_error, work); 489362306a36Sopenharmony_ci 489462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, 489562306a36Sopenharmony_ci "undelivered TRANSACTION_ERROR: %u\n", 489662306a36Sopenharmony_ci e->cmd); 489762306a36Sopenharmony_ci } break; 489862306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION_PENDING: 489962306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: 490062306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION_COMPLETE: { 490162306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, 490262306a36Sopenharmony_ci "undelivered TRANSACTION_COMPLETE\n"); 490362306a36Sopenharmony_ci kfree(w); 490462306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); 490562306a36Sopenharmony_ci } break; 490662306a36Sopenharmony_ci case BINDER_WORK_DEAD_BINDER_AND_CLEAR: 490762306a36Sopenharmony_ci case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { 490862306a36Sopenharmony_ci struct binder_ref_death *death; 490962306a36Sopenharmony_ci 491062306a36Sopenharmony_ci death = container_of(w, struct binder_ref_death, work); 491162306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, 491262306a36Sopenharmony_ci "undelivered death notification, %016llx\n", 491362306a36Sopenharmony_ci (u64)death->cookie); 491462306a36Sopenharmony_ci kfree(death); 491562306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_DEATH); 491662306a36Sopenharmony_ci } break; 491762306a36Sopenharmony_ci case BINDER_WORK_NODE: 491862306a36Sopenharmony_ci break; 491962306a36Sopenharmony_ci default: 492062306a36Sopenharmony_ci pr_err("unexpected work type, %d, not freed\n", 492162306a36Sopenharmony_ci wtype); 492262306a36Sopenharmony_ci break; 492362306a36Sopenharmony_ci } 492462306a36Sopenharmony_ci } 492562306a36Sopenharmony_ci 492662306a36Sopenharmony_ci} 492762306a36Sopenharmony_ci 492862306a36Sopenharmony_cistatic struct binder_thread *binder_get_thread_ilocked( 492962306a36Sopenharmony_ci struct binder_proc *proc, struct binder_thread *new_thread) 493062306a36Sopenharmony_ci{ 493162306a36Sopenharmony_ci struct binder_thread *thread = NULL; 493262306a36Sopenharmony_ci struct rb_node *parent = NULL; 493362306a36Sopenharmony_ci struct rb_node **p = &proc->threads.rb_node; 493462306a36Sopenharmony_ci 493562306a36Sopenharmony_ci while (*p) { 493662306a36Sopenharmony_ci parent = *p; 493762306a36Sopenharmony_ci thread = rb_entry(parent, struct binder_thread, rb_node); 493862306a36Sopenharmony_ci 493962306a36Sopenharmony_ci if (current->pid < thread->pid) 494062306a36Sopenharmony_ci p = &(*p)->rb_left; 494162306a36Sopenharmony_ci else if (current->pid > thread->pid) 494262306a36Sopenharmony_ci p = &(*p)->rb_right; 494362306a36Sopenharmony_ci else 494462306a36Sopenharmony_ci return thread; 494562306a36Sopenharmony_ci } 494662306a36Sopenharmony_ci if (!new_thread) 494762306a36Sopenharmony_ci return NULL; 494862306a36Sopenharmony_ci thread = new_thread; 494962306a36Sopenharmony_ci binder_stats_created(BINDER_STAT_THREAD); 495062306a36Sopenharmony_ci thread->proc = proc; 495162306a36Sopenharmony_ci thread->pid = current->pid; 495262306a36Sopenharmony_ci atomic_set(&thread->tmp_ref, 0); 495362306a36Sopenharmony_ci init_waitqueue_head(&thread->wait); 495462306a36Sopenharmony_ci INIT_LIST_HEAD(&thread->todo); 495562306a36Sopenharmony_ci rb_link_node(&thread->rb_node, parent, p); 495662306a36Sopenharmony_ci rb_insert_color(&thread->rb_node, &proc->threads); 495762306a36Sopenharmony_ci thread->looper_need_return = true; 495862306a36Sopenharmony_ci thread->return_error.work.type = BINDER_WORK_RETURN_ERROR; 495962306a36Sopenharmony_ci thread->return_error.cmd = BR_OK; 496062306a36Sopenharmony_ci thread->reply_error.work.type = BINDER_WORK_RETURN_ERROR; 496162306a36Sopenharmony_ci thread->reply_error.cmd = BR_OK; 496262306a36Sopenharmony_ci thread->ee.command = BR_OK; 496362306a36Sopenharmony_ci INIT_LIST_HEAD(&new_thread->waiting_thread_node); 496462306a36Sopenharmony_ci return thread; 496562306a36Sopenharmony_ci} 496662306a36Sopenharmony_ci 496762306a36Sopenharmony_cistatic struct binder_thread *binder_get_thread(struct binder_proc *proc) 496862306a36Sopenharmony_ci{ 496962306a36Sopenharmony_ci struct binder_thread *thread; 497062306a36Sopenharmony_ci struct binder_thread *new_thread; 497162306a36Sopenharmony_ci 497262306a36Sopenharmony_ci binder_inner_proc_lock(proc); 497362306a36Sopenharmony_ci thread = binder_get_thread_ilocked(proc, NULL); 497462306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 497562306a36Sopenharmony_ci if (!thread) { 497662306a36Sopenharmony_ci new_thread = kzalloc(sizeof(*thread), GFP_KERNEL); 497762306a36Sopenharmony_ci if (new_thread == NULL) 497862306a36Sopenharmony_ci return NULL; 497962306a36Sopenharmony_ci binder_inner_proc_lock(proc); 498062306a36Sopenharmony_ci thread = binder_get_thread_ilocked(proc, new_thread); 498162306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 498262306a36Sopenharmony_ci if (thread != new_thread) 498362306a36Sopenharmony_ci kfree(new_thread); 498462306a36Sopenharmony_ci } 498562306a36Sopenharmony_ci return thread; 498662306a36Sopenharmony_ci} 498762306a36Sopenharmony_ci 498862306a36Sopenharmony_cistatic void binder_free_proc(struct binder_proc *proc) 498962306a36Sopenharmony_ci{ 499062306a36Sopenharmony_ci struct binder_device *device; 499162306a36Sopenharmony_ci 499262306a36Sopenharmony_ci BUG_ON(!list_empty(&proc->todo)); 499362306a36Sopenharmony_ci BUG_ON(!list_empty(&proc->delivered_death)); 499462306a36Sopenharmony_ci if (proc->outstanding_txns) 499562306a36Sopenharmony_ci pr_warn("%s: Unexpected outstanding_txns %d\n", 499662306a36Sopenharmony_ci __func__, proc->outstanding_txns); 499762306a36Sopenharmony_ci device = container_of(proc->context, struct binder_device, context); 499862306a36Sopenharmony_ci if (refcount_dec_and_test(&device->ref)) { 499962306a36Sopenharmony_ci kfree(proc->context->name); 500062306a36Sopenharmony_ci kfree(device); 500162306a36Sopenharmony_ci } 500262306a36Sopenharmony_ci binder_alloc_deferred_release(&proc->alloc); 500362306a36Sopenharmony_ci put_task_struct(proc->tsk); 500462306a36Sopenharmony_ci put_cred(proc->cred); 500562306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_PROC); 500662306a36Sopenharmony_ci kfree(proc); 500762306a36Sopenharmony_ci} 500862306a36Sopenharmony_ci 500962306a36Sopenharmony_cistatic void binder_free_thread(struct binder_thread *thread) 501062306a36Sopenharmony_ci{ 501162306a36Sopenharmony_ci BUG_ON(!list_empty(&thread->todo)); 501262306a36Sopenharmony_ci binder_stats_deleted(BINDER_STAT_THREAD); 501362306a36Sopenharmony_ci binder_proc_dec_tmpref(thread->proc); 501462306a36Sopenharmony_ci kfree(thread); 501562306a36Sopenharmony_ci} 501662306a36Sopenharmony_ci 501762306a36Sopenharmony_cistatic int binder_thread_release(struct binder_proc *proc, 501862306a36Sopenharmony_ci struct binder_thread *thread) 501962306a36Sopenharmony_ci{ 502062306a36Sopenharmony_ci struct binder_transaction *t; 502162306a36Sopenharmony_ci struct binder_transaction *send_reply = NULL; 502262306a36Sopenharmony_ci int active_transactions = 0; 502362306a36Sopenharmony_ci struct binder_transaction *last_t = NULL; 502462306a36Sopenharmony_ci 502562306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 502662306a36Sopenharmony_ci /* 502762306a36Sopenharmony_ci * take a ref on the proc so it survives 502862306a36Sopenharmony_ci * after we remove this thread from proc->threads. 502962306a36Sopenharmony_ci * The corresponding dec is when we actually 503062306a36Sopenharmony_ci * free the thread in binder_free_thread() 503162306a36Sopenharmony_ci */ 503262306a36Sopenharmony_ci proc->tmp_ref++; 503362306a36Sopenharmony_ci /* 503462306a36Sopenharmony_ci * take a ref on this thread to ensure it 503562306a36Sopenharmony_ci * survives while we are releasing it 503662306a36Sopenharmony_ci */ 503762306a36Sopenharmony_ci atomic_inc(&thread->tmp_ref); 503862306a36Sopenharmony_ci rb_erase(&thread->rb_node, &proc->threads); 503962306a36Sopenharmony_ci t = thread->transaction_stack; 504062306a36Sopenharmony_ci if (t) { 504162306a36Sopenharmony_ci spin_lock(&t->lock); 504262306a36Sopenharmony_ci if (t->to_thread == thread) 504362306a36Sopenharmony_ci send_reply = t; 504462306a36Sopenharmony_ci } else { 504562306a36Sopenharmony_ci __acquire(&t->lock); 504662306a36Sopenharmony_ci } 504762306a36Sopenharmony_ci thread->is_dead = true; 504862306a36Sopenharmony_ci 504962306a36Sopenharmony_ci while (t) { 505062306a36Sopenharmony_ci last_t = t; 505162306a36Sopenharmony_ci active_transactions++; 505262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, 505362306a36Sopenharmony_ci "release %d:%d transaction %d %s, still active\n", 505462306a36Sopenharmony_ci proc->pid, thread->pid, 505562306a36Sopenharmony_ci t->debug_id, 505662306a36Sopenharmony_ci (t->to_thread == thread) ? "in" : "out"); 505762306a36Sopenharmony_ci 505862306a36Sopenharmony_ci if (t->to_thread == thread) { 505962306a36Sopenharmony_ci thread->proc->outstanding_txns--; 506062306a36Sopenharmony_ci t->to_proc = NULL; 506162306a36Sopenharmony_ci t->to_thread = NULL; 506262306a36Sopenharmony_ci if (t->buffer) { 506362306a36Sopenharmony_ci t->buffer->transaction = NULL; 506462306a36Sopenharmony_ci t->buffer = NULL; 506562306a36Sopenharmony_ci } 506662306a36Sopenharmony_ci t = t->to_parent; 506762306a36Sopenharmony_ci } else if (t->from == thread) { 506862306a36Sopenharmony_ci t->from = NULL; 506962306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 507062306a36Sopenharmony_ci t->from_pid = -1; 507162306a36Sopenharmony_ci t->from_tid = -1; 507262306a36Sopenharmony_ci#endif 507362306a36Sopenharmony_ci t = t->from_parent; 507462306a36Sopenharmony_ci } else 507562306a36Sopenharmony_ci BUG(); 507662306a36Sopenharmony_ci spin_unlock(&last_t->lock); 507762306a36Sopenharmony_ci if (t) 507862306a36Sopenharmony_ci spin_lock(&t->lock); 507962306a36Sopenharmony_ci else 508062306a36Sopenharmony_ci __acquire(&t->lock); 508162306a36Sopenharmony_ci } 508262306a36Sopenharmony_ci /* annotation for sparse, lock not acquired in last iteration above */ 508362306a36Sopenharmony_ci __release(&t->lock); 508462306a36Sopenharmony_ci 508562306a36Sopenharmony_ci /* 508662306a36Sopenharmony_ci * If this thread used poll, make sure we remove the waitqueue from any 508762306a36Sopenharmony_ci * poll data structures holding it. 508862306a36Sopenharmony_ci */ 508962306a36Sopenharmony_ci if (thread->looper & BINDER_LOOPER_STATE_POLL) 509062306a36Sopenharmony_ci wake_up_pollfree(&thread->wait); 509162306a36Sopenharmony_ci 509262306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 509362306a36Sopenharmony_ci 509462306a36Sopenharmony_ci /* 509562306a36Sopenharmony_ci * This is needed to avoid races between wake_up_pollfree() above and 509662306a36Sopenharmony_ci * someone else removing the last entry from the queue for other reasons 509762306a36Sopenharmony_ci * (e.g. ep_remove_wait_queue() being called due to an epoll file 509862306a36Sopenharmony_ci * descriptor being closed). Such other users hold an RCU read lock, so 509962306a36Sopenharmony_ci * we can be sure they're done after we call synchronize_rcu(). 510062306a36Sopenharmony_ci */ 510162306a36Sopenharmony_ci if (thread->looper & BINDER_LOOPER_STATE_POLL) 510262306a36Sopenharmony_ci synchronize_rcu(); 510362306a36Sopenharmony_ci 510462306a36Sopenharmony_ci if (send_reply) 510562306a36Sopenharmony_ci binder_send_failed_reply(send_reply, BR_DEAD_REPLY); 510662306a36Sopenharmony_ci binder_release_work(proc, &thread->todo); 510762306a36Sopenharmony_ci binder_thread_dec_tmpref(thread); 510862306a36Sopenharmony_ci return active_transactions; 510962306a36Sopenharmony_ci} 511062306a36Sopenharmony_ci 511162306a36Sopenharmony_cistatic __poll_t binder_poll(struct file *filp, 511262306a36Sopenharmony_ci struct poll_table_struct *wait) 511362306a36Sopenharmony_ci{ 511462306a36Sopenharmony_ci struct binder_proc *proc = filp->private_data; 511562306a36Sopenharmony_ci struct binder_thread *thread = NULL; 511662306a36Sopenharmony_ci bool wait_for_proc_work; 511762306a36Sopenharmony_ci 511862306a36Sopenharmony_ci thread = binder_get_thread(proc); 511962306a36Sopenharmony_ci if (!thread) 512062306a36Sopenharmony_ci return EPOLLERR; 512162306a36Sopenharmony_ci 512262306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 512362306a36Sopenharmony_ci thread->looper |= BINDER_LOOPER_STATE_POLL; 512462306a36Sopenharmony_ci wait_for_proc_work = binder_available_for_proc_work_ilocked(thread); 512562306a36Sopenharmony_ci 512662306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 512762306a36Sopenharmony_ci 512862306a36Sopenharmony_ci poll_wait(filp, &thread->wait, wait); 512962306a36Sopenharmony_ci 513062306a36Sopenharmony_ci if (binder_has_work(thread, wait_for_proc_work)) 513162306a36Sopenharmony_ci return EPOLLIN; 513262306a36Sopenharmony_ci 513362306a36Sopenharmony_ci return 0; 513462306a36Sopenharmony_ci} 513562306a36Sopenharmony_ci 513662306a36Sopenharmony_cistatic int binder_ioctl_write_read(struct file *filp, 513762306a36Sopenharmony_ci unsigned int cmd, unsigned long arg, 513862306a36Sopenharmony_ci struct binder_thread *thread) 513962306a36Sopenharmony_ci{ 514062306a36Sopenharmony_ci int ret = 0; 514162306a36Sopenharmony_ci struct binder_proc *proc = filp->private_data; 514262306a36Sopenharmony_ci unsigned int size = _IOC_SIZE(cmd); 514362306a36Sopenharmony_ci void __user *ubuf = (void __user *)arg; 514462306a36Sopenharmony_ci struct binder_write_read bwr; 514562306a36Sopenharmony_ci 514662306a36Sopenharmony_ci if (size != sizeof(struct binder_write_read)) { 514762306a36Sopenharmony_ci ret = -EINVAL; 514862306a36Sopenharmony_ci goto out; 514962306a36Sopenharmony_ci } 515062306a36Sopenharmony_ci 515162306a36Sopenharmony_ci if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { 515262306a36Sopenharmony_ci ret = -EFAULT; 515362306a36Sopenharmony_ci goto out; 515462306a36Sopenharmony_ci } 515562306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_READ_WRITE, 515662306a36Sopenharmony_ci "%d:%d write %lld at %016llx, read %lld at %016llx\n", 515762306a36Sopenharmony_ci proc->pid, thread->pid, 515862306a36Sopenharmony_ci (u64)bwr.write_size, (u64)bwr.write_buffer, 515962306a36Sopenharmony_ci (u64)bwr.read_size, (u64)bwr.read_buffer); 516062306a36Sopenharmony_ci 516162306a36Sopenharmony_ci if (bwr.write_size > 0) { 516262306a36Sopenharmony_ci ret = binder_thread_write(proc, thread, 516362306a36Sopenharmony_ci bwr.write_buffer, 516462306a36Sopenharmony_ci bwr.write_size, 516562306a36Sopenharmony_ci &bwr.write_consumed); 516662306a36Sopenharmony_ci trace_binder_write_done(ret); 516762306a36Sopenharmony_ci if (ret < 0) { 516862306a36Sopenharmony_ci bwr.read_consumed = 0; 516962306a36Sopenharmony_ci if (copy_to_user(ubuf, &bwr, sizeof(bwr))) 517062306a36Sopenharmony_ci ret = -EFAULT; 517162306a36Sopenharmony_ci goto out; 517262306a36Sopenharmony_ci } 517362306a36Sopenharmony_ci } 517462306a36Sopenharmony_ci if (bwr.read_size > 0) { 517562306a36Sopenharmony_ci ret = binder_thread_read(proc, thread, bwr.read_buffer, 517662306a36Sopenharmony_ci bwr.read_size, 517762306a36Sopenharmony_ci &bwr.read_consumed, 517862306a36Sopenharmony_ci filp->f_flags & O_NONBLOCK); 517962306a36Sopenharmony_ci trace_binder_read_done(ret); 518062306a36Sopenharmony_ci binder_inner_proc_lock(proc); 518162306a36Sopenharmony_ci if (!binder_worklist_empty_ilocked(&proc->todo)) 518262306a36Sopenharmony_ci binder_wakeup_proc_ilocked(proc); 518362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 518462306a36Sopenharmony_ci if (ret < 0) { 518562306a36Sopenharmony_ci if (copy_to_user(ubuf, &bwr, sizeof(bwr))) 518662306a36Sopenharmony_ci ret = -EFAULT; 518762306a36Sopenharmony_ci goto out; 518862306a36Sopenharmony_ci } 518962306a36Sopenharmony_ci } 519062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_READ_WRITE, 519162306a36Sopenharmony_ci "%d:%d wrote %lld of %lld, read return %lld of %lld\n", 519262306a36Sopenharmony_ci proc->pid, thread->pid, 519362306a36Sopenharmony_ci (u64)bwr.write_consumed, (u64)bwr.write_size, 519462306a36Sopenharmony_ci (u64)bwr.read_consumed, (u64)bwr.read_size); 519562306a36Sopenharmony_ci if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { 519662306a36Sopenharmony_ci ret = -EFAULT; 519762306a36Sopenharmony_ci goto out; 519862306a36Sopenharmony_ci } 519962306a36Sopenharmony_ciout: 520062306a36Sopenharmony_ci return ret; 520162306a36Sopenharmony_ci} 520262306a36Sopenharmony_ci 520362306a36Sopenharmony_cistatic int binder_ioctl_set_ctx_mgr(struct file *filp, 520462306a36Sopenharmony_ci struct flat_binder_object *fbo) 520562306a36Sopenharmony_ci{ 520662306a36Sopenharmony_ci int ret = 0; 520762306a36Sopenharmony_ci struct binder_proc *proc = filp->private_data; 520862306a36Sopenharmony_ci struct binder_context *context = proc->context; 520962306a36Sopenharmony_ci struct binder_node *new_node; 521062306a36Sopenharmony_ci kuid_t curr_euid = current_euid(); 521162306a36Sopenharmony_ci 521262306a36Sopenharmony_ci mutex_lock(&context->context_mgr_node_lock); 521362306a36Sopenharmony_ci if (context->binder_context_mgr_node) { 521462306a36Sopenharmony_ci pr_err("BINDER_SET_CONTEXT_MGR already set\n"); 521562306a36Sopenharmony_ci ret = -EBUSY; 521662306a36Sopenharmony_ci goto out; 521762306a36Sopenharmony_ci } 521862306a36Sopenharmony_ci ret = security_binder_set_context_mgr(proc->cred); 521962306a36Sopenharmony_ci if (ret < 0) 522062306a36Sopenharmony_ci goto out; 522162306a36Sopenharmony_ci if (uid_valid(context->binder_context_mgr_uid)) { 522262306a36Sopenharmony_ci if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) { 522362306a36Sopenharmony_ci pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", 522462306a36Sopenharmony_ci from_kuid(&init_user_ns, curr_euid), 522562306a36Sopenharmony_ci from_kuid(&init_user_ns, 522662306a36Sopenharmony_ci context->binder_context_mgr_uid)); 522762306a36Sopenharmony_ci ret = -EPERM; 522862306a36Sopenharmony_ci goto out; 522962306a36Sopenharmony_ci } 523062306a36Sopenharmony_ci } else { 523162306a36Sopenharmony_ci context->binder_context_mgr_uid = curr_euid; 523262306a36Sopenharmony_ci } 523362306a36Sopenharmony_ci new_node = binder_new_node(proc, fbo); 523462306a36Sopenharmony_ci if (!new_node) { 523562306a36Sopenharmony_ci ret = -ENOMEM; 523662306a36Sopenharmony_ci goto out; 523762306a36Sopenharmony_ci } 523862306a36Sopenharmony_ci binder_node_lock(new_node); 523962306a36Sopenharmony_ci new_node->local_weak_refs++; 524062306a36Sopenharmony_ci new_node->local_strong_refs++; 524162306a36Sopenharmony_ci new_node->has_strong_ref = 1; 524262306a36Sopenharmony_ci new_node->has_weak_ref = 1; 524362306a36Sopenharmony_ci context->binder_context_mgr_node = new_node; 524462306a36Sopenharmony_ci binder_node_unlock(new_node); 524562306a36Sopenharmony_ci binder_put_node(new_node); 524662306a36Sopenharmony_ciout: 524762306a36Sopenharmony_ci mutex_unlock(&context->context_mgr_node_lock); 524862306a36Sopenharmony_ci return ret; 524962306a36Sopenharmony_ci} 525062306a36Sopenharmony_ci 525162306a36Sopenharmony_cistatic int binder_ioctl_get_node_info_for_ref(struct binder_proc *proc, 525262306a36Sopenharmony_ci struct binder_node_info_for_ref *info) 525362306a36Sopenharmony_ci{ 525462306a36Sopenharmony_ci struct binder_node *node; 525562306a36Sopenharmony_ci struct binder_context *context = proc->context; 525662306a36Sopenharmony_ci __u32 handle = info->handle; 525762306a36Sopenharmony_ci 525862306a36Sopenharmony_ci if (info->strong_count || info->weak_count || info->reserved1 || 525962306a36Sopenharmony_ci info->reserved2 || info->reserved3) { 526062306a36Sopenharmony_ci binder_user_error("%d BINDER_GET_NODE_INFO_FOR_REF: only handle may be non-zero.", 526162306a36Sopenharmony_ci proc->pid); 526262306a36Sopenharmony_ci return -EINVAL; 526362306a36Sopenharmony_ci } 526462306a36Sopenharmony_ci 526562306a36Sopenharmony_ci /* This ioctl may only be used by the context manager */ 526662306a36Sopenharmony_ci mutex_lock(&context->context_mgr_node_lock); 526762306a36Sopenharmony_ci if (!context->binder_context_mgr_node || 526862306a36Sopenharmony_ci context->binder_context_mgr_node->proc != proc) { 526962306a36Sopenharmony_ci mutex_unlock(&context->context_mgr_node_lock); 527062306a36Sopenharmony_ci return -EPERM; 527162306a36Sopenharmony_ci } 527262306a36Sopenharmony_ci mutex_unlock(&context->context_mgr_node_lock); 527362306a36Sopenharmony_ci 527462306a36Sopenharmony_ci node = binder_get_node_from_ref(proc, handle, true, NULL); 527562306a36Sopenharmony_ci if (!node) 527662306a36Sopenharmony_ci return -EINVAL; 527762306a36Sopenharmony_ci 527862306a36Sopenharmony_ci info->strong_count = node->local_strong_refs + 527962306a36Sopenharmony_ci node->internal_strong_refs; 528062306a36Sopenharmony_ci info->weak_count = node->local_weak_refs; 528162306a36Sopenharmony_ci 528262306a36Sopenharmony_ci binder_put_node(node); 528362306a36Sopenharmony_ci 528462306a36Sopenharmony_ci return 0; 528562306a36Sopenharmony_ci} 528662306a36Sopenharmony_ci 528762306a36Sopenharmony_cistatic int binder_ioctl_get_node_debug_info(struct binder_proc *proc, 528862306a36Sopenharmony_ci struct binder_node_debug_info *info) 528962306a36Sopenharmony_ci{ 529062306a36Sopenharmony_ci struct rb_node *n; 529162306a36Sopenharmony_ci binder_uintptr_t ptr = info->ptr; 529262306a36Sopenharmony_ci 529362306a36Sopenharmony_ci memset(info, 0, sizeof(*info)); 529462306a36Sopenharmony_ci 529562306a36Sopenharmony_ci binder_inner_proc_lock(proc); 529662306a36Sopenharmony_ci for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) { 529762306a36Sopenharmony_ci struct binder_node *node = rb_entry(n, struct binder_node, 529862306a36Sopenharmony_ci rb_node); 529962306a36Sopenharmony_ci if (node->ptr > ptr) { 530062306a36Sopenharmony_ci info->ptr = node->ptr; 530162306a36Sopenharmony_ci info->cookie = node->cookie; 530262306a36Sopenharmony_ci info->has_strong_ref = node->has_strong_ref; 530362306a36Sopenharmony_ci info->has_weak_ref = node->has_weak_ref; 530462306a36Sopenharmony_ci break; 530562306a36Sopenharmony_ci } 530662306a36Sopenharmony_ci } 530762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 530862306a36Sopenharmony_ci 530962306a36Sopenharmony_ci return 0; 531062306a36Sopenharmony_ci} 531162306a36Sopenharmony_ci 531262306a36Sopenharmony_cistatic bool binder_txns_pending_ilocked(struct binder_proc *proc) 531362306a36Sopenharmony_ci{ 531462306a36Sopenharmony_ci struct rb_node *n; 531562306a36Sopenharmony_ci struct binder_thread *thread; 531662306a36Sopenharmony_ci 531762306a36Sopenharmony_ci if (proc->outstanding_txns > 0) 531862306a36Sopenharmony_ci return true; 531962306a36Sopenharmony_ci 532062306a36Sopenharmony_ci for (n = rb_first(&proc->threads); n; n = rb_next(n)) { 532162306a36Sopenharmony_ci thread = rb_entry(n, struct binder_thread, rb_node); 532262306a36Sopenharmony_ci if (thread->transaction_stack) 532362306a36Sopenharmony_ci return true; 532462306a36Sopenharmony_ci } 532562306a36Sopenharmony_ci return false; 532662306a36Sopenharmony_ci} 532762306a36Sopenharmony_ci 532862306a36Sopenharmony_cistatic int binder_ioctl_freeze(struct binder_freeze_info *info, 532962306a36Sopenharmony_ci struct binder_proc *target_proc) 533062306a36Sopenharmony_ci{ 533162306a36Sopenharmony_ci int ret = 0; 533262306a36Sopenharmony_ci 533362306a36Sopenharmony_ci if (!info->enable) { 533462306a36Sopenharmony_ci binder_inner_proc_lock(target_proc); 533562306a36Sopenharmony_ci target_proc->sync_recv = false; 533662306a36Sopenharmony_ci target_proc->async_recv = false; 533762306a36Sopenharmony_ci target_proc->is_frozen = false; 533862306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 533962306a36Sopenharmony_ci return 0; 534062306a36Sopenharmony_ci } 534162306a36Sopenharmony_ci 534262306a36Sopenharmony_ci /* 534362306a36Sopenharmony_ci * Freezing the target. Prevent new transactions by 534462306a36Sopenharmony_ci * setting frozen state. If timeout specified, wait 534562306a36Sopenharmony_ci * for transactions to drain. 534662306a36Sopenharmony_ci */ 534762306a36Sopenharmony_ci binder_inner_proc_lock(target_proc); 534862306a36Sopenharmony_ci target_proc->sync_recv = false; 534962306a36Sopenharmony_ci target_proc->async_recv = false; 535062306a36Sopenharmony_ci target_proc->is_frozen = true; 535162306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 535262306a36Sopenharmony_ci 535362306a36Sopenharmony_ci if (info->timeout_ms > 0) 535462306a36Sopenharmony_ci ret = wait_event_interruptible_timeout( 535562306a36Sopenharmony_ci target_proc->freeze_wait, 535662306a36Sopenharmony_ci (!target_proc->outstanding_txns), 535762306a36Sopenharmony_ci msecs_to_jiffies(info->timeout_ms)); 535862306a36Sopenharmony_ci 535962306a36Sopenharmony_ci /* Check pending transactions that wait for reply */ 536062306a36Sopenharmony_ci if (ret >= 0) { 536162306a36Sopenharmony_ci binder_inner_proc_lock(target_proc); 536262306a36Sopenharmony_ci if (binder_txns_pending_ilocked(target_proc)) 536362306a36Sopenharmony_ci ret = -EAGAIN; 536462306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 536562306a36Sopenharmony_ci } 536662306a36Sopenharmony_ci 536762306a36Sopenharmony_ci if (ret < 0) { 536862306a36Sopenharmony_ci binder_inner_proc_lock(target_proc); 536962306a36Sopenharmony_ci target_proc->is_frozen = false; 537062306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 537162306a36Sopenharmony_ci } 537262306a36Sopenharmony_ci 537362306a36Sopenharmony_ci return ret; 537462306a36Sopenharmony_ci} 537562306a36Sopenharmony_ci 537662306a36Sopenharmony_cistatic int binder_ioctl_get_freezer_info( 537762306a36Sopenharmony_ci struct binder_frozen_status_info *info) 537862306a36Sopenharmony_ci{ 537962306a36Sopenharmony_ci struct binder_proc *target_proc; 538062306a36Sopenharmony_ci bool found = false; 538162306a36Sopenharmony_ci __u32 txns_pending; 538262306a36Sopenharmony_ci 538362306a36Sopenharmony_ci info->sync_recv = 0; 538462306a36Sopenharmony_ci info->async_recv = 0; 538562306a36Sopenharmony_ci 538662306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 538762306a36Sopenharmony_ci hlist_for_each_entry(target_proc, &binder_procs, proc_node) { 538862306a36Sopenharmony_ci if (target_proc->pid == info->pid) { 538962306a36Sopenharmony_ci found = true; 539062306a36Sopenharmony_ci binder_inner_proc_lock(target_proc); 539162306a36Sopenharmony_ci txns_pending = binder_txns_pending_ilocked(target_proc); 539262306a36Sopenharmony_ci info->sync_recv |= target_proc->sync_recv | 539362306a36Sopenharmony_ci (txns_pending << 1); 539462306a36Sopenharmony_ci info->async_recv |= target_proc->async_recv; 539562306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 539662306a36Sopenharmony_ci } 539762306a36Sopenharmony_ci } 539862306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 539962306a36Sopenharmony_ci 540062306a36Sopenharmony_ci if (!found) 540162306a36Sopenharmony_ci return -EINVAL; 540262306a36Sopenharmony_ci 540362306a36Sopenharmony_ci return 0; 540462306a36Sopenharmony_ci} 540562306a36Sopenharmony_ci 540662306a36Sopenharmony_cistatic int binder_ioctl_get_extended_error(struct binder_thread *thread, 540762306a36Sopenharmony_ci void __user *ubuf) 540862306a36Sopenharmony_ci{ 540962306a36Sopenharmony_ci struct binder_extended_error ee; 541062306a36Sopenharmony_ci 541162306a36Sopenharmony_ci binder_inner_proc_lock(thread->proc); 541262306a36Sopenharmony_ci ee = thread->ee; 541362306a36Sopenharmony_ci binder_set_extended_error(&thread->ee, 0, BR_OK, 0); 541462306a36Sopenharmony_ci binder_inner_proc_unlock(thread->proc); 541562306a36Sopenharmony_ci 541662306a36Sopenharmony_ci if (copy_to_user(ubuf, &ee, sizeof(ee))) 541762306a36Sopenharmony_ci return -EFAULT; 541862306a36Sopenharmony_ci 541962306a36Sopenharmony_ci return 0; 542062306a36Sopenharmony_ci} 542162306a36Sopenharmony_ci 542262306a36Sopenharmony_cistatic long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 542362306a36Sopenharmony_ci{ 542462306a36Sopenharmony_ci int ret; 542562306a36Sopenharmony_ci struct binder_proc *proc = filp->private_data; 542662306a36Sopenharmony_ci struct binder_thread *thread; 542762306a36Sopenharmony_ci unsigned int size = _IOC_SIZE(cmd); 542862306a36Sopenharmony_ci void __user *ubuf = (void __user *)arg; 542962306a36Sopenharmony_ci 543062306a36Sopenharmony_ci /*pr_info("binder_ioctl: %d:%d %x %lx\n", 543162306a36Sopenharmony_ci proc->pid, current->pid, cmd, arg);*/ 543262306a36Sopenharmony_ci 543362306a36Sopenharmony_ci binder_selftest_alloc(&proc->alloc); 543462306a36Sopenharmony_ci 543562306a36Sopenharmony_ci trace_binder_ioctl(cmd, arg); 543662306a36Sopenharmony_ci 543762306a36Sopenharmony_ci ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); 543862306a36Sopenharmony_ci if (ret) 543962306a36Sopenharmony_ci goto err_unlocked; 544062306a36Sopenharmony_ci 544162306a36Sopenharmony_ci thread = binder_get_thread(proc); 544262306a36Sopenharmony_ci if (thread == NULL) { 544362306a36Sopenharmony_ci ret = -ENOMEM; 544462306a36Sopenharmony_ci goto err; 544562306a36Sopenharmony_ci } 544662306a36Sopenharmony_ci 544762306a36Sopenharmony_ci switch (cmd) { 544862306a36Sopenharmony_ci case BINDER_WRITE_READ: 544962306a36Sopenharmony_ci ret = binder_ioctl_write_read(filp, cmd, arg, thread); 545062306a36Sopenharmony_ci if (ret) 545162306a36Sopenharmony_ci goto err; 545262306a36Sopenharmony_ci break; 545362306a36Sopenharmony_ci case BINDER_SET_MAX_THREADS: { 545462306a36Sopenharmony_ci int max_threads; 545562306a36Sopenharmony_ci 545662306a36Sopenharmony_ci if (copy_from_user(&max_threads, ubuf, 545762306a36Sopenharmony_ci sizeof(max_threads))) { 545862306a36Sopenharmony_ci ret = -EINVAL; 545962306a36Sopenharmony_ci goto err; 546062306a36Sopenharmony_ci } 546162306a36Sopenharmony_ci binder_inner_proc_lock(proc); 546262306a36Sopenharmony_ci proc->max_threads = max_threads; 546362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 546462306a36Sopenharmony_ci break; 546562306a36Sopenharmony_ci } 546662306a36Sopenharmony_ci case BINDER_SET_CONTEXT_MGR_EXT: { 546762306a36Sopenharmony_ci struct flat_binder_object fbo; 546862306a36Sopenharmony_ci 546962306a36Sopenharmony_ci if (copy_from_user(&fbo, ubuf, sizeof(fbo))) { 547062306a36Sopenharmony_ci ret = -EINVAL; 547162306a36Sopenharmony_ci goto err; 547262306a36Sopenharmony_ci } 547362306a36Sopenharmony_ci ret = binder_ioctl_set_ctx_mgr(filp, &fbo); 547462306a36Sopenharmony_ci if (ret) 547562306a36Sopenharmony_ci goto err; 547662306a36Sopenharmony_ci break; 547762306a36Sopenharmony_ci } 547862306a36Sopenharmony_ci case BINDER_SET_CONTEXT_MGR: 547962306a36Sopenharmony_ci ret = binder_ioctl_set_ctx_mgr(filp, NULL); 548062306a36Sopenharmony_ci if (ret) 548162306a36Sopenharmony_ci goto err; 548262306a36Sopenharmony_ci break; 548362306a36Sopenharmony_ci case BINDER_THREAD_EXIT: 548462306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n", 548562306a36Sopenharmony_ci proc->pid, thread->pid); 548662306a36Sopenharmony_ci binder_thread_release(proc, thread); 548762306a36Sopenharmony_ci thread = NULL; 548862306a36Sopenharmony_ci break; 548962306a36Sopenharmony_ci case BINDER_VERSION: { 549062306a36Sopenharmony_ci struct binder_version __user *ver = ubuf; 549162306a36Sopenharmony_ci 549262306a36Sopenharmony_ci if (size != sizeof(struct binder_version)) { 549362306a36Sopenharmony_ci ret = -EINVAL; 549462306a36Sopenharmony_ci goto err; 549562306a36Sopenharmony_ci } 549662306a36Sopenharmony_ci if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, 549762306a36Sopenharmony_ci &ver->protocol_version)) { 549862306a36Sopenharmony_ci ret = -EINVAL; 549962306a36Sopenharmony_ci goto err; 550062306a36Sopenharmony_ci } 550162306a36Sopenharmony_ci break; 550262306a36Sopenharmony_ci } 550362306a36Sopenharmony_ci case BINDER_GET_NODE_INFO_FOR_REF: { 550462306a36Sopenharmony_ci struct binder_node_info_for_ref info; 550562306a36Sopenharmony_ci 550662306a36Sopenharmony_ci if (copy_from_user(&info, ubuf, sizeof(info))) { 550762306a36Sopenharmony_ci ret = -EFAULT; 550862306a36Sopenharmony_ci goto err; 550962306a36Sopenharmony_ci } 551062306a36Sopenharmony_ci 551162306a36Sopenharmony_ci ret = binder_ioctl_get_node_info_for_ref(proc, &info); 551262306a36Sopenharmony_ci if (ret < 0) 551362306a36Sopenharmony_ci goto err; 551462306a36Sopenharmony_ci 551562306a36Sopenharmony_ci if (copy_to_user(ubuf, &info, sizeof(info))) { 551662306a36Sopenharmony_ci ret = -EFAULT; 551762306a36Sopenharmony_ci goto err; 551862306a36Sopenharmony_ci } 551962306a36Sopenharmony_ci 552062306a36Sopenharmony_ci break; 552162306a36Sopenharmony_ci } 552262306a36Sopenharmony_ci case BINDER_GET_NODE_DEBUG_INFO: { 552362306a36Sopenharmony_ci struct binder_node_debug_info info; 552462306a36Sopenharmony_ci 552562306a36Sopenharmony_ci if (copy_from_user(&info, ubuf, sizeof(info))) { 552662306a36Sopenharmony_ci ret = -EFAULT; 552762306a36Sopenharmony_ci goto err; 552862306a36Sopenharmony_ci } 552962306a36Sopenharmony_ci 553062306a36Sopenharmony_ci ret = binder_ioctl_get_node_debug_info(proc, &info); 553162306a36Sopenharmony_ci if (ret < 0) 553262306a36Sopenharmony_ci goto err; 553362306a36Sopenharmony_ci 553462306a36Sopenharmony_ci if (copy_to_user(ubuf, &info, sizeof(info))) { 553562306a36Sopenharmony_ci ret = -EFAULT; 553662306a36Sopenharmony_ci goto err; 553762306a36Sopenharmony_ci } 553862306a36Sopenharmony_ci break; 553962306a36Sopenharmony_ci } 554062306a36Sopenharmony_ci case BINDER_FREEZE: { 554162306a36Sopenharmony_ci struct binder_freeze_info info; 554262306a36Sopenharmony_ci struct binder_proc **target_procs = NULL, *target_proc; 554362306a36Sopenharmony_ci int target_procs_count = 0, i = 0; 554462306a36Sopenharmony_ci 554562306a36Sopenharmony_ci ret = 0; 554662306a36Sopenharmony_ci 554762306a36Sopenharmony_ci if (copy_from_user(&info, ubuf, sizeof(info))) { 554862306a36Sopenharmony_ci ret = -EFAULT; 554962306a36Sopenharmony_ci goto err; 555062306a36Sopenharmony_ci } 555162306a36Sopenharmony_ci 555262306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 555362306a36Sopenharmony_ci hlist_for_each_entry(target_proc, &binder_procs, proc_node) { 555462306a36Sopenharmony_ci if (target_proc->pid == info.pid) 555562306a36Sopenharmony_ci target_procs_count++; 555662306a36Sopenharmony_ci } 555762306a36Sopenharmony_ci 555862306a36Sopenharmony_ci if (target_procs_count == 0) { 555962306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 556062306a36Sopenharmony_ci ret = -EINVAL; 556162306a36Sopenharmony_ci goto err; 556262306a36Sopenharmony_ci } 556362306a36Sopenharmony_ci 556462306a36Sopenharmony_ci target_procs = kcalloc(target_procs_count, 556562306a36Sopenharmony_ci sizeof(struct binder_proc *), 556662306a36Sopenharmony_ci GFP_KERNEL); 556762306a36Sopenharmony_ci 556862306a36Sopenharmony_ci if (!target_procs) { 556962306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 557062306a36Sopenharmony_ci ret = -ENOMEM; 557162306a36Sopenharmony_ci goto err; 557262306a36Sopenharmony_ci } 557362306a36Sopenharmony_ci 557462306a36Sopenharmony_ci hlist_for_each_entry(target_proc, &binder_procs, proc_node) { 557562306a36Sopenharmony_ci if (target_proc->pid != info.pid) 557662306a36Sopenharmony_ci continue; 557762306a36Sopenharmony_ci 557862306a36Sopenharmony_ci binder_inner_proc_lock(target_proc); 557962306a36Sopenharmony_ci target_proc->tmp_ref++; 558062306a36Sopenharmony_ci binder_inner_proc_unlock(target_proc); 558162306a36Sopenharmony_ci 558262306a36Sopenharmony_ci target_procs[i++] = target_proc; 558362306a36Sopenharmony_ci } 558462306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 558562306a36Sopenharmony_ci 558662306a36Sopenharmony_ci for (i = 0; i < target_procs_count; i++) { 558762306a36Sopenharmony_ci if (ret >= 0) 558862306a36Sopenharmony_ci ret = binder_ioctl_freeze(&info, 558962306a36Sopenharmony_ci target_procs[i]); 559062306a36Sopenharmony_ci 559162306a36Sopenharmony_ci binder_proc_dec_tmpref(target_procs[i]); 559262306a36Sopenharmony_ci } 559362306a36Sopenharmony_ci 559462306a36Sopenharmony_ci kfree(target_procs); 559562306a36Sopenharmony_ci 559662306a36Sopenharmony_ci if (ret < 0) 559762306a36Sopenharmony_ci goto err; 559862306a36Sopenharmony_ci break; 559962306a36Sopenharmony_ci } 560062306a36Sopenharmony_ci case BINDER_GET_FROZEN_INFO: { 560162306a36Sopenharmony_ci struct binder_frozen_status_info info; 560262306a36Sopenharmony_ci 560362306a36Sopenharmony_ci if (copy_from_user(&info, ubuf, sizeof(info))) { 560462306a36Sopenharmony_ci ret = -EFAULT; 560562306a36Sopenharmony_ci goto err; 560662306a36Sopenharmony_ci } 560762306a36Sopenharmony_ci 560862306a36Sopenharmony_ci ret = binder_ioctl_get_freezer_info(&info); 560962306a36Sopenharmony_ci if (ret < 0) 561062306a36Sopenharmony_ci goto err; 561162306a36Sopenharmony_ci 561262306a36Sopenharmony_ci if (copy_to_user(ubuf, &info, sizeof(info))) { 561362306a36Sopenharmony_ci ret = -EFAULT; 561462306a36Sopenharmony_ci goto err; 561562306a36Sopenharmony_ci } 561662306a36Sopenharmony_ci break; 561762306a36Sopenharmony_ci } 561862306a36Sopenharmony_ci case BINDER_ENABLE_ONEWAY_SPAM_DETECTION: { 561962306a36Sopenharmony_ci uint32_t enable; 562062306a36Sopenharmony_ci 562162306a36Sopenharmony_ci if (copy_from_user(&enable, ubuf, sizeof(enable))) { 562262306a36Sopenharmony_ci ret = -EFAULT; 562362306a36Sopenharmony_ci goto err; 562462306a36Sopenharmony_ci } 562562306a36Sopenharmony_ci binder_inner_proc_lock(proc); 562662306a36Sopenharmony_ci proc->oneway_spam_detection_enabled = (bool)enable; 562762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 562862306a36Sopenharmony_ci break; 562962306a36Sopenharmony_ci } 563062306a36Sopenharmony_ci case BINDER_GET_EXTENDED_ERROR: 563162306a36Sopenharmony_ci ret = binder_ioctl_get_extended_error(thread, ubuf); 563262306a36Sopenharmony_ci if (ret < 0) 563362306a36Sopenharmony_ci goto err; 563462306a36Sopenharmony_ci break; 563562306a36Sopenharmony_ci case BINDER_FEATURE_SET: { 563662306a36Sopenharmony_ci struct binder_feature_set __user *features = ubuf; 563762306a36Sopenharmony_ci 563862306a36Sopenharmony_ci if (size != sizeof(struct binder_feature_set)) { 563962306a36Sopenharmony_ci ret = -EINVAL; 564062306a36Sopenharmony_ci goto err; 564162306a36Sopenharmony_ci } 564262306a36Sopenharmony_ci if (put_user(BINDER_CURRENT_FEATURE_SET, &features->feature_set)) { 564362306a36Sopenharmony_ci ret = -EINVAL; 564462306a36Sopenharmony_ci goto err; 564562306a36Sopenharmony_ci } 564662306a36Sopenharmony_ci break; 564762306a36Sopenharmony_ci } 564862306a36Sopenharmony_ci#ifdef CONFIG_ACCESS_TOKENID 564962306a36Sopenharmony_ci case BINDER_GET_ACCESS_TOKEN: { 565062306a36Sopenharmony_ci struct access_token __user *tokens = ubuf; 565162306a36Sopenharmony_ci u64 token, ftoken; 565262306a36Sopenharmony_ci 565362306a36Sopenharmony_ci if (size != sizeof(struct access_token)) { 565462306a36Sopenharmony_ci ret = -EINVAL; 565562306a36Sopenharmony_ci goto err; 565662306a36Sopenharmony_ci } 565762306a36Sopenharmony_ci binder_inner_proc_lock(proc); 565862306a36Sopenharmony_ci token = thread->tokens.sender_tokenid; 565962306a36Sopenharmony_ci ftoken = thread->tokens.first_tokenid; 566062306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 566162306a36Sopenharmony_ci if (put_user(token, &tokens->sender_tokenid)) { 566262306a36Sopenharmony_ci ret = -EINVAL; 566362306a36Sopenharmony_ci goto err; 566462306a36Sopenharmony_ci } 566562306a36Sopenharmony_ci if (put_user(ftoken, &tokens->first_tokenid)) { 566662306a36Sopenharmony_ci ret = -EINVAL; 566762306a36Sopenharmony_ci goto err; 566862306a36Sopenharmony_ci } 566962306a36Sopenharmony_ci break; 567062306a36Sopenharmony_ci } 567162306a36Sopenharmony_ci#endif /* CONFIG_ACCESS_TOKENID */ 567262306a36Sopenharmony_ci 567362306a36Sopenharmony_ci#ifdef CONFIG_BINDER_SENDER_INFO 567462306a36Sopenharmony_ci case BINDER_GET_SENDER_INFO: { 567562306a36Sopenharmony_ci struct binder_sender_info __user *sender = ubuf; 567662306a36Sopenharmony_ci u64 token, ftoken, sender_pid_nr; 567762306a36Sopenharmony_ci if (size != sizeof(struct binder_sender_info)) { 567862306a36Sopenharmony_ci ret = -EINVAL; 567962306a36Sopenharmony_ci goto err; 568062306a36Sopenharmony_ci } 568162306a36Sopenharmony_ci binder_inner_proc_lock(proc); 568262306a36Sopenharmony_ci#ifdef CONFIG_ACCESS_TOKENID 568362306a36Sopenharmony_ci token = thread->tokens.sender_tokenid; 568462306a36Sopenharmony_ci ftoken = thread->tokens.first_tokenid; 568562306a36Sopenharmony_ci#endif /*CONFIG_ACCESS_TOKENID*/ 568662306a36Sopenharmony_ci sender_pid_nr = thread->sender_pid_nr; 568762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 568862306a36Sopenharmony_ci#ifdef CONFIG_ACCESS_TOKENID 568962306a36Sopenharmony_ci if (put_user(token, &sender->tokens.sender_tokenid)) { 569062306a36Sopenharmony_ci ret = -EFAULT; 569162306a36Sopenharmony_ci goto err; 569262306a36Sopenharmony_ci } 569362306a36Sopenharmony_ci if (put_user(ftoken, &sender->tokens.first_tokenid)) { 569462306a36Sopenharmony_ci ret = -EFAULT; 569562306a36Sopenharmony_ci goto err; 569662306a36Sopenharmony_ci } 569762306a36Sopenharmony_ci#endif /*CONFIG_ACCESS_TOKENID*/ 569862306a36Sopenharmony_ci if (put_user(sender_pid_nr, &sender->sender_pid_nr)) { 569962306a36Sopenharmony_ci ret = -EFAULT; 570062306a36Sopenharmony_ci goto err; 570162306a36Sopenharmony_ci } 570262306a36Sopenharmony_ci break; 570362306a36Sopenharmony_ci } 570462306a36Sopenharmony_ci#endif /* CONFIG_BINDER_SENDER_INFO */ 570562306a36Sopenharmony_ci default: 570662306a36Sopenharmony_ci ret = -EINVAL; 570762306a36Sopenharmony_ci goto err; 570862306a36Sopenharmony_ci } 570962306a36Sopenharmony_ci ret = 0; 571062306a36Sopenharmony_cierr: 571162306a36Sopenharmony_ci if (thread) 571262306a36Sopenharmony_ci thread->looper_need_return = false; 571362306a36Sopenharmony_ci wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); 571462306a36Sopenharmony_ci if (ret && ret != -EINTR) 571562306a36Sopenharmony_ci pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); 571662306a36Sopenharmony_cierr_unlocked: 571762306a36Sopenharmony_ci trace_binder_ioctl_done(ret); 571862306a36Sopenharmony_ci return ret; 571962306a36Sopenharmony_ci} 572062306a36Sopenharmony_ci 572162306a36Sopenharmony_cistatic void binder_vma_open(struct vm_area_struct *vma) 572262306a36Sopenharmony_ci{ 572362306a36Sopenharmony_ci struct binder_proc *proc = vma->vm_private_data; 572462306a36Sopenharmony_ci 572562306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_OPEN_CLOSE, 572662306a36Sopenharmony_ci "%d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", 572762306a36Sopenharmony_ci proc->pid, vma->vm_start, vma->vm_end, 572862306a36Sopenharmony_ci (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, 572962306a36Sopenharmony_ci (unsigned long)pgprot_val(vma->vm_page_prot)); 573062306a36Sopenharmony_ci} 573162306a36Sopenharmony_ci 573262306a36Sopenharmony_cistatic void binder_vma_close(struct vm_area_struct *vma) 573362306a36Sopenharmony_ci{ 573462306a36Sopenharmony_ci struct binder_proc *proc = vma->vm_private_data; 573562306a36Sopenharmony_ci 573662306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_OPEN_CLOSE, 573762306a36Sopenharmony_ci "%d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", 573862306a36Sopenharmony_ci proc->pid, vma->vm_start, vma->vm_end, 573962306a36Sopenharmony_ci (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, 574062306a36Sopenharmony_ci (unsigned long)pgprot_val(vma->vm_page_prot)); 574162306a36Sopenharmony_ci binder_alloc_vma_close(&proc->alloc); 574262306a36Sopenharmony_ci} 574362306a36Sopenharmony_ci 574462306a36Sopenharmony_cistatic vm_fault_t binder_vm_fault(struct vm_fault *vmf) 574562306a36Sopenharmony_ci{ 574662306a36Sopenharmony_ci return VM_FAULT_SIGBUS; 574762306a36Sopenharmony_ci} 574862306a36Sopenharmony_ci 574962306a36Sopenharmony_cistatic const struct vm_operations_struct binder_vm_ops = { 575062306a36Sopenharmony_ci .open = binder_vma_open, 575162306a36Sopenharmony_ci .close = binder_vma_close, 575262306a36Sopenharmony_ci .fault = binder_vm_fault, 575362306a36Sopenharmony_ci}; 575462306a36Sopenharmony_ci 575562306a36Sopenharmony_cistatic int binder_mmap(struct file *filp, struct vm_area_struct *vma) 575662306a36Sopenharmony_ci{ 575762306a36Sopenharmony_ci struct binder_proc *proc = filp->private_data; 575862306a36Sopenharmony_ci 575962306a36Sopenharmony_ci if (proc->tsk != current->group_leader) 576062306a36Sopenharmony_ci return -EINVAL; 576162306a36Sopenharmony_ci 576262306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_OPEN_CLOSE, 576362306a36Sopenharmony_ci "%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", 576462306a36Sopenharmony_ci __func__, proc->pid, vma->vm_start, vma->vm_end, 576562306a36Sopenharmony_ci (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, 576662306a36Sopenharmony_ci (unsigned long)pgprot_val(vma->vm_page_prot)); 576762306a36Sopenharmony_ci 576862306a36Sopenharmony_ci if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) { 576962306a36Sopenharmony_ci pr_err("%s: %d %lx-%lx %s failed %d\n", __func__, 577062306a36Sopenharmony_ci proc->pid, vma->vm_start, vma->vm_end, "bad vm_flags", -EPERM); 577162306a36Sopenharmony_ci return -EPERM; 577262306a36Sopenharmony_ci } 577362306a36Sopenharmony_ci vm_flags_mod(vma, VM_DONTCOPY | VM_MIXEDMAP, VM_MAYWRITE); 577462306a36Sopenharmony_ci 577562306a36Sopenharmony_ci vma->vm_ops = &binder_vm_ops; 577662306a36Sopenharmony_ci vma->vm_private_data = proc; 577762306a36Sopenharmony_ci 577862306a36Sopenharmony_ci return binder_alloc_mmap_handler(&proc->alloc, vma); 577962306a36Sopenharmony_ci} 578062306a36Sopenharmony_ci 578162306a36Sopenharmony_cistatic int binder_open(struct inode *nodp, struct file *filp) 578262306a36Sopenharmony_ci{ 578362306a36Sopenharmony_ci struct binder_proc *proc, *itr; 578462306a36Sopenharmony_ci struct binder_device *binder_dev; 578562306a36Sopenharmony_ci struct binderfs_info *info; 578662306a36Sopenharmony_ci struct dentry *binder_binderfs_dir_entry_proc = NULL; 578762306a36Sopenharmony_ci bool existing_pid = false; 578862306a36Sopenharmony_ci 578962306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, 579062306a36Sopenharmony_ci current->group_leader->pid, current->pid); 579162306a36Sopenharmony_ci 579262306a36Sopenharmony_ci proc = kzalloc(sizeof(*proc), GFP_KERNEL); 579362306a36Sopenharmony_ci if (proc == NULL) 579462306a36Sopenharmony_ci return -ENOMEM; 579562306a36Sopenharmony_ci spin_lock_init(&proc->inner_lock); 579662306a36Sopenharmony_ci spin_lock_init(&proc->outer_lock); 579762306a36Sopenharmony_ci get_task_struct(current->group_leader); 579862306a36Sopenharmony_ci proc->tsk = current->group_leader; 579962306a36Sopenharmony_ci proc->cred = get_cred(filp->f_cred); 580062306a36Sopenharmony_ci INIT_LIST_HEAD(&proc->todo); 580162306a36Sopenharmony_ci init_waitqueue_head(&proc->freeze_wait); 580262306a36Sopenharmony_ci proc->default_priority = task_nice(current); 580362306a36Sopenharmony_ci /* binderfs stashes devices in i_private */ 580462306a36Sopenharmony_ci if (is_binderfs_device(nodp)) { 580562306a36Sopenharmony_ci binder_dev = nodp->i_private; 580662306a36Sopenharmony_ci info = nodp->i_sb->s_fs_info; 580762306a36Sopenharmony_ci binder_binderfs_dir_entry_proc = info->proc_log_dir; 580862306a36Sopenharmony_ci } else { 580962306a36Sopenharmony_ci binder_dev = container_of(filp->private_data, 581062306a36Sopenharmony_ci struct binder_device, miscdev); 581162306a36Sopenharmony_ci } 581262306a36Sopenharmony_ci refcount_inc(&binder_dev->ref); 581362306a36Sopenharmony_ci proc->context = &binder_dev->context; 581462306a36Sopenharmony_ci binder_alloc_init(&proc->alloc); 581562306a36Sopenharmony_ci 581662306a36Sopenharmony_ci binder_stats_created(BINDER_STAT_PROC); 581762306a36Sopenharmony_ci proc->pid = current->group_leader->pid; 581862306a36Sopenharmony_ci INIT_LIST_HEAD(&proc->delivered_death); 581962306a36Sopenharmony_ci INIT_LIST_HEAD(&proc->waiting_threads); 582062306a36Sopenharmony_ci filp->private_data = proc; 582162306a36Sopenharmony_ci 582262306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 582362306a36Sopenharmony_ci hlist_for_each_entry(itr, &binder_procs, proc_node) { 582462306a36Sopenharmony_ci if (itr->pid == proc->pid) { 582562306a36Sopenharmony_ci existing_pid = true; 582662306a36Sopenharmony_ci break; 582762306a36Sopenharmony_ci } 582862306a36Sopenharmony_ci } 582962306a36Sopenharmony_ci hlist_add_head(&proc->proc_node, &binder_procs); 583062306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 583162306a36Sopenharmony_ci 583262306a36Sopenharmony_ci if (binder_debugfs_dir_entry_proc && !existing_pid) { 583362306a36Sopenharmony_ci char strbuf[11]; 583462306a36Sopenharmony_ci 583562306a36Sopenharmony_ci snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); 583662306a36Sopenharmony_ci /* 583762306a36Sopenharmony_ci * proc debug entries are shared between contexts. 583862306a36Sopenharmony_ci * Only create for the first PID to avoid debugfs log spamming 583962306a36Sopenharmony_ci * The printing code will anyway print all contexts for a given 584062306a36Sopenharmony_ci * PID so this is not a problem. 584162306a36Sopenharmony_ci */ 584262306a36Sopenharmony_ci proc->debugfs_entry = debugfs_create_file(strbuf, 0444, 584362306a36Sopenharmony_ci binder_debugfs_dir_entry_proc, 584462306a36Sopenharmony_ci (void *)(unsigned long)proc->pid, 584562306a36Sopenharmony_ci &proc_fops); 584662306a36Sopenharmony_ci } 584762306a36Sopenharmony_ci 584862306a36Sopenharmony_ci if (binder_binderfs_dir_entry_proc && !existing_pid) { 584962306a36Sopenharmony_ci char strbuf[11]; 585062306a36Sopenharmony_ci struct dentry *binderfs_entry; 585162306a36Sopenharmony_ci 585262306a36Sopenharmony_ci snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); 585362306a36Sopenharmony_ci /* 585462306a36Sopenharmony_ci * Similar to debugfs, the process specific log file is shared 585562306a36Sopenharmony_ci * between contexts. Only create for the first PID. 585662306a36Sopenharmony_ci * This is ok since same as debugfs, the log file will contain 585762306a36Sopenharmony_ci * information on all contexts of a given PID. 585862306a36Sopenharmony_ci */ 585962306a36Sopenharmony_ci binderfs_entry = binderfs_create_file(binder_binderfs_dir_entry_proc, 586062306a36Sopenharmony_ci strbuf, &proc_fops, (void *)(unsigned long)proc->pid); 586162306a36Sopenharmony_ci if (!IS_ERR(binderfs_entry)) { 586262306a36Sopenharmony_ci proc->binderfs_entry = binderfs_entry; 586362306a36Sopenharmony_ci } else { 586462306a36Sopenharmony_ci int error; 586562306a36Sopenharmony_ci 586662306a36Sopenharmony_ci error = PTR_ERR(binderfs_entry); 586762306a36Sopenharmony_ci pr_warn("Unable to create file %s in binderfs (error %d)\n", 586862306a36Sopenharmony_ci strbuf, error); 586962306a36Sopenharmony_ci } 587062306a36Sopenharmony_ci } 587162306a36Sopenharmony_ci 587262306a36Sopenharmony_ci return 0; 587362306a36Sopenharmony_ci} 587462306a36Sopenharmony_ci 587562306a36Sopenharmony_cistatic int binder_flush(struct file *filp, fl_owner_t id) 587662306a36Sopenharmony_ci{ 587762306a36Sopenharmony_ci struct binder_proc *proc = filp->private_data; 587862306a36Sopenharmony_ci 587962306a36Sopenharmony_ci binder_defer_work(proc, BINDER_DEFERRED_FLUSH); 588062306a36Sopenharmony_ci 588162306a36Sopenharmony_ci return 0; 588262306a36Sopenharmony_ci} 588362306a36Sopenharmony_ci 588462306a36Sopenharmony_cistatic void binder_deferred_flush(struct binder_proc *proc) 588562306a36Sopenharmony_ci{ 588662306a36Sopenharmony_ci struct rb_node *n; 588762306a36Sopenharmony_ci int wake_count = 0; 588862306a36Sopenharmony_ci 588962306a36Sopenharmony_ci binder_inner_proc_lock(proc); 589062306a36Sopenharmony_ci for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { 589162306a36Sopenharmony_ci struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); 589262306a36Sopenharmony_ci 589362306a36Sopenharmony_ci thread->looper_need_return = true; 589462306a36Sopenharmony_ci if (thread->looper & BINDER_LOOPER_STATE_WAITING) { 589562306a36Sopenharmony_ci wake_up_interruptible(&thread->wait); 589662306a36Sopenharmony_ci wake_count++; 589762306a36Sopenharmony_ci } 589862306a36Sopenharmony_ci } 589962306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 590062306a36Sopenharmony_ci 590162306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_OPEN_CLOSE, 590262306a36Sopenharmony_ci "binder_flush: %d woke %d threads\n", proc->pid, 590362306a36Sopenharmony_ci wake_count); 590462306a36Sopenharmony_ci} 590562306a36Sopenharmony_ci 590662306a36Sopenharmony_cistatic int binder_release(struct inode *nodp, struct file *filp) 590762306a36Sopenharmony_ci{ 590862306a36Sopenharmony_ci struct binder_proc *proc = filp->private_data; 590962306a36Sopenharmony_ci 591062306a36Sopenharmony_ci debugfs_remove(proc->debugfs_entry); 591162306a36Sopenharmony_ci 591262306a36Sopenharmony_ci if (proc->binderfs_entry) { 591362306a36Sopenharmony_ci binderfs_remove_file(proc->binderfs_entry); 591462306a36Sopenharmony_ci proc->binderfs_entry = NULL; 591562306a36Sopenharmony_ci } 591662306a36Sopenharmony_ci 591762306a36Sopenharmony_ci binder_defer_work(proc, BINDER_DEFERRED_RELEASE); 591862306a36Sopenharmony_ci 591962306a36Sopenharmony_ci return 0; 592062306a36Sopenharmony_ci} 592162306a36Sopenharmony_ci 592262306a36Sopenharmony_cistatic int binder_node_release(struct binder_node *node, int refs) 592362306a36Sopenharmony_ci{ 592462306a36Sopenharmony_ci struct binder_ref *ref; 592562306a36Sopenharmony_ci int death = 0; 592662306a36Sopenharmony_ci struct binder_proc *proc = node->proc; 592762306a36Sopenharmony_ci 592862306a36Sopenharmony_ci binder_release_work(proc, &node->async_todo); 592962306a36Sopenharmony_ci 593062306a36Sopenharmony_ci binder_node_lock(node); 593162306a36Sopenharmony_ci binder_inner_proc_lock(proc); 593262306a36Sopenharmony_ci binder_dequeue_work_ilocked(&node->work); 593362306a36Sopenharmony_ci /* 593462306a36Sopenharmony_ci * The caller must have taken a temporary ref on the node, 593562306a36Sopenharmony_ci */ 593662306a36Sopenharmony_ci BUG_ON(!node->tmp_refs); 593762306a36Sopenharmony_ci if (hlist_empty(&node->refs) && node->tmp_refs == 1) { 593862306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 593962306a36Sopenharmony_ci binder_node_unlock(node); 594062306a36Sopenharmony_ci binder_free_node(node); 594162306a36Sopenharmony_ci 594262306a36Sopenharmony_ci return refs; 594362306a36Sopenharmony_ci } 594462306a36Sopenharmony_ci 594562306a36Sopenharmony_ci node->proc = NULL; 594662306a36Sopenharmony_ci node->local_strong_refs = 0; 594762306a36Sopenharmony_ci node->local_weak_refs = 0; 594862306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 594962306a36Sopenharmony_ci 595062306a36Sopenharmony_ci spin_lock(&binder_dead_nodes_lock); 595162306a36Sopenharmony_ci hlist_add_head(&node->dead_node, &binder_dead_nodes); 595262306a36Sopenharmony_ci spin_unlock(&binder_dead_nodes_lock); 595362306a36Sopenharmony_ci 595462306a36Sopenharmony_ci hlist_for_each_entry(ref, &node->refs, node_entry) { 595562306a36Sopenharmony_ci refs++; 595662306a36Sopenharmony_ci /* 595762306a36Sopenharmony_ci * Need the node lock to synchronize 595862306a36Sopenharmony_ci * with new notification requests and the 595962306a36Sopenharmony_ci * inner lock to synchronize with queued 596062306a36Sopenharmony_ci * death notifications. 596162306a36Sopenharmony_ci */ 596262306a36Sopenharmony_ci binder_inner_proc_lock(ref->proc); 596362306a36Sopenharmony_ci if (!ref->death) { 596462306a36Sopenharmony_ci binder_inner_proc_unlock(ref->proc); 596562306a36Sopenharmony_ci continue; 596662306a36Sopenharmony_ci } 596762306a36Sopenharmony_ci 596862306a36Sopenharmony_ci death++; 596962306a36Sopenharmony_ci 597062306a36Sopenharmony_ci BUG_ON(!list_empty(&ref->death->work.entry)); 597162306a36Sopenharmony_ci ref->death->work.type = BINDER_WORK_DEAD_BINDER; 597262306a36Sopenharmony_ci binder_enqueue_work_ilocked(&ref->death->work, 597362306a36Sopenharmony_ci &ref->proc->todo); 597462306a36Sopenharmony_ci binder_wakeup_proc_ilocked(ref->proc); 597562306a36Sopenharmony_ci binder_inner_proc_unlock(ref->proc); 597662306a36Sopenharmony_ci } 597762306a36Sopenharmony_ci 597862306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_BINDER, 597962306a36Sopenharmony_ci "node %d now dead, refs %d, death %d\n", 598062306a36Sopenharmony_ci node->debug_id, refs, death); 598162306a36Sopenharmony_ci binder_node_unlock(node); 598262306a36Sopenharmony_ci binder_put_node(node); 598362306a36Sopenharmony_ci 598462306a36Sopenharmony_ci return refs; 598562306a36Sopenharmony_ci} 598662306a36Sopenharmony_ci 598762306a36Sopenharmony_cistatic void binder_deferred_release(struct binder_proc *proc) 598862306a36Sopenharmony_ci{ 598962306a36Sopenharmony_ci struct binder_context *context = proc->context; 599062306a36Sopenharmony_ci struct rb_node *n; 599162306a36Sopenharmony_ci int threads, nodes, incoming_refs, outgoing_refs, active_transactions; 599262306a36Sopenharmony_ci 599362306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 599462306a36Sopenharmony_ci hlist_del(&proc->proc_node); 599562306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 599662306a36Sopenharmony_ci 599762306a36Sopenharmony_ci mutex_lock(&context->context_mgr_node_lock); 599862306a36Sopenharmony_ci if (context->binder_context_mgr_node && 599962306a36Sopenharmony_ci context->binder_context_mgr_node->proc == proc) { 600062306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_DEAD_BINDER, 600162306a36Sopenharmony_ci "%s: %d context_mgr_node gone\n", 600262306a36Sopenharmony_ci __func__, proc->pid); 600362306a36Sopenharmony_ci context->binder_context_mgr_node = NULL; 600462306a36Sopenharmony_ci } 600562306a36Sopenharmony_ci mutex_unlock(&context->context_mgr_node_lock); 600662306a36Sopenharmony_ci binder_inner_proc_lock(proc); 600762306a36Sopenharmony_ci /* 600862306a36Sopenharmony_ci * Make sure proc stays alive after we 600962306a36Sopenharmony_ci * remove all the threads 601062306a36Sopenharmony_ci */ 601162306a36Sopenharmony_ci proc->tmp_ref++; 601262306a36Sopenharmony_ci 601362306a36Sopenharmony_ci proc->is_dead = true; 601462306a36Sopenharmony_ci proc->is_frozen = false; 601562306a36Sopenharmony_ci proc->sync_recv = false; 601662306a36Sopenharmony_ci proc->async_recv = false; 601762306a36Sopenharmony_ci threads = 0; 601862306a36Sopenharmony_ci active_transactions = 0; 601962306a36Sopenharmony_ci while ((n = rb_first(&proc->threads))) { 602062306a36Sopenharmony_ci struct binder_thread *thread; 602162306a36Sopenharmony_ci 602262306a36Sopenharmony_ci thread = rb_entry(n, struct binder_thread, rb_node); 602362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 602462306a36Sopenharmony_ci threads++; 602562306a36Sopenharmony_ci active_transactions += binder_thread_release(proc, thread); 602662306a36Sopenharmony_ci binder_inner_proc_lock(proc); 602762306a36Sopenharmony_ci } 602862306a36Sopenharmony_ci 602962306a36Sopenharmony_ci nodes = 0; 603062306a36Sopenharmony_ci incoming_refs = 0; 603162306a36Sopenharmony_ci while ((n = rb_first(&proc->nodes))) { 603262306a36Sopenharmony_ci struct binder_node *node; 603362306a36Sopenharmony_ci 603462306a36Sopenharmony_ci node = rb_entry(n, struct binder_node, rb_node); 603562306a36Sopenharmony_ci nodes++; 603662306a36Sopenharmony_ci /* 603762306a36Sopenharmony_ci * take a temporary ref on the node before 603862306a36Sopenharmony_ci * calling binder_node_release() which will either 603962306a36Sopenharmony_ci * kfree() the node or call binder_put_node() 604062306a36Sopenharmony_ci */ 604162306a36Sopenharmony_ci binder_inc_node_tmpref_ilocked(node); 604262306a36Sopenharmony_ci rb_erase(&node->rb_node, &proc->nodes); 604362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 604462306a36Sopenharmony_ci incoming_refs = binder_node_release(node, incoming_refs); 604562306a36Sopenharmony_ci binder_inner_proc_lock(proc); 604662306a36Sopenharmony_ci } 604762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 604862306a36Sopenharmony_ci 604962306a36Sopenharmony_ci outgoing_refs = 0; 605062306a36Sopenharmony_ci binder_proc_lock(proc); 605162306a36Sopenharmony_ci while ((n = rb_first(&proc->refs_by_desc))) { 605262306a36Sopenharmony_ci struct binder_ref *ref; 605362306a36Sopenharmony_ci 605462306a36Sopenharmony_ci ref = rb_entry(n, struct binder_ref, rb_node_desc); 605562306a36Sopenharmony_ci outgoing_refs++; 605662306a36Sopenharmony_ci binder_cleanup_ref_olocked(ref); 605762306a36Sopenharmony_ci binder_proc_unlock(proc); 605862306a36Sopenharmony_ci binder_free_ref(ref); 605962306a36Sopenharmony_ci binder_proc_lock(proc); 606062306a36Sopenharmony_ci } 606162306a36Sopenharmony_ci binder_proc_unlock(proc); 606262306a36Sopenharmony_ci 606362306a36Sopenharmony_ci binder_release_work(proc, &proc->todo); 606462306a36Sopenharmony_ci binder_release_work(proc, &proc->delivered_death); 606562306a36Sopenharmony_ci 606662306a36Sopenharmony_ci binder_debug(BINDER_DEBUG_OPEN_CLOSE, 606762306a36Sopenharmony_ci "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n", 606862306a36Sopenharmony_ci __func__, proc->pid, threads, nodes, incoming_refs, 606962306a36Sopenharmony_ci outgoing_refs, active_transactions); 607062306a36Sopenharmony_ci 607162306a36Sopenharmony_ci binder_proc_dec_tmpref(proc); 607262306a36Sopenharmony_ci} 607362306a36Sopenharmony_ci 607462306a36Sopenharmony_cistatic void binder_deferred_func(struct work_struct *work) 607562306a36Sopenharmony_ci{ 607662306a36Sopenharmony_ci struct binder_proc *proc; 607762306a36Sopenharmony_ci 607862306a36Sopenharmony_ci int defer; 607962306a36Sopenharmony_ci 608062306a36Sopenharmony_ci do { 608162306a36Sopenharmony_ci mutex_lock(&binder_deferred_lock); 608262306a36Sopenharmony_ci if (!hlist_empty(&binder_deferred_list)) { 608362306a36Sopenharmony_ci proc = hlist_entry(binder_deferred_list.first, 608462306a36Sopenharmony_ci struct binder_proc, deferred_work_node); 608562306a36Sopenharmony_ci hlist_del_init(&proc->deferred_work_node); 608662306a36Sopenharmony_ci defer = proc->deferred_work; 608762306a36Sopenharmony_ci proc->deferred_work = 0; 608862306a36Sopenharmony_ci } else { 608962306a36Sopenharmony_ci proc = NULL; 609062306a36Sopenharmony_ci defer = 0; 609162306a36Sopenharmony_ci } 609262306a36Sopenharmony_ci mutex_unlock(&binder_deferred_lock); 609362306a36Sopenharmony_ci 609462306a36Sopenharmony_ci if (defer & BINDER_DEFERRED_FLUSH) 609562306a36Sopenharmony_ci binder_deferred_flush(proc); 609662306a36Sopenharmony_ci 609762306a36Sopenharmony_ci if (defer & BINDER_DEFERRED_RELEASE) 609862306a36Sopenharmony_ci binder_deferred_release(proc); /* frees proc */ 609962306a36Sopenharmony_ci } while (proc); 610062306a36Sopenharmony_ci} 610162306a36Sopenharmony_cistatic DECLARE_WORK(binder_deferred_work, binder_deferred_func); 610262306a36Sopenharmony_ci 610362306a36Sopenharmony_cistatic void 610462306a36Sopenharmony_cibinder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer) 610562306a36Sopenharmony_ci{ 610662306a36Sopenharmony_ci mutex_lock(&binder_deferred_lock); 610762306a36Sopenharmony_ci proc->deferred_work |= defer; 610862306a36Sopenharmony_ci if (hlist_unhashed(&proc->deferred_work_node)) { 610962306a36Sopenharmony_ci hlist_add_head(&proc->deferred_work_node, 611062306a36Sopenharmony_ci &binder_deferred_list); 611162306a36Sopenharmony_ci schedule_work(&binder_deferred_work); 611262306a36Sopenharmony_ci } 611362306a36Sopenharmony_ci mutex_unlock(&binder_deferred_lock); 611462306a36Sopenharmony_ci} 611562306a36Sopenharmony_ci 611662306a36Sopenharmony_cistatic void print_binder_transaction_ilocked(struct seq_file *m, 611762306a36Sopenharmony_ci struct binder_proc *proc, 611862306a36Sopenharmony_ci const char *prefix, 611962306a36Sopenharmony_ci struct binder_transaction *t) 612062306a36Sopenharmony_ci{ 612162306a36Sopenharmony_ci struct binder_proc *to_proc; 612262306a36Sopenharmony_ci struct binder_buffer *buffer = t->buffer; 612362306a36Sopenharmony_ci ktime_t current_time = ktime_get(); 612462306a36Sopenharmony_ci 612562306a36Sopenharmony_ci spin_lock(&t->lock); 612662306a36Sopenharmony_ci to_proc = t->to_proc; 612762306a36Sopenharmony_ci seq_printf(m, 612862306a36Sopenharmony_ci "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d elapsed %lldms", 612962306a36Sopenharmony_ci prefix, t->debug_id, t, 613062306a36Sopenharmony_ci t->from_pid, 613162306a36Sopenharmony_ci t->from_tid, 613262306a36Sopenharmony_ci to_proc ? to_proc->pid : 0, 613362306a36Sopenharmony_ci t->to_thread ? t->to_thread->pid : 0, 613462306a36Sopenharmony_ci t->code, t->flags, t->priority, t->need_reply, 613562306a36Sopenharmony_ci ktime_ms_delta(current_time, t->start_time)); 613662306a36Sopenharmony_ci spin_unlock(&t->lock); 613762306a36Sopenharmony_ci 613862306a36Sopenharmony_ci if (proc != to_proc) { 613962306a36Sopenharmony_ci /* 614062306a36Sopenharmony_ci * Can only safely deref buffer if we are holding the 614162306a36Sopenharmony_ci * correct proc inner lock for this node 614262306a36Sopenharmony_ci */ 614362306a36Sopenharmony_ci seq_puts(m, "\n"); 614462306a36Sopenharmony_ci return; 614562306a36Sopenharmony_ci } 614662306a36Sopenharmony_ci 614762306a36Sopenharmony_ci if (buffer == NULL) { 614862306a36Sopenharmony_ci seq_puts(m, " buffer free\n"); 614962306a36Sopenharmony_ci return; 615062306a36Sopenharmony_ci } 615162306a36Sopenharmony_ci if (buffer->target_node) 615262306a36Sopenharmony_ci seq_printf(m, " node %d", buffer->target_node->debug_id); 615362306a36Sopenharmony_ci seq_printf(m, " size %zd:%zd data %pK\n", 615462306a36Sopenharmony_ci buffer->data_size, buffer->offsets_size, 615562306a36Sopenharmony_ci buffer->user_data); 615662306a36Sopenharmony_ci} 615762306a36Sopenharmony_ci 615862306a36Sopenharmony_cistatic void print_binder_work_ilocked(struct seq_file *m, 615962306a36Sopenharmony_ci struct binder_proc *proc, 616062306a36Sopenharmony_ci const char *prefix, 616162306a36Sopenharmony_ci const char *transaction_prefix, 616262306a36Sopenharmony_ci struct binder_work *w) 616362306a36Sopenharmony_ci{ 616462306a36Sopenharmony_ci struct binder_node *node; 616562306a36Sopenharmony_ci struct binder_transaction *t; 616662306a36Sopenharmony_ci 616762306a36Sopenharmony_ci switch (w->type) { 616862306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION: 616962306a36Sopenharmony_ci t = container_of(w, struct binder_transaction, work); 617062306a36Sopenharmony_ci print_binder_transaction_ilocked( 617162306a36Sopenharmony_ci m, proc, transaction_prefix, t); 617262306a36Sopenharmony_ci break; 617362306a36Sopenharmony_ci case BINDER_WORK_RETURN_ERROR: { 617462306a36Sopenharmony_ci struct binder_error *e = container_of( 617562306a36Sopenharmony_ci w, struct binder_error, work); 617662306a36Sopenharmony_ci 617762306a36Sopenharmony_ci seq_printf(m, "%stransaction error: %u\n", 617862306a36Sopenharmony_ci prefix, e->cmd); 617962306a36Sopenharmony_ci } break; 618062306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION_COMPLETE: 618162306a36Sopenharmony_ci seq_printf(m, "%stransaction complete\n", prefix); 618262306a36Sopenharmony_ci break; 618362306a36Sopenharmony_ci case BINDER_WORK_NODE: 618462306a36Sopenharmony_ci node = container_of(w, struct binder_node, work); 618562306a36Sopenharmony_ci seq_printf(m, "%snode work %d: u%016llx c%016llx\n", 618662306a36Sopenharmony_ci prefix, node->debug_id, 618762306a36Sopenharmony_ci (u64)node->ptr, (u64)node->cookie); 618862306a36Sopenharmony_ci break; 618962306a36Sopenharmony_ci case BINDER_WORK_DEAD_BINDER: 619062306a36Sopenharmony_ci seq_printf(m, "%shas dead binder\n", prefix); 619162306a36Sopenharmony_ci break; 619262306a36Sopenharmony_ci case BINDER_WORK_DEAD_BINDER_AND_CLEAR: 619362306a36Sopenharmony_ci seq_printf(m, "%shas cleared dead binder\n", prefix); 619462306a36Sopenharmony_ci break; 619562306a36Sopenharmony_ci case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: 619662306a36Sopenharmony_ci seq_printf(m, "%shas cleared death notification\n", prefix); 619762306a36Sopenharmony_ci break; 619862306a36Sopenharmony_ci default: 619962306a36Sopenharmony_ci seq_printf(m, "%sunknown work: type %d\n", prefix, w->type); 620062306a36Sopenharmony_ci break; 620162306a36Sopenharmony_ci } 620262306a36Sopenharmony_ci} 620362306a36Sopenharmony_ci 620462306a36Sopenharmony_cistatic void print_binder_thread_ilocked(struct seq_file *m, 620562306a36Sopenharmony_ci struct binder_thread *thread, 620662306a36Sopenharmony_ci int print_always) 620762306a36Sopenharmony_ci{ 620862306a36Sopenharmony_ci struct binder_transaction *t; 620962306a36Sopenharmony_ci struct binder_work *w; 621062306a36Sopenharmony_ci size_t start_pos = m->count; 621162306a36Sopenharmony_ci size_t header_pos; 621262306a36Sopenharmony_ci 621362306a36Sopenharmony_ci seq_printf(m, " thread %d: l %02x need_return %d tr %d\n", 621462306a36Sopenharmony_ci thread->pid, thread->looper, 621562306a36Sopenharmony_ci thread->looper_need_return, 621662306a36Sopenharmony_ci atomic_read(&thread->tmp_ref)); 621762306a36Sopenharmony_ci header_pos = m->count; 621862306a36Sopenharmony_ci t = thread->transaction_stack; 621962306a36Sopenharmony_ci while (t) { 622062306a36Sopenharmony_ci if (t->from == thread) { 622162306a36Sopenharmony_ci print_binder_transaction_ilocked(m, thread->proc, 622262306a36Sopenharmony_ci " outgoing transaction", t); 622362306a36Sopenharmony_ci t = t->from_parent; 622462306a36Sopenharmony_ci } else if (t->to_thread == thread) { 622562306a36Sopenharmony_ci print_binder_transaction_ilocked(m, thread->proc, 622662306a36Sopenharmony_ci " incoming transaction", t); 622762306a36Sopenharmony_ci t = t->to_parent; 622862306a36Sopenharmony_ci } else { 622962306a36Sopenharmony_ci print_binder_transaction_ilocked(m, thread->proc, 623062306a36Sopenharmony_ci " bad transaction", t); 623162306a36Sopenharmony_ci t = NULL; 623262306a36Sopenharmony_ci } 623362306a36Sopenharmony_ci } 623462306a36Sopenharmony_ci list_for_each_entry(w, &thread->todo, entry) { 623562306a36Sopenharmony_ci print_binder_work_ilocked(m, thread->proc, " ", 623662306a36Sopenharmony_ci " pending transaction", w); 623762306a36Sopenharmony_ci } 623862306a36Sopenharmony_ci if (!print_always && m->count == header_pos) 623962306a36Sopenharmony_ci m->count = start_pos; 624062306a36Sopenharmony_ci} 624162306a36Sopenharmony_ci 624262306a36Sopenharmony_cistatic void print_binder_node_nilocked(struct seq_file *m, 624362306a36Sopenharmony_ci struct binder_node *node) 624462306a36Sopenharmony_ci{ 624562306a36Sopenharmony_ci struct binder_ref *ref; 624662306a36Sopenharmony_ci struct binder_work *w; 624762306a36Sopenharmony_ci int count; 624862306a36Sopenharmony_ci 624962306a36Sopenharmony_ci count = 0; 625062306a36Sopenharmony_ci hlist_for_each_entry(ref, &node->refs, node_entry) 625162306a36Sopenharmony_ci count++; 625262306a36Sopenharmony_ci 625362306a36Sopenharmony_ci seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d", 625462306a36Sopenharmony_ci node->debug_id, (u64)node->ptr, (u64)node->cookie, 625562306a36Sopenharmony_ci node->has_strong_ref, node->has_weak_ref, 625662306a36Sopenharmony_ci node->local_strong_refs, node->local_weak_refs, 625762306a36Sopenharmony_ci node->internal_strong_refs, count, node->tmp_refs); 625862306a36Sopenharmony_ci if (count) { 625962306a36Sopenharmony_ci seq_puts(m, " proc"); 626062306a36Sopenharmony_ci hlist_for_each_entry(ref, &node->refs, node_entry) 626162306a36Sopenharmony_ci seq_printf(m, " %d", ref->proc->pid); 626262306a36Sopenharmony_ci } 626362306a36Sopenharmony_ci seq_puts(m, "\n"); 626462306a36Sopenharmony_ci if (node->proc) { 626562306a36Sopenharmony_ci list_for_each_entry(w, &node->async_todo, entry) 626662306a36Sopenharmony_ci print_binder_work_ilocked(m, node->proc, " ", 626762306a36Sopenharmony_ci " pending async transaction", w); 626862306a36Sopenharmony_ci } 626962306a36Sopenharmony_ci} 627062306a36Sopenharmony_ci 627162306a36Sopenharmony_cistatic void print_binder_ref_olocked(struct seq_file *m, 627262306a36Sopenharmony_ci struct binder_ref *ref) 627362306a36Sopenharmony_ci{ 627462306a36Sopenharmony_ci binder_node_lock(ref->node); 627562306a36Sopenharmony_ci seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n", 627662306a36Sopenharmony_ci ref->data.debug_id, ref->data.desc, 627762306a36Sopenharmony_ci ref->node->proc ? "" : "dead ", 627862306a36Sopenharmony_ci ref->node->debug_id, ref->data.strong, 627962306a36Sopenharmony_ci ref->data.weak, ref->death); 628062306a36Sopenharmony_ci binder_node_unlock(ref->node); 628162306a36Sopenharmony_ci} 628262306a36Sopenharmony_ci 628362306a36Sopenharmony_cistatic void print_binder_proc(struct seq_file *m, 628462306a36Sopenharmony_ci struct binder_proc *proc, int print_all) 628562306a36Sopenharmony_ci{ 628662306a36Sopenharmony_ci struct binder_work *w; 628762306a36Sopenharmony_ci struct rb_node *n; 628862306a36Sopenharmony_ci size_t start_pos = m->count; 628962306a36Sopenharmony_ci size_t header_pos; 629062306a36Sopenharmony_ci struct binder_node *last_node = NULL; 629162306a36Sopenharmony_ci 629262306a36Sopenharmony_ci seq_printf(m, "proc %d\n", proc->pid); 629362306a36Sopenharmony_ci seq_printf(m, "context %s\n", proc->context->name); 629462306a36Sopenharmony_ci header_pos = m->count; 629562306a36Sopenharmony_ci 629662306a36Sopenharmony_ci binder_inner_proc_lock(proc); 629762306a36Sopenharmony_ci for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) 629862306a36Sopenharmony_ci print_binder_thread_ilocked(m, rb_entry(n, struct binder_thread, 629962306a36Sopenharmony_ci rb_node), print_all); 630062306a36Sopenharmony_ci 630162306a36Sopenharmony_ci for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) { 630262306a36Sopenharmony_ci struct binder_node *node = rb_entry(n, struct binder_node, 630362306a36Sopenharmony_ci rb_node); 630462306a36Sopenharmony_ci if (!print_all && !node->has_async_transaction) 630562306a36Sopenharmony_ci continue; 630662306a36Sopenharmony_ci 630762306a36Sopenharmony_ci /* 630862306a36Sopenharmony_ci * take a temporary reference on the node so it 630962306a36Sopenharmony_ci * survives and isn't removed from the tree 631062306a36Sopenharmony_ci * while we print it. 631162306a36Sopenharmony_ci */ 631262306a36Sopenharmony_ci binder_inc_node_tmpref_ilocked(node); 631362306a36Sopenharmony_ci /* Need to drop inner lock to take node lock */ 631462306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 631562306a36Sopenharmony_ci if (last_node) 631662306a36Sopenharmony_ci binder_put_node(last_node); 631762306a36Sopenharmony_ci binder_node_inner_lock(node); 631862306a36Sopenharmony_ci print_binder_node_nilocked(m, node); 631962306a36Sopenharmony_ci binder_node_inner_unlock(node); 632062306a36Sopenharmony_ci last_node = node; 632162306a36Sopenharmony_ci binder_inner_proc_lock(proc); 632262306a36Sopenharmony_ci } 632362306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 632462306a36Sopenharmony_ci if (last_node) 632562306a36Sopenharmony_ci binder_put_node(last_node); 632662306a36Sopenharmony_ci 632762306a36Sopenharmony_ci if (print_all) { 632862306a36Sopenharmony_ci binder_proc_lock(proc); 632962306a36Sopenharmony_ci for (n = rb_first(&proc->refs_by_desc); 633062306a36Sopenharmony_ci n != NULL; 633162306a36Sopenharmony_ci n = rb_next(n)) 633262306a36Sopenharmony_ci print_binder_ref_olocked(m, rb_entry(n, 633362306a36Sopenharmony_ci struct binder_ref, 633462306a36Sopenharmony_ci rb_node_desc)); 633562306a36Sopenharmony_ci binder_proc_unlock(proc); 633662306a36Sopenharmony_ci } 633762306a36Sopenharmony_ci binder_alloc_print_allocated(m, &proc->alloc); 633862306a36Sopenharmony_ci binder_inner_proc_lock(proc); 633962306a36Sopenharmony_ci list_for_each_entry(w, &proc->todo, entry) 634062306a36Sopenharmony_ci print_binder_work_ilocked(m, proc, " ", 634162306a36Sopenharmony_ci " pending transaction", w); 634262306a36Sopenharmony_ci list_for_each_entry(w, &proc->delivered_death, entry) { 634362306a36Sopenharmony_ci seq_puts(m, " has delivered dead binder\n"); 634462306a36Sopenharmony_ci break; 634562306a36Sopenharmony_ci } 634662306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 634762306a36Sopenharmony_ci if (!print_all && m->count == header_pos) 634862306a36Sopenharmony_ci m->count = start_pos; 634962306a36Sopenharmony_ci} 635062306a36Sopenharmony_ci 635162306a36Sopenharmony_cistatic const char * const binder_return_strings[] = { 635262306a36Sopenharmony_ci "BR_ERROR", 635362306a36Sopenharmony_ci "BR_OK", 635462306a36Sopenharmony_ci "BR_TRANSACTION", 635562306a36Sopenharmony_ci "BR_REPLY", 635662306a36Sopenharmony_ci "BR_ACQUIRE_RESULT", 635762306a36Sopenharmony_ci "BR_DEAD_REPLY", 635862306a36Sopenharmony_ci "BR_TRANSACTION_COMPLETE", 635962306a36Sopenharmony_ci "BR_INCREFS", 636062306a36Sopenharmony_ci "BR_ACQUIRE", 636162306a36Sopenharmony_ci "BR_RELEASE", 636262306a36Sopenharmony_ci "BR_DECREFS", 636362306a36Sopenharmony_ci "BR_ATTEMPT_ACQUIRE", 636462306a36Sopenharmony_ci "BR_NOOP", 636562306a36Sopenharmony_ci "BR_SPAWN_LOOPER", 636662306a36Sopenharmony_ci "BR_FINISHED", 636762306a36Sopenharmony_ci "BR_DEAD_BINDER", 636862306a36Sopenharmony_ci "BR_CLEAR_DEATH_NOTIFICATION_DONE", 636962306a36Sopenharmony_ci "BR_FAILED_REPLY", 637062306a36Sopenharmony_ci "BR_FROZEN_REPLY", 637162306a36Sopenharmony_ci "BR_ONEWAY_SPAM_SUSPECT", 637262306a36Sopenharmony_ci "BR_TRANSACTION_PENDING_FROZEN" 637362306a36Sopenharmony_ci}; 637462306a36Sopenharmony_ci 637562306a36Sopenharmony_cistatic const char * const binder_command_strings[] = { 637662306a36Sopenharmony_ci "BC_TRANSACTION", 637762306a36Sopenharmony_ci "BC_REPLY", 637862306a36Sopenharmony_ci "BC_ACQUIRE_RESULT", 637962306a36Sopenharmony_ci "BC_FREE_BUFFER", 638062306a36Sopenharmony_ci "BC_INCREFS", 638162306a36Sopenharmony_ci "BC_ACQUIRE", 638262306a36Sopenharmony_ci "BC_RELEASE", 638362306a36Sopenharmony_ci "BC_DECREFS", 638462306a36Sopenharmony_ci "BC_INCREFS_DONE", 638562306a36Sopenharmony_ci "BC_ACQUIRE_DONE", 638662306a36Sopenharmony_ci "BC_ATTEMPT_ACQUIRE", 638762306a36Sopenharmony_ci "BC_REGISTER_LOOPER", 638862306a36Sopenharmony_ci "BC_ENTER_LOOPER", 638962306a36Sopenharmony_ci "BC_EXIT_LOOPER", 639062306a36Sopenharmony_ci "BC_REQUEST_DEATH_NOTIFICATION", 639162306a36Sopenharmony_ci "BC_CLEAR_DEATH_NOTIFICATION", 639262306a36Sopenharmony_ci "BC_DEAD_BINDER_DONE", 639362306a36Sopenharmony_ci "BC_TRANSACTION_SG", 639462306a36Sopenharmony_ci "BC_REPLY_SG", 639562306a36Sopenharmony_ci}; 639662306a36Sopenharmony_ci 639762306a36Sopenharmony_cistatic const char * const binder_objstat_strings[] = { 639862306a36Sopenharmony_ci "proc", 639962306a36Sopenharmony_ci "thread", 640062306a36Sopenharmony_ci "node", 640162306a36Sopenharmony_ci "ref", 640262306a36Sopenharmony_ci "death", 640362306a36Sopenharmony_ci "transaction", 640462306a36Sopenharmony_ci "transaction_complete" 640562306a36Sopenharmony_ci}; 640662306a36Sopenharmony_ci 640762306a36Sopenharmony_cistatic void print_binder_stats(struct seq_file *m, const char *prefix, 640862306a36Sopenharmony_ci struct binder_stats *stats) 640962306a36Sopenharmony_ci{ 641062306a36Sopenharmony_ci int i; 641162306a36Sopenharmony_ci 641262306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(stats->bc) != 641362306a36Sopenharmony_ci ARRAY_SIZE(binder_command_strings)); 641462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(stats->bc); i++) { 641562306a36Sopenharmony_ci int temp = atomic_read(&stats->bc[i]); 641662306a36Sopenharmony_ci 641762306a36Sopenharmony_ci if (temp) 641862306a36Sopenharmony_ci seq_printf(m, "%s%s: %d\n", prefix, 641962306a36Sopenharmony_ci binder_command_strings[i], temp); 642062306a36Sopenharmony_ci } 642162306a36Sopenharmony_ci 642262306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(stats->br) != 642362306a36Sopenharmony_ci ARRAY_SIZE(binder_return_strings)); 642462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(stats->br); i++) { 642562306a36Sopenharmony_ci int temp = atomic_read(&stats->br[i]); 642662306a36Sopenharmony_ci 642762306a36Sopenharmony_ci if (temp) 642862306a36Sopenharmony_ci seq_printf(m, "%s%s: %d\n", prefix, 642962306a36Sopenharmony_ci binder_return_strings[i], temp); 643062306a36Sopenharmony_ci } 643162306a36Sopenharmony_ci 643262306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != 643362306a36Sopenharmony_ci ARRAY_SIZE(binder_objstat_strings)); 643462306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != 643562306a36Sopenharmony_ci ARRAY_SIZE(stats->obj_deleted)); 643662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) { 643762306a36Sopenharmony_ci int created = atomic_read(&stats->obj_created[i]); 643862306a36Sopenharmony_ci int deleted = atomic_read(&stats->obj_deleted[i]); 643962306a36Sopenharmony_ci 644062306a36Sopenharmony_ci if (created || deleted) 644162306a36Sopenharmony_ci seq_printf(m, "%s%s: active %d total %d\n", 644262306a36Sopenharmony_ci prefix, 644362306a36Sopenharmony_ci binder_objstat_strings[i], 644462306a36Sopenharmony_ci created - deleted, 644562306a36Sopenharmony_ci created); 644662306a36Sopenharmony_ci } 644762306a36Sopenharmony_ci} 644862306a36Sopenharmony_ci 644962306a36Sopenharmony_cistatic void print_binder_proc_stats(struct seq_file *m, 645062306a36Sopenharmony_ci struct binder_proc *proc) 645162306a36Sopenharmony_ci{ 645262306a36Sopenharmony_ci struct binder_work *w; 645362306a36Sopenharmony_ci struct binder_thread *thread; 645462306a36Sopenharmony_ci struct rb_node *n; 645562306a36Sopenharmony_ci int count, strong, weak, ready_threads; 645662306a36Sopenharmony_ci size_t free_async_space = 645762306a36Sopenharmony_ci binder_alloc_get_free_async_space(&proc->alloc); 645862306a36Sopenharmony_ci 645962306a36Sopenharmony_ci seq_printf(m, "proc %d\n", proc->pid); 646062306a36Sopenharmony_ci seq_printf(m, "context %s\n", proc->context->name); 646162306a36Sopenharmony_ci count = 0; 646262306a36Sopenharmony_ci ready_threads = 0; 646362306a36Sopenharmony_ci binder_inner_proc_lock(proc); 646462306a36Sopenharmony_ci for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) 646562306a36Sopenharmony_ci count++; 646662306a36Sopenharmony_ci 646762306a36Sopenharmony_ci list_for_each_entry(thread, &proc->waiting_threads, waiting_thread_node) 646862306a36Sopenharmony_ci ready_threads++; 646962306a36Sopenharmony_ci 647062306a36Sopenharmony_ci seq_printf(m, " threads: %d\n", count); 647162306a36Sopenharmony_ci seq_printf(m, " requested threads: %d+%d/%d\n" 647262306a36Sopenharmony_ci " ready threads %d\n" 647362306a36Sopenharmony_ci " free async space %zd\n", proc->requested_threads, 647462306a36Sopenharmony_ci proc->requested_threads_started, proc->max_threads, 647562306a36Sopenharmony_ci ready_threads, 647662306a36Sopenharmony_ci free_async_space); 647762306a36Sopenharmony_ci count = 0; 647862306a36Sopenharmony_ci for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) 647962306a36Sopenharmony_ci count++; 648062306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 648162306a36Sopenharmony_ci seq_printf(m, " nodes: %d\n", count); 648262306a36Sopenharmony_ci count = 0; 648362306a36Sopenharmony_ci strong = 0; 648462306a36Sopenharmony_ci weak = 0; 648562306a36Sopenharmony_ci binder_proc_lock(proc); 648662306a36Sopenharmony_ci for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { 648762306a36Sopenharmony_ci struct binder_ref *ref = rb_entry(n, struct binder_ref, 648862306a36Sopenharmony_ci rb_node_desc); 648962306a36Sopenharmony_ci count++; 649062306a36Sopenharmony_ci strong += ref->data.strong; 649162306a36Sopenharmony_ci weak += ref->data.weak; 649262306a36Sopenharmony_ci } 649362306a36Sopenharmony_ci binder_proc_unlock(proc); 649462306a36Sopenharmony_ci seq_printf(m, " refs: %d s %d w %d\n", count, strong, weak); 649562306a36Sopenharmony_ci 649662306a36Sopenharmony_ci count = binder_alloc_get_allocated_count(&proc->alloc); 649762306a36Sopenharmony_ci seq_printf(m, " buffers: %d\n", count); 649862306a36Sopenharmony_ci 649962306a36Sopenharmony_ci binder_alloc_print_pages(m, &proc->alloc); 650062306a36Sopenharmony_ci 650162306a36Sopenharmony_ci count = 0; 650262306a36Sopenharmony_ci binder_inner_proc_lock(proc); 650362306a36Sopenharmony_ci list_for_each_entry(w, &proc->todo, entry) { 650462306a36Sopenharmony_ci if (w->type == BINDER_WORK_TRANSACTION) 650562306a36Sopenharmony_ci count++; 650662306a36Sopenharmony_ci } 650762306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 650862306a36Sopenharmony_ci seq_printf(m, " pending transactions: %d\n", count); 650962306a36Sopenharmony_ci 651062306a36Sopenharmony_ci print_binder_stats(m, " ", &proc->stats); 651162306a36Sopenharmony_ci} 651262306a36Sopenharmony_ci 651362306a36Sopenharmony_cistatic int state_show(struct seq_file *m, void *unused) 651462306a36Sopenharmony_ci{ 651562306a36Sopenharmony_ci struct binder_proc *proc; 651662306a36Sopenharmony_ci struct binder_node *node; 651762306a36Sopenharmony_ci struct binder_node *last_node = NULL; 651862306a36Sopenharmony_ci 651962306a36Sopenharmony_ci seq_puts(m, "binder state:\n"); 652062306a36Sopenharmony_ci 652162306a36Sopenharmony_ci spin_lock(&binder_dead_nodes_lock); 652262306a36Sopenharmony_ci if (!hlist_empty(&binder_dead_nodes)) 652362306a36Sopenharmony_ci seq_puts(m, "dead nodes:\n"); 652462306a36Sopenharmony_ci hlist_for_each_entry(node, &binder_dead_nodes, dead_node) { 652562306a36Sopenharmony_ci /* 652662306a36Sopenharmony_ci * take a temporary reference on the node so it 652762306a36Sopenharmony_ci * survives and isn't removed from the list 652862306a36Sopenharmony_ci * while we print it. 652962306a36Sopenharmony_ci */ 653062306a36Sopenharmony_ci node->tmp_refs++; 653162306a36Sopenharmony_ci spin_unlock(&binder_dead_nodes_lock); 653262306a36Sopenharmony_ci if (last_node) 653362306a36Sopenharmony_ci binder_put_node(last_node); 653462306a36Sopenharmony_ci binder_node_lock(node); 653562306a36Sopenharmony_ci print_binder_node_nilocked(m, node); 653662306a36Sopenharmony_ci binder_node_unlock(node); 653762306a36Sopenharmony_ci last_node = node; 653862306a36Sopenharmony_ci spin_lock(&binder_dead_nodes_lock); 653962306a36Sopenharmony_ci } 654062306a36Sopenharmony_ci spin_unlock(&binder_dead_nodes_lock); 654162306a36Sopenharmony_ci if (last_node) 654262306a36Sopenharmony_ci binder_put_node(last_node); 654362306a36Sopenharmony_ci 654462306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 654562306a36Sopenharmony_ci hlist_for_each_entry(proc, &binder_procs, proc_node) 654662306a36Sopenharmony_ci print_binder_proc(m, proc, 1); 654762306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 654862306a36Sopenharmony_ci 654962306a36Sopenharmony_ci return 0; 655062306a36Sopenharmony_ci} 655162306a36Sopenharmony_ci 655262306a36Sopenharmony_cistatic int stats_show(struct seq_file *m, void *unused) 655362306a36Sopenharmony_ci{ 655462306a36Sopenharmony_ci struct binder_proc *proc; 655562306a36Sopenharmony_ci 655662306a36Sopenharmony_ci seq_puts(m, "binder stats:\n"); 655762306a36Sopenharmony_ci 655862306a36Sopenharmony_ci print_binder_stats(m, "", &binder_stats); 655962306a36Sopenharmony_ci 656062306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 656162306a36Sopenharmony_ci hlist_for_each_entry(proc, &binder_procs, proc_node) 656262306a36Sopenharmony_ci print_binder_proc_stats(m, proc); 656362306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 656462306a36Sopenharmony_ci 656562306a36Sopenharmony_ci return 0; 656662306a36Sopenharmony_ci} 656762306a36Sopenharmony_ci 656862306a36Sopenharmony_cistatic int transactions_show(struct seq_file *m, void *unused) 656962306a36Sopenharmony_ci{ 657062306a36Sopenharmony_ci struct binder_proc *proc; 657162306a36Sopenharmony_ci 657262306a36Sopenharmony_ci seq_puts(m, "binder transactions:\n"); 657362306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 657462306a36Sopenharmony_ci hlist_for_each_entry(proc, &binder_procs, proc_node) 657562306a36Sopenharmony_ci print_binder_proc(m, proc, 0); 657662306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 657762306a36Sopenharmony_ci 657862306a36Sopenharmony_ci return 0; 657962306a36Sopenharmony_ci} 658062306a36Sopenharmony_ci 658162306a36Sopenharmony_cistatic int proc_show(struct seq_file *m, void *unused) 658262306a36Sopenharmony_ci{ 658362306a36Sopenharmony_ci struct binder_proc *itr; 658462306a36Sopenharmony_ci int pid = (unsigned long)m->private; 658562306a36Sopenharmony_ci 658662306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 658762306a36Sopenharmony_ci hlist_for_each_entry(itr, &binder_procs, proc_node) { 658862306a36Sopenharmony_ci if (itr->pid == pid) { 658962306a36Sopenharmony_ci seq_puts(m, "binder proc state:\n"); 659062306a36Sopenharmony_ci print_binder_proc(m, itr, 1); 659162306a36Sopenharmony_ci } 659262306a36Sopenharmony_ci } 659362306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 659462306a36Sopenharmony_ci 659562306a36Sopenharmony_ci return 0; 659662306a36Sopenharmony_ci} 659762306a36Sopenharmony_ci 659862306a36Sopenharmony_cistatic void print_binder_transaction_log_entry(struct seq_file *m, 659962306a36Sopenharmony_ci struct binder_transaction_log_entry *e) 660062306a36Sopenharmony_ci{ 660162306a36Sopenharmony_ci int debug_id = READ_ONCE(e->debug_id_done); 660262306a36Sopenharmony_ci /* 660362306a36Sopenharmony_ci * read barrier to guarantee debug_id_done read before 660462306a36Sopenharmony_ci * we print the log values 660562306a36Sopenharmony_ci */ 660662306a36Sopenharmony_ci smp_rmb(); 660762306a36Sopenharmony_ci seq_printf(m, 660862306a36Sopenharmony_ci "%d: %s from %d:%d to %d:%d context %s node %d handle %d size %d:%d ret %d/%d l=%d", 660962306a36Sopenharmony_ci e->debug_id, (e->call_type == 2) ? "reply" : 661062306a36Sopenharmony_ci ((e->call_type == 1) ? "async" : "call "), e->from_proc, 661162306a36Sopenharmony_ci e->from_thread, e->to_proc, e->to_thread, e->context_name, 661262306a36Sopenharmony_ci e->to_node, e->target_handle, e->data_size, e->offsets_size, 661362306a36Sopenharmony_ci e->return_error, e->return_error_param, 661462306a36Sopenharmony_ci e->return_error_line); 661562306a36Sopenharmony_ci /* 661662306a36Sopenharmony_ci * read-barrier to guarantee read of debug_id_done after 661762306a36Sopenharmony_ci * done printing the fields of the entry 661862306a36Sopenharmony_ci */ 661962306a36Sopenharmony_ci smp_rmb(); 662062306a36Sopenharmony_ci seq_printf(m, debug_id && debug_id == READ_ONCE(e->debug_id_done) ? 662162306a36Sopenharmony_ci "\n" : " (incomplete)\n"); 662262306a36Sopenharmony_ci} 662362306a36Sopenharmony_ci 662462306a36Sopenharmony_cistatic int transaction_log_show(struct seq_file *m, void *unused) 662562306a36Sopenharmony_ci{ 662662306a36Sopenharmony_ci struct binder_transaction_log *log = m->private; 662762306a36Sopenharmony_ci unsigned int log_cur = atomic_read(&log->cur); 662862306a36Sopenharmony_ci unsigned int count; 662962306a36Sopenharmony_ci unsigned int cur; 663062306a36Sopenharmony_ci int i; 663162306a36Sopenharmony_ci 663262306a36Sopenharmony_ci count = log_cur + 1; 663362306a36Sopenharmony_ci cur = count < ARRAY_SIZE(log->entry) && !log->full ? 663462306a36Sopenharmony_ci 0 : count % ARRAY_SIZE(log->entry); 663562306a36Sopenharmony_ci if (count > ARRAY_SIZE(log->entry) || log->full) 663662306a36Sopenharmony_ci count = ARRAY_SIZE(log->entry); 663762306a36Sopenharmony_ci for (i = 0; i < count; i++) { 663862306a36Sopenharmony_ci unsigned int index = cur++ % ARRAY_SIZE(log->entry); 663962306a36Sopenharmony_ci 664062306a36Sopenharmony_ci print_binder_transaction_log_entry(m, &log->entry[index]); 664162306a36Sopenharmony_ci } 664262306a36Sopenharmony_ci return 0; 664362306a36Sopenharmony_ci} 664462306a36Sopenharmony_ci 664562306a36Sopenharmony_ciconst struct file_operations binder_fops = { 664662306a36Sopenharmony_ci .owner = THIS_MODULE, 664762306a36Sopenharmony_ci .poll = binder_poll, 664862306a36Sopenharmony_ci .unlocked_ioctl = binder_ioctl, 664962306a36Sopenharmony_ci .compat_ioctl = compat_ptr_ioctl, 665062306a36Sopenharmony_ci .mmap = binder_mmap, 665162306a36Sopenharmony_ci .open = binder_open, 665262306a36Sopenharmony_ci .flush = binder_flush, 665362306a36Sopenharmony_ci .release = binder_release, 665462306a36Sopenharmony_ci}; 665562306a36Sopenharmony_ci 665662306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(state); 665762306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(stats); 665862306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(transactions); 665962306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(transaction_log); 666062306a36Sopenharmony_ci 666162306a36Sopenharmony_ciconst struct binder_debugfs_entry binder_debugfs_entries[] = { 666262306a36Sopenharmony_ci { 666362306a36Sopenharmony_ci .name = "state", 666462306a36Sopenharmony_ci .mode = 0444, 666562306a36Sopenharmony_ci .fops = &state_fops, 666662306a36Sopenharmony_ci .data = NULL, 666762306a36Sopenharmony_ci }, 666862306a36Sopenharmony_ci { 666962306a36Sopenharmony_ci .name = "stats", 667062306a36Sopenharmony_ci .mode = 0444, 667162306a36Sopenharmony_ci .fops = &stats_fops, 667262306a36Sopenharmony_ci .data = NULL, 667362306a36Sopenharmony_ci }, 667462306a36Sopenharmony_ci { 667562306a36Sopenharmony_ci .name = "transactions", 667662306a36Sopenharmony_ci .mode = 0444, 667762306a36Sopenharmony_ci .fops = &transactions_fops, 667862306a36Sopenharmony_ci .data = NULL, 667962306a36Sopenharmony_ci }, 668062306a36Sopenharmony_ci { 668162306a36Sopenharmony_ci .name = "transaction_log", 668262306a36Sopenharmony_ci .mode = 0444, 668362306a36Sopenharmony_ci .fops = &transaction_log_fops, 668462306a36Sopenharmony_ci .data = &binder_transaction_log, 668562306a36Sopenharmony_ci }, 668662306a36Sopenharmony_ci { 668762306a36Sopenharmony_ci .name = "failed_transaction_log", 668862306a36Sopenharmony_ci .mode = 0444, 668962306a36Sopenharmony_ci .fops = &transaction_log_fops, 669062306a36Sopenharmony_ci .data = &binder_transaction_log_failed, 669162306a36Sopenharmony_ci }, 669262306a36Sopenharmony_ci {} /* terminator */ 669362306a36Sopenharmony_ci}; 669462306a36Sopenharmony_ci 669562306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 669662306a36Sopenharmony_cistatic void print_binder_transaction_brief_ilocked( 669762306a36Sopenharmony_ci struct seq_file *m, 669862306a36Sopenharmony_ci const char *prefix, struct binder_transaction *t, 669962306a36Sopenharmony_ci u64 timestamp) 670062306a36Sopenharmony_ci{ 670162306a36Sopenharmony_ci struct binder_proc *to_proc = NULL; 670262306a36Sopenharmony_ci int from_pid = 0; 670362306a36Sopenharmony_ci int from_tid = 0; 670462306a36Sopenharmony_ci int to_pid = 0; 670562306a36Sopenharmony_ci u64 sec; 670662306a36Sopenharmony_ci u32 nsec; 670762306a36Sopenharmony_ci 670862306a36Sopenharmony_ci spin_lock(&t->lock); 670962306a36Sopenharmony_ci to_proc = t->to_proc; 671062306a36Sopenharmony_ci from_pid = t->from ? (t->from->proc ? t->from->proc->pid : 0) : t->from_pid; 671162306a36Sopenharmony_ci from_tid = t->from ? t->from->pid : t->from_tid; 671262306a36Sopenharmony_ci to_pid = to_proc ? to_proc->pid : 0; 671362306a36Sopenharmony_ci sec = div_u64_rem((timestamp - t->timestamp), 1000000000, &nsec); 671462306a36Sopenharmony_ci 671562306a36Sopenharmony_ci seq_printf(m, 671662306a36Sopenharmony_ci "%s%d:%d to %d:%d code %x wait:%llu.%u s\n", 671762306a36Sopenharmony_ci prefix, 671862306a36Sopenharmony_ci from_pid, from_tid, 671962306a36Sopenharmony_ci to_pid, t->to_thread ? t->to_thread->pid : 0, 672062306a36Sopenharmony_ci t->code, 672162306a36Sopenharmony_ci timestamp > t->timestamp ? sec : 0, 672262306a36Sopenharmony_ci timestamp > t->timestamp ? nsec : 0); 672362306a36Sopenharmony_ci spin_unlock(&t->lock); 672462306a36Sopenharmony_ci} 672562306a36Sopenharmony_ci 672662306a36Sopenharmony_cistatic void print_binder_work_transaction_nilocked(struct seq_file *m, 672762306a36Sopenharmony_ci const char *prefix, struct binder_work *w, 672862306a36Sopenharmony_ci u64 timestamp) 672962306a36Sopenharmony_ci{ 673062306a36Sopenharmony_ci struct binder_transaction *t = NULL; 673162306a36Sopenharmony_ci 673262306a36Sopenharmony_ci switch (w->type) { 673362306a36Sopenharmony_ci case BINDER_WORK_TRANSACTION: 673462306a36Sopenharmony_ci t = container_of(w, struct binder_transaction, work); 673562306a36Sopenharmony_ci print_binder_transaction_brief_ilocked(m, prefix, t, timestamp); 673662306a36Sopenharmony_ci break; 673762306a36Sopenharmony_ci 673862306a36Sopenharmony_ci default: 673962306a36Sopenharmony_ci break; 674062306a36Sopenharmony_ci } 674162306a36Sopenharmony_ci} 674262306a36Sopenharmony_ci 674362306a36Sopenharmony_cistatic void print_binder_transaction_brief(struct seq_file *m, 674462306a36Sopenharmony_ci struct binder_proc *proc, 674562306a36Sopenharmony_ci u64 timestamp) 674662306a36Sopenharmony_ci{ 674762306a36Sopenharmony_ci struct binder_work *w = NULL; 674862306a36Sopenharmony_ci struct rb_node *n = NULL; 674962306a36Sopenharmony_ci struct binder_node *last_node = NULL; 675062306a36Sopenharmony_ci size_t start_pos = m->count; 675162306a36Sopenharmony_ci size_t header_pos = m->count; 675262306a36Sopenharmony_ci 675362306a36Sopenharmony_ci /* sync binder / not one way */ 675462306a36Sopenharmony_ci binder_inner_proc_lock(proc); 675562306a36Sopenharmony_ci for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { 675662306a36Sopenharmony_ci struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); 675762306a36Sopenharmony_ci struct binder_transaction *t = thread->transaction_stack; 675862306a36Sopenharmony_ci while (t) { 675962306a36Sopenharmony_ci if (t->from == thread) { 676062306a36Sopenharmony_ci print_binder_transaction_brief_ilocked(m, "\t", t, timestamp); 676162306a36Sopenharmony_ci t = t->from_parent; 676262306a36Sopenharmony_ci } else if (t->to_thread == thread) { 676362306a36Sopenharmony_ci t = t->to_parent; 676462306a36Sopenharmony_ci } else { 676562306a36Sopenharmony_ci t = NULL; 676662306a36Sopenharmony_ci } 676762306a36Sopenharmony_ci } 676862306a36Sopenharmony_ci } 676962306a36Sopenharmony_ci 677062306a36Sopenharmony_ci /* async binder / one way */ 677162306a36Sopenharmony_ci for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) { 677262306a36Sopenharmony_ci struct binder_node *node = rb_entry(n, struct binder_node, rb_node); 677362306a36Sopenharmony_ci /* 677462306a36Sopenharmony_ci * take a temporary reference on the node so it 677562306a36Sopenharmony_ci * survives and isn't removed from the tree 677662306a36Sopenharmony_ci * while we print it. 677762306a36Sopenharmony_ci */ 677862306a36Sopenharmony_ci binder_inc_node_tmpref_ilocked(node); 677962306a36Sopenharmony_ci /* Need to drop inner lock to take node lock */ 678062306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 678162306a36Sopenharmony_ci if (last_node) 678262306a36Sopenharmony_ci binder_put_node(last_node); 678362306a36Sopenharmony_ci binder_node_inner_lock(node); 678462306a36Sopenharmony_ci list_for_each_entry(w, &node->async_todo, entry) 678562306a36Sopenharmony_ci print_binder_work_transaction_nilocked(m, "async\t", w, timestamp); 678662306a36Sopenharmony_ci binder_node_inner_unlock(node); 678762306a36Sopenharmony_ci last_node = node; 678862306a36Sopenharmony_ci binder_inner_proc_lock(proc); 678962306a36Sopenharmony_ci } 679062306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 679162306a36Sopenharmony_ci 679262306a36Sopenharmony_ci if (last_node) 679362306a36Sopenharmony_ci binder_put_node(last_node); 679462306a36Sopenharmony_ci 679562306a36Sopenharmony_ci if (m->count == header_pos) 679662306a36Sopenharmony_ci m->count = start_pos; 679762306a36Sopenharmony_ci} 679862306a36Sopenharmony_ci 679962306a36Sopenharmony_cistatic void print_binder_proc_brief(struct seq_file *m, 680062306a36Sopenharmony_ci struct binder_proc *proc) 680162306a36Sopenharmony_ci{ 680262306a36Sopenharmony_ci struct binder_thread *thread = NULL; 680362306a36Sopenharmony_ci int ready_threads = 0; 680462306a36Sopenharmony_ci size_t free_async_space = binder_alloc_get_free_async_space(&proc->alloc); 680562306a36Sopenharmony_ci 680662306a36Sopenharmony_ci seq_printf(m, "%d\t", proc->pid); 680762306a36Sopenharmony_ci seq_printf(m, "%s\t", proc->context->name); 680862306a36Sopenharmony_ci 680962306a36Sopenharmony_ci binder_inner_proc_lock(proc); 681062306a36Sopenharmony_ci list_for_each_entry(thread, &proc->waiting_threads, waiting_thread_node) 681162306a36Sopenharmony_ci ready_threads++; 681262306a36Sopenharmony_ci 681362306a36Sopenharmony_ci seq_printf(m, "%d\t%d\t%d\t%d" 681462306a36Sopenharmony_ci "\t%zd\n", proc->requested_threads, 681562306a36Sopenharmony_ci proc->requested_threads_started, proc->max_threads, 681662306a36Sopenharmony_ci ready_threads, 681762306a36Sopenharmony_ci free_async_space); 681862306a36Sopenharmony_ci binder_inner_proc_unlock(proc); 681962306a36Sopenharmony_ci} 682062306a36Sopenharmony_ci 682162306a36Sopenharmony_cistatic int binder_transaction_proc_show(struct seq_file *m, void *unused) 682262306a36Sopenharmony_ci{ 682362306a36Sopenharmony_ci struct binder_proc *proc = NULL; 682462306a36Sopenharmony_ci u64 now = 0; 682562306a36Sopenharmony_ci 682662306a36Sopenharmony_ci mutex_lock(&binder_procs_lock); 682762306a36Sopenharmony_ci now = binder_clock(); 682862306a36Sopenharmony_ci hlist_for_each_entry(proc, &binder_procs, proc_node) 682962306a36Sopenharmony_ci print_binder_transaction_brief(m, proc, now); 683062306a36Sopenharmony_ci 683162306a36Sopenharmony_ci seq_printf(m, "\npid\tcontext\t\trequest\tstarted\tmax\tready\tfree_async_space\n"); 683262306a36Sopenharmony_ci hlist_for_each_entry(proc, &binder_procs, proc_node) 683362306a36Sopenharmony_ci print_binder_proc_brief(m, proc); 683462306a36Sopenharmony_ci mutex_unlock(&binder_procs_lock); 683562306a36Sopenharmony_ci 683662306a36Sopenharmony_ci return 0; 683762306a36Sopenharmony_ci} 683862306a36Sopenharmony_ci#endif 683962306a36Sopenharmony_ci 684062306a36Sopenharmony_cistatic int __init init_binder_device(const char *name) 684162306a36Sopenharmony_ci{ 684262306a36Sopenharmony_ci int ret; 684362306a36Sopenharmony_ci struct binder_device *binder_device; 684462306a36Sopenharmony_ci 684562306a36Sopenharmony_ci binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL); 684662306a36Sopenharmony_ci if (!binder_device) 684762306a36Sopenharmony_ci return -ENOMEM; 684862306a36Sopenharmony_ci 684962306a36Sopenharmony_ci binder_device->miscdev.fops = &binder_fops; 685062306a36Sopenharmony_ci binder_device->miscdev.minor = MISC_DYNAMIC_MINOR; 685162306a36Sopenharmony_ci binder_device->miscdev.name = name; 685262306a36Sopenharmony_ci 685362306a36Sopenharmony_ci refcount_set(&binder_device->ref, 1); 685462306a36Sopenharmony_ci binder_device->context.binder_context_mgr_uid = INVALID_UID; 685562306a36Sopenharmony_ci binder_device->context.name = name; 685662306a36Sopenharmony_ci mutex_init(&binder_device->context.context_mgr_node_lock); 685762306a36Sopenharmony_ci 685862306a36Sopenharmony_ci ret = misc_register(&binder_device->miscdev); 685962306a36Sopenharmony_ci if (ret < 0) { 686062306a36Sopenharmony_ci kfree(binder_device); 686162306a36Sopenharmony_ci return ret; 686262306a36Sopenharmony_ci } 686362306a36Sopenharmony_ci 686462306a36Sopenharmony_ci hlist_add_head(&binder_device->hlist, &binder_devices); 686562306a36Sopenharmony_ci 686662306a36Sopenharmony_ci return ret; 686762306a36Sopenharmony_ci} 686862306a36Sopenharmony_ci 686962306a36Sopenharmony_cistatic int __init binder_init(void) 687062306a36Sopenharmony_ci{ 687162306a36Sopenharmony_ci int ret; 687262306a36Sopenharmony_ci char *device_name, *device_tmp; 687362306a36Sopenharmony_ci struct binder_device *device; 687462306a36Sopenharmony_ci struct hlist_node *tmp; 687562306a36Sopenharmony_ci char *device_names = NULL; 687662306a36Sopenharmony_ci const struct binder_debugfs_entry *db_entry; 687762306a36Sopenharmony_ci 687862306a36Sopenharmony_ci ret = binder_alloc_shrinker_init(); 687962306a36Sopenharmony_ci if (ret) 688062306a36Sopenharmony_ci return ret; 688162306a36Sopenharmony_ci 688262306a36Sopenharmony_ci atomic_set(&binder_transaction_log.cur, ~0U); 688362306a36Sopenharmony_ci atomic_set(&binder_transaction_log_failed.cur, ~0U); 688462306a36Sopenharmony_ci 688562306a36Sopenharmony_ci binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); 688662306a36Sopenharmony_ci 688762306a36Sopenharmony_ci binder_for_each_debugfs_entry(db_entry) 688862306a36Sopenharmony_ci debugfs_create_file(db_entry->name, 688962306a36Sopenharmony_ci db_entry->mode, 689062306a36Sopenharmony_ci binder_debugfs_dir_entry_root, 689162306a36Sopenharmony_ci db_entry->data, 689262306a36Sopenharmony_ci db_entry->fops); 689362306a36Sopenharmony_ci 689462306a36Sopenharmony_ci binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", 689562306a36Sopenharmony_ci binder_debugfs_dir_entry_root); 689662306a36Sopenharmony_ci 689762306a36Sopenharmony_ci if (binder_debugfs_dir_entry_root) { 689862306a36Sopenharmony_ci#ifdef CONFIG_BINDER_TRANSACTION_PROC_BRIEF 689962306a36Sopenharmony_ci proc_create_data("transaction_proc", 690062306a36Sopenharmony_ci S_IRUGO, 690162306a36Sopenharmony_ci NULL, 690262306a36Sopenharmony_ci &binder_transaction_proc_proc_ops, 690362306a36Sopenharmony_ci NULL); 690462306a36Sopenharmony_ci#endif 690562306a36Sopenharmony_ci } 690662306a36Sopenharmony_ci 690762306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) && 690862306a36Sopenharmony_ci strcmp(binder_devices_param, "") != 0) { 690962306a36Sopenharmony_ci /* 691062306a36Sopenharmony_ci * Copy the module_parameter string, because we don't want to 691162306a36Sopenharmony_ci * tokenize it in-place. 691262306a36Sopenharmony_ci */ 691362306a36Sopenharmony_ci device_names = kstrdup(binder_devices_param, GFP_KERNEL); 691462306a36Sopenharmony_ci if (!device_names) { 691562306a36Sopenharmony_ci ret = -ENOMEM; 691662306a36Sopenharmony_ci goto err_alloc_device_names_failed; 691762306a36Sopenharmony_ci } 691862306a36Sopenharmony_ci 691962306a36Sopenharmony_ci device_tmp = device_names; 692062306a36Sopenharmony_ci while ((device_name = strsep(&device_tmp, ","))) { 692162306a36Sopenharmony_ci ret = init_binder_device(device_name); 692262306a36Sopenharmony_ci if (ret) 692362306a36Sopenharmony_ci goto err_init_binder_device_failed; 692462306a36Sopenharmony_ci } 692562306a36Sopenharmony_ci } 692662306a36Sopenharmony_ci 692762306a36Sopenharmony_ci ret = init_binderfs(); 692862306a36Sopenharmony_ci if (ret) 692962306a36Sopenharmony_ci goto err_init_binder_device_failed; 693062306a36Sopenharmony_ci 693162306a36Sopenharmony_ci return ret; 693262306a36Sopenharmony_ci 693362306a36Sopenharmony_cierr_init_binder_device_failed: 693462306a36Sopenharmony_ci hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) { 693562306a36Sopenharmony_ci misc_deregister(&device->miscdev); 693662306a36Sopenharmony_ci hlist_del(&device->hlist); 693762306a36Sopenharmony_ci kfree(device); 693862306a36Sopenharmony_ci } 693962306a36Sopenharmony_ci 694062306a36Sopenharmony_ci kfree(device_names); 694162306a36Sopenharmony_ci 694262306a36Sopenharmony_cierr_alloc_device_names_failed: 694362306a36Sopenharmony_ci debugfs_remove_recursive(binder_debugfs_dir_entry_root); 694462306a36Sopenharmony_ci binder_alloc_shrinker_exit(); 694562306a36Sopenharmony_ci 694662306a36Sopenharmony_ci return ret; 694762306a36Sopenharmony_ci} 694862306a36Sopenharmony_ci 694962306a36Sopenharmony_cidevice_initcall(binder_init); 695062306a36Sopenharmony_ci 695162306a36Sopenharmony_ci#define CREATE_TRACE_POINTS 695262306a36Sopenharmony_ci#include "binder_trace.h" 695362306a36Sopenharmony_ci 695462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 6955