summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPrakash Surya <[email protected]>2011-12-16 14:57:31 -0800
committerBrian Behlendorf <[email protected]>2011-12-16 16:54:00 -0800
commit8f2503e0af490ea253d6db1a15b4901437171cc1 (patch)
tree5aa2d69dd5838d2495d698595b9ff11a2e8f5335 /include
parente7e5f78e7bf6dc86337483f4d9f01becc017d185 (diff)
Store copy of tqent_flags prior to servicing task
A preallocated taskq_ent_t's tqent_flags must be checked prior to servicing the taskq_ent_t. Once a preallocated taskq entry is serviced, the ownership of the entry is handed back to the caller of taskq_dispatch, thus the entry's contents can potentially be mangled. In particular, this is a problem in the case where a preallocated taskq entry is serviced, and the caller clears it's tqent_flags field. Thus, when the function returns and task_done is called, it looks as though the entry is **not** a preallocated task (when in fact it **is** a preallocated task). In this situation, task_done will place the preallocated taskq_ent_t structure onto the taskq_t's free list. This is a **huge** mistake. If the taskq_ent_t is then freed by the caller of taskq_dispatch, the taskq_t's free list will hold a pointer to garbage data. Even worse, if nothing has over written the freed memory before the pointer is dereferenced, it may still look as though it points to a valid list_head belonging to a taskq_ent_t structure. Thus, the task entry's flags are now copied prior to servicing the task. This copy is then checked to see if it is a preallocated task, and determine if the entry needs to be passed down to the task_done function. Signed-off-by: Prakash Surya <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #71
Diffstat (limited to 'include')
-rw-r--r--include/sys/taskq.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/include/sys/taskq.h b/include/sys/taskq.h
index 0a7143375..fec4de8ca 100644
--- a/include/sys/taskq.h
+++ b/include/sys/taskq.h
@@ -97,6 +97,7 @@ typedef struct taskq_thread {
struct task_struct *tqt_thread;
taskq_t *tqt_tq;
taskqid_t tqt_id;
+ uintptr_t tqt_flags;
} taskq_thread_t;
/* Global system-wide dynamic task queue available for all consumers */