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