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
17 #include <cutils/native_handle.h>
18
19 #include <errno.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
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
android_fdsan_create_owner_tag(int,uint64_t)36 uint64_t android_fdsan_create_owner_tag(int /*type*/, uint64_t /*tag*/) {
37 return 0;
38 }
android_fdsan_get_owner_tag(int)39 uint64_t android_fdsan_get_owner_tag(int /*fd*/) {
40 return 0;
41 }
android_fdsan_close_with_tag(int fd,uint64_t)42 int android_fdsan_close_with_tag(int fd, uint64_t /*tag*/) {
43 return close(fd);
44 }
android_fdsan_exchange_owner_tag(int,uint64_t,uint64_t)45 void android_fdsan_exchange_owner_tag(int /*fd*/, uint64_t /*expected_tag*/, uint64_t /*tag*/) {}
46 #endif // !__BIONIC__
47
get_fdsan_tag(const native_handle_t * handle)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
close_internal(const native_handle_t * h,bool allowUntagged)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
swap_fdsan_tags(const native_handle_t * handle,uint64_t expected_tag,uint64_t new_tag)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
native_handle_init(char * storage,int numFds,int numInts)86 native_handle_t* native_handle_init(char* storage, int numFds, int numInts) {
87 if ((uintptr_t)storage % alignof(native_handle_t)) {
88 errno = EINVAL;
89 return NULL;
90 }
91
92 native_handle_t* handle = (native_handle_t*)storage;
93 handle->version = sizeof(native_handle_t);
94 handle->numFds = numFds;
95 handle->numInts = numInts;
96 return handle;
97 }
98
native_handle_create(int numFds,int numInts)99 native_handle_t* native_handle_create(int numFds, int numInts) {
100 if (numFds < 0 || numInts < 0 || numFds > NATIVE_HANDLE_MAX_FDS ||
101 numInts > NATIVE_HANDLE_MAX_INTS) {
102 errno = EINVAL;
103 return NULL;
104 }
105
106 size_t mallocSize = sizeof(native_handle_t) + (sizeof(int) * (numFds + numInts));
107 native_handle_t* h = static_cast<native_handle_t*>(malloc(mallocSize));
108 if (h) {
109 h->version = sizeof(native_handle_t);
110 h->numFds = numFds;
111 h->numInts = numInts;
112 }
113 return h;
114 }
115
native_handle_set_fdsan_tag(const native_handle_t * handle)116 void native_handle_set_fdsan_tag(const native_handle_t* handle) {
117 swap_fdsan_tags(handle, 0, get_fdsan_tag(handle));
118 }
119
native_handle_unset_fdsan_tag(const native_handle_t * handle)120 void native_handle_unset_fdsan_tag(const native_handle_t* handle) {
121 swap_fdsan_tags(handle, get_fdsan_tag(handle), 0);
122 }
123
native_handle_clone(const native_handle_t * handle)124 native_handle_t* native_handle_clone(const native_handle_t* handle) {
125 native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts);
126 if (clone == NULL) return NULL;
127
128 for (int i = 0; i < handle->numFds; i++) {
129 clone->data[i] = dup(handle->data[i]);
130 if (clone->data[i] == -1) {
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],
139 sizeof(int) * handle->numInts);
140
141 return clone;
142 }
143
native_handle_delete(native_handle_t * h)144 int native_handle_delete(native_handle_t* h) {
145 if (h) {
146 if (h->version != sizeof(native_handle_t)) return -EINVAL;
147 free(h);
148 }
149 return 0;
150 }
151
native_handle_close(const native_handle_t * h)152 int native_handle_close(const native_handle_t* h) {
153 return close_internal(h, /*allowUntagged=*/true);
154 }
155
native_handle_close_with_tag(const native_handle_t * h)156 int native_handle_close_with_tag(const native_handle_t* h) {
157 return close_internal(h, /*allowUntagged=*/false);
158 }
159