引言:大家都知道知名意大利天才少年Luca放出来的针对owningTask.n11ame);
RetCode = is_io_service_open_extended(
service,
owningTask,
In0P->connect_type,
In0P->ndr,
(io_buf_ptr_t)(In0P->properties.address),
In0P->propertiesCnt, &OutP->result, &connection);
task_deallocate(owningTask);
...
}
内核已经把所有包含在消息中的权限复制进来,所以In0P->owningTask.name 实际上是指向一个struct ipc_port的指针,而不是用户态看到的mach端口名。
下面是convert_port_to_task:
task_t
convert_port_to_task(
ipc_port_t port)
{
task_t task = TASK_NULL;
if (IP_VALID(port)) {
ip_lock(port);
if (ip_active(port) &&
ip_kotype(port) == IKOT_TASK)
{
task = (task_t)port->ip_kobject;
assert(task != TASK_NULL);
task_reference_internal(task);
}
ip_unlock(port);
}
return (task);
}
它检查了port参数,确保是一个任务端口对象,然后通过调用task_reference来对任务提供引用,返回task_t指针。task_t是对struct task指针的别名,从代码中可以看出,它是一个引用计数对象。
这里is_is_service_open_extended仅仅是将owningTask传给::newUserClient:
res = service->newUserClient(
owningTask,
(void *) owningTask,
connect_type,
propertiesDict,
&client );
newUserClient是一个IOService方法,如果它们想提供多userclient类型,它可以被一个IOService覆盖。否则默认执行在IOKit记录中查询IOService的IOUserClient子类类名,通过IOKit的反射API(链接:https://bugs.chromium.org/p/project-zero/issues/detail?id=221)分配它,并调用它的::initWithTask方法。::initWithTask的默认执行流也不对owningTask做任何处理。
查看代码到此,似乎默认情况下owningTask并不会保有对userclient的引用(这会避免userclient对任务进行引用,形成循环引用,事实却完全相反;如果userclient想要保持对owningTask的引用,它必须对owningTask进行引用——不存在隐式的所属关系。
译者:ruanbonan
原文链接:https://googleprojectzero.blogspot.kr/2016/10/taskt-considered-harmful.html
原文作者:lan Beer,Project Zero
微信公众号:看雪iOS安全小组 我们的微博:http://weibo.com/pediyiosteam
我们的知乎:http://zhihu.com/people/pediyiosteam
加入我们:看雪iOS安全小组成员募集中:http://bbs.pediy.com/showthread.php?t=212949
[看雪iOS安全小组]置顶向导集合贴: http://bbs.pediy.com/showthread.php?t=212685
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |