Add permission checks to DeleteSaveDataFileSystem

This commit is contained in:
Alex Barney 2020-08-25 23:03:48 -07:00
parent 1f25b87d20
commit 4552a2d94f
4 changed files with 38 additions and 20 deletions

View file

@ -190,17 +190,27 @@ namespace LibHac.FsSrv
private Result DeleteSaveDataFileSystemImpl(SaveDataSpaceId spaceId, ulong saveDataId) private Result DeleteSaveDataFileSystemImpl(SaveDataSpaceId spaceId, ulong saveDataId)
{ {
Result rc = OpenSaveDataIndexerAccessor(out SaveDataIndexerAccessor accessor, spaceId); Result rc = GetProgramInfo(out ProgramInfo programInfo);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
using (accessor) SaveDataIndexerAccessor accessor = null;
try
{ {
SaveDataType saveType;
if (saveDataId == FileSystemServer.SaveIndexerId) if (saveDataId == FileSystemServer.SaveIndexerId)
{ {
// missing: This save can only be deleted by the FS process itself if (!IsCurrentProcess(CurrentProcess))
return ResultFs.PermissionDenied.Log();
saveType = SaveDataType.System;
} }
else else
{ {
rc = OpenSaveDataIndexerAccessor(out accessor, spaceId);
if (rc.IsFailure()) return rc;
if (spaceId != SaveDataSpaceId.ProperSystem && spaceId != SaveDataSpaceId.SafeMode) if (spaceId != SaveDataSpaceId.ProperSystem && spaceId != SaveDataSpaceId.SafeMode)
{ {
rc = accessor.Indexer.GetValue(out SaveDataIndexerValue value, saveDataId); rc = accessor.Indexer.GetValue(out SaveDataIndexerValue value, saveDataId);
@ -214,13 +224,17 @@ namespace LibHac.FsSrv
if (key.Type == SaveDataType.System || key.Type == SaveDataType.SystemBcat) if (key.Type == SaveDataType.System || key.Type == SaveDataType.SystemBcat)
{ {
// Check if permissions allow deleting system save data if (!programInfo.AccessControl.CanCall(OperationType.DeleteSystemSaveData))
return ResultFs.PermissionDenied.Log();
} }
else else
{ {
// Check if permissions allow deleting save data if (!programInfo.AccessControl.CanCall(OperationType.DeleteSaveData))
return ResultFs.PermissionDenied.Log();
} }
saveType = key.Type;
rc = accessor.Indexer.SetState(saveDataId, SaveDataState.Creating); rc = accessor.Indexer.SetState(saveDataId, SaveDataState.Creating);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -228,11 +242,12 @@ namespace LibHac.FsSrv
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
} }
rc = DeleteSaveDataFileSystemImpl2(spaceId, saveDataId); rc = DeleteSaveDataFileSystemImpl2(spaceId, saveDataId, saveType, false);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
if (saveDataId != FileSystemServer.SaveIndexerId) if (saveDataId != FileSystemServer.SaveIndexerId)
{ {
// ReSharper disable once PossibleNullReferenceException
rc = accessor.Indexer.Delete(saveDataId); rc = accessor.Indexer.Delete(saveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -242,12 +257,14 @@ namespace LibHac.FsSrv
return Result.Success; return Result.Success;
} }
finally { accessor?.Dispose(); }
} }
private Result DeleteSaveDataFileSystemImpl2(SaveDataSpaceId spaceId, ulong saveDataId) // ReSharper disable once UnusedParameter.Local
private Result DeleteSaveDataFileSystemImpl2(SaveDataSpaceId spaceId, ulong saveDataId, SaveDataType type, bool shouldWipe)
{ {
// missing: Check extra data flags for this value. Bit 3 // missing: Check extra data flags for this value. Bit 3
bool doSecureDelete = false; bool doSecureDelete = shouldWipe;
Result rc = FsProxyCore.DeleteSaveDataMetaFiles(saveDataId, spaceId); Result rc = FsProxyCore.DeleteSaveDataMetaFiles(saveDataId, spaceId);
if (rc.IsFailure() && !ResultFs.PathNotFound.Includes(rc)) if (rc.IsFailure() && !ResultFs.PathNotFound.Includes(rc))
@ -275,7 +292,6 @@ namespace LibHac.FsSrv
using (accessor) using (accessor)
{ {
rc = accessor.Indexer.GetValue(out SaveDataIndexerValue value, saveDataId); rc = accessor.Indexer.GetValue(out SaveDataIndexerValue value, saveDataId);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
@ -326,6 +342,8 @@ namespace LibHac.FsSrv
SaveDataIndexerAccessor accessor = null; SaveDataIndexerAccessor accessor = null;
// Missing permission checks
try try
{ {
if (attribute.StaticSaveDataId == FileSystemServer.SaveIndexerId) if (attribute.StaticSaveDataId == FileSystemServer.SaveIndexerId)
@ -399,7 +417,7 @@ namespace LibHac.FsSrv
{ {
if (!ResultFs.PathAlreadyExists.Includes(rc)) return rc; if (!ResultFs.PathAlreadyExists.Includes(rc)) return rc;
rc = DeleteSaveDataFileSystemImpl2(creationInfo.SpaceId, saveDataId); rc = DeleteSaveDataFileSystemImpl2(creationInfo.SpaceId, saveDataId, attribute.Type, false);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
rc = FsProxyCore.CreateSaveDataFileSystem(saveDataId, ref attribute, ref creationInfo, SaveDataRootPath, rc = FsProxyCore.CreateSaveDataFileSystem(saveDataId, ref attribute, ref creationInfo, SaveDataRootPath,
@ -455,7 +473,7 @@ namespace LibHac.FsSrv
// Revert changes if an error happened in the middle of creation // Revert changes if an error happened in the middle of creation
if (isDeleteNeeded) if (isDeleteNeeded)
{ {
DeleteSaveDataFileSystemImpl2(creationInfo.SpaceId, saveDataId).IgnoreResult(); DeleteSaveDataFileSystemImpl2(creationInfo.SpaceId, saveDataId, attribute.Type, false).IgnoreResult();
if (accessor != null && saveDataId != FileSystemServer.SaveIndexerId) if (accessor != null && saveDataId != FileSystemServer.SaveIndexerId)
{ {
@ -1253,6 +1271,13 @@ namespace LibHac.FsSrv
return FsProxyCore.ProgramRegistry.GetProgramInfo(out programInfo, CurrentProcess); return FsProxyCore.ProgramRegistry.GetProgramInfo(out programInfo, CurrentProcess);
} }
internal bool IsCurrentProcess(ulong processId)
{
ulong currentId = Hos.Os.GetCurrentProcessId().Value;
return processId == currentId;
}
private static bool IsSystemSaveDataId(ulong id) private static bool IsSystemSaveDataId(ulong id)
{ {
return (long)id < 0; return (long)id < 0;

View file

@ -96,13 +96,6 @@ namespace LibHac.FsSrv
return new ProgramRegistryImpl(FsProxyCore.Config.ProgramRegistryServiceImpl); return new ProgramRegistryImpl(FsProxyCore.Config.ProgramRegistryServiceImpl);
} }
internal bool IsCurrentProcess(ulong processId)
{
ulong currentId = Hos.Os.GetCurrentProcessId().Value;
return processId == currentId;
}
private class FileSystemProxyService : IServiceObject private class FileSystemProxyService : IServiceObject
{ {
private readonly FileSystemServer _server; private readonly FileSystemServer _server;

View file

@ -167,7 +167,7 @@ namespace LibHac.FsSrv.Impl
ReadOnlySpan<byte> accessControlDescriptor) ReadOnlySpan<byte> accessControlDescriptor)
{ {
ProcessId = 0; ProcessId = 0;
AccessControl = new AccessControl(fsServer, accessControlData, accessControlDescriptor); AccessControl = new AccessControl(fsServer, accessControlData, accessControlDescriptor, ulong.MaxValue);
ProgramId = default; ProgramId = default;
StorageId = 0; StorageId = 0;
} }

View file

@ -21,7 +21,7 @@ namespace LibHac.Tests.Fs.FileSystemClientTests
var horizon = new Horizon(new StopWatchTimeSpanGenerator(), config); var horizon = new Horizon(new StopWatchTimeSpanGenerator(), config);
HorizonClient horizonClient = horizon.CreateHorizonClient(); HorizonClient horizonClient = horizon.CreatePrivilegedHorizonClient();
return horizonClient.Fs; return horizonClient.Fs;
} }