Skip to content

Commit fedb484

Browse files
authored
Merge pull request #88682 from vseanreesermsft/internal-merge-7.0-2023-07-11-1024
Merging internal commits for release/7.0
2 parents e3034a1 + 4147d8e commit fedb484

File tree

5 files changed

+127
-11
lines changed

5 files changed

+127
-11
lines changed

src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ private static ArraySegment<byte> DecryptContentInfo(ContentInfoAsn contentInfo,
249249
default,
250250
encryptedData.EncryptedContentInfo.EncryptedContent.Value.Span,
251251
destination);
252+
253+
// When padding happens to be as expected (false-positive), we can detect gibberish and prevent unexpected failures later
254+
// This extra check makes it so it's very unlikely we'll end up with false positive.
255+
AsnValueReader outerSafeBag = new AsnValueReader(destination.AsSpan(0, written), AsnEncodingRules.BER);
256+
AsnValueReader safeBagReader = outerSafeBag.ReadSequence();
257+
outerSafeBag.ThrowIfNotEmpty();
252258
}
253259
catch
254260
{
@@ -259,6 +265,12 @@ private static ArraySegment<byte> DecryptContentInfo(ContentInfoAsn contentInfo,
259265
default,
260266
encryptedData.EncryptedContentInfo.EncryptedContent.Value.Span,
261267
destination);
268+
269+
// When padding happens to be as expected (false-positive), we can detect gibberish and prevent unexpected failures later
270+
// This extra check makes it so it's very unlikely we'll end up with false positive.
271+
AsnValueReader outerSafeBag = new AsnValueReader(destination.AsSpan(0, written), AsnEncodingRules.BER);
272+
AsnValueReader safeBagReader = outerSafeBag.ReadSequence();
273+
outerSafeBag.ThrowIfNotEmpty();
262274
}
263275
}
264276
finally

src/native/eventpipe/ds-ipc-pal-namedpipe.c

Lines changed: 110 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ ep_rt_object_free (void *ptr)
5757
}
5858
#endif /* !FEATURE_PERFTRACING_STANDALONE_PAL */
5959

60+
static HANDLE _ipc_listen_ownership_handle = INVALID_HANDLE_VALUE;
61+
6062
/*
6163
* Forward declares of all static functions.
6264
*/
@@ -91,6 +93,18 @@ static
9193
bool
9294
ipc_stream_close_func (void *object);
9395

96+
static
97+
void
98+
ipc_close_ownership_handle (
99+
ds_ipc_error_callback_func callback);
100+
101+
static
102+
bool
103+
ipc_createpipe_helper (
104+
DiagnosticsIpc *ipc,
105+
bool ensure_pipe_creation,
106+
ds_ipc_error_callback_func callback);
107+
94108
static
95109
DiagnosticsIpcStream *
96110
ipc_stream_alloc (
@@ -108,8 +122,9 @@ ds_ipc_pal_init (void)
108122
}
109123

110124
bool
111-
ds_ipc_pal_shutdown (void)
125+
ds_ipc_pal_shutdown (ds_ipc_error_callback_func callback)
112126
{
127+
ipc_close_ownership_handle(callback);
113128
return true;
114129
}
115130

@@ -330,9 +345,11 @@ ds_ipc_poll (
330345
ep_exit_error_handler ();
331346
}
332347

