blob: b85c93b81c2b30771d539d3735379a71494f3b46 [file] [log] [blame]
Mathias Agopian3fc51ba2009-05-20 14:16:34 -07001/*
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 Hughesbf0492a2017-05-01 21:34:15 -070017#include <cutils/native_handle.h>
Mathias Agopian3fc51ba2009-05-20 14:16:34 -070018
Mathias Agopian3fc51ba2009-05-20 14:16:34 -070019#include <errno.h>
Mark Salyzyn23ed4c22016-09-28 13:33:27 -070020#include <stdint.h>
Mathias Agopian3fc51ba2009-05-20 14:16:34 -070021#include <stdlib.h>
Mark Salyzyn23ed4c22016-09-28 13:33:27 -070022#include <string.h>
Mathias Agopian3fc51ba2009-05-20 14:16:34 -070023#include <unistd.h>
24
Brian Duddie9f2af692022-08-24 19:52:08 +000025// Needs to come after stdlib includes to capture the __BIONIC__ definition
26#ifdef __BIONIC__
27#include <android/fdsan.h>
28#endif
29
30namespace {
31
32#if !defined(__BIONIC__)
33// fdsan stubs when not linked against bionic
34#define ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE 0
35
36uint64_t android_fdsan_create_owner_tag(int /*type*/, uint64_t /*tag*/) {
37 return 0;
38}
39uint64_t android_fdsan_get_owner_tag(int /*fd*/) {
40 return 0;
41}
42int android_fdsan_close_with_tag(int fd, uint64_t /*tag*/) {
43 return close(fd);
44}
45void android_fdsan_exchange_owner_tag(int /*fd*/, uint64_t /*expected_tag*/, uint64_t /*tag*/) {}
46#endif // !__BIONIC__
47
48uint64_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
53int 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
73void 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 Hughesbf0492a2017-05-01 21:34:15 -070086native_handle_t* native_handle_init(char* storage, int numFds, int numInts) {
Brian Duddie9f2af692022-08-24 19:52:08 +000087 if ((uintptr_t)storage % alignof(native_handle_t)) {
Elliott Hughesbf0492a2017-05-01 21:34:15 -070088 errno = EINVAL;
Chia-I Wub8437912016-09-23 11:17:11 +080089 return NULL;
90 }
91
Brian Duddie9f2af692022-08-24 19:52:08 +000092 native_handle_t* handle = (native_handle_t*)storage;
Chia-I Wub8437912016-09-23 11:17:11 +080093 handle->version = sizeof(native_handle_t);
94 handle->numFds = numFds;
95 handle->numInts = numInts;
Chia-I Wub8437912016-09-23 11:17:11 +080096 return handle;
97}
98
Elliott Hughesbf0492a2017-05-01 21:34:15 -070099native_handle_t* native_handle_create(int numFds, int numInts) {
Martijn Coenen02debfa2018-12-05 09:42:25 +0100100 if (numFds < 0 || numInts < 0 || numFds > NATIVE_HANDLE_MAX_FDS ||
101 numInts > NATIVE_HANDLE_MAX_INTS) {
Elliott Hughesbf0492a2017-05-01 21:34:15 -0700102 errno = EINVAL;
Adam Lesinski07edc3b2015-04-27 12:13:33 -0700103 return NULL;
104 }
Mathias Agopian3fc51ba2009-05-20 14:16:34 -0700105
Adam Lesinski07edc3b2015-04-27 12:13:33 -0700106 size_t mallocSize = sizeof(native_handle_t) + (sizeof(int) * (numFds + numInts));
Elliott Hughes8e9aeb92017-11-10 10:22:07 -0800107 native_handle_t* h = static_cast<native_handle_t*>(malloc(mallocSize));
Michael Lentine2b8852d2014-10-31 15:22:52 -0700108 if (h) {
109 h->version = sizeof(native_handle_t);
110 h->numFds = numFds;
111 h->numInts = numInts;
112 }
Mathias Agopian3fc51ba2009-05-20 14:16:34 -0700113 return h;
114}
115
Brian Duddie9f2af692022-08-24 19:52:08 +0000116void native_handle_set_fdsan_tag(const native_handle_t* handle) {
117 swap_fdsan_tags(handle, 0, get_fdsan_tag(handle));
118}
119
120void native_handle_unset_fdsan_tag(const native_handle_t* handle) {
121 swap_fdsan_tags(handle, get_fdsan_tag(handle), 0);
122}
123
Elliott Hughesbf0492a2017-05-01 21:34:15 -0700124native_handle_t* native_handle_clone(const native_handle_t* handle) {
Chia-I Wufd3ea3d2016-09-23 11:13:52 +0800125 native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts);
Elliott Hughesbf0492a2017-05-01 21:34:15 -0700126 if (clone == NULL) return NULL;
Chia-I Wufd3ea3d2016-09-23 11:13:52 +0800127
Elliott Hughesbf0492a2017-05-01 21:34:15 -0700128 for (int i = 0; i < handle->numFds; i++) {
Chia-I Wufd3ea3d2016-09-23 11:13:52 +0800129 clone->data[i] = dup(handle->data[i]);
Elliott Hughesbf0492a2017-05-01 21:34:15 -0700130 if (clone->data[i] == -1) {
Chia-I Wufd3ea3d2016-09-23 11:13:52 +0800131 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 Hughesbf0492a2017-05-01 21:34:15 -0700139 sizeof(int) * handle->numInts);
Chia-I Wufd3ea3d2016-09-23 11:13:52 +0800140
141 return clone;
142}
143
Elliott Hughesbf0492a2017-05-01 21:34:15 -0700144int native_handle_delete(native_handle_t* h) {
Mathias Agopian3fc51ba2009-05-20 14:16:34 -0700145 if (h) {
Elliott Hughesbf0492a2017-05-01 21:34:15 -0700146 if (h->version != sizeof(native_handle_t)) return -EINVAL;
Mathias Agopian3fc51ba2009-05-20 14:16:34 -0700147 free(h);
148 }
149 return 0;
150}
151
Elliott Hughesbf0492a2017-05-01 21:34:15 -0700152int native_handle_close(const native_handle_t* h) {
Brian Duddie9f2af692022-08-24 19:52:08 +0000153 return close_internal(h, /*allowUntagged=*/true);
154}
Elliott Hughes7e424842019-11-12 20:20:42 -0800155
Brian Duddie9f2af692022-08-24 19:52:08 +0000156int native_handle_close_with_tag(const native_handle_t* h) {
157 return close_internal(h, /*allowUntagged=*/false);
Mathias Agopian3fc51ba2009-05-20 14:16:34 -0700158}