If unlinking of the file fails, rte_fbarray_destroy() keeps the fbarray
mapped and attempts to downgrade the exclusive file lock back to a
shared lock. The result of this downgrade is currently ignored.

Check the return value and log a failure. Save errno immediately after
the failed unlink(), because subsequent calls may change it. Before
returning, set rte_errno to the saved value so the caller receives the
primary reason why the destroy operation failed.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes: 5b61c62cfd76 ("fbarray: add internal tailq for mapped areas")
Cc: [email protected]

Signed-off-by: Daniil Iskhakov <[email protected]>
---
v2:
- preserve the unlink() error across the lock downgrade attempt
- check the lock operation result explicitly
- update the Fixes tag to the commit that introduced the unchecked
    downgrade
---
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
 lib/eal/common/eal_common_fbarray.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/lib/eal/common/eal_common_fbarray.c 
b/lib/eal/common/eal_common_fbarray.c
index 8bdcefb717..5b3532893c 100644
--- a/lib/eal/common/eal_common_fbarray.c
+++ b/lib/eal/common/eal_common_fbarray.c
@@ -1015,15 +1015,19 @@ rte_fbarray_destroy(struct rte_fbarray *arr)
                /* we're OK to destroy the file */
                eal_get_fbarray_path(path, sizeof(path), arr->name);
                if (unlink(path)) {
+                       const int unlink_errno = errno;
+
                        EAL_LOG(DEBUG, "Cannot unlink fbarray: %s",
-                               strerror(errno));
-                       rte_errno = errno;
+                               strerror(unlink_errno));
                        /*
                         * we're still holding an exclusive lock, so drop it to
                         * shared.
                         */
-                       eal_file_lock(fd, EAL_FLOCK_SHARED, EAL_FLOCK_RETURN);
+                       if (eal_file_lock(fd, EAL_FLOCK_SHARED, 
EAL_FLOCK_RETURN) != 0)
+                               EAL_LOG(DEBUG, "Cannot restore fbarray shared 
lock: %s",
+                                       rte_strerror(rte_errno));
 
+                       rte_errno = unlink_errno;
                        ret = -1;
                        goto out;
                }
-- 
2.53.0

Reply via email to