Mutual exclusion across user session in Citrix environment - windows

I have an application that runs in Citrix environment. The application can be run simultaneously by several users in different user sessions. In my application I am writing to a file which should be mutually exclusive across all the user sessions. I tried Mutex to avoid writing to a file from different user sessions but using Mutex failed as in some scenarios different user sessions could not detect whether the Mutex object was already created.
Could any one tell me which of the below approach is better to achieve mutual exclusion across all the user sessions:
Using Named pipes :
If named pipe already exists then application will wait till the pipe gets closed by the application instance which had opened it. Otherwise create the named pipe to indicate the acquiring of lock.
Using a lock file:
Create a normal file on disk to indicate the acquiring of lock and delete when unlock needs to be done.

You don't need to use a lock file. You can use the built in file system sharing mechanism.
When you open the file by calling CreateFile() you determine the sharing access for subsequent attempts to open the file with the dwShareMode parameter. For example, set this to 0 and no other process will be able to open the file.

Related

Is there a way to know if the current process holds a specific file lock?

We have a serie of applications running on windows that uses file locking for protecting concurrent access to their data (shared files on network drive).
Sometimes, it seems one of these process fails to release one of these locks and everything freezes until the process is killed. Finding out who holds that lock is not always trivial (needs an admin to go on the file server and check network open files, go one workstation, find process and kill it).
We have a message queue system between the applications that is serviced by a background thread so, in theory, it would be possible to send out a message to every process asking them if they hold a lock to a specific file and if they do, mybe take an action like kill the process if the lock is held longer than a few seconds)
So, the question is: is there a way for a thread to know if a different thread of the same process holds a lock (LockFile) against a given file?
I'm not sure if there is a API to query this but a process can query itself with the LockFileEx function:
A shared lock can overlap an exclusive lock if both locks were created using the same file handle. When a shared lock overlaps an exclusive lock, the only possible access is a read by the owner of the locks.
The other thread could query and see if it can get shared access.
If you control the file format you could write the computer name and process id to the start of the file every time you take the lock. File memory mappings can view the file contents even while it is locked.

Ways to find out if the process is created by system (by pid) on macOS?

I'm implementing API which allows to launch other apps (using NSTask) inside VFS (FUSE on macOS). After VFS is mounted a bunch of processes start accessing launched VFS in which my app works, and I'd like to implement some kind of filtering mechnism which will allow to detect whether process which is accessing the VFS is created by system (and potentially safe) or not, and if so it'll be granted an access to the file system where my app runs.
So far I'm able to get basic information of the process by it's pid. For example: process path, uid, ppid, code signature of the process etc (using Security framework, libproc etc)
I've done a couple of tests and see that there are process with uid != 0 and still critical for my app to run (if I deny access to them app which is started in VFS crashes) (e.g. /usr/libexec/secinitd, /System/Library/CoreServices/Dock.app/Contents/MacOS/Dock), so looks like approach with filtering processes by pids, uids, ppids might not work.
So the question is: is it possible to distinguish whether process which is accessing my app was created by system and is potentially safe? I also don't want to do too much work by denying accees to critical system processes which will allow the app to successfully start and run in VFS.
Judging from the comment thread, your threat model is data theft via malware etc.
In this case, you can trust almost nothing, so the best way is probably to maintain an explicit whitelist of processes which are allowed to access your mount point, and block access to everything else by default. Log any processes to which access is denied, and allow the user to reverse that decision and add them to the whitelist. In other words, let the user decide what applications they consider safe.
Your said that according to your inspection, there were several processes which were mandatory for the process to run, so why won't use try-and-error approach.
You deploy you FUSE drive on clean environment and record all processes that attempt to access your files - try to prevent each process and keep only those which crash your apps, and add them to a white-list.
Of course that this list is subject to change in different macOS versions, but it can give you the general idea.
Alternatively, you can break your app into couple of parts. for example, put the sensitive logic inside separated dylib file, and prevent access to this file only.. since dylib is not the main executable in your app, I believe fewer processes require mandatory access it.

Secure Named Shared Memory on Windows so only specific processes can open

Is there a way to set the permissions with Named Shared Memory in Windows so that the access control is done by process rather than by user? I'd like to have one program create the memory, pass a handle or pass back a PID so that the client process can access the memory. All other processes should be denied access. Thanks
Access control is only by security principals, which can be users, groups, computers, and the like.
If you have an object that you want shared with another process, you can use DuplicateHandle.
No, because processes are not security principles.
Instead, use an unnamed file mapping and give the client process a copy of the handle using DuplicateHandle.

How to grant Network Share access to Low Mandatory Level process?

