-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Cannot set ReadMode after creating a NamedPipeClientStream instance #83072
Comments
Tagging subscribers to this area: @dotnet/area-system-io Issue DetailsConsider this code: var pipeOut = new NamedPipeServerStream("SomeNamedPipe",
PipeDirection.Out,
1,
PipeTransmissionMode.Message);
var pipeIn = new NamedPipeClientStream(".",
"SomeNamedPipe",
PipeDirection.In);
pipeIn.Connect();
pipeIn.ReadMode = PipeTransmissionMode.Message; // <-- exception thrown here In .NET Framework, there used to be a constructor on the client side that accepted var pipeIn =
new NamedPipeClientStream(".",
"SomeNamedPipe",
PipeAccessRights.ReadData | PipeAccessRights.WriteAttributes,
PipeOptions.None,
System.Security.Principal.TokenImpersonationLevel.None,
System.IO.HandleInheritability.None); Unfortunately, we haven't ported that constructor to .NET Core+. The underlying problem is that, according to the documentation of the Windows method The .NET Framework solution worked because it would set Unfortunately, the only workaround available in .NET Core+ is to:
I wrote a working example of this workaround for .NET 6.0 and published it here: https://github.com/carlossanlop/experiments/tree/NamedPipeClientStream_ReadMode But we should consider solving it in runtime. Note that in .NET Core+ we use
|
We should push PipeAccessRights down from System.IO.Pipes.AccessControl to System.IO.Pipes and add the |
Fixes a longstanding issue inherited from the .NET framework which prevents ReadMode being set to Message on the client end of read only named pipes on Windows platforms. Also added in new tests for Message mode on Windows to verify correct functionality. Fix dotnet#83072
Given #94742 is closed, wondering if there's any update on this one? Please note that this is also blocking scenarios such as modifying DACLs from a The reason for that is flags such as |
I think it's marked as |
The desired functionality should already be possible with NamedPipeServerStreamAcl.Create, but apparently there's a bug. Rather than adding this constructor, we should either fix the bug or bring back all of the constructors that were cut for being Windows-only (merging the Pipes and Pipes.AccessControl assembly implementations). |
I opened #98060 to follow up on fixing the bug. |
I think there was a misunderstanding (perhaps from a typo I corrected). This issue requests an API for I think moving all the ACLs APIs back is an interesting follow on issue, but I think we should fix this problem first since it's distinct from ACLs. |
To follow up on a few things questioned in the API review stream:
[SupportedOSPlatform("windows")]
public PipeSecurity GetAccessControl();
[SupportedOSPlatform("windows")]
public void SetAccessControl(PipeSecurity pipeSecurity); The Windows implementations already exist as extension methods that literally be copied to the class. (They are only like 3-5 lines each). Other platforms would just throw PlatformNotSupported exceptions, obviously. The hard thing would be that My suggestion: Add this constructor and the equivalent ones for the Server Streams. That seem like it gives full source compat when targeting Windows and referencing System.Security.AccessControl. Which I think could win over some of the API reviewers. A later effort could look fully merging the two assemblies, to allow those two missing APIs to be added, enabling full API and ABI compat. (With System.Security.AccessControl becoming just a facade in both Reference and runtime assembly form.) Hope this helps. |
Looks good as proposed. We discussed whether PipeAccessRights needed SupportedOSPlatform("windows"), and decided that "no" was the correct answer. The nullability annotations should be made correct based on what .NET Framework accepts/rejects. namespace System.IO.Pipes;
// existing type
public sealed partial class NamedPipeClientStream : PipeStream
{
// new constructor
[SupportedOSPlatform("windows")]
public NamedPipeClientStream(String serverName, String pipeName, PipeAccessRights desiredAccessRights,
PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability)
}
// existing type moved from System.IO.Pipes.AccessControl assembly.
[System.FlagsAttribute]
public enum PipeAccessRights
{
ReadData = 1,
WriteData = 2,
CreateNewInstance = 4,
ReadExtendedAttributes = 8,
WriteExtendedAttributes = 16,
ReadAttributes = 128,
WriteAttributes = 256,
Write = 274,
Delete = 65536,
ReadPermissions = 131072,
Read = 131209,
ReadWrite = 131483,
ChangePermissions = 262144,
TakeOwnership = 524288,
Synchronize = 1048576,
FullControl = 2032031,
AccessSystemSecurity = 16777216,
} |
Background and motivation
Cannot set
ReadMode
after creating aNamedPipeClientStream
instance. This is due to not exposing theNamedPipeClientStream
constructor which accepts aPipeAccessRights
.API Proposal
API Usage
Alternative Designs
We could expose this with a
Create
factory method instead, as was done forNamedPipeServerStream
runtime/src/libraries/System.IO.Pipes.AccessControl/ref/System.IO.Pipes.AccessControl.cs
Lines 9 to 16 in dbb335c
However that's not necessary and probably a misnomer since this new constructor isn't really about ACLs, but instead access rights on the handle. Contrast that to those existing factory methods which take
PipeSecurity
which is an ACLs concept. Splitting hairs, perhaps, since the API is related to access and is likely not supported on non-Windows, but I think we can do better here by exposing the exact missing API so we should.Risks
Moving types around carries with it some risk. Luckily all the assemblies here are in the shared framework (since 6.0) and referenced as a set so it's less of a risk,
Original issue
Consider this code:
In .NET Framework, there used to be a constructor on the client side that accepted
PipeAccessRights
, which would solve the issue, and would allow the user to changeReadMode
later:Unfortunately, we haven't ported that constructor to .NET Core+.
The underlying problem is that, according to the documentation of the Windows method
CreateNamedPipe
, we need to pass theFILE_WRITE_ATTRIBUTES
access right when constructing the pipe handle, to be able to modify it after creation. This is explained in the remarks: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea#remarksThe .NET Framework solution worked because it would set
FILE_WRITE_ATTRIBUTES
when using the constructor that takes aPipeAccessRights
argument.Unfortunately, the only workaround available in .NET Core+ is to:
SafePipeHandle
, making sure to passFILE_WRITE_ATTRIBUTES
to the P/Invoke, which is not straightforward.true
to the argument that indicates that the pipe should get connected.ReadMode
.I wrote a working example of this workaround for .NET 6.0 and published it here: https://github.com/carlossanlop/experiments/tree/NamedPipeClientStream_ReadMode
But we should consider solving it in runtime.
Note that the workaround provided above had to call an internal constructor from
PipeSecurity
using reflection. It's another argumemt supporting the idea that we should provide the solution ourselves.The text was updated successfully, but these errors were encountered: