From 2b5e1380aace4462f1532a7f8431bfa90d599330 Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Tue, 10 Feb 2015 12:18:39 -0500 Subject: [PATCH] dtrace: support building on UEK4 Support building DTrace modules on UEK4. Various things changed at the kernel level between UEK3 and UEK4 that require adjustments in the building of the DTrace modules. - ARCH no longer reflects the difference between x86 and x86_64. So, we now use UTS_MACHINE to drive the architecture-specific portions of DTrace during the building process. - The trick used to implement a direct call probe in dt_test_probe() required updating to avoid compiler warnings/errors. It is a little bit less "ugly" now :) - The uid and gid used in the task structure now uses kuid_t and kgid_t as datatypes, which are no longer numeric values but rather a struct. - The API for the IDR facility in the Linux kernel changed. - The flush_delayed_work_sync() function has been removed. Source code has been updated to use flush_delayed_work(). - The mechanism to enforce turning preemption on and off has been updated. Orabug: 20456825 Signed-off-by: Kris Van Hees Acked-by: Nick Alcock --- dtrace/Kbuild | 7 ++-- dtrace/dt_test_dev.c | 8 +++- dtrace/dtrace_dev.c | 4 +- dtrace/dtrace_dif.c | 4 +- dtrace/dtrace_ecb.c | 13 +++--- dtrace/dtrace_match.c | 10 ++--- dtrace/dtrace_priv.c | 12 +++--- dtrace/dtrace_probe.c | 42 +++++++++----------- dtrace/dtrace_ptofapi.c | 3 +- dtrace/dtrace_state.c | 10 ++--- dtrace/dtrace_util.c | 2 +- dtrace/fasttrap_dev.c | 2 +- dtrace/include/dtrace/dtrace_impl.h | 8 ++-- dtrace/include/dtrace/dtrace_impl_defines.h | 6 +-- dtrace/include/uapi/linux/dtrace/stability.h | 3 +- 15 files changed, 66 insertions(+), 68 deletions(-) diff --git a/dtrace/Kbuild b/dtrace/Kbuild index a567bb8c9b69..ae8f15b81d9f 100644 --- a/dtrace/Kbuild +++ b/dtrace/Kbuild @@ -25,7 +25,7 @@ # Use is subject to license terms. EXTRA_CFLAGS := -I$(src)/include -I$(src)/include/uapi \ - -I$(src)/include/$(ARCH) + -I$(src)/include/$(UTS_MACHINE) obj-$(CONFIG_DT_CORE) += dtrace.o obj-$(CONFIG_DT_FASTTRAP) += fasttrap.o @@ -36,7 +36,8 @@ obj-$(CONFIG_DT_DT_TEST) += dt_test.o obj-$(CONFIG_DT_DT_PERF) += dt_perf.o dtrace-y := dtrace_mod.o dtrace_dev.o \ - dtrace_asm_$(ARCH).o dtrace_isa_$(ARCH).o \ + dtrace_asm_$(UTS_MACHINE).o \ + dtrace_isa_$(UTS_MACHINE).o \ dtrace_actdesc.o dtrace_anon.o \ dtrace_buffer.o dtrace_dif.o dtrace_dof.o \ dtrace_ecb.o dtrace_enable.o \ @@ -47,7 +48,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \ dtrace_spec.o dtrace_state.o dtrace_util.o fasttrap-y := fasttrap_mod.o fasttrap_dev.o profile-y := profile_mod.o profile_dev.o -sdt-y := sdt_mod.o sdt_dev.o sdt_$(ARCH).o +sdt-y := sdt_mod.o sdt_dev.o sdt_$(UTS_MACHINE).o systrace-y := systrace_mod.o systrace_dev.o dt_test-y := dt_test_mod.o dt_test_dev.o dt_perf-y := dt_perf_mod.o dt_perf_dev.o diff --git a/dtrace/dt_test_dev.c b/dtrace/dt_test_dev.c index 33cec8e396b7..9292da8e34cd 100644 --- a/dtrace/dt_test_dev.c +++ b/dtrace/dt_test_dev.c @@ -62,6 +62,12 @@ void dt_test_destroy(void *arg, dtrace_id_t id, void *parg) { } +void probe_p(dtrace_id_t pid, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, + uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6, + uintptr_t arg7, uintptr_t arg8, uintptr_t arg9) +{ +} + /* * Direct calling into dtrace_probe() when passing more than 5 parameters to * the probe requires a stub function. Otherwise we may not be able to get @@ -77,7 +83,7 @@ void dt_test_probe(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, * Not at all... * But we're doing it anyway... */ - void (*probe_fn)() = (void *)&dtrace_probe; + typeof(probe_p) *probe_fn = (void *)&dtrace_probe; probe_fn(pid, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); diff --git a/dtrace/dtrace_dev.c b/dtrace/dtrace_dev.c index b41abc23287f..c7be698ad500 100644 --- a/dtrace/dtrace_dev.c +++ b/dtrace/dtrace_dev.c @@ -101,7 +101,7 @@ static int dtrace_open(struct inode *inode, struct file *file) { dtrace_state_t *state; uint32_t priv; - uid_t uid; + kuid_t uid; dtrace_cred2priv(file->f_cred, &priv, &uid); if (priv == DTRACE_PRIV_NONE) @@ -495,7 +495,7 @@ static long dtrace_ioctl(struct file *file, dtrace_probedesc_t desc; dtrace_probekey_t pkey; uint32_t priv; - uid_t uid; + kuid_t uid; dt_dbg_ioctl("IOCTL %s (cmd %#x), argp %p\n", cmd == DTRACEIOC_PROBES ? "PROBES" diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c index b759f5c14d6e..5d6468e8d9dd 100644 --- a/dtrace/dtrace_dif.c +++ b/dtrace/dtrace_dif.c @@ -2286,7 +2286,7 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate, * Additionally, it is safe to dereference one's own process * credential, since this is never NULL after process birth. */ - return (uint64_t)current->real_cred->uid; + return (uint64_t)from_kuid(NULL, current_real_cred()->uid); case DIF_VAR_GID: if (!dtrace_priv_proc(state)) @@ -2299,7 +2299,7 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate, * Additionally, it is safe to dereference one's own process * credential, since this is never NULL after process birth. */ - return (uint64_t)current->real_cred->gid; + return (uint64_t)from_kgid(NULL, current_real_cred()->gid); case DIF_VAR_ERRNO: { int64_t arg0; diff --git a/dtrace/dtrace_ecb.c b/dtrace/dtrace_ecb.c index c7ad8c976a10..6eaaa3c47bec 100644 --- a/dtrace/dtrace_ecb.c +++ b/dtrace/dtrace_ecb.c @@ -42,7 +42,6 @@ static dtrace_action_t *dtrace_ecb_aggregation_create(dtrace_ecb_t *ecb, dtrace_recdesc_t *frec; dtrace_aggid_t aggid; dtrace_state_t *state = ecb->dte_state; - int err; agg = kzalloc(sizeof(dtrace_aggregation_t), GFP_KERNEL); if (agg == NULL) @@ -141,14 +140,14 @@ success: * Get an ID for the aggregation (add it to the idr). */ mutex_unlock(&dtrace_lock); -again: - idr_pre_get(&state->dts_agg_idr, __GFP_NOFAIL); + + idr_preload(GFP_KERNEL); mutex_lock(&dtrace_lock); - err = idr_get_new(&state->dts_agg_idr, agg, &aggid); - if (err == -EAGAIN) { - mutex_unlock(&dtrace_lock); - goto again; + aggid = idr_alloc_cyclic(&state->dts_agg_idr, agg, 0, 0, GFP_NOWAIT); + idr_preload_end(); + if (aggid < 0) { + /* FIXME: need to handle this */ } state->dts_naggs++; diff --git a/dtrace/dtrace_match.c b/dtrace/dtrace_match.c index 75666a5430d9..7efd7f48abad 100644 --- a/dtrace/dtrace_match.c +++ b/dtrace/dtrace_match.c @@ -31,7 +31,7 @@ dtrace_hash_t *dtrace_bymod; dtrace_hash_t *dtrace_byfunc; dtrace_hash_t *dtrace_byname; -int dtrace_match_priv(const dtrace_probe_t *prp, uint32_t priv, uid_t uid) +int dtrace_match_priv(const dtrace_probe_t *prp, uint32_t priv, kuid_t uid) { if (priv != DTRACE_PRIV_ALL) { uint32_t ppriv = @@ -46,7 +46,7 @@ int dtrace_match_priv(const dtrace_probe_t *prp, uint32_t priv, uid_t uid) return 0; if (((ppriv & ~match) & DTRACE_PRIV_OWNER) != 0 && - uid != prp->dtpr_provider->dtpv_priv.dtpp_uid) + !uid_eq(uid, prp->dtpr_provider->dtpv_priv.dtpp_uid)) return 0; } @@ -54,7 +54,7 @@ int dtrace_match_priv(const dtrace_probe_t *prp, uint32_t priv, uid_t uid) } int dtrace_match_probe(const dtrace_probe_t *prp, const dtrace_probekey_t *pkp, - uint32_t priv, uid_t uid) + uint32_t priv, kuid_t uid) { dtrace_provider_t *pvp = prp->dtpr_provider; int rv; @@ -204,7 +204,7 @@ int dtrace_match_nonzero(const char *s, const char *p, int depth) struct probe_match { const dtrace_probekey_t *pkp; uint32_t priv; - uid_t uid; + kuid_t uid; int (*matched)(dtrace_probe_t *, void *); void *arg; int nmatched; @@ -229,7 +229,7 @@ static int dtrace_match_one(int id, void *p, void *data) return 0; } -int dtrace_match(const dtrace_probekey_t *pkp, uint32_t priv, uid_t uid, +int dtrace_match(const dtrace_probekey_t *pkp, uint32_t priv, kuid_t uid, int (*matched)(dtrace_probe_t *, void *), void *arg) { dtrace_probe_t template, *probe; diff --git a/dtrace/dtrace_priv.c b/dtrace/dtrace_priv.c index a19b08e2fa95..79930a57eb3d 100644 --- a/dtrace/dtrace_priv.c +++ b/dtrace/dtrace_priv.c @@ -45,12 +45,12 @@ int dtrace_priv_proc_common_user(dtrace_state_t *state) ASSERT(s_cr != NULL); if ((cr = current_cred()) != NULL && - s_cr->euid == cr->euid && - s_cr->euid == cr->uid && - s_cr->euid == cr->suid && - s_cr->egid == cr->egid && - s_cr->egid == cr->gid && - s_cr->egid == cr->sgid) + uid_eq(s_cr->euid, cr->euid) && + uid_eq(s_cr->euid, cr->uid) && + uid_eq(s_cr->euid, cr->suid) && + gid_eq(s_cr->egid, cr->egid) && + gid_eq(s_cr->egid, cr->gid) && + gid_eq(s_cr->egid, cr->sgid)) return 1; return 0; diff --git a/dtrace/dtrace_probe.c b/dtrace/dtrace_probe.c index 0437ba21810c..35ab7f1d82b1 100644 --- a/dtrace/dtrace_probe.c +++ b/dtrace/dtrace_probe.c @@ -59,12 +59,11 @@ dtrace_id_t dtrace_probe_create(dtrace_provider_id_t prov, const char *mod, dtrace_probe_t *probe; dtrace_provider_t *provider = (dtrace_provider_t *)prov; dtrace_id_t id; - int err; probe = kmem_cache_alloc(dtrace_probe_cachep, __GFP_NOFAIL); /* - * The idr_pre_get() function should be called without holding locks. + * The ir_preload() function should be called without holding locks. * When the provider is the DTrace core itself, dtrace_lock will be * held when we enter this function. */ @@ -73,14 +72,13 @@ dtrace_id_t dtrace_probe_create(dtrace_provider_id_t prov, const char *mod, mutex_unlock(&dtrace_lock); } -again: - idr_pre_get(&dtrace_probe_idr, __GFP_NOFAIL); + idr_preload(GFP_KERNEL); mutex_lock(&dtrace_lock); - err = idr_get_new(&dtrace_probe_idr, probe, &id); - if (err == -EAGAIN) { - mutex_unlock(&dtrace_lock); - goto again; + id = idr_alloc_cyclic(&dtrace_probe_idr, probe, 0, 0, GFP_NOWAIT); + idr_preload_end(); + if (id < 0) { + /* FIXME: Need to handle failure */ } probe->dtpr_id = id; @@ -113,7 +111,7 @@ int dtrace_probe_enable(const dtrace_probedesc_t *desc, dtrace_enabling_t *enab) { dtrace_probekey_t pkey; uint32_t priv; - uid_t uid; + kuid_t uid; dtrace_ecb_create_cache = NULL; @@ -729,12 +727,12 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, ASSERT(s_cr != NULL); if ((cr = current_cred()) == NULL || - s_cr->euid != cr->euid || - s_cr->euid != cr->uid || - s_cr->euid != cr->suid || - s_cr->egid != cr->egid || - s_cr->egid != cr->gid || - s_cr->egid != cr->sgid) + !uid_eq(s_cr->euid, cr->euid) || + !uid_eq(s_cr->euid, cr->uid) || + !uid_eq(s_cr->euid, cr->suid) || + !gid_eq(s_cr->egid, cr->egid) || + !gid_eq(s_cr->egid, cr->gid) || + !gid_eq(s_cr->egid, cr->sgid)) continue; } } @@ -1282,7 +1280,6 @@ EXPORT_SYMBOL(dtrace_probe); int dtrace_probe_init(void) { dtrace_id_t id; - int err; dtrace_probe_cachep = KMEM_CACHE(dtrace_probe, SLAB_HWCACHE_ALIGN); if (dtrace_probe_cachep == NULL) @@ -1295,30 +1292,27 @@ int dtrace_probe_init(void) * being the very first entry. This is used in functionality that runs * through the list of probes. * - * We need to drop our locks when calling idr_pre_get(), so we try to + * We need to drop our locks when calling idr_preload(), so we try to * get them back right after. */ -again: mutex_unlock(&dtrace_lock); mutex_unlock(&dtrace_provider_lock); mutex_unlock(&cpu_lock); - idr_pre_get(&dtrace_probe_idr, __GFP_NOFAIL); + idr_preload(GFP_KERNEL); mutex_lock(&cpu_lock); mutex_lock(&dtrace_provider_lock); mutex_lock(&dtrace_lock); - err = idr_get_new(&dtrace_probe_idr, NULL, &id); - if (err == -EAGAIN) - goto again; + id = idr_alloc_cyclic(&dtrace_probe_idr, NULL, 0, 0, GFP_NOWAIT); + idr_preload_end(); return id == 0 ? 0 : -EAGAIN; } void dtrace_probe_exit(void) { - idr_remove_all(&dtrace_probe_idr); idr_destroy(&dtrace_probe_idr); kmem_cache_destroy(dtrace_probe_cachep); } @@ -1358,7 +1352,7 @@ 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, 0, + match = dtrace_match(&pkey, DTRACE_PRIV_ALL, make_kuid(NULL, 0), dtrace_probe_lookup_match, &id); mutex_unlock(&dtrace_lock); diff --git a/dtrace/dtrace_ptofapi.c b/dtrace/dtrace_ptofapi.c index 15964f858da5..3933a65165dd 100644 --- a/dtrace/dtrace_ptofapi.c +++ b/dtrace/dtrace_ptofapi.c @@ -203,7 +203,8 @@ int dtrace_register(const char *name, const dtrace_pattr_t *pap, uint32_t priv, provider->dtpv_priv.dtpp_flags = priv; if (cr != NULL) { - provider->dtpv_priv.dtpp_uid = get_cred(cr)->uid; + provider->dtpv_priv.dtpp_uid = + make_kuid(NULL, from_kuid(NULL, get_cred(cr)->uid)); put_cred(cr); } diff --git a/dtrace/dtrace_state.c b/dtrace/dtrace_state.c index 15910c118ad1..837879dd7cdd 100644 --- a/dtrace/dtrace_state.c +++ b/dtrace/dtrace_state.c @@ -339,7 +339,6 @@ dtrace_state_t *dtrace_state_create(struct file *file) #ifdef FIXME const cred_t *cr = file->f_cred; #endif - int err; dtrace_aggid_t aggid; ASSERT(MUTEX_HELD(&cpu_lock)); @@ -373,18 +372,16 @@ dtrace_state_t *dtrace_state_create(struct file *file) * Create a first entry in the aggregation IDR, so that ID 0 is used as * that gets used as meaning 'none'. */ -again: mutex_unlock(&dtrace_lock); mutex_unlock(&cpu_lock); - idr_pre_get(&state->dts_agg_idr, __GFP_NOFAIL); + idr_preload(GFP_KERNEL); mutex_lock(&cpu_lock); mutex_lock(&dtrace_lock); - err = idr_get_new(&state->dts_agg_idr, NULL, &aggid); - if (err == -EAGAIN) - goto again; + aggid = idr_alloc_cyclic(&state->dts_agg_idr, NULL, 0, 0, GFP_NOWAIT); + idr_preload_end(); ASSERT(aggid == 0); @@ -1075,7 +1072,6 @@ void dtrace_state_destroy(dtrace_state_t *state) * If there were aggregations allocated, they should have been cleaned * up by now, so we can get rid of the idr. */ - idr_remove_all(&state->dts_agg_idr); idr_destroy(&state->dts_agg_idr); vfree(state->dts_buffer); diff --git a/dtrace/dtrace_util.c b/dtrace/dtrace_util.c index 40cdc2c769cf..e558c6321fa1 100644 --- a/dtrace/dtrace_util.c +++ b/dtrace/dtrace_util.c @@ -130,7 +130,7 @@ int dtrace_badname(const char *s) return 0; } -void dtrace_cred2priv(const cred_t *cr, uint32_t *privp, uid_t *uidp) +void dtrace_cred2priv(const cred_t *cr, uint32_t *privp, kuid_t *uidp) { #ifdef FIXME /* diff --git a/dtrace/fasttrap_dev.c b/dtrace/fasttrap_dev.c index 2b3bef83fafc..c46ee71e1c72 100644 --- a/dtrace/fasttrap_dev.c +++ b/dtrace/fasttrap_dev.c @@ -1671,7 +1671,7 @@ void fasttrap_dev_exit(void) if (tmp != CLEANUP_NONE) { mutex_unlock(&fasttrap_cleanup_mtx); - flush_delayed_work_sync(&fasttrap_cleanup); + flush_delayed_work(&fasttrap_cleanup); mutex_lock(&fasttrap_cleanup_mtx); } } diff --git a/dtrace/include/dtrace/dtrace_impl.h b/dtrace/include/dtrace/dtrace_impl.h index 23f5d446caea..8f816a663f0f 100644 --- a/dtrace/include/dtrace/dtrace_impl.h +++ b/dtrace/include/dtrace/dtrace_impl.h @@ -483,14 +483,14 @@ extern dtrace_hash_t *dtrace_bymod; extern dtrace_hash_t *dtrace_byfunc; extern dtrace_hash_t *dtrace_byname; -extern int dtrace_match_priv(const dtrace_probe_t *, uint32_t, uid_t); +extern int dtrace_match_priv(const dtrace_probe_t *, uint32_t, kuid_t); extern int dtrace_match_probe(const dtrace_probe_t *, - const dtrace_probekey_t *, uint32_t, uid_t); + const dtrace_probekey_t *, uint32_t, kuid_t); extern int dtrace_match_glob(const char *, const char *, int); extern int dtrace_match_string(const char *, const char *, int); extern int dtrace_match_nul(const char *, const char *, int); extern int dtrace_match_nonzero(const char *, const char *, int); -extern int dtrace_match(const dtrace_probekey_t *, uint32_t, uid_t, +extern int dtrace_match(const dtrace_probekey_t *, uint32_t, kuid_t, int (*matched)(dtrace_probe_t *, void *), void *); extern void dtrace_probekey(const dtrace_probedesc_t *, dtrace_probekey_t *); @@ -850,7 +850,7 @@ extern int dtrace_strncmp(char *, char *, size_t); extern size_t dtrace_strlen(const char *, size_t); extern int dtrace_badattr(const dtrace_attribute_t *); extern int dtrace_badname(const char *); -extern void dtrace_cred2priv(const cred_t *, uint32_t *, uid_t *); +extern void dtrace_cred2priv(const cred_t *, uint32_t *, kuid_t *); typedef void for_each_module_fn(void *, struct module *); extern void dtrace_for_each_module(for_each_module_fn *fn, void *arg); diff --git a/dtrace/include/dtrace/dtrace_impl_defines.h b/dtrace/include/dtrace/dtrace_impl_defines.h index e17f185ff340..737dd50fb8c3 100644 --- a/dtrace/include/dtrace/dtrace_impl_defines.h +++ b/dtrace/include/dtrace/dtrace_impl_defines.h @@ -192,13 +192,13 @@ typedef enum dtrace_speculation_state { #define MUTEX_HELD(lock) mutex_owned(lock) #ifdef CONFIG_PREEMPT_VOLUNTARY -# define dtrace_is_preemptive() (!(preempt_count() & PREEMPT_ACTIVE)) +# define dtrace_is_preemptive() (preempt_count() > 0) # define dtrace_preempt_off() do { \ - add_preempt_count(PREEMPT_ACTIVE); \ + preempt_count_inc(); \ barrier(); \ } while (0) # define dtrace_preempt_on() do { \ - sub_preempt_count(PREEMPT_ACTIVE); \ + preempt_count_dec(); \ barrier(); \ } while (0) #endif diff --git a/dtrace/include/uapi/linux/dtrace/stability.h b/dtrace/include/uapi/linux/dtrace/stability.h index 9b9eb142dcc8..7427f1ee3e5a 100644 --- a/dtrace/include/uapi/linux/dtrace/stability.h +++ b/dtrace/include/uapi/linux/dtrace/stability.h @@ -32,6 +32,7 @@ * Use is subject to license terms. */ +#include #include #include @@ -44,7 +45,7 @@ typedef struct dtrace_ppriv { uint32_t dtpp_flags; /* privilege flags */ - uid_t dtpp_uid; /* user ID */ + kuid_t dtpp_uid; /* user ID */ } dtrace_ppriv_t; typedef struct dtrace_attribute { -- 2.50.1