Is there any way to grant access to network shares to Low Mandatory Level processes (UAC)?
Further explanation:
To migrate some third-party library security issues we are considering setting Integrity Mode to isolating process to Low, but we do need to have process read/write freely from specified single file system share (UNC path, possibly on separate computer).
Does anyone know is there a way to do this?
Thanks
Yes this is available by default. Integrity of a process only affects local security not remote security. This can be proven by creating a low integrity version of notepad -
Copy C:\windows\system32\notepad.exe to a location i.e.
C:\test\lownote.exe
Run icacls C:\test\lownote.exe /setintegritylevel Low
Run lownote
Confirm with Process Explorer (http://live.sysinternals.com/procexp.exe) it is running as low integrity. Note you can open files on HDD but can't save to them,
except in low integrity sections of user profile Browse to network,
path using UNC share - you can open/save files fine.
That being said you may come across access denied messages when using a low integrity process to write to network shares. This cause can be found by using procmon on the computer running your app http://live.sysinternals.com/ProcMon.exe and filtering to include Result is "ACCESS DENIED" and Process Name is - the name of your process.
What will not available is drive mappings...you will see an "access denied" thrown when trying to read HKCU[location of drive letter]
As per MSDN documentation:
However, you can use other types of communication between a low-integrity process and a higher-integrity process. The types of communication that you can use include:
Clipboard (copy and paste)
Remote procedure call (RPC)
Sockets
Window messages that the higher-integrity process has been explicitly
allowed to receive from lower-integrity processes by calling
ChangeWindowMessageFilter
Shared memory, where the higher-integrity
process explicitly lowers the mandatory label on the shared memory
section ( Important This is particularly dangerous, and the
higher-integrity process must be careful to validate all data that is
written to the shared section.)
COM interfaces, where the launch
activation rights are set programmatically by the higher-integrity
process to allow binding from low integrity clients
Named pipes,
where the creator explicitly sets the mandatory label on the pipe to allow access to lower-integrity processes
ref http://msdn.microsoft.com/en-us/library/bb625960.aspx

Setting Access permissions on Semaphore?

I am assuming that once a semaphore is created by a process, it will be accessible by any process/user.
Is it possible to put access restrictions on a particular semaphore so that it can be accessible by only certain processes/users or only certain processes can release the semaphore.
I see some problems if we make a semaphore accessible by all processes.Eg: a dummy process can read the semaphore and release the lock at wish making a false signal to the actual process that is really waiting for the semaphore lock.
All these questions are arising as I am getting very weird output with the following code snippet:
use Win32::Semaphore;
$sem = Win32::Semaphore->new(0, 1,"reliance2692")
or print "Can't create semaphore\n";
$sem = Win32::Semaphore->open("reliance2692")
or print "Can't open semaphore\n";
print "Semaphore:" . $sem . "\n";
By running the above program, I am getting the following output
Can't create semaphore
Can't open semaphore
The output shows that its failed to create a semaphore and even failed to open semaphore.
creating a semaphore might have failed if a semaphore already exists with the given name.
I don't understand why opening a semaphore failed.
Can some clarify the scenario where both creating semaphore & opening semaphore fails.
Win32::Semaphore->new calls the Windows API function CreateSemaphore and gets the process's default security descriptor, which usually means that processes running as the same user as your script can have full access whereas processes running as other accounts get no access. So, for starters, your assumption is false.
The name you choose in your Perl code is passed directly to the API function, so it's subject to the same namespace rules as all other Win32 kernel objects.
Win32::Semaphore provides no interface for specifying access restrictions. Even if it did, Windows does not provide per-process permissions. Permissions are attached to the user, not the process.
If you're getting "access denied" from new, then that suggests there's another program running that chose to use that same name for something else — maybe another semaphore, or maybe something else, like an event or a mutex — and that process is running as a different user.
If you're getting "access denied" from open, then, in addition to the possibilities for new, it could be that another process has already opened a semaphore with the same name but has not granted full permissions to other users. Win32::Semaphore->open requests SEMAPHORE_ALL_ACCESS permission.
If the semaphore has already been opened by a process running as the same user, then you should not get "access denied." Neither new nor open should fail in that case, although $^E might hold 183 (ERROR_ALREADY_EXISTS) anyway.
For the record, I'm the author of Win32::Semaphore. As mobrule and Rob have explained, Windows security is user/group based. It's not possible to have a semaphore that only certain processes can access. If any process belonging to a user can access a semaphore, then any process of that user can access that semaphore.
Normally, the default access allows only the current user to access the semaphore. Nobody's ever requested the ability to have Win32::Semaphore specify a non-default security descriptor, and the associated API is non-trivial. If somebody created a module to manage a SECURITY_ATTRIBUTES structure, I'd be happy to add support for that to Win32::Semaphore and the related IPC modules. Win32-Security does not appear to be that module, although it might be a start.
If you need a semaphore to work across multiple users, your only solution right now is to create the semaphore outside of Win32::Semaphore, passing an appropriate SECURITY_ATTRIBUTES pointer. You could do that with a small helper program written in C, or using Inline::C. (Remember that once created, a semaphore exists as long as any process has an open handle to it, so your helper program needs to keep the semaphore handle open until you've called Win32::Semaphore->open on it.)
From Win32::Semaphore pod
$semaphore = Win32::Semaphore->new($initial, $maximum, [$name])
Constructor for a new semaphore object. $initial is the initial count, and $maximum is
the maximum count for the semaphore. If $name is omitted or undef, creates an unnamed
semaphore object.
If $name signifies an existing semaphore object, then $initial and $maximum are ignored
and the object is opened. If this happens, $^E will be set to 183
(ERROR_ALREADY_EXISTS).
If I'm reading this correctly, if your call to Win32::Semaphore->new refers to an existing semaphore, then the new call will open the semaphore as well, and the subsequent open call will be redundant (it's not clear to me from the pod what should happen if you open a sempahore that is already open).
Perhaps you could step through the code, checking the value of $sem as well as $! and $^E at each step.
Additional reply: the Windows API does have methods for setting access control of semaphores, but
they don't appear to be exposed in the Perl Win32::Semaphore module
access control can't be set unless it was already allowed by the other process that created the semaphore
I don't know if you have any good options for this problem. Can you modify the process that creates the semaphore to relax access restrictions? Ask the Win32::Semaphore author to update his module? Try to fix Win32::Semaphore yourself?

Resources