Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Harden NUT work with strings where dynamic formatting strings are used #2460

Draft
wants to merge 29 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2c1823a
common/common.c, include/common.h, tests/nutlogtest.c, NEWS.adoc: int…
jimklimov May 30, 2024
ebcb0eb
drivers/dstate.{c,h}: add vdstate_setinfo(), vdstate_addenum() and ve…
jimklimov May 31, 2024
eee0568
docs/developers.txt, docs/new-drivers.txt, docs/nut.dict: document ha…
jimklimov May 31, 2024
6f1e257
common/common.c, tests/nutlogtest.c: minimize_formatting_string(): co…
jimklimov May 31, 2024
a64e7b4
common/common.c, include/common.h, drivers/dstate.c, tests/nutlogtest…
jimklimov Jun 1, 2024
06711d9
common/common.c: vsnprintf_dynamic(): NULL "dst" or its "size" are a …
jimklimov Jun 1, 2024
8f3f609
drivers/nutdrv_qx_bestups.c: bestups_model(): fix bogus sprintf() for…
jimklimov Jun 1, 2024
5a3986e
Harden NUT work with strings: comment which use-cases we DID NOT swit…
jimklimov Jun 1, 2024
6946774
Harden NUT work with strings by switching to snprintf_dynamic() inste…
jimklimov Jun 1, 2024
84404b9
drivers/nutdrv_qx_bestups.c: bestups_batt_packs(): range-check and pr…
jimklimov Jun 1, 2024
56b9a72
drivers/nutdrv_qx_bestups.c: bestups_get_pins_shutdown_mode(): commen…
jimklimov Jun 1, 2024
c4cfa87
drivers/nutdrv_qx_blazer-common.c: blazer_process_command() for "test…
jimklimov Jun 1, 2024
3b7a01b
tools/nut-scanner/nutscan-serial.c: Harden NUT work with strings by s…
jimklimov Jun 1, 2024
d00e737
tools/nut-scanner/nutscan-serial.c: add /dev/cua* patterns for differ…
jimklimov Jun 1, 2024
c18ccdb
common/common.c: minimize_formatting_string(): warn in doc that this …
jimklimov Jun 2, 2024
900d64d
tests/nutlogtest.c, common/common.c: validate_formatting_string(): to…
jimklimov Jun 2, 2024
8ccaa27
m4/ax_c_pragmas.m4: detect support for plain "-Wformat" and for "-Wfo…
jimklimov Jun 2, 2024
41ce7c7
tests/nutlogtest.c: use support for plain "-Wformat" and for "-Wforma…
jimklimov Jun 2, 2024
a885244
Merge branch 'master' into issue-2450
jimklimov Jun 4, 2024
ca46f80
include/common.h, common/common.c, drivers/dstate.c, drivers/nutdrv_q…
jimklimov Jun 4, 2024
bca2635
Merge branch 'master' into issue-2450
jimklimov Jun 6, 2024
e52b8d7
Merge branch 'master' into issue-2450
jimklimov Jun 10, 2024
9a9b482
Merge branch 'master' into issue-2450
jimklimov Jun 15, 2024
4c18980
Merge branch 'master' into issue-2450
jimklimov Jun 24, 2024
05b0ea8
Merge branch 'master' into issue-2450
jimklimov Jul 14, 2024
2b04872
Merge branch 'master' into issue-2450
jimklimov Jul 15, 2024
d2a289a
Merge branch 'master' into issue-2450
jimklimov Jul 19, 2024
b2e3442
Merge branch 'master' into issue-2450
jimklimov Jul 21, 2024
d22b19e
Merge branch 'master' into issue-2450
jimklimov Jul 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ during a NUT build.
respective warnings issued by the new generations of analysis tools.
[#823, #2437, link:https://github.com/networkupstools/nut-website/issues/52[nut-website issue #52]]

- common code hardening: added sanity-checking for dynamically constructed or
selected formatting strings with variable-argument list methods (typically
used with log printing, `dstate` setting, etc.) [#2450]

- added `scripts/valgrind` with a helper script and suppression file to
ignore common third-party problems. [#2511]

Expand Down
54 changes: 15 additions & 39 deletions clients/upsclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,16 +555,6 @@ const char *upscli_strerror(UPSCONN_t *ups)
char sslbuf[UPSCLI_ERRBUF_LEN];
#endif

#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif

if (!ups) {
return upscli_errlist[UPSCLI_ERR_INVALIDARG].str;
}
Expand All @@ -583,23 +573,26 @@ const char *upscli_strerror(UPSCONN_t *ups)
return upscli_errlist[ups->upserror].str;

case 1: /* add message from system's strerror */
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
snprintf_dynamic(
ups->errbuf, UPSCLI_ERRBUF_LEN,
upscli_errlist[ups->upserror].str,
strerror(ups->syserrno));
"%s", strerror(ups->syserrno));
return ups->errbuf;

case 2: /* SSL error */
#ifdef WITH_OPENSSL
err = ERR_get_error();
if (err) {
ERR_error_string(err, sslbuf);
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
snprintf_dynamic(
ups->errbuf, UPSCLI_ERRBUF_LEN,
upscli_errlist[ups->upserror].str,
sslbuf);
"%s", sslbuf);
} else {
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
snprintf_dynamic(
ups->errbuf, UPSCLI_ERRBUF_LEN,
upscli_errlist[ups->upserror].str,
"peer disconnected");
"%s", "peer disconnected");
}
#elif defined(WITH_NSS) /* WITH_OPENSSL */
if (PR_GetErrorTextLength() < UPSCLI_ERRBUF_LEN) {
Expand All @@ -616,16 +609,13 @@ const char *upscli_strerror(UPSCONN_t *ups)
return ups->errbuf;

case 3: /* parsing (parseconf) error */
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
snprintf_dynamic(
ups->errbuf, UPSCLI_ERRBUF_LEN,
upscli_errlist[ups->upserror].str,
ups->pc_ctx.errmsg);
"%s", ups->pc_ctx.errmsg);
return ups->errbuf;
}

