Recent

Author Topic: SimpleIPC communication between standard user and root on macOS  (Read 1642 times)

inferno

  • New Member
  • *
  • Posts: 34
SimpleIPC communication between standard user and root on macOS
« on: January 02, 2021, 10:25:35 pm »
Hi all,
I'm trying to implement bidirectional communication between two prosesses in macOS using TSimpleIPCClient and TSimpleIPCServer. When both processes are running by the same user (owner) everyting works well. When one process is started by the regular user and the other process by the root, the communication is broken. It must be some permissions issue. There is Global property (I set it to true) in the TSimpleIPCServer (https://www.freepascal.org/docs-html/current/fcl/simpleipc/tsimpleipcserver.global.html) but it looks it is related only to other processes started by the same user.

Is any way to establish communication on macOS between two processes owned by two different users (standard/admin user and root) using TSimpleIPCClient and TSimpleIPCServer?

Best regards,
Inferno

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2020
  • Former Delphi 1-7, 10.2 user
Re: SimpleIPC communication between standard user and root on macOS
« Reply #1 on: January 03, 2021, 01:28:51 am »
You don't show any code, so I'm resorting to my crystal ball. Are you using a port below 1024 which is only accessible by root? That would explain it. If so, you should be using an ephemeral port in the range 49152-65535.

inferno

  • New Member
  • *
  • Posts: 34
Re: SimpleIPC communication between standard user and root on macOS
« Reply #2 on: January 03, 2021, 11:24:14 pm »
Hi trev,
Thank you for your reply. I didn't show the code beacuse it is a little bit complicated, but finally at the end it works like simple examples that can be found on the forum:

https://forum.lazarus.freepascal.org/index.php?topic=30135.0
https://forum.lazarus.freepascal.org/index.php?topic=43489.0

For one way communication you need:

- for server site set:
Code: Pascal  [Select][+][-]
  1.     IPCServer.ServerID:='some_id';
  2.     IPCServer.Global:=true;
  3.     IPCServer.OnMessage:=@ProcessMessageFromRemote;
  4.     IPCServer.StartServer;
  and run in some loop:
Code: Pascal  [Select][+][-]
  1.     IPCServer.PeekMessage(PeekingTimeout, true);

- for client site set:
Code: Pascal  [Select][+][-]
  1.     IPCClient.ServerID:='some_id';
  2.     if IPCClient.ServerRunning then
  3.       IPCClient.Active:=true;
  and run:
Code: Pascal  [Select][+][-]
  1.     IPCClient.SendMessage('some_string');
(in my code messages contain streams with packed records)

The issue is not in the code because when both sites are started by the same user the communication works well without issues. Also TSimpleIPCClient and TSimpleIPCServer have no properties or methods that potentially can change someting here.

Socked ports you mentioned is something related to TCP and UDP networking, but has nothing to do with SimpleIPC as this is based on different mechanism described below.

To replicate the issue you can simply compile the example from the second link and test. When you run client and server by the same user the communication will work well. When you run one of the two, client as regular user and server as root (with sodo), the communication will fail.

What I found until now:

1. TSimpleIPCClient and TSimpleIPCServer are based on named pipes. Named pipes are special kind of files (marked by the letter p) used in interprocess communication. These files  follow FIFO behavour. They can be created manually with mkfifo command.

2. When TSimpleIPCServer server is running (Active=true), the FIFO file is created. The location and permissions of the named pipe file depend of the processes owner:

- when both processes are started by the root the named pipe location is: /private/tmp/<ServerID>. The owner is root, the group is wheel, and the permissions are (probably applied according to users umask excluding execution): prw-r--r--

- when both processes are started by the regular (standard or admin) user, the named pipe location is: /private/var/folders/xx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/T/<ServerID>. The owner is the user that run the processes, the group is staff, and the permissions are the same: prw-r--r--

3. To find the named pipes you can use lsof  -p <PROCESS PID> command. It will show all files opened by the process, including FIFO files used by named pipes.

So to fix the issue the process started by root need to be some way forced to create its named pipes FIFO files in the the same location as regular users and with permissions that allow others access the files. This is exactly the functionality of the mkfifo command where you provide permisions (mode) and file path. 

Also in my opinion SimpleIPC limitation to single user significantly narrows the scope of applications...

Any idea how to fix this issue? :)

Best regards,
Inferno
« Last Edit: January 03, 2021, 11:28:23 pm by inferno »

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2020
  • Former Delphi 1-7, 10.2 user
Re: SimpleIPC communication between standard user and root on macOS
« Reply #3 on: January 04, 2021, 12:56:45 am »
Sorry, I've never used IPC as opposed to sockets in programs such as sendmail milters, but I would expect the same sort of principles to apply. So:

* Does the server instance have to be started as root? Generally not a good idea; if it does you should probably drop to an unprivileged user as soon as root privileges are no longer needed.
* You should be able to specify the directory containing your name pipe and give it an appropriate umask.

Actually the C function to create a named pipe is:

Code: C  [Select][+][-]
  1. int mkfifo(const char *pathname, mode_t mode);

where mode sets the permissions being a combination of (mode & ~umask).

I will go look at the simpleIPC examples now...
« Last Edit: January 04, 2021, 01:03:42 am by trev »

 

TinyPortal © 2005-2018