-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.h
278 lines (219 loc) · 10.4 KB
/
util.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef USB_BOUNCER_UTIL_H_
#define USB_BOUNCER_UTIL_H_
#include <unistd.h>
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
#include <base/files/file_path.h>
#include <base/files/scoped_file.h>
#include <base/functional/bind.h>
#include <base/functional/callback.h>
#include <base/time/time.h>
#include <brillo/files/safe_fd.h>
#include <google/protobuf/map.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/timestamp.pb.h>
#include <metrics/metrics_library.h>
#include "usb_bouncer/usb_bouncer.pb.h"
namespace usb_bouncer {
using google::protobuf::Timestamp;
using EntryMap = google::protobuf::Map<std::string, RuleEntry>;
constexpr char kUsbBouncerUser[] = "usb_bouncer";
constexpr char kUsbBouncerGroup[] = "usb_bouncer";
constexpr char kDefaultDbName[] = "devices.proto";
constexpr char kUserDbBaseDir[] = "/run/daemon-store/usb_bouncer";
constexpr char kUserDbParentDir[] = "device-db";
constexpr char kDBusPath[] = "/run/dbus/system_bus_socket";
constexpr uid_t kRootUid = 0;
constexpr int kDefaultWaitTimeoutInSeconds = 5;
enum class UMADeviceRecognized {
kRecognized,
kUnrecognized,
};
enum class UMAEventTiming {
kLoggedOut = 0,
kLoggedIn = 1,
kLocked = 2,
// TODO(crbug.com/1218246) Change UMA enum names kUmaDeviceAttachedHistogram.*
// if new enums are added to avoid data discontinuity.
kMaxValue = kLocked,
};
enum class UMAPortType {
kTypeA,
kTypeC,
};
enum class UMADeviceSpeed {
kOther = 0,
k1_5 = 1, // 1.5 Mbps (USB 1.1)
k12 = 2, // 12 Mbps (USB 1.1)
k480 = 3, // 480 Mbps (USB 2.0)
k480Fallback = 4, // SuperSpeed device operating in 480 Mbps (USB 2.0)
k5000 = 5, // 5000 Mbps (USB 3.2 Gen 1)
k10000 = 6, // 10000 Mbps (USB 3.2 Gen 2)
k20000 = 7, // 20000 Mbps (USB 3.2 Gen 2x2)
kMaxValue = k20000,
};
struct UsbSessionMetric {
std::string boot_id;
int64_t system_time;
int action;
int devnum;
int busnum;
int depth;
int vid;
int pid;
};
// Returns true if the process has CAP_CHOWN.
bool CanChown();
std::string Hash(const std::string& content);
std::string Hash(const google::protobuf::RepeatedPtrField<std::string>& rules);
// Set USB devices to be authorized by default and authorize any devices that
// were left unauthorized. This is performed on unlock when USBGuard is
// disabled. If an error occurs, false is returned.
bool AuthorizeAll(const std::string& devpath = "/sys/devices");
// Invokes usbguard to get a rule corresponding to |devpath|. Note that
// |devpath| isn't actually a valid path until you prepend "/sys". This matches
// the behavior of udev. The return value is a allow-list rule from usbguard
// with the port specific fields removed.
std::string GetRuleFromDevPath(const std::string& devpath);
// Returns false for rules that should not be included in the allow-list at the
// lock screen. The basic idea is to exclude devices whose function cannot be
// performed if they are first plugged in at the lock screen. Some examples
// include printers, scanners, and USB storage devices.
bool IncludeRuleAtLockscreen(const std::string& rule);
// Returns false if rule is not a valid rule.
bool ValidateRule(const std::string& rule);
// Log device attach events to inform future changes in policy.
void UMALogDeviceAttached(MetricsLibrary* metrics,
const std::string& rule,
UMADeviceRecognized recognized,
UMAEventTiming timing);
// Log external device attach events.
void UMALogExternalDeviceAttached(MetricsLibrary* metrics,
const std::string& rule,
UMADeviceRecognized recognized,
UMAEventTiming timing,
UMAPortType port,
UMADeviceSpeed speed);
// Report structured metrics on external device attach events.
void StructuredMetricsExternalDeviceAttached(
int VendorId,
std::string VendorName,
int ProductId,
std::string ProductName,
int DeviceClass,
std::vector<int64_t> InterfaceClass);
// Report structured metric on device attach and removal with topology and
// system boot information. Device topology information only gets recorded
// on device connection. This will only record the metric for devices in the
// USB metrics allowlist.
void StructuredMetricsUsbSessionEvent(UsbSessionMetric session_metric);
// Report structured metric on error uevents from the hub driver.
void StructuredMetricsHubError(int ErrorCode,
int VendorId,
int ProductId,
int DeviceClass,
std::string UsbTreePath,
int ConnectedDuration);
// Report structured metric on error uevents from the xHCI driver.
void StructuredMetricsXhciError(int ErrorCode, int DeviceClass);
// Returns the path where the user DB should be written if there is a user
// signed in and CrOS is unlocked. Otherwise, returns an empty path. In the
// multi-login case, the primary user's daemon-store is used.
base::FilePath GetUserDBDir();
// Returns true if a guest session is active.
bool IsGuestSession();
// Returns true if the lock screen is being shown. On a D-Bus failure true is
// returned because that is the safer failure state. This may result in some
// devices not being added to a user's allow-list, but that is safer than a
// malicious device being added to the allow-list while at the lock-screen.
bool IsLockscreenShown();
std::string StripLeadingPathSeparators(const std::string& path);
// Returns a set of all the rules present in |entries|. This serves as a
// filtering step prior to generating the rules configuration for
// usbguard-daemon so that there aren't duplicate rules. The rules are
// de-duplicated by string value ignoring any metadata like the time last used.
std::unordered_set<std::string> UniqueRules(const EntryMap& entries);
// Attempts to open the specified statefile at
// |base_path|/|parent|/|state_file_name| with the proper permissions. The
// parent directory and state file will be cleared if the ownership or
// permissions don't match. They will be created if they do not exist. If |lock|
// is true, this call blocks until an exclusive lock can be obtained for |path|.
// All runs of usb_bouncer are expected to be relatively fast (<250ms), so
// blocking should be ok.
brillo::SafeFD OpenStateFile(const base::FilePath& base_path,
const std::string& parent_dir,
const std::string& state_file_name,
bool lock);
// Forks (exiting the parent), calls setsid, and returns the result of a second
// fork.
//
// This is used to avoid blocking udev while waiting on journald to finish
// setting up logging, D-Bus to be ready, or D-Bus calls that can take on the
// order of seconds to complete.
void Daemonize();
void UpdateTimestamp(Timestamp* timestamp);
size_t RemoveEntriesOlderThan(base::TimeDelta cutoff, EntryMap* map);
// Given an USB device path, parse its root device path through USB device sysfs
// topology. If the given device is not part of a tree (no USB hub in between),
// return |dev| as it is.
//
// E.g. .../1-2/1-2.3/1-2.3.4 is attached to the root hub, .../1-2.
base::FilePath GetRootDevice(base::FilePath dev);
// Given a USB interface path, return the path of its parent USB device.
// If GetInterfaceDevice is unable to determine the parent USB device, it will
// return an empty FilePath.
base::FilePath GetInterfaceDevice(base::FilePath intf);
// Given a devpath, determine if the USB device is external or internal based on
// physical location of device (PLD) and removable property.
bool IsExternalDevice(base::FilePath normalized_devpath);
// Determine if the board is ChromeOS Flex to exclude from metrics reporting
// since we do not have control over firmware on ChromeOS Flex and sysfs values
// are unexpected. Return true if the board cannot be determined to avoid
// possibility of metrics pollution.
bool IsFlexBoard();
// Returns port type for a sysfs device (i.e. USB-A, USB-C).
UMAPortType GetPortType(base::FilePath normalized_devpath);
// Returns USB device speed for a sysfs device.
UMADeviceSpeed GetDeviceSpeed(base::FilePath normalized_devpath);
// Returns vendor ID for a sysfs device.
int GetVendorId(base::FilePath normalized_devpath);
// Returns vendor name for a sysfs device.
std::string GetVendorName(base::FilePath normalized_devpath);
// Returns product ID for a sysfs device.
int GetProductId(base::FilePath normalized_devpath);
// Returns product name for a sysfs device.
std::string GetProductName(base::FilePath normalized_devpath);
// Assigns VID and PID from a uevent's product environment variable. This can
// be used by USB bouncer methods that receive the product environment variable
// to read VID/PID on device disconnection.
void GetVidPidFromEnvVar(std::string product, int* vendor_id, int* product_id);
// Returns device class for a sysfs device.
int GetDeviceClass(base::FilePath normalized_devpath);
// Returns interface classes for a sysfs device.
std::vector<int64_t> GetInterfaceClass(base::FilePath normalized_devpath);
// Returns a USB device's location in the USB device tree. Here, the device
// location is a string with the content of the USB device's devpath file
// which includes a period-separated list of numbers with information on hubs
// and ports between the device and host controller (Example: "1.5.3.2").
std::string GetUsbTreePath(base::FilePath normalized_devpath);
// Returns the depth of a device in a USB topology. This is based on the USB
// tree path returned by GetUsbTreePath.
int GetUsbTreeDepth(base::FilePath normalized_devpath);
// Returns the connected duration, in milliseconds, for a sysfs device.
int GetConnectedDuration(base::FilePath normalized_devpath);
// Returns the PCI device class for a sysfs device.
int GetPciDeviceClass(base::FilePath normalized_devpath);
// Returns the kernel boot_id, which is a unique identifier randomly generated
// each time a system boots.
std::string GetBootId();
// Returns the time since boot in microseconds.
int64_t GetSystemTime();
} // namespace usb_bouncer
#endif // USB_BOUNCER_UTIL_H_