* 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"
        }
 
        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;
        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);
 }
                               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
         */
        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;
 }
        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;
        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