[ltt-dev] [PATCH v2] lttng: Fix potential invalid pointer derefference
Gui Jianfeng
guijianfeng at cn.fujitsu.com
Mon Feb 23 20:56:19 EST 2009
Mathieu Desnoyers wrote:
> * Gui Jianfeng (guijianfeng at cn.fujitsu.com) wrote:
>> Hi Mathieu,
>>
>> Calling get_ltt_root() and put_ltt_root() pair may induce invalid pointer
>> derefference. Consider the following scenario:
>>
>> CPU 0 CPU 1
>> ---------------------- ----------------------
>> 1 root = get_ltt_root()
>> 2 root = get_ltt_root()
>> 3 put_ltt_root() //global root is freed
>> 4 using root(crash here)
>>
>> Here is the fix for this issue. Thanks a lot to Zhaolei to point this out
>> in offline.
>>
>> This patch assumes that the *ltt root remove* patch has been applied.
>>
>> Signed-off-by: Gui Jianfeng <guijianfeng at cn.fujistu.com>
>> ---
>> include/linux/ltt-core.h | 3 ++-
>> ltt/ltt-core.c | 25 +++++++++++++++++++++----
>> ltt/ltt-relay.c | 10 +++++++++-
>> ltt/ltt-userspace-event.c | 3 +++
>> 4 files changed, 35 insertions(+), 6 deletions(-)
>>
>> diff --git a/include/linux/ltt-core.h b/include/linux/ltt-core.h
>> index 28394cb..786c2b1 100644
>> --- a/include/linux/ltt-core.h
>> +++ b/include/linux/ltt-core.h
>> @@ -30,9 +30,10 @@ extern struct ltt_traces ltt_traces;
>> /*
>> * get dentry of ltt's root dir
>> */
>> -void put_ltt_root(void);
>> struct dentry *get_ltt_root(void);
>>
>> +void put_ltt_root(void);
>> +
>> /* Keep track of trap nesting inside LTT */
>> DECLARE_PER_CPU(unsigned int, ltt_nesting);
>>
>> diff --git a/ltt/ltt-core.c b/ltt/ltt-core.c
>> index 314750b..03b81ca 100644
>> --- a/ltt/ltt-core.c
>> +++ b/ltt/ltt-core.c
>> @@ -10,6 +10,7 @@
>> #include <linux/percpu.h>
>> #include <linux/module.h>
>> #include <linux/debugfs.h>
>> +#include <linux/kref.h>
>>
>> /* Traces structures */
>> struct ltt_traces ltt_traces = {
>> @@ -23,12 +24,22 @@ static DEFINE_MUTEX(ltt_traces_mutex);
>>
>> /* dentry of ltt's root dir */
>> static struct dentry *ltt_root_dentry;
>> +static struct kref ltt_root_kref = {
>> + .refcount = ATOMIC_INIT(0),
>> +};
>> +
>> +static void ltt_root_release(struct kref *ref)
>> +{
>> + return;
>> +}
>>
>> void put_ltt_root(void)
>> {
>> - if (ltt_root_dentry && list_empty(<t_root_dentry->d_subdirs)) {
>> - debugfs_remove(ltt_root_dentry);
>> - ltt_root_dentry = NULL;
>> + if (ltt_root_dentry) {
>> + if (kref_put(<t_root_kref, ltt_root_release)) {
>> + debugfs_remove(ltt_root_dentry);
>> + ltt_root_dentry = NULL;
>
> Those two should go in ltt_root_release. See other (wide) use of
> kref_get/kref_put in the LTT code as example.
>
> Mathieu
>
>> + }
>> }
>> }
>> EXPORT_SYMBOL_GPL(put_ltt_root);
>> @@ -37,9 +48,15 @@ struct dentry *get_ltt_root(void)
>> {
>> if (!ltt_root_dentry) {
>> ltt_root_dentry = debugfs_create_dir(LTT_ROOT, NULL);
>> - if (!ltt_root_dentry)
>> + if (!ltt_root_dentry) {
>> printk(KERN_ERR "LTT : create ltt root dir failed\n");
>> + goto out;
>> + }
>> + kref_init(<t_root_kref);
>> + goto out;
>> }
>> + kref_get(<t_root_kref);
>> +out:
>> return ltt_root_dentry;
>> }
>> EXPORT_SYMBOL_GPL(get_ltt_root);
>> diff --git a/ltt/ltt-relay.c b/ltt/ltt-relay.c
>> index 7c544f4..8378802 100644
>> --- a/ltt/ltt-relay.c
>> +++ b/ltt/ltt-relay.c
>> @@ -833,8 +833,16 @@ end:
>>
>> static int ltt_relay_create_dirs(struct ltt_trace_struct *new_trace)
>> {
>> + struct dentry *ltt_root_dentry;
>> +
>> + ltt_root_dentry = get_ltt_root();
>> + if (!ltt_root_dentry)
>> + return ENOENT;
>> +
>> new_trace->dentry.trace_root = debugfs_create_dir(new_trace->trace_name,
>> - get_ltt_root());
>> + ltt_root_dentry);
>> + put_ltt_root();
>> + ltt_root_dentry = NULL;
>
> If ltt_root_dentry is local to the function, I don't see real value in
> setting it to null ?
Ok, will remove.
>
> You should also modifify ltt-relay-locked, because it has almost the
> exact same code as ltt-relay.c.
ltt-relay-locked doesn't use get_ltt_root(), it has its own root directory
called "ltt-locked", so i don't see why ltt-relay-locked should be modified.
>
> Thanks,
>
> Mathieu
>
>> if (new_trace->dentry.trace_root == NULL) {
>> printk(KERN_ERR "LTT : Trace directory name %s already taken\n",
>> new_trace->trace_name);
>> diff --git a/ltt/ltt-userspace-event.c b/ltt/ltt-userspace-event.c
>> index a48f336..487516b 100644
>> --- a/ltt/ltt-userspace-event.c
>> +++ b/ltt/ltt-userspace-event.c
>> @@ -110,7 +110,10 @@ static int __init ltt_userspace_init(void)
>> err = -EPERM;
>> goto err_no_file;
>> }
>> +
>> + return err;
>> err_no_file:
>> + put_ltt_root();
>> err_no_root:
>> return err;
>> }
>> --
>> 1.5.4.rc3
>>
>>
>> _______________________________________________
>> ltt-dev mailing list
>> ltt-dev at lists.casi.polymtl.ca
>> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
>>
>
--
Regards
Gui Jianfeng
More information about the lttng-dev
mailing list