Skip to content

Commit

Permalink
Convert MessageID in smb2_hdr to LE
Browse files Browse the repository at this point in the history
We have encountered failures when When testing smb2 mounts on ppc64
machines when using both Samba as well as Windows 2012.

On poking around, the problem was determined to be caused by the
high endian MessageID passed in the header for smb2. On checking the
corresponding MID for smb1 is converted to LE before being sent on the
wire.

We have tested this patch successfully on a ppc64 machine.

Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
  • Loading branch information
Sachin Prabhu authored and Steve French committed Dec 14, 2014
1 parent 9ea18f8 commit 9235d09
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 11 deletions.
6 changes: 3 additions & 3 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -661,16 +661,16 @@ set_credits(struct TCP_Server_Info *server, const int val)
server->ops->set_credits(server, val);
}

static inline __u64
static inline __le64
get_next_mid64(struct TCP_Server_Info *server)
{
return server->ops->get_next_mid(server);
return cpu_to_le64(server->ops->get_next_mid(server));
}

static inline __le16
get_next_mid(struct TCP_Server_Info *server)
{
__u16 mid = get_next_mid64(server);
__u16 mid = server->ops->get_next_mid(server);
/*
* The value in the SMB header should be little endian for easy
* on-the-wire decoding.
Expand Down
12 changes: 7 additions & 5 deletions fs/cifs/smb2misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
static int
check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
{
__u64 wire_mid = le64_to_cpu(hdr->MessageId);

/*
* Make sure that this really is an SMB, that it is a response,
* and that the message ids match.
*/
if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) &&
(mid == hdr->MessageId)) {
(mid == wire_mid)) {
if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
return 0;
else {
Expand All @@ -51,11 +53,11 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER)
cifs_dbg(VFS, "Bad protocol string signature header %x\n",
*(unsigned int *) hdr->ProtocolId);
if (mid != hdr->MessageId)
if (mid != wire_mid)
cifs_dbg(VFS, "Mids do not match: %llu and %llu\n",
mid, hdr->MessageId);
mid, wire_mid);
}
cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", hdr->MessageId);
cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", wire_mid);
return 1;
}

Expand Down Expand Up @@ -95,7 +97,7 @@ smb2_check_message(char *buf, unsigned int length)
{
struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
__u64 mid = hdr->MessageId;
__u64 mid = le64_to_cpu(hdr->MessageId);
__u32 len = get_rfc1002_length(buf);
__u32 clc_len; /* calculated length */
int command;
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/smb2ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,11 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
{
struct mid_q_entry *mid;
struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
__u64 wire_mid = le64_to_cpu(hdr->MessageId);

spin_lock(&GlobalMid_Lock);
list_for_each_entry(mid, &server->pending_mid_q, qhead) {
if ((mid->mid == hdr->MessageId) &&
if ((mid->mid == wire_mid) &&
(mid->mid_state == MID_REQUEST_SUBMITTED) &&
(mid->command == hdr->Command)) {
spin_unlock(&GlobalMid_Lock);
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/smb2pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ struct smb2_hdr {
__le16 CreditRequest; /* CreditResponse */
__le32 Flags;
__le32 NextCommand;
__u64 MessageId; /* opaque - so can stay little endian */
__le64 MessageId;
__le32 ProcessId;
__u32 TreeId; /* opaque - so do not make little endian */
__u64 SessionId; /* opaque - so do not make little endian */
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/smb2transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
return temp;
else {
memset(temp, 0, sizeof(struct mid_q_entry));
temp->mid = smb_buffer->MessageId; /* always LE */
temp->mid = le64_to_cpu(smb_buffer->MessageId);
temp->pid = current->pid;
temp->command = smb_buffer->Command; /* Always LE */
temp->when_alloc = jiffies;
Expand Down

0 comments on commit 9235d09

Please sign in to comment.