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
|
diff -ur linux-2.4.27/fs/smbfs/proc.c linux-2.4.28/fs/smbfs/proc.c
--- linux-2.4.27/fs/smbfs/proc.c 2004-11-12 19:32:24.000000000 +0000
+++ linux-2.4.28/fs/smbfs/proc.c 2004-11-19 20:18:27.000000000 +0000
@@ -1289,10 +1289,12 @@
data_len = WVAL(buf, 1);
/* we can NOT simply trust the data_len given by the server ... */
- if (data_len > server->packet_size - (buf+3 - server->packet)) {
- printk(KERN_ERR "smb_proc_read: invalid data length!! "
- "%d > %d - (%p - %p)\n",
- data_len, server->packet_size, buf+3, server->packet);
+ if (data_len > count ||
+ (buf+3 - server->packet) + data_len > server->packet_size) {
+ printk(KERN_ERR "smb_proc_read: invalid data length/offset!! "
+ "%d > %d || (%p - %p) + %d > %d\n",
+ data_len, count,
+ buf+3, server->packet, data_len, server->packet_size);
result = -EIO;
goto out;
}
@@ -1378,10 +1380,12 @@
buf = smb_base(server->packet) + data_off;
/* we can NOT simply trust the info given by the server ... */
- if (data_len > server->packet_size - (buf - server->packet)) {
- printk(KERN_ERR "smb_proc_read: invalid data length!! "
- "%d > %d - (%p - %p)\n",
- data_len, server->packet_size, buf, server->packet);
+ if (data_len > count ||
+ (buf - server->packet) + data_len > server->packet_size) {
+ printk(KERN_ERR "smb_proc_readX: invalid data length/offset!! "
+ "%d > %d || (%p - %p) + %d > %d\n",
+ data_len, count,
+ buf, server->packet, data_len, server->packet_size);
result = -EIO;
goto out;
}
diff -ur linux-2.4.27/fs/smbfs/sock.c linux-2.4.28/fs/smbfs/sock.c
--- linux-2.4.27/fs/smbfs/sock.c 2004-11-12 19:32:24.000000000 +0000
+++ linux-2.4.28/fs/smbfs/sock.c 2004-11-19 20:18:27.000000000 +0000
@@ -571,7 +571,11 @@
parm_disp, parm_offset, parm_count,
data_disp, data_offset, data_count);
*parm = base + parm_offset;
+ if (*parm - inbuf + parm_tot > server->packet_size)
+ goto out_bad_parm;
*data = base + data_offset;
+ if (*data - inbuf + data_tot > server->packet_size)
+ goto out_bad_data;
goto success;
}
@@ -591,6 +595,8 @@
rcv_buf = smb_vmalloc(buf_len);
if (!rcv_buf)
goto out_no_mem;
+ memset(rcv_buf, 0, buf_len);
+
*parm = rcv_buf;
*data = rcv_buf + total_p;
} else if (data_tot > total_d || parm_tot > total_p)
@@ -598,8 +604,12 @@
if (parm_disp + parm_count > total_p)
goto out_bad_parm;
+ if (parm_offset + parm_count > server->packet_size)
+ goto out_bad_parm;
if (data_disp + data_count > total_d)
goto out_bad_data;
+ if (data_offset + data_count > server->packet_size)
+ goto out_bad_data;
memcpy(*parm + parm_disp, base + parm_offset, parm_count);
memcpy(*data + data_disp, base + data_offset, data_count);
@@ -610,8 +620,11 @@
* Check whether we've received all of the data. Note that
* we use the packet totals -- total lengths might shrink!
*/
- if (data_len >= data_tot && parm_len >= parm_tot)
+ if (data_len >= data_tot && parm_len >= parm_tot) {
+ data_len = data_tot;
+ parm_len = parm_tot;
break;
+ }
}
/*
@@ -625,6 +638,9 @@
server->packet = rcv_buf;
rcv_buf = inbuf;
} else {
+ if (parm_len + data_len > buf_len)
+ goto out_data_grew;
+
PARANOIA("copying data, old size=%d, new size=%u\n",
server->packet_size, buf_len);
memcpy(inbuf, rcv_buf, parm_len + data_len);
|