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