Skip to content

Commit 92e7c3b

Browse files
authored
Merge d0aedb1 into 93f8671
2 parents 93f8671 + d0aedb1 commit 92e7c3b

7 files changed

Lines changed: 627 additions & 158 deletions

File tree

NEWS.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ but the `nutshutdown` script would bail out quickly and quietly. [PR #3008]
123123
in other programs. Extended public API of libupsclient and libnutscan
124124
to diligently arrange debug-logging when at run-time those libraries
125125
actually have different copies of the methods and data involved. [#3378]
126+
* Revised 'dstate' machinery to track socket connections closed mid-way
127+
through a call, to avoid access after `free()`. [#3302]
126128

127129
- NUT for Windows specific updates:
128130
* Revised detection of (relative) paths to program and configuration files

common/wincompat.c

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ char *getpass(const char *prompt)
6868
{
6969
HANDLE hStdin;
7070
DWORD mode;
71+
size_t len;
7172

7273
hStdin = GetStdHandle(STD_INPUT_HANDLE);
7374
if (hStdin == INVALID_HANDLE_VALUE) {
@@ -86,8 +87,9 @@ char *getpass(const char *prompt)
8687
}
8788

8889
/* deal with that pesky newline */
89-
if (strlen(wincompat_password) > 1) {
90-
wincompat_password[strlen(wincompat_password) - 1] = '\0';
90+
len = strlen(wincompat_password);
91+
if (len > 1) {
92+
wincompat_password[len - 1] = '\0';
9193
}
9294

9395
hStdin = GetStdHandle(STD_INPUT_HANDLE);
@@ -407,6 +409,7 @@ int win_system(const char * command)
407409
si.cb = sizeof(si);
408410
memset(&pi, 0, sizeof(pi));
409411

412+
upsdebugx(4, "%s: calling CreateProcess: %s", __func__, NUT_STRARG(command));
410413
res = CreateProcess(NULL, (char *)command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
411414

412415
if (res != 0) {
@@ -417,20 +420,22 @@ int win_system(const char * command)
417420
}
418421

419422
/* the " character is forbiden in Windows files , so we filter this character
420-
in data file paths to be coherent with command line which require " to
421-
distinguish the command from its parameter. This avoid complicated
422-
explanation in the documentation */
423+
* in data file paths to be coherent with command line which require " to
424+
* distinguish the command from its parameter. This avoid complicated
425+
* explanation in the documentation */
423426
char * filter_path(const char * source)
424427
{
425428
char *res;
426429
unsigned int i, j;
430+
size_t len;
427431

428432
if (source == NULL) {
429433
return NULL;
430434
}
431435

432-
res = xmalloc(strlen(source) + 1);
433-
for (i=0, j=0; i <= strlen(source); i++) {
436+
len = strlen(source);
437+
res = xmalloc(len + 1);
438+
for (i=0, j=0; i <= len; i++) {
434439
if (source[i] != '"') {
435440
res[j] = source[i];
436441
j++;
@@ -474,6 +479,7 @@ void syslog(int priority, const char *fmt, ...)
474479
/* then comes the message */
475480
memcpy(buf1 + sizeof(DWORD), buf2, sizeof(buf2));
476481

482+
upsdebugx(6, "%s: posting to event log NAMED_PIPE: '%s'", __func__, pipe_full_name);
477483
pipe = CreateFile(
478484
pipe_full_name, /* pipe name */
479485
GENERIC_WRITE,
@@ -484,6 +490,10 @@ void syslog(int priority, const char *fmt, ...)
484490
NULL); /* no template file */
485491

486492
if (pipe == INVALID_HANDLE_VALUE) {
493+
upsdebug_with_errno(1,
494+
"%s: SKIP: can't open existing event log NAMED_PIPE: '%s'",
495+
__func__, pipe_full_name);
496+
487497
return;
488498
}
489499

@@ -492,6 +502,7 @@ void syslog(int priority, const char *fmt, ...)
492502
/* testing result is useless. If we have an error and try to report it,
493503
* this will probably lead to a call to this function and an infinite
494504
* loop */
505+
upsdebugx(6, "%s: closing event log NAMED_PIPE", __func__);
495506
CloseHandle(pipe);
496507
}
497508

@@ -526,6 +537,7 @@ void pipe_create(const char * pipe_name)
526537
CloseHandle(pipe_connection_overlapped.hEvent);
527538
}
528539
memset(&pipe_connection_overlapped, 0, sizeof(pipe_connection_overlapped));
540+
upsdebugx(2, "%s: creating NAMED_PIPE (listener): '%s'", __func__, pipe_full_name);
529541
pipe_connection_handle = CreateNamedPipe(
530542
pipe_full_name,
531543
PIPE_ACCESS_INBOUND /* to server only */
@@ -560,7 +572,7 @@ void pipe_create(const char * pipe_name)
560572
/* Wait for a connection */
561573
ret = ConnectNamedPipe(pipe_connection_handle, &pipe_connection_overlapped);
562574
if (ret == 0 && GetLastError() != ERROR_IO_PENDING) {
563-
upslogx(LOG_ERR, "ConnectNamedPipe error");
575+
upslog_with_errno(LOG_ERR, "ConnectNamedPipe error");
564576
}
565577
}
566578

@@ -569,6 +581,12 @@ void pipe_connect()
569581
/* We have detected a connection on the opened pipe. So we start by saving its handle and create a new pipe for future connections */
570582
pipe_conn_t *conn;
571583

584+
/* TOTHINK: Here we seem to have assumptions about a general connection
585+
* via overlapped I/O being the signal to daemon (via named_pipe_name)...
586+
* might this conflict with other I/Os (driver/server sockets, dummy-ups
587+
* files, etc.)?
588+
*/
589+
upsdebugx(3, "%s: handle incoming connection on NAMED PIPE", __func__);
572590
conn = xcalloc(1, sizeof(*conn));
573591
conn->handle = pipe_connection_handle;
574592

@@ -587,7 +605,7 @@ void pipe_connect()
587605
);
588606
if (conn->overlapped.hEvent == NULL) {
589607
/* FIXME: Is this (still) about event log only? */
590-
upslogx(LOG_ERR, "Can't create event for reading event log");
608+
upslog_with_errno(LOG_ERR, "Can't create event for reading event log");
591609
return;
592610
}
593611

@@ -605,17 +623,20 @@ void pipe_connect()
605623

606624
void pipe_disconnect(pipe_conn_t *conn)
607625
{
626+
upsdebugx(3, "%s: starting", __func__);
627+
608628
if (conn->overlapped.hEvent != INVALID_HANDLE_VALUE) {
629+
upsdebugx(4, "%s: calling CloseHandle() for conn->overlapped.hEvent", __func__);
609630
CloseHandle(conn->overlapped.hEvent);
610631
conn->overlapped.hEvent = INVALID_HANDLE_VALUE;
611632
}
612633

613634
if (conn->handle != INVALID_HANDLE_VALUE) {
635+
upsdebugx(4, "%s: calling DisconnectNamedPipe() for not-yet-invalid conn->handle", __func__);
614636
if (DisconnectNamedPipe(conn->handle) == 0) {
615-
upslogx(LOG_ERR,
616-
"DisconnectNamedPipe error : %d",
617-
(int)GetLastError());
637+
upslog_with_errno(LOG_ERR, "DisconnectNamedPipe failed");
618638
}
639+
upsdebugx(4, "%s: calling CloseHandle() for conn->handle", __func__);
619640
CloseHandle(conn->handle);
620641
conn->handle = INVALID_HANDLE_VALUE;
621642
}
@@ -642,7 +663,7 @@ int pipe_ready(pipe_conn_t *conn)
642663

643664
res = GetOverlappedResult(conn->handle, &conn->overlapped, &bytesRead, FALSE);
644665
if (res == 0) {
645-
upslogx(LOG_ERR, "Pipe read error");
666+
upslog_with_errno(LOG_ERR, "Pipe read error");
646667
pipe_disconnect(conn);
647668
return 0;
648669
}
@@ -657,9 +678,11 @@ int send_to_named_pipe(const char * pipe_name, const char * data)
657678
BOOL result = FALSE;
658679
DWORD bytesWritten = 0;
659680
char pipe_full_name[NUT_PATH_MAX + 1];
681+
size_t len;
660682

661683
snprintf(pipe_full_name, sizeof(pipe_full_name), "\\\\.\\pipe\\%s", pipe_name);
662684

685+
upsdebugx(6, "%s: posting to NAMED_PIPE: '%s'", __func__, pipe_full_name);
663686
pipe = CreateFile(
664687
pipe_full_name,
665688
GENERIC_WRITE,
@@ -670,16 +693,23 @@ int send_to_named_pipe(const char * pipe_name, const char * data)
670693
NULL); /* no template file */
671694

672695
if (pipe == INVALID_HANDLE_VALUE) {
696+
upsdebug_with_errno(1,
697+
"%s: SKIP: can't open existing NAMED_PIPE: '%s'",
698+
__func__, pipe_full_name);
699+
673700
return 1;
674701
}
675702

676-
result = WriteFile(pipe, data, strlen(data) + 1, &bytesWritten, NULL);
703+
len = strlen(data);
704+
result = WriteFile(pipe, data, len + 1, &bytesWritten, NULL);
677705

678-
if (result == 0 || bytesWritten != strlen(data) + 1) {
706+
if (result == 0 || bytesWritten != len + 1) {
707+
upsdebug_with_errno(6, "%s: closing event log NAMED_PIPE, did not write as much as expected to", __func__);
679708
CloseHandle(pipe);
680709
return 1;
681710
}
682711

712+
upsdebugx(6, "%s: closing event log NAMED_PIPE", __func__);
683713
CloseHandle(pipe);
684714
return 0;
685715
}
@@ -955,7 +985,7 @@ serial_handler_t * w32_serial_open(const char *name, int flags)
955985
0);
956986

957987
if (sh->handle == INVALID_HANDLE_VALUE) {
958-
upslogx(LOG_ERR, "could not open %s", name);
988+
upslog_with_errno(LOG_ERR, "could not open %s", name);
959989
errno = EPERM;
960990
return NULL;
961991
}
@@ -994,7 +1024,7 @@ serial_handler_t * w32_serial_open(const char *name, int flags)
9941024
state.fAbortOnError = TRUE;
9951025

9961026
if (!SetCommState(sh->handle, &state)) {
997-
upslogx(LOG_ERR,
1027+
upslog_with_errno(LOG_ERR,
9981028
"couldn't set initial state for %s",
9991029
name);
10001030
}
@@ -1125,7 +1155,7 @@ int tcflush(serial_handler_t *sh, int queue)
11251155
if (queue == TCOFLUSH || queue == TCIOFLUSH)
11261156
PurgeComm(sh->handle, PURGE_TXABORT | PURGE_TXCLEAR);
11271157

1128-
if ((queue == TCIFLUSH) | (queue == TCIOFLUSH))
1158+
if ((queue == TCIFLUSH) || (queue == TCIOFLUSH))
11291159
{
11301160
/* Input flushing by polling until nothing turns up
11311161
* (we stop after 1000 chars anyway) */
@@ -1469,7 +1499,7 @@ TCSAFLUSH: flush output and discard input, then change attributes.
14691499
res = SetCommTimeouts(sh->handle, &to);
14701500
if (!res)
14711501
{
1472-
upslogx(LOG_ERR, "SetCommTimeout failed");
1502+
upslog_with_errno(LOG_ERR, "SetCommTimeout failed");
14731503
errno = EIO;
14741504
return -1;
14751505
}

0 commit comments

Comments
 (0)