Binder getCallingUid() getCallingPid() 返回?
??Android在进程间交互的时候,会使用Binder机制。在Binder交互过程中,通过Binder.getCallingUid()、Binder.getCallingPid()得到调用方的UID和进程PID。
@CriticalNative
public static final native int getCallingPid();
@CriticalNative
public static final native int getCallingUid();
??这俩函数的实现在android_util_Binder.cpp中
static jint android_os_Binder_getCallingPid()
{
return IPCThreadState::self()->getCallingPid();
}
static jint android_os_Binder_getCallingUid()
{
return IPCThreadState::self()->getCallingUid();
}
??IPCThreadState这个类对应着线程,
pid_t IPCThreadState::getCallingPid() const
{
checkContextIsBinderForUse(__func__);
return mCallingPid;
}
uid_t IPCThreadState::getCallingUid() const
{
checkContextIsBinderForUse(__func__);
return mCallingUid;
}
??所以现在就知道Binder.getCallingUid()、Binder.getCallingPid()得到的值了,就是对应的线程对应的IPCThreadState类对象的成员mCallingUid、mCallingPid的值。
mCallingUid mCallingPid在哪块赋值
Binder交互过程中协议命令
??要知道mCallingUid mCallingPid在哪块赋值,需要知道Binder交互过程。在这块只需要知道有关mCallingUid、mCallingPid相关的代码。
??在BC_TRANSACTION命令中如下代码:
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply,
binder_size_t extra_buffers_size)
{
…………
t->sender_euid = task_euid(proc->tsk);
…………
}
??其中t是binder_transaction指针,在这里将成员变量sender_euid 设置为调用进程的uid。在BC_TRANSACTION将事务数据设置完毕之后,会唤醒目标进程的线程进行处理相应事务,这块相关代码在binder_thread_read()中。
static int binder_thread_read(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed, int non_block)
{
…………
trd->code = t->code;
trd->flags = t->flags;
trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid);
t_from = binder_get_txn_from(t);
if (t_from) {
struct task_struct *sender = t_from->proc->tsk;
trd->sender_pid =
task_tgid_nr_ns(sender,
task_active_pid_ns(current));
trace_android_vh_sync_txn_recvd(thread->task, t_from->task);
} else {
trd->sender_pid = 0;
}
…………
}
??在这里是在目标线程里执行代码的,trd是binder_transaction_data类指针,将它的成员变量sender_euid设置为t->sender_euid,这块的t->sender_euid就是上面赋值的调用方进程的uid。sender是调用方的进程描述符,trd->sender_pid在这块设置成调用方进程的pid。然后设置完事务数据之后,将cmd设置为BR_TRANSACTION或者BR_TRANSACTION_SEC_CTX之后,返回到用户态进行处理。 ??用户态进程处理的代码如下:
status_t IPCThreadState::executeCommand(int32_t cmd)
{
…………
case BR_TRANSACTION_SEC_CTX:
case BR_TRANSACTION:
{
…………
const pid_t origPid = mCallingPid;
const char* origSid = mCallingSid;
const uid_t origUid = mCallingUid;
…………
mCallingPid = tr.sender_pid;
mCallingSid = reinterpret_cast<const char*>(tr_secctx.secctx);
mCallingUid = tr.sender_euid;
…………
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags);
…………
mCallingPid = origPid;
mCallingSid = origSid;
mCallingUid = origUid;
…………
break;
}
…………
}
??tr是binder_transaction_data对象,里面的数据就是在binder_thread_read()中设置的。在这里可以看到,在这里看到mCallingPid、mCallingUid被设置之后,就调用被调用对象的transact()方法。等到整个Bind处理完毕之后,就会将mCallingPid、mCallingUid设置为它们原来的值。
|