Automatically detect AppArmor support at runtime
UserMetricsService::Authentication::getConfinementContext
uses an AppArmor call to return the confinement context. If USERMETRICS_NO_AUTH
envvar is set, then the session is treated as unconfined. This works in AppArmor-less contexts, as long as USERMETRICS_NO_AUTH
is set.
USERMETRICS_NO_AUTH
is neat, but relies on knowledge that it even exists to work. If USERMETRICS_NO_AUTH
wasn't set in a session that doesn't use AppArmor, then issues will occur. aa_gettaskcon
will fail and a confinement context of ""
will be returned. Data sources with this empty context that get put into the database will not be found on subsequent DBusUserMetrics::createDataSource
calls, so the entry is assumed to not be present yet. The attempt to create said entry that follows will then fail, since an entry with the same unique name already exists, and usermetricservice will throw an exception and die:
SQL query "SELECT \"usermetricsservice::datasource\".\"id\", \"usermetricsservice::datasource\".\"name\", \"usermetricsservice::datasource\".\"secret\", \"usermetricsservice::datasource\".\"formatString\", \"usermetricsservice::datasource\".\"emptyDataString\", \"usermetricsservice::datasource\".\"textDomain\", \"usermetricsservice::datasource\".\"metricType\", \"usermetricsservice::datasource\".\"hasMinimum\", \"usermetricsservice::datasource\".\"minimum\", \"usermetricsservice::datasource\".\"hasMaximum\", \"usermetricsservice::datasource\".\"maximum\" FROM \"usermetricsservice::datasource\" WHERE \"usermetricsservice::datasource\".\"name\" = ? AND \"usermetricsservice::datasource\".\"secret\" = ?"
SQL :a = test-messages-sent
SQL :bb =
SQL query "SELECT \"usermetricsservice::datasource\".\"id\", \"usermetricsservice::datasource\".\"name\", \"usermetricsservice::datasource\".\"secret\", \"usermetricsservice::datasource\".\"formatString\", \"usermetricsservice::datasource\".\"emptyDataString\", \"usermetricsservice::datasource\".\"textDomain\", \"usermetricsservice::datasource\".\"metricType\", \"usermetricsservice::datasource\".\"hasMinimum\", \"usermetricsservice::datasource\".\"minimum\", \"usermetricsservice::datasource\".\"hasMaximum\", \"usermetricsservice::datasource\".\"maximum\" FROM \"usermetricsservice::datasource\" WHERE \"usermetricsservice::datasource\".\"name\" = ? AND \"usermetricsservice::datasource\".\"secret\" = ?"
SQL :a = test-messages-sent
SQL :bb = unconfined
SQL query "INSERT INTO \"usermetricsservice::datasource\" (\"emptyDataString\", \"formatString\", \"hasMaximum\", \"hasMinimum\", \"maximum\", \"metricType\", \"minimum\", \"name\", \"secret\", \"textDomain\") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
SQL :a = No text messages send today
SQL :bb = <b>%1</b> text messages send today
SQL :bc = false
SQL :bd = true
SQL :be = 0
SQL :bf = 0
SQL :bg = 0
SQL :bh = text-messages-sent
SQL :bi =
SQL :bj = telephony-service
[the next time telephony-service-indicator gets restarted]
SQL query "SELECT \"usermetricsservice::datasource\".\"id\", \"usermetricsservice::datasource\".\"name\", \"usermetricsservice::datasource\".\"secret\", \"usermetricsservice::datasource\".\"formatString\", \"usermetricsservice::datasource\".\"emptyDataString\", \"usermetricsservice::datasource\".\"textDomain\", \"usermetricsservice::datasource\".\"metricType\", \"usermetricsservice::datasource\".\"hasMinimum\", \"usermetricsservice::datasource\".\"minimum\", \"usermetricsservice::datasource\".\"hasMaximum\", \"usermetricsservice::datasource\".\"maximum\" FROM \"usermetricsservice::datasource\" WHERE \"usermetricsservice::datasource\".\"name\" = ? AND \"usermetricsservice::datasource\".\"secret\" = ?"
SQL :a = test-messages-sent
SQL :bb =
SQL query "SELECT \"usermetricsservice::datasource\".\"id\", \"usermetricsservice::datasource\".\"name\", \"usermetricsservice::datasource\".\"secret\", \"usermetricsservice::datasource\".\"formatString\", \"usermetricsservice::datasource\".\"emptyDataString\", \"usermetricsservice::datasource\".\"textDomain\", \"usermetricsservice::datasource\".\"metricType\", \"usermetricsservice::datasource\".\"hasMinimum\", \"usermetricsservice::datasource\".\"minimum\", \"usermetricsservice::datasource\".\"hasMaximum\", \"usermetricsservice::datasource\".\"maximum\" FROM \"usermetricsservice::datasource\" WHERE \"usermetricsservice::datasource\".\"name\" = ? AND \"usermetricsservice::datasource\".\"secret\" = ?"
SQL :a = test-messages-sent
SQL :bb = unconfined
SQL query "INSERT INTO \"usermetricsservice::datasource\" (\"emptyDataString\", \"formatString\", \"hasMaximum\", \"hasMinimum\", \"maximum\", \"metricType\", \"minimum\", \"name\", \"secret\", \"textDomain\") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
SQL :a = No text messages send today
SQL :bb = <b>%1</b> text messages send today
SQL :bc = false
SQL :bd = true
SQL :be = 0
SQL :bf = 0
SQL :bg = 0
SQL :bh = text-messages-sent
SQL :bi =
SQL :bj = telephony-service
SQL error QSqlError("19", "Unable to fetch row", "UNIQUE constraint failed: usermetricsservice::datasource.name, usermetricsservice::datasource.secret")
Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt.
You must not let any exception whatsoever propagate through Qt code.
If that is not possible, in Qt 5 you must at least reimplement
QCoreApplication::notify() and catch all exceptions there.
User-metrics service error: Could not save data source
Ideas/Suggestions:
- Detect if AppArmor is running, and automatically go the
"uncontained"
route if it's not. Kind of like how content-hub!33 would ask the D-Bus session if AppArmor D-Bus mediation is in use before making any assumptions about security context values, and falls back to"uncontained"
for compatibility. An idea: Checkingaa_gettaskcon
return value &errno
to differentiate "AA not running" from "failed to get context"? - Maybe look into why this subsequent query fails? The entry does get put into the sqlite database, but
QDjangoQuerySetPrivate::sqlFetch
doesn't find it in its results. Seems weird… Maybechar *con(0);
should instead be initialised to"unconfined"
if havingNULL
there is just not supported? - Maybe document the existence of
USERMETRICS_NO_AUTH
, what it does & when it should be used?