LARGE_WRITE_X

tridge at samba.org tridge at samba.org
Tue Dec 14 03:47:40 GMT 2004


Jeremy and Steve,

I looked into large readx and large writex for Samba4 a few months
ago, and found it difficult to make reliable.

This is what we do at the moment for large readx/writex in Samba4.

In the packet recv code we cope with the incorrect bcc like this:

		if (req->in.data_size + 0x10000 <= 
		    req->in.size - PTR_DIFF(req->in.data, req->in.buffer) &&
		    (req->in.wct < 1 || SVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE)) {
			/* its an oversized packet! fun for all the family */
			req->in.data_size = req->in.size - PTR_DIFF(req->in.data,req->in.buffer);
		}

In readx we cope with large sizes like this:

	if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
		uint32_t high_part = IVAL(req->in.vwv, VWV(7));
		if (high_part == 1) {
			io->readx.in.maxcnt |= high_part << 16;
		}
	}

Note the ==1 check. That is important to cope as best as possible with
possible uninitialised data in this field.

In writex we cope with large sizes like this:

	if (req->in.wct == 14) {
		uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
		uint16_t count_high = SVAL(req->in.vwv, VWV(9));
		io->writex.in.offset |= (((uint64_t)offset_high) << 32);
		io->writex.in.count |= ((uint32_t)count_high) << 16;
	}
	/* make sure the data is in bounds */
	if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
		req_reply_error(req, NT_STATUS_UNSUCCESSFUL);
		return;
	} 

Finally, in the packet allocation code for readx we ensure that we do
not pad the data offset if the packet is exactly 0xFFFF long,
otherwise the pad bytes take us to 64k, and things fall apart:

	/* readx reply packets can be over-sized */
	req->control_flags |= REQ_CONTROL_LARGE;
	if (io->readx.in.maxcnt != 0xFFFF &&
	    io->readx.in.mincnt != 0xFFFF) {
		req_grow_data(req, 1 + io->readx.out.nread);
		SCVAL(req->out.data, 0, 0); /* padding */
	} else {
		req_grow_data(req, io->readx.out.nread);
	}

Also note the use of the request flag REQ_CONTROL_LARGE. This is an
internal flag in Samba4 that says "don't check the max buffer size
limits while processing this packet".

The worst problems happen with signing. Windows does not handle signed
connections with large readx/writex at all, even if the "large" just
means bigger than the negotiated buffer size, and smaller than 64k. 

Cheers, Tridge


More information about the samba-technical mailing list