1 /*
2  * Copyright (C) 2020 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 "VoldNativeServiceValidation.h"
18 
19 #include <android-base/stringprintf.h>
20 #include <android-base/strings.h>
21 #include <binder/IPCThreadState.h>
22 #include <binder/IServiceManager.h>
23 #include <private/android_filesystem_config.h>
24 
25 #include <cctype>
26 #include <string_view>
27 
28 using android::base::StringPrintf;
29 using namespace std::literals;
30 
31 namespace android::vold {
32 
Ok()33 binder::Status Ok() {
34     return binder::Status::ok();
35 }
36 
Exception(uint32_t code,const std::string & msg)37 binder::Status Exception(uint32_t code, const std::string& msg) {
38     return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
39 }
40 
CheckPermission(const char * permission)41 binder::Status CheckPermission(const char* permission) {
42     pid_t pid;
43     uid_t uid;
44 
45     if (checkCallingPermission(String16(permission), reinterpret_cast<int32_t*>(&pid),
46                                reinterpret_cast<int32_t*>(&uid))) {
47         return Ok();
48     } else {
49         return Exception(binder::Status::EX_SECURITY,
50                          StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission));
51     }
52 }
53 
CheckUidOrRoot(uid_t expectedUid)54 binder::Status CheckUidOrRoot(uid_t expectedUid) {
55     uid_t uid = IPCThreadState::self()->getCallingUid();
56     if (uid == expectedUid || uid == AID_ROOT) {
57         return Ok();
58     } else {
59         return Exception(binder::Status::EX_SECURITY,
60                          StringPrintf("UID %d is not expected UID %d", uid, expectedUid));
61     }
62 }
63 
CheckArgumentId(const std::string & id)64 binder::Status CheckArgumentId(const std::string& id) {
65     if (id.empty()) {
66         return Exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Missing ID");
67     }
68     for (const char& c : id) {
69         if (!std::isalnum(c) && c != ':' && c != ',') {
70             return Exception(binder::Status::EX_ILLEGAL_ARGUMENT,
71                              StringPrintf("ID %s is malformed", id.c_str()));
72         }
73     }
74     return Ok();
75 }
76 
CheckArgumentPath(const std::string & path)77 binder::Status CheckArgumentPath(const std::string& path) {
78     if (path.empty()) {
79         return Exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Missing path");
80     }
81     if (path[0] != '/') {
82         return Exception(binder::Status::EX_ILLEGAL_ARGUMENT,
83                          StringPrintf("Path %s is relative", path.c_str()));
84     }
85     if (path.find("/../"sv) != path.npos || android::base::EndsWith(path, "/.."sv)) {
86         return Exception(binder::Status::EX_ILLEGAL_ARGUMENT,
87                          StringPrintf("Path %s is shady", path.c_str()));
88     }
89     for (const char& c : path) {
90         if (c == '\0' || c == '\n') {
91             return Exception(binder::Status::EX_ILLEGAL_ARGUMENT,
92                              StringPrintf("Path %s is malformed", path.c_str()));
93         }
94     }
95     return Ok();
96 }
97 
CheckArgumentHex(const std::string & hex)98 binder::Status CheckArgumentHex(const std::string& hex) {
99     // Empty hex strings are allowed
100     for (const char& c : hex) {
101         if (!std::isxdigit(c) && c != ':' && c != '-') {
102             return Exception(binder::Status::EX_ILLEGAL_ARGUMENT,
103                              StringPrintf("Hex %s is malformed", hex.c_str()));
104         }
105     }
106     return Ok();
107 }
108 
109 }  // namespace android::vold
110