Re: [PATCH 00/10] [RFC] Simple IPC Mechanism
From: Jeff Hostetler <hidden>
Date: 2021-01-12 23:26:19
On 1/12/21 3:01 PM, Junio C Hamano wrote:
"Jeff Hostetler via GitGitGadget" [off-list ref] writes:quoted
This series introduces a multi-threaded IPC mechanism called "Simple IPC". This is a library-layer feature to make it easy to create very long running daemon/service applications and for unrelated Git commands to communicate with them. Communication uses pkt-line messaging over a Windows named pipe or Unix domain socket. On the server side, Simple IPC implements a (platform-specific) connection listener and worker thread-pool to accept and handle a series of client connections. The server functionality is completely hidden behind the ipc_server_run() and ipc_server_run_async() APIs. The daemon/service application only needs to define an application-specific callback to handle client requests. Note that Simple IPC is completely unrelated to the long running process feature (described in sub-process.h) where the lifetime of a "sub-process" child is bound to that of the invoking parent process and communication occurs over the child's stdin/stdout. Simple IPC will serve as a basis for a future builtin FSMonitor daemon feature.What kind of security implications does this bring into the system? Can a Simple IPC daemon be connected by any client? How does the daemon know that the other side is authorized to make requests? When a git binary acting as client connect to whatever happens to be listening to the well-known location, how does it know if the other side is the daemon it wanted to talk to and not a malicious MITM or other impersonator? Or is this to be only used for "this is meant to be used to give read-only access to data that is public anyway" kind of daemon, e.g. "git://" transport that serves clones and fetches? Or is this meant to be used on client machines where all the processes are assumed to be working for the end user, so it is OK to declare that anything will go (good old DOS mental model?) I know at the Mechanism level we do not yet know how it will be used, but we cannot retrofit sufficient security, so it would be necessary to know answers to these questions. Thanks.
Good questions. Yes, this is a local-only mechanism. A local-only named pipe on Windows and a Unix domain socket on Unix. In both cases the daemon creates the pipe/socket as the foreground user (since the daemon process will be implicitly started by the first Git command that needs to talk to it). Later client process try to open the pipe/socket with RW access if they can. On Windows a local named pipe is created by the server side. It rejects remote connections. I did not put an ACL, so it should inherit the system default which grants the user RW access (since the daemon is implicitly started by the first foreground client command that needs to talk to it.) Other users in the user's group and the anonymous user should have R but not W access to it, so they could not be able to connect. The name pipe is kept in the local Named Pipe File System (NPFS) as `\\.\pipe\<unique-path>` so it is globally visible on the system, but I don't think it is a problem. On the Unix side, the socket is created inside the .git directory by the daemon. Potential clients would have to have access to the working directory and the .git directory to connect to the socket, so in normal circumstances they would be able to read everything in the WD anyway. So again, I don't think it is a problem. Alternatively, if a malicious server is started and holds the named pipe or socket: the client might be able to talk to it (assuming that bad server grants access or impersonates the rightful user). The client might not be able to tell they've been tricked, but at that point the system is already compromised. So unless I'm missing something, I think we're OK either way. Jeff