Commit 97567a23 authored by Marc Dionne's avatar Marc Dionne Committed by David Howells

afs: Deal with an empty callback array

Servers may send a callback array that is the same size as
the FID array, or an empty array.  If the callback count is
0, the code would attempt to read (fid_count * 12) bytes of
data, which would fail and result in an unmarshalling error.
This would lead to stale data for remotely modified files
or directories.

Store the callback array size in the internal afs_call
structure and use that to determine the amount of data to
read.
Signed-off-by: default avatarMarc Dionne <marc.dionne@auristor.com>
parent 4336ae58
...@@ -187,7 +187,6 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -187,7 +187,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
struct afs_callback *cb; struct afs_callback *cb;
struct afs_server *server; struct afs_server *server;
__be32 *bp; __be32 *bp;
u32 tmp;
int ret, loop; int ret, loop;
_enter("{%u}", call->unmarshall); _enter("{%u}", call->unmarshall);
...@@ -249,9 +248,9 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -249,9 +248,9 @@ static int afs_deliver_cb_callback(struct afs_call *call)
if (ret < 0) if (ret < 0)
return ret; return ret;
tmp = ntohl(call->tmp); call->count2 = ntohl(call->tmp);
_debug("CB count: %u", tmp); _debug("CB count: %u", call->count2);
if (tmp != call->count && tmp != 0) if (call->count2 != call->count && call->count2 != 0)
return -EBADMSG; return -EBADMSG;
call->offset = 0; call->offset = 0;
call->unmarshall++; call->unmarshall++;
...@@ -259,14 +258,14 @@ static int afs_deliver_cb_callback(struct afs_call *call) ...@@ -259,14 +258,14 @@ static int afs_deliver_cb_callback(struct afs_call *call)
case 4: case 4:
_debug("extract CB array"); _debug("extract CB array");
ret = afs_extract_data(call, call->buffer, ret = afs_extract_data(call, call->buffer,
call->count * 3 * 4, false); call->count2 * 3 * 4, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
_debug("unmarshall CB array"); _debug("unmarshall CB array");
cb = call->request; cb = call->request;
bp = call->buffer; bp = call->buffer;
for (loop = call->count; loop > 0; loop--, cb++) { for (loop = call->count2; loop > 0; loop--, cb++) {
cb->version = ntohl(*bp++); cb->version = ntohl(*bp++);
cb->expiry = ntohl(*bp++); cb->expiry = ntohl(*bp++);
cb->type = ntohl(*bp++); cb->type = ntohl(*bp++);
......
...@@ -90,7 +90,10 @@ struct afs_call { ...@@ -90,7 +90,10 @@ struct afs_call {
unsigned request_size; /* size of request data */ unsigned request_size; /* size of request data */
unsigned reply_max; /* maximum size of reply */ unsigned reply_max; /* maximum size of reply */
unsigned first_offset; /* offset into mapping[first] */ unsigned first_offset; /* offset into mapping[first] */
unsigned last_to; /* amount of mapping[last] */ union {
unsigned last_to; /* amount of mapping[last] */
unsigned count2; /* count used in unmarshalling */
};
unsigned char unmarshall; /* unmarshalling phase */ unsigned char unmarshall; /* unmarshalling phase */
bool incoming; /* T if incoming call */ bool incoming; /* T if incoming call */
bool send_pages; /* T if data from mapping should be sent */ bool send_pages; /* T if data from mapping should be sent */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment