[jcifs] SmbComWriteAndX writes corrupt offset to wire

Michael B Allen mba2000 at ioplex.com
Wed Apr 14 02:55:45 GMT 2004


Hi Richard,

> After the server has been running for a few 10s of minutes we notice
> that the files written to the share are corrupt. It seems that files are
> initially copied ok, and then something 'breaks'. An ethereal trace
> shows that the offset of the server-bound WriteAndX messages is corrupt.

So once it happends it never corrects itself? That's strange because
you would think that provided the SmbFileOutputStream is closed and is
used exclusively by a single thread that any state associated with that
object would be reset when the next object was created. Has to be related
to some static variable/object.

> The following code...
> byte[] buffer = new byte[4000];
> while ((int length = in.read(buffer)) > 0) {
>   out.write(buffer, 0, length);
> }
> produces WriteAndX messages with the following offsets...
> 0, 3840, 7936, etc (instead of 0, 4000, 8000)
> in hex these values are: 0x0F00 and 0x1F00 (should be 0x0FA0 and 0x1F40
> - i.e. it appears that the bottom byte is being squashed to zero)
>
> This appears to be confirmed by the following ALL level log:
> Apr 9 12:25:53.107 - smb sent
> SmbComWriteAndX[command=SMB_COM_WRITE_ANDX,received=false,
> errorCode=0x00000000,flags=0x0018,flags2=0x8003,tid=28677,pid=22517,
> uid=57345,mid=2957,wordCount=14,byteCount=4000,andxCommand=0xFF,
> andxOffset=0,fid=9,offset=4000,writeMode=0,remaining=0,dataLength=4000,
> dataOffset=63]
> Apr 9 12:25:53.107 - smb sent
> 00000: FF 53 4D 42 2F 00 00 00 00 18 03 80 00 00 00 00  |ÿSMB/...........|
> 00010: 00 00 00 00 00 00 00 00 05 70 F5 57 01 E0 8D 0B  |.........põW.à..|
> 00020: 0E FF 00 00 00 09 00 00 0F 00 00 00 00 00 00 00  |.ÿ..............|
> 00030: 00 00 00 00 00 A0 0F 3F 00 00 00 00 00 A0 0F 58  |..... .?..... .X|

That's very interesting. It looks like an encoding error. Unfortunately
I have spend several hours trying to track this down without any luck. I
do not see anything obviously wrong with the encoding routines and I have
created a test program that writes 259760 byte file to a server every
800ms and then reads it back every 3 seconds. After letting it run for a
good hour with -Xmx500k for a while now I'm not seeing any problems.

> What is interesting is that the toString() of the SmbComWriteAndX still
> shows 4000, yet the hex dump shows 00 0F 00 00 (decimal 3840)

Yes it is. Good catch. It might be critically important. Can you try this
jar?

  http://home.comcast.net/~miallen1/jcifs/jcifs-0.8.2x.jar

Maybe we can zoom in on where the encoding error. Don't run with
log=ALL. It has very selective debugging statements hardcoded in
it. Basically the encoding routines for SmbComWriteAndX are called like:

writeWireFormat
	writeHeaderWriteFormat
	writeAndXWireFormat
		writeParameterWordsWireFormat
		writeBytesWireFormat

The offset is encoded in writeParameterWordsWireFormat but I suspect
it could be that it's encoded properly there only to be clobbered
by something or someone else. So I have placed hexdump calls at the
end of writeWireFormat, at the end of writeAndXWireFormat, and end
of writeParameterWordsWireFormat. The System.err output should looks
something like this:

