Hi KR,

the patches have been uploaded

Best regards
Alin


On Thu, Jun 19, 2025 at 1:14 AM <kr....@kerogit.eu> wrote:

> Hello,
>
> finally got to it, 4th revision of the patches is in branch named
> uart_fixes_rfc4 and also attached. This revision incorporates
> suggestions from GitHub review.
>
> 1. The order of patches in the series is reversed (not counting the typo
> fix patch.) The less intrusive one is now placed before the other. This
> way, the smaller fix is not affected by changes that follow, namely by
> using the new data type.
>
> 2. Instead of ifdefs in various places, the patch introduces type
> sbuf_size_t in include/nuttx/serial/serial.h . Buffer size, head and
> tail variables are changed to this type.
>
> 3. ARCH_LD_16BIT_NOT_ATOMIC configuration option is renamed to
> ARCH_LDST_16BIT_NOT_ATOMIC to denote that store operations are not
> atomic as well for the architecture.
>
> 4. Default serial buffer size is changed from 256 to 252. Additionally,
> help of configuration options for USARTn_(RX|TX)BUFSIZE now mentions
> that if the architecture is unable to load/store 16-bit values
> atomically, the size of buffer is stored in uint8_t.
>
> 5. New configuration option ARCH_HAVE_SERIAL_8BIT_BUFSIZE is added. This
> configuration option triggers change of sbuf_size_t from default int16_t
> to architecture-specific uint8_t. It is, however, not selected from AVR
> serial driver Kconfig option as the review suggests. Instead, it is
> selected by ARCH_LDST_16BIT_NOT_ATOMIC. The reasoning for doing it this
> way is that AVR is (likely) not the only architecture suffering from
> this race condition - any 8-bit architecture is, unless it does 16-bit
> loads/stores atomically. As far as I was able to find, this applies to
> Z80 as well.
>
> Also, serial buffer is likely not the only area that introduces such a
> race. If more such cases are found, selecting all configuration options
> that enable measures that prevent these race conditions from all
> affected architectures would lead to M x N configuration options and all
> architectures would need to track new options being added. Selecting all
> of them from single point (ie. from ARCH_LDST_16BIT_NOT_ATOMIC) makes
> the configuration easier, the architecture only needs to declare what is
> is (in)capable of and all related options will be enabled automatically.
>
> As for the comment from jlaitine - I also find it strange that the
> original index is a signed value and I found no reason for it being that
> way. And yes, it is left untouched to prevent any changes in other
> architectures.
>
> If there is still something left to improve, let me know. Thanks.
>
> On 2025-06-11 13:42, alin.jerpe...@sony.com wrote:
> > Hi KR,
> >
> > I added your comments
> >
> > Best regards
> > Alin
> > ________________________________
> > Från: kr....@kerogit.eu <kr....@kerogit.eu>
> > Skickat: den 11 juni 2025 07:54
> > Till: dev@nuttx.apache.org <dev@nuttx.apache.org>
> > Ämne: Re: Sv: Sv: RFC: fix race conditions in drivers/serial/serial.c
> >
> > Hello, thanks. Here is a response to xiaoxiang781216's review: > could
> > we extract a common typedef to avoid #ifdef/#else/#endif spread > the
> > code base? Can do - sbuf_size_t seems unused throughout the whole tree
> > so I'll add that to serial. h.
> >
> >
> > Hello,
> >
> > thanks. Here is a response to xiaoxiang781216's review:
> >
> >> could we extract a common typedef to avoid #ifdef/#else/#endif spread
> >> the code base?
> >
> > Can do - sbuf_size_t seems unused throughout the whole tree so I'll add
> > that to serial.h.
> >
> >> can we change to ARCH_HAVE_8BIT_BUFSIZE and put into serial/Kconfig?
> >
> > I am not sure if that means to a) change the name from
> > ARCH_LD_16BIT_NOT_ATOMIC to ARCH_HAVE_8BIT_BUFSIZE or b) add
> > ARCH_HAVE_8BIT_BUFSIZE and have it selected by
> > ARCH_LD_16BIT_NOT_ATOMIC?
> > Neither seems fully correct though.
> >
> > The first variant reduces the problem to buffers only but that is too
> > narrow. Essentially, any other value that is simultaneously written in
> > interrupt code and read in non-interrupt code needs the be treated in
> > the same manner as buffer head/tail here. The current name reflects
> > that. Also, adding ARCH_LD_32BIT_NOT_ATOMIC may be needed as well
> > (possibly not only for AVR but for 16 bit microcontrollers too - if I
> > understand it correctly, that applies to Freescale M9S12.)
> >
> > The second variant implies that all of the arch has 8 bit buffer size
> > for all buffers everywhere which is not true and may not be desirable.
> >
> > How about adding ARCH_HAVE_8BIT_SERIAL_BUFSIZE to serial/Kconfig and
> > have it selected by ARCH_LD_16BIT_NOT_ATOMIC?
> >
> >> could we directly change the default value to 255
> >
> > Can be done but that would affect other architectures as well which is
> > something I wanted to avoid. Also, using 255 feels dangerous when the
> > underlying type is uint8_t. Might lead to bugs where expression like (x
> > + 1 > size) never evaluates to true. Not that I see any such code in
> > current sources, but if the default value should change for all
> > architectures, I would rather use 252 out of abundance of caution.
> >
> >> move to help of ARCH_LD_16BIT_NOT_ATOMIC
> >
> > I think it would be better to put something more generic in there.
> > Additionally, I'll copy the comment about the buffer size to help for
> > USARTn_RX/TXBUFSIZE.
> >
> >> why not merge to previous patch
> >
> > Because it fixes different bug (on all architectures.) I will reorder
> > the patches to make that more obvious and to have the less intrusive
> > one
> > be the first in case it turns out that the second one needs to be
> > reverted.
> >
> > On 2025-06-09 15:10, alin.jerpe...@sony.com wrote:
> >> Hi KR,
> >>
> >> the patches have been updated
> >>
> https://urldefense.com/v3/__https://github.com/apache/nuttx/pull/16466__;!!O7_YSHcmd9jp3hj_4dEAcyQ!1y3RB5EUXoBosi8vAEcjSyRXMCiRnRtrGSfJEO84MiLP3anDf6k6445X2RlUvrB55u8lzti4-TaTVNIzppE$
> >>
> >> Best regads
> >> Alin
> >>
> >> ________________________________
> >> Från: kr....@kerogit.eu <kr....@kerogit.eu>
> >> Skickat: den 9 juni 2025 12:12
> >> Till: dev@nuttx.apache.org <dev@nuttx.apache.org>
> >> Ämne: Re: Sv: RFC: fix race conditions in drivers/serial/serial.c
> >>
> >> Hello, reworked version of the series is in branch uart_fixes_rfc3 and
> >> also attached. This version incorporates xiaoxiang781216's suggestion
> >> on GitHub to simply make the buffer size stored in uint8_t variable if
> >> the architecture cannot handle
> >>
> >>
> >> Hello,
> >>
> >> reworked version of the series is in branch uart_fixes_rfc3 and also
> >> attached. This version incorporates xiaoxiang781216's suggestion on
> >> GitHub to simply make the buffer size stored in uint8_t variable if
> >> the
> >> architecture cannot handle 16-bit loads atomically.
> >>
> >> Fix for TOCTOU in watermark calculation was split into a separate
> >> patch
> >> since it addresses a different issue.
> >>
> >> Testing was done in the same way as the original version of the
> >> series.
> >>
> >> On 2025-06-05 07:44, kr....@kerogit.eu wrote:
> >>> Hello,
> >>>
> >>> based on the feedback in GitHub review, I will redo the patch
> >>> differently and reduce the size of the circular buffers so the
> >>> variables fit into uint8_t.
> >>>
> >>> To respond to xiaoxiang781216's comment about using atomic_xxx API
> >>> instead the critical section - I was considering that as well but in
> >>> the end, I concluded that the critical section is highly unlikely to
> >>> be
> >>> compiled in on any architecture that supports SMP. It does set a bad
> >>> example though, that did not occur to me previously.
> >>>
> >>> The atomic_xxx API I decided not to use because when I tried it, it
> >>> produced buggy code. I will post a patch/question regarding that in a
> >>> separate thread.
> >>>
> >>> Nevertheless, if reads are made atomic, neither of the above is
> >>> needed.
> >>>
> >>> Thanks for the feedback, will try to do the rework in next few days.
> >>>
> >>> On 2025-06-02 18:58, kr....@kerogit.eu wrote:
> >>>> Hello,
> >>>>
> >>>> I noticed a review from Allan C. Assis about a spelling error.
> >>>> Updated
> >>>> patches are attached and also available in repository in
> >>>> uart_fixes_rfc2 branch. (Sorry about the extra work, I was even
> >>>> trying
> >>>> to check the word using web search... but I didn't spot that the
> >>>> search autocorrected it so my conclusion was that the spellchecker I
> >>>> also used is just tripping on the plural.)
> >>>>
> >>>> Best regards
> >>>>
> >>>> On 2025-06-02 09:39, alin.jerpe...@sony.com wrote:
> >>>>> Hi KR,
> >>>>>
> >>>>> thank for submitting the patches
> >>>>>
> >>>>> They have been uploaded to mainline and are under review
> >>>>>
> https://urldefense.com/v3/__https://github.com/apache/nuttx/pull/16466__;!!O7_YSHcmd9jp3hj_4dEAcyQ!yLV1nobwBFiEr5gCY_xNYvnCqhLJeSSyqnb6uJgKkEsQ6_1NJtMiI_zeeQRnjWuYSysKvDDj5FMrky7Yhq8$
> >>>>>
> >>>>>
> >>>>> Best regards
> >>>>> Alin
> >>>>> ________________________________
> >>>>> Från: kr....@kerogit.eu <kr....@kerogit.eu>
> >>>>> Skickat: den 1 juni 2025 22:42
> >>>>> Till: dev@nuttx.apache.org <dev@nuttx.apache.org>
> >>>>> Ämne: RFC: fix race conditions in drivers/serial/serial.c
> >>>>>
> >>>>> While going through the code in drivers/serial/serial. c, I noticed
> >>>>> this comment: The head and tail pointers are 16-bit values. The
> >>>>> only
> >>>>> time that the following could be unsafe is if the CPU made two
> >>>>> non-atomic 8-bit accesses to obtain the 16-bit
> >>>>>
> >>>>>
> >>>>> While going through the code in drivers/serial/serial.c, I noticed
> >>>>> this
> >>>>> comment:
> >>>>>
> >>>>> The head and tail pointers are 16-bit values.  The only time that
> >>>>> the following could be unsafe is if the CPU made two non-atomic
> >>>>> 8-bit accesses to obtain the 16-bit head index.
> >>>>>
> >>>>> This is what happens for (at least) AVR architecture. These are
> >>>>> 8bit
> >>>>> microcontrollers and as such, they will fetch the 16-bit value in
> >>>>> two
> >>>>> 8-bit load instructions; interrupt routine may execute between
> >>>>> those
> >>>>> and
> >>>>> change the value being read. This will result in corrupted read
> >>>>> (one
> >>>>> byte of the value will be from pre-interrupt state and the other
> >>>>> from
> >>>>> post-interrupt state.)
> >>>>>
> >>>>> This patch introduces CONFIG_ARCH_LD_16BIT_NOT_ATOMIC configuration
> >>>>> option, which is automatically selected for architectures known to
> >>>>> be
> >>>>> unable to load 16bit values in one instruction. (It is currently
> >>>>> only
> >>>>> set for AVR. I presume it might be also useful for Z80 but I do not
> >>>>> have
> >>>>> any experience with that architecture so I did no changes there.)
> >>>>> When
> >>>>> this configuration option is set, reads of recv.head and xmit.tail
> >>>>> are
> >>>>> enclosed with enter_critical_section and leave_critical_section
> >>>>> calls
> >>>>> to
> >>>>> prevent interrupt handlers from running, if needed. Not all reads
> >>>>> need
> >>>>> to be protected this way - some are already in existing critical
> >>>>> sections and some happen with the UART-specific interrupt disabled.
> >>>>>
> >>>>> If the configuration option is not set, the code simply loads the
> >>>>> value
> >>>>> into a local variable. Subsequent direct uses of the unprotected
> >>>>> volatile variable are replaced with the local variables for both
> >>>>> cases.
> >>>>>
> >>>>> There is also a related change that only applies when
> >>>>> CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is set. Aside from the
> >>>>> protection
> >>>>> selected by CONFIG_ARCH_LD_16BIT_NOT_ATOMIC, this patch also fixes
> >>>>> calculation of the nbuffered value. This calculation is not running
> >>>>> with
> >>>>> interrupts disabled and value of rxbuf->head can change between the
> >>>>> condition and actual computation. Even if the load itself is
> >>>>> atomic,
> >>>>> this leads to TOCTOU error.
> >>>>>
> >>>>> Impact: this change should not impact architectures that do not
> >>>>> benefit
> >>>>> from this change at all unless CONFIG_SERIAL_IFLOWCONTROL is set.
> >>>>> If
> >>>>> CONFIG_SERIAL_IFLOWCONTROL is set, the only change that remains in
> >>>>> effect is the fix of the TOCTOU error.
> >>>>>
> >>>>> Testing: Patch was tested with rv-virt:nsh - disassembly of
> >>>>> functions
> >>>>> from drivers/serial/serial.c was compared and did not change after
> >>>>> the
> >>>>> patch was applied - with one exception. The exception was an
> >>>>> address
> >>>>> of
> >>>>> a global variable, I assume it was caused by change of g_version
> >>>>> length
> >>>>> (which notes that the tree is dirty) and is therefore
> >>>>> inconsequential.
> >>>>> CONFIG_SERIAL_IFLOWCONTROL was not set in this test.
> >>>>>
> >>>>> Configuration with CONFIG_SERIAL_IFLOWCONTROL set was tested by
> >>>>> building
> >>>>> it for AVR DA/DB. Configuration with CONFIG_SERIAL_IFLOWCONTROL
> >>>>> unset
> >>>>> was tested by custom echo application running on AVR128DA28 for a
> >>>>> few
> >>>>> hours.
> >>>>>
> >>>>> I also ran CI test: 1044 passed, 10 skipped, 14 deselected, 3
> >>>>> warnings
> >>>>> in 2463.23s (0:41:03)
> >>>>>
> >>>>>
> >>>>> On a related note, it seems to me that there may be a bug in echo
> >>>>> handling in uart_readv. If dev->tc_lflag & ECHO is true, then
> >>>>> uart_putxmitchar is called. This function adds the received
> >>>>> character
> >>>>> to
> >>>>> transmit buffer and increments xmit.head value. However,
> >>>>> uart_putxmitchar is also called from uart_writev; this function
> >>>>> states
> >>>>> "Only one user can access dev->xmit.head at a time" and takes the
> >>>>> dev->xmit.lock. As far as I can see, uart_readv does not take the
> >>>>> lock
> >>>>> and may interfere with uart_writev. Evaluating and solving this
> >>>>> properly
> >>>>> is currently above my skillset though. (If this is even considered
> >>>>> serious enough to warrant a fix.)
> >>>>>
> >>>>>
> >>>>> The patch series also fixes a typo in drivers/serial/serial.c
> >>>>>
> >>>>>
> >>>>> Both patches are attached to this message and also available in a
> >>>>> git
> >>>>> repository nuttx.git at git.kerogit.eu accessible through HTTP/S.
> >>>>> (Trying to prevent bot traffic by not posting the URL in
> >>>>> machine-readable form.) The relevant branch is called
> >>>>> uart_fixes_rfc1.
> >>>>> If the patches are acceptable, I would like to ask someone with
> >>>>> GitHub
> >>>>> account to open a PR (I don't have a GH account.) Any comments or
> >>>>> suggestions are welcome.
>

Reply via email to