Fixup the large_writex problem (a large_writex can send a full 64k of data,
authorJeremy Allison <jra@samba.org>
Thu, 24 May 2001 19:28:22 +0000 (19:28 +0000)
committerJeremy Allison <jra@samba.org>
Thu, 24 May 2001 19:28:22 +0000 (19:28 +0000)
we already have space for this we just need to understand the length correctly).
Jeremy.
(This used to be commit 19145bae720bbcc32dcab380c62a33d1f0e3eef0)

source3/include/smb.h
source3/lib/util_sock.c
source3/smbd/oplock.c
source3/smbd/process.c
source3/smbd/reply.c

index 616b75dded6086ddf2d2aef1d97b6f1a08d758bd..d810e11340f639acca1b353788ec735324aaae8b 100644 (file)
@@ -27,6 +27,7 @@
 
 #define BUFFER_SIZE (0xFFFF)
 #define SAFETY_MARGIN 1024
+#define LARGE_WRITEX_HDR_SIZE 65
 
 #define NMB_PORT 137
 #define DGRAM_PORT 138
index 3269042117b6909b83735ca7c9108992912b860a..b59debe929a8ac1569ac36b167437e8a32605bfb 100644 (file)
@@ -642,35 +642,38 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
 
 BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
 {
-  ssize_t len,ret;
+       ssize_t len,ret;
 
-  smb_read_error = 0;
+       smb_read_error = 0;
 
-  memset(buffer,'\0',smb_size + 100);
+       memset(buffer,'\0',smb_size + 100);
 
-  len = read_smb_length_return_keepalive(fd,buffer,timeout);
-  if (len < 0)
-  {
-    DEBUG(10,("receive_smb: length < 0!\n"));
-    return(False);
-  }
+       len = read_smb_length_return_keepalive(fd,buffer,timeout);
+       if (len < 0) {
+               DEBUG(10,("receive_smb: length < 0!\n"));
+               return(False);
+       }
 
-  if (len > BUFFER_SIZE) {
-    DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
-    if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
-    {
-       exit(1);
-    }
-  }
+       /*
+        * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
+     * of header. Don't print the error if this fits.... JRA.
+        */
 
-  if(len > 0) {
-    ret = read_socket_data(fd,buffer+4,len);
-    if (ret != len) {
-      smb_read_error = READ_ERROR;
-      return False;
-    }
-  }
-  return(True);
+       if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
+               DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
+               if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
+                       exit(1);
+       }
+
+       if(len > 0) {
+               ret = read_socket_data(fd,buffer+4,len);
+               if (ret != len) {
+                       smb_read_error = READ_ERROR;
+                       return False;
+               }
+       }
+
+       return(True);
 }
 
 /****************************************************************************
index e0b494017a05b6a05b12186cbd8473421a39aa14..ac0836324bab5429b4cd3b536774b08e42f4e60d 100644 (file)
@@ -676,13 +676,13 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B
      messages crossing on the wire.
    */
 
-  if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
+  if((inbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL)
   {
     DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
     return False;
   }
 
-  if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
+  if((outbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL)
   {
     DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
     free(inbuf);
index ac5454c48c8d1d23ebc31afb0139493369c706f7..74c0cbc96f62ec2171c6f412306a83859b42829b 100644 (file)
@@ -1184,8 +1184,8 @@ void smbd_process(void)
        time_t last_timeout_processing_time = time(NULL);
        unsigned int num_smbs = 0;
 
-       InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
-       OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+       InBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
+       OutBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
        if ((InBuffer == NULL) || (OutBuffer == NULL)) 
                return;
 
@@ -1208,7 +1208,7 @@ void smbd_process(void)
                lp_talloc_free();
                main_loop_talloc_free();
 
-               while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) {
+               while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
                        if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
                                return;
                        num_smbs = 0; /* Reset smb counter. */
index b43512329e991b6e6fd1105394c49fa514a8006e..914f1801d25de28657820139717738e6c2748a98 100644 (file)
@@ -2665,10 +2665,11 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
 {
   files_struct *fsp = file_fsp(inbuf,smb_vwv2);
   SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
-  size_t numtowrite = SVAL(inbuf,smb_vwv10);
+  size_t numtowrite = SVAL(inbuf,smb_vwv10)|(((size_t)SVAL(inbuf,smb_vwv9))<<16);
   BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
   ssize_t nwritten = -1;
   unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
+  unsigned int smblen = smb_len(inbuf);
   char *data;
   START_PROFILE(SMBwriteX);
 
@@ -2682,7 +2683,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
   CHECK_WRITE(fsp);
   CHECK_ERROR(fsp);
 
-  if(smb_doff > smb_len(inbuf)) {
+  if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
     END_PROFILE(SMBwriteX);
     return(ERROR(ERRDOS,ERRbadmem));
   }