binder系列17-binder冻结-1-提交记录查阅
基于原生 Linux-6.13
freeze相关提交总共有:
e2610b268bb7 //2013年的提交,目前已经没有其痕迹了
7e20434cbca8
d579b04a52a1
432ff1e91694
ca63c66935b9
1db76ec2b4b2
ae28c1be1e54
595ea72efff9
cb2aeb2ec258
其中:
1. e2610b268bb7
binder: use freezable blocking calls
Avoid waking up every thread sleeping in a binder call during
suspend and resume by calling a freezable blocking call. Previous
patches modified the freezer to avoid sending wakeups to threads
that are blocked in freezable blocking calls.
This call was selected to be converted to a freezable call because
it doesn't hold any locks or release any resources when interrupted
that might be needed by another freezing task or a kernel driver
during suspend, and is a common site where idle userspace tasks are
blocked.
binder: use freezable blocking calls
2. 432ff1e91694
binder: BINDER_FREEZE ioctl
Frozen tasks can't process binder transactions, so a way is required to
inform transmitting ends of communication failures due to the frozen
state of their receiving counterparts. Additionally, races are possible
between transitions to frozen state and binder transactions enqueued to
a specific process.
Implement BINDER_FREEZE ioctl for user space to inform the binder driver
about the intention to freeze or unfreeze a process. When the ioctl is
called, block the caller until any pending binder transactions toward
the target process are flushed. Return an error to transactions to
processes marked as frozen.
小结: 执行 ioctl(BINDER_FREEZE) 传参 binder_freeze_info 结构,其各成员含义:
struct binder_freeze_info {
__u32 pid; //对此pid对应的所有 target_proc 进行操作
__u32 enable; //为false表示解冻,为true表示冻结
__u32 timeout_ms; //若是冻结会使用这个超时参数,超时后会自动唤醒
};
(1) 若 info->enable 为真,则会让PID指定的所有 target_proc 进行冻结,进入D状态,若指定了超时参数 info->timeout_ms
会等待超时或 target_proc->outstanding_txns = false 再冻结,此时会向所有感兴趣的客户端发送服务已冻结的通知。
(2) 若 info->enable 为假,则会对PID指定的所有 target_proc 进行解冻,并对所有客户端发送服务解冻通知。
3. ae28c1be1e54
binder: BINDER_GET_FROZEN_INFO ioctl
User space needs to know if binder transactions occurred to frozen
processes. Introduce a new BINDER_GET_FROZEN ioctl and keep track of
transactions occurring to frozen proceses.
就是获取 pid 对应的 target_proc 在被冻结期间是否又收到了同步/异步binder请求。
4. d579b04a52a1
binder: frozen notification
Frozen processes present a significant challenge in binder transactions.
When a process is frozen, it cannot, by design, accept and/or respond to
binder transactions. As a result, the sender needs to adjust its
behavior, such as postponing transactions until the peer process
unfreezes. However, there is currently no way to subscribe to these
state change events, making it impossible to implement frozen-aware
behaviors efficiently.
Introduce a binder API for subscribing to frozen state change events.
This allows programs to react to changes in peer process state,
mitigating issues related to binder transactions sent to frozen
processes.
Implementation details:
For a given binder_ref, the state of frozen notification can be one of
the followings:
1. Userspace doesn't want a notification. binder_ref->freeze is null.
2. Userspace wants a notification but none is in flight.
list_empty(&binder_ref->freeze->work.entry) = true
3. A notification is in flight and waiting to be read by userspace.
binder_ref_freeze.sent is false.
4. A notification was read by userspace and kernel is waiting for an ack.
binder_ref_freeze.sent is true.
When a notification is in flight, new state change events are coalesced into
the existing binder_ref_freeze struct. If userspace hasn't picked up the
notification yet, the driver simply rewrites the state. Otherwise, the
notification is flagged as requiring a resend, which will be performed
once userspace acks the original notification that's inflight.
See https://r.android.com/3070045 for how userspace is going to use this
feature. //注: 这里是libbinder库的实现。
binder_thread_write
case BC_REQUEST_FREEZE_NOTIFICATION:
binder_request_freeze_notification //[1]
case BC_CLEAR_FREEZE_NOTIFICATION:
binder_clear_freeze_notification //[2]
case BC_FREEZE_NOTIFICATION_DONE:
binder_freeze_notification_done //[3]
[1] 和注册死亡通知一样的操作,注册通知时,同时就可以获取当前状态。
[2] 取消注册freeze通知,取消注册的用户会立即收到 BR_CLEAR_FREEZE_NOTIFICATION_DONE 数据。
[3] 完成通知之后的。
5. 7e20434cbca8
binder: fix freeze UAF in binder_release_work()
When a binder reference is cleaned up, any freeze work queued in the
associated process should also be removed. Otherwise, the reference is
freed while its ref->freeze.work is still queued in proc->work leading
to a use-after-free issue as shown by the following KASAN report:
binder_cleanup_ref_olocked: ref->freeze->work 是挂在 ref->proc 的 todo 链表上的。
6. 830d7db744b4
binder: fix BINDER_WORK_FROZEN_BINDER debug logs
The BINDER_WORK_FROZEN_BINDER type is not handled in the binder_logs
entries and it shows up as "unknown work" when logged:
proc 649
context binder-test
thread 649: l 00 need_return 0 tr 0
ref 13: desc 1 node 8 s 1 w 0 d 0000000053c4c0c3
unknown work: type 10
This patch add the freeze work type and is now logged as such:
proc 637
context binder-test
thread 637: l 00 need_return 0 tr 0
ref 8: desc 1 node 3 s 1 w 0 d 00000000dc39e9c6
has frozen binder
7. 595ea72efff9
binder: fix BINDER_WORK_CLEAR_FREEZE_NOTIFICATION debug logs
proc 699
context binder-test
thread 699: l 00 need_return 0 tr 0
ref 25: desc 1 node 20 s 1 w 0 d 00000000c03e09a3
unknown work: type 11
proc 640
context binder-test
thread 640: l 00 need_return 0 tr 0
ref 8: desc 1 node 3 s 1 w 0 d 000000002bb493e1
has cleared freeze notification
Fixes: d579b04a52a1 ("binder: frozen notification")
8. ca63c66935b9
binder: allow freeze notification for dead nodes
Alice points out that binder_request_freeze_notification() should not
return EINVAL when the relevant node is dead [1]. The node can die at
any point even if the user input is valid. Instead, allow the request
to be allocated but skip the initial notification for dead nodes. This
avoids propagating unnecessary errors back to userspace.
9. 1db76ec2b4b2
binder: fix memleak of proc->delivered_freeze
If a freeze notification is cleared with BC_CLEAR_FREEZE_NOTIFICATION
before calling binder_freeze_notification_done(), then it is detached
from its reference (e.g. ref->freeze) but the work remains queued in
proc->delivered_freeze. This leads to a memory leak when the process
exits as any pending entries in proc->delivered_freeze are not freed:
unreferenced object 0xffff38e8cfa36180 (size 64):
comm "binder-util", pid 655, jiffies 4294936641
hex dump (first 32 bytes):
b8 e9 9e c8 e8 38 ff ff b8 e9 9e c8 e8 38 ff ff .....8.......8..
0b 00 00 00 00 00 00 00 3c 1f 4b 00 00 00 00 00 ........<.K.....
backtrace (crc 95983b32):
[<000000000d0582cf>] kmemleak_alloc+0x34/0x40
[<000000009c99a513>] __kmalloc_cache_noprof+0x208/0x280
[<00000000313b1704>] binder_thread_write+0xdec/0x439c
[<000000000cbd33bb>] binder_ioctl+0x1b68/0x22cc
[<000000002bbedeeb>] __arm64_sys_ioctl+0x124/0x190
[<00000000b439adee>] invoke_syscall+0x6c/0x254
[<00000000173558fc>] el0_svc_common.constprop.0+0xac/0x230
[<0000000084f72311>] do_el0_svc+0x40/0x58
[<000000008b872457>] el0_svc+0x38/0x78
[<00000000ee778653>] el0t_64_sync_handler+0x120/0x12c
[<00000000a8ec61bf>] el0t_64_sync+0x190/0x194
This patch fixes the leak by ensuring that any pending entries in
proc->delivered_freeze are freed during binder_deferred_release().
10. cb2aeb2ec258
binder: add delivered_freeze to debugfs output
Add the pending proc->delivered_freeze work to the debugfs output. This
information was omitted in the original implementation of the freeze
notification and can be valuable for debugging issues.
Fixes: d579b04a52a1 ("binder: frozen notification")
总结
这些补丁提供了,可以通过 ioctl(BINDER_FREEZE) 设置一个进程被冻结或取消冻结,此时这个进程会收到自己被冻结或解冻的通知,接收到的命令是 BR_FROZEN_BINDER.
各个业务也可以通过 ioctl(BC_REQUEST_FREEZE_NOTIFICATION)/ioctl(BC_CLEAR_FREEZE_NOTIFICATION) 注册服务冻结/解冻通知,也是收到 BR_FROZEN_BINDER 类型的通知。
注: 目前只看了个大概,以后用到了再细看。
注: 检索 BINDER_FREEZE 只有msm-5.4内核才开始带入binder冻结的。
posted on 2025-03-24 21:16 Hello-World3 阅读(170) 评论(0) 收藏 举报