348+
static
333349
bool
334-
ds_ipc_listen (
350+
ipc_createpipe_helper (
335351
DiagnosticsIpc *ipc,
352+
bool ensure_pipe_creation,
336353
ds_ipc_error_callback_func callback)
337354
{
338355
bool result = false;
@@ -348,16 +365,41 @@ ds_ipc_listen (
348365
if (ipc->is_listening)
349366
return true;
350367

351-
EP_ASSERT (ipc->pipe == INVALID_HANDLE_VALUE);
368+
if (!ensure_pipe_creation && _ipc_listen_ownership_handle == INVALID_HANDLE_VALUE)
369+
{
370+
if (callback)
371+
callback ("Can't ensure we have ownership of the pipe. Disallowing creation.", -1);
372+
return false;
373+
}
374+
375+
if (ensure_pipe_creation && _ipc_listen_ownership_handle != INVALID_HANDLE_VALUE)
376+
{
377+
if (callback)
378+
callback ("Inconsistent state - pipe sentinel already in use for listen.", -1);
379+
return false;
380+
}
381+
382+
EP_ASSERT (ipc->pipe == INVALID_HANDLE_VALUE);
352383

353384
const uint32_t in_buffer_size = 16 * 1024;
354385
const uint32_t out_buffer_size = 16 * 1024;
355386

387+
DWORD creationFlags = PIPE_ACCESS_DUPLEX // read/write access
388+
| FILE_FLAG_OVERLAPPED; // async listening.
389+
390+
if (ensure_pipe_creation)
391+
{
392+
// Fail if we can't own pipe. This is the only way to ensure
393+
// ownership of the pipe, and by extension the default DACL.
394+
// Otherwise, Windows treats this as a FIFO queue get-or-create
395+
// request and we might end up with DACLs set by other creators.
396+
creationFlags |= FILE_FLAG_FIRST_PIPE_INSTANCE;
397+
}
398+
356399
DS_ENTER_BLOCKING_PAL_SECTION;
357400
ipc->pipe = CreateNamedPipeA (
358401
ipc->pipe_name, // pipe name
359-
PIPE_ACCESS_DUPLEX | // read/write access
360-
FILE_FLAG_OVERLAPPED, // async listening
402+
creationFlags,
361403
PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, // message type pipe, message-read and blocking mode
362404
PIPE_UNLIMITED_INSTANCES, // max. instances
363405
out_buffer_size, // output buffer size
@@ -372,6 +414,28 @@ ds_ipc_listen (
372414
ep_raise_error ();
373415
}
374416

417+
if (ensure_pipe_creation)
418+
{
419+
EP_ASSERT (_ipc_listen_ownership_handle == INVALID_HANDLE_VALUE);
420+
421+
// The dupe and leak of the handle to ensure listen EP ownership for process duration.
422+
bool createdSentinel = DuplicateHandle(
423+
GetCurrentProcess(),
424+
ipc->pipe,
425+
GetCurrentProcess(),
426+
&_ipc_listen_ownership_handle,
427+
0,
428+
FALSE,
429+
DUPLICATE_SAME_ACCESS);
430+
431+
if (!createdSentinel)
432+
{
433+
if (callback)
434+
callback ("Failed to ownership sentinel.", GetLastError());
435+
ep_raise_error();
436+
}
437+
}
438+
375439
EP_ASSERT (ipc->overlap.hEvent == INVALID_HANDLE_VALUE);
376440

377441
ipc->overlap.hEvent = CreateEventW (NULL, true, false, NULL);
@@ -407,10 +471,23 @@ ds_ipc_listen (
407471

408472
ep_on_error:
409473
ds_ipc_close (ipc, false, callback);
474+
if (ensure_pipe_creation)
475+
ipc_close_ownership_handle(callback);
410476
result = false;
411477
ep_exit_error_handler ();
412478
}
413479

480+
bool
481+
ds_ipc_listen (
482+
DiagnosticsIpc *ipc,
483+
ds_ipc_error_callback_func callback)
484+
{
485+
// This is the first time that this listening channel is created
486+
// from the perspective of the runtime. Request we ensure that we create
487+
// the pipe.
488+
return ipc_createpipe_helper(ipc, true, callback);
489+
}
490+
414491
DiagnosticsIpcStream *
415492
ds_ipc_accept (
416493
DiagnosticsIpc *ipc,
@@ -459,7 +536,10 @@ ds_ipc_accept (
459536
memset(&ipc->overlap, 0, sizeof(OVERLAPPED)); // clear the overlapped objects state
460537
ipc->overlap.hEvent = INVALID_HANDLE_VALUE;
461538

462-
ep_raise_error_if_nok (ds_ipc_listen (ipc, callback));
539+
// At this point we have at least one open connection with this pipe,
540+
// so this listen pipe won't recreate the named pipe and thus inherit
541+
// all the necessary DACLs from the original listen call.
542+
ep_raise_error_if_nok (ipc_createpipe_helper (ipc, false, callback));
463543

464544
ep_on_exit:
465545
return stream;
@@ -526,6 +606,27 @@ ds_ipc_connect (
526606
ep_exit_error_handler ();
527607
}
528608

609+
void
610+
ipc_close_ownership_handle (
611+
ds_ipc_error_callback_func callback)
612+
{
613+
if (_ipc_listen_ownership_handle == INVALID_HANDLE_VALUE)
614+
return;
615+
616+
const BOOL success_close_pipe = CloseHandle(_ipc_listen_ownership_handle);
617+
if (success_close_pipe != TRUE)
618+
{
619+
if (callback)
620+
callback ("Failed to IPC ownership sentinel handle", GetLastError());
621+
// Explicitly don't reset it. Failing to close and setting it to an invalid handle
622+
// leaks the handle in a way we can't diagnose anything. Leaving it rooted helps us
623+
// assert state consistency.
624+
return;
625+
}
626+
627+
_ipc_listen_ownership_handle = INVALID_HANDLE_VALUE;
628+
}
629+
529630
void
530631
ds_ipc_close (
531632
DiagnosticsIpc *ipc,
@@ -535,7 +636,9 @@ ds_ipc_close (
535636
EP_ASSERT (ipc != NULL);
536637

537638
// don't attempt cleanup on shutdown and let the OS handle it
538-
if (is_shutdown) {
639+
// except in the case of listen pipes - if they leak the process
640+
// will fail to reinitialize the pipe for embedding scenarios.
641+
if (is_shutdown && ipc->mode != DS_IPC_CONNECTION_MODE_LISTEN) {
539642
if (callback)
540643
callback ("Closing without cleaning underlying handles", 100);
541644
return;

src/native/eventpipe/ds-ipc-pal-socket.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,11 +1009,12 @@ ds_ipc_pal_init (void)
10091009
}
10101010

10111011
bool
1012-
ds_ipc_pal_shutdown (void)
1012+
ds_ipc_pal_shutdown (ds_ipc_error_callback_func callback)
10131013
{
10141014
#ifdef HOST_WIN32
10151015
if (_ipc_pal_socket_init)
1016-
WSACleanup ();
1016+
if (WSACleanup() == SOCKET_ERROR && callback)
1017+
callback ("Failed to cleanup Winsock", WSAGetLastError());
10171018
#endif
10181019
_ipc_pal_socket_init = false;
10191020
return true;

src/native/eventpipe/ds-ipc-pal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ bool
2121
ds_ipc_pal_init (void);
2222

2323
bool
24-
ds_ipc_pal_shutdown (void);
24+
ds_ipc_pal_shutdown (ds_ipc_error_callback_func callback);
2525

2626
int32_t
2727
ds_ipc_get_handle_int32_t (DiagnosticsIpc *ipc);

src/native/eventpipe/ds-server.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ ds_server_shutdown (void)
247247
ds_ipc_stream_factory_shutdown (server_error_callback_close);
248248

249249
ds_ipc_stream_factory_fini ();
250-
ds_ipc_pal_shutdown ();
250+
ds_ipc_pal_shutdown (server_error_callback_close);
251251
return true;
252252
}
253253

0 commit comments

Comments
 (0)