Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2007 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 17 | #include <cutils/native_handle.h> |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 18 | |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 19 | #include <errno.h> |
Mark Salyzyn | 23ed4c2 | 2016-09-28 13:33:27 -0700 | [diff] [blame] | 20 | #include <stdint.h> |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 21 | #include <stdlib.h> |
Mark Salyzyn | 23ed4c2 | 2016-09-28 13:33:27 -0700 | [diff] [blame] | 22 | #include <string.h> |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 23 | #include <unistd.h> |
| 24 | |
Brian Duddie | 9f2af69 | 2022-08-24 19:52:08 +0000 | [diff] [blame^] | 25 | // Needs to come after stdlib includes to capture the __BIONIC__ definition |
| 26 | #ifdef __BIONIC__ |
| 27 | #include <android/fdsan.h> |
| 28 | #endif |
| 29 | |
| 30 | namespace { |
| 31 | |
| 32 | #if !defined(__BIONIC__) |
| 33 | // fdsan stubs when not linked against bionic |
| 34 | #define ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE 0 |
| 35 | |
| 36 | uint64_t android_fdsan_create_owner_tag(int /*type*/, uint64_t /*tag*/) { |
| 37 | return 0; |
| 38 | } |
| 39 | uint64_t android_fdsan_get_owner_tag(int /*fd*/) { |
| 40 | return 0; |
| 41 | } |
| 42 | int android_fdsan_close_with_tag(int fd, uint64_t /*tag*/) { |
| 43 | return close(fd); |
| 44 | } |
| 45 | void android_fdsan_exchange_owner_tag(int /*fd*/, uint64_t /*expected_tag*/, uint64_t /*tag*/) {} |
| 46 | #endif // !__BIONIC__ |
| 47 | |
| 48 | uint64_t get_fdsan_tag(const native_handle_t* handle) { |
| 49 | return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE, |
| 50 | reinterpret_cast<uint64_t>(handle)); |
| 51 | } |
| 52 | |
| 53 | int close_internal(const native_handle_t* h, bool allowUntagged) { |
| 54 | if (!h) return 0; |
| 55 | |
| 56 | if (h->version != sizeof(native_handle_t)) return -EINVAL; |
| 57 | |
| 58 | const int numFds = h->numFds; |
| 59 | uint64_t tag; |
| 60 | if (allowUntagged && numFds > 0 && android_fdsan_get_owner_tag(h->data[0]) == 0) { |
| 61 | tag = 0; |
| 62 | } else { |
| 63 | tag = get_fdsan_tag(h); |
| 64 | } |
| 65 | int saved_errno = errno; |
| 66 | for (int i = 0; i < numFds; ++i) { |
| 67 | android_fdsan_close_with_tag(h->data[i], tag); |
| 68 | } |
| 69 | errno = saved_errno; |
| 70 | return 0; |
| 71 | } |
| 72 | |
| 73 | void swap_fdsan_tags(const native_handle_t* handle, uint64_t expected_tag, uint64_t new_tag) { |
| 74 | if (!handle || handle->version != sizeof(native_handle_t)) return; |
| 75 | |
| 76 | for (int i = 0; i < handle->numFds; i++) { |
| 77 | // allow for idempotence to make the APIs easier to use |
| 78 | if (android_fdsan_get_owner_tag(handle->data[i]) != new_tag) { |
| 79 | android_fdsan_exchange_owner_tag(handle->data[i], expected_tag, new_tag); |
| 80 | } |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | } // anonymous namespace |
| 85 | |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 86 | native_handle_t* native_handle_init(char* storage, int numFds, int numInts) { |
Brian Duddie | 9f2af69 | 2022-08-24 19:52:08 +0000 | [diff] [blame^] | 87 | if ((uintptr_t)storage % alignof(native_handle_t)) { |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 88 | errno = EINVAL; |
Chia-I Wu | b843791 | 2016-09-23 11:17:11 +0800 | [diff] [blame] | 89 | return NULL; |
| 90 | } |
| 91 | |
Brian Duddie | 9f2af69 | 2022-08-24 19:52:08 +0000 | [diff] [blame^] | 92 | native_handle_t* handle = (native_handle_t*)storage; |
Chia-I Wu | b843791 | 2016-09-23 11:17:11 +0800 | [diff] [blame] | 93 | handle->version = sizeof(native_handle_t); |
| 94 | handle->numFds = numFds; |
| 95 | handle->numInts = numInts; |
Chia-I Wu | b843791 | 2016-09-23 11:17:11 +0800 | [diff] [blame] | 96 | return handle; |
| 97 | } |
| 98 | |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 99 | native_handle_t* native_handle_create(int numFds, int numInts) { |
Martijn Coenen | 02debfa | 2018-12-05 09:42:25 +0100 | [diff] [blame] | 100 | if (numFds < 0 || numInts < 0 || numFds > NATIVE_HANDLE_MAX_FDS || |
| 101 | numInts > NATIVE_HANDLE_MAX_INTS) { |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 102 | errno = EINVAL; |
Adam Lesinski | 07edc3b | 2015-04-27 12:13:33 -0700 | [diff] [blame] | 103 | return NULL; |
| 104 | } |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 105 | |
Adam Lesinski | 07edc3b | 2015-04-27 12:13:33 -0700 | [diff] [blame] | 106 | size_t mallocSize = sizeof(native_handle_t) + (sizeof(int) * (numFds + numInts)); |
Elliott Hughes | 8e9aeb9 | 2017-11-10 10:22:07 -0800 | [diff] [blame] | 107 | native_handle_t* h = static_cast<native_handle_t*>(malloc(mallocSize)); |
Michael Lentine | 2b8852d | 2014-10-31 15:22:52 -0700 | [diff] [blame] | 108 | if (h) { |
| 109 | h->version = sizeof(native_handle_t); |
| 110 | h->numFds = numFds; |
| 111 | h->numInts = numInts; |
| 112 | } |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 113 | return h; |
| 114 | } |
| 115 | |
Brian Duddie | 9f2af69 | 2022-08-24 19:52:08 +0000 | [diff] [blame^] | 116 | void native_handle_set_fdsan_tag(const native_handle_t* handle) { |
| 117 | swap_fdsan_tags(handle, 0, get_fdsan_tag(handle)); |
| 118 | } |
| 119 | |
| 120 | void native_handle_unset_fdsan_tag(const native_handle_t* handle) { |
| 121 | swap_fdsan_tags(handle, get_fdsan_tag(handle), 0); |
| 122 | } |
| 123 | |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 124 | native_handle_t* native_handle_clone(const native_handle_t* handle) { |
Chia-I Wu | fd3ea3d | 2016-09-23 11:13:52 +0800 | [diff] [blame] | 125 | native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts); |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 126 | if (clone == NULL) return NULL; |
Chia-I Wu | fd3ea3d | 2016-09-23 11:13:52 +0800 | [diff] [blame] | 127 | |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 128 | for (int i = 0; i < handle->numFds; i++) { |
Chia-I Wu | fd3ea3d | 2016-09-23 11:13:52 +0800 | [diff] [blame] | 129 | clone->data[i] = dup(handle->data[i]); |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 130 | if (clone->data[i] == -1) { |
Chia-I Wu | fd3ea3d | 2016-09-23 11:13:52 +0800 | [diff] [blame] | 131 | clone->numFds = i; |
| 132 | native_handle_close(clone); |
| 133 | native_handle_delete(clone); |
| 134 | return NULL; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | memcpy(&clone->data[handle->numFds], &handle->data[handle->numFds], |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 139 | sizeof(int) * handle->numInts); |
Chia-I Wu | fd3ea3d | 2016-09-23 11:13:52 +0800 | [diff] [blame] | 140 | |
| 141 | return clone; |
| 142 | } |
| 143 | |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 144 | int native_handle_delete(native_handle_t* h) { |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 145 | if (h) { |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 146 | if (h->version != sizeof(native_handle_t)) return -EINVAL; |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 147 | free(h); |
| 148 | } |
| 149 | return 0; |
| 150 | } |
| 151 | |
Elliott Hughes | bf0492a | 2017-05-01 21:34:15 -0700 | [diff] [blame] | 152 | int native_handle_close(const native_handle_t* h) { |
Brian Duddie | 9f2af69 | 2022-08-24 19:52:08 +0000 | [diff] [blame^] | 153 | return close_internal(h, /*allowUntagged=*/true); |
| 154 | } |
Elliott Hughes | 7e42484 | 2019-11-12 20:20:42 -0800 | [diff] [blame] | 155 | |
Brian Duddie | 9f2af69 | 2022-08-24 19:52:08 +0000 | [diff] [blame^] | 156 | int native_handle_close_with_tag(const native_handle_t* h) { |
| 157 | return close_internal(h, /*allowUntagged=*/false); |
Mathias Agopian | 3fc51ba | 2009-05-20 14:16:34 -0700 | [diff] [blame] | 158 | } |