diff options
author | Steven Rostedt <srostedt@redhat.com> | 2011-12-19 19:07:36 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-12-21 07:23:11 -0500 |
commit | 06a51d9307380c78bb5c92e68fc80ad2c7d7f890 (patch) | |
tree | e0f38e8780f92937e8f19f17b8bf9eff6bcc3137 | |
parent | c842e975520f8ab09e293cc92f51a1f396251fd5 (diff) |
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>
-rw-r--r-- | kernel/trace/ftrace.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index a383d6c67bfa..e1ee07f81ca2 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -999,6 +999,11 @@ static struct ftrace_page *ftrace_new_pgs; | |||
999 | static struct ftrace_page *ftrace_pages_start; | 999 | static struct ftrace_page *ftrace_pages_start; |
1000 | static struct ftrace_page *ftrace_pages; | 1000 | static struct ftrace_page *ftrace_pages; |
1001 | 1001 | ||
1002 | static bool ftrace_hash_empty(struct ftrace_hash *hash) | ||
1003 | { | ||
1004 | return !hash || !hash->count; | ||
1005 | } | ||
1006 | |||
1002 | static struct ftrace_func_entry * | 1007 | static struct ftrace_func_entry * |
1003 | ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip) | 1008 | ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip) |
1004 | { | 1009 | { |
@@ -1007,7 +1012,7 @@ ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip) | |||
1007 | struct hlist_head *hhd; | 1012 | struct hlist_head *hhd; |
1008 | struct hlist_node *n; | 1013 | struct hlist_node *n; |
1009 | 1014 | ||
1010 | if (!hash->count) | 1015 | if (ftrace_hash_empty(hash)) |
1011 | return NULL; | 1016 | return NULL; |
1012 | 1017 | ||
1013 | if (hash->size_bits > 0) | 1018 | if (hash->size_bits > 0) |
@@ -1151,7 +1156,7 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash) | |||
1151 | return NULL; | 1156 | return NULL; |
1152 | 1157 | ||
1153 | /* Empty hash? */ | 1158 | /* Empty hash? */ |
1154 | if (!hash || !hash->count) | 1159 | if (ftrace_hash_empty(hash)) |
1155 | return new_hash; | 1160 | return new_hash; |
1156 | 1161 | ||
1157 | size = 1 << hash->size_bits; | 1162 | size = 1 << hash->size_bits; |
@@ -1276,9 +1281,9 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) | |||
1276 | filter_hash = rcu_dereference_raw(ops->filter_hash); | 1281 | filter_hash = rcu_dereference_raw(ops->filter_hash); |
1277 | notrace_hash = rcu_dereference_raw(ops->notrace_hash); | 1282 | notrace_hash = rcu_dereference_raw(ops->notrace_hash); |
1278 | 1283 | ||
1279 | if ((!filter_hash || !filter_hash->count || | 1284 | if ((ftrace_hash_empty(filter_hash) || |
1280 | ftrace_lookup_ip(filter_hash, ip)) && | 1285 | ftrace_lookup_ip(filter_hash, ip)) && |
1281 | (!notrace_hash || !notrace_hash->count || | 1286 | (ftrace_hash_empty(notrace_hash) || |
1282 | !ftrace_lookup_ip(notrace_hash, ip))) | 1287 | !ftrace_lookup_ip(notrace_hash, ip))) |
1283 | ret = 1; | 1288 | ret = 1; |
1284 | else | 1289 | else |
@@ -1371,7 +1376,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops, | |||
1371 | if (filter_hash) { | 1376 | if (filter_hash) { |
1372 | hash = ops->filter_hash; | 1377 | hash = ops->filter_hash; |
1373 | other_hash = ops->notrace_hash; | 1378 | other_hash = ops->notrace_hash; |
1374 | if (!hash || !hash->count) | 1379 | if (ftrace_hash_empty(hash)) |
1375 | all = 1; | 1380 | all = 1; |
1376 | } else { | 1381 | } else { |
1377 | inc = !inc; | 1382 | inc = !inc; |
@@ -1381,7 +1386,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops, | |||
1381 | * If the notrace hash has no items, | 1386 | * If the notrace hash has no items, |
1382 | * then there's nothing to do. | 1387 | * then there's nothing to do. |
1383 | */ | 1388 | */ |
1384 | if (!hash || !hash->count) | 1389 | if (ftrace_hash_empty(hash)) |
1385 | return; | 1390 | return; |
1386 | } | 1391 | } |
1387 | 1392 | ||
@@ -1398,8 +1403,8 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops, | |||
1398 | if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip)) | 1403 | if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip)) |
1399 | match = 1; | 1404 | match = 1; |
1400 | } else { | 1405 | } else { |
1401 | in_hash = hash && !!ftrace_lookup_ip(hash, rec->ip); | 1406 | in_hash = !!ftrace_lookup_ip(hash, rec->ip); |
1402 | in_other_hash = other_hash && !!ftrace_lookup_ip(other_hash, rec->ip); | 1407 | in_other_hash = !!ftrace_lookup_ip(other_hash, rec->ip); |
1403 | 1408 | ||
1404 | /* | 1409 | /* |
1405 | * | 1410 | * |
@@ -1407,7 +1412,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops, | |||
1407 | if (filter_hash && in_hash && !in_other_hash) | 1412 | if (filter_hash && in_hash && !in_other_hash) |
1408 | match = 1; | 1413 | match = 1; |
1409 | else if (!filter_hash && in_hash && | 1414 | else if (!filter_hash && in_hash && |
1410 | (in_other_hash || !other_hash->count)) | 1415 | (in_other_hash || ftrace_hash_empty(other_hash))) |
1411 | match = 1; | 1416 | match = 1; |
1412 | } | 1417 | } |
1413 | if (!match) | 1418 | if (!match) |
@@ -1950,7 +1955,7 @@ static int ops_traces_mod(struct ftrace_ops *ops) | |||
1950 | struct ftrace_hash *hash; | 1955 | struct ftrace_hash *hash; |
1951 | 1956 | ||
1952 | hash = ops->filter_hash; | 1957 | hash = ops->filter_hash; |
1953 | return !!(!hash || !hash->count); | 1958 | return ftrace_hash_empty(hash); |
1954 | } | 1959 | } |
1955 | 1960 | ||
1956 | static int ftrace_update_code(struct module *mod) | 1961 | static int ftrace_update_code(struct module *mod) |
@@ -2320,7 +2325,8 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
2320 | * off, we can short cut and just print out that all | 2325 | * off, we can short cut and just print out that all |
2321 | * functions are enabled. | 2326 | * functions are enabled. |
2322 | */ | 2327 | */ |
2323 | if (iter->flags & FTRACE_ITER_FILTER && !ops->filter_hash->count) { | 2328 | if (iter->flags & FTRACE_ITER_FILTER && |
2329 | ftrace_hash_empty(ops->filter_hash)) { | ||
2324 | if (*pos > 0) | 2330 | if (*pos > 0) |
2325 | return t_hash_start(m, pos); | 2331 | return t_hash_start(m, pos); |
2326 | iter->flags |= FTRACE_ITER_PRINTALL; | 2332 | iter->flags |= FTRACE_ITER_PRINTALL; |