summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-06-11 04:35:25 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-06-11 04:35:25 +0400
commit1b79821fe7855c34030bc2f177660874e0a0ab62 (patch)
tree0421a6958fabad4a7b25f9bfc6232ed332f1a2c6
parentab0296319a8cb970f4e42659472bb40fbfae3e56 (diff)
parent6390460af8a672754dd6743f326515e98f52b2a7 (diff)
downloadlinux-1b79821fe7855c34030bc2f177660874e0a0ab62.tar.xz
Merge tag '9p-3.10-bug-fix-1' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs
Pull net/9p bug fix from Eric Van Hensbergen: "zero copy error fix" * tag '9p-3.10-bug-fix-1' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs: net/9p: Handle error in zero copy request correctly for 9p2000.u
-rw-r--r--net/9p/client.c55
1 files changed, 18 insertions, 37 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 8eb75425e6e6..addc116cecf0 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -562,36 +562,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
if (!p9_is_proto_dotl(c)) {
/* Error is reported in string format */
- uint16_t len;
- /* 7 = header size for RERROR, 2 is the size of string len; */
- int inline_len = in_hdrlen - (7 + 2);
+ int len;
+ /* 7 = header size for RERROR; */
+ int inline_len = in_hdrlen - 7;
- /* Read the size of error string */
- err = p9pdu_readf(req->rc, c->proto_version, "w", &len);
- if (err)
- goto out_err;
-
- ename = kmalloc(len + 1, GFP_NOFS);
- if (!ename) {
- err = -ENOMEM;
+ len = req->rc->size - req->rc->offset;
+ if (len > (P9_ZC_HDR_SZ - 7)) {
+ err = -EFAULT;
goto out_err;
}
- if (len <= inline_len) {
- /* We have error in protocol buffer itself */
- if (pdu_read(req->rc, ename, len)) {
- err = -EFAULT;
- goto out_free;
- }
- } else {
- /*
- * Part of the data is in user space buffer.
- */
- if (pdu_read(req->rc, ename, inline_len)) {
- err = -EFAULT;
- goto out_free;
-
- }
+ ename = &req->rc->sdata[req->rc->offset];
+ if (len > inline_len) {
+ /* We have error in external buffer */
if (kern_buf) {
memcpy(ename + inline_len, uidata,
len - inline_len);
@@ -600,19 +583,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
uidata, len - inline_len);
if (err) {
err = -EFAULT;
- goto out_free;
+ goto out_err;
}
}
}
- ename[len] = 0;
- if (p9_is_proto_dotu(c)) {
- /* For dotu we also have error code */
- err = p9pdu_readf(req->rc,
- c->proto_version, "d", &ecode);
- if (err)
- goto out_free;
+ ename = NULL;
+ err = p9pdu_readf(req->rc, c->proto_version, "s?d",
+ &ename, &ecode);
+ if (err)
+ goto out_err;
+
+ if (p9_is_proto_dotu(c))
err = -ecode;
- }
+
if (!err || !IS_ERR_VALUE(err)) {
err = p9_errstr2errno(ename, strlen(ename));
@@ -628,8 +611,6 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
}
return err;
-out_free:
- kfree(ename);
out_err:
p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
return err;