--- a/kernel/eka/debug/securityServer/src/c_security_svr_session.cpp Wed Aug 18 11:08:29 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2593 +0,0 @@
-// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// Provides the debug security server session implementation.
-//
-//
-
-/**
- @file
- @internalTechnology
- @released
-*/
-
-// Needed so we get the text strings for capabilities
-#define __INCLUDE_CAPABILITY_NAMES__
-
-#include <e32std.h>
-#include <e32std_private.h>
-#include <e32btrace.h>
-#include <d32btrace.h>
-#include <e32base.h>
-#include <e32base_private.h>
-#include <e32uid.h>
-#include <f32file.h>
-#include <e32capability.h>
-#include <rm_debug_api.h>
-
-// required for direct parsing of e32image/tromimage headers
-#include <f32image.h>
-#include <e32rom.h>
-
-//added for direct access to media driver
-#include <partitions.h>
-#include <ftlcontrolio.h>
-
-#include "c_security_svr_session.h"
-#include "c_security_svr_server.h"
-#include "c_security_svr_async.h"
-#include "rm_debug_logging.h"
-#ifdef _DEBUG
-#include "low_mem_requests.h"
-#endif
-
-using namespace Debug;
-
-CSecuritySvrSession::CSecuritySvrSession()
- : iDebugAgentProcessIdStored(EFalse),
- iDebugAgentProcessId(0),
- iServerNotified(EFalse),
- iCrashConnected(EFalse)
- {
- // Ensure that this debug agent has no target capability override
- // by default
- iOEMDebugCapabilities.SetEmpty();
- }
-
-void CSecuritySvrSession::ServiceError(const RMessage2 &aMessage, TInt aError)
- {
- LOG_MSG2("CSecuritySvrSession::ServiceError(), aError: %d\n", aError);
-
- //insert ending heap markers
- HeapWatcher(aMessage.Function(), EFalse);
-
- aMessage.Complete(aError);
- }
-
-/**
-Called by the client/server framework as part of session creation.
-
-Notifies the server that a session is being created
-*/
-void CSecuritySvrSession::CreateL()
- {
- LOG_MSG("CSecuritySvrSession::CreateL()\n");
-
- //notify the server that the session has been opened
- Server().SessionOpened();
- iServerNotified = ETrue;
- }
-
-/**
- Returns a reference to the DSS
-
- @return a reference to the DSS
- */
-CSecuritySvrServer& CSecuritySvrSession::Server() const
- {
- return *static_cast<CSecuritySvrServer*>(const_cast<CServer2*>(CSession2::Server()));
- }
-
-/**
-Session destructor. Performs necessary cleanup and notifies the server that the
-session is being closed
-*/
-CSecuritySvrSession::~CSecuritySvrSession()
- {
- LOG_MSG("CSecuritySvrSession::~CSecuritySvrSession!()\n");
-
- //forced detachment if attached to processes
- if(iDebugAgentProcessIdStored)
- {
- // Cancel any outstanding async objects.
- iAsyncHandlers.ResetAndDestroy();
-
- // Inform the device driver of the agent detach.
- Server().iKernelDriver.DetachAgent(iDebugAgentProcessId.Id());
-
- LOG_MSG( "CSecuritySvrSession::~CSecuritySvrSession() : -> securityServer.DetachAllProcesses()\n" );
- Server().DetachAllProcesses(iDebugAgentProcessId);
- }
-
- //notify the server that the session has closed
- if(iServerNotified)
- {
- Server().SessionClosed();
- }
- }
-
-void CSecuritySvrSession::ConstructL()
- {
- // nothing to do
- }
-
-/**
- Used to insert heap checking markers.
-
- @param aFunction The function that heap markers should be added for
- @param aEntry if ETrue indicates that heap checking is starting, if EFalse
- that heap checking is ending.
- */
-void CSecuritySvrSession::HeapWatcher(const TUint32 aFunction, const TBool aEntry) const
- {
- switch(aFunction)
- {
- case EDebugServAttachExecutable:
- return;
- case EDebugServDetachExecutable:
- return;
- case EDebugServSuspendThread:
- return;
- case EDebugServResumeThread:
- return;
-// used for out-of-memory testing in debug mode
-#ifdef _DEBUG
- // start heap marking in on entry, do nothing on exit
- case EDebugServMarkHeap:
- {
- if(aEntry)
- {
- __UHEAP_MARK;
- }
- return;
- }
- // stop heap marking on exit, do nothing on entry
- case EDebugServMarkEnd:
- {
- if(!aEntry)
- {
- __UHEAP_MARKEND;
- }
- return;
- }
-#endif
- default:
- if(aEntry)
- {
- __UHEAP_MARK;
- }
- else
- {
- __UHEAP_MARKEND;
- }
- return;
- }
- }
-
-void CSecuritySvrSession::ServiceL(const RMessage2& aMessage)
-//
-// Session service handler
-//
- {
- //insert starting heap markers
- HeapWatcher(aMessage.Function(), ETrue);
-
- switch(aMessage.Function())
- {
- case EDebugServResumeThread:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServResumeThread\n" );
- ResumeThreadL(aMessage);
- break;
-
- case EDebugServSuspendThread:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSuspendThread\n" );
- SuspendThreadL(aMessage);
- break;
-
- case EDebugServReadMemory:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServReadMemory\n" );
- ReadMemoryL(aMessage);
- break;
-
- case EDebugServWriteMemory:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServWriteMemory\n" );
- WriteMemoryL(aMessage);
- break;
-
- case EDebugServSetBreak:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSetBreak\n" );
- SetBreakL(aMessage);
- break;
-
- case EDebugServClearBreak:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServClearBreak\n" );
- ClearBreakL(aMessage);
- break;
-
- case EDebugServModifyBreak:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServModifyBreak\n" );
- ModifyBreakL(aMessage);
- break;
-
- case EDebugServModifyProcessBreak:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServModifyProcessBreak\n" );
- ModifyProcessBreakL(aMessage);
- break;
-
- case EDebugServBreakInfo:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServBreakInfo\n" );
- BreakInfoL(aMessage);
- break;
-
- case EDebugServReadRegisters:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServReadRegisters\n" );
- ReadRegistersL(aMessage);
- break;
-
- case EDebugServWriteRegisters:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServWriteRegisters\n" );
- WriteRegistersL(aMessage);
- break;
-
- case EDebugServGetEvent:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetEvent\n" );
- GetEventL(aMessage);
- break;
-
- case EDebugServCancelGetEvent:
- CancelGetEventL(aMessage);
- break;
-
- case EDebugServAttachExecutable:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServAttachExecutable\n" );
- AttachProcessL(aMessage);
- break;
-
- case EDebugServDetachExecutable:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServDetachExecutable\n" );
- DetachProcessL(aMessage);
- break;
-
- case EDebugServGetDebugFunctionalityBufSize:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetDebugFunctionalityBufSize\n" );
- GetDebugFunctionalityBufSizeL(aMessage);
- break;
-
- case EDebugServGetDebugFunctionality:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetDebugFunctionality\n" );
- GetDebugFunctionalityL(aMessage);
- break;
-
- case EDebugServSetEventAction:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSetEventAction\n" );
- SetEventActionL(aMessage);
- break;
-
- case EDebugServGetList:
- LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetList\n" );
- GetListL(aMessage);
- break;
-
- case EDebugServStep:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServStep\n");
- StepL(aMessage);
- break;
-
- case EDebugServSetProcessBreak:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServSetProcessBreak\n");
- SetProcessBreakL(aMessage);
- break;
-
- case EDebugServProcessBreakInfo:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServProcessBreakInfo\n");
- ProcessBreakInfoL(aMessage);
- break;
-
- case EDebugServKillProcess:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServKillProcess\n");
- KillProcessL(aMessage);
- break;
-
-#ifdef _DEBUG
- case EDebugServMarkHeap:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServMarkHeap\n");
- // all taken care of in HeapWatcher
- aMessage.Complete(KErrNone);
- break;
-
- case EDebugServMarkEnd:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServMarkEnd\n");
- // all taken care of in HeapWatcher
- aMessage.Complete(KErrNone);
- break;
-
- case EDebugServFailAlloc:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServFailAlloc\n");
- DoFailAlloc(aMessage);
- break;
-#endif
- case EDebugServReadCrashFlash:
- ReadCrashLogL(aMessage);
- break;
- case EDebugServWriteCrashFlash:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServWriteCrashFlash\n");
- WriteCrashConfigL(aMessage);
- break;
- case EDebugServEraseCrashFlash:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServEraseCrashFlash\n");
- EraseCrashLogL(aMessage);
- break;
- case EDebugServEraseEntireCrashFlash:
- LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServEraseEntireCrashFlash\n");
- EraseEntireCrashLogL(aMessage);
- break;
- default:
- LOG_MSG( "CSecuritySvrSession::ServiceL() Unknown request, calling User::Leave(KErrNotSupported);\n" );
- User::Leave(KErrNotSupported);
- break;
- }
-
- //insert ending heap markers
- HeapWatcher(aMessage.Function(), EFalse);
- }
-
-#ifdef _DEBUG
-/**
- Used to control heap failure in debug mode.
- @param aMessage If aMessage.Int0 is non-zero then heap will be set to fail on that allocation.
- If aMessage.Int0 is zero then the heap failure count is reset
- */
-void CSecuritySvrSession::DoFailAlloc(const RMessage2& aMessage)
- {
- TInt count = aMessage.Int0();
- if(count == 0)
- {
- __UHEAP_RESET;
- }
- else
- {
- __UHEAP_FAILNEXT(count);
- }
- aMessage.Complete(KErrNone);
- }
-#endif
-
-/**
-Suspends execution of the specified thread.
-
-@param aMessage contains an integer representation of the target thread's
- thread ID at offset 0.
-
-@leave KErrPermissionDenied if security check fails or KErrArgument if the
- thread does not exist
-*/
-void CSecuritySvrSession::SuspendThreadL(const RMessage2& aMessage)
- {
-
- LOG_MSG( "CSecuritySvrSession::SuspendThreadL()\n" );
-
- //get thread ID
- TThreadId threadId = ReadTThreadIdL(aMessage, 0);
- //check attached
- CheckAttachedL(threadId, aMessage, EFalse);
-
- //security check passed so can perform actions
- User::LeaveIfError(Server().iKernelDriver.SuspendThread(threadId));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-Resumes execution of the specified thread.
-
-@param aMessage contains an integer representation of the target thread's
- thread ID at offset 0.
-
-@leave KErrPermissionDenied if security check fails or KErrArgument if the
- thread does not exist
-*/
-void CSecuritySvrSession::ResumeThreadL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::ResumeThreadL()\n" );
-
- //get thread ID
- TThreadId threadId = ReadTThreadIdL(aMessage, 0);
-
- //check attached
- CheckAttachedL(threadId, aMessage, EFalse);
-
- //security check passed so can perform actions
- TInt err = Server().iKernelDriver.ResumeThread(threadId);
- aMessage.Complete(err);
- }
-
-void CSecuritySvrSession::GetDebugFunctionalityBufSizeL(const RMessage2& aMessage)
-//
-// Retrieve size of functionality data buffer in bytes which must be allocated
-// by the client
-//
- {
- LOG_MSG( "CSecuritySvrSession::GetDebugFunctionalityBufSizeL()\n" );
-
- TUint32 result = 0;
- // Get Buffer size from the kernel driver
- User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionalityBufSize(result));
-
- TPtr8 stuff((TUint8*)&result,4, 4);
-
- aMessage.WriteL(0,stuff);
-
- aMessage.Complete(KErrNone);
- }
-
-void CSecuritySvrSession::GetDebugFunctionalityL(const RMessage2& aMessage)
-//
-// Retrieve the functionality data and place it in a buffer
-// allocated by the client.
-//
- {
- LOG_MSG( "CSecuritySvrSession::GetDebugFunctionalityL()\n" );
-
- TUint32 dfsize = 0;
-
- // Get Buffer size from the kernel driver
- User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionalityBufSize(dfsize));
-
- // Allocate space for the functionality data
- HBufC8* dftext = HBufC8::NewLC(dfsize);
-
- const TPtr8& dfPtr = dftext->Des();
-
- // Extract said data from the device driver
- User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionality((TDes8&)dfPtr));
-
- // Return data to client
- aMessage.WriteL(0,dfPtr);
-
- // Free buffer
- CleanupStack::PopAndDestroy(dftext);
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-Reads memory from a specified thread using the passed parameters. The user
-should ensure that the TPtr8 that is passed in has size greater than or equal
-to the size of the memory that is trying to be read.
-
-@param aMessage The RMessage2 object should be constructed as follows:
- * aMessage.Int0() is the thread ID of the target debug app
- * aMessage.Ptr1() is a TMemoryInfo object which contains the following:
- * the address of the memory to be read from the target debug thread
- * the size of the memory block to be read from the target debug thread
- * the access size to use
- * the endianess to interpret the data as
- * aMessage.Ptr2() is the address of the buffer in the debug agent thread
- that the data from the target debug app should be written into
-
-@leave KErrPermissionDenied if client is not attached to the target
- thread's process,
- KErrNoMemory if memory could not be allocated,
- KErrArgument if there are problems with the aMessage object,
- KErrBadHandle if the thread represented by aMessage.Ptr0() is invalid,
- an error value from CSecuritySvrSession::ValidateMemoryInfo if checking
- the memory attributes failed,
- or another of the system wide error codes
-*/
-void CSecuritySvrSession::ReadMemoryL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::ReadMemoryL()\n" );
-
- //get debug app thread ID
- TThreadId threadId = ReadTThreadIdL(aMessage, 0);
-
- CheckAttachedL(threadId, aMessage, ETrue);
-
- //create and initialise the memory info object
- TMemoryInfo targetMemory;
- TPtr8 targetMemoryPtr( (TUint8 *)&targetMemory, sizeof(TMemoryInfo) );
-
- aMessage.ReadL(1,targetMemoryPtr);
-
- //check memory info is acceptable
- ValidateMemoryInfoL(threadId, targetMemory, ETrue);
-
- RBuf8 data;
- data.CreateL(targetMemory.iSize);
- data.CleanupClosePushL();
-
- //fill buffer with data from target debug thread
- User::LeaveIfError(Server().iKernelDriver.ReadMemory(threadId, targetMemory.iAddress, targetMemory.iSize, data));
-
- //attempt to write the data from the target debug thread back to the agent
- aMessage.WriteL(2, data);
-
- //delete temporary buffer
- CleanupStack::PopAndDestroy(&data);
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-Writes memory to a specified thread using the passed parameters.
-
-@param aMessage The RMessage2 object should be constructed as follows:
- * aMessage.Ptr0() is the thread ID of the target debug app
- * aMessage.Ptr1() is a TMemoryInfo object which contains the following:
- * the address of the memory to be written to the target debug thread
- * the size of the memory block to be written to the target debug thread
- * the access size to use
- * the endianess to interpret the data as
- * aMessage.Ptr2() is the address of the buffer in the debug agent thread
- that the data to write to the target debug app should be read from
-
-@leave KErrPermissionDenied if client is not attached (actively) to the target
- thread's process,
- KErrNoMemory if memory could not be allocated,
- KErrArgument if there are problems with the aMessage object,
- KErrBadHandle if the thread represented by aMessage.Ptr0() is invalid,
- an error value from CSecuritySvrSession::ValidateMemoryInfo if checking
- the memory attributes failed,
- or another of the system wide error codes
-*/
-void CSecuritySvrSession::WriteMemoryL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::WriteMemoryL()\n" );
-
- //get debug app thread ID
- TThreadId threadId = ReadTThreadIdL(aMessage, 0);
-
- CheckAttachedL(threadId, aMessage, EFalse);
-
- //create and initialise the memory info object
- TMemoryInfo targetMemory;
- TPtr8 targetMemoryPtr( (TUint8 *)&targetMemory, sizeof(TMemoryInfo) );
-
- aMessage.ReadL(1,targetMemoryPtr);
-
- //check memory info is acceptable
- ValidateMemoryInfoL(threadId, targetMemory, EFalse);
-
- //create temporary buffer and read data from client
- RBuf8 data;
- data.CreateL(targetMemory.iSize);
- data.CleanupClosePushL();
-
- aMessage.ReadL(2, data);
-
- // what about telling the driver about endianess/access size?
- User::LeaveIfError(Server().iKernelDriver.WriteMemory(threadId, targetMemory.iAddress, targetMemory.iSize, data));
-
- //free temporary buffer
- CleanupStack::PopAndDestroy(&data);
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-@internalTechnology
-
-Notes: This call is used to set a thread specific breakpoint. Its input arguments
-are the thread id, address and architecture type of the breakpoint. It returns success
-or failure, and if successful, it sets the TBreakId in the Debug Agent to the
-breakpoint id by which it can be referenced in future calls to ModifyBreak,ClearBreak and
-BreakInfo.
-
-@param aMessage.Ptr0() - aThreadId is thread id of the target debug process
-@param aMessage.Ptr1() - Address of a TBreakInfo in the Debug Agent
-@param aMessage.Ptr2() - Address of a TBreakId in the Debug Agent
-@leave KErrPermissionDenied if the security check fails.
- KErrAlreadyExists if there is a breakpoint overlapping the desired address.
- KErrNotSupported if the architecture type is unrecognised.
- KErrNoMemory if there is no more memory to complete the operation.
- KErrArgument if the breakpoint address alignment is unsuitable for the requested
- breakpoint.
- KErrOverflow if there are too many breakpoints set.
-*/
-void CSecuritySvrSession::SetBreakL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::SetBreakL!()\n" );
-
- //get debug app thread ID
- TThreadId threadId = ReadTThreadIdL(aMessage, 0);
-
- //check that the agent has attached to the target process
- CheckAttachedL(threadId, aMessage, EFalse);
-
- //create and initialise the memory info object
- TBreakInfo breakInfo;
- TPtr8 breakInfoPtr( (TUint8 *)&breakInfo, sizeof(TBreakInfo) );
-
- aMessage.ReadL(1,breakInfoPtr);
-
- //set break in target app
- TBreakId breakId = 0;
- User::LeaveIfError(Server().iKernelDriver.SetBreak(breakId, threadId, breakInfo.iAddress, breakInfo.iArchitectureMode));
-
- //attempt to write the break id back to the debug agent
- WriteDataL(aMessage, 2, &breakId, sizeof(breakId));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-Clears a breakpoint previously set by a SetBreak() call.
-
-@param aMessage.Int0() - TBreakId of the breakpoint to be removed.
-*/
-void CSecuritySvrSession::ClearBreakL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::ClearBreakL()\n" );
-
- const TInt breakId = aMessage.Int0();
-
- // Check that the breakpoint exists
- TUint64 objectId;
- TUint32 address;
- TArchitectureMode mode;
- TBool threadSpecific = EFalse;
-
- User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,objectId,address,mode,threadSpecific));
-
- if(threadSpecific)
- {
- // Check that the debug agent is attached to the thread for which the
- // breakpoint is currently set.
- CheckAttachedL(TThreadId(objectId), aMessage, EFalse);
- }
- else
- {
- // Check that the debug agent is attached to the process for which the
- // breakpoint is currently set.
- CheckAttachedL(TProcessId(objectId), aMessage, EFalse);
- }
-
- // Finally clear the breakpoint
- User::LeaveIfError(Server().iKernelDriver.ClearBreak(breakId));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-@param aMessage.Int0() - Breakpoint Id of interest
-@param aMessage.Ptr1() - Address in Debug Agent to place threadId of the breakpoint
-@param aMessage.Ptr2() - Address in Debug Agent to place address of the breakpoint
-@param aMessage.Ptr3() - Address in Debug Agent to place the architecture mode of the breakpoint
-@leave Any error which may be returned by RSessionBase::SendReceive()
-*/
-void CSecuritySvrSession::BreakInfoL(const RMessage2& aMessage)
- {
- const TBreakId breakId = (TBreakId)aMessage.Int0();
-
- TThreadId threadId;
- TUint32 address;
- TArchitectureMode mode;
- TBool threadSpecific = ETrue;
-
- TUint64 threadIdData;
- User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,threadIdData,address,mode,threadSpecific));
-
- if(!threadSpecific)
- {
- User::Leave(KErrNotFound);
- }
-
- threadId = TThreadId(threadIdData);
-
- //check that the agent has attached to the target process
- CheckAttachedL(threadId, aMessage, EFalse);
-
- // return the threadId
- WriteDataL(aMessage, 1, &threadId, sizeof(threadId));
-
- // return the address
- WriteDataL(aMessage, 2, &address, sizeof(address));
-
- // return the mode
- WriteDataL(aMessage, 3, &mode, sizeof(mode));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-@internalTechnology
-
-Modify a previously set breakpoint.
-
-@param aMessage.Int0() - The breakpoint id of the breakpoint to modify
-@param aMessage.Ptr1() - The new Thread Id for the breakpoint
-@param aMessage.Int2() - The new virtual memory address for the breakpoint
-@param aMessage.Int3() - The new architecture mode for the breakpoint
-@return KErrNone if succesful. KErrPermissionDenied if the security check fails.
- KErrAlreadyExists if there is a breakpoint overlapping the desired address.
- KErrNotSupported if the architecture type is unrecognised.
- KErrNoMemory if there is no more memory to complete the operation.
- KErrArgument if the breakpoint address alignment is unsuitable for the requested
- breakpoint.
- KErrOverflow if there are too many breakpoints set.
-*/
-void CSecuritySvrSession::ModifyBreakL(const RMessage2& aMessage)
- {
- const TBreakId breakId = (TBreakId)aMessage.Int0();
- const TThreadId threadId = ReadTThreadIdL(aMessage, 1);
- const TUint32 address = aMessage.Int2();
- const TArchitectureMode mode = (TArchitectureMode)aMessage.Int3();
-
- // Get information on the breakpoint to check the security status
- TUint64 checkThreadId;
- TUint32 checkAddress;
- TArchitectureMode checkMode;
- TBool threadSpecific;
-
- User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,checkThreadId,checkAddress,checkMode,threadSpecific));
-
- // Security check that the thread Id is associated with the debug agent
-
- //check that the agent has attached to the target process
- CheckAttachedL(TThreadId(checkThreadId), aMessage, EFalse);
-
- // now check that the thread Id which is being set is permitted
- //check that the agent has attached to the target process
- CheckAttachedL(threadId, aMessage, EFalse);
-
- User::LeaveIfError(Server().iKernelDriver.ModifyBreak(breakId,threadId,address,mode));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-@internalTechnology
-
-Notes: This call is used to set a process wide breakpoint. Its input arguments
-are the process id, address and architecture type of the breakpoint. It returns success
-or failure, and if successful, it sets the TBreakId in the Debug Agent to the
-breakpoint id by which it can be referenced in future calls to ModifyBreak,ClearBreak and
-BreakInfo.
-
-@param aMessage.Ptr0() - aProcessId is process id of the target debug process
-@param aMessage.Ptr1() - Address of a TBreakInfo in the Debug Agent
-@param aMessage.Ptr2() - Address of a TBreakId in the Debug Agent
-@leave KErrPermissionDenied if the security check fails.
- KErrAlreadyExists if there is a breakpoint overlapping the desired address.
- KErrNotSupported if the architecture type is unrecognised.
- KErrNoMemory if there is no more memory to complete the operation.
- KErrArgument if the breakpoint address alignment is unsuitable for the requested
- breakpoint.
- KErrOverflow if there are too many breakpoints set.
-*/
-void CSecuritySvrSession::SetProcessBreakL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::SetProcessBreakL()\n" );
-
- //get debug app thread ID
- TProcessId procId = ReadTProcessIdL(aMessage, 0);
-
- //check that the agent has attached to the target process
- CheckAttachedL(procId, aMessage, EFalse);
-
- //create and initialise the memory info object
- TBreakInfo breakInfo;
- TPtr8 breakInfoPtr( (TUint8 *)&breakInfo, sizeof(TBreakInfo) );
-
- aMessage.ReadL(1,breakInfoPtr);
-
- //set break in target app
- TBreakId breakId = 0;
- User::LeaveIfError(Server().iKernelDriver.SetProcessBreak(breakId, procId, breakInfo.iAddress, breakInfo.iArchitectureMode));
-
- //attempt to write the break id back to the debug agent
- WriteDataL(aMessage, 2, &breakId, sizeof(breakId));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-@internalTechnology
-
-Modify a previously set process breakpoint.
-
-@param aMessage.Int0() - The breakpoint id of the breakpoint to modify
-@param aMessage.Ptr1() - The new Process Id for the breakpoint
-@param aMessage.Int2() - The new virtual memory address for the breakpoint
-@param aMessage.Int3() - The new architecture mode for the breakpoint
-@return KErrNone if succesful. KErrPermissionDenied if the security check fails.
- KErrAlreadyExists if there is a breakpoint overlapping the desired address.
- KErrNotSupported if the architecture type is unrecognised.
- KErrNoMemory if there is no more memory to complete the operation.
- KErrArgument if the breakpoint address alignment is unsuitable for the requested
- breakpoint.
- KErrOverflow if there are too many breakpoints set.
-*/
-void CSecuritySvrSession::ModifyProcessBreakL(const RMessage2& aMessage)
- {
- const TBreakId breakId = (TBreakId)aMessage.Int0();
- const TProcessId processId = ReadTProcessIdL(aMessage, 1);
- const TUint32 address = aMessage.Int2();
- const TArchitectureMode mode = (TArchitectureMode)aMessage.Int3();
-
- // Get information on the breakpoint to check the security status
- TUint64 checkProcessId;
- TUint32 checkAddress;
- TArchitectureMode checkMode;
- TBool threadSpecific;
-
- User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,checkProcessId,checkAddress,checkMode,threadSpecific));
-
- // Security check that the thread Id is associated with the debug agent
-
- //check that the agent has attached to the target process
- CheckAttachedL(TProcessId(checkProcessId), aMessage, EFalse);
-
- // now check that the thread Id which is being set is permitted
- //check that the agent has attached to the target process
- CheckAttachedL(processId, aMessage, EFalse);
-
- User::LeaveIfError(Server().iKernelDriver.ModifyProcessBreak(breakId,processId,address,mode));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-@param aMessage.Int0() - Breakpoint Id of interest
-@param aMessage.Ptr1() - Address in Debug Agent to place process Id of the breakpoint
-@param aMessage.Ptr2() - Address in Debug Agent to place address of the breakpoint
-@param aMessage.Ptr3() - Address in Debug Agent to place the architecture mode of the breakpoint
-@leave Any error which may be returned by RSessionBase::SendReceive()
-*/
-void CSecuritySvrSession::ProcessBreakInfoL(const RMessage2& aMessage)
- {
- const TBreakId breakId = (TBreakId)aMessage.Int0();
-
- TProcessId procId;
- TUint32 address;
- TArchitectureMode mode;
- TBool threadSpecific;
-
- TUint64 procIdData;
- User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,procIdData,address,mode,threadSpecific));
- if(threadSpecific)
- {
- User::Leave(KErrNotFound);
- }
- procId = TProcessId(procIdData);
-
- //check that the agent has attached to the target process
- CheckAttachedL(procId, aMessage, EFalse);
-
- // return the processId
- WriteDataL(aMessage, 1, &procId, sizeof(procId));
-
- // return the address
- WriteDataL(aMessage, 2, &address, sizeof(address));
-
- // return the mode
- WriteDataL(aMessage, 3, &mode, sizeof(mode));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-Read register values.
-
-@param aMessage should contain:
- * at offset 0 a pointer to the thread ID of the target thread
- * at offset 1 a descriptor representing an array of TRegisterInfo
- register IDs
- * at offset 2 a descriptor representing an array into which TRegisterValue
- register values will be written
- * at offset 3 a descriptor representing an array into which TUint8
- register flags will be written
-
-@leave KErrArgument if the max length of the array at offset 1 is not a
- multiple of sizeof(TRegisterInfo), if the max length of the array
- at offset 2 is not a multiple of sizeof(TRegisterValue), if the max
- length of the array at offset 3 is not a multiple of sizeof(TUint8), if
- any of the descriptors have max length of 0, or if the three
- descriptors do not represent the same number of registers,
- KErrNoMemory if there is insufficient memory,
- KErrDied, if the thread with thread ID aThreadId is dead
-*/
-void CSecuritySvrSession::ReadRegistersL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::ReadRegistersL()\n" );
-
- const TThreadId threadId = ReadTThreadIdL(aMessage, 0);
-
- //check the agent is attached to the thread
- CheckAttachedL(threadId, aMessage, ETrue);
-
- //number of registers being requested
- TUint32 numberOfRegisters;
-
- //check length of descriptors is acceptable
- ValidateRegisterBuffersL(aMessage, numberOfRegisters);
-
- // Passed data will be saved in this descriptor.
- RBuf8 ids;
- ids.CreateL(numberOfRegisters * sizeof(TRegisterInfo));
- // Do the right cleanup if anything subsequently goes wrong
- ids.CleanupClosePushL();
-
- //read the data from the client thread
- aMessage.ReadL(1, ids);
-
- //create buffer to fill with data from target debug thread
- HBufC8 *data = HBufC8::NewLC(aMessage.GetDesMaxLength(2));
- TPtr8 values(data->Des());
-
- HBufC8 *flagsData = HBufC8::NewLC(numberOfRegisters * sizeof(TUint8));
- TPtr8 flags(flagsData->Des());
-
- //get register info and return relevant parts back to agent
- User::LeaveIfError(Server().iKernelDriver.ReadRegisters(threadId, ids, values, flags));
- aMessage.WriteL(2, values);
- aMessage.WriteL(3, flags);
-
- //delete temporary buffers and return status
- CleanupStack::PopAndDestroy(flagsData);
- CleanupStack::PopAndDestroy(data);
- CleanupStack::PopAndDestroy(&ids);
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-Write register values.
-
-@param aMessage should contain:
- * at offset 0 a pointer to the thread ID of the target thread
- * at offset 1 a descriptor representing an array of TRegisterInfo
- register IDs
- * at offset 2 a descriptor representing an array of TRegisterValue register
- values
- * at offset 3 a descriptor representing an array into which TUint8
- register flags will be written
-
-@leave KErrArgument if the max length of the array at offset 1 is not a
- multiple of sizeof(TRegisterInfo), if the max length of the array
- at offset 2 is not a multiple of sizeof(TRegisterValue), if the max
- length of the array at offset 3 is not a multiple of sizeof(TUint8), if
- any of the descriptors have max length of 0, or if the three
- descriptors do not represent the same number of registers,
- KErrNoMemory if there is insufficient memory,
- KErrDied, if the thread with thread ID aThreadId is dead
-*/
-void CSecuritySvrSession::WriteRegistersL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::WriteRegistersL()\n" );
-
- const TThreadId threadId = ReadTThreadIdL(aMessage, 0);
-
- CheckAttachedL(threadId, aMessage, EFalse);
-
- //number of registers attempting to set
- TUint32 numberOfRegisters;
-
- //check length of descriptors is acceptable
- ValidateRegisterBuffersL(aMessage, numberOfRegisters);
-
- // Passed register ids will be saved in this descriptor.
- RBuf8 ids;
-
- //allocate buffer
- ids.CreateL(numberOfRegisters * sizeof(TRegisterInfo));
-
- // Do the right cleanup if anything subsequently goes wrong
- ids.CleanupClosePushL();
-
- //read the data from the client thread
- aMessage.ReadL(1, ids);
-
- // Passed register values will be saved in this descriptor.
- RBuf8 values;
-
- //allocate buffer
- values.CreateL(aMessage.GetDesMaxLength(2));
- // Do the right cleanup if anything subsequently goes wrong
- values.CleanupClosePushL();
- //read the data from the client thread
- aMessage.ReadL(2,values);
-
- HBufC8 *flagsData = HBufC8::NewLC(numberOfRegisters*sizeof(TUint8));
- TPtr8 flags(flagsData->Des());
-
- //get register info and return relevant parts back to agent
- User::LeaveIfError(Server().iKernelDriver.WriteRegisters(threadId, ids, values, flags));
-
- //write flags data back
- aMessage.WriteL(3, flags);
-
- CleanupStack::PopAndDestroy(flagsData);
- CleanupStack::PopAndDestroy(&values);
- CleanupStack::PopAndDestroy(&ids);
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-Processes an attach request from a debug agent. Gets the target debug
-processes' original FileName as an argument. The method sets completion
-status of the aMessage argument to KErrNone if successfully attached and to
-another of the system wide error codes if there were problems.
-
-@param aMessage contains:
- * a boolean at offset 0 which indicates whether the agent wishes to
- attach passively
- * a buffer at offset 1 which contains the FileName
- of the target debug process.
-*/
-void CSecuritySvrSession::AttachProcessL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::AttachProcessL()\n" );
-
- const TBool passive = aMessage.Int0();
-
- TInt deslen = aMessage.GetDesLengthL(1);
-
- // Passed data will be saved in this descriptor.
- RBuf processName;
-
- // Max length set to the value of "deslen", but current length is zero
- processName.CreateL(deslen);
-
- // Do the right cleanup if anything subsequently goes wrong
- processName.CleanupClosePushL();
-
- // Copy the client's descriptor data into our buffer.
- aMessage.ReadL(1,processName);
-
- //
- // Security Check
- //
- // It is not permitted to debug the debug security server!
- //
- // get the secure id of the executable
- TUid secureId(TUid::Null());
- GetSecureIdL(processName, secureId);
- if (KUidDebugSecurityServer.iUid == secureId.iUid)
- {
- // The debug agent has requested to debug the Debug Security Server
- // This is either an error, or an attempt to breach security. We
- // therefore refuse to agree to this request, and return KErrPermissionDenied
- LOG_MSG("CSecuritySvrSession::AttachProcessL() - Debug Agent attempted to debug the Debug Security Server\n");
-
- User::Leave(KErrPermissionDenied);
- }
-
- //get the debug agent's thread and push handle onto clean up stack
- RThread clientThread;
- User::LeaveIfError(aMessage.Client(clientThread));
- CleanupClosePushL(clientThread);
-
- //get the debug agent's process
- RProcess clientProcess;
- User::LeaveIfError(clientThread.Process(clientProcess));
-
- //finished with thread so close handle and destroy
- CleanupStack::PopAndDestroy(&clientThread);
-
- //get the debug agent's process id
- TProcessId processId = clientProcess.Id();
-
- //store the debug agent's process id for forced detaching later if the
- //agent doesn't tidy up after itself
- StoreDebugAgentId(processId);
-
- // Read the OEM Debug token capabilities (if any)
- GetDebugAgentOEMTokenCapsL();
-
- //finished with process so close handle
- clientProcess.Close();
-
- // Get the Security info via rlibrary::getinfo
- RLibrary::TInfo info;
- TPckg<RLibrary::TInfo> infoBuf(info);
-
- TInt err = RLibrary::GetInfo(processName, infoBuf);
- if (err != KErrNone)
- {
- LOG_MSG("CSecuritySvrSession::AttachProcessL() - Cannot parse the target executable header\n");
-
- // Could not read the header for this executable :-(
-
- CleanupStack::PopAndDestroy(&processName);
-
- aMessage.Complete(KErrPermissionDenied);
-
- return;
- }
-
- // Special case for AllFiles - OEM Debug tokens MUST have
- // AllFiles, as this is what allows them to read contents
- // of other executables.
- TBool checkDebuggable = ETrue;
-
- // Does an OEM Debug Token permit debug where it would normally not be
- // permitted?
- if ( Server().OEMTokenPermitsDebugL(iOEMDebugCapabilities, info.iSecurityInfo.iCaps) )
- {
- // OEM Debug token is valid and has sufficient capabilities
- LOG_MSG("CSecuritySvrSession::AttachProcessL() - Debug Agent has sufficient capabilites based on OEM Debug Token");
-
- checkDebuggable = EFalse;
- }
-
- if (checkDebuggable)
- {
- // OEM Debug token (if any), does not confer sufficient capabilities to
- // debug the specified target executable. Therefore debugging can only
- // be permitted if the target executable itself has been built as 'Debuggable'
- LOG_MSG("CSecuritySvrSession::AttachProcessL() - Debug Agent has insufficient capabilites based on OEM Debug Token");
-
- IsDebuggableL(processName);
- }
-
- User::LeaveIfError(Server().AttachProcessL(processName, processId, passive));
-
- // Inform the kernel driver about the attachment, so that it
- // can track per-agent data about the process.
- RBuf8 processName8;
-
- processName8.CreateL(deslen);
-
- processName8.CleanupClosePushL();
-
- processName8.Copy(processName);
-
- User::LeaveIfError(Server().iKernelDriver.AttachProcess(processName8, processId.Id()));
-
- // Create an Active Object to handle asynchronous calls to GetEvent
- CSecuritySvrAsync* handler = CSecuritySvrAsync::NewL(this,processName8,processId);
-
- err = iAsyncHandlers.Insert(handler,0);
- if (err != KErrNone)
- {
- // If we don't have an asynchronous handler, we should detach
- // the driver as well.
- if( (KErrNone != Server().iKernelDriver.DetachProcess(processName8,processId.Id()))
- || (KErrNone != Server().DetachProcess(processName, processId)) )
- {
- // this is a serious error, neither of these calls should fail so
- // we panic the server after closing the driver and printing a message
-
- LOG_MSG("CSecuritySvrSession::AttachProcessL(): critical error during cleanup\n");
- Server().iKernelDriver.Close();
- RProcess process;
- process.Panic(_L("AttachProcessL() failed"), KErrServerTerminated);
- }
- }
-
- User::LeaveIfError(err);
-
- CleanupStack::PopAndDestroy(&processName8);
-
- CleanupStack::PopAndDestroy(&processName);
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-Reads the OEM Debug Token associated with the debug agent if any. The OEM Debug Token
-allows the Debug Agent to debug certain executables which have not been built as
-'Debuggable'.
-
-This works as follows: The OEM Debug Token is an executable with a special name
-of the form "OEMDebug_<DA_SID>.exe" where <DA_SID> is the Secure ID of the Debug Agent
-in hexadecimal. For example: "OEMDebug_F123ABCD.exe" would be a valid name. This token executable
-must be signed with 'AllFiles' + X, where X is the set of PlatSec capabilities that are
-possessed by the target executable to be debugged.
-
-This function reads the capabilities possessed by the token by creating a process based
-on the executable, and reading the TSecurityInfo associated with the process. This ensures
-that the loader has validated the token has not been tampered with and that the security
-information is valid.
-
-The security information is then stored for future use as member data in iOEMDebugCapabilities.
-
-Leaves if there is an error, otherwise simply fills in the capabilities
-in iOEMDebugCapabilities.
-
-It is not an error for the OEM Debug token not to exist. In this case, the function simply returns.
-*/
-void CSecuritySvrSession::GetDebugAgentOEMTokenCapsL(void)
- {
- // Sanity check
- if (!iDebugAgentProcessIdStored)
- {
- LOG_MSG("CSecuritySvrSession::GetDebugAgentOEMTokenCapsL() - Debug Agent Process Id not stored");
-
- // We have not stored the debug agent process id!
- User::Leave(KErrNotReady);
- }
-
- // Obtain the security info about the debug agent process
- //get the debug agent's process
- RProcess debugAgentProcess;
-
- CleanupClosePushL(debugAgentProcess);
-
- debugAgentProcess.Open(iDebugAgentProcessId);
-
- // We have now obtained a process handle based on the token executable, so we can check its security properties.
- TSecurityInfo secInfo(debugAgentProcess);
-
-// Compute the name of the OEM debug token based on the SID of the debug agent
-_LIT(KDSSOEMDebugTokenPrefix,"OEMDebug_");
-_LIT(KDSSOEMDebugTokenAppendFmt,"%08X.exe");
-
- RBuf agentTokenName;
- agentTokenName.CreateL(KDSSOEMDebugTokenPrefix().Size()+8+1); // allow space for SID+null terminator
- agentTokenName.CleanupClosePushL();
-
- agentTokenName.SetLength(0);
-
- // Add OEMDebug_
- agentTokenName.Append(KDSSOEMDebugTokenPrefix());
-
- // Add debug agent Secure ID
- agentTokenName.AppendFormat(KDSSOEMDebugTokenAppendFmt,secInfo.iSecureId.iId);
-
- // just log the token name for the moment.
- RBuf8 agentTokenName8;
-
- agentTokenName8.CreateL(agentTokenName.Length()+1);
-
- agentTokenName8.CleanupClosePushL();
-
- agentTokenName8.Copy(agentTokenName);
-
- agentTokenName8.Append(TChar(0));
-
- //LOG_MSG2("CSecuritySvrSession::GetDebugAgentOEMTokenCapsL() - OEM Debug Token Name is %s",agentTokenName8.Ptr());
-
- // Cleanup
- CleanupStack::PopAndDestroy(&agentTokenName8);
-
- // Now locate and start the executable...
- RProcess agentToken;
- TInt err = agentToken.Create(agentTokenName, KNullDesC);
- if (KErrNone != err)
- {
- // Failed to create a process based on the token, just give up
- LOG_MSG2("CSecuritySvrSession::GetDebugAgentOEMTokenCapsL() - Could not create process based on token due to err 0x%8x\n",err);
-
- // Cleanup remaining items from the stack
- CleanupStack::PopAndDestroy(&agentTokenName);
-
- CleanupStack::PopAndDestroy(&debugAgentProcess);
- return;
- }
-
- // Synchronise with the process to make sure it hasn't died straight away
- TRequestStatus stat;
- agentToken.Rendezvous(stat);
- if (stat != KRequestPending)
- {
- // logon failed - agentToken is not yet running, so cannot have terminated
- agentToken.Kill(0); // Abort startup
- }
-
- // store the OEM Debug Token security data
- TSecurityInfo agentSecInfo(agentToken);
-
- // Note capabilities for future use
- iOEMDebugCapabilities=agentSecInfo.iCaps;
-
- // resume the token. It _should_ just exit, but we don't really care.
- agentToken.Resume();
-
- // Wait to synchronise with agentToken - if it dies in the meantime, it
- // also gets completed
- User::WaitForRequest(stat);
-
- // Just close the handle to it again.
- agentToken.Close();
-
- // Cleanup remaining items from the stack
- CleanupStack::PopAndDestroy(&agentTokenName);
-
- CleanupStack::PopAndDestroy(&debugAgentProcess);
-
- }
-
-/**
- Checks whether the file passed in as aExecutable is XIP or not
-
- @param aExecutable file to check
- @return ETrue if the file is XIP, EFalse otherwise
- */
-TBool CSecuritySvrSession::IsExecutableXipL(RFile& aExecutable)
- {
- TUint atts;
- User::LeaveIfError(aExecutable.Att(atts));
-
- return atts & KEntryAttXIP;
- }
-/**
- Gets access to the symbian crash partition for crash access operation.
- */
-void CSecuritySvrSession::ConnectCrashPartitionL (void)
- {
- LOG_MSG("CSecuritySvrSession::ConnectCrashPartitionL()");
-
- TBool changed;
- TInt error = KErrNone;
- TInt i=0;
-
- //Intialising to EFalse
- iCrashConnected = EFalse;
-
- TPckg<TLocalDriveCapsV2> capsBuf(iCaps);
-
- //check for the symbian crash partition
- for (i=0; i<KMaxLocalDrives; i++)
- {
- error = iLocalDrive.Connect (i, changed);
- if ( error == KErrNone)
- {
- error = iLocalDrive.Caps(capsBuf);
- if ( error != KErrNone)
- {
- //continue if not found
- continue;
- }
- if ( iCaps.iPartitionType == (TUint16)KPartitionTypeSymbianCrashLog)
- {
- LOG_MSG2("Found Symbian crash log partition on drive: %d",i);
- iCrashConnected = ETrue;
- break;
- }
- }
- }
- if ( i == KMaxLocalDrives)
- {
- LOG_MSG("No crash log partition found with valid crash log signature found. Exiting...");
- User::Leave (KErrNotFound);
- }
-
- // Nand Flash not currently supported.
- if (iCaps.iType == EMediaNANDFlash)
- {
- LOG_MSG( "CSecuritySvrSession::ConnectCrashPartitionL() Nand Flash not currently supported\n" );
- User::Leave (KErrNotSupported);
- }
- }
-/** Checks that aHeaderData contains enough data to cast it to the
- appropriate header type.
-
- @param aHeaderData buffer containing header data read from a file
- @param aXip boolean indicating whether the header data is for an XIP image
-
- @return ETrue if enough data in buffer, EFalse otherwise
- */
-TBool CSecuritySvrSession::CheckSufficientData(const TDesC8& aHeaderData, const TBool aXip) const
- {
- TUint minimumHeaderSize = aXip ? sizeof(TRomImageHeader) : sizeof(E32ImageHeaderV);
- return (aHeaderData.Length() >= minimumHeaderSize);
- }
-
-/**
- Opens a file handle to aFileName using aFileHandle
- @param aFileName file to open handle to
- @param aFs file system to use to open the handle
- @param aFileHandle file handle to open
-
- @leave one of the system wide error codes
- */
-void CSecuritySvrSession::OpenFileHandleL(const TDesC& aFileName, RFs& aFs, RFile& aFileHandle)
- {
- TInt err = aFileHandle.Open(aFs, aFileName, EFileRead | EFileShareReadersOnly);
- if (err != KErrNone)
- {
- // Could not open the file for reading
- LOG_MSG("CSecuritySvrSession::OpenFileHandleL - Failed to open executable\n");
-
- User::Leave(err);
- }
- }
-
-/**
- Checks whether an executable has the debug bit set
-
- @param aHeaderData buffer containing the header of the executable
- @param aXip indication of whether the executable is XIP or not
-
- @return ETrue if debug bit is set, EFalse otherwise
- */
-TBool CSecuritySvrSession::IsDebugBitSet(const TDesC8& aHeaderData, const TBool aXip)
- {
- if(!CheckSufficientData(aHeaderData, aXip))
- {
- return EFalse;
- }
-
- if (aXip)
- {
- TRomImageHeader* hdr = (TRomImageHeader*)aHeaderData.Ptr();
- return (hdr->iFlags & KRomImageDebuggable);
- }
- else
- {
- // it is an epoc32 image
- E32ImageHeaderV* hdr = (E32ImageHeaderV*)aHeaderData.Ptr();
- return (hdr->iFlags & KImageDebuggable);
- }
- }
-
-/**
-Determines whether a particular executable is marked as 'debuggable'
-
-Notes:
-This function is currently hard coded to understand the format of e32 and
-TRomImage file headers. Ideally this will be replaced by a call to RLibrary::GetInfo
-which can return the 'debuggable' information. Unfortunately, this call currently
-does not provide the information for XIP executables :-(
-
-@leave KErrPermissionDenied if the debug bit is not set, or one of the other
-system wide error codes
-*/
-void CSecuritySvrSession::IsDebuggableL(const TDesC& aFileName)
- {
-#ifndef IGNORE_DEBUGGABLE_BIT
-
- RFs fs;
- User::LeaveIfError(fs.Connect());
- CleanupClosePushL(fs);
-
- RFile targetExe;
- OpenFileHandleL(aFileName, fs, targetExe);
- CleanupClosePushL(targetExe);
-
- // Read in the entire header
- RBuf8 e32HdrBuf;
- e32HdrBuf.CreateL(RLibrary::KRequiredImageHeaderSize);
- e32HdrBuf.CleanupClosePushL();
-
- // Read the entire header as far as possible
- TInt err = targetExe.Read(e32HdrBuf);
- if (err != KErrNone)
- {
- // Could not read the file
- LOG_MSG("CSecuritySvrSession::IsDebuggableL - Failed to read executable\n");
-
- User::Leave(err);
- }
-
- if(!CheckSufficientData(e32HdrBuf, IsExecutableXipL(targetExe)))
- {
- User::Leave(KErrGeneral);
- }
-
- if(! IsDebugBitSet(e32HdrBuf, IsExecutableXipL(targetExe)))
- {
- User::Leave(KErrPermissionDenied);
- }
- CleanupStack::PopAndDestroy(3, &fs);
-
-#else
- LOG_MSG("CSecuritySvrSession::IsDebuggableL() Debuggable bit temporarily ignored!!!");
-#endif
- }
-
-/**
-Processes a detach request from a debug agent. Gets the target debug
-processes' original FileName as an argument. The method sets completion
-status of the aMessage argument to KErrNone if successfully detached and to
-another of the system wide error codes if there were problems.
-
-@param aMessage contains:
- * a buffer at offset 0 which contains the FileName
- of the target debug process.
-*/
-void CSecuritySvrSession::DetachProcessL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::DetachProcessL()\n" );
-
- TInt deslen = aMessage.GetDesLengthL(0);
- // Passed data will be saved in this descriptor.
- RBuf processName;
-
- // Max length set to the value of "deslen", but current length is zero
- processName.CreateL(deslen);
-
- // Do the right cleanup if anything subsequently goes wrong
- processName.CleanupClosePushL();
-
- // Copy the client's descriptor data into our buffer.
- aMessage.ReadL(0,processName);
-
- User::LeaveIfError(Server().DetachProcess(processName, iDebugAgentProcessId));
-
- // Inform the kernel driver about the detachment, so that
- // it can stop tracking per-agent data for the debugged process.
- RBuf8 processName8;
-
- processName8.CreateL(deslen);
-
- processName8.CleanupClosePushL();
-
- processName8.Copy(processName);
-
- // Remove the Asynchronous Object associated with this process
- for(TInt i=0; i<iAsyncHandlers.Count(); i++)
- {
- if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0)
- {
- delete iAsyncHandlers[i];
- iAsyncHandlers.Remove(i);
-
- break;
- }
- }
-
- // Inform the driver that we are no longer attached to this process
- User::LeaveIfError(Server().iKernelDriver.DetachProcess(processName8,iDebugAgentProcessId.Id()));
-
- CleanupStack::PopAndDestroy(&processName8);
- CleanupStack::PopAndDestroy(&processName);
-
- aMessage.Complete(KErrNone);
- }
-
-/**
-@param aMessage The RMessage2 object is expected to contain:
- * aMessage.Int0() - TDes8 Containing the process name.
- * aMessage.Int1() - Address of TPtr8 containing TEventInfo
-
-*/
-void CSecuritySvrSession::GetEventL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::GetEventL()\n" );
-
- // Local descriptor to contain target process name
- TInt deslen = aMessage.GetDesLengthL(0);
-
- RBuf processName;
-
- processName.CreateL(deslen);
-
- processName.CleanupClosePushL();
-
- // Read the target process name into processName
- aMessage.ReadL(0,processName);
-
- // Check if debug agent is attached to process
- if(!Server().CheckAttachedProcess(processName, aMessage, EFalse))
- {
- LOG_MSG("CSecuritySvrSession::GetEventL() - Not attached to this process\n");
-
- // Debug Agent is not attached at all to the requested process
- User::Leave(KErrPermissionDenied);
- }
-
- // Identify which process is being debugged, so that
- // we can locate the appropriate active object handler.
- RBuf8 processName8;
-
- processName8.CreateL(processName.Length());
-
- processName8.CleanupClosePushL();
-
- processName8.Copy(processName);
-
- // Find the Asynchronous Object associated with this process,
- // as it is permissible to have an outstanding GetEvent call
- // for each attached process.
- TBool foundHandler = EFalse;
- for(TInt i=0; i<iAsyncHandlers.Count(); i++)
- {
- if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0)
- {
- iAsyncHandlers[i]->GetEvent(aMessage);
- foundHandler = ETrue;
- break;
- }
- }
-
- if (foundHandler == EFalse)
- {
- // could not find an async handler object. Report the problem.
- LOG_MSG("CSecuritySvrSessionL - Could not find a handler object\n");
- User::Leave(KErrNotFound);
- }
-
- // Actually make the driver call, passing in the agent Id
- // so that the driver knows which per-agent event queue
- // to interrogate to retrieve the latest event.
- CleanupStack::PopAndDestroy(&processName8);
- CleanupStack::PopAndDestroy(&processName);
- }
-
-/**
-Cancels a pre-issued GetEvent call for a specific debugged process.
-
-@param aMessage.Int0() - TDes8 containing aProcessName
-*/
-void CSecuritySvrSession::CancelGetEventL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::CancelGetEventL()\n" );
-
- // Local descriptor to contain target process name
- TInt deslen = aMessage.GetDesLengthL(0);
-
- RBuf processName;
-
- processName.CreateL(deslen);
-
- processName.CleanupClosePushL();
-
- // Read the target process name into processName
- aMessage.ReadL(0,processName,0);
-
- // Debug Agent is not an active debugger. Check if the DA is passively attached
- if(!Server().CheckAttachedProcess(processName, aMessage, EFalse))
- {
- // Debug Agent is not attached at all to the requested process
- User::Leave(KErrPermissionDenied);
- }
-
- // Identify the appropriate active object associate
- // with this process.
- RBuf8 processName8;
-
- processName8.CreateL(processName.Length());
-
- processName8.CleanupClosePushL();
-
- processName8.Copy(processName);
-
- // Find the Asynchronous Object associated with this process
- TBool foundHandler = EFalse;
- for(TInt i=0; i<iAsyncHandlers.Count(); i++)
- {
- if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0)
- {
-
- // Found the AO handler, so cancel the outstanding getevent call.
- iAsyncHandlers[i]->Cancel();
- foundHandler = ETrue;
- break;
- }
- }
-
- if(!foundHandler)
- {
- // We could not found a handler, so report the problem to the debug agent
- User::Leave(KErrNotFound);
- }
-
- //do cleanup
- CleanupStack::PopAndDestroy(&processName8);
- CleanupStack::PopAndDestroy(&processName);
-
- aMessage.Complete(KErrNone);
- }
-
-/*
- Purpose: Sets the required event action to be taken for a specific
- process and event combination
-
-@param aMessage The RMessage2 object is expected to contain:
- * aMessage.Int0() - TDes8 Containing the process name.
- * aMessage.Int1() - TEventType
- * aMessage.Int2() - TKernelEventAction
- *
-*/
-void CSecuritySvrSession::SetEventActionL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::SetEventActionL()\n" );
-
- // Local descriptor to contain target process name
- TInt deslen = aMessage.GetDesLengthL(0);
-
- RBuf processName;
-
- processName.CreateL(deslen);
-
- processName.CleanupClosePushL();
-
- // Read the target process name into processName
- aMessage.ReadL(0,processName);
-
- //check that the agent has attached to the target process
- if(!Server().CheckAttachedProcess(processName, aMessage, EFalse))
- {
- // Debug Agent is not attached at all to the requested process
- User::Leave(KErrPermissionDenied);
- }
-
- // Extract and validate the arguments from aMessage
- TUint32 event = aMessage.Int1();
- if (event >= EEventsLast)
- {
- // Supplied event Id was not recognised
- User::Leave(KErrArgument);
- }
-
- TUint32 action = aMessage.Int2();
- if(action >= EActionLast)
- {
- // Supplied event action was not recognised
- User::Leave(KErrArgument);
- }
-
- RBuf8 processName8;
-
- processName8.CreateL(processName.Length());
-
- processName8.CleanupClosePushL();
-
- processName8.Copy(processName);
-
- // Make the call to the device driver
- TInt err = Server().iKernelDriver.SetEventAction(processName8, \
- (TEventType)event,\
- (TKernelEventAction)action,\
- iDebugAgentProcessId.Id());
-
- User::LeaveIfError(err);
-
- CleanupStack::PopAndDestroy(&processName8);
- CleanupStack::PopAndDestroy(&processName);
-
- aMessage.Complete(KErrNone);
-}
-
-/**
-Purpose: Single-step a thread for a specified number of instructions
-
-@param aMessage.Ptr0() - Thread Id of the thread to be stepped
-@param aMessage.Int1() - Number of instructions to step.
-
-@leave one of the system wide error codes
-
-*/
-void CSecuritySvrSession::StepL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::StepL()\n" );
-
- const TThreadId threadId = ReadTThreadIdL(aMessage, 0);
- const TInt32 numSteps = aMessage.Int1();
-
- CheckAttachedL(threadId, aMessage, EFalse);
-
- User::LeaveIfError(Server().iKernelDriver.Step( threadId, numSteps ));
-
- aMessage.Complete(KErrNone);
- }
-
-/**
- * This checks whether or not the agent is permitted access to the flash partition
- * @return KErrNone if allowed, otherwise one of the system wide error codes
- * @leave one of the system wide error codes
- */
-TInt CSecuritySvrSession::CheckFlashAccessPermissionL(const RThread aClientThread)
- {
- //get the debug agent's process
- RProcess clientProcess;
- User::LeaveIfError(aClientThread.Process(clientProcess));
-
- //get the debug agent's process id
- TProcessId processId = clientProcess.Id();
-
- //store the debug agent's process id for forced detaching later if the
- //agent doesn't tidy up after itself
- StoreDebugAgentId(processId);
-
- // Read the OEM Debug token capabilities (if any)
- GetDebugAgentOEMTokenCapsL();
-
- if(Server().OEMTokenPermitsFlashAccessL((iOEMDebugCapabilities)))
- {
- return KErrNone;
- }
-
- return KErrPermissionDenied;
- }
-
-/**
-Purpose: Read the crash log from the crash flash partition
-@param aMessage.Int0() - Position to read from.
-@param aMessage.Ptr1() - Buffer to hold the data retrieved
-@param aMessage.Int2() - Size of the data to read.
-
-@leave one of the system wide error codes
-*/
-void CSecuritySvrSession::ReadCrashLogL (const RMessage2& aMessage)
- {
- //get the debug agent's thread and push handle onto clean up stack
- RThread clientThread;
- User::LeaveIfError(aMessage.Client(clientThread));
- CleanupClosePushL(clientThread);
-
- TInt err = CheckFlashAccessPermissionL(clientThread);
-
- CleanupStack::PopAndDestroy(&clientThread);
-
- if(KErrNone != err)
- {
- LOG_MSG2( "CSecuritySvrSession::ReadCrashLogL() Access Not Granted - [%d]\n", err );
- aMessage.Complete(err);
- return;
- }
-
- //Check whether drive connected.
- if(!iCrashConnected)
- ConnectCrashPartitionL();
-
- TInt readPosition = aMessage.Int0(); //read position
-
- TInt readSize = aMessage.Int2(); //read size
-
- RBuf8 readBuf;
- readBuf.CreateL(readSize);
- readBuf.CleanupClosePushL();
-
- err = iLocalDrive.Read (readPosition, readSize, readBuf);
-
- //write the list data back
- aMessage.WriteL (1, readBuf);
-
- CleanupStack::PopAndDestroy (&readBuf);
-
- //Complete message
- aMessage.Complete(err);
- }
-/**
-Purpose: Function to write the crash config to the crash flash partition
-
-@param aMessage.Int0() - write position in bytes from start position in flash partition.
-@param aMessage.Ptr1() - Buffer containing the data to be written onto the flash.
- The size could be 0 if only flash partition size is needed.
-@param aMessage.Int2() - returns the size of the flash partition.
-
-@leave one of the system wide error codes
-*/
-void CSecuritySvrSession::WriteCrashConfigL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::WriteCrashConfigL()\n" );
-
- //get the debug agent's thread and push handle onto clean up stack
- RThread clientThread;
- User::LeaveIfError(aMessage.Client(clientThread));
- CleanupClosePushL(clientThread);
-
- TInt err = CheckFlashAccessPermissionL(clientThread);
-
- CleanupStack::PopAndDestroy(&clientThread);
-
- if(KErrNone != err)
- {
- LOG_MSG2( "CSecuritySvrSession::WriteCrashConfigL() Access Not Granted - [%d]\n", err );
- aMessage.Complete(err);
- return;
- }
-
- //Check whether drive connected.
- if(!iCrashConnected)
- ConnectCrashPartitionL();
-
- // Get the length of the buffer
- TInt deslen = aMessage.GetDesLengthL(1);
-
- RBuf8 dataBuf;
- dataBuf.CreateL(deslen);
- dataBuf.CleanupClosePushL();
-
- // data to be written to flash
- aMessage.ReadL(1,dataBuf);
-
- TUint32 position = aMessage.Int0(); //position to start from
-
- err = iLocalDrive.Write(position,(const TDesC8&)dataBuf);
-
- TPtr8 dataSize((TUint8*)&deslen,4, 4);
-
- //write the size of the data written back
- aMessage.WriteL(2,dataSize);
-
- //destroy buffer
- CleanupStack::PopAndDestroy(&dataBuf);
-
- aMessage.Complete(err);
- }
-/**
-Purpose: Method to erase the crash flash block
-
-@param aMessage.Int0() - write position in bytes from start position in flash partition.
-@param aMessage.Int2() - Number of blocks to erase.
-
-@leave one of the system wide error codes
-*/
-
-void CSecuritySvrSession::EraseCrashLogL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::EraseCrashLogL()\n" );
-
- //get the debug agent's thread and push handle onto clean up stack
- RThread clientThread;
- User::LeaveIfError(aMessage.Client(clientThread));
- CleanupClosePushL(clientThread);
-
- TInt err = CheckFlashAccessPermissionL(clientThread);
-
- CleanupStack::PopAndDestroy(&clientThread);
-
- if(KErrNone != err)
- {
- LOG_MSG2( "CSecuritySvrSession::EraseCrashLogL() Access Not Granted - [%d]\n", err );
- aMessage.Complete(err);
- return;
- }
-
- //Check whether drive connected.
- if(!iCrashConnected)
- ConnectCrashPartitionL();
-
- TInt64 position = aMessage.Int0();
- TInt size = aMessage.Int1();
-
- //Format drive
- err = iLocalDrive.Format(position,size*iCaps.iEraseBlockSize);
-
- aMessage.Complete(err);
- }
-
-/**
-Purpose: Method to erase the entire crash flash block
-@leave one of the system wide error codes
-*/
-
-void CSecuritySvrSession::EraseEntireCrashLogL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::EraseEntireCrashLogL()\n" );
-
- //get the debug agent's thread and push handle onto clean up stack
- RThread clientThread;
- User::LeaveIfError(aMessage.Client(clientThread));
- CleanupClosePushL(clientThread);
-
- TInt err = CheckFlashAccessPermissionL(clientThread);
-
- CleanupStack::PopAndDestroy(&clientThread);
-
- if(KErrNone != err)
- {
- LOG_MSG2( "CSecuritySvrSession::EraseEntireCrashLogL() Access Not Granted - [%d]\n", err );
- aMessage.Complete(err);
- return;
- }
-
- //Check whether drive connected.
- if(!iCrashConnected)
- ConnectCrashPartitionL();
-
- TUint numberBlocks = iCaps.iSize /iCaps.iEraseBlockSize;
-
- //Format drive
- for(TInt i = 0; i < numberBlocks; i++)
- {
- err = iLocalDrive.Format(i*iCaps.iEraseBlockSize,iCaps.iEraseBlockSize);
- if(KErrNone != err)
- {
- RDebug::Printf("err = %d", err);
- aMessage.Complete(err);
- return;
- }
- }
-
-
- aMessage.Complete(err);
- }
-
-
-/**
-Purpose: Kill a specified process
-
-@param aMessage.Ptr0() - Process Id of the thread to be stepped
-@param aMessage.Int1() - Reason code to supply when killing the process.
-
-@leave one of the system wide error codes
-
-*/
-void CSecuritySvrSession::KillProcessL(const RMessage2& aMessage)
- {
- LOG_MSG( "CSecuritySvrSession::KillProcessL()\n" );
-
- const TProcessId processId = ReadTProcessIdL(aMessage, 0);
- const TInt32 reason = aMessage.Int1();
-
- CheckAttachedL(processId, aMessage, EFalse);
-
- User::LeaveIfError(Server().iKernelDriver.KillProcess( processId, reason ));
-
- aMessage.Complete(KErrNone);
- }
-
-/** Gets the secure id of aFileName
- @param aFileName file name of executable to get SID for
- @param aSecureId on return will contain the SID of aFileName
-
- @leave one of the system wide error codes
- */
-void CSecuritySvrSession::GetSecureIdL(const TDesC& aFileName, TUid& aSecureId)
- {
- RFs fs;
- User::LeaveIfError(fs.Connect());
- CleanupClosePushL(fs);
-
- RFile targetExe;
- OpenFileHandleL(aFileName, fs, targetExe);
- CleanupClosePushL(targetExe);
-
- // Read in the entire header
- RBuf8 e32HdrBuf;
- e32HdrBuf.CreateL(RLibrary::KRequiredImageHeaderSize);
- e32HdrBuf.CleanupClosePushL();
-
- // Read the entire header as far as possible
- TInt err = targetExe.Read(e32HdrBuf);
- if (err != KErrNone)
- {
- // Could not read the file
- LOG_MSG("CSecuritySvrSession::GetSecureIdL - Failed to read executable\n");
-
- User::Leave(err);
- }
-
- if(!CheckSufficientData(e32HdrBuf, IsExecutableXipL(targetExe)))
- {
- User::Leave(KErrGeneral);
- }
-
- aSecureId = GetSecureIdL(e32HdrBuf, IsExecutableXipL(targetExe));
-
- CleanupStack::PopAndDestroy(3, &fs);
- }
-
-/** Get the secure id from aHeaderData
- @param aHeaderData an executable's header data to read SID from
- @param aXip indication of whether the header data is from an XIP file
-
- @return secure ID from aHeaderData
- */
-TUid CSecuritySvrSession::GetSecureIdL(const TDesC8& aHeaderData, TBool aXip)
- {
- if(!CheckSufficientData(aHeaderData, aXip))
- {
- User::Leave(KErrGeneral);
- }
-
- if (aXip)
- {
- TRomImageHeader* hdr = (TRomImageHeader*)aHeaderData.Ptr();
- return TUid::Uid(hdr->iS.iSecureId);
- }
- else
- {
- // it is an epoc32 image
- E32ImageHeaderV* hdr = (E32ImageHeaderV*)aHeaderData.Ptr();
- return TUid::Uid(hdr->iS.iSecureId);
- }
- }
-
-/**
-@param aMessage contains:
- * aMessage.Ptr0() a TListDetails object
- * aMessage.Ptr1() a client supplied TDes8 for the driver to return data in
- * aMessage.Ptr2() a TUint32 for the driver to return the size of the requested listing's data in
-
-@leave KErrTooBig if the buffer passed as argument 1 of aMessage is too
- small to contain the requested data,
- KErrNoMemory if a temporary buffer could not be allocated,
- or one of the other system wide error codes
-*/
-void CSecuritySvrSession::GetListL(const RMessage2& aMessage)
- {
- LOG_MSG("CSecuritySvrSession::GetListL()");
-
- // buffer to write list data into before copying back to agent
- RBuf8 listDetailsBuf;
-
- //allocate buffer
- listDetailsBuf.CreateL(sizeof(TListDetails));
-
- // Do the right cleanup if anything subsequently goes wrong
- listDetailsBuf.CleanupClosePushL();
-
- //read the data from the client thread
- aMessage.ReadL(0, listDetailsBuf);
- TListDetails* listDetails = (TListDetails*)listDetailsBuf.Ptr();
-
- //get the type of list requested
- TListId type = (TListId)aMessage.Int0();
-
- //create a buffer to store the data in
- RBuf8 buffer;
- buffer.CreateL(aMessage.GetDesMaxLength(1));
- buffer.CleanupClosePushL();
-
- //create a temporary variable to potentially store data length in
- TUint32 size = 0;
-
- TInt err = KErrNone;
-
- // the executables list is generated in the DSS rather than in the driver
- // so is treated separately
- if(listDetails->iListId == EExecutables)
- {
- if(listDetails->iListScope != EScopeGlobal)
- {
- User::Leave(KErrArgument);
- }
- if(listDetails->iTargetId != 0)
- {
- User::Leave(KErrArgument);
- }
- err = GetExecutablesListL(buffer, size);
- }
- else
- {
- err = Server().iKernelDriver.GetList(listDetails->iListId, listDetails->iListScope, listDetails->iTargetId, iDebugAgentProcessId, buffer, size);
- }
-
- if(err == KErrNone)
- {
- //write the list data back
- aMessage.WriteL(1, buffer);
- }
-
- TPtr8 sizePtr((TUint8*)&size, sizeof(TUint32), sizeof(TUint32));
- //write size back to agent
- aMessage.WriteL(2, sizePtr);
-
- CleanupStack::PopAndDestroy(&buffer);
- CleanupStack::PopAndDestroy(&listDetailsBuf);
-
- aMessage.Complete(err);
- }
-
-/**
-Gets the executables list and returns it in aBuffer if it's big enough
-
-@param aBuffer caller supplied buffer to write data into
-@param aSize on return contains the size of the data in the buffer, or the
- size that the buffer would need to be to contain the data
-
-@return KErrNone on success, or KErrTooBig if the requested data will not fit in aBuffer
-
-@leave one of the system wide error codes
-*/
-TInt CSecuritySvrSession::GetExecutablesListL(TDes8& aBuffer, TUint32& aSize) const
- {
- LOG_MSG("CSecuritySvrSession::GetExecutablesList()");
-
- //initialise values and connect to file system
- aSize = 0;
- aBuffer.SetLength(0);
- RFs fs;
- User::LeaveIfError(fs.Connect());
- CleanupClosePushL(fs);
-
- // uids corresponding to executable image
- TUidType uids(KExecutableImageUid, KNullUid, KNullUid);
-
- //create a string containing the directory name. The drive letter is represented
- //by X but will be replaced by the appropriate drive letter for each drive
- _LIT(KColonSysBin,":\\sys\\bin\\");
-
- //create a modifiable copy of KColonSysBin, preceeded by an empty space for the drive letter
- RBuf dirName;
- dirName.CreateL(1 + KColonSysBin().Length());
- dirName.CleanupClosePushL();
-
- //set the length to 1 (to later fill with the drive letter) and then append KColonSysBin
- dirName.SetLength(1);
- dirName.Append(KColonSysBin());
-
- //get the list of valid drives for the device
- TDriveList driveList;
- User::LeaveIfError(fs.DriveList(driveList));
-
- //check each valid sys/bin directory for executables
- for(TInt i=0; i<KMaxDrives; i++)
- {
- //if the drive is not valid then skip this drive
- if(!driveList[i])
- {
- //skip processing this drive
- continue;
- }
-
- //get the drive letter and insert it as the drive letter for dirName
- TChar driveLetter;
- User::LeaveIfError(fs.DriveToChar(i, driveLetter));
- dirName[0] = (TUint)driveLetter;
-
- //get a list of the exes in this drive's sys/bin directory
- CDir* localDir = NULL;
- TInt err = fs.GetDir(dirName, uids, ESortByName, localDir);
- if(KErrNoMemory == err)
- {
- User::Leave(err);
- }
- if(!localDir)
- {
- //skip processing this drive
- continue;
- }
-
- //push onto cleanup stack in case we leave
- CleanupStack::PushL(localDir);
-
- //iterate through the files
- for(TInt j=0; j<localDir->Count(); j++)
- {
- //will store x:\sys\bin\<file-name> type string
- RBuf fullPathName;
-
- TUint16 nameLength = dirName.Length() + (*localDir)[j].iName.Length();
- fullPathName.CreateL(nameLength);
- fullPathName.CleanupClosePushL();
- fullPathName.Copy(dirName);
- fullPathName.Append((*localDir)[j].iName);
-
- //add the data to the buffer
- AppendExecutableData(aBuffer, aSize, fullPathName);
-
- //do cleanup
- CleanupStack::PopAndDestroy(&fullPathName);
- }
-
- //do cleanup
- CleanupStack::PopAndDestroy(localDir);
- }
-
- //do cleanup
- CleanupStack::PopAndDestroy(2, &fs);
-
- //return appropriate value as to whether the kernel's data was too big
- return (aSize <= aBuffer.MaxLength()) ? KErrNone : KErrTooBig;
- }
-
-
-/**
- Append data to aBuffer and update size of aSize if the data will fit. If it will
- not fit then just puts the nee size in aSize.
-
- @param aBuffer buffer to append the data to
- @param aSize on return contains the new size of the buffer if the data could be
- appended, otherwise aSize is updated to reflect the size the buffer would have if
- the data had fitted.
- @param aEntryName file name of the entry to add to the buffer
- */
-void CSecuritySvrSession::AppendExecutableData(TDes8& aBuffer, TUint32& aSize, const TDesC& aEntryName) const
- {
- //update aSize to include the size of the data for this entry
- aSize = Align4(aSize + sizeof(TExecutablesListEntry) + (2*aEntryName.Length()) - sizeof(TUint16));
-
- //if the data will fit, and we haven't already stopped putting data in, then append the data,
- //if we've stopped putting data in then aSize will be bigger than aBuffer.MaxLength()
- if(aSize <= aBuffer.MaxLength())
- {
- TExecutablesListEntry& entry = *(TExecutablesListEntry*)(aBuffer.Ptr() + aBuffer.Length());
- //check whether an agent has registered to actively debug fullPathName
- TBool activelyDebugged = IsDebugged(aEntryName, EFalse);
- entry.iIsActivelyDebugged = activelyDebugged ? 1 : 0;
-
- //check whether any agents have registered to passively debug fullPathName
- TBool passivelyDebugged = IsDebugged(aEntryName, ETrue);
- entry.iIsPassivelyDebugged = passivelyDebugged ? 1 : 0;
-
- entry.iNameLength = aEntryName.Length();
- TPtr name(&(entry.iName[0]), aEntryName.Length(), aEntryName.Length());
- name = aEntryName;
- //pad the buffer to a four byte boundary
- aBuffer.SetLength(aSize);
- }
- }
-/**
-Helper function
-
-Write data back to the thread that owns aMessage
-
-@param aMessage the message which is passed between processes
-@param aIndex the message slot which the data will be passed back in
-@param aPtr pointer to data in this thread to be written into aMessage
-@param aPtrSize size in bytes of the data to be written
-
-@leave one of the system wide error codes
-*/
-void CSecuritySvrSession::WriteDataL(const RMessage2& aMessage, const TInt aIndex, const TAny* aPtr, const TUint32 aPtrSize) const
- {
- TPtr8 dataPtr((TUint8*)aPtr, aPtrSize, aPtrSize);
-
- aMessage.WriteL(aIndex, dataPtr);
- }
-
-/**
-Stores the PID of the debug agent, if it is not already stored.
-
-@param aDebugAgentProcessId PID of the debug agent
-*/
-void CSecuritySvrSession::StoreDebugAgentId(const TProcessId aDebugAgentProcessId)
- {
- if(! iDebugAgentProcessIdStored)
- {
- iDebugAgentProcessIdStored = ETrue;
- iDebugAgentProcessId = aDebugAgentProcessId;
- }
- }
-
-/**
-Helper function.
-
-Checks whether the debug agent (the owner of the aMessage) is attached to the
-thread with thread id of aThreadId.
-
-@param aThreadId thread ID of target debug thread
-@param aMessage message owned by the debug agent
-@param aPassive indicates whether to check if attached passively or actively
-
-@leave KErrPermissionDenied if the agent is not attached to the process,
- KErrNoMemory if the security server could not be accessed
-*/
-void CSecuritySvrSession::CheckAttachedL(const TThreadId aThreadId, const RMessage2& aMessage, const TBool aPassive) const
- {
- //check that the agent has attached to the target process
- if(! Server().CheckAttached(aThreadId, aMessage, aPassive))
- {
- LOG_MSG("CSecuritySvrSession::CheckAttachedL() failed");
- User::Leave(KErrPermissionDenied);
- }
- }
-
-/**
-Helper function.
-
-Checks whether the debug agent (the owner of the aMessage) is attached to the
-process with process id of aProcessId.
-
-@param aProcessId process ID of target debug thread
-@param aMessage message owned by the debug agent
-@param aPassive indicates whether to check if attached passively or actively
-
-@leave KErrPermissionDenied if the agent is not attached to the process,
- KErrNoMemory if the security server could not be accessed
-*/
-void CSecuritySvrSession::CheckAttachedL(const TProcessId aProcessId, const RMessage2& aMessage, const TBool aPassive) const
- {
-
- //check that the agent has attached to the target process
- if(! Server().CheckAttached(aProcessId, aMessage, aPassive))
- {
- LOG_MSG("CSecuritySvrSession::CheckAttachedL() (process) failed");
- User::Leave(KErrPermissionDenied);
- }
- }
-
-/**
-Check whether the debug agent is permitted to attach to the target process.
-Note that this function does not actually attach the agent to the process, it
-simply tests whether an attach call would potentially be successful.
-
-Currently this method returns ETrue in all cases but will be updated once
-the security checking framework is in place.
-
-@param aDebugAgentProcessId process id of the debug agent
-@param aTargetProcessName original file name of the target process
-
-@return ETrue if the debug agent would be allowed to attch to the target process,
- EFalse otherwise
-*/
-TBool CSecuritySvrSession::PermitDebugL(const TProcessId aDebugAgentProcessId, const TDesC& aTargetProcessName) const
- {
- return ETrue;
- }
-
-/**
-Helper function
-
-Validates that the memory info passed in meets the debug driver's requirements
-
-@param aMemoryInfo memory info passed in from client
-
-@leave KErrArgument if:
- * size is zero
- * size is greater than the max block size
- * size + address > 0xffffffff
- * address is not access size aligned
- * size is not a multiple of the access size
- KErrNotSupported if:
- * iAccess is not TAccess::EAccess32
- * iEndianess is not TEndianess::EEndLE8
- KErrUnknown if:
- * the max memory block size cannot be determined
- or one of the other system wide error codes
-*/
-void CSecuritySvrSession::ValidateMemoryInfoL(const TThreadId aThreadId, const TMemoryInfo &aMemoryInfo, const TBool aReadOperation)
- {
- //check size is not 0
- if(aMemoryInfo.iSize == 0)
- User::Leave(KErrArgument);
-
- //get the max block size supported
- TUint32 maxSize = 0;
- User::LeaveIfError(Server().iKernelDriver.GetMemoryOperationMaxBlockSize(maxSize));
-
- //check that the block size given is less than the max block size
- if(aMemoryInfo.iSize > maxSize)
- User::Leave(KErrArgument);
-
- //must ensure that address + size <= 0xffffffff as will attempt to
- //read past 0xffffffff, which wouldn't be good
- TUint32 maxAddress = (~aMemoryInfo.iSize) + 1;
- if(aMemoryInfo.iAddress > maxAddress)
- User::Leave(KErrArgument);
-
- //check that arguments are supported
- if(aMemoryInfo.iAccess != EAccess32)
- User::Leave(KErrNotSupported);
-
- if(aMemoryInfo.iEndianess != EEndLE8)
- User::Leave(KErrNotSupported);
-
- //check that address is multiple of access size
- TInt addressIndicator = aMemoryInfo.iAddress % aMemoryInfo.iAccess;
- if(addressIndicator != 0)
- {
- User::Leave(KErrArgument);
- }
-
- //check that size is multiple of access size
- TInt sizeIndicator = aMemoryInfo.iSize % aMemoryInfo.iAccess;
- if(sizeIndicator != 0)
- User::Leave(KErrArgument);
- }
-
-/**
-Helper function
-
-Validates that the three buffers relating to reading register data are of
-appropriate sizes, and calculates the number of registers being requested.
-
-@param aMessage message which in offsets 1, 2 and 3 contains descriptors
-@param aNumberOfRegisters if the function returns with KErrNone this will
- contain the number of registers being requested, guaranteed to be non-zero
-
-@leave KErrArgument if descriptors do not represent the same number of
- registers, if any of the descriptors have max length of 0, if any of
- the descriptors have max lengths which are not multiples of their data
- type's size or if any of the descriptors have max lengths greater than
- the max block size for memory operations
- or one of the other system wide error codes if there were problems
- in getting the descriptors' lengths.
-*/
-void CSecuritySvrSession::ValidateRegisterBuffersL(const RMessage2& aMessage, TUint32& aNumberOfRegisters)
- {
- //get lengths of buffers, if error occurs returned value will be less then zero
- TInt idsBufferLength = aMessage.GetDesMaxLength(1);
- if(idsBufferLength < 0)
- {
- User::Leave(idsBufferLength);
- }
- TInt valuesBufferLength = aMessage.GetDesMaxLength(2);
- if(valuesBufferLength < 0)
- {
- User::Leave(valuesBufferLength);
- }
- TInt flagsBufferLength = aMessage.GetDesMaxLength(3);
- if(flagsBufferLength < 0)
- {
- User::Leave(flagsBufferLength);
- }
-
- //get the max block size supported
- TUint32 maxSize = 0;
- User::LeaveIfError(Server().iKernelDriver.GetMemoryOperationMaxBlockSize(maxSize));
-
- //check none of the descriptors have size greater than the max block size
- if((idsBufferLength > maxSize) || (valuesBufferLength > maxSize) || (flagsBufferLength > maxSize))
- User::Leave(KErrArgument);
-
- //get sizes of the three types of data the buffers represent arrays of
- //and validate that the buffer lengths are multiples of the data sizes
- TUint idSize = sizeof(TRegisterInfo);
- if(idsBufferLength % idSize != 0)
- User::Leave(KErrArgument);
-
- TUint flagSize = sizeof(TUint8);
- if(flagsBufferLength % flagSize != 0)
- User::Leave(KErrArgument);
-
- //perform check on id buffer length
- if(idsBufferLength == 0)
- User::Leave(KErrArgument);
-
- //calculate number of registers being requested
- aNumberOfRegisters = idsBufferLength / idSize;
-
- //check flags buffer is of appropriate size
- if(flagsBufferLength != (aNumberOfRegisters * flagSize))
- User::Leave(KErrArgument);
- }
-
-/**
-Establish whether any agents have registered to debug the specified aFileName
-
-@param aFileName originating file name of the target process
-@param aPassive indicates whether to check if there has been active attachment,
-or passive attachment.
-
-@return ETrue if aFileName is being debugged, EFalse otherwise
-
-*/
-TBool CSecuritySvrSession::IsDebugged(const TDesC& aFileName, const TBool aPassive) const
- {
- //check whether the target process is being debugged
- return Server().IsDebugged(aFileName, aPassive);
- }
-
-/**
- Helper function which reads a TThreadId object from a client
-
- @param aMessage the message object containing the reference to the TThreadId
- @param aIndex the message argument containing the reference
-
- @return the TThreadId passed in by the client
- @leave KErrArgument if aIndex is outside of the valid range
- */
-TThreadId CSecuritySvrSession::ReadTThreadIdL(const RMessagePtr2& aMessage, const TInt aIndex) const
- {
- //create a temporary TThreadId to read the data into
- TThreadId tempThreadId;
- TPtr8 threadIdPtr((TUint8*)&tempThreadId, sizeof(TThreadId));
-
- // read the data in from the client
- aMessage.ReadL(aIndex, threadIdPtr);
-
- return tempThreadId;
- }
-
-/**
- Helper function which reads a TProcessId object from a client
-
- @param aMessage the message object containing the reference to the TProcessId
- @param aIndex the message argument containing the reference
-
- @return the TProcessId passed in by the client
- @leave KErrArgument if aIndex is outside of the valid range
- */
-TProcessId CSecuritySvrSession::ReadTProcessIdL(const RMessagePtr2& aMessage, const TInt aIndex) const
- {
- //create a temporary TProcessId to read the data into
- TProcessId tempProcessId;
- TPtr8 processIdPtr((TUint8*)&tempProcessId, sizeof(TProcessId));
-
- // read the data in from the client
- aMessage.ReadL(aIndex, processIdPtr);
-
- return tempProcessId;
- }
-
-// End of file - c_security_svr_session.cpp