You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add the CurrentUserOnly and CurrentSessionOnly options for named Mutex, Semaphore, and EventWaitHandle (#112213)
- In `Mutex`, `Semaphore`, and `EventWaitHandle`, added overloads for methods with a `name` argument to also include a `NamedWaitHandleOptions options` argument. The `CurrentUserOnly` option indicates whether the object should be limited in access to the current user. The `CurrentSessionOnly` option indicates whether the object object is intended to be used only within the current session (an alternative to the name prefixes, such as `Global\`). The default value for `NamedWaitHandleOptions` has `CurrentUserOnly=true` and `CurrentSessionOnly=true`.
- On Unixes, named semaphores and events are not supported. Named mutexes are have a functional implementation on Unixes in CoreCLR. NativeAOT and Mono on Unixes use an incomplete/temporary implementation where named mutexes are just process-local mutexes stored in a dictionary keyed by the name and can't be used to synchronize between processes. This change only briefly extends the NativeAOT/Mono implementation to add another prefix to the name when `CurrentUserOnly=true`. Sharing the CoreCLR Unix named mutex implementation with NativeAOT/Mono is left to a separate change. Most of what is described below when `CurrentUserOnly=true` on Unixes refers to the CoreCLR implementation.
- The plan is to also deprecate the APIs with a `name` argument but without an `options` argument in a separate change
- API review: #102682 (comment)
### Windows with `CurrentUserOnly=true`
When creating a named mutex, a security descriptor is created and assigned to the object.
- The owner and group are set to the current user
- The DACL has two ACEs:
- One ACE allows the current user the relevant access rights
- Another ACE allows the `BUILTIN\Administrators` group the `READ_CONTROL` access right to enable reading the security info for diagnostic purposes
- The SACL has a mandatory label ACE
- The access policy prevents principals with an integrity level lower than the object from opening the object
- The integrity level assigned to the object is the same as what would be assigned by the system by default
- When opening a named mutex, the owner and DACL are verified to see if they are as expected, and if not, a `WaitHandleCannotBeOpenedException` is thrown
- Access controls are set when creating an object and checked when opening an object. Once a handle to the object is obtained, typical synchronization operations may not do further access checks. It's up to the caller to be careful about how the handle to the object is passed around.
### Unixes with `CurrentUserOnly=true`
- Files relevant to named mutexes (shared memory and lock files) go under `/tmp/.dotnet-uidN/` where `N` is the effective user ID
- `/tmp/` (or equivalent) was chosen mainly for the automatic cleanup, as the number of files can add up in cases where mutexes are not disposed, particularly when randomly generated names are used upon each invocation of a process. Due to the use of a global location `/tmp/` or equivalent, it would be possible for a user to deny access to the `.dotnet-uidN` directory of a different user if the directory hadn't been created yet. An alternative considered was to use the home directory and introduce some kind of periodic cleanup strategy, but there are also other tradeoffs.
- `/tmp/` or equivalent must either have the sticky bit, or it must be owned by the current user and without write access for any other user. Otherwise, an exception is thrown.
- Permissions of the `/tmp/.dotnet-uidN/` directory and files/directories under it are limited in access to the current user
- When opening a named mutex, the owner and permissions of relevant files/directories are verified to see if they are as expected, and if not, an exception is thrown
- Access controls are set when creating an object and checked when opening an object. Once a handle to the object is obtained, typical synchronization operations may not do further access checks. It's up to the caller to be careful about how the handle to the object is passed around.
### Namespaces
- On Windows, there is no namespace for kernel objects for each user. `CurrentSessionOnly=true` is close, but it is possible for multiple users to be running code simultaneously in the same session. There is a global namespace, and a namespace per session. When `CurrentUserOnly=true`, callers may need to ensure that the name used is distinguished for different users.
- On Unixes, a different directory tree is used when `CurrentUserOnly=true`, so each user has a separate namespace for objects, including for session-scoped and session-unscoped objects.
<value>An object with the specified name '{0}' exists and can't be opened because it's not compatible with the specified option 'CurrentUserOnly = true'.</value>
0 commit comments