History

ftrace: Also allocate and copy hash for reading of filter files

Currently the reader of set_ftrace_filter and set_ftrace_notrace just adds the pointer to the global tracer hash to its iterator. Unlike the writer that allocates a copy of the hash, the reader keeps the pointer to the filter hashes. This is problematic because this pointer is static across function calls that release the locks that can update the global tracer hashes. This can cause UAF and similar bugs. Allocate and copy the hash for reading the filter files like it is done for the writers. This not only fixes UAF bugs, but also makes the code a bit simpler as it doesn't have to differentiate when to free the iterator's hash between writers and readers.

Steven Rostedt committed 1 year ago

Commit bfb336c1 parent 4013aef1 file · +10 −9Browse files

Unified · Split

kernel/trace/ftrace.c+10−9
@@ -4661,13 +4661,17 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, · 4660 unmodified lines
4661 } else {4661 } else {
4662 iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash);4662 iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash);
4663 }4663 }
4664 } else {
4665 if (hash)
4666 iter->hash = alloc_and_copy_ftrace_hash(hash->size_bits, hash);
4667 else
4668 iter->hash = EMPTY_HASH;
4669 }
4664 4670
4665 if (!iter->hash) {4671 if (!iter->hash) {
4666 trace_parser_put(&iter->parser);4672 trace_parser_put(&iter->parser);
4667 goto out_unlock;4673 goto out_unlock;
4668 }4674 }
4669 } else
4670 iter->hash = hash;
4671 4675
4672 ret = 0;4676 ret = 0;
4673 4677
@@ -6543,9 +6547,6 @@ int ftrace_regex_release(struct inode *inode, struct file *file) · 1869 unmodified lines
6543 ftrace_hash_move_and_update_ops(iter->ops, orig_hash,6547 ftrace_hash_move_and_update_ops(iter->ops, orig_hash,
6544 iter->hash, filter_hash);6548 iter->hash, filter_hash);
6545 mutex_unlock(&ftrace_lock);6549 mutex_unlock(&ftrace_lock);
6546 } else {
6547 /* For read only, the hash is the ops hash */
6548 iter->hash = NULL;
6549 }6550 }
6550 6551
6551 mutex_unlock(&iter->ops->func_hash->regex_lock);6552 mutex_unlock(&iter->ops->func_hash->regex_lock);