1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
diff -ruN samba-2.0.10.orig/source/include/smb.h samba-2.0.10/source/include/smb.h
--- samba-2.0.10.orig/source/include/smb.h 2006-03-06 22:25:53.000000000 +0100
+++ samba-2.0.10/source/include/smb.h 2006-03-06 22:27:31.000000000 +0100
@@ -24,8 +24,14 @@
#ifndef _SMB_H
#define _SMB_H
+#if defined(LARGE_SMB_OFF_T)
+#define BUFFER_SIZE (128*1024)
+#else /* no large readwrite possible */
#define BUFFER_SIZE (0xFFFF)
+#endif
+
#define SAFETY_MARGIN 1024
+#define LARGE_WRITEX_HDR_SIZE 65
#define NMB_PORT 137
#define DGRAM_PORT 138
diff -ruN samba-2.0.10.orig/source/lib/util_sock.c samba-2.0.10/source/lib/util_sock.c
--- samba-2.0.10.orig/source/lib/util_sock.c 2000-03-16 23:59:18.000000000 +0100
+++ samba-2.0.10/source/lib/util_sock.c 2006-03-06 22:27:31.000000000 +0100
@@ -649,19 +649,21 @@
memset(buffer,'\0',smb_size + 100);
len = read_smb_length_return_keepalive(fd,buffer,timeout);
- if (len < 0)
- {
+ if (len < 0) {
DEBUG(10,("receive_smb: length < 0!\n"));
return(False);
}
- if (len > BUFFER_SIZE) {
+ /*
+ * 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 > (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);
diff -ruN samba-2.0.10.orig/source/smbd/oplock.c samba-2.0.10/source/smbd/oplock.c
--- samba-2.0.10.orig/source/smbd/oplock.c 2000-04-25 04:32:14.000000000 +0200
+++ samba-2.0.10/source/smbd/oplock.c 2006-03-06 22:27:31.000000000 +0100
@@ -887,13 +887,13 @@
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);
diff -ruN samba-2.0.10.orig/source/smbd/process.c samba-2.0.10/source/smbd/process.c
--- samba-2.0.10.orig/source/smbd/process.c 2006-03-06 22:25:28.000000000 +0100
+++ samba-2.0.10/source/smbd/process.c 2006-03-06 22:27:31.000000000 +0100
@@ -995,8 +995,8 @@
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;
@@ -1027,7 +1027,7 @@
/* free up temporary memory */
lp_talloc_free();
- while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb))
+ while(!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout,&got_smb))
{
if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
return;
diff -ruN samba-2.0.10.orig/source/smbd/reply.c samba-2.0.10/source/smbd/reply.c
--- samba-2.0.10.orig/source/smbd/reply.c 2006-03-06 22:25:53.000000000 +0100
+++ samba-2.0.10/source/smbd/reply.c 2006-03-06 22:27:31.000000000 +0100
@@ -2551,17 +2551,28 @@
size_t numtowrite = SVAL(inbuf,smb_vwv10);
BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
ssize_t nwritten = -1;
- int smb_doff = SVAL(inbuf,smb_vwv11);
+ unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
+ unsigned int smblen = smb_len(inbuf);
char *data;
+ BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
/* If it's an IPC, pass off the pipe handler. */
- if (IS_IPC(conn))
+ if (IS_IPC(conn)) {
return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
+ }
CHECK_FSP(fsp,conn);
CHECK_WRITE(fsp);
CHECK_ERROR(fsp);
+ /* Deal with possible LARGE_WRITEX */
+ if (large_writeX)
+ numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
+
+ if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
+ return(ERROR(ERRDOS,ERRbadmem));
+ }
+
data = smb_base(inbuf) + smb_doff;
if(CVAL(inbuf,smb_wct) == 14) {
@@ -2586,8 +2597,9 @@
#endif /* LARGE_SMB_OFF_T */
}
- if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
return(ERROR(ERRDOS,ERRlock));
+ }
/* X/Open SMB protocol says that, unlike SMBwrite
if the length is zero then NO truncation is
@@ -2598,12 +2610,15 @@
else
nwritten = write_file(fsp,data,startpos,numtowrite);
- if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
+ if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
set_message(outbuf,6,0,True);
SSVAL(outbuf,smb_vwv2,nwritten);
+ if (large_writeX)
+ SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
if (nwritten < (ssize_t)numtowrite) {
CVAL(outbuf,smb_rcls) = ERRHRD;
|