I have a problem related to file management done by a service application. My problem is that users are able to move files to the recycle bin for which I've created a hardlink, and once they do this, I loose the ability to list the hardlinks available.
This appears to only happen when the removed hardlink file sits inside the $RECYCLER
folder but not on a folder with similar permissions on the same disk.
To replicate my problem assume one has a user account named Service
with a suitable password.
On the current user account:
md C:\tmp
echo CONTENTS>C:\tmp\1
fsutil hardlink create C:\tmp\2 C:\tmp\1
That would have created a file named C:\tmp\1
and a hardlink to it named C:\tmp\2
.
Now if you runas
another terminal with user Service
you can:
fsutil hardlink list C:\tmp\1
\tmp\1
\tmp\2
That works fine.
Now if you (as the original user) move the 2
file to the recycle bin, you cannot access the files as Service
.
type C:\tmp\1
Access is denied.
fsutil hardlink list C:\tmp\1
Error: Access is denied.
That's because Explorer will have changed the DACL on the file to a restrictive one where only the current user, SYSTEM
and an Administrator have access to the file.
If you do a icacls C:\tmp\1 /reset
as the original user, now you can access the contents of the file as Service
:
type C:\tmp\1
CONTENTS
But if you try to list the hardlinks, it will show you the first link and an access denied error:
fsutil hardlink list C:\tmp\1
\tmp\1
Error: Access is denied.
If you list the hardlinks on the file as the original user, you get to know the recycle bin path of the original file:
fsutil hardlink list C:\tmp\1
\tmp\1
\$Recycle.Bin\S-1-5-21-111111111-2222222222-3333333333-1002\$R1GX1HN
And if you move that file to another (as the original user) folder:
md C:\tmp2
move \$Recycle.Bin\S-1-5-21-111111111-2222222222-3333333333-1002\$R1GX1HN C:\tmp2
Now as Service
you can list all the hardlinks:
fsutil hardlink list C:\tmp\1
\tmp\1
\tmp2\$R1GX1HN
Any idea why this may be happening?
Does this have anything to do with Mandatory Integrity Control?
As explained in the comments by @Eryk Sun, the problem is related to the way hardlinks are reported by Win32 API.
It appears that fsutil
uses FindFirstFileName
and FindNextFileName
functions, both of which use NtQueryInformationFile
which in turn returns a structure with entries of type FILE_LINK_ENTRY_INFORMATION
which have the hardlink name and the parent folder NTFS ID
.
The problem manifests itself when the caller does not have permission to open the containing folder to get its name (probably using OpenFileById
and GetFinalPathByHandle
).