diff --git a/drivers/android/binder.c b/drivers/android/binder.c index daae755d0ddb..b28b56e6e4a2 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2851,9 +2851,28 @@ static void binder_transaction(struct binder_proc *proc, if (target_node && target_node->txn_security_ctx) { u32 secid; size_t added_size; + int max_retries = 100; security_task_getsecid(proc->tsk, &secid); + retry_alloc: 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) { return_error = BR_FAILED_REPLY; return_error_param = ret;