Bernhard Übelacker dixit:

> On Thu, 4 Apr 2024 21:00:59 +0000 (UTC) Thorsten Glaser <t...@mirbsd.de> 
> wrote:
>> Sometimes, it does not crash with a smashed stack but instead:
>>
>> Setting up sasl2-bin (2.1.28+dfsg1-6+b1) ...
>> BDB0002 __fop_file_setup:  Retry limit (100) exceeded
>> saslpasswd2: generic failure
>
> This looks to be a result of the pre-existing /etc/__db.sasldb2.
> If this file gets removed the stack smashing occurs again.

Right, I got there as well but not any further.

> By some experimenting I could convince gdb to load the debug symbols.

Massive detective work, thanks!

> And the stack seems to point into function __os_unique_id from libdb-5.3.so.
>
> Unfortunately I am not sure where the canary gets overwritten.

I had an immediate hunch as I saw this:

> 38              __os_gettime(env, &v, 1);

And:

> (gdb) ptype /o v
> type = struct {
> /*      0      |       8 */    time_t tv_sec;
> /*      8      |       4 */    long tv_nsec;
>
>                               /* total size (bytes):   12 */
>                             }

This is, in the source:

typedef struct {
        time_t  tv_sec;                         /* seconds */
#ifdef HAVE_MIXED_SIZE_ADDRESSING
        int32_t tv_nsec;
#else
        long    tv_nsec;                        /* nanoseconds */
#endif
} db_timespec;

Compare the newer system header:

struct timespec
{
#ifdef __USE_TIME_BITS64
  __time64_t tv_sec;            /* Seconds.  */
#else
  __time_t tv_sec;              /* Seconds.  */
#endif
#if __WORDSIZE == 64 \
  || (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64) \
  || (__TIMESIZE == 32 && !defined __USE_TIME_BITS64)
  __syscall_slong_t tv_nsec;    /* Nanoseconds.  */
#else
# if __BYTE_ORDER == __BIG_ENDIAN
  int: 32;           /* Padding.  */
  long int tv_nsec;  /* Nanoseconds.  */
# else
  long int tv_nsec;  /* Nanoseconds.  */
  int: 32;           /* Padding.  */
# endif
#endif
};

This is actually longer and (IMHO) really stupid. But Linux has:

struct __kernel_timespec {
        __kernel_time64_t       tv_sec;                 /* seconds */
        long long               tv_nsec;                /* nanoseconds */
};

So this is actually expected. *checks POSIX* which says:

| The <time.h> header shall declare the timespec structure, which shall
| include at least the following members:
|
| time_t tv_sec         Whole seconds.
| long tv_nsec          Nanoseconds [0, 999 999 999].

So both the kernel definition (tv_nsec must be long, not long long,
which is incompatible on ILP32 big endian platforms) and the one by
db5.3 (struct timespec may include extra members and be in any order)
actually violate POSIX… *sigh*

And yes, it does cast to struct timespec and passes it
to clock_gettime().

But it does give us a possible fix, which I’ll be testing.

bye,
//mirabilos
-- 
22:20⎜<asarch> The crazy that persists in his craziness becomes a master
22:21⎜<asarch> And the distance between the craziness and geniality is
only measured by the success 18:35⎜<asarch> "Psychotics are consistently
inconsistent. The essence of sanity is to be inconsistently inconsistent

Reply via email to