From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754931AbbLIKEY (ORCPT ); Wed, 9 Dec 2015 05:04:24 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:45394 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754671AbbLIJlA (ORCPT ); Wed, 9 Dec 2015 04:41:00 -0500 From: Luis Henriques To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com Cc: Eric Biggers , Al Viro , Luis Henriques Subject: [PATCH 3.16.y-ckt 085/126] fs/pipe.c: return error code rather than 0 in pipe_write() Date: Wed, 9 Dec 2015 09:37:35 +0000 Message-Id: <1449653896-5236-86-git-send-email-luis.henriques@canonical.com> In-Reply-To: <1449653896-5236-1-git-send-email-luis.henriques@canonical.com> References: <1449653896-5236-1-git-send-email-luis.henriques@canonical.com> X-Extended-Stable: 3.16 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.7-ckt21 -stable review patch. If anyone has any objections, please let me know. ------------------ From: Eric Biggers commit 6ae08069939f17422835448acae76bda8d96b16a upstream. pipe_write() would return 0 if it failed to merge the beginning of the data to write with the last, partially filled pipe buffer. It should return an error code instead. Userspace programs could be confused by write() returning 0 when called with a nonzero 'count'. The EFAULT error case was a regression from f0d1bec9d5 ("new helper: copy_page_from_iter()"), while the ops->confirm() error case was a much older bug. Test program: #include #include #include int main(void) { int fd[2]; char data[1] = {0}; assert(0 == pipe(fd)); assert(1 == write(fd[1], data, 1)); /* prior to this patch, write() returned 0 here */ assert(-1 == write(fd[1], NULL, 1)); assert(errno == EFAULT); } Signed-off-by: Eric Biggers Signed-off-by: Al Viro Signed-off-by: Luis Henriques --- fs/pipe.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index 21981e58e2a6..6c856a155530 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -367,18 +367,17 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) int offset = buf->offset + buf->len; if (ops->can_merge && offset + chars <= PAGE_SIZE) { - int error = ops->confirm(pipe, buf); - if (error) + ret = ops->confirm(pipe, buf); + if (ret) goto out; ret = copy_page_from_iter(buf->page, offset, chars, from); if (unlikely(ret < chars)) { - error = -EFAULT; + ret = -EFAULT; goto out; } do_wakeup = 1; - buf->len += chars; - ret = chars; + buf->len += ret; if (!iov_iter_count(from)) goto out; }