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