Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 18 May 2020 21:05:38 +0200
From:      Michael Tuexen <tuexen@freebsd.org>
To:        cem@freebsd.org
Cc:        src-committers <src-committers@freebsd.org>, svn-src-all <svn-src-all@freebsd.org>, svn-src-head <svn-src-head@freebsd.org>
Subject:   Re: svn commit: r361209 - head/sys/netinet
Message-ID:  <064C2DCD-6279-4442-A900-0ECCD50CC4FA@freebsd.org>
In-Reply-To: <CAG6CVpU3QpCr9WVsuc1eRJrEV3XuQEWGHRCZ9FHMmRmB2N67Mg@mail.gmail.com>
References:  <202005181007.04IA713t089936@repo.freebsd.org> <CAG6CVpWA1gKLzacDeAFOGTKJcNrg608k5yu8CJg48_WFS0omnA@mail.gmail.com> <E8554788-B6CD-44A9-8ABF-7F3CD129F87F@freebsd.org> <CAG6CVpU3QpCr9WVsuc1eRJrEV3XuQEWGHRCZ9FHMmRmB2N67Mg@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
> On 18. May 2020, at 20:23, Conrad Meyer <cem@freebsd.org> wrote:
>=20
> On Mon, May 18, 2020 at 10:35 AM Michael Tuexen <tuexen@freebsd.org> =
wrote:
>>=20
>>> On 18. May 2020, at 17:38, Conrad Meyer <cem@FreeBSD.org> wrote:
>>>=20
>>> These changes are a bit odd.  The only reason a standards-compliant
>>> snprintf() would fail to nul-terminate a buffer is if the provided
>>> buffer had length zero.  Since this is not the case in any of these
>>> uses, I wonder why this revision was made?  Does a SCTP downstream
>>=20
>> when compiling the code in userland with gcc 10, it warns that
>> the output might be truncated. That is true and intended.
>> So checking that the call doesn't fail silences this warning and
>> ensures the code works in case snprintf() returns an error. I don't
>> see in the POSIX specification a statement limiting the case where
>> it could fail.
>>=20
>>> have a broken snprintf implementation, and if so, wouldn't it make
>>> more sense to create a standards-compliant portability shim for that
>>> platform instead of this more invasive change?
>>=20
>> If you want, I can revert the change and use the code only on =
non-FreeBSD
>> platforms.
>=20
> Hi Michael,
>=20
> If truncation is intended, the GCC warning is spurious.  Given how
> often snprintf is used in this way, I wonder if it would make sense to
> just disable it across the entire tree.  Regardless, IMO it makes
The issue wasn't reported against the kernel code, but running the code
in userland. I don't really control the flags people are using.
> sense to disable the warning, rather than make these changes to check
> for errors that can't happen.  It does not even "fix" the thing GCC is
OK. I'll revert this change and replace it upstream by something like

#if defined(__FreeBSD_)
	snprintf(msg, sizeof(msg), "Never sent serial number %8.8x", =
serial_num)
#else
	if (snprintf(msg, sizeof(msg), "Never sent serial number %8.8x", =
serial_num) < 0) {
		msg[0] =3D '\0';
	}
#endif

I don't know if other platforms guarantee that snprintf() can't fail.
If it fails, the stack would send out un-initialized stack memory on
the network.
> warning about, since we aren't testing for truncation at all; it's
> just a warning defeat mechanism.  -Wno- is a better warning-defeat
> mechanism.
>=20
> Re: documentation of snprintf nul-termination, I would look at this
> part of the FreeBSD manual page:
>=20
>     The snprintf() and vsnprintf() functions will write at most size-1 =
of the
>     characters printed into the output string (the size'th character =
then
>     gets the terminating =E2=80=98\0=E2=80=99); if the return value is =
greater than or equal
>     to the size argument, the string was too short and some of the =
printed
>     characters were discarded.  The output is always null-terminated, =
unless
>     size is 0.
>=20
> Note the last sentence especially.  As far as error conditions, those
> are canonically documented in the ERRORS section of the manual page
> rather than RETURN VALUES.  For whatever reason, mdoc(7) standard puts
> EXAMPLES between the two sections, and additionally snprintf.3 has a
> non-standard COMPATIBILITY section between the two, so they are not
> directly adjacent.  Here's that section, though:
>=20
> ERRORS
>     In addition to the errors documented for the write(2) system call, =
the
>     printf() family of functions may fail if:
>=20
>     [EILSEQ]           An invalid wide character code was encountered.
>=20
>     [ENOMEM]           Insufficient storage space is available.
>=20
>     [EOVERFLOW]        The size argument exceeds INT_MAX + 1, or the =
return
>                        value would be too large to be represented by =
an int.
>=20
> The section is unfortunately generalized and non-specific; snprintf
> probably cannot fail with ENOMEM, for example, nor write(2) errors.
> But EOVERFLOW is well-documented.
>=20
> Re: POSIX definition, POSIX is not the canonical definition of
> snprintf; the C standard is.  C (2018) reads:
>=20
>> If n is zero, nothing shall be written and s may be a null pointer. =
Otherwise, output bytes beyond the n-1st shall be discarded instead of =
being written to the array, and a null byte is written at the end of the =
bytes actually written into the array.
>=20
> Emphasis on the last clause.  (POSIX uses the exact same language.)
> As far as conditions where snprintf may fail, POSIX only defines a
> single case (covered in snprintf.3 above):
>=20
>> The snprintf() function shall fail if: [EOVERFLOW], The value of n is =
greater than INT_MAX.
>=20
> That is not the case in any of these invocations.
Just to be clear: My problem is NOT that the output is not zero =
terminated.
I use snprintf() in a way that it is, if it does not fail.

I was just adding protection code for the case it fails and leaves the
buffer uninitialized. since I don't want so sent out uninitialized stack =
memory.

I learnt that on FreeBSD this is not a problem and I'll remove that =
protection
code for this platform.

Best regards
Michael
>=20
> Probably snprintf(9) should be specifically documented; printf(9) does
> not cover it yet.  This is a documentation gap.  Additionally, the
> COMPATIBILITY section of snprintf.3 should probably be moved to
> STANDARDS (to help move ERRORS and RETURN VALUES closer together).
> Finally, it might be nice to have kernel snprintf(9) _Static_assert
> that the provided length is shorter than INT_MAX (when it is a
> compiler constant, and detect non-constant cases at runtime).
> Currently, snprintf(9) fails to detect buffers that would produce a
> result which overflows.
>=20
> Best regards,
> Conrad




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?064C2DCD-6279-4442-A900-0ECCD50CC4FA>