summaryrefslogtreecommitdiffstats
path: root/fs/afs/cmservice.c
diff options
context:
space:
mode:
authorMarc Dionne <marc.dionne@auristor.com>2017-03-16 12:27:44 -0400
committerDavid Howells <dhowells@redhat.com>2017-03-16 12:27:44 -0400
commitbcd89270d93b7edebb5de5e5e7dca1a77a33496e (patch)
tree3e196dac7eed6313b0cd3111002434efc8ed0bb8 /fs/afs/cmservice.c
parent627f46943ff90bcc32ddeb675d881c043c6fa2ae (diff)
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: Marc Dionne <marc.dionne@auristor.com>
Diffstat (limited to 'fs/afs/cmservice.c')
-rw-r--r--fs/afs/cmservice.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 2edbdcbf6432..3062cceb5c2a 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -187,7 +187,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
187 struct afs_callback *cb; 187 struct afs_callback *cb;
188 struct afs_server *server; 188 struct afs_server *server;
189 __be32 *bp; 189 __be32 *bp;
190 u32 tmp;
191 int ret, loop; 190 int ret, loop;
192 191
193 _enter("{%u}", call->unmarshall); 192 _enter("{%u}", call->unmarshall);
@@ -249,9 +248,9 @@ static int afs_deliver_cb_callback(struct afs_call *call)
249 if (ret < 0) 248 if (ret < 0)
250 return ret; 249 return ret;
251 250
252 tmp = ntohl(call->tmp); 251 call->count2 = ntohl(call->tmp);
253 _debug("CB count: %u", tmp); 252 _debug("CB count: %u", call->count2);
254 if (tmp != call->count && tmp != 0) 253 if (call->count2 != call->count && call->count2 != 0)
255 return -EBADMSG; 254 return -EBADMSG;
256 call->offset = 0; 255 call->offset = 0;
257 call->unmarshall++; 256 call->unmarshall++;
@@ -259,14 +258,14 @@ static int afs_deliver_cb_callback(struct afs_call *call)
259 case 4: 258 case 4:
260 _debug("extract CB array"); 259 _debug("extract CB array");
261 ret = afs_extract_data(call, call->buffer, 260 ret = afs_extract_data(call, call->buffer,
262 call->count * 3 * 4, false); 261 call->count2 * 3 * 4, false);
263 if (ret < 0) 262 if (ret < 0)
264 return ret; 263 return ret;
265 264
266 _debug("unmarshall CB array"); 265 _debug("unmarshall CB array");
267 cb = call->request; 266 cb = call->request;
268 bp = call->buffer; 267 bp = call->buffer;
269 for (loop = call->count; loop > 0; loop--, cb++) { 268 for (loop = call->count2; loop > 0; loop--, cb++) {
270 cb->version = ntohl(*bp++); 269 cb->version = ntohl(*bp++);
271 cb->expiry = ntohl(*bp++); 270 cb->expiry = ntohl(*bp++);
272 cb->type = ntohl(*bp++); 271 cb->type = ntohl(*bp++);