/src/usbguard/src/Library/UEventParser.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Copyright (C) 2016 Red Hat, Inc. |
3 | | // |
4 | | // This program is free software; you can redistribute it and/or modify |
5 | | // it under the terms of the GNU General Public License as published by |
6 | | // the Free Software Foundation; either version 2 of the License, or |
7 | | // (at your option) any later version. |
8 | | // |
9 | | // This program is distributed in the hope that it will be useful, |
10 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | // GNU General Public License for more details. |
13 | | // |
14 | | // You should have received a copy of the GNU General Public License |
15 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | | // |
17 | | // Authors: Daniel Kopecek <dkopecek@redhat.com> |
18 | | // |
19 | | #ifdef HAVE_BUILD_CONFIG_H |
20 | | #include <build-config.h> |
21 | | #endif |
22 | | |
23 | | #include "UEventParser.hpp" |
24 | | #include "UEvent.hpp" |
25 | | #include "Common/Utility.hpp" |
26 | | |
27 | | #include "usbguard/Logger.hpp" |
28 | | |
29 | | #include <fstream> |
30 | | |
31 | | #if TAO_PEGTL_VERSION_MAJOR >= 3 |
32 | | #include <tao/pegtl/contrib/trace.hpp> |
33 | | #else |
34 | | #include <tao/pegtl/contrib/tracer.hpp> |
35 | | #endif |
36 | | using namespace tao; |
37 | | |
38 | | namespace usbguard |
39 | | { |
40 | | namespace UEventParser |
41 | | { |
42 | | template<typename Rule> |
43 | | struct actions |
44 | | : pegtl::nothing<Rule> {}; |
45 | | |
46 | | template<> |
47 | | struct actions<attribute> { |
48 | | template<typename Input> |
49 | | static void apply(const Input& in, UEvent& uevent) |
50 | 126k | { |
51 | 126k | try { |
52 | 126k | const auto p = in.string().find_first_of('='); |
53 | | |
54 | 126k | if (p == std::string::npos || p == (in.string().size() - 1)) { |
55 | 0 | throw pegtl::parse_error("invalid attribute format", in); |
56 | 0 | } |
57 | | |
58 | 126k | const std::string key = in.string().substr(0, p); |
59 | 126k | const std::string value = trim(in.string().substr(p + 1, std::string::npos), std::string("\n\0", 2)); |
60 | | |
61 | 126k | for (const std::string header_key : { |
62 | 126k | "ACTION", "DEVPATH" |
63 | 253k | }) { |
64 | 253k | if (key == header_key) { |
65 | | /* |
66 | | * Sanity check the value only if the value is already assigned, |
67 | | * because with umockdev device manager we need to parse ACTION |
68 | | * and DEVPATH from the uevent data and we don't know it before |
69 | | * that. |
70 | | */ |
71 | 1.28k | if (!uevent.getAttribute(header_key).empty()) { |
72 | 1.28k | if (value != uevent.getAttribute(header_key)) { |
73 | 239 | throw pegtl::parse_error("header value mismatch", in); |
74 | 239 | } |
75 | 1.28k | } |
76 | 1.28k | } |
77 | 253k | } |
78 | 126k | uevent.setAttribute(key, value); |
79 | 126k | } |
80 | 126k | catch (const pegtl::parse_error& ex) { |
81 | 239 | throw; |
82 | 239 | } |
83 | 126k | catch (const std::exception& ex) { |
84 | 0 | throw pegtl::parse_error(ex.what(), in); |
85 | 0 | } |
86 | 126k | } |
87 | | }; |
88 | | |
89 | | template<> |
90 | | struct actions<action> { |
91 | | template<typename Input> |
92 | | static void apply(const Input& in, UEvent& uevent) |
93 | 1.19k | { |
94 | 1.19k | uevent.setAttribute("ACTION", in.string()); |
95 | 1.19k | } |
96 | | }; |
97 | | |
98 | | template<> |
99 | | struct actions<devpath> { |
100 | | template<typename Input> |
101 | | static void apply(const Input& in, UEvent& uevent) |
102 | 1.08k | { |
103 | 1.08k | uevent.setAttribute("DEVPATH", in.string()); |
104 | 1.08k | } |
105 | | }; |
106 | | } /* namespace UEventParser */ |
107 | | |
108 | | void parseUEventFromFile(const std::string& uevent_path, UEvent& uevent, bool attributes_only, bool trace) |
109 | 0 | { |
110 | 0 | std::ifstream uevent_stream(uevent_path); |
111 | |
|
112 | 0 | if (uevent_stream.good()) { |
113 | 0 | std::string uevent_string(4096, 0); |
114 | 0 | uevent_stream.readsome(&uevent_string[0], uevent_string.capacity()); |
115 | 0 | const auto read_size = uevent_stream.gcount(); |
116 | |
|
117 | 0 | if (read_size > 0) { |
118 | 0 | uevent_string.resize(read_size); |
119 | 0 | parseUEventFromString(uevent_string, uevent, attributes_only, trace); |
120 | 0 | } |
121 | 0 | } |
122 | 0 | else { |
123 | 0 | throw std::runtime_error("failed to open uevent source file"); |
124 | 0 | } |
125 | 0 | } |
126 | | |
127 | | template<class G> |
128 | | void parseUEventFromString(const std::string& uevent_string, UEvent& uevent, bool trace) |
129 | 1.21k | { |
130 | 1.21k | try { |
131 | 1.21k | tao::pegtl::string_input<> in(uevent_string, std::string()); |
132 | | |
133 | 1.21k | if (!trace) { |
134 | 1.21k | tao::pegtl::parse<G, UEventParser::actions>(in, uevent); |
135 | 1.21k | } |
136 | 0 | else { |
137 | 0 | #if TAO_PEGTL_VERSION_MAJOR >= 3 |
138 | 0 | tao::pegtl::complete_trace<G, UEventParser::actions>(in, uevent); |
139 | | #else |
140 | | tao::pegtl::parse<G, UEventParser::actions, tao::pegtl::tracer>(in, uevent); |
141 | | #endif |
142 | 0 | } |
143 | 1.21k | } |
144 | 1.21k | catch (...) { |
145 | 239 | throw; |
146 | 239 | } |
147 | 1.21k | } Unexecuted instantiation: void usbguard::parseUEventFromString<usbguard::UEventParser::attributes>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, usbguard::UEvent&, bool) void usbguard::parseUEventFromString<usbguard::UEventParser::grammar>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, usbguard::UEvent&, bool) Line | Count | Source | 129 | 1.21k | { | 130 | 1.21k | try { | 131 | 1.21k | tao::pegtl::string_input<> in(uevent_string, std::string()); | 132 | | | 133 | 1.21k | if (!trace) { | 134 | 1.21k | tao::pegtl::parse<G, UEventParser::actions>(in, uevent); | 135 | 1.21k | } | 136 | 0 | else { | 137 | 0 | #if TAO_PEGTL_VERSION_MAJOR >= 3 | 138 | 0 | tao::pegtl::complete_trace<G, UEventParser::actions>(in, uevent); | 139 | | #else | 140 | | tao::pegtl::parse<G, UEventParser::actions, tao::pegtl::tracer>(in, uevent); | 141 | | #endif | 142 | 0 | } | 143 | 1.21k | } | 144 | 1.21k | catch (...) { | 145 | 239 | throw; | 146 | 239 | } | 147 | 1.21k | } |
|
148 | | |
149 | | void parseUEventFromString(const std::string& uevent_string, UEvent& uevent, bool attributes_only, bool trace) |
150 | 1.21k | { |
151 | 1.21k | if (attributes_only) { |
152 | 0 | parseUEventFromString<UEventParser::attributes>(uevent_string, uevent, trace); |
153 | 0 | } |
154 | 1.21k | else { |
155 | 1.21k | parseUEventFromString<UEventParser::grammar>(uevent_string, uevent, trace); |
156 | 1.21k | } |
157 | 1.21k | } |
158 | | } /* namespace usbguard */ |
159 | | |
160 | | /* vim: set ts=2 sw=2 et */ |