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 /kernel/trace | |
| 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>
Diffstat (limited to 'kernel/trace')
| -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; |
