diff --git a/src/CLI/PolicyGenerator.cpp b/src/CLI/PolicyGenerator.cpp index 9887d270..c9f1e6d4 100644 --- a/src/CLI/PolicyGenerator.cpp +++ b/src/CLI/PolicyGenerator.cpp @@ -33,6 +33,7 @@ namespace usbguard _hash_only = false; _port_specific = false; _port_specific_noserial = true; + _devpath = ""; _with_catchall = false; _catchall_target = Rule::Target::Block; _dm = DeviceManager::create(*this, "uevent"); @@ -62,7 +63,12 @@ namespace usbguard void PolicyGenerator::generate() { - _dm->scan(); + if (_devpath.empty()) { + _dm->scan(); + } + else { + _dm->scan(_devpath); + } if (_with_catchall) { Rule catchall_rule; @@ -76,6 +82,11 @@ namespace usbguard return _ruleset; } + void PolicyGenerator::setDevpath(const std::string& devpath) + { + _devpath = devpath; + } + void PolicyGenerator::setExplicitCatchAllRule(bool state, Rule::Target target) { _with_catchall = state; diff --git a/src/CLI/PolicyGenerator.hpp b/src/CLI/PolicyGenerator.hpp index b9d04cfd..e3ccd58b 100644 --- a/src/CLI/PolicyGenerator.hpp +++ b/src/CLI/PolicyGenerator.hpp @@ -38,6 +38,7 @@ namespace usbguard void setHashOnly(bool state); void setPortSpecificRules(bool state); void setPortSpecificNoSerialRules(bool state); + void setDevpath(const std::string& devpath); void setExplicitCatchAllRule(bool state, Rule::Target target = Rule::Target::Block); void generate(); @@ -55,6 +56,7 @@ namespace usbguard bool _hash_only; bool _port_specific; bool _port_specific_noserial; + std::string _devpath; bool _with_catchall; Rule::Target _catchall_target; }; diff --git a/src/CLI/usbguard-generate-policy.cpp b/src/CLI/usbguard-generate-policy.cpp index a1fbbf7c..218d7238 100644 --- a/src/CLI/usbguard-generate-policy.cpp +++ b/src/CLI/usbguard-generate-policy.cpp @@ -34,12 +34,13 @@ namespace usbguard { - static const char* options_short = "hpPt:HXLb:o:n:"; + static const char* options_short = "hpPd:t:HXLb:o:n:"; static const struct ::option options_long[] = { { "help", no_argument, nullptr, 'h' }, { "with-ports", no_argument, nullptr, 'p' }, { "no-ports-sn", no_argument, nullptr, 'P' }, + { "devpath", required_argument, nullptr, 'd' }, { "target", required_argument, nullptr, 't' }, { "hash-only", no_argument, nullptr, 'H' }, { "no-hashes", no_argument, nullptr, 'X' }, @@ -58,6 +59,8 @@ namespace usbguard stream << " -p, --with-ports Generate port specific rules for all devices." << std::endl; stream << " -P, --no-ports-sn Don't generate port specific rule for devices" << std::endl; stream << " without an iSerial value." << std::endl; + stream << " -d, --devpath Only generate a rule for the device at the specified" << std::endl; + stream << " sub path of /sys." << std::endl; stream << " -t, --target Generate an explicit \"catch all\" rule with the" << std::endl; stream << " specified target. Possible targets: allow, block, reject." << std::endl; stream << " -X, --no-hashes Don't generate a hash attribute for each device." << std::endl; @@ -75,6 +78,7 @@ namespace usbguard { bool port_specific = false; bool port_specific_noserial = true; + std::string devpath = ""; bool with_catchall = false; std::string catchall_target = "block"; bool with_hashes = true; @@ -100,6 +104,10 @@ namespace usbguard port_specific_noserial = false; break; + case 'd': + devpath = optarg; + break; + case 't': with_catchall = true; catchall_target = optarg; @@ -143,6 +151,7 @@ namespace usbguard generator.setHashOnly(only_hashes); generator.setPortSpecificRules(port_specific); generator.setPortSpecificNoSerialRules(port_specific_noserial); + generator.setDevpath(devpath); generator.setExplicitCatchAllRule(with_catchall, Rule::targetFromString(catchall_target)); generator.generate(); diff --git a/src/Library/UEventDeviceManager.cpp b/src/Library/UEventDeviceManager.cpp index ca0ed96d..ca0a7073 100644 --- a/src/Library/UEventDeviceManager.cpp +++ b/src/Library/UEventDeviceManager.cpp @@ -316,6 +316,27 @@ namespace usbguard } } + void UEventDeviceManager::scan(const std::string& devpath) + { + std::vector components; + tokenizeString(devpath, components, "/", /*trim_empty=*/true); + auto base = std::find_if(components.begin(), components.end(), + [](const std::string& component) -> bool { + return hasPrefix(component, "usb"); + }); + std::string path = ""; + + for (auto itr = components.begin(); itr < components.end(); ++itr) { + path += "/" + *itr; + + if (itr >= base) { + ueventProcessAction("add", path); + } + } + + ueventProcessAction("add", path); + } + std::shared_ptr UEventDeviceManager::applyDevicePolicy(uint32_t id, Rule::Target target) { USBGUARD_LOG(Trace) << "id=" << id @@ -547,6 +568,11 @@ namespace usbguard } const std::string sysfs_devpath = uevent.getAttribute("DEVPATH"); + ueventProcessAction(action, sysfs_devpath); + } + + void UEventDeviceManager::ueventProcessAction(const std::string& action, const std::string& sysfs_devpath) + { bool enumeration_notify = false; try { diff --git a/src/Library/UEventDeviceManager.hpp b/src/Library/UEventDeviceManager.hpp index 2ab0a2e7..23e933cd 100644 --- a/src/Library/UEventDeviceManager.hpp +++ b/src/Library/UEventDeviceManager.hpp @@ -76,6 +76,7 @@ namespace usbguard void start() override; void stop() override; void scan() override; + void scan(const std::string& devpath) override; std::shared_ptr applyDevicePolicy(uint32_t id, Rule::Target target) override; void insertDevice(std::shared_ptr device); @@ -94,6 +95,7 @@ namespace usbguard int ueventOpen(); void ueventProcessRead(); void ueventProcessUEvent(const UEvent& uevent); + void ueventProcessAction(const std::string& action, const std::string& sysfs_devpath); int ueventEnumerateDevices(); int ueventEnumerateTriggerDevice(const std::string& devpath, const std::string& buspath); diff --git a/src/Library/UMockdevDeviceManager.cpp b/src/Library/UMockdevDeviceManager.cpp index 47e100ca..0da609b1 100644 --- a/src/Library/UMockdevDeviceManager.cpp +++ b/src/Library/UMockdevDeviceManager.cpp @@ -584,6 +584,11 @@ namespace usbguard } } + void UMockdevDeviceManager::scan(const std::string& devpath) + { + USBGUARD_LOG(Trace) << "devpath=" << devpath; + } + std::shared_ptr UMockdevDeviceManager::applyDevicePolicy(uint32_t id, Rule::Target target) { USBGUARD_LOG(Trace) << "id=" << id diff --git a/src/Library/UMockdevDeviceManager.hpp b/src/Library/UMockdevDeviceManager.hpp index 0880a27d..71e4b207 100644 --- a/src/Library/UMockdevDeviceManager.hpp +++ b/src/Library/UMockdevDeviceManager.hpp @@ -83,6 +83,7 @@ namespace usbguard void start() override; void stop() override; void scan() override; + void scan(const std::string& devpath) override; std::shared_ptr applyDevicePolicy(uint32_t id, Rule::Target target) override; void insertDevice(std::shared_ptr device); diff --git a/src/Library/public/usbguard/DeviceManager.hpp b/src/Library/public/usbguard/DeviceManager.hpp index ff14955a..dd4eadb7 100644 --- a/src/Library/public/usbguard/DeviceManager.hpp +++ b/src/Library/public/usbguard/DeviceManager.hpp @@ -59,6 +59,7 @@ namespace usbguard virtual void start() = 0; virtual void stop() = 0; virtual void scan() = 0; + virtual void scan(const std::string& devpath) = 0; void setRestoreControllerDeviceState(bool enabled); bool getRestoreControllerDeviceState() const;