Padding byte in cifs readx response
Christof Schmitt
cs at samba.org
Fri Aug 1 16:19:05 MDT 2014
On Wed, Jul 30, 2014 at 05:09:45PM -0700, Jeremy Allison wrote:
> On Wed, Jul 30, 2014 at 04:34:01PM -0700, Christof Schmitt wrote:
> > It was pointed out to me that a padding byte in the readx response is
> > missing:
> >
> > http://msdn.microsoft.com/en-us/library/ee441872.aspx
> > Pad (1 byte): This field is optional. When using the NT LAN Manager
> > dialect, this field can be used to align the Data field to a 16-bit
> > boundary relative to the start of the SMB Header. If Unicode strings are
> > being used, this field MUST be present. When used, this field MUST be
> > one padding byte long.
> >
> > I wrote a simple test for this, and it succeeds against a Windows 7 and
> > fails in
> > make test TESTS=raw.read
> >
> > UNEXPECTED(failure): samba3.raw.read.readx(s3dc)
> > REASON: _StringException: _StringException:
> > ../source4/torture/raw/read.c:441: data not 16 bit aligned
> > envlog: SMBD LOG of: LOCALS3DC2
>
> Probably missing in smbd in order to make the sendfile
> code easier....
>
> I'm guessing the Windows client works fine without it,
> but probably a good thing to fix so long as it doesn't
> make smbd horribly slower in this case.
I am trying to fix the non-sendfile codepath first, but i seem to be
missing something. The attached patch is my current (failing) attempt, i
will continue with this next week.
Christof
-------------- next part --------------
>From e648ede0ff875a92a1eeea0cc7d404da78bc819d Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Fri, 1 Aug 2014 15:17:04 -0700
Subject: [PATCH] wip
---
source3/smbd/process.c | 29 +++++++++++++++++++++++++----
source3/smbd/proto.h | 1 +
source3/smbd/reply.c | 6 ++++--
3 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 127bbb3..5d20516 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1336,10 +1336,14 @@ static const struct smb_message_struct {
static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
const char *inbuf, char **outbuf, uint8_t num_words,
- uint32_t num_bytes)
+ uint32_t num_bytes, bool pad)
{
size_t smb_len = MIN_SMB_SIZE + VWV(num_words) + num_bytes;
+ if (pad) {
+ smb_len += 1;
+ }
+
/*
* Protect against integer wrap.
* The SMB layer reply can be up to 0xFFFFFF bytes.
@@ -1363,7 +1367,15 @@ static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
}
construct_reply_common(req, inbuf, *outbuf);
- srv_set_message(*outbuf, num_words, num_bytes, false);
+
+ SCVAL(*outbuf,smb_wct,num_words);
+ SSVAL(*outbuf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
+ if (pad) {
+ smb_setlen(*outbuf,(smb_size + num_words*2 + 1 + num_bytes - 4));
+ } else {
+ smb_setlen(*outbuf,(smb_size + num_words*2 + num_bytes - 4));
+ }
+
/*
* Zero out the word area, the caller has to take care of the bcc area
* himself
@@ -1379,12 +1391,21 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
{
char *outbuf;
if (!create_outbuf(req, req, (const char *)req->inbuf, &outbuf, num_words,
- num_bytes)) {
+ num_bytes, false)) {
smb_panic("could not allocate output buffer\n");
}
req->outbuf = (uint8_t *)outbuf;
}
+void reply_outbuf_pad(struct smb_request *req, uint8 num_words, uint32 num_bytes)
+{
+ char *outbuf;
+ if (!create_outbuf(req, req, (const char *)req->inbuf, &outbuf, num_words,
+ num_bytes, true)) {
+ smb_panic("could not allocate output buffer\n");
+ }
+ req->outbuf = (uint8_t *)outbuf;
+}
/*******************************************************************
Dump a packet to a file.
@@ -3039,7 +3060,7 @@ static bool smbd_echo_reply(struct smbd_echo_state *state,
}
if (!create_outbuf(talloc_tos(), &req, (const char *)req.inbuf, &outbuf,
- 1, req.buflen)) {
+ 1, req.buflen, false)) {
DEBUG(10, ("create_outbuf failed\n"));
return false;
}
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index eab05c2..ed777e9 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -769,6 +769,7 @@ bool push_deferred_open_message_smb(struct smb_request *req,
struct deferred_open_record *open_rec);
NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid);
void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes);
+void reply_outbuf_pad(struct smb_request *req, uint8 num_words, uint32 num_bytes);
void smb_request_done(struct smb_request *req);
const char *smb_fn_name(int type);
void add_to_common_flags2(uint32 v);
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index d54326a..1751d27 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3674,7 +3674,8 @@ static int setup_readX_header(struct smb_request *req, char *outbuf,
(smb_wct - 4) /* offset from smb header to wct */
+ 1 /* the wct field */
+ 12 * sizeof(uint16_t) /* vwv */
- + 2); /* the buflen field */
+ + 2 /* the buflen field */
+ + 1); /* padding byte */
SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
SSVAL(outbuf,smb_vwv11,smb_maxcnt);
/* Reset the outgoing length, set_message truncates at 0x1FFFF. */
@@ -3849,7 +3850,8 @@ normal_read:
nosendfile_read:
- reply_outbuf(req, 12, smb_maxcnt);
+ reply_outbuf_pad(req, 12, smb_maxcnt);
+
SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
--
1.7.1
More information about the samba-technical
mailing list