fput: task_work_add() can fail if the caller has passed exit_task_work()
authorOleg Nesterov <oleg@redhat.com>
Fri, 14 Jun 2013 19:09:47 +0000 (21:09 +0200)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 15 Jun 2013 01:39:08 +0000 (05:39 +0400)
commite7b2c4069252732d52f1de6d1f7c82d99a156659
tree61058c0dd3806eaf067d1e6cf1634aa1acc9336e
parent698b8223631472bf982ed570b0812faa61955683
fput: task_work_add() can fail if the caller has passed exit_task_work()

fput() assumes that it can't be called after exit_task_work() but
this is not true, for example free_ipc_ns()->shm_destroy() can do
this. In this case fput() silently leaks the file.

Change it to fallback to delayed_fput_work if task_work_add() fails.
The patch looks complicated but it is not, it changes the code from

if (PF_KTHREAD) {
schedule_work(...);
return;
}
task_work_add(...)

to
if (!PF_KTHREAD) {
if (!task_work_add(...))
return;
/* fallback */
}
schedule_work(...);

As for shm_destroy() in particular, we could make another fix but I
think this change makes sense anyway. There could be another similar
user, it is not safe to assume that task_work_add() can't fail.

Reported-by: Andrey Vagin <avagin@openvz.org>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/file_table.c