[PATCH rtems-libbsd] ipsec-tools: Fix copying fd_set prior to select

Christian MAUDERER christian.mauderer at embedded-brains.de
Wed May 24 13:42:12 UTC 2023


On 2023-05-24 02:33, Chris Johns wrote:
> On 24/5/2023 9:13 am, Chris Johns wrote:
>> On 23/5/2023 5:30 pm, Christian MAUDERER wrote:
>>> Hello Chris,
>>>
>>> On 2023-05-23 08:53, Chris Johns wrote:
>>>> On 23/5/2023 4:25 pm, Christian MAUDERER wrote:
>>>>> Hello Chris,
>>>>>
>>>>> On 2023-05-23 03:36, Chris Johns wrote:
>>>>>> Hi,
>>>>>>
>>>>>> I have been resolving this by adding:
>>>>>>
>>>>>> #define preset_mask *preset_mask_prealloc
>>>>>> #define active_mask *active_mask_prealloc
>>>>>>
>>>>>> as the assignment logic works as is. It does not catch FD_ZERO which is a shame
>>>>>> but is helps avoid us adding a special case.
>>>>>
>>>>> Thanks for the suggestion. I used that solution already in the file during the
>>>>> initial port. But it doesn't work in this case (and maybe we should check other
>>>>> cases in libbsd too). It only copies the first element of the array of fd_sets.
>>>>>
>>>>> The variables / defines are (in the patched version - see [1]):
>>>>>
>>>>> static fd_set *allocated_preset_mask, *allocated_active_mask;
>>>>> static struct fd_monitor *allocated_fd_monitors;
>>>>> #define preset_mask (*allocated_preset_mask)
>>>>> #define active_mask (*allocated_active_mask)
>>>>> #define fd_monitors (allocated_fd_monitors)
>>>>>
>>>>> They are allocated as follows (see [2]):
>>>>>
>>>>>       allocated_preset_mask = calloc(sizeof(fd_set),
>>>>>           howmany(rtems_libio_number_iops, sizeof(fd_set) * 8));
>>>>>       allocated_active_mask = calloc(sizeof(fd_set),
>>>>>           howmany(rtems_libio_number_iops, sizeof(fd_set) * 8));
>>>>>       allocated_fd_monitors = calloc(
>>>>>           rtems_libio_number_iops, sizeof(struct fd_monitor));
>>>>>
>>>>> So basically it's a bunch of arrays of fd_sets. If I now use the following
>>>>> (unpatched) assignment:
>>>>>
>>>>>       active_mask = preset_mask;
>>>>>
>>>>> After the preprocessor the line will be
>>>>>
>>>>>       (*allocated_active_mask) = (*allocated_preset_mask);
>>>>>
>>>>> Which copies only the first element. That's why I had to add the memcpy. Did I
>>>>> miss some better solution?
>>>>
>>>> I am using this in ntpd which I checked yesterday:
>>>>
>>>> #ifdef __rtems__
>>>> #include <rtems/libio_.h>
>>>> static size_t rtems_ntpd_fds_size;
>>>> static int rtems_fd_set_alloc(fd_set **setp) {
>>>>           if (*setp == NULL) {
>>>>                   rtems_ntpd_fds_size = sizeof(fd_set) *
>>>> (howmany(rtems_libio_number_iops, sizeof(fd_set) * 8));
>>>>                   *setp = malloc(rtems_ntpd_fds_size);
>>>>                   if (*setp == NULL) {
>>>>                           errno = ENOMEM;
>>>>                           return -1;
>>>>                   }
>>>>                   memset(*setp, 0, rtems_ntpd_fds_size);
>>>>           }
>>>>           return 0;
>>>> }
>>>> #define activefds (*activefds_prealloc)
>>>> static fd_set *activefds_prealloc;
>>>> #define rtems_activefds_alloc() rtems_fd_set_alloc(&activefds_prealloc)
>>>> #else /* __rtems__ */
>>>> static fd_set activefds;
>>>> #endif /* __rtems__ */
>>>>
>>>> and:
>>>>
>>>> #if __rtems__
>>>>           #define rdfdes (*rdfdes_prealloc)
>>>>           static fd_set *rdfdes_prealloc;
>>>> #else /* __rtems__ */
>>>>           fd_set rdfdes;
>>>> #endif /* __rtems__ */
>>>>           int nfound;
>>>>
>>>> #if __rtems__
>>>>           if (rtems_fd_set_alloc(&rdfdes_prealloc) < 0) {
>>>>                   return;
>>>>           }
>>>>           memset(rdfdes_prealloc, 0, rtems_ntpd_fds_size);
>>>> #else /* __rtems__ */
>>>>           FD_ZERO(&set);
>>>> #endif /* __rtems__ */
>>>>
>>>> with:
>>>>
>>>>           ++handler_calls;
>>>>           rdfdes = activefds;
>>>
>>> But isn't that line resolving to
>>>
>>>    (*rdfdes_prealloc) = (*activefds_prealloc);
>>>
>>> That would also copy only the first element.
>>>
>>>>
>>>> Stepping:
>>>>
>>>> Thread 9 hit Breakpoint 1, _ntp_io_handler () at
>>>> ../../bsd/freebsd/contrib/ntp/ntpd/ntp_io.c:3727
>>>> 3727            rdfdes = activefds;
>>>> (gdb) x /8bx activefds_prealloc
>>>> 0x1083e650:     0x20    0x44    0x05    0x20    0x00    0x40    0x00    0x00
>>>> (gdb) x /8bx rdfdes_prealloc
>>>> 0x108353a0:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
>>>> (gdb) n
>>>> 3736                    t1.tv_usec = 0;
>>>> (gdb) x /8bx rdfdes_prealloc
>>>> 0x108353a0:     0x20    0x44    0x05    0x20    0x00    0x40    0x00    0x00
>>>>
>>>> Looks ok to me.
>>>
>>> fd_set is 64 bit wide. So a copy of the first 64 bit works. Does it still work
>>> if you have 256 files in the system?
>>
>> Good question. I have not checked but I will.
>>
>> FYI EPICS has set its limit to 64 because of this issue with select. I suspect
>> they do not want to hack their select calls like this and I understand them
>> taking that position.
> 
> Yes, I see the issue. The equate only works if the file ops count is the same as
> the newlib defined fd_set.
> 
> Chris

Thanks for the confirmation. Do you see a better solution than the 
memcpy in my patch?

Best regards

Christian
-- 
--------------------------------------------
embedded brains GmbH & Co. KG
Herr Christian MAUDERER
Dornierstr. 4
82178 Puchheim
Germany
email:  christian.mauderer at embedded-brains.de
phone:  +49-89-18 94 741 - 18
mobile: +49-176-152 206 08

Registergericht: Amtsgericht München
Registernummer: HRA 117265
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/


More information about the devel mailing list