1 /*
2 * Copyright (C) 2019 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 #define LOG_TAG "Stability"
17
18 #include <binder/Stability.h>
19
20 #include <binder/BpBinder.h>
21 #include <binder/Binder.h>
22
23 namespace android {
24 namespace internal {
25
26 // the libbinder parcel format is currently unstable
27
28 // oldest version which is supported
29 constexpr uint8_t kBinderWireFormatOldest = 1;
30 // current version
31 constexpr uint8_t kBinderWireFormatVersion = 1;
32
currentFromLevel(Level level)33 Stability::Category Stability::Category::currentFromLevel(Level level) {
34 return {
35 .version = kBinderWireFormatVersion,
36 .reserved = {0},
37 .level = level,
38 };
39 }
40
forceDowngradeToStability(const sp<IBinder> & binder,Level level)41 void Stability::forceDowngradeToStability(const sp<IBinder>& binder, Level level) {
42 // Downgrading a remote binder would require also copying the version from
43 // the binder sent here. In practice though, we don't need to downgrade the
44 // stability of a remote binder, since this would as an effect only restrict
45 // what we can do to it.
46 LOG_ALWAYS_FATAL_IF(!binder || !binder->localBinder(), "Can only downgrade local binder");
47
48 auto stability = Category::currentFromLevel(level);
49 status_t result = setRepr(binder.get(), stability.repr(), REPR_LOG | REPR_ALLOW_DOWNGRADE);
50 LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
51 }
52
forceDowngradeToLocalStability(const sp<IBinder> & binder)53 void Stability::forceDowngradeToLocalStability(const sp<IBinder>& binder) {
54 forceDowngradeToStability(binder, getLocalLevel());
55 }
56
forceDowngradeToSystemStability(const sp<IBinder> & binder)57 void Stability::forceDowngradeToSystemStability(const sp<IBinder>& binder) {
58 forceDowngradeToStability(binder, Level::SYSTEM);
59 }
60
forceDowngradeToVendorStability(const sp<IBinder> & binder)61 void Stability::forceDowngradeToVendorStability(const sp<IBinder>& binder) {
62 forceDowngradeToStability(binder, Level::VENDOR);
63 }
64
debugString()65 std::string Stability::Category::debugString() {
66 return levelString(level) + " wire protocol version "
67 + std::to_string(version);
68 }
69
markCompilationUnit(IBinder * binder)70 void Stability::markCompilationUnit(IBinder* binder) {
71 auto stability = Category::currentFromLevel(getLocalLevel());
72 status_t result = setRepr(binder, stability.repr(), REPR_LOG);
73 LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
74 }
75
markVintf(IBinder * binder)76 void Stability::markVintf(IBinder* binder) {
77 auto stability = Category::currentFromLevel(Level::VINTF);
78 status_t result = setRepr(binder, stability.repr(), REPR_LOG);
79 LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
80 }
81
debugLogStability(const std::string & tag,const sp<IBinder> & binder)82 void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) {
83 auto stability = getCategory(binder.get());
84 ALOGE("%s: stability is %s", tag.c_str(), stability.debugString().c_str());
85 }
86
markVndk(IBinder * binder)87 void Stability::markVndk(IBinder* binder) {
88 auto stability = Category::currentFromLevel(Level::VENDOR);
89 status_t result = setRepr(binder, stability.repr(), REPR_LOG);
90 LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
91 }
92
requiresVintfDeclaration(const sp<IBinder> & binder)93 bool Stability::requiresVintfDeclaration(const sp<IBinder>& binder) {
94 return check(getCategory(binder.get()), Level::VINTF);
95 }
96
tryMarkCompilationUnit(IBinder * binder)97 void Stability::tryMarkCompilationUnit(IBinder* binder) {
98 auto stability = Category::currentFromLevel(getLocalLevel());
99 (void) setRepr(binder, stability.repr(), REPR_NONE);
100 }
101
getLocalLevel()102 Stability::Level Stability::getLocalLevel() {
103 #ifdef __ANDROID_APEX__
104 #error APEX can't use libbinder (must use libbinder_ndk)
105 #endif
106
107 #ifdef __ANDROID_VNDK__
108 return Level::VENDOR;
109 #else
110 // TODO(b/139325195): split up stability levels for system/APEX.
111 return Level::SYSTEM;
112 #endif
113 }
114
115 status_t Stability::setRepr(IBinder* binder, int32_t representation, uint32_t flags) {
116 bool log = flags & REPR_LOG;
117 bool allowDowngrade = flags & REPR_ALLOW_DOWNGRADE;
118
119 auto current = getCategory(binder);
120 auto setting = Category::fromRepr(representation);
121
122 // If we have ahold of a binder with a newer declared version, then it
123 // should support older versions, and we will simply write our parcels with
124 // the current wire parcel format.
125 if (setting.version < kBinderWireFormatOldest) {
126 // always log, because this shouldn't happen
127 ALOGE("Cannot accept binder with older binder wire protocol version "
128 "%u. Versions less than %u are unsupported.", setting.version,
129 kBinderWireFormatOldest);
130 return BAD_TYPE;
131 }
132
133 // null binder is always written w/ 'UNDECLARED' stability
134 if (binder == nullptr) {
135 if (setting.level == UNDECLARED) {
136 return OK;
137 } else {
138 if (log) {
139 ALOGE("Null binder written with stability %s.",
140 levelString(setting.level).c_str());
141 }
142 return BAD_TYPE;
143 }
144 }
145
146 if (!isDeclaredLevel(setting.level)) {
147 if (log) {
148 ALOGE("Can only set known stability, not %u.", setting.level);
149 }
150 return BAD_TYPE;
151 }
152
153 if (current == setting) return OK;
154
155 bool hasAlreadyBeenSet = current.repr() != 0;
156 bool isAllowedDowngrade = allowDowngrade && check(current, setting.level);
157 if (hasAlreadyBeenSet && !isAllowedDowngrade) {
158 if (log) {
159 ALOGE("Interface being set with %s but it is already marked as %s",
160 setting.debugString().c_str(),
161 current.debugString().c_str());
162 }
163 return BAD_TYPE;
164 }
165
166 if (isAllowedDowngrade) {
167 ALOGI("Interface set with %s downgraded to %s stability",
168 current.debugString().c_str(),
169 setting.debugString().c_str());
170 }
171
172 BBinder* local = binder->localBinder();
173 if (local != nullptr) {
174 local->mStability = setting.repr();
175 } else {
176 binder->remoteBinder()->mStability = setting.repr();
177 }
178
179 return OK;
180 }
181
getCategory(IBinder * binder)182 Stability::Category Stability::getCategory(IBinder* binder) {
183 if (binder == nullptr) {
184 return Category::currentFromLevel(Level::UNDECLARED);
185 }
186
187 BBinder* local = binder->localBinder();
188 if (local != nullptr) {
189 return Category::fromRepr(local->mStability);
190 }
191
192 return Category::fromRepr(binder->remoteBinder()->mStability);
193 }
194
check(Category provided,Level required)195 bool Stability::check(Category provided, Level required) {
196 bool stable = (provided.level & required) == required;
197
198 if (provided.level != UNDECLARED && !isDeclaredLevel(provided.level)) {
199 ALOGE("Unknown stability when checking interface stability %d.",
200 provided.level);
201
202 stable = false;
203 }
204
205 return stable;
206 }
207
isDeclaredLevel(Level stability)208 bool Stability::isDeclaredLevel(Level stability) {
209 return stability == VENDOR || stability == SYSTEM || stability == VINTF;
210 }
211
levelString(Level level)212 std::string Stability::levelString(Level level) {
213 switch (level) {
214 case Level::UNDECLARED: return "undeclared stability";
215 case Level::VENDOR: return "vendor stability";
216 case Level::SYSTEM: return "system stability";
217 case Level::VINTF: return "vintf stability";
218 }
219 return "unknown stability " + std::to_string(level);
220 }
221
222 } // namespace internal
223 } // namespace stability
224