A customer reported that their call to SetFileValidData
was failing with ERROR_PRIVILEGE_NOT_HELD
despite the fact that they held the privilege whose name is defined by the symbol SE_MANAGE_VOLUME_NAME
. (Note that the “name” in “manage volume name” doesn’t mean that you are managing the name of the volume; rather it means “This is the name of the privilege for managing volumes.”)
The customer was kind enough to reduce the problem to a simple program:
#include <windows.h> int main(int argc, char** argv) { // This succeeds HANDLE h = CreateFileW(L"test", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, nullptr); LARGE_INTEGER newSize; newSize.QuadPart = 256 * 1024 * 10; // This succeeds SetFilePointerEx(h, newSize, nullptr, FILE_BEGIN); // This succeeds SetEndOfFile(h); HANDLE hToken; // This succeeds OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); // This succeeds SetPrivilege(hToken, SE_MANAGE_VOLUME_NAME, TRUE); // This succeeds CloseHandle(hToken); // This fails with ERROR_PRIVILEGE_NOT_HELD SetFileValidData(h, newSize.QuadPart); CloseHandle(h); return 0; }
The answer is hidden in the documentation for the SetFileValidData
function:
A caller must have the SE_MANAGE_VOLUME_NAME privilege enabled when opening a file initially.
The program didn’t enable the manage volume privilege until after it had already created the file handle.
This requirement that the privilege be active at the point the handle is created becomes less surprising when you realize that the general policy for kernel object security is that security is checked at the time handles are created, rather than when they are used.
0 comments