Commit d48654bd authored by Ritesh Harjani (IBM)'s avatar Ritesh Harjani (IBM) Committed by Madhavan Srinivasan
Browse files

pseries/papr-hvpipe: Fix the usage of copy_to_user()



copy_to_user() return bytes_not_copied to the user buffer. If there was
an error writing bytes into the user buffer, i.e. if copy_to_user
returns a non-zero value, then we should simply return -EFAULT from the
->read() call.

Otherwise, in the non-patched version, we may end up mixing
"bytes_not_copied + bytes_copied (HVPIPE_HDR_LEN)" as the return value
to the user in ->read() call

Also let's make sure we clear the hvpipe_status flag, if we have
consumed the hvpipe msg by making the rtas call. ret = -EFAULT means
copy_to_user has failed but that still means that the msg was read from
the hvpipe, hence for both cases, success & -EFAULT, we should clear the
HVPIPE_MSG_AVAILABLE flag in hvpipe_status.

Cc: stable@vger.kernel.org
Fixes: cebdb522 ("powerpc/pseries: Receive payload with ibm,receive-hvpipe-msg RTAS")
Signed-off-by: default avatarRitesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: default avatarMadhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/8fda3212a1ad48879c174e92f67472d9b9f1c3b7.1777606826.git.ritesh.list@gmail.com
parent 713e468c
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -206,10 +206,11 @@ static int hvpipe_rtas_recv_msg(char __user *buf, int size)
					bytes_written, size);
				bytes_written = size;
			}
			ret = copy_to_user(buf,
			if (copy_to_user(buf,
					rtas_work_area_raw_buf(work_area),
					bytes_written);
			if (!ret)
					bytes_written))
				ret = -EFAULT;
			else
				ret = bytes_written;
		}
	} else {
@@ -328,7 +329,7 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,

	struct hvpipe_source_info *src_info = file->private_data;
	struct papr_hvpipe_hdr hdr = {};
	long ret;
	ssize_t ret = 0;

	/*
	 * Return -ENXIO during migration
@@ -376,7 +377,7 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,

	ret = copy_to_user(buf, &hdr, HVPIPE_HDR_LEN);
	if (ret)
		return ret;
		return -EFAULT;

	/*
	 * Message event has payload, so get the payload with
@@ -385,19 +386,23 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,
	if (hdr.flags & HVPIPE_MSG_AVAILABLE) {
		ret = hvpipe_rtas_recv_msg(buf + HVPIPE_HDR_LEN,
				size - HVPIPE_HDR_LEN);
		if (ret > 0) {
		/*
		 * Always clear MSG_AVAILABLE once the RTAS call has drained
		 * the message, regardless of whether copy_to_user succeeded.
		 */
		if (ret >= 0 || ret == -EFAULT)
			src_info->hvpipe_status &= ~HVPIPE_MSG_AVAILABLE;
			ret += HVPIPE_HDR_LEN;
		}
	} else if (hdr.flags & HVPIPE_LOST_CONNECTION) {
		/*
		 * Hypervisor is closing the pipe for the specific
		 * source. So notify user space.
		 */
		src_info->hvpipe_status &= ~HVPIPE_LOST_CONNECTION;
		ret = HVPIPE_HDR_LEN;
	}

	if (ret >= 0)
		ret += HVPIPE_HDR_LEN;

	return ret;
}