From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Carlos Llamas <cmllamas@google.com>
Cc: "Arve Hjønnevåg" <arve@android.com>,
"Todd Kjos" <tkjos@android.com>,
"Martijn Coenen" <maco@android.com>,
"Joel Fernandes" <joel@joelfernandes.org>,
"Christian Brauner" <brauner@kernel.org>,
"Hridya Valsaraju" <hridya@google.com>,
"Suren Baghdasaryan" <surenb@google.com>,
"Arnd Bergmann" <arnd@arndb.de>,
"Masahiro Yamada" <masahiroy@kernel.org>,
"Li Li" <dualli@google.com>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] binder: add BINDER_GET_EXTENDED_ERROR ioctl
Date: Fri, 22 Apr 2022 17:25:07 +0200 [thread overview]
Message-ID: <YmLI03OT6st9fcQD@kroah.com> (raw)
In-Reply-To: <20220421042040.759068-1-cmllamas@google.com>
On Thu, Apr 21, 2022 at 04:20:36AM +0000, Carlos Llamas wrote:
> Provide a userspace mechanism to pull precise error information upon
> failed operations. Extending the current error codes returned by the
> interfaces allows userspace to better determine the course of action.
> This could be for instance, retrying a failed transaction at a later
> point and thus offloading the error handling from the driver.
>
> Some of the elements for logging failed transactions and similar are
> folded into this new logic to avoid duplication. Such is the case for
> error line numbers, which become irrelevant after assigning individual
> error messages instead.
>
> This patch also adds BINDER_GET_EXTENDED_ERROR to the binderfs feature
> list, to help userspace determine if the new ioctl is supported by the
> driver.
Hint, when you say "also" in a changelog text, that's a hint that this
should be more than one patch. The last thing should be a separate
change, right?
>
> Signed-off-by: Carlos Llamas <cmllamas@google.com>
> ---
> drivers/android/binder.c | 355 +++++++++++++++-------------
> drivers/android/binder_internal.h | 9 +-
> drivers/android/binderfs.c | 8 +
> include/uapi/linux/android/binder.h | 16 ++
> 4 files changed, 219 insertions(+), 169 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 8351c5638880..42a324634f25 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2697,6 +2697,54 @@ static struct binder_node *binder_get_node_refs_for_txn(
> return target_node;
> }
>
> +#define binder_txn_error(x...) binder_transaction_error(0, x)
> +#define binder_user_txn_error(x...) binder_transaction_error(1, x)
> +static __printf(6, 7) void binder_transaction_error(int user,
> + struct binder_transaction_log_entry *e,
> + struct binder_extended_error *ee,
> + uint32_t command, int32_t param,
> + const char *format, ...)
> +{
> + struct va_format vaf;
> + va_list args;
> +
> + /* don't override previous error */
> + if (command != BR_OK && ee->command != BR_OK)
> + return;
> +
> + ee->command = command;
> + ee->param = param;
> +
> + va_start(args, format);
> + vsnprintf(e->strerr, sizeof(e->strerr), format, args);
> +
> + vaf.va = &args;
> + vaf.fmt = format;
> + if (user)
> + binder_user_error("%d:%d %pV\n",
> + e->from_proc, e->from_thread, &vaf);
> + else
> + binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, "%d:%d %pV\n",
> + e->from_proc, e->from_thread, &vaf);
> + va_end(args);
> +}
> +
> +static void binder_set_txn_from_error(struct binder_transaction *txn,
> + struct binder_extended_error *ee)
> +{
> + struct binder_thread *from = binder_get_txn_from_and_acq_inner(txn);
> +
> + if (!from)
> + return;
> +
> + /* don't override previous error */
> + if (ee->command != BR_OK && from->ee.command == BR_OK)
> + from->ee = *ee;
> +
> + binder_inner_proc_unlock(from->proc);
> + binder_thread_dec_tmpref(from);
> +}
> +
> static void binder_transaction(struct binder_proc *proc,
> struct binder_thread *thread,
> struct binder_transaction_data *tr, int reply,
> @@ -2716,9 +2764,8 @@ static void binder_transaction(struct binder_proc *proc,
> struct binder_node *target_node = NULL;
> struct binder_transaction *in_reply_to = NULL;
> struct binder_transaction_log_entry *e;
> + struct binder_extended_error ee;
> uint32_t return_error = 0;
> - uint32_t return_error_param = 0;
> - uint32_t return_error_line = 0;
> binder_size_t last_fixup_obj_off = 0;
> binder_size_t last_fixup_min_off = 0;
> struct binder_context *context = proc->context;
> @@ -2741,32 +2788,30 @@ static void binder_transaction(struct binder_proc *proc,
> e->data_size = tr->data_size;
> e->offsets_size = tr->offsets_size;
> strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME);
> + ee.id = t_debug_id;
> + ee.command = BR_OK;
> + ee.param = 0;
>
> if (reply) {
> binder_inner_proc_lock(proc);
> in_reply_to = thread->transaction_stack;
> if (in_reply_to == NULL) {
> binder_inner_proc_unlock(proc);
> - binder_user_error("%d:%d got reply transaction with no transaction stack\n",
> - proc->pid, thread->pid);
> - return_error = BR_FAILED_REPLY;
> - return_error_param = -EPROTO;
> - return_error_line = __LINE__;
> + binder_user_txn_error(e, &ee, BR_FAILED_REPLY, -EPROTO,
> + "reply with no transaction stack");
> goto err_empty_call_stack;
> }
> if (in_reply_to->to_thread != thread) {
> spin_lock(&in_reply_to->lock);
> - binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n",
> - proc->pid, thread->pid, in_reply_to->debug_id,
> + binder_user_txn_error(e, &ee, BR_FAILED_REPLY, -EPROTO,
> + "bad transaction stack in reply to %d %d:%d",
> + in_reply_to->debug_id,
> in_reply_to->to_proc ?
> in_reply_to->to_proc->pid : 0,
> in_reply_to->to_thread ?
> in_reply_to->to_thread->pid : 0);
> spin_unlock(&in_reply_to->lock);
> binder_inner_proc_unlock(proc);
> - return_error = BR_FAILED_REPLY;
> - return_error_param = -EPROTO;
> - return_error_line = __LINE__;
> in_reply_to = NULL;
> goto err_bad_call_stack;
> }
> @@ -2777,20 +2822,17 @@ static void binder_transaction(struct binder_proc *proc,
> if (target_thread == NULL) {
> /* annotation for sparse */
> __release(&target_thread->proc->inner_lock);
> - return_error = BR_DEAD_REPLY;
> - return_error_line = __LINE__;
> + binder_txn_error(e, &ee, BR_DEAD_REPLY, 0,
> + "reply target not found");
> goto err_dead_binder;
> }
> if (target_thread->transaction_stack != in_reply_to) {
> - binder_user_error("%d:%d got reply transaction with bad target transaction stack %d, expected %d\n",
> - proc->pid, thread->pid,
> + binder_user_txn_error(e, &ee, BR_FAILED_REPLY, -EPROTO,
> + "bad target transaction stack %d vs %d",
> target_thread->transaction_stack ?
> target_thread->transaction_stack->debug_id : 0,
> in_reply_to->debug_id);
> binder_inner_proc_unlock(target_thread->proc);
> - return_error = BR_FAILED_REPLY;
> - return_error_param = -EPROTO;
> - return_error_line = __LINE__;
> in_reply_to = NULL;
> target_thread = NULL;
> goto err_dead_binder;
> @@ -2812,15 +2854,15 @@ static void binder_transaction(struct binder_proc *proc,
> binder_proc_lock(proc);
> ref = binder_get_ref_olocked(proc, tr->target.handle,
> true);
> - if (ref) {
> + if (ref)
> target_node = binder_get_node_refs_for_txn(
> ref->node, &target_proc,
> &return_error);
> - } else {
> - binder_user_error("%d:%d got transaction to invalid handle, %u\n",
> - proc->pid, thread->pid, tr->target.handle);
> - return_error = BR_FAILED_REPLY;
> - }
> + else
> + binder_user_txn_error(e, &ee, BR_FAILED_REPLY,
> + -EINVAL,
> + "invalid transaction handle %u",
> + tr->target.handle);
> binder_proc_unlock(proc);
> } else {
> mutex_lock(&context->context_mgr_node_lock);
> @@ -2833,11 +2875,9 @@ static void binder_transaction(struct binder_proc *proc,
> return_error = BR_DEAD_REPLY;
> mutex_unlock(&context->context_mgr_node_lock);
> if (target_node && target_proc->pid == proc->pid) {
> - binder_user_error("%d:%d got transaction to context manager from process owning it\n",
> - proc->pid, thread->pid);
> - return_error = BR_FAILED_REPLY;
> - return_error_param = -EINVAL;
> - return_error_line = __LINE__;
> + binder_user_txn_error(e, &ee, BR_FAILED_REPLY,
> + -EINVAL,
> + "forbidden self transaction by context manager");
> goto err_invalid_target_handle;
> }
> }
> @@ -2845,22 +2885,20 @@ static void binder_transaction(struct binder_proc *proc,
> /*
> * return_error is set above
> */
> - return_error_param = -EINVAL;
> - return_error_line = __LINE__;
> + binder_txn_error(e, &ee, return_error, -EINVAL,
> + "cannot find target node");
You do this a lot, how about making this one commit (first one), and
then adding the new "back end" to the error stuff in a second commit.
That would make it much easier to review, first commit does nothing new,
second one adds the new functionality, and third adds the feature flag.
thanks,
greg k-h
next prev parent reply other threads:[~2022-04-22 15:25 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-21 4:20 [PATCH] binder: add BINDER_GET_EXTENDED_ERROR ioctl Carlos Llamas
2022-04-22 15:25 ` Greg Kroah-Hartman [this message]
2022-04-22 16:01 ` Carlos Llamas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YmLI03OT6st9fcQD@kroah.com \
--to=gregkh@linuxfoundation.org \
--cc=arnd@arndb.de \
--cc=arve@android.com \
--cc=brauner@kernel.org \
--cc=cmllamas@google.com \
--cc=dualli@google.com \
--cc=hridya@google.com \
--cc=joel@joelfernandes.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maco@android.com \
--cc=masahiroy@kernel.org \
--cc=surenb@google.com \
--cc=tkjos@android.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.