1 /*
2 * Copyright 2024, 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 "libdebuggerd/utility_host.h"
18
19 #include <ctype.h>
20 #include <sys/prctl.h>
21
22 #include <charconv>
23 #include <limits>
24 #include <string>
25
26 #include <android-base/stringprintf.h>
27
28 using android::base::StringPrintf;
29
30 #ifndef PR_MTE_TAG_SHIFT
31 #define PR_MTE_TAG_SHIFT 3
32 #endif
33
34 #ifndef PR_MTE_TAG_MASK
35 #define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
36 #endif
37
38 #ifndef PR_MTE_TCF_ASYNC
39 #define PR_MTE_TCF_ASYNC (1UL << 2)
40 #endif
41
42 #ifndef PR_MTE_TCF_SYNC
43 #define PR_MTE_TCF_SYNC (1UL << 1)
44 #endif
45
46 #ifndef PR_PAC_APIAKEY
47 #define PR_PAC_APIAKEY (1UL << 0)
48 #endif
49
50 #ifndef PR_PAC_APIBKEY
51 #define PR_PAC_APIBKEY (1UL << 1)
52 #endif
53
54 #ifndef PR_PAC_APDAKEY
55 #define PR_PAC_APDAKEY (1UL << 2)
56 #endif
57
58 #ifndef PR_PAC_APDBKEY
59 #define PR_PAC_APDBKEY (1UL << 3)
60 #endif
61
62 #ifndef PR_PAC_APGAKEY
63 #define PR_PAC_APGAKEY (1UL << 4)
64 #endif
65
66 #ifndef PR_TAGGED_ADDR_ENABLE
67 #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
68 #endif
69
70 #define DESCRIBE_FLAG(flag) \
71 if (value & flag) { \
72 desc += ", "; \
73 desc += #flag; \
74 value &= ~flag; \
75 }
76
describe_end(long value,std::string & desc)77 static std::string describe_end(long value, std::string& desc) {
78 if (value) {
79 desc += StringPrintf(", unknown 0x%lx", value);
80 }
81 return desc.empty() ? "" : " (" + desc.substr(2) + ")";
82 }
83
describe_tagged_addr_ctrl(long value)84 std::string describe_tagged_addr_ctrl(long value) {
85 std::string desc;
86 DESCRIBE_FLAG(PR_TAGGED_ADDR_ENABLE);
87 DESCRIBE_FLAG(PR_MTE_TCF_SYNC);
88 DESCRIBE_FLAG(PR_MTE_TCF_ASYNC);
89 if (value & PR_MTE_TAG_MASK) {
90 desc += StringPrintf(", mask 0x%04lx", (value & PR_MTE_TAG_MASK) >> PR_MTE_TAG_SHIFT);
91 value &= ~PR_MTE_TAG_MASK;
92 }
93 return describe_end(value, desc);
94 }
95
describe_pac_enabled_keys(long value)96 std::string describe_pac_enabled_keys(long value) {
97 std::string desc;
98 DESCRIBE_FLAG(PR_PAC_APIAKEY);
99 DESCRIBE_FLAG(PR_PAC_APIBKEY);
100 DESCRIBE_FLAG(PR_PAC_APDAKEY);
101 DESCRIBE_FLAG(PR_PAC_APDBKEY);
102 DESCRIBE_FLAG(PR_PAC_APGAKEY);
103 return describe_end(value, desc);
104 }
105
oct_encode(const std::string & data,bool (* should_encode_func)(int))106 static std::string oct_encode(const std::string& data, bool (*should_encode_func)(int)) {
107 std::string oct_encoded;
108 oct_encoded.reserve(data.size());
109
110 // N.B. the unsigned here is very important, otherwise e.g. \255 would render as
111 // \-123 (and overflow our buffer).
112 for (unsigned char c : data) {
113 if (should_encode_func(c)) {
114 std::string oct_digits("\\\0\0\0", 4);
115 // char is encodable in 3 oct digits
116 static_assert(std::numeric_limits<unsigned char>::max() <= 8 * 8 * 8);
117 auto [ptr, ec] = std::to_chars(oct_digits.data() + 1, oct_digits.data() + 4, c, 8);
118 oct_digits.resize(ptr - oct_digits.data());
119 oct_encoded += oct_digits;
120 } else {
121 oct_encoded += c;
122 }
123 }
124 return oct_encoded;
125 }
126
oct_encode_non_ascii_printable(const std::string & data)127 std::string oct_encode_non_ascii_printable(const std::string& data) {
128 return oct_encode(data, [](int c) { return !isgraph(c) && !isspace(c); });
129 }
130
oct_encode_non_printable(const std::string & data)131 std::string oct_encode_non_printable(const std::string& data) {
132 return oct_encode(data, [](int c) { return !isprint(c); });
133 }
134