Bug 1299004
| Summary: | Unhandled EINTR during connection establishment leads to EACCES failure | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Red Hat Enterprise Linux 6 | Reporter: | Olga Kornieskaia <kolga> | ||||
| Component: | nfs-utils | Assignee: | Steve Dickson <steved> | ||||
| Status: | CLOSED ERRATA | QA Contact: | Yongcheng Yang <yoyang> | ||||
| Severity: | medium | Docs Contact: | |||||
| Priority: | unspecified | ||||||
| Version: | 6.7 | CC: | eguan, fs-qe, yoyang | ||||
| Target Milestone: | rc | ||||||
| Target Release: | --- | ||||||
| Hardware: | x86_64 | ||||||
| OS: | Linux | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | nfs-utils-1.2.3-69.el6 | Doc Type: | Bug Fix | ||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | Environment: | ||||||
| Last Closed: | 2016-05-11 00:04:51 UTC | Type: | Bug | ||||
| Regression: | --- | Mount Type: | --- | ||||
| Documentation: | --- | CRM: | |||||
| Verified Versions: | Category: | --- | |||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||
| Embargoed: | |||||||
| Attachments: |
|
||||||
The needed upstream patch
Author: Olga Kornievskaia <kolga>
Date: Sat Jan 16 12:25:46 2016 -0500
nfs_connect_nb: handle EINTR during connection establishment
Have checked this patch was merged into nfs-utils-1.2.3-69.el6 Move to VERIFIED and set SanityOnly according to Comment 5 Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://rhn.redhat.com/errata/RHBA-2016-0868.html |
Created attachment 1115190 [details] testing scripts Description of problem: When gssd tries to establish an rpc client with an NFS server, it can receives EINTR during connection establishment which the current code does not handle. It results in the nfs operation failing with "permission denied". Version-Release number of selected component (if applicable): Problem exists in upstream nfs-utils. Asking to be fixed in RHEL6.x How reproducible: Create 9mounts on the client with each security flavor for each nfs versions:nfs3krb5, nfs3krb5i, nfs3krb5p, same for nfs4 and nfs4.1. On each mount as user create a directory to write a file, then unmount and then repeat from mount in a loop. Attached is a tar of my script(s) for reproducing the problem (I'm not a script person so it's just functional) I run “allnfskrb2.sh” which starts on the background each of the 9 other files. To kill it I did “killall *hammer*”. then to unmount the 9mounts I run nfsumount.sh. Scripts depend that on the fileserver there are several directories created (i used to start hammer there and didn’t change it after i change to only create a single file): /t/hammer/nfs3krb5 … /nfs3krb5i … /nfs3krb5p … /nfs4krb5 … /nfs4krb5i …. /nfs4krb5p …. /nfs41krb5 … /nfs41krb5i … /nfs41krb5p Steps to Reproduce: 1. 2. 3. Actual results: Operation fails with "permission denied". Expected results: No failure should happen. Additional info: This problem exists in the upstream nfs-utils. Thus I submitted an upstream nfs-utils patch for review. From d346c9516bedfda11bb47ab541e33a3d10f339bf Mon Sep 17 00:00:00 2001 From: Olga Kornievskaia <kolga> Date: Thu, 14 Jan 2016 09:55:38 -0500 Subject: [PATCH 1/1] [nfs-utils] handle EINTR during connection establishment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit both connect() and select() can receive EINTR signals that we need to recover from. In Unix Network Programming, volume 1, section 5.9, W. Richard Stevens states: What we are doing […] is restarting the interrupted system call ourself. This is fine for accept, along with the functions such as read, write, select and open. But there is one function that we cannot restart ourself: connect. If this function returns EINTR, we cannot call it again, as doing so will return an immediate error. When connect is interrupted by a caught signal and is not automatically restarted, we must call select to wait for the connection to complete, Thus for connect() treat both EINPROGRESS and EINTR the same -- call select(). For select(), it should be re-tried again upon receiving EINTR. Signed-off-by: Olga Kornievskaia <kolga> --- support/nfs/rpc_socket.c | 16 +++++++++++----- 1 files changed, 11 insertions(+), 5 deletions(-) diff --git a/support/nfs/rpc_socket.c b/support/nfs/rpc_socket.c index c14efe8..edd43cc 100644 --- a/support/nfs/rpc_socket.c +++ b/support/nfs/rpc_socket.c @@ -215,7 +215,7 @@ static int nfs_connect_nb(const int fd, const struct sockaddr *sap, * use it later. */ ret = connect(fd, sap, salen); - if (ret < 0 && errno != EINPROGRESS) { + if (ret < 0 && errno != EINPROGRESS && errno != EINTR) { ret = -1; goto done; } @@ -227,10 +227,16 @@ static int nfs_connect_nb(const int fd, const struct sockaddr *sap, FD_ZERO(&rset); FD_SET(fd, &rset); - ret = select(fd + 1, NULL, &rset, NULL, timeout); - if (ret <= 0) { - if (ret == 0) - errno = ETIMEDOUT; + while ((ret = select(fd + 1, NULL, &rset, NULL, timeout)) < 0) { + if (errno != EINTR) { + ret = -1; + goto done; + } else { + continue; + } + } + if (ret == 0) { + errno = ETIMEDOUT; ret = -1; goto done; } -- 1.7.1