ksmbd: fix potential use-after-free in oplock/lease break ack
commit 50f930db22 upstream.
If ksmbd_iov_pin_rsp return error, use-after-free can happen by
accessing opinfo->state and opinfo_put and ksmbd_fd_put could
called twice.
Reported-by: Ziyan Xu <research@securitygossip.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d0195c42e6
commit
8106adc21a
@@ -8535,11 +8535,6 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
opinfo->op_state = OPLOCK_STATE_NONE;
|
|
||||||
wake_up_interruptible_all(&opinfo->oplock_q);
|
|
||||||
opinfo_put(opinfo);
|
|
||||||
ksmbd_fd_put(work, fp);
|
|
||||||
|
|
||||||
rsp->StructureSize = cpu_to_le16(24);
|
rsp->StructureSize = cpu_to_le16(24);
|
||||||
rsp->OplockLevel = rsp_oplevel;
|
rsp->OplockLevel = rsp_oplevel;
|
||||||
rsp->Reserved = 0;
|
rsp->Reserved = 0;
|
||||||
@@ -8547,16 +8542,15 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
|
|||||||
rsp->VolatileFid = volatile_id;
|
rsp->VolatileFid = volatile_id;
|
||||||
rsp->PersistentFid = persistent_id;
|
rsp->PersistentFid = persistent_id;
|
||||||
ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_oplock_break));
|
ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_oplock_break));
|
||||||
if (!ret)
|
if (ret) {
|
||||||
return;
|
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
smb2_set_err_rsp(work);
|
||||||
|
}
|
||||||
|
|
||||||
opinfo->op_state = OPLOCK_STATE_NONE;
|
opinfo->op_state = OPLOCK_STATE_NONE;
|
||||||
wake_up_interruptible_all(&opinfo->oplock_q);
|
wake_up_interruptible_all(&opinfo->oplock_q);
|
||||||
|
|
||||||
opinfo_put(opinfo);
|
opinfo_put(opinfo);
|
||||||
ksmbd_fd_put(work, fp);
|
ksmbd_fd_put(work, fp);
|
||||||
smb2_set_err_rsp(work);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_lease_state(struct lease *lease, __le32 req_state)
|
static int check_lease_state(struct lease *lease, __le32 req_state)
|
||||||
@@ -8686,11 +8680,6 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lease_state = lease->state;
|
lease_state = lease->state;
|
||||||
opinfo->op_state = OPLOCK_STATE_NONE;
|
|
||||||
wake_up_interruptible_all(&opinfo->oplock_q);
|
|
||||||
atomic_dec(&opinfo->breaking_cnt);
|
|
||||||
wake_up_interruptible_all(&opinfo->oplock_brk);
|
|
||||||
opinfo_put(opinfo);
|
|
||||||
|
|
||||||
rsp->StructureSize = cpu_to_le16(36);
|
rsp->StructureSize = cpu_to_le16(36);
|
||||||
rsp->Reserved = 0;
|
rsp->Reserved = 0;
|
||||||
@@ -8699,16 +8688,16 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
|
|||||||
rsp->LeaseState = lease_state;
|
rsp->LeaseState = lease_state;
|
||||||
rsp->LeaseDuration = 0;
|
rsp->LeaseDuration = 0;
|
||||||
ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_lease_ack));
|
ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_lease_ack));
|
||||||
if (!ret)
|
if (ret) {
|
||||||
return;
|
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
smb2_set_err_rsp(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
opinfo->op_state = OPLOCK_STATE_NONE;
|
||||||
wake_up_interruptible_all(&opinfo->oplock_q);
|
wake_up_interruptible_all(&opinfo->oplock_q);
|
||||||
atomic_dec(&opinfo->breaking_cnt);
|
atomic_dec(&opinfo->breaking_cnt);
|
||||||
wake_up_interruptible_all(&opinfo->oplock_brk);
|
wake_up_interruptible_all(&opinfo->oplock_brk);
|
||||||
|
|
||||||
opinfo_put(opinfo);
|
opinfo_put(opinfo);
|
||||||
smb2_set_err_rsp(work);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user