From: Nick Alcock Date: Fri, 8 May 2015 13:20:37 +0000 (+0100) Subject: dtrace: use the initial user namespace in suitable {from,make}_kuid() calls X-Git-Tag: v4.1.12-111.0.20170907_2225~3^2~3^2~75 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=429593d67da5ad978317cbb340a7fab0b4c8c5d8;p=users%2Fjedix%2Flinux-maple.git dtrace: use the initial user namespace in suitable {from,make}_kuid() calls 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 Acked-by: Kris Van Hees --- diff --git a/dtrace/dtrace_dev.c b/dtrace/dtrace_dev.c index 7c0317a3ec0ff..268df6d4bec68 100644 --- a/dtrace/dtrace_dev.c +++ b/dtrace/dtrace_dev.c @@ -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. */ diff --git a/dtrace/dtrace_match.c b/dtrace/dtrace_match.c index b9dccfcce1002..12f8be8ad0066 100644 --- a/dtrace/dtrace_match.c +++ b/dtrace/dtrace_match.c @@ -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; } diff --git a/dtrace/dtrace_probe.c b/dtrace/dtrace_probe.c index 35ab7f1d82b13..05c7359525638 100644 --- a/dtrace/dtrace_probe.c +++ b/dtrace/dtrace_probe.c @@ -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); diff --git a/dtrace/dtrace_ptofapi.c b/dtrace/dtrace_ptofapi.c index cf19589c88f44..532a1e9bf1912 100644 --- a/dtrace/dtrace_ptofapi.c +++ b/dtrace/dtrace_ptofapi.c @@ -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); } diff --git a/dtrace/include/dtrace/dtrace_impl.h b/dtrace/include/dtrace/dtrace_impl.h index 8f816a663f0fb..e681855cb6c50 100644 --- a/dtrace/include/dtrace/dtrace_impl.h +++ b/dtrace/include/dtrace/dtrace_impl.h @@ -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 *);