summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-09-30 14:21:56 +0200
committerKarolin Seeger <kseeger@samba.org>2009-09-30 14:21:56 +0200
commitdff54f716bdd76e3d167dc96bba6e168ef58cadd (patch)
tree5e97b2fc987e70bf336e3835bd9314470f7db987
parent42c537c845f48149cb8492cb0eaa114fe64694f1 (diff)
downloadsamba-v3-0-stable.tar.gz
samba-v3-0-stable.tar.xz
samba-v3-0-stable.zip
Fix for CVE-2009-2906.samba-3.0.37v3-0-stable
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--source/include/smb.h1
-rw-r--r--source/smbd/process.c20
2 files changed, 17 insertions, 4 deletions
diff --git a/source/include/smb.h b/source/include/smb.h
index 7484efd1925..e512add4be2 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -759,6 +759,7 @@ struct pending_message_list {
struct pending_message_list *next, *prev;
struct timeval request_time; /* When was this first issued? */
struct timeval end_time; /* When does this time out? */
+ bool processed;
DATA_BLOB buf;
DATA_BLOB private_data;
};
diff --git a/source/smbd/process.c b/source/smbd/process.c
index cf2988699b8..e861e16e0e2 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -93,6 +93,7 @@ static BOOL push_queued_message(char *buf, int msg_len,
msg->request_time = request_time;
msg->end_time = end_time;
+ msg->processed = false;
if (private_data) {
msg->private_data = data_blob_talloc(msg, private_data,
@@ -162,7 +163,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)
@@ -170,7 +171,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;
}
}
@@ -409,6 +410,10 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
/* We leave this message on the queue so the open code can
know this is a retry. */
DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
+
+ /* Mark the message as processed so this is not
+ * re-processed in error. */
+ msg->processed = true;
return True;
}
}
@@ -967,8 +972,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
}
if (!change_to_user(conn,session_tag)) {
- remove_deferred_open_smb_message(
- SVAL(inbuf, smb_mid));
return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid)));
}
@@ -1017,9 +1020,11 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
{
+ struct pending_message_list *pml = NULL;
int type = CVAL(inbuf,smb_com);
int outsize = 0;
int msg_type = CVAL(inbuf,0);
+ uint16_t mid = SVAL(inbuf, smb_mid);
chain_size = 0;
file_chain_reset();
@@ -1032,6 +1037,13 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
outsize = switch_message(type,inbuf,outbuf,size,bufsize);
+ /* If this was a deferred message and it's still there and
+ * was processed, remove it. */
+ pml = get_open_deferred_message(mid);
+ if (pml && pml->processed) {
+ remove_deferred_open_smb_message(mid);
+ }
+
outsize += chain_size;
if(outsize > 4)