main: writeParameterWordsWireFormat: offset=188000
00000: FF 53 4D 42 2F 00 00 00 00 18 03 80 00 00 00 00  |ÿSMB/...........|
00010: 00 00 00 00 00 00 00 00 00 08 6B 12 00 08 DF 16  |..........k...ß.|
00020: 0E FF 00 00 00 07 30 60 DE 02 00 00 00 00 00 00  |.ÿ....0`Þ.......|
00030: 00 00 00 00 00 A0 0F 3F 00 00 00 00              |..... .?....    |

main: writeAndXWireFormat1
00000: FF 53 4D 42 2F 00 00 00 00 18 03 80 00 00 00 00  |ÿSMB/...........|
00010: 00 00 00 00 00 00 00 00 00 08 6B 12 00 08 DF 16  |..........k...ß.|
00020: 0E FF 00 00 00 07 30 60 DE 02 00 00 00 00 00 00  |.ÿ....0`Þ.......|
00030: 00 00 00 00 00 A0 0F 3F 00 00 00 00 00 A0 0F     |..... .?..... . |

main: writeWireFormat
00000: FF 53 4D 42 2F 00 00 00 00 18 03 80 00 00 00 00  |ÿSMB/...........|
00010: 00 00 00 00 00 00 00 00 00 08 6B 12 00 08 DF 16  |..........k...ß.|
00020: 0E FF 00 00 00 07 30 60 DE 02 00 00 00 00 00 00  |.ÿ....0`Þ.......|
00030: 00 00 00 00 00 A0 0F 3F 00 00 00 00 00 A0 0F     |..... .?..... . |

main:
SmbComWriteAndX[command=SMB_COM_WRITE_ANDX,received=false,errorCode=0x00000000,flags=0x0018,flags2=0x8003,tid=2048,pid=4715,uid=2048,mid=5855,wordCount=14,byteCount=4000,andxCommand=0xFF,andxOffset=0,fid=12295,offset=188000,writeMode=0,remaining=0,dataLength=4000,dataOffset=63]
00000: FF 53 4D 42 2F 00 00 00 00 18 03 80 00 00 00 00  |ÿSMB/...........|
00010: 00 00 00 00 00 00 00 00 00 08 6B 12 00 08 DF 16  |..........k...ß.|
00020: 0E FF 00 00 00 07 30 60 DE 02 00 00 00 00 00 00  |.ÿ....0`Þ.......|
00030: 00 00 00 00 00 A0 0F 3F 00 00 00 00 00 A0 0F     |..... .?..... . |

So each sub-encoding method is called first and then the full SMB toString
and it's hexdump is printed immediately after the packet is written to the
wire. So this last dump is what should appear on the wire. Also notice the
thread name preceeds every debugging message (in the above case it is
'main').

The data shown is just the header so the third line will always look like
this (not to be confused with other packets that will likey have a
different
WordCount other than 0E):

00020: 0E FF 00 00 00 07 30 60 DE 02 00 00 00 00 00 00  |.ÿ....0`Þ.......|
       1  2  3  4     5     6           7

The fields are:

1 WordCount
2 AndXCommand
3 AndXReserved
4 AndXOffset
5 Fid
6 Offset <---- HERE'S THE OFFSET FIELD
7 Reserved

So you should be able to just eyeball that 1st byte of the Offset (0x60
depicted above) and zero in on where it get's clobbered to 0x00. Can
you do that?

Also you might try this jar:

   http://home.comcast.net/~miallen1/jcifs/jcifs-0.9.0p3.jar

It has some very significant changes regarding how the NbtSocket layer
works and how MIDs (multiplex ids) are allocated. It's basically a
"cleanup release" so it's very much a work in progress but it's reported
to work well so far. Probably won't make a difference but it's worth a
shot.

> There seems so little time/space for this to go wrong!
> Could the signing be going wrong - don't think so - we don't think we
> are using this and, anyway it would do an arraycopy of 8 bytes

Doubt it's signing.

> writeWireFormat just calls writeHeader and writeAndXWireFormat which
> seem simple enough...

Right. If toString says offset is right (4000) but the hexdump printed
after the packet is written to the wire is wrong than let's see if we can
zoom in on what in between is causing that byte to get clobbered.

> there does not seem to be batching going on...

I've never seen anything batch with an SmbComWriteAndX. You can set
jcifs.smb.client.useBatching = false.

This is kind of a serious bug so I hope we can figure it out. I just
wish I could reproduce it. It's going to be tough without a minimalistic
program to reproduce the issue.

Mike



More information about the jcifs mailing list