summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-10-01 14:32:36 +0200
committerKarolin Seeger <kseeger@samba.org>2009-10-01 14:32:36 +0200
commit8a6b90d401e3c8d4d04ade36020bfc5c31c9603e (patch)
tree78a505a653de9ae0f88d84ea41dbddfaacb86db2
parent0597b97d159b22314f2b485145df7b82af717f0d (diff)
downloadsamba-8a6b90d401e3c8d4d04ade36020bfc5c31c9603e.tar.gz
samba-8a6b90d401e3c8d4d04ade36020bfc5c31c9603e.tar.bz2
samba-8a6b90d401e3c8d4d04ade36020bfc5c31c9603e.zip
Fix for CVE-2009-2906.
Summary: Specially crafted SMB requests on authenticated SMB connections can send smbd into a 100% CPU loop, causing a DoS on the Samba server.
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/smbd/process.c30
2 files changed, 26 insertions, 5 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 3c3ced6baf..cee95a9b17 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -727,6 +727,7 @@ struct pending_message_list {
struct smb_perfcount_data pcd;
uint32_t seqnum;
bool encrypted;
+ bool processed;
DATA_BLOB buf;
DATA_BLOB private_data;
};
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index ccb7f9dce3..fbaa9dee29 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -417,6 +417,7 @@ static void smbd_deferred_open_timer(struct event_context *ev,
struct pending_message_list *msg = talloc_get_type(private_data,
struct pending_message_list);
TALLOC_CTX *mem_ctx = talloc_tos();
+ uint16_t mid = SVAL(msg->buf.data,smb_mid);
uint8_t *inbuf;
inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
@@ -429,11 +430,21 @@ static void smbd_deferred_open_timer(struct event_context *ev,
/* We leave this message on the queue so the open code can
know this is a retry. */
DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
- (unsigned int)SVAL(msg->buf.data,smb_mid)));
+ (unsigned int)mid ));
+
+ /* Mark the message as processed so this is not
+ * re-processed in error. */
+ msg->processed = true;
process_smb(smbd_server_conn, inbuf,
msg->buf.length, 0,
msg->seqnum, msg->encrypted, &msg->pcd);
+
+ /* If it's still there and was processed, remove it. */
+ msg = get_open_deferred_message(mid);
+ if (msg && msg->processed) {
+ remove_deferred_open_smb_message(mid);
+ }
}
/****************************************************************************
@@ -466,6 +477,7 @@ static bool push_queued_message(struct smb_request *req,
msg->request_time = request_time;
msg->seqnum = req->seqnum;
msg->encrypted = req->encrypted;
+ msg->processed = false;
SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
if (private_data) {
@@ -507,7 +519,7 @@ void remove_deferred_open_smb_message(uint16 mid)
for (pml = deferred_open_queue; pml; pml = pml->next) {
if (mid == SVAL(pml->buf.data,smb_mid)) {
- DEBUG(10,("remove_sharing_violation_open_smb_message: "
+ DEBUG(10,("remove_deferred_open_smb_message: "
"deleting mid %u len %u\n",
(unsigned int)mid,
(unsigned int)pml->buf.length ));
@@ -537,6 +549,15 @@ void schedule_deferred_open_smb_message(uint16 mid)
if (mid == msg_mid) {
struct timed_event *te;
+ if (pml->processed) {
+ /* A processed message should not be
+ * rescheduled. */
+ DEBUG(0,("schedule_deferred_open_smb_message: LOGIC ERROR "
+ "message mid %u was already processed\n",
+ msg_mid ));
+ continue;
+ }
+
DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
mid ));
@@ -563,7 +584,7 @@ void schedule_deferred_open_smb_message(uint16 mid)
}
/****************************************************************************
- Return true if this mid is on the deferred queue.
+ Return true if this mid is on the deferred queue and was not yet processed.
****************************************************************************/
bool open_was_deferred(uint16 mid)
@@ -571,7 +592,7 @@ bool open_was_deferred(uint16 mid)
struct pending_message_list *pml;
for (pml = deferred_open_queue; pml; pml = pml->next) {
- if (SVAL(pml->buf.data,smb_mid) == mid) {
+ if (SVAL(pml->buf.data,smb_mid) == mid && !pml->processed) {
return True;
}
}
@@ -1309,7 +1330,6 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
DEBUG(0, ("Error: Could not change to user. Removing "
"deferred open, mid=%d.\n", req->mid));
reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
- remove_deferred_open_smb_message(req->mid);
return conn;
}