diff options
-rw-r--r-- | src/mm-base-manager.c | 4 | ||||
-rw-r--r-- | src/mm-context.c | 12 | ||||
-rw-r--r-- | src/mm-filter.c | 78 | ||||
-rw-r--r-- | src/mm-filter.h | 77 |
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, |