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);