1 /*
2 * Copyright (C) 2017 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 STATSD_DEBUG false // STOPSHIP if true
17 #include "Log.h"
18
19 #include "matchers/matcher_util.h"
20
21 #include <fnmatch.h>
22
23 #include "matchers/AtomMatchingTracker.h"
24 #include "src/statsd_config.pb.h"
25 #include "stats_util.h"
26 #include "utils/Regex.h"
27
28 using std::set;
29 using std::string;
30 using std::unique_ptr;
31 using std::vector;
32
33 namespace android {
34 namespace os {
35 namespace statsd {
36
combinationMatch(const vector<int> & children,const LogicalOperation & operation,const vector<MatchingState> & matcherResults)37 bool combinationMatch(const vector<int>& children, const LogicalOperation& operation,
38 const vector<MatchingState>& matcherResults) {
39 bool matched;
40 switch (operation) {
41 case LogicalOperation::AND: {
42 matched = true;
43 for (const int childIndex : children) {
44 if (matcherResults[childIndex] != MatchingState::kMatched) {
45 matched = false;
46 break;
47 }
48 }
49 break;
50 }
51 case LogicalOperation::OR: {
52 matched = false;
53 for (const int childIndex : children) {
54 if (matcherResults[childIndex] == MatchingState::kMatched) {
55 matched = true;
56 break;
57 }
58 }
59 break;
60 }
61 case LogicalOperation::NOT:
62 matched = matcherResults[children[0]] == MatchingState::kNotMatched;
63 break;
64 case LogicalOperation::NAND:
65 matched = false;
66 for (const int childIndex : children) {
67 if (matcherResults[childIndex] != MatchingState::kMatched) {
68 matched = true;
69 break;
70 }
71 }
72 break;
73 case LogicalOperation::NOR:
74 matched = true;
75 for (const int childIndex : children) {
76 if (matcherResults[childIndex] == MatchingState::kMatched) {
77 matched = false;
78 break;
79 }
80 }
81 break;
82 case LogicalOperation::LOGICAL_OPERATION_UNSPECIFIED:
83 matched = false;
84 break;
85 }
86 return matched;
87 }
88
tryMatchString(const sp<UidMap> & uidMap,const FieldValue & fieldValue,const string & str_match)89 static bool tryMatchString(const sp<UidMap>& uidMap, const FieldValue& fieldValue,
90 const string& str_match) {
91 if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) {
92 int uid = fieldValue.mValue.int_value;
93 auto aidIt = UidMap::sAidToUidMapping.find(str_match);
94 if (aidIt != UidMap::sAidToUidMapping.end()) {
95 return ((int)aidIt->second) == uid;
96 }
97 return uidMap->hasApp(uid, str_match);
98 } else if (fieldValue.mValue.getType() == STRING) {
99 return fieldValue.mValue.str_value == str_match;
100 }
101 return false;
102 }
103
tryMatchWildcardString(const sp<UidMap> & uidMap,const FieldValue & fieldValue,const string & wildcardPattern)104 static bool tryMatchWildcardString(const sp<UidMap>& uidMap, const FieldValue& fieldValue,
105 const string& wildcardPattern) {
106 if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) {
107 int uid = fieldValue.mValue.int_value;
108 // TODO(b/236886985): replace aid/uid mapping with efficient bidirectional container
109 // AidToUidMapping will never have uids above 10000
110 if (uid < 10000) {
111 for (auto aidIt = UidMap::sAidToUidMapping.begin();
112 aidIt != UidMap::sAidToUidMapping.end(); ++aidIt) {
113 if ((int)aidIt->second == uid) {
114 // Assumes there is only one aid mapping for each uid
115 return fnmatch(wildcardPattern.c_str(), aidIt->first.c_str(), 0) == 0;
116 }
117 }
118 }
119 std::set<string> packageNames = uidMap->getAppNamesFromUid(uid, false /* normalize*/);
120 for (const auto& packageName : packageNames) {
121 if (fnmatch(wildcardPattern.c_str(), packageName.c_str(), 0) == 0) {
122 return true;
123 }
124 }
125 } else if (fieldValue.mValue.getType() == STRING) {
126 return fnmatch(wildcardPattern.c_str(), fieldValue.mValue.str_value.c_str(), 0) == 0;
127 }
128 return false;
129 }
130
getTransformedEvent(const FieldValueMatcher & matcher,const LogEvent & event,int start,int end)131 static unique_ptr<LogEvent> getTransformedEvent(const FieldValueMatcher& matcher,
132 const LogEvent& event, int start, int end) {
133 if (!matcher.has_replace_string()) {
134 return nullptr;
135 }
136
137 unique_ptr<Regex> re = Regex::create(matcher.replace_string().regex());
138
139 if (re == nullptr) {
140 return nullptr;
141 }
142
143 const string& replacement = matcher.replace_string().replacement();
144 unique_ptr<LogEvent> transformedEvent = nullptr;
145 for (int i = start; i < end; i++) {
146 const LogEvent& eventRef = transformedEvent == nullptr ? event : *transformedEvent;
147 const FieldValue& fieldValue = eventRef.getValues()[i];
148 if (fieldValue.mValue.getType() != STRING) {
149 continue;
150 }
151 string str = fieldValue.mValue.str_value;
152 if (!re->replace(str, replacement) || str == fieldValue.mValue.str_value) {
153 continue;
154 }
155
156 // String transformation occurred, update the FieldValue in transformedEvent.
157 if (transformedEvent == nullptr) {
158 transformedEvent = std::make_unique<LogEvent>(event);
159 }
160 (*transformedEvent->getMutableValues())[i].mValue.str_value = str;
161 }
162 return transformedEvent;
163 }
164
getStartEndAtDepth(int targetField,int start,int end,int depth,const vector<FieldValue> & values)165 static pair<int, int> getStartEndAtDepth(int targetField, int start, int end, int depth,
166 const vector<FieldValue>& values) {
167 // Filter by entry field first
168 int newStart = -1;
169 int newEnd = end;
170 // because the fields are naturally sorted in the DFS order. we can safely
171 // break when pos is larger than the one we are searching for.
172 for (int i = start; i < end; i++) {
173 int pos = values[i].mField.getPosAtDepth(depth);
174 if (pos == targetField) {
175 if (newStart == -1) {
176 newStart = i;
177 }
178 newEnd = i + 1;
179 } else if (pos > targetField) {
180 break;
181 }
182 }
183
184 return {newStart, newEnd};
185 }
186
187 /*
188 * Returns pairs of start-end indices in vector<FieldValue> that pariticipate in matching.
189 * The returned vector is empty if an error was encountered.
190 * If Position is ANY and value_matcher is matches_tuple, the vector contains a start/end pair
191 * corresponding for each child FieldValueMatcher in matches_tuple. For all other cases, the
192 * returned vector is of size 1.
193 *
194 * Also updates the depth reference parameter if matcher has Position specified.
195 */
computeRanges(const FieldValueMatcher & matcher,const vector<FieldValue> & values,int start,int end,int & depth)196 static vector<pair<int, int>> computeRanges(const FieldValueMatcher& matcher,
197 const vector<FieldValue>& values, int start, int end,
198 int& depth) {
199 // Now we have zoomed in to a new range
200 std::tie(start, end) = getStartEndAtDepth(matcher.field(), start, end, depth, values);
201
202 if (start == -1) {
203 // No such field found.
204 return {};
205 }
206
207 vector<pair<int, int>> ranges;
208 if (matcher.has_position()) {
209 // Repeated fields position is stored as a node in the path.
210 depth++;
211 if (depth > 2) {
212 return ranges;
213 }
214 switch (matcher.position()) {
215 case Position::FIRST: {
216 for (int i = start; i < end; i++) {
217 int pos = values[i].mField.getPosAtDepth(depth);
218 if (pos != 1) {
219 // Again, the log elements are stored in sorted order. so
220 // once the position is > 1, we break;
221 end = i;
222 break;
223 }
224 }
225 ranges.push_back(std::make_pair(start, end));
226 break;
227 }
228 case Position::LAST: {
229 // move the starting index to the first LAST field at the depth.
230 for (int i = start; i < end; i++) {
231 if (values[i].mField.isLastPos(depth)) {
232 start = i;
233 break;
234 }
235 }
236 ranges.push_back(std::make_pair(start, end));
237 break;
238 }
239 case Position::ALL:
240 // ALL is only supported for string transformation. If a value_matcher other than
241 // matches_tuple is present, the matcher is invalid. This is enforced when
242 // the AtomMatchingTracker is initialized.
243
244 // fallthrough
245 case Position::ANY: {
246 // For string transformation, this case is treated the same as Position:ALL.
247 // Given a matcher on attribution_node[ANY].tag with a matches_tuple containing a
248 // child FieldValueMatcher with eq_string: "foo" and regex_replace: "[\d]+$" --> "",
249 // an event with attribution tags: ["bar123", "foo12", "abc230"] will transform to
250 // have attribution tags ["bar", "foo", "abc"] and will be a successful match.
251
252 // Note that if value_matcher is matches_tuple, there should be no string
253 // transformation on this matcher. However, child FieldValueMatchers in
254 // matches_tuple can have string transformations. This is enforced when
255 // AtomMatchingTracker is initialized.
256
257 if (matcher.value_matcher_case() == FieldValueMatcher::kMatchesTuple) {
258 // For ANY with matches_tuple, if all the children matchers match in any of the
259 // sub trees, it's a match.
260 // Here start is guaranteed to be a valid index.
261 int currentPos = values[start].mField.getPosAtDepth(depth);
262 // Now find all sub trees ranges.
263 for (int i = start; i < end; i++) {
264 int newPos = values[i].mField.getPosAtDepth(depth);
265 if (newPos != currentPos) {
266 ranges.push_back(std::make_pair(start, i));
267 start = i;
268 currentPos = newPos;
269 }
270 }
271 }
272 ranges.push_back(std::make_pair(start, end));
273 break;
274 }
275 case Position::POSITION_UNKNOWN:
276 break;
277 }
278 } else {
279 // No position
280 ranges.push_back(std::make_pair(start, end));
281 }
282
283 return ranges;
284 }
285
matchesSimple(const sp<UidMap> & uidMap,const FieldValueMatcher & matcher,const LogEvent & event,int start,int end,int depth)286 static MatchResult matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher,
287 const LogEvent& event, int start, int end, int depth) {
288 if (depth > 2) {
289 ALOGE("Depth >= 3 not supported");
290 return {false, nullptr};
291 }
292
293 if (start >= end) {
294 return {false, nullptr};
295 }
296
297 const vector<pair<int, int>> ranges =
298 computeRanges(matcher, event.getValues(), start, end, depth);
299
300 if (ranges.empty()) {
301 // No such field found.
302 return {false, nullptr};
303 }
304
305 // ranges should have exactly one start/end pair at this point unless position is ANY and
306 // value_matcher is matches_tuple.
307 std::tie(start, end) = ranges[0];
308
309 unique_ptr<LogEvent> transformedEvent = getTransformedEvent(matcher, event, start, end);
310
311 const vector<FieldValue>& values =
312 transformedEvent == nullptr ? event.getValues() : transformedEvent->getValues();
313
314 switch (matcher.value_matcher_case()) {
315 case FieldValueMatcher::kMatchesTuple: {
316 ++depth;
317 // If any range matches all matchers, good.
318 bool matchResult = false;
319 for (const auto& [rangeStart, rangeEnd] : ranges) {
320 bool matched = true;
321 for (const auto& subMatcher : matcher.matches_tuple().field_value_matcher()) {
322 const LogEvent& eventRef =
323 transformedEvent == nullptr ? event : *transformedEvent;
324 auto [hasMatched, newTransformedEvent] = matchesSimple(
325 uidMap, subMatcher, eventRef, rangeStart, rangeEnd, depth);
326 if (newTransformedEvent != nullptr) {
327 transformedEvent = std::move(newTransformedEvent);
328 }
329 if (!hasMatched) {
330 matched = false;
331 }
332 }
333 matchResult = matchResult || matched;
334 }
335 return {matchResult, std::move(transformedEvent)};
336 }
337 // Finally, we get to the point of real value matching.
338 // If the field matcher ends with ANY, then we have [start, end) range > 1.
339 // In the following, we should return true, when ANY of the values matches.
340 case FieldValueMatcher::ValueMatcherCase::kEqBool: {
341 for (int i = start; i < end; i++) {
342 if ((values[i].mValue.getType() == INT &&
343 (values[i].mValue.int_value != 0) == matcher.eq_bool()) ||
344 (values[i].mValue.getType() == LONG &&
345 (values[i].mValue.long_value != 0) == matcher.eq_bool())) {
346 return {true, std::move(transformedEvent)};
347 }
348 }
349 return {false, std::move(transformedEvent)};
350 }
351 case FieldValueMatcher::ValueMatcherCase::kEqString: {
352 for (int i = start; i < end; i++) {
353 if (tryMatchString(uidMap, values[i], matcher.eq_string())) {
354 return {true, std::move(transformedEvent)};
355 }
356 }
357 return {false, std::move(transformedEvent)};
358 }
359 case FieldValueMatcher::ValueMatcherCase::kNeqAnyString: {
360 const auto& str_list = matcher.neq_any_string();
361 for (int i = start; i < end; i++) {
362 bool notEqAll = true;
363 for (const auto& str : str_list.str_value()) {
364 if (tryMatchString(uidMap, values[i], str)) {
365 notEqAll = false;
366 break;
367 }
368 }
369 if (notEqAll) {
370 return {true, std::move(transformedEvent)};
371 }
372 }
373 return {false, std::move(transformedEvent)};
374 }
375 case FieldValueMatcher::ValueMatcherCase::kEqAnyString: {
376 const auto& str_list = matcher.eq_any_string();
377 for (int i = start; i < end; i++) {
378 for (const auto& str : str_list.str_value()) {
379 if (tryMatchString(uidMap, values[i], str)) {
380 return {true, std::move(transformedEvent)};
381 }
382 }
383 }
384 return {false, std::move(transformedEvent)};
385 }
386 case FieldValueMatcher::ValueMatcherCase::kEqWildcardString: {
387 for (int i = start; i < end; i++) {
388 if (tryMatchWildcardString(uidMap, values[i], matcher.eq_wildcard_string())) {
389 return {true, std::move(transformedEvent)};
390 }
391 }
392 return {false, std::move(transformedEvent)};
393 }
394 case FieldValueMatcher::ValueMatcherCase::kEqAnyWildcardString: {
395 const auto& str_list = matcher.eq_any_wildcard_string();
396 for (int i = start; i < end; i++) {
397 for (const auto& str : str_list.str_value()) {
398 if (tryMatchWildcardString(uidMap, values[i], str)) {
399 return {true, std::move(transformedEvent)};
400 }
401 }
402 }
403 return {false, std::move(transformedEvent)};
404 }
405 case FieldValueMatcher::ValueMatcherCase::kNeqAnyWildcardString: {
406 const auto& str_list = matcher.neq_any_wildcard_string();
407 for (int i = start; i < end; i++) {
408 bool notEqAll = true;
409 for (const auto& str : str_list.str_value()) {
410 if (tryMatchWildcardString(uidMap, values[i], str)) {
411 notEqAll = false;
412 break;
413 }
414 }
415 if (notEqAll) {
416 return {true, std::move(transformedEvent)};
417 }
418 }
419 return {false, std::move(transformedEvent)};
420 }
421 case FieldValueMatcher::ValueMatcherCase::kEqInt: {
422 for (int i = start; i < end; i++) {
423 if (values[i].mValue.getType() == INT &&
424 (matcher.eq_int() == values[i].mValue.int_value)) {
425 return {true, std::move(transformedEvent)};
426 }
427 // eq_int covers both int and long.
428 if (values[i].mValue.getType() == LONG &&
429 (matcher.eq_int() == values[i].mValue.long_value)) {
430 return {true, std::move(transformedEvent)};
431 }
432 }
433 return {false, std::move(transformedEvent)};
434 }
435 case FieldValueMatcher::ValueMatcherCase::kEqAnyInt: {
436 const auto& int_list = matcher.eq_any_int();
437 for (int i = start; i < end; i++) {
438 for (const int int_value : int_list.int_value()) {
439 if (values[i].mValue.getType() == INT &&
440 (int_value == values[i].mValue.int_value)) {
441 return {true, std::move(transformedEvent)};
442 }
443 // eq_any_int covers both int and long.
444 if (values[i].mValue.getType() == LONG &&
445 (int_value == values[i].mValue.long_value)) {
446 return {true, std::move(transformedEvent)};
447 }
448 }
449 }
450 return {false, std::move(transformedEvent)};
451 }
452 case FieldValueMatcher::ValueMatcherCase::kNeqAnyInt: {
453 const auto& int_list = matcher.neq_any_int();
454 for (int i = start; i < end; i++) {
455 bool notEqAll = true;
456 for (const int int_value : int_list.int_value()) {
457 if (values[i].mValue.getType() == INT &&
458 (int_value == values[i].mValue.int_value)) {
459 notEqAll = false;
460 break;
461 }
462 // neq_any_int covers both int and long.
463 if (values[i].mValue.getType() == LONG &&
464 (int_value == values[i].mValue.long_value)) {
465 notEqAll = false;
466 break;
467 }
468 }
469 if (notEqAll) {
470 return {true, std::move(transformedEvent)};
471 }
472 }
473 return {false, std::move(transformedEvent)};
474 }
475 case FieldValueMatcher::ValueMatcherCase::kLtInt: {
476 for (int i = start; i < end; i++) {
477 if (values[i].mValue.getType() == INT &&
478 (values[i].mValue.int_value < matcher.lt_int())) {
479 return {true, std::move(transformedEvent)};
480 }
481 // lt_int covers both int and long.
482 if (values[i].mValue.getType() == LONG &&
483 (values[i].mValue.long_value < matcher.lt_int())) {
484 return {true, std::move(transformedEvent)};
485 }
486 }
487 return {false, std::move(transformedEvent)};
488 }
489 case FieldValueMatcher::ValueMatcherCase::kGtInt: {
490 for (int i = start; i < end; i++) {
491 if (values[i].mValue.getType() == INT &&
492 (values[i].mValue.int_value > matcher.gt_int())) {
493 return {true, std::move(transformedEvent)};
494 }
495 // gt_int covers both int and long.
496 if (values[i].mValue.getType() == LONG &&
497 (values[i].mValue.long_value > matcher.gt_int())) {
498 return {true, std::move(transformedEvent)};
499 }
500 }
501 return {false, std::move(transformedEvent)};
502 }
503 case FieldValueMatcher::ValueMatcherCase::kLtFloat: {
504 for (int i = start; i < end; i++) {
505 if (values[i].mValue.getType() == FLOAT &&
506 (values[i].mValue.float_value < matcher.lt_float())) {
507 return {true, std::move(transformedEvent)};
508 }
509 }
510 return {false, std::move(transformedEvent)};
511 }
512 case FieldValueMatcher::ValueMatcherCase::kGtFloat: {
513 for (int i = start; i < end; i++) {
514 if (values[i].mValue.getType() == FLOAT &&
515 (values[i].mValue.float_value > matcher.gt_float())) {
516 return {true, std::move(transformedEvent)};
517 }
518 }
519 return {false, std::move(transformedEvent)};
520 }
521 case FieldValueMatcher::ValueMatcherCase::kLteInt: {
522 for (int i = start; i < end; i++) {
523 if (values[i].mValue.getType() == INT &&
524 (values[i].mValue.int_value <= matcher.lte_int())) {
525 return {true, std::move(transformedEvent)};
526 }
527 // lte_int covers both int and long.
528 if (values[i].mValue.getType() == LONG &&
529 (values[i].mValue.long_value <= matcher.lte_int())) {
530 return {true, std::move(transformedEvent)};
531 }
532 }
533 return {false, std::move(transformedEvent)};
534 }
535 case FieldValueMatcher::ValueMatcherCase::kGteInt: {
536 for (int i = start; i < end; i++) {
537 if (values[i].mValue.getType() == INT &&
538 (values[i].mValue.int_value >= matcher.gte_int())) {
539 return {true, std::move(transformedEvent)};
540 }
541 // gte_int covers both int and long.
542 if (values[i].mValue.getType() == LONG &&
543 (values[i].mValue.long_value >= matcher.gte_int())) {
544 return {true, std::move(transformedEvent)};
545 }
546 }
547 return {false, std::move(transformedEvent)};
548 }
549 default:
550 // This only happens if the matcher has a string transformation and no value_matcher. So
551 // the default match result is true. If there is no string transformation either then
552 // this matcher is invalid, which is enforced when the AtomMatchingTracker is
553 // initialized.
554 return {true, std::move(transformedEvent)};
555 }
556 }
557
matchesSimple(const sp<UidMap> & uidMap,const SimpleAtomMatcher & simpleMatcher,const LogEvent & event)558 MatchResult matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher,
559 const LogEvent& event) {
560 if (event.GetTagId() != simpleMatcher.atom_id()) {
561 return {false, nullptr};
562 }
563
564 unique_ptr<LogEvent> transformedEvent = nullptr;
565 for (const auto& matcher : simpleMatcher.field_value_matcher()) {
566 const LogEvent& inputEvent = transformedEvent == nullptr ? event : *transformedEvent;
567 auto [hasMatched, newTransformedEvent] =
568 matchesSimple(uidMap, matcher, inputEvent, 0, inputEvent.getValues().size(), 0);
569 if (newTransformedEvent != nullptr) {
570 transformedEvent = std::move(newTransformedEvent);
571 }
572 if (!hasMatched) {
573 return {false, std::move(transformedEvent)};
574 }
575 }
576 return {true, std::move(transformedEvent)};
577 }
578
579 } // namespace statsd
580 } // namespace os
581 } // namespace android
582