@@ -63,6 +63,7 @@ DWORD SharedMemoryException::GetErrorCode() const
63
63
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
64
64
// SharedMemoryHelpers
65
65
66
+ const mode_t SharedMemoryHelpers::PermissionsMask_CurrentUser_ReadWrite = S_IRUSR | S_IWUSR;
66
67
const mode_t SharedMemoryHelpers::PermissionsMask_CurrentUser_ReadWriteExecute = S_IRUSR | S_IWUSR | S_IXUSR;
67
68
const mode_t SharedMemoryHelpers::PermissionsMask_AllUsers_ReadWrite =
68
69
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
@@ -97,13 +98,22 @@ SIZE_T SharedMemoryHelpers::AlignUp(SIZE_T value, SIZE_T alignment)
97
98
bool SharedMemoryHelpers::EnsureDirectoryExists (
98
99
const char *path,
99
100
bool isGlobalLockAcquired,
101
+ bool hasCurrentUserAccessOnly,
102
+ bool setStickyFlag,
100
103
bool createIfNotExist,
101
104
bool isSystemDirectory)
102
105
{
103
106
_ASSERTE (path != nullptr );
104
107
_ASSERTE (!(isSystemDirectory && createIfNotExist)); // should not create or change permissions on system directories
105
108
_ASSERTE (SharedMemoryManager::IsCreationDeletionProcessLockAcquired ());
106
109
_ASSERTE (!isGlobalLockAcquired || SharedMemoryManager::IsCreationDeletionFileLockAcquired ());
110
+ _ASSERTE (!(setStickyFlag && hasCurrentUserAccessOnly)); // Sticky bit doesn't make sense with current user access only
111
+
112
+ mode_t mode = hasCurrentUserAccessOnly ? PermissionsMask_CurrentUser_ReadWriteExecute : PermissionsMask_AllUsers_ReadWriteExecute;
113
+ if (setStickyFlag)
114
+ {
115
+ mode |= S_ISVTX;
116
+ }
107
117
108
118
// Check if the path already exists
109
119
struct stat statInfo;
@@ -124,11 +134,11 @@ bool SharedMemoryHelpers::EnsureDirectoryExists(
124
134
125
135
if (isGlobalLockAcquired)
126
136
{
127
- if (mkdir (path, PermissionsMask_AllUsers_ReadWriteExecute ) != 0 )
137
+ if (mkdir (path, mode ) != 0 )
128
138
{
129
139
throw SharedMemoryException (static_cast <DWORD>(SharedMemoryError::IO));
130
140
}
131
- if (chmod (path, PermissionsMask_AllUsers_ReadWriteExecute ) != 0 )
141
+ if (chmod (path, mode ) != 0 )
132
142
{
133
143
rmdir (path);
134
144
throw SharedMemoryException (static_cast <DWORD>(SharedMemoryError::IO));
@@ -143,7 +153,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists(
143
153
{
144
154
throw SharedMemoryException (static_cast <DWORD>(SharedMemoryError::IO));
145
155
}
146
- if (chmod (tempPath, PermissionsMask_AllUsers_ReadWriteExecute ) != 0 )
156
+ if (chmod (tempPath, mode ) != 0 )
147
157
{
148
158
rmdir (tempPath);
149
159
throw SharedMemoryException (static_cast <DWORD>(SharedMemoryError::IO));
@@ -183,13 +193,18 @@ bool SharedMemoryHelpers::EnsureDirectoryExists(
183
193
// For non-system directories (such as gSharedFilesPath/SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME),
184
194
// require sufficient permissions for all users and try to update them if requested to create the directory, so that
185
195
// shared memory files may be shared by all processes on the system.
186
- if ((statInfo.st_mode & PermissionsMask_AllUsers_ReadWriteExecute ) == PermissionsMask_AllUsers_ReadWriteExecute )
196
+ if ((statInfo.st_mode & mode ) == mode )
187
197
{
188
198
return true ;
189
199
}
190
- if (!createIfNotExist || chmod (path, PermissionsMask_AllUsers_ReadWriteExecute ) != 0 )
200
+ if (!createIfNotExist || chmod (path, mode ) != 0 )
191
201
{
192
- throw SharedMemoryException (static_cast <DWORD>(SharedMemoryError::IO));
202
+ // We were not asked to create the path or we weren't able to set the new permissions.
203
+ // As a last resort, check that at least the current user has full access.
204
+ if ((statInfo.st_mode & PermissionsMask_CurrentUser_ReadWriteExecute) != PermissionsMask_CurrentUser_ReadWriteExecute)
205
+ {
206
+ throw SharedMemoryException (static_cast <DWORD>(SharedMemoryError::IO));
207
+ }
193
208
}
194
209
return true ;
195
210
}
@@ -239,7 +254,7 @@ int SharedMemoryHelpers::OpenDirectory(LPCSTR path)
239
254
return fileDescriptor;
240
255
}
241
256
242
- int SharedMemoryHelpers::CreateOrOpenFile (LPCSTR path, bool createIfNotExist, bool *createdRef)
257
+ int SharedMemoryHelpers::CreateOrOpenFile (LPCSTR path, bool createIfNotExist, bool isSessionScope, bool *createdRef)
243
258
{
244
259
_ASSERTE (path != nullptr );
245
260
_ASSERTE (path[0 ] != ' \0 ' );
@@ -269,12 +284,13 @@ int SharedMemoryHelpers::CreateOrOpenFile(LPCSTR path, bool createIfNotExist, bo
269
284
270
285
// File does not exist, create the file
271
286
openFlags |= O_CREAT | O_EXCL;
272
- fileDescriptor = Open (path, openFlags, PermissionsMask_AllUsers_ReadWrite);
287
+ mode_t mode = isSessionScope ? PermissionsMask_CurrentUser_ReadWrite : PermissionsMask_AllUsers_ReadWrite;
288
+ fileDescriptor = Open (path, openFlags, mode);
273
289
_ASSERTE (fileDescriptor != -1 );
274
290
275
291
// The permissions mask passed to open() is filtered by the process' permissions umask, so open() may not set all of
276
292
// the requested permissions. Use chmod() to set the proper permissions.
277
- if (chmod (path, PermissionsMask_AllUsers_ReadWrite ) != 0 )
293
+ if (chmod (path, mode ) != 0 )
278
294
{
279
295
CloseFile (fileDescriptor);
280
296
unlink (path);
@@ -655,7 +671,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen(
655
671
SharedMemoryHelpers::VerifyStringOperation (SharedMemoryManager::CopySharedMemoryBasePath (filePath));
656
672
SharedMemoryHelpers::VerifyStringOperation (filePath.Append (' /' ));
657
673
SharedMemoryHelpers::VerifyStringOperation (id.AppendSessionDirectoryName (filePath));
658
- if (!SharedMemoryHelpers::EnsureDirectoryExists (filePath, true /* isGlobalLockAcquired */ , createIfNotExist))
674
+ if (!SharedMemoryHelpers::EnsureDirectoryExists (filePath, true /* isGlobalLockAcquired */ , id. IsSessionScope (), false /* setStickyFlag */ , createIfNotExist))
659
675
{
660
676
_ASSERTE (!createIfNotExist);
661
677
return nullptr ;
@@ -668,7 +684,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen(
668
684
SharedMemoryHelpers::VerifyStringOperation (filePath.Append (id.GetName (), id.GetNameCharCount ()));
669
685
670
686
bool createdFile;
671
- int fileDescriptor = SharedMemoryHelpers::CreateOrOpenFile (filePath, createIfNotExist, &createdFile);
687
+ int fileDescriptor = SharedMemoryHelpers::CreateOrOpenFile (filePath, createIfNotExist, id. IsSessionScope (), &createdFile);
672
688
if (fileDescriptor == -1 )
673
689
{
674
690
_ASSERTE (!createIfNotExist);
@@ -1117,17 +1133,23 @@ void SharedMemoryManager::AcquireCreationDeletionFileLock()
1117
1133
if (!SharedMemoryHelpers::EnsureDirectoryExists (
1118
1134
*gSharedFilesPath ,
1119
1135
false /* isGlobalLockAcquired */ ,
1136
+ false /* hasCurrentUserAccessOnly */ ,
1137
+ true /* setStickyFlag */ ,
1120
1138
false /* createIfNotExist */ ,
1121
1139
true /* isSystemDirectory */ ))
1122
1140
{
1123
1141
throw SharedMemoryException (static_cast <DWORD>(SharedMemoryError::IO));
1124
1142
}
1125
1143
SharedMemoryHelpers::EnsureDirectoryExists (
1126
1144
*s_runtimeTempDirectoryPath,
1127
- false /* isGlobalLockAcquired */ );
1145
+ false /* isGlobalLockAcquired */ ,
1146
+ false /* hasCurrentUserAccessOnly */ ,
1147
+ true /* setStickyFlag */ );
1128
1148
SharedMemoryHelpers::EnsureDirectoryExists (
1129
1149
*s_sharedMemoryDirectoryPath,
1130
- false /* isGlobalLockAcquired */ );
1150
+ false /* isGlobalLockAcquired */ ,
1151
+ false /* hasCurrentUserAccessOnly */ ,
1152
+ true /* setStickyFlag */ );
1131
1153
s_creationDeletionLockFileDescriptor = SharedMemoryHelpers::OpenDirectory (*s_sharedMemoryDirectoryPath);
1132
1154
if (s_creationDeletionLockFileDescriptor == -1 )
1133
1155
{
0 commit comments