ftrace: Create ftrace_hash_empty() helper routine
There are two types of hashes in the ftrace_ops; one type is the filter_hash and the other is the notrace_hash. Either one may be null, meaning it has no elements. But when elements are added, the hash is allocated. Throughout the code, a check needs to be made to see if a hash exists or the hash has elements, but the check if the hash exists is usually missing causing the possible "NULL pointer dereference bug". Add a helper routine called "ftrace_hash_empty()" that returns true if the hash doesn't exist or its count is zero. As they mean the same thing. Last-bug-reported-by: Jiri Olsa <jolsa@redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
c842e97552
commit
06a51d9307
|
@ -999,6 +999,11 @@ static struct ftrace_page *ftrace_new_pgs;
|
||||||
static struct ftrace_page *ftrace_pages_start;
|
static struct ftrace_page *ftrace_pages_start;
|
||||||
static struct ftrace_page *ftrace_pages;
|
static struct ftrace_page *ftrace_pages;
|
||||||
|
|
||||||
|
static bool ftrace_hash_empty(struct ftrace_hash *hash)
|
||||||
|
{
|
||||||
|
return !hash || !hash->count;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ftrace_func_entry *
|
static struct ftrace_func_entry *
|
||||||
ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
|
ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
|
||||||
{
|
{
|
||||||
|
@ -1007,7 +1012,7 @@ ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
|
||||||
struct hlist_head *hhd;
|
struct hlist_head *hhd;
|
||||||
struct hlist_node *n;
|
struct hlist_node *n;
|
||||||
|
|
||||||
if (!hash->count)
|
if (ftrace_hash_empty(hash))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (hash->size_bits > 0)
|
if (hash->size_bits > 0)
|
||||||
|
@ -1151,7 +1156,7 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Empty hash? */
|
/* Empty hash? */
|
||||||
if (!hash || !hash->count)
|
if (ftrace_hash_empty(hash))
|
||||||
return new_hash;
|
return new_hash;
|
||||||
|
|
||||||
size = 1 << hash->size_bits;
|
size = 1 << hash->size_bits;
|
||||||
|
@ -1276,9 +1281,9 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
|
||||||
filter_hash = rcu_dereference_raw(ops->filter_hash);
|
filter_hash = rcu_dereference_raw(ops->filter_hash);
|
||||||
notrace_hash = rcu_dereference_raw(ops->notrace_hash);
|
notrace_hash = rcu_dereference_raw(ops->notrace_hash);
|
||||||
|
|
||||||
if ((!filter_hash || !filter_hash->count ||
|
if ((ftrace_hash_empty(filter_hash) ||
|
||||||
ftrace_lookup_ip(filter_hash, ip)) &&
|
ftrace_lookup_ip(filter_hash, ip)) &&
|
||||||
(!notrace_hash || !notrace_hash->count ||
|
(ftrace_hash_empty(notrace_hash) ||
|
||||||
!ftrace_lookup_ip(notrace_hash, ip)))
|
!ftrace_lookup_ip(notrace_hash, ip)))
|
||||||
ret = 1;
|
ret = 1;
|
||||||
else
|
else
|
||||||
|
@ -1371,7 +1376,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
|
||||||
if (filter_hash) {
|
if (filter_hash) {
|
||||||
hash = ops->filter_hash;
|
hash = ops->filter_hash;
|
||||||
other_hash = ops->notrace_hash;
|
other_hash = ops->notrace_hash;
|
||||||
if (!hash || !hash->count)
|
if (ftrace_hash_empty(hash))
|
||||||
all = 1;
|
all = 1;
|
||||||
} else {
|
} else {
|
||||||
inc = !inc;
|
inc = !inc;
|
||||||
|
@ -1381,7 +1386,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
|
||||||
* If the notrace hash has no items,
|
* If the notrace hash has no items,
|
||||||
* then there's nothing to do.
|
* then there's nothing to do.
|
||||||
*/
|
*/
|
||||||
if (!hash || !hash->count)
|
if (ftrace_hash_empty(hash))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,8 +1403,8 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
|
||||||
if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip))
|
if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip))
|
||||||
match = 1;
|
match = 1;
|
||||||
} else {
|
} else {
|
||||||
in_hash = hash && !!ftrace_lookup_ip(hash, rec->ip);
|
in_hash = !!ftrace_lookup_ip(hash, rec->ip);
|
||||||
in_other_hash = other_hash && !!ftrace_lookup_ip(other_hash, rec->ip);
|
in_other_hash = !!ftrace_lookup_ip(other_hash, rec->ip);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
|
@ -1407,7 +1412,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
|
||||||
if (filter_hash && in_hash && !in_other_hash)
|
if (filter_hash && in_hash && !in_other_hash)
|
||||||
match = 1;
|
match = 1;
|
||||||
else if (!filter_hash && in_hash &&
|
else if (!filter_hash && in_hash &&
|
||||||
(in_other_hash || !other_hash->count))
|
(in_other_hash || ftrace_hash_empty(other_hash)))
|
||||||
match = 1;
|
match = 1;
|
||||||
}
|
}
|
||||||
if (!match)
|
if (!match)
|
||||||
|
@ -1950,7 +1955,7 @@ static int ops_traces_mod(struct ftrace_ops *ops)
|
||||||
struct ftrace_hash *hash;
|
struct ftrace_hash *hash;
|
||||||
|
|
||||||
hash = ops->filter_hash;
|
hash = ops->filter_hash;
|
||||||
return !!(!hash || !hash->count);
|
return ftrace_hash_empty(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ftrace_update_code(struct module *mod)
|
static int ftrace_update_code(struct module *mod)
|
||||||
|
@ -2320,7 +2325,8 @@ static void *t_start(struct seq_file *m, loff_t *pos)
|
||||||
* off, we can short cut and just print out that all
|
* off, we can short cut and just print out that all
|
||||||
* functions are enabled.
|
* functions are enabled.
|
||||||
*/
|
*/
|
||||||
if (iter->flags & FTRACE_ITER_FILTER && !ops->filter_hash->count) {
|
if (iter->flags & FTRACE_ITER_FILTER &&
|
||||||
|
ftrace_hash_empty(ops->filter_hash)) {
|
||||||
if (*pos > 0)
|
if (*pos > 0)
|
||||||
return t_hash_start(m, pos);
|
return t_hash_start(m, pos);
|
||||||
iter->flags |= FTRACE_ITER_PRINTALL;
|
iter->flags |= FTRACE_ITER_PRINTALL;
|
||||||
|
|
Loading…
Reference in New Issue