diff options
| author | Martijn Coenen <maco@android.com> | 2017-11-13 04:06:08 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-11-28 10:54:45 -0500 |
| commit | fb2c445277e7b0b4ffe10de8114bad4eccaca948 (patch) | |
| tree | 2e47a7a38cacb813e62cd88049435131da0d8cfc /drivers/android | |
| parent | 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323 (diff) | |
ANDROID: binder: fix transaction leak.
If a call to put_user() fails, we failed to
properly free a transaction and send a failed
reply (if necessary).
Signed-off-by: Martijn Coenen <maco@android.com>
Cc: stable <stable@vger.kernel.org> # 4.14
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/android')
| -rw-r--r-- | drivers/android/binder.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index a73596a4f804..bccec9de0533 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c | |||
| @@ -1948,6 +1948,26 @@ static void binder_send_failed_reply(struct binder_transaction *t, | |||
| 1948 | } | 1948 | } |
| 1949 | 1949 | ||
| 1950 | /** | 1950 | /** |
| 1951 | * binder_cleanup_transaction() - cleans up undelivered transaction | ||
| 1952 | * @t: transaction that needs to be cleaned up | ||
| 1953 | * @reason: reason the transaction wasn't delivered | ||
| 1954 | * @error_code: error to return to caller (if synchronous call) | ||
| 1955 | */ | ||
| 1956 | static void binder_cleanup_transaction(struct binder_transaction *t, | ||
| 1957 | const char *reason, | ||
| 1958 | uint32_t error_code) | ||
| 1959 | { | ||
| 1960 | if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) { | ||
| 1961 | binder_send_failed_reply(t, error_code); | ||
| 1962 | } else { | ||
| 1963 | binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, | ||
| 1964 | "undelivered transaction %d, %s\n", | ||
| 1965 | t->debug_id, reason); | ||
| 1966 | binder_free_transaction(t); | ||
| 1967 | } | ||
| 1968 | } | ||
| 1969 | |||
| 1970 | /** | ||
| 1951 | * binder_validate_object() - checks for a valid metadata object in a buffer. | 1971 | * binder_validate_object() - checks for a valid metadata object in a buffer. |
| 1952 | * @buffer: binder_buffer that we're parsing. | 1972 | * @buffer: binder_buffer that we're parsing. |
| 1953 | * @offset: offset in the buffer at which to validate an object. | 1973 | * @offset: offset in the buffer at which to validate an object. |
| @@ -4015,12 +4035,20 @@ retry: | |||
| 4015 | if (put_user(cmd, (uint32_t __user *)ptr)) { | 4035 | if (put_user(cmd, (uint32_t __user *)ptr)) { |
| 4016 | if (t_from) | 4036 | if (t_from) |
| 4017 | binder_thread_dec_tmpref(t_from); | 4037 | binder_thread_dec_tmpref(t_from); |
| 4038 | |||
| 4039 | binder_cleanup_transaction(t, "put_user failed", | ||
| 4040 | BR_FAILED_REPLY); | ||
| 4041 | |||
| 4018 | return -EFAULT; | 4042 | return -EFAULT; |
| 4019 | } | 4043 | } |
| 4020 | ptr += sizeof(uint32_t); | 4044 | ptr += sizeof(uint32_t); |
| 4021 | if (copy_to_user(ptr, &tr, sizeof(tr))) { | 4045 | if (copy_to_user(ptr, &tr, sizeof(tr))) { |
| 4022 | if (t_from) | 4046 | if (t_from) |
| 4023 | binder_thread_dec_tmpref(t_from); | 4047 | binder_thread_dec_tmpref(t_from); |
| 4048 | |||
| 4049 | binder_cleanup_transaction(t, "copy_to_user failed", | ||
| 4050 | BR_FAILED_REPLY); | ||
| 4051 | |||
| 4024 | return -EFAULT; | 4052 | return -EFAULT; |
| 4025 | } | 4053 | } |
| 4026 | ptr += sizeof(tr); | 4054 | ptr += sizeof(tr); |
| @@ -4090,15 +4118,9 @@ static void binder_release_work(struct binder_proc *proc, | |||
| 4090 | struct binder_transaction *t; | 4118 | struct binder_transaction *t; |
| 4091 | 4119 | ||
| 4092 | t = container_of(w, struct binder_transaction, work); | 4120 | t = container_of(w, struct binder_transaction, work); |
| 4093 | if (t->buffer->target_node && | 4121 | |
| 4094 | !(t->flags & TF_ONE_WAY)) { | 4122 | binder_cleanup_transaction(t, "process died.", |
| 4095 | binder_send_failed_reply(t, BR_DEAD_REPLY); | 4123 | BR_DEAD_REPLY); |
| 4096 | } else { | ||
| 4097 | binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, | ||
| 4098 | "undelivered transaction %d\n", | ||
| 4099 | t->debug_id); | ||
| 4100 | binder_free_transaction(t); | ||
| 4101 | } | ||
| 4102 | } break; | 4124 | } break; |
| 4103 | case BINDER_WORK_RETURN_ERROR: { | 4125 | case BINDER_WORK_RETURN_ERROR: { |
| 4104 | struct binder_error *e = container_of( | 4126 | struct binder_error *e = container_of( |
