From a347ce10482c1a29caee04b500f0ea2bfee0cf7c Mon Sep 17 00:00:00 2001 From: Aaron Nyholm Date: Tue, 7 Oct 2025 13:22:06 +1100 Subject: [PATCH] cpukit/close.c: Fix reference counting under concurrent access. Fixes issue with IOP being freed during close call. --- cpukit/libcsupport/src/close.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/cpukit/libcsupport/src/close.c b/cpukit/libcsupport/src/close.c index fcb51b9fc9..968f1471ce 100644 --- a/cpukit/libcsupport/src/close.c +++ b/cpukit/libcsupport/src/close.c @@ -52,7 +52,7 @@ int close( rtems_set_errno_and_return_minus_one( EBADF ); } - iop = rtems_libio_iop( fd ); + LIBIO_GET_IOP( fd, iop ); flags = rtems_libio_iop_flags( iop ); while ( true ) { @@ -60,15 +60,10 @@ int close( bool success; if ( ( flags & LIBIO_FLAGS_OPEN ) == 0 ) { + rtems_libio_iop_drop( iop ); rtems_set_errno_and_return_minus_one( EBADF ); } - /* The expected flags depends on close when busy flag. If set - * there can be references held when calling the close handler */ - if ( ( flags & LIBIO_FLAGS_CLOSE_BUSY ) == 0 ) { - flags &= LIBIO_FLAGS_FLAGS_MASK; - } - desired = flags & ~LIBIO_FLAGS_OPEN; success = _Atomic_Compare_exchange_uint( &iop->flags, @@ -82,14 +77,15 @@ int close( break; } - if ( ( flags & LIBIO_FLAGS_REFERENCE_MASK ) != 0 ) { + if ( ( flags & LIBIO_FLAGS_REFERENCE_MASK ) != LIBIO_FLAGS_REFERENCE_INC ) { + rtems_libio_iop_drop( iop ); rtems_set_errno_and_return_minus_one( EBUSY ); } } rc = (*iop->pathinfo.handlers->close_h)( iop ); - rtems_libio_free( iop ); + rtems_libio_iop_drop( iop ); return rc; }