Модифицированный код binder.c, основанный на этом.
https://github.com/S3NEO/android_kernel_samsung_s3ve3g/blob/24c9b3454fddc6a5b332989cb4f4455c21867a42/drivers/staging/android/binder.c#L3222
Я хочу напечатать двусвязный список task_list:
static int binder_free_thread(struct binder_proc *proc,
struct binder_thread *thread)
{
struct binder_transaction *t;
struct binder_transaction *send_reply = NULL;
int active_transactions = 0;
static const size_t memberOffset = offsetof(binder_thread, wait);
wait_queue_head_t *wqhptr = &thread->wait;
struct list_head *n1,*p1;
wait_queue_head_t *my2;
printk(KERN_INFO "iovec str size:%d",sizeof(iovec));
printk(KERN_INFO "thread->task_list:%p",(void *)&wqhptr->task_list);
list_for_each_safe(p1,n1, &wqhptr->task_list){
my2 = list_entry(p1, wait_queue_head_t, task_list);
printk (KERN_INFO "my2 t= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
}
Это должно быть wait_queueглава списка, поэтому я бы предположил, что он должен содержать записи .... однако он ничего не показывает?
Вопросы:
- Как его заполнить?
- Почему он пуст?
К вашему сведению Указатель & wqhptr-> task_list указывает на некоторую память.
Запуск кода:
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define BINDER_THREAD_EXIT 0x40046208ul
int main()
{
int fd, epfd;
struct epoll_event event = { .events = EPOLLIN };
fd = open("/dev/binder0", O_RDONLY);
epfd = epoll_create(1000);
epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
ioctl(fd, BINDER_THREAD_EXIT, NULL);
}
Это связано с этим:
https://bugs.chromium.org/p/project-zero/issues/detail?id=1942
Вот исходный код ядра, с которым я работаю (доступен для поиска через GitHub):
https://github.com/S3NEO/android_kernel_samsung_s3ve3g/
Обновление 1:
static void ep_remove_wait_queue(struct eppoll_entry *pwq)
{
wait_queue_head_t *whead;
wait_queue_t *strptr;
struct list_head *n1,*p1;
wait_queue_t *my2;
rcu_read_lock();
/* If it is cleared by POLLFREE, it should be rcu-safe */
whead = rcu_dereference(pwq->whead);
if (whead)
{
strptr=&pwq->wait;
list_for_each_safe(p1,n1, &strptr->task_list){
my2 = list_entry(p1, wait_queue_t, task_list);
printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
}
Эта одна печатает записи.
Я, хотя thread-> wait, будет таким же, как & pwq-> wait ..... это?
Вопросы:
- да или нет?
- как заполнить нить-> ждать от Binder, чтобы иметь записи и чтобы они соответствовали & pwq-> waitТак как это должно произойти, после использования Free ....
Спасибо,
Обновление 2:
static void ep_remove_wait_queue(struct eppoll_entry *pwq)
{
wait_queue_head_t *whead;
wait_queue_t *strptr;
struct list_head *n1,*p1;
wait_queue_t *my2;
rcu_read_lock();
/* If it is cleared by POLLFREE, it should be rcu-safe */
whead = rcu_dereference(pwq->whead);
printk(KERN_INFO "whead before");
if (whead)
{
strptr=&pwq->wait;
list_for_each_safe(p1,n1, &pwq->whead){
my2 = list_entry(p1, wait_queue_t, task_list);
printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
}
Должно быть вышенапечатайте это чем?
Спасибо,
Обновление 3:
static void ep_remove_wait_queue(struct eppoll_entry *pwq)
{
wait_queue_head_t *whead;
wait_queue_t *strptr;
struct list_head *n1,*p1;
wait_queue_t *my2;
rcu_read_lock();
/* If it is cleared by POLLFREE, it should be rcu-safe */
whead = rcu_dereference(pwq->whead);
printk(KERN_INFO "whead before");
if (whead)
{
strptr=&pwq->wait;
list_for_each_safe(p1,n1, &pwq->whead->task_list){
my2 = list_entry(p1, wait_queue_t, task_list);
printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
}
Попытка выше ... Recompinig ...
Обновление 4:
binder.c
static int binder_free_thread(struct binder_proc *proc,
struct binder_thread *thread)
{
struct binder_transaction *t;
struct binder_transaction *send_reply = NULL;
int active_transactions = 0;
static const size_t memberOffset = offsetof(binder_thread, wait);
wait_queue_head_t *wqhptr = &thread->wait;
wait_queue_head_t *pwqhptr = &proc->wait;
struct list_head *n1,*p1;
wait_queue_t *my2;
printk(KERN_INFO "iovec str size:%d",sizeof(iovec));
printk(KERN_INFO "thread->task_list:%p",(void *)&wqhptr->task_list);
printk(KERN_INFO "proc->task_list:%p",(void *)&pwqhptr->task_list);
list_for_each_safe(p1,n1, &pwqhptr->task_list){
my2 = list_entry(p1, wait_queue_t, task_list);
printk (KERN_INFO "p list= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
}
list_for_each_safe(p1,n1, &wqhptr->task_list){
my2 = list_entry(p1, wait_queue_t, task_list);
printk (KERN_INFO "t list= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
}
eventpoll.c
static void ep_remove_wait_queue(struct eppoll_entry *pwq)
{
wait_queue_head_t *whead;
wait_queue_t *strptr;
struct list_head *n1,*p1;
wait_queue_t *my2;
rcu_read_lock();
/* If it is cleared by POLLFREE, it should be rcu-safe */
whead = rcu_dereference(pwq->whead);
printk(KERN_INFO "whead before");
if (whead)
{
strptr=&pwq->wait;
list_for_each_safe(p1,n1, &pwq->whead->task_list){
my2 = list_entry(p1, wait_queue_t, task_list);
printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
}
remove_wait_queue(whead, &pwq->wait);
printk(KERN_INFO "remove wait queue:%p", (void*)&pwq->wait);
printk(KERN_INFO "remove wait queue task list:%p", (void*)&strptr->task_list);
Я вижу список принтеровТед ..... но во время загрузки Android не мой PoC:
Во время запуска Android
[ 84.747753] binder_ioctl: 1878:2371 40046208 0
[ 84.747765] iovec str size:8
[ 84.747771] thread->task_list:e4fb2e30
[ 84.747777] proc->task_list:e57d866c
[ 84.747784] p list= e57d866c e7fffe7c
[ 84.747790] p list= e656de7c e57d866c
[ 84.747797] binder_free_thread size:252 worker_off:44
[ 84.747804] freed thread:e4fb2e00
Я вижу, proc-> task_list ... повлияет ли free () 0xe4fb2e00 на это?
Мой PoC:
[ 642.254192] wq queue:e7ce8798
[ 642.254201] epoll struct:e7ce8780
[ 642.254214] wq queue:e7ce8f98
[ 642.254220] epoll struct:e7ce8f80
[ 642.254230] wq queue:e7ce8718
[ 642.254236] epoll struct:e7ce8700
[ 642.254266] binder_ioctl: 7392:7392 40046208 0
[ 642.254274] iovec str size:8
[ 642.254280] thread->task_list:e5389b30
[ 642.254286] proc->task_list:c309d86c
[ 642.254292] binder_free_thread size:252 worker_off:44
[ 642.254299] freed thread:e5389b00
[ 642.254736] ep_unregister_pollwait struct:e7ce8780 epi struct:e51d0480
[ 642.254792] ep_unregister_pollwait struct:e7ce8f80 epi struct:e51d0a80
[ 642.254799] ep_unregister_pollwait list not empty
[ 642.254805] whead before
[ 642.254811] my2= c0f50cc4 c0f50cc4
[ 642.254817] remove wait queue:e734b994
[ 642.254823] remove wait queue task list:e734b9a0
[ 642.254830] ep_unregister_pollwait list not empty
[ 642.254835] whead before
[ 642.254841] my2= c0f50cd0 c0f50cd0
[ 642.254847] remove wait queue:e734bb24
[ 642.254852] remove wait queue task list:e734bb30
[ 642.254863] ep_free
[ 642.254873] ep_free
[ 642.254881] ep_free
Мой PoC:
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#define BINDER_THREAD_EXIT 0x40046208ul
#define BINDER_VERSION 0xc0046209ul
int main()
{
int fd,fd1,fd2, epfd,epfd1,epfd2;
struct epoll_event event = { .events = EPOLLOUT };
fd = open("/dev/binder", O_RDONLY);
fd1 = open("/dev/random", O_RDONLY);
epfd = epoll_create(1000);
epfd1 = epoll_create(1000);
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event)) err(1, "epoll_add");
if (epoll_ctl(epfd1, EPOLL_CTL_ADD, fd1, &event)) err(1, "epoll_add");
//ioctl(fd, BINDER_VERSION, NULL);
ioctl(fd, BINDER_THREAD_EXIT, NULL);
printf("Finished here.");
}
У кого-нибудь есть идеи, почему?
Обновление 5:
Я сузил его ... поэтому я хочу повторить поведение com.cyanogenmod.lockclock
Он ведет себя так, как я хочу, чтобы он увидел:
s3ve3g:/ # ps | grep 2140
u0_a50 2140 257 845744 36336 sys_epoll_ b4ed9114 S com.cyanogenmod.lockclock
Источник:
https://github.com/LineageOS/android_packages_apps_LockClock
[ 53.617686] binder_ioctl: 2140:2401 40046208 0
[ 53.617697] iovec str size:8
[ 53.617704] thread->task_list:e5b2c030
[ 53.617710] proc->task_list:e609206c
[ 53.617716] p list= e609206c e50c3e7c
[ 53.617722] p list= e50c5e7c e609206c
[ 53.617729] binder_free_thread size:252 worker_off:44
[ 53.617736] freed thread:e5b2c000
[ 53.617755] ep_unregister_pollwait struct:e5f5c680 epi struct:e5f4c280
[ 53.617762] ep_unregister_pollwait list not empty
[ 53.617768] whead before
[ 53.617773] my2= e8b10308 e8b10308
[ 53.617779] remove wait queue:e5fd755c
[ 53.617785] remove wait queue task list:e5fd7568
[ 53.617803] ep_free
Я думаю, что здесь используется Binder:
https://github.com/LineageOS/android_packages_apps_LockClock/blob/5239d22272aa2b7a2bcf2c45482395da3e163289/src/org/lineageos/lockclock/DeviceStatusService.java
Есть идеи, как повторить это, используя C (собственный) код?