Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42fe6484 authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Eric Van Hensbergen
Browse files

net/9p: Handle error in zero copy request correctly for 9p2000.u



For zero copy request, error will be encoded in the user space buffer.
So copy the error code correctly using copy_from_user. Here we use the
extra bytes we allocate for zero copy request. If total error details
are more than P9_ZC_HDR_SZ - 7 bytes, we return -EFAULT. The patch also
avoid a memory allocation in the error path.

Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
parent 535bcd3c
Loading
Loading
Loading
Loading
+18 −37
Original line number Diff line number Diff line
@@ -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;
			goto out_err;
		}
		if (len <= inline_len) {
			/* We have error in protocol buffer itself */
			if (pdu_read(req->rc, ename, len)) {
		len =  req->rc->size - req->rc->offset;
		if (len > (P9_ZC_HDR_SZ - 7)) {
			err = -EFAULT;
				goto out_free;

			goto out_err;
		}
		} 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);
		ename = NULL;
		err = p9pdu_readf(req->rc, c->proto_version, "s?d",
				  &ename, &ecode);
		if (err)
				goto out_free;
			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;