#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif

/* fallthrough */

snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN, "Unknown error flag %d",
Expand Down Expand Up @@ -1319,23 +1309,9 @@ static void build_cmd(char *buf, size_t bufsize, const char *cmdname,
format = " %s";
}

/* snprintfcat would tie us to common */

len = strlen(buf);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
snprintf(buf + len, bufsize - len, format,
pconf_encode(arg[i], enc, sizeof(enc)));
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
snprintfcat_dynamic(
buf, bufsize, format,
"%s", pconf_encode(arg[i], enc, sizeof(enc)));
}

len = strlen(buf);
Expand Down
24 changes: 10 additions & 14 deletions clients/upsimage.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,20 +275,10 @@ static void drawbar(
gdImageFilledRectangle(im, 25, bar_y, width - 25, scale_height,
bar_color);

/* stick the text version of the value at the bottom center */
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
snprintf(text, sizeof(text), format, value);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif
/* stick the text version of the value at the bottom center
* expected format is one of imgvar[] entries for "double value"
*/
snprintf_dynamic(text, sizeof(text), format, "%f", value);
gdImageString(im, gdFontMediumBold,
(width - (int)(strlen(text))*gdFontMediumBold->w)/2,
height - gdFontMediumBold->h,
Expand Down Expand Up @@ -321,6 +311,12 @@ static void noimage(const char *fmt, ...)
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
/* Note: Not converting to hardened NUT methods with dynamic
* format string checking, this one is used locally with
* fixed strings (and args) */
/* FIXME: Actually, almost only fixed strings, no formatting
* needed here: one use-case of having a format, and another
* with externally prepared snprintf(). */
vsnprintf(msg, sizeof(msg), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
Expand Down
17 changes: 4 additions & 13 deletions clients/upsmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,21 +378,12 @@ static void do_notify(const utype_t *ups, int ntype)
if (notifylist[i].type == ntype) {
upsdebugx(2, "%s: ntype 0x%04x (%s)", __func__, ntype,
notifylist[i].name);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
snprintf(msg, sizeof(msg),

snprintf_dynamic(msg, sizeof(msg),
notifylist[i].msg ? notifylist[i].msg : notifylist[i].stockmsg,
"%s",
ups ? ups->sys : "");
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
#endif

notify(msg, notifylist[i].flags, notifylist[i].name,
upsname);

Expand Down
4 changes: 4 additions & 0 deletions clients/upssched.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ static int send_to_one(conn_t *conn, const char *fmt, ...)
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
/* Note: Not converting to hardened NUT methods with dynamic
* format string checking, this one is used locally with
* fixed strings (and args) */
/* FIXME: Actually, only fixed strings, no formatting here. */
vsnprintf(buf, sizeof(buf), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
Expand Down
3 changes: 3 additions & 0 deletions clients/upsset.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ static void error_page(const char *next, const char *title,
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
/* Note: Not converting to hardened NUT methods with dynamic
* format string checking, this one is used locally with
* fixed strings (and args) quite extensively. */
vsnprintf(msg, sizeof(msg), fmt, ap);
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
#pragma GCC diagnostic pop
Expand Down
Loading
Loading