]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: use the initial user namespace in suitable {from,make}_kuid() calls
authorNick Alcock <nick.alcock@oracle.com>
Fri, 8 May 2015 13:20:37 +0000 (14:20 +0100)
committerKris Van Hees <kris.van.hees@oracle.com>
Tue, 21 Jul 2015 06:51:24 +0000 (02:51 -0400)
There are several places in DTrace (mostly related to privileged or destructive
operations or unprivileged tracing) where we try to compare uids for equality,
thus need to convert them from or to kuid_ts so we can do that.  We want to look
in the initial user namespace for this (since it is only in that namespace that
all uids on the system are unambiguous).  We were doing this by passing a NULL
to from_kuid() / make_kuid(), but in the presence of CONFIG_USER_NS this results
in dereferencing a null pointer.

So acquire the initial user namespace from a temporary kernel-thread creds
structure, and use it in all such places.

Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Acked-by: Kris Van Hees <kris.van.hees@oracle.com>
dtrace/dtrace_dev.c
dtrace/dtrace_match.c
dtrace/dtrace_probe.c
dtrace/dtrace_ptofapi.c
dtrace/include/dtrace/dtrace_impl.h

index 7c0317a3ec0fffccbf4fb4bc4c86ec7e2503b7ba..268df6d4bec68152209567684d6659b971a2d86d 100644 (file)
@@ -71,6 +71,8 @@ static int                    dtrace_toxranges_max;
 struct kmem_cache              *dtrace_state_cachep;
 struct kmem_cache              *dtrace_pdata_cachep;
 
+struct user_namespace          *init_user_namespace;
+
 static dtrace_pattr_t          dtrace_provider_attr = {
 { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
@@ -1379,6 +1381,7 @@ int dtrace_dev_init(void)
 {
        dtrace_provider_id_t    id;
        int                     rc = 0;
+       struct cred             *cred;
 
        /*
         * Register the device for the DTrace core.
@@ -1475,6 +1478,17 @@ int dtrace_dev_init(void)
                                offsetof(dtrace_probe_t, dtpr_nextname),
                                offsetof(dtrace_probe_t, dtpr_prevname));
 
+       /*
+        * FIXME, this is a very nonstandard pattern for OOM-checking but
+        * unavoidable given the absence of OOM-checking elsewhere in this
+        * function.
+        */
+       cred = prepare_kernel_cred(NULL);
+       if (cred) {
+               init_user_namespace = cred->user_ns;
+               put_cred(cred);
+       }
+
        /*
         * Ensure that the X configuration parameter has a legal value.
         */
index b9dccfcce1002560275e80bbed8145420e4f5928..12f8be8ad00662b1ac04a270c8c6b3a55962f72c 100644 (file)
@@ -46,7 +46,8 @@ int dtrace_match_priv(const dtrace_probe_t *prp, uint32_t priv, kuid_t uid)
                        return 0;
 
                if (((ppriv & ~match) & DTRACE_PRIV_OWNER) != 0 &&
-                   !uid_eq(uid, make_kuid(NULL, prp->dtpr_provider->dtpv_priv.dtpp_uid)))
+                   !uid_eq(uid, make_kuid(init_user_namespace,
+                              prp->dtpr_provider->dtpv_priv.dtpp_uid)))
                        return 0;
        }
 
index 35ab7f1d82b135ee8b0f8942f9fde168e7f1bbb5..05c7359525638af10e703ac31c0e909a6271bee2 100644 (file)
@@ -1352,7 +1352,8 @@ dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t prid, const char *mod,
        pkey.dtpk_id = DTRACE_IDNONE;
 
        mutex_lock(&dtrace_lock);
-       match = dtrace_match(&pkey, DTRACE_PRIV_ALL, make_kuid(NULL, 0),
+       match = dtrace_match(&pkey, DTRACE_PRIV_ALL,
+                            make_kuid(init_user_namespace, 0),
                             dtrace_probe_lookup_match, &id);
        mutex_unlock(&dtrace_lock);
 
index cf19589c88f4412d1b8b6ef0cef79bd2d77ff9a1..532a1e9bf1912aa32ca826d737104e2cf19e9304 100644 (file)
@@ -204,7 +204,7 @@ int dtrace_register(const char *name, const dtrace_pattr_t *pap, uint32_t priv,
 
        if (cr != NULL) {
                provider->dtpv_priv.dtpp_uid =
-                       from_kuid(NULL, get_cred(cr)->uid);
+                       from_kuid(init_user_namespace, get_cred(cr)->uid);
                put_cred(cr);
        }
 
index 8f816a663f0fbf86e2cb14968fa021670cbae06f..e681855cb6c50254cb8c409c2e6bd494f8e736cb 100644 (file)
@@ -830,6 +830,8 @@ extern dtrace_id_t          dtrace_probeid_error;
 
 extern dtrace_dynvar_t         dtrace_dynhash_sink;
 
+extern struct user_namespace   *init_user_namespace;
+
 extern int dtrace_dstate_init(dtrace_dstate_t *, size_t);
 extern void dtrace_dstate_fini(dtrace_dstate_t *);
 extern void dtrace_vstate_fini(dtrace_vstate_t *);