ANDROID: binder: retry security_secid_to_secctx()

security_secid_to_secctx() can fail because of a GFP_ATOMIC allocation
This needs to be retried from userspace. However, binder driver doesn't
propagate specific enough error codes just yet (WIP b/28321379). We'll
retry on the binder driver as a temporary work around until userspace
can do this instead.

Bug: 174806915
Signed-off-by: Carlos Llamas <cmllamas@google.com>
Change-Id: Ifebddeb7adf9707613512952b97ab702f0d2d592
This commit is contained in:
Carlos Llamas
2021-07-20 17:23:46 +00:00
parent 9fdfeda4c9
commit 3bca0b5344

View File

@@ -2851,9 +2851,28 @@ static void binder_transaction(struct binder_proc *proc,
if (target_node && target_node->txn_security_ctx) { if (target_node && target_node->txn_security_ctx) {
u32 secid; u32 secid;
size_t added_size; size_t added_size;
int max_retries = 100;
security_task_getsecid(proc->tsk, &secid); security_task_getsecid(proc->tsk, &secid);
retry_alloc:
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
if (ret == -ENOMEM && max_retries-- > 0) {
struct page *dummy_page;
/*
* security_secid_to_secctx() can fail because of a
* GFP_ATOMIC allocation in which case -ENOMEM is
* returned. This needs to be retried, but there is
* currently no way to tell userspace to retry so we
* do it here. We make sure there is still available
* memory first and then retry.
*/
dummy_page = alloc_page(GFP_KERNEL);
if (dummy_page) {
__free_page(dummy_page);
goto retry_alloc;
}
}
if (ret) { if (ret) {
return_error = BR_FAILED_REPLY; return_error = BR_FAILED_REPLY;
return_error_param = ret; return_error_param = ret;