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