|
74 | 74 |
|
75 | 75 | #include <linux/cacheflush.h> |
76 | 76 |
|
| 77 | +#include "binder_netlink.h" |
77 | 78 | #include "binder_internal.h" |
78 | 79 | #include "binder_trace.h" |
79 | 80 |
|
@@ -2993,6 +2994,67 @@ static void binder_set_txn_from_error(struct binder_transaction *t, int id, |
2993 | 2994 | binder_thread_dec_tmpref(from); |
2994 | 2995 | } |
2995 | 2996 |
|
| 2997 | +/** |
| 2998 | + * binder_netlink_report() - report a transaction failure via netlink |
| 2999 | + * @proc: the binder proc sending the transaction |
| 3000 | + * @t: the binder transaction that failed |
| 3001 | + * @data_size: the user provided data size for the transaction |
| 3002 | + * @error: enum binder_driver_return_protocol returned to sender |
| 3003 | + */ |
| 3004 | +static void binder_netlink_report(struct binder_proc *proc, |
| 3005 | + struct binder_transaction *t, |
| 3006 | + u32 data_size, |
| 3007 | + u32 error) |
| 3008 | +{ |
| 3009 | + const char *context = proc->context->name; |
| 3010 | + struct sk_buff *skb; |
| 3011 | + void *hdr; |
| 3012 | + |
| 3013 | + if (!genl_has_listeners(&binder_nl_family, &init_net, |
| 3014 | + BINDER_NLGRP_REPORT)) |
| 3015 | + return; |
| 3016 | + |
| 3017 | + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 3018 | + if (!skb) |
| 3019 | + return; |
| 3020 | + |
| 3021 | + hdr = genlmsg_put(skb, 0, 0, &binder_nl_family, 0, BINDER_CMD_REPORT); |
| 3022 | + if (!hdr) |
| 3023 | + goto free_skb; |
| 3024 | + |
| 3025 | + if (nla_put_u32(skb, BINDER_A_REPORT_ERROR, error) || |
| 3026 | + nla_put_string(skb, BINDER_A_REPORT_CONTEXT, context) || |
| 3027 | + nla_put_u32(skb, BINDER_A_REPORT_FROM_PID, t->from_pid) || |
| 3028 | + nla_put_u32(skb, BINDER_A_REPORT_FROM_TID, t->from_tid)) |
| 3029 | + goto cancel_skb; |
| 3030 | + |
| 3031 | + if (t->to_proc && |
| 3032 | + nla_put_u32(skb, BINDER_A_REPORT_TO_PID, t->to_proc->pid)) |
| 3033 | + goto cancel_skb; |
| 3034 | + |
| 3035 | + if (t->to_thread && |
| 3036 | + nla_put_u32(skb, BINDER_A_REPORT_TO_TID, t->to_thread->pid)) |
| 3037 | + goto cancel_skb; |
| 3038 | + |
| 3039 | + if (t->is_reply && nla_put_flag(skb, BINDER_A_REPORT_IS_REPLY)) |
| 3040 | + goto cancel_skb; |
| 3041 | + |
| 3042 | + if (nla_put_u32(skb, BINDER_A_REPORT_FLAGS, t->flags) || |
| 3043 | + nla_put_u32(skb, BINDER_A_REPORT_CODE, t->code) || |
| 3044 | + nla_put_u32(skb, BINDER_A_REPORT_DATA_SIZE, data_size)) |
| 3045 | + goto cancel_skb; |
| 3046 | + |
| 3047 | + genlmsg_end(skb, hdr); |
| 3048 | + genlmsg_multicast(&binder_nl_family, skb, 0, BINDER_NLGRP_REPORT, |
| 3049 | + GFP_KERNEL); |
| 3050 | + return; |
| 3051 | + |
| 3052 | +cancel_skb: |
| 3053 | + genlmsg_cancel(skb, hdr); |
| 3054 | +free_skb: |
| 3055 | + nlmsg_free(skb); |
| 3056 | +} |
| 3057 | + |
2996 | 3058 | static void binder_transaction(struct binder_proc *proc, |
2997 | 3059 | struct binder_thread *thread, |
2998 | 3060 | struct binder_transaction_data *tr, int reply, |
@@ -3679,10 +3741,13 @@ static void binder_transaction(struct binder_proc *proc, |
3679 | 3741 | return_error_line = __LINE__; |
3680 | 3742 | goto err_copy_data_failed; |
3681 | 3743 | } |
3682 | | - if (t->buffer->oneway_spam_suspect) |
| 3744 | + if (t->buffer->oneway_spam_suspect) { |
3683 | 3745 | tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT; |
3684 | | - else |
| 3746 | + binder_netlink_report(proc, t, tr->data_size, |
| 3747 | + BR_ONEWAY_SPAM_SUSPECT); |
| 3748 | + } else { |
3685 | 3749 | tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; |
| 3750 | + } |
3686 | 3751 |
|
3687 | 3752 | if (reply) { |
3688 | 3753 | binder_enqueue_thread_work(thread, tcomplete); |
@@ -3730,8 +3795,11 @@ static void binder_transaction(struct binder_proc *proc, |
3730 | 3795 | * process and is put in a pending queue, waiting for the target |
3731 | 3796 | * process to be unfrozen. |
3732 | 3797 | */ |
3733 | | - if (return_error == BR_TRANSACTION_PENDING_FROZEN) |
| 3798 | + if (return_error == BR_TRANSACTION_PENDING_FROZEN) { |
3734 | 3799 | tcomplete->type = BINDER_WORK_TRANSACTION_PENDING; |
| 3800 | + binder_netlink_report(proc, t, tr->data_size, |
| 3801 | + return_error); |
| 3802 | + } |
3735 | 3803 | binder_enqueue_thread_work(thread, tcomplete); |
3736 | 3804 | if (return_error && |
3737 | 3805 | return_error != BR_TRANSACTION_PENDING_FROZEN) |
@@ -3789,6 +3857,8 @@ static void binder_transaction(struct binder_proc *proc, |
3789 | 3857 | binder_dec_node(target_node, 1, 0); |
3790 | 3858 | binder_dec_node_tmpref(target_node); |
3791 | 3859 | } |
| 3860 | + |
| 3861 | + binder_netlink_report(proc, t, tr->data_size, return_error); |
3792 | 3862 | kfree(t); |
3793 | 3863 | binder_stats_deleted(BINDER_STAT_TRANSACTION); |
3794 | 3864 | err_alloc_t_failed: |
@@ -7059,12 +7129,19 @@ static int __init binder_init(void) |
7059 | 7129 | } |
7060 | 7130 | } |
7061 | 7131 |
|
7062 | | - ret = init_binderfs(); |
| 7132 | + ret = genl_register_family(&binder_nl_family); |
7063 | 7133 | if (ret) |
7064 | 7134 | goto err_init_binder_device_failed; |
7065 | 7135 |
|
| 7136 | + ret = init_binderfs(); |
| 7137 | + if (ret) |
| 7138 | + goto err_init_binderfs_failed; |
| 7139 | + |
7066 | 7140 | return ret; |
7067 | 7141 |
|
| 7142 | +err_init_binderfs_failed: |
| 7143 | + genl_unregister_family(&binder_nl_family); |
| 7144 | + |
7068 | 7145 | err_init_binder_device_failed: |
7069 | 7146 | hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) { |
7070 | 7147 | misc_deregister(&device->miscdev); |
|
0 commit comments