Commit 940e3a8dd6683a3787faf769b3df7a06f1c2fa31
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs
Pull v9fs update from Eric Van Hensbergen. * tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs: 9P: Fix race between p9_write_work() and p9_fd_request() 9P: Fix race in p9_write_work() 9P: fix test at the end of p9_write_work() 9P: Fix race in p9_read_work() 9p: don't use __getname/__putname for uname/aname net/9p: Check errno validity fs/9p: avoid debug OOPS when reading a long symlink
Showing 4 changed files Side-by-side Diff
fs/9p/v9fs.c
... | ... | @@ -184,10 +184,20 @@ |
184 | 184 | v9ses->afid = option; |
185 | 185 | break; |
186 | 186 | case Opt_uname: |
187 | - match_strlcpy(v9ses->uname, &args[0], PATH_MAX); | |
187 | + kfree(v9ses->uname); | |
188 | + v9ses->uname = match_strdup(&args[0]); | |
189 | + if (!v9ses->uname) { | |
190 | + ret = -ENOMEM; | |
191 | + goto free_and_return; | |
192 | + } | |
188 | 193 | break; |
189 | 194 | case Opt_remotename: |
190 | - match_strlcpy(v9ses->aname, &args[0], PATH_MAX); | |
195 | + kfree(v9ses->aname); | |
196 | + v9ses->aname = match_strdup(&args[0]); | |
197 | + if (!v9ses->aname) { | |
198 | + ret = -ENOMEM; | |
199 | + goto free_and_return; | |
200 | + } | |
191 | 201 | break; |
192 | 202 | case Opt_nodevmap: |
193 | 203 | v9ses->nodev = 1; |
194 | 204 | |
195 | 205 | |
196 | 206 | |
... | ... | @@ -287,21 +297,21 @@ |
287 | 297 | struct p9_fid *fid; |
288 | 298 | int rc; |
289 | 299 | |
290 | - v9ses->uname = __getname(); | |
300 | + v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); | |
291 | 301 | if (!v9ses->uname) |
292 | 302 | return ERR_PTR(-ENOMEM); |
293 | 303 | |
294 | - v9ses->aname = __getname(); | |
304 | + v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); | |
295 | 305 | if (!v9ses->aname) { |
296 | - __putname(v9ses->uname); | |
306 | + kfree(v9ses->uname); | |
297 | 307 | return ERR_PTR(-ENOMEM); |
298 | 308 | } |
299 | 309 | init_rwsem(&v9ses->rename_sem); |
300 | 310 | |
301 | 311 | rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY); |
302 | 312 | if (rc) { |
303 | - __putname(v9ses->aname); | |
304 | - __putname(v9ses->uname); | |
313 | + kfree(v9ses->aname); | |
314 | + kfree(v9ses->uname); | |
305 | 315 | return ERR_PTR(rc); |
306 | 316 | } |
307 | 317 | |
... | ... | @@ -309,8 +319,6 @@ |
309 | 319 | list_add(&v9ses->slist, &v9fs_sessionlist); |
310 | 320 | spin_unlock(&v9fs_sessionlist_lock); |
311 | 321 | |
312 | - strcpy(v9ses->uname, V9FS_DEFUSER); | |
313 | - strcpy(v9ses->aname, V9FS_DEFANAME); | |
314 | 322 | v9ses->uid = ~0; |
315 | 323 | v9ses->dfltuid = V9FS_DEFUID; |
316 | 324 | v9ses->dfltgid = V9FS_DEFGID; |
... | ... | @@ -412,8 +420,8 @@ |
412 | 420 | kfree(v9ses->cachetag); |
413 | 421 | } |
414 | 422 | #endif |
415 | - __putname(v9ses->uname); | |
416 | - __putname(v9ses->aname); | |
423 | + kfree(v9ses->uname); | |
424 | + kfree(v9ses->aname); | |
417 | 425 | |
418 | 426 | bdi_destroy(&v9ses->bdi); |
419 | 427 |
fs/9p/vfs_inode.c
... | ... | @@ -1276,12 +1276,12 @@ |
1276 | 1276 | } |
1277 | 1277 | |
1278 | 1278 | /* copy extension buffer into buffer */ |
1279 | - strncpy(buffer, st->extension, buflen); | |
1279 | + retval = min(strlen(st->extension)+1, (size_t)buflen); | |
1280 | + memcpy(buffer, st->extension, retval); | |
1280 | 1281 | |
1281 | - p9_debug(P9_DEBUG_VFS, "%s -> %s (%s)\n", | |
1282 | - dentry->d_name.name, st->extension, buffer); | |
1282 | + p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n", | |
1283 | + dentry->d_name.name, st->extension, buflen, buffer); | |
1283 | 1284 | |
1284 | - retval = strnlen(buffer, buflen); | |
1285 | 1285 | done: |
1286 | 1286 | p9stat_free(st); |
1287 | 1287 | kfree(st); |
net/9p/client.c
... | ... | @@ -76,6 +76,20 @@ |
76 | 76 | } |
77 | 77 | EXPORT_SYMBOL(p9_is_proto_dotu); |
78 | 78 | |
79 | +/* | |
80 | + * Some error codes are taken directly from the server replies, | |
81 | + * make sure they are valid. | |
82 | + */ | |
83 | +static int safe_errno(int err) | |
84 | +{ | |
85 | + if ((err > 0) || (err < -MAX_ERRNO)) { | |
86 | + p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err); | |
87 | + return -EPROTO; | |
88 | + } | |
89 | + return err; | |
90 | +} | |
91 | + | |
92 | + | |
79 | 93 | /* Interpret mount option for protocol version */ |
80 | 94 | static int get_protocol_version(char *s) |
81 | 95 | { |
... | ... | @@ -782,7 +796,7 @@ |
782 | 796 | return req; |
783 | 797 | reterr: |
784 | 798 | p9_free_req(c, req); |
785 | - return ERR_PTR(err); | |
799 | + return ERR_PTR(safe_errno(err)); | |
786 | 800 | } |
787 | 801 | |
788 | 802 | /** |
... | ... | @@ -865,7 +879,7 @@ |
865 | 879 | return req; |
866 | 880 | reterr: |
867 | 881 | p9_free_req(c, req); |
868 | - return ERR_PTR(err); | |
882 | + return ERR_PTR(safe_errno(err)); | |
869 | 883 | } |
870 | 884 | |
871 | 885 | static struct p9_fid *p9_fid_create(struct p9_client *clnt) |
net/9p/trans_fd.c
... | ... | @@ -316,8 +316,7 @@ |
316 | 316 | m->rsize - m->rpos); |
317 | 317 | p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err); |
318 | 318 | if (err == -EAGAIN) { |
319 | - clear_bit(Rworksched, &m->wsched); | |
320 | - return; | |
319 | + goto end_clear; | |
321 | 320 | } |
322 | 321 | |
323 | 322 | if (err <= 0) |
324 | 323 | |
325 | 324 | |
... | ... | @@ -379,19 +378,20 @@ |
379 | 378 | m->req = NULL; |
380 | 379 | } |
381 | 380 | |
381 | +end_clear: | |
382 | + clear_bit(Rworksched, &m->wsched); | |
383 | + | |
382 | 384 | if (!list_empty(&m->req_list)) { |
383 | 385 | if (test_and_clear_bit(Rpending, &m->wsched)) |
384 | 386 | n = POLLIN; |
385 | 387 | else |
386 | 388 | n = p9_fd_poll(m->client, NULL); |
387 | 389 | |
388 | - if (n & POLLIN) { | |
390 | + if ((n & POLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) { | |
389 | 391 | p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m); |
390 | 392 | schedule_work(&m->rq); |
391 | - } else | |
392 | - clear_bit(Rworksched, &m->wsched); | |
393 | - } else | |
394 | - clear_bit(Rworksched, &m->wsched); | |
393 | + } | |
394 | + } | |
395 | 395 | |
396 | 396 | return; |
397 | 397 | error: |
398 | 398 | |
399 | 399 | |
... | ... | @@ -453,12 +453,13 @@ |
453 | 453 | } |
454 | 454 | |
455 | 455 | if (!m->wsize) { |
456 | + spin_lock(&m->client->lock); | |
456 | 457 | if (list_empty(&m->unsent_req_list)) { |
457 | 458 | clear_bit(Wworksched, &m->wsched); |
459 | + spin_unlock(&m->client->lock); | |
458 | 460 | return; |
459 | 461 | } |
460 | 462 | |
461 | - spin_lock(&m->client->lock); | |
462 | 463 | req = list_entry(m->unsent_req_list.next, struct p9_req_t, |
463 | 464 | req_list); |
464 | 465 | req->status = REQ_STATUS_SENT; |
465 | 466 | |
... | ... | @@ -476,11 +477,10 @@ |
476 | 477 | clear_bit(Wpending, &m->wsched); |
477 | 478 | err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos); |
478 | 479 | p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err); |
479 | - if (err == -EAGAIN) { | |
480 | - clear_bit(Wworksched, &m->wsched); | |
481 | - return; | |
482 | - } | |
480 | + if (err == -EAGAIN) | |
481 | + goto end_clear; | |
483 | 482 | |
483 | + | |
484 | 484 | if (err < 0) |
485 | 485 | goto error; |
486 | 486 | else if (err == 0) { |
487 | 487 | |
488 | 488 | |
... | ... | @@ -492,19 +492,21 @@ |
492 | 492 | if (m->wpos == m->wsize) |
493 | 493 | m->wpos = m->wsize = 0; |
494 | 494 | |
495 | - if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) { | |
495 | +end_clear: | |
496 | + clear_bit(Wworksched, &m->wsched); | |
497 | + | |
498 | + if (m->wsize || !list_empty(&m->unsent_req_list)) { | |
496 | 499 | if (test_and_clear_bit(Wpending, &m->wsched)) |
497 | 500 | n = POLLOUT; |
498 | 501 | else |
499 | 502 | n = p9_fd_poll(m->client, NULL); |
500 | 503 | |
501 | - if (n & POLLOUT) { | |
504 | + if ((n & POLLOUT) && | |
505 | + !test_and_set_bit(Wworksched, &m->wsched)) { | |
502 | 506 | p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m); |
503 | 507 | schedule_work(&m->wq); |
504 | - } else | |
505 | - clear_bit(Wworksched, &m->wsched); | |
506 | - } else | |
507 | - clear_bit(Wworksched, &m->wsched); | |
508 | + } | |
509 | + } | |
508 | 510 | |
509 | 511 | return; |
510 | 512 |