From patchwork Wed Aug 29 21:20:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 145476 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp61878ljw; Wed, 29 Aug 2018 14:20:52 -0700 (PDT) X-Google-Smtp-Source: ANB0VdbJcXEus9bJuhn4BIz+7EJ22SC4vqqi9gX6t45L6OtwD1v8H4Of0HJ/zhRp9KZ/0uURoRLa X-Received: by 2002:a17:902:f20f:: with SMTP id gn15mr7377636plb.173.1535577652348; Wed, 29 Aug 2018 14:20:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535577652; cv=none; d=google.com; s=arc-20160816; b=I+bVLD83G6HZuGCa9WNEyS7E4ItxeY4niCbteG7UjRiO+n+9WHn4yhB3hNmwXEpx8N ZT79k1ZQguN+1fH258XAUDWSr3+g/35YKHQ/h+npkA+njTmjUGl7KX7JDresk4JbNahc 8f1GbHSaHCSeRQL3rluH8hHu+w9zTiC+NjFtk4Zqg7aqb8J54UN5rJA6WmG+QnXMDzVl w71CVJX5uh5vRJMTzzNx2VjOZKE/ixYdABJDNED0FwKDMuZOT9PbLTFLQz+k0++ibb7x UI5b8F6GuQ/UtkrtcdJwkRJ8yi3dX8kOVKhwrNS+19Zh4iXLppeSXTtvVY3EkKP77ZDe O+/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=message-id:date:subject:to:from:dkim-signature:delivered-to:sender :list-help:list-post:list-archive:list-subscribe:list-unsubscribe :list-id:precedence:mailing-list:dkim-signature:domainkey-signature :arc-authentication-results; bh=lalW4HWR3JgMGGPMCcPSj5SBoiOBbd9jPWXMdWE3ae0=; b=nqztoJbV7znmdDA2XtuYq/kqJ0UImL7sj2jusmpg5iAPLvtg0OdEE99jijMCyc473k wI5qxENxazFZi9pC8Z+AuQysPR0r1OWF0uViNMqMb+QmvsbL/dRtSU637JZWd9KZnfIK OTGj2ZZ77GZ4raLvXrJe7D72aqDH4nLQwtn91vpBKO23tbJRjMq4m0RAQeSeXWFNZ+di yiiUwDoEq9P5LoF4/l6fj0R2oNC+ya205L4gDBkaKYsR27zdrd21YKQxhitNut6txF4k /kmlBqje2liDOgTyVj5YcYDGsS7uEva+09uVgD3VYDyxniuVheVAp63g7z9fVf/xRAtq HC3Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=XE5dgun6; dkim=pass header.i=@linaro.org header.s=google header.b=hENJCtCa; spf=pass (google.com: domain of libc-alpha-return-95572-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="libc-alpha-return-95572-patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id z123-v6si5085279pfc.289.2018.08.29.14.20.51 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 29 Aug 2018 14:20:52 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-return-95572-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=XE5dgun6; dkim=pass header.i=@linaro.org header.s=google header.b=hENJCtCa; spf=pass (google.com: domain of libc-alpha-return-95572-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="libc-alpha-return-95572-patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id; q=dns; s= default; b=GhEqO/xNjijyNFN0Pzezube9jiDVCSmN4+AdGHwe1lArvrFaYm00M KoCARtrvCifsrs7cqzgYBAX1P4dAxpmQ/awRPccw37V1Y3qYZUDJNHgS9Jk5XbBT wAG3LvMXwAjo06vRd6tl46CYGRtz+Ef/wifskKDf6SsTvuFHGsRzp0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id; s=default; bh=enOBfNDSID9cetZjzksxXPASbK4=; b=XE5dgun6tht011hwPVyPF5QsKAKf 1+3vqdSAey1aGxE1MHRYtOZp+9CdO/0iCVz8z0CYSdjKHiAbcVi2lkbd2XoyLfRU ewiSudVnSl52l2iwzGOpuMjn2x3e8QYnAaO8Ss+nc1VlmITmbS3fXYMwI4X81v7I ZQ44MnGSfUrOACU= Received: (qmail 74445 invoked by alias); 29 Aug 2018 21:20:43 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 74436 invoked by uid 89); 29 Aug 2018 21:20:42 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SEM_URI, SEM_URIRED, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-qk0-f194.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id; bh=lalW4HWR3JgMGGPMCcPSj5SBoiOBbd9jPWXMdWE3ae0=; b=hENJCtCalD6oF6Vsj7Rh+mfUO/oiYkTcipAOeYWBOscHza5IbNtSm6Yj89qi8Sqaie KTeoivgKWWEeBCx/HJnNT5SnCDeKvh5QN+Bjbv4E6MXeF1xobPsP87nDVGIlqr/uKfXc WsSodQpi1igZ89X+TChw98duMo7j7tTrCzQO4= Return-Path: From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH] Fix misreported errno on preadv2/pwritev2 (BZ#23579) Date: Wed, 29 Aug 2018 18:20:32 -0300 Message-Id: <20180829212032.32507-1-adhemerval.zanella@linaro.org> The fallback code of Linux wrapper for preadv2/pwritev2 executes regardless of the errno code for preadv2, instead of the case where the syscall is not supported. This fixes it by calling the fallback code iff errno is ENOSYS. The patch also adds tests for both invalid file descriptor and invalid iov_len and vector count. The only discrepancy between preadv2 and fallback code regarding error reporting is when an invalid flags are used. The fallback code bails out earlier with ENOTSUP instead of EINVAL/EBADF when the syscall is used. Checked on x86_64-linux-gnu on a 4.4.0 and 4.15.0 kernel. [BZ #23579] * misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd): New test. * misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test): Call do_test_with_invalid_fd. * sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff errno is ENOSYS. * sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise. * sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise. * sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise. --- ChangeLog | 13 ++++++ misc/tst-preadvwritev2-common.c | 65 +++++++++++++++++++++++++-- misc/tst-preadvwritev2.c | 2 + misc/tst-preadvwritev64v2.c | 2 + sysdeps/unix/sysv/linux/preadv2.c | 2 +- sysdeps/unix/sysv/linux/preadv64v2.c | 2 +- sysdeps/unix/sysv/linux/pwritev2.c | 2 +- sysdeps/unix/sysv/linux/pwritev64v2.c | 2 +- 8 files changed, 83 insertions(+), 7 deletions(-) -- 2.17.1 diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c index f889a21544..50b9da3fea 100644 --- a/misc/tst-preadvwritev2-common.c +++ b/misc/tst-preadvwritev2-common.c @@ -19,9 +19,6 @@ #include #include -static void -do_test_with_invalid_flags (void) -{ #ifndef RWF_HIPRI # define RWF_HIPRI 0 #endif @@ -39,6 +36,68 @@ do_test_with_invalid_flags (void) #endif #define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \ | RWF_APPEND) + +static void +do_test_with_invalid_fd (void) +{ + char buf[256]; + struct iovec iov = { buf, sizeof buf }; + + /* Check with flag being 0 to use the fallback code which calls pwritev + or writev. */ + TEST_VERIFY (preadv2 (-1, &iov, 1, -1, 0) == -1); + TEST_COMPARE (errno, EBADF); + TEST_VERIFY (pwritev2 (-1, &iov, 1, -1, 0) == -1); + TEST_COMPARE (errno, EBADF); + + /* Same tests as before but with flags being different than 0. Since + there is no emulation for any flag value, fallback code returns + ENOTSUP. This is different running on a kernel with preadv2/pwritev2 + support, where EBADF is returned). */ + TEST_VERIFY (preadv2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EBADF || errno == ENOTSUP); + TEST_VERIFY (pwritev2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EBADF || errno == ENOTSUP); +} + +static void +do_test_with_invalid_iov (void) +{ + { + char buf[256]; + struct iovec iov; + + iov.iov_base = buf; + iov.iov_len = (size_t)SSIZE_MAX + 1; + + TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, 0) == -1); + TEST_COMPARE (errno, EINVAL); + TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, 0) == -1); + TEST_COMPARE (errno, EINVAL); + + /* Same as for invalid file descriptor tests, emulation fallback + first checks for flag value and return ENOTSUP. */ + TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); + TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); + } + + { + /* An invalid iovec buffer should trigger an invalid memory access + or an error (Linux for instance returns EFAULT). */ + struct iovec iov[IOV_MAX+1] = { 0 }; + + TEST_VERIFY (preadv2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); + TEST_VERIFY (pwritev2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); + TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); + } +} + +static void +do_test_with_invalid_flags (void) +{ /* Set the next bit from the mask of all supported flags. */ int invalid_flag = RWF_SUPPORTED != 0 ? __builtin_clz (RWF_SUPPORTED) : 2; invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag); diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c index be22802dbe..cb58cbe41e 100644 --- a/misc/tst-preadvwritev2.c +++ b/misc/tst-preadvwritev2.c @@ -30,6 +30,8 @@ do_test (void) { do_test_with_invalid_flags (); do_test_without_offset (); + do_test_with_invalid_fd (); + do_test_with_invalid_iov (); return do_test_with_offset (0); } diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c index 8d3cc32b28..6a9de54c78 100644 --- a/misc/tst-preadvwritev64v2.c +++ b/misc/tst-preadvwritev64v2.c @@ -32,6 +32,8 @@ do_test (void) { do_test_with_invalid_flags (); do_test_without_offset (); + do_test_with_invalid_fd (); + do_test_with_invalid_iov (); return do_test_with_offset (0); } diff --git a/sysdeps/unix/sysv/linux/preadv2.c b/sysdeps/unix/sysv/linux/preadv2.c index c8bf0764ef..bb08cbc5fd 100644 --- a/sysdeps/unix/sysv/linux/preadv2.c +++ b/sysdeps/unix/sysv/linux/preadv2.c @@ -32,7 +32,7 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset, # ifdef __NR_preadv2 ssize_t result = SYSCALL_CANCEL (preadv2, fd, vector, count, LO_HI_LONG (offset), flags); - if (result >= 0) + if (result >= 0 || errno != ENOSYS) return result; # endif /* Trying to emulate the preadv2 syscall flags is troublesome: diff --git a/sysdeps/unix/sysv/linux/preadv64v2.c b/sysdeps/unix/sysv/linux/preadv64v2.c index d7400a0252..b72a047347 100644 --- a/sysdeps/unix/sysv/linux/preadv64v2.c +++ b/sysdeps/unix/sysv/linux/preadv64v2.c @@ -30,7 +30,7 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset, #ifdef __NR_preadv64v2 ssize_t result = SYSCALL_CANCEL (preadv64v2, fd, vector, count, LO_HI_LONG (offset), flags); - if (result >= 0) + if (result >= 0 || errno != ENOSYS) return result; #endif /* Trying to emulate the preadv2 syscall flags is troublesome: diff --git a/sysdeps/unix/sysv/linux/pwritev2.c b/sysdeps/unix/sysv/linux/pwritev2.c index 29c2264c8f..26333ebd43 100644 --- a/sysdeps/unix/sysv/linux/pwritev2.c +++ b/sysdeps/unix/sysv/linux/pwritev2.c @@ -28,7 +28,7 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset, # ifdef __NR_pwritev2 ssize_t result = SYSCALL_CANCEL (pwritev2, fd, vector, count, LO_HI_LONG (offset), flags); - if (result >= 0) + if (result >= 0 || errno != ENOSYS) return result; # endif /* Trying to emulate the pwritev2 syscall flags is troublesome: diff --git a/sysdeps/unix/sysv/linux/pwritev64v2.c b/sysdeps/unix/sysv/linux/pwritev64v2.c index 42da321149..17ea905aa6 100644 --- a/sysdeps/unix/sysv/linux/pwritev64v2.c +++ b/sysdeps/unix/sysv/linux/pwritev64v2.c @@ -30,7 +30,7 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset, #ifdef __NR_pwritev64v2 ssize_t result = SYSCALL_CANCEL (pwritev64v2, fd, vector, count, LO_HI_LONG (offset), flags); - if (result >= 0) + if (result >= 0 || errno != ENOSYS) return result; #endif /* Trying to emulate the pwritev2 syscall flags is troublesome: