|
@@ -4,6 +4,7 @@
|
|
|
* Author: Mathieu Poirier <mathieu.poirier@linaro.org>
|
|
|
*/
|
|
|
|
|
|
+#include <linux/pid_namespace.h>
|
|
|
#include <linux/pm_runtime.h>
|
|
|
#include <linux/sysfs.h>
|
|
|
#include "coresight-etm4x.h"
|
|
@@ -250,10 +251,8 @@ static ssize_t reset_store(struct device *dev,
|
|
|
}
|
|
|
|
|
|
config->ctxid_idx = 0x0;
|
|
|
- for (i = 0; i < drvdata->numcidc; i++) {
|
|
|
+ for (i = 0; i < drvdata->numcidc; i++)
|
|
|
config->ctxid_pid[i] = 0x0;
|
|
|
- config->ctxid_vpid[i] = 0x0;
|
|
|
- }
|
|
|
|
|
|
config->ctxid_mask0 = 0x0;
|
|
|
config->ctxid_mask1 = 0x0;
|
|
@@ -1637,9 +1636,16 @@ static ssize_t ctxid_pid_show(struct device *dev,
|
|
|
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
|
|
struct etmv4_config *config = &drvdata->config;
|
|
|
|
|
|
+ /*
|
|
|
+ * Don't use contextID tracing if coming from a PID namespace. See
|
|
|
+ * comment in ctxid_pid_store().
|
|
|
+ */
|
|
|
+ if (task_active_pid_ns(current) != &init_pid_ns)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
spin_lock(&drvdata->spinlock);
|
|
|
idx = config->ctxid_idx;
|
|
|
- val = (unsigned long)config->ctxid_vpid[idx];
|
|
|
+ val = (unsigned long)config->ctxid_pid[idx];
|
|
|
spin_unlock(&drvdata->spinlock);
|
|
|
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
|
|
|
}
|
|
@@ -1649,10 +1655,22 @@ static ssize_t ctxid_pid_store(struct device *dev,
|
|
|
const char *buf, size_t size)
|
|
|
{
|
|
|
u8 idx;
|
|
|
- unsigned long vpid, pid;
|
|
|
+ unsigned long pid;
|
|
|
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
|
|
struct etmv4_config *config = &drvdata->config;
|
|
|
|
|
|
+ /*
|
|
|
+ * When contextID tracing is enabled the tracers will insert the
|
|
|
+ * value found in the contextID register in the trace stream. But if
|
|
|
+ * a process is in a namespace the PID of that process as seen from the
|
|
|
+ * namespace won't be what the kernel sees, something that makes the
|
|
|
+ * feature confusing and can potentially leak kernel only information.
|
|
|
+ * As such refuse to use the feature if @current is not in the initial
|
|
|
+ * PID namespace.
|
|
|
+ */
|
|
|
+ if (task_active_pid_ns(current) != &init_pid_ns)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
/*
|
|
|
* only implemented when ctxid tracing is enabled, i.e. at least one
|
|
|
* ctxid comparator is implemented and ctxid is greater than 0 bits
|
|
@@ -1660,15 +1678,12 @@ static ssize_t ctxid_pid_store(struct device *dev,
|
|
|
*/
|
|
|
if (!drvdata->ctxid_size || !drvdata->numcidc)
|
|
|
return -EINVAL;
|
|
|
- if (kstrtoul(buf, 16, &vpid))
|
|
|
+ if (kstrtoul(buf, 16, &pid))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- pid = coresight_vpid_to_pid(vpid);
|
|
|
-
|
|
|
spin_lock(&drvdata->spinlock);
|
|
|
idx = config->ctxid_idx;
|
|
|
config->ctxid_pid[idx] = (u64)pid;
|
|
|
- config->ctxid_vpid[idx] = (u64)vpid;
|
|
|
spin_unlock(&drvdata->spinlock);
|
|
|
return size;
|
|
|
}
|
|
@@ -1682,6 +1697,13 @@ static ssize_t ctxid_masks_show(struct device *dev,
|
|
|
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
|
|
struct etmv4_config *config = &drvdata->config;
|
|
|
|
|
|
+ /*
|
|
|
+ * Don't use contextID tracing if coming from a PID namespace. See
|
|
|
+ * comment in ctxid_pid_store().
|
|
|
+ */
|
|
|
+ if (task_active_pid_ns(current) != &init_pid_ns)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
spin_lock(&drvdata->spinlock);
|
|
|
val1 = config->ctxid_mask0;
|
|
|
val2 = config->ctxid_mask1;
|
|
@@ -1698,6 +1720,13 @@ static ssize_t ctxid_masks_store(struct device *dev,
|
|
|
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
|
|
struct etmv4_config *config = &drvdata->config;
|
|
|
|
|
|
+ /*
|
|
|
+ * Don't use contextID tracing if coming from a PID namespace. See
|
|
|
+ * comment in ctxid_pid_store().
|
|
|
+ */
|
|
|
+ if (task_active_pid_ns(current) != &init_pid_ns)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
/*
|
|
|
* only implemented when ctxid tracing is enabled, i.e. at least one
|
|
|
* ctxid comparator is implemented and ctxid is greater than 0 bits
|