• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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