autofs4: close the races around autofs4_notify_daemon()
Don't drop ->wq_mutex before calling autofs4_notify_daemon() only to regain it there. Besides being pointless, that opens a race window where autofs4_wait_release() could've come and freed wq->name.name. And do the debugging printk in the "reused an existing wq" case before dropping ->wq_mutex - the same reason... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Acked-by: Ian Kent <raven@themaw.net>
This commit is contained in:
@@ -109,13 +109,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
|
|||||||
|
|
||||||
pkt.hdr.proto_version = sbi->version;
|
pkt.hdr.proto_version = sbi->version;
|
||||||
pkt.hdr.type = type;
|
pkt.hdr.type = type;
|
||||||
mutex_lock(&sbi->wq_mutex);
|
|
||||||
|
|
||||||
/* Check if we have become catatonic */
|
|
||||||
if (sbi->catatonic) {
|
|
||||||
mutex_unlock(&sbi->wq_mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
/* Kernel protocol v4 missing and expire packets */
|
/* Kernel protocol v4 missing and expire packets */
|
||||||
case autofs_ptype_missing:
|
case autofs_ptype_missing:
|
||||||
@@ -427,7 +421,6 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
|
|||||||
wq->tgid = current->tgid;
|
wq->tgid = current->tgid;
|
||||||
wq->status = -EINTR; /* Status return if interrupted */
|
wq->status = -EINTR; /* Status return if interrupted */
|
||||||
wq->wait_ctr = 2;
|
wq->wait_ctr = 2;
|
||||||
mutex_unlock(&sbi->wq_mutex);
|
|
||||||
|
|
||||||
if (sbi->version < 5) {
|
if (sbi->version < 5) {
|
||||||
if (notify == NFY_MOUNT)
|
if (notify == NFY_MOUNT)
|
||||||
@@ -449,15 +442,15 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
|
|||||||
(unsigned long) wq->wait_queue_token, wq->name.len,
|
(unsigned long) wq->wait_queue_token, wq->name.len,
|
||||||
wq->name.name, notify);
|
wq->name.name, notify);
|
||||||
|
|
||||||
/* autofs4_notify_daemon() may block */
|
/* autofs4_notify_daemon() may block; it will unlock ->wq_mutex */
|
||||||
autofs4_notify_daemon(sbi, wq, type);
|
autofs4_notify_daemon(sbi, wq, type);
|
||||||
} else {
|
} else {
|
||||||
wq->wait_ctr++;
|
wq->wait_ctr++;
|
||||||
mutex_unlock(&sbi->wq_mutex);
|
|
||||||
kfree(qstr.name);
|
|
||||||
DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
|
DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
|
||||||
(unsigned long) wq->wait_queue_token, wq->name.len,
|
(unsigned long) wq->wait_queue_token, wq->name.len,
|
||||||
wq->name.name, notify);
|
wq->name.name, notify);
|
||||||
|
mutex_unlock(&sbi->wq_mutex);
|
||||||
|
kfree(qstr.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user