aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-base-manager.c4
-rw-r--r--src/mm-context.c12
-rw-r--r--src/mm-filter.c78
-rw-r--r--src/mm-filter.h77
4 files changed, 142 insertions, 29 deletions
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
index a77b4f1b..6961ca90 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -1139,7 +1139,9 @@ initable_init (GInitable *initable,
#endif
/* Create filter */
- priv->filter = mm_filter_new (priv->filter_policy);
+ priv->filter = mm_filter_new (priv->filter_policy, error);
+ if (!priv->filter)
+ return FALSE;
/* Create plugin manager */
priv->plugin_manager = mm_plugin_manager_new (priv->plugin_dir, error);
diff --git a/src/mm-context.c b/src/mm-context.c
index 3dac3903..88d71384 100644
--- a/src/mm-context.c
+++ b/src/mm-context.c
@@ -58,6 +58,16 @@ filter_policy_option_arg (const gchar *option_name,
return TRUE;
}
+ if (!g_ascii_strcasecmp (value, "strict")) {
+ filter_policy = MM_FILTER_POLICY_STRICT;
+ return TRUE;
+ }
+
+ if (!g_ascii_strcasecmp (value, "paranoid")) {
+ filter_policy = MM_FILTER_POLICY_PARANOID;
+ return TRUE;
+ }
+
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Invalid filter policy value given: %s",
value);
@@ -67,7 +77,7 @@ filter_policy_option_arg (const gchar *option_name,
static const GOptionEntry entries[] = {
{
"filter-policy", 0, 0, G_OPTION_ARG_CALLBACK, filter_policy_option_arg,
- "Filter policy: one of DEFAULT, WHITELIST-ONLY",
+ "Filter policy: one of DEFAULT, WHITELIST-ONLY, STRICT, PARANOID",
"[POLICY]"
},
{
diff --git a/src/mm-filter.c b/src/mm-filter.c
index 50a7dffa..087166f0 100644
--- a/src/mm-filter.c
+++ b/src/mm-filter.c
@@ -81,6 +81,9 @@ mm_filter_port (MMFilter *self,
if ((self->priv->enabled_rules & MM_FILTER_RULE_TTY) &&
(g_strcmp0 (subsystem, "tty") == 0)) {
const gchar *physdev_subsystem;
+ const gchar *driver;
+
+ /* Blacklist rules first */
/* Ignore blacklisted tty devices. */
if ((self->priv->enabled_rules & MM_FILTER_RULE_TTY_BLACKLIST) &&
@@ -97,6 +100,8 @@ mm_filter_port (MMFilter *self,
return FALSE;
}
+ /* Mixed blacklist/whitelist rules */
+
/* If the physdev is a 'platform' or 'pnp' device that's not whitelisted, ignore it */
physdev_subsystem = mm_kernel_device_get_physdev_subsystem (port);
if ((self->priv->enabled_rules & MM_FILTER_RULE_TTY_PLATFORM_DRIVER) &&
@@ -109,8 +114,41 @@ mm_filter_port (MMFilter *self,
return TRUE;
}
- /* Otherwise, TTY probed */
- return TRUE;
+ /* Default allowed? */
+ if (self->priv->enabled_rules & MM_FILTER_RULE_TTY_DEFAULT_ALLOWED) {
+ mm_dbg ("[filter] (%s/%s) port allowed", subsystem, name);
+ return TRUE;
+ }
+
+ /* Whitelist rules last */
+
+ /* If the TTY kernel driver is one expected modem kernel driver, allow it */
+ driver = mm_kernel_device_get_driver (port);
+ if ((self->priv->enabled_rules & MM_FILTER_RULE_TTY_DRIVER) &&
+ (!g_strcmp0 (driver, "option") ||
+ !g_strcmp0 (driver, "qcserial") ||
+ !g_strcmp0 (driver, "sierra"))) {
+ mm_dbg ("[filter] (%s/%s): port allowed: modem-specific kernel driver detected", subsystem, name);
+ return TRUE;
+ }
+
+ /* If the TTY kernel driver is cdc-acm and the interface is class=2/subclass=2/protocol=1, allow it */
+ if ((self->priv->enabled_rules & MM_FILTER_RULE_TTY_ACM_INTERFACE) &&
+ (!g_strcmp0 (driver, "cdc_acm")) &&
+ (mm_kernel_device_get_interface_class (port) == 2) &&
+ (mm_kernel_device_get_interface_subclass (port) == 2) &&
+ (mm_kernel_device_get_interface_protocol (port) == 1)) {
+ mm_dbg ("[filter] (%s/%s): port allowed: cdc-acm interface reported AT-capable", subsystem, name);
+ return TRUE;
+ }
+
+ /* Default forbidden? */
+ if (self->priv->enabled_rules & MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN) {
+ mm_dbg ("[filter] (%s/%s) port forbidden", subsystem, name);
+ return FALSE;
+ }
+
+ g_assert_not_reached ();
}
/* Otherwise forbidden */
@@ -157,13 +195,30 @@ filter_rule_env_process (MMFilterRule enabled_rules)
/*****************************************************************************/
+/* If TTY rule enabled, either DEFAULT_ALLOWED or DEFAULT_FORBIDDEN must be set. */
+#define VALIDATE_RULE_TTY(rules) (!(rules & MM_FILTER_RULE_TTY) || \
+ ((rules & (MM_FILTER_RULE_TTY_DEFAULT_ALLOWED | MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN)) && \
+ ((rules & (MM_FILTER_RULE_TTY_DEFAULT_ALLOWED | MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN)) != \
+ (MM_FILTER_RULE_TTY_DEFAULT_ALLOWED | MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN))))
+
MMFilter *
-mm_filter_new (MMFilterRule enabled_rules)
+mm_filter_new (MMFilterRule enabled_rules,
+ GError **error)
{
- MMFilter *self;
+ MMFilter *self;
+ MMFilterRule updated_rules;
+
+ /* The input enabled rules are coming from predefined filter profiles. */
+ g_assert (VALIDATE_RULE_TTY (enabled_rules));
+ updated_rules = filter_rule_env_process (enabled_rules);
+ if (!VALIDATE_RULE_TTY (updated_rules)) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "Invalid rules after processing envvars");
+ return NULL;
+ }
self = g_object_new (MM_TYPE_FILTER,
- MM_FILTER_ENABLED_RULES, filter_rule_env_process (enabled_rules),
+ MM_FILTER_ENABLED_RULES, updated_rules,
NULL);
#define RULE_ENABLED_STR(flag) ((self->priv->enabled_rules & flag) ? "yes" : "no")
@@ -173,12 +228,21 @@ mm_filter_new (MMFilterRule enabled_rules)
mm_dbg ("[filter] virtual devices forbidden: %s", RULE_ENABLED_STR (MM_FILTER_RULE_VIRTUAL));
mm_dbg ("[filter] net devices allowed: %s", RULE_ENABLED_STR (MM_FILTER_RULE_NET));
mm_dbg ("[filter] cdc-wdm devices allowed: %s", RULE_ENABLED_STR (MM_FILTER_RULE_CDC_WDM));
- mm_dbg ("[filter] tty devices allowed: %s", RULE_ENABLED_STR (MM_FILTER_RULE_TTY));
if (self->priv->enabled_rules & MM_FILTER_RULE_TTY) {
+ mm_dbg ("[filter] tty devices:");
mm_dbg ("[filter] blacklist applied: %s", RULE_ENABLED_STR (MM_FILTER_RULE_TTY_BLACKLIST));
mm_dbg ("[filter] manual scan only applied: %s", RULE_ENABLED_STR (MM_FILTER_RULE_TTY_MANUAL_SCAN_ONLY));
mm_dbg ("[filter] platform driver check: %s", RULE_ENABLED_STR (MM_FILTER_RULE_TTY_PLATFORM_DRIVER));
- }
+ mm_dbg ("[filter] driver check: %s", RULE_ENABLED_STR (MM_FILTER_RULE_TTY_DRIVER));
+ mm_dbg ("[filter] cdc-acm interface check: %s", RULE_ENABLED_STR (MM_FILTER_RULE_TTY_ACM_INTERFACE));
+ if (self->priv->enabled_rules & MM_FILTER_RULE_TTY_DEFAULT_ALLOWED)
+ mm_dbg ("[filter] default: allowed");
+ else if (self->priv->enabled_rules & MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN)
+ mm_dbg ("[filter] default: forbidden");
+ else
+ g_assert_not_reached ();
+ } else
+ mm_dbg ("[filter] tty devices: no");
#undef RULE_ENABLED_STR
diff --git a/src/mm-filter.h b/src/mm-filter.h
index ba8afdbe..6c4e7e49 100644
--- a/src/mm-filter.h
+++ b/src/mm-filter.h
@@ -44,26 +44,33 @@ typedef struct {
GType mm_filter_get_type (void);
typedef enum { /*< underscore_name=mm_filter_rule >*/
- MM_FILTER_RULE_NONE = 0,
- MM_FILTER_RULE_EXPLICIT_WHITELIST = 1 << 0,
- MM_FILTER_RULE_VIRTUAL = 1 << 1,
- MM_FILTER_RULE_NET = 1 << 2,
- MM_FILTER_RULE_CDC_WDM = 1 << 3,
- MM_FILTER_RULE_TTY = 1 << 4,
- MM_FILTER_RULE_TTY_BLACKLIST = 1 << 5,
- MM_FILTER_RULE_TTY_MANUAL_SCAN_ONLY = 1 << 6,
- MM_FILTER_RULE_TTY_PLATFORM_DRIVER = 1 << 7,
+ MM_FILTER_RULE_NONE = 0,
+ MM_FILTER_RULE_EXPLICIT_WHITELIST = 1 << 0,
+ MM_FILTER_RULE_VIRTUAL = 1 << 1,
+ MM_FILTER_RULE_NET = 1 << 2,
+ MM_FILTER_RULE_CDC_WDM = 1 << 3,
+ MM_FILTER_RULE_TTY = 1 << 4,
+ MM_FILTER_RULE_TTY_BLACKLIST = 1 << 5,
+ MM_FILTER_RULE_TTY_MANUAL_SCAN_ONLY = 1 << 6,
+ MM_FILTER_RULE_TTY_PLATFORM_DRIVER = 1 << 7,
+ MM_FILTER_RULE_TTY_DEFAULT_ALLOWED = 1 << 8,
+ MM_FILTER_RULE_TTY_DRIVER = 1 << 9,
+ MM_FILTER_RULE_TTY_ACM_INTERFACE = 1 << 10,
+ MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN = 1 << 11,
} MMFilterRule;
-#define MM_FILTER_RULE_ALL \
- (MM_FILTER_RULE_EXPLICIT_WHITELIST | \
- MM_FILTER_RULE_VIRTUAL | \
- MM_FILTER_RULE_NET | \
- MM_FILTER_RULE_CDC_WDM | \
- MM_FILTER_RULE_TTY | \
- MM_FILTER_RULE_TTY_BLACKLIST | \
- MM_FILTER_RULE_TTY_MANUAL_SCAN_ONLY | \
- MM_FILTER_RULE_TTY_PLATFORM_DRIVER)
+#define MM_FILTER_RULE_ALL \
+ (MM_FILTER_RULE_EXPLICIT_WHITELIST | \
+ MM_FILTER_RULE_VIRTUAL | \
+ MM_FILTER_RULE_NET | \
+ MM_FILTER_RULE_CDC_WDM | \
+ MM_FILTER_RULE_TTY | \
+ MM_FILTER_RULE_TTY_BLACKLIST | \
+ MM_FILTER_RULE_TTY_MANUAL_SCAN_ONLY | \
+ MM_FILTER_RULE_TTY_PLATFORM_DRIVER | \
+ MM_FILTER_RULE_TTY_DEFAULT_ALLOWED | \
+ MM_FILTER_RULE_TTY_DRIVER | \
+ MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN)
/* This is the default ModemManager policy that tries to automatically probe
* device ports unless they're blacklisted in some way or another. */
@@ -75,13 +82,43 @@ typedef enum { /*< underscore_name=mm_filter_rule >*/
MM_FILTER_RULE_TTY | \
MM_FILTER_RULE_TTY_BLACKLIST | \
MM_FILTER_RULE_TTY_MANUAL_SCAN_ONLY | \
- MM_FILTER_RULE_TTY_PLATFORM_DRIVER)
+ MM_FILTER_RULE_TTY_PLATFORM_DRIVER | \
+ MM_FILTER_RULE_TTY_DEFAULT_ALLOWED)
+
+/* This is a stricter policy which will only automatically probe device ports
+ * if they are allowed by any of the automatic whitelist rules. */
+#define MM_FILTER_POLICY_STRICT \
+ (MM_FILTER_RULE_EXPLICIT_WHITELIST | \
+ MM_FILTER_RULE_VIRTUAL | \
+ MM_FILTER_RULE_NET | \
+ MM_FILTER_RULE_CDC_WDM | \
+ MM_FILTER_RULE_TTY | \
+ MM_FILTER_RULE_TTY_PLATFORM_DRIVER | \
+ MM_FILTER_RULE_TTY_DRIVER | \
+ MM_FILTER_RULE_TTY_ACM_INTERFACE | \
+ MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN)
+
+/* This is equivalent to the strict policy, but also applying the device
+ * blacklists explicitly */
+#define MM_FILTER_POLICY_PARANOID \
+ (MM_FILTER_RULE_EXPLICIT_WHITELIST | \
+ MM_FILTER_RULE_VIRTUAL | \
+ MM_FILTER_RULE_NET | \
+ MM_FILTER_RULE_CDC_WDM | \
+ MM_FILTER_RULE_TTY | \
+ MM_FILTER_RULE_TTY_BLACKLIST | \
+ MM_FILTER_RULE_TTY_MANUAL_SCAN_ONLY | \
+ MM_FILTER_RULE_TTY_PLATFORM_DRIVER | \
+ MM_FILTER_RULE_TTY_DRIVER | \
+ MM_FILTER_RULE_TTY_ACM_INTERFACE | \
+ MM_FILTER_RULE_TTY_DEFAULT_FORBIDDEN)
/* This policy only allows using device ports explicitly whitelisted via
* udev rules. i.e. ModemManager won't do any kind of automatic probing. */
#define MM_FILTER_POLICY_WHITELIST_ONLY MM_FILTER_RULE_EXPLICIT_WHITELIST
-MMFilter *mm_filter_new (MMFilterRule enabled_rules);
+MMFilter *mm_filter_new (MMFilterRule enabled_rules,
+ GError **error);
gboolean mm_filter_port (MMFilter *self,
MMKernelDevice *port,