sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\secure\t_sdrivers.cpp sl@0: // Overview: sl@0: // Test the security aspects of device drivers. sl@0: // API Information: sl@0: // N/A sl@0: // Details: sl@0: // - For a variety of capability sets, test loading and opening various sl@0: // devices and check that the results are as expected. sl@0: // Platforms/Drives/Compatibility: sl@0: // All. sl@0: // Assumptions/Requirement/Pre-requisites: sl@0: // Failures and causes: sl@0: // Base Port information: sl@0: // sl@0: // sl@0: sl@0: #define __INCLUDE_CAPABILITY_NAMES__ sl@0: sl@0: #define __E32TEST_EXTENSION__ sl@0: #include sl@0: #include sl@0: // SYM_BRANCH: Delete old sound driver sl@0: // #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: LOCAL_D RTest test(_L("T_SDRIVERS")); sl@0: sl@0: TCapabilitySet Capabilities; sl@0: sl@0: LOCAL_C TBool CheckLoaded(TInt aResult) sl@0: { sl@0: switch(aResult) sl@0: { sl@0: case KErrAlreadyExists: sl@0: RDebug::Print(_L(" Already Exists")); sl@0: return ETrue; sl@0: sl@0: case KErrNone: sl@0: RDebug::Print(_L(" No Error")); sl@0: return ETrue; sl@0: sl@0: case KErrNotFound: sl@0: RDebug::Print(_L(" Not found")); sl@0: return EFalse; sl@0: sl@0: default: sl@0: test(EFalse); sl@0: return EFalse; sl@0: } sl@0: } sl@0: sl@0: sl@0: class TDriverCheck; sl@0: typedef void (*TDriverCheckTestFunction)(TDriverCheck&); sl@0: sl@0: class TDriverCheck sl@0: { sl@0: public: sl@0: TBool Check(TInt aResult); sl@0: void ShowResult(); sl@0: public: sl@0: TDriverCheckTestFunction iTestFunction; sl@0: const char* iDeviceName; sl@0: TCapability iCapability; sl@0: TBool iTested; sl@0: TBool iPolicingVerified; sl@0: }; sl@0: sl@0: TBool TDriverCheck::Check(TInt aResult) sl@0: { sl@0: switch(aResult) sl@0: { sl@0: case KErrNotSupported: sl@0: RDebug::Print(_L(" Not Supported")); sl@0: return ETrue; sl@0: case KErrInUse: sl@0: RDebug::Print(_L(" In Use")); sl@0: return ETrue; sl@0: case KErrAccessDenied: sl@0: RDebug::Print(_L(" Access Denied (In Use?)")); sl@0: return ETrue; sl@0: case KErrNone: sl@0: RDebug::Print(_L(" No Error")); sl@0: break; sl@0: case KErrPermissionDenied: sl@0: RDebug::Print(_L(" Permission Denied")); sl@0: break; sl@0: default: sl@0: RDebug::Print(_L(" Error %d"),aResult); sl@0: return ETrue; sl@0: } sl@0: sl@0: if(Capabilities.HasCapability(iCapability)) sl@0: { sl@0: if(aResult==KErrNone) sl@0: iTested = 1; sl@0: return aResult==KErrNone; sl@0: } sl@0: else if(PlatSec::IsCapabilityEnforced(iCapability)) sl@0: { sl@0: if(aResult==KErrPermissionDenied) sl@0: iPolicingVerified = 1; sl@0: return aResult==KErrPermissionDenied; sl@0: } sl@0: else sl@0: { sl@0: return aResult==KErrNone; sl@0: } sl@0: } sl@0: sl@0: void TDriverCheck::ShowResult() sl@0: { sl@0: TBuf8<32> nameBuf((const TUint8*)iDeviceName); sl@0: TPtr name(nameBuf.Expand()); sl@0: if(iTested) sl@0: { sl@0: if(iPolicingVerified) sl@0: test.Printf(_L("* %S - Verified security checking\n"),&name); sl@0: else sl@0: test.Printf(_L("* %S - Did NOT verify security checking (Capabilties may be disabled)\n"),&name); sl@0: } sl@0: else sl@0: test.Printf(_L("* %S - Not tested (Driver may be missing or in use)\n"),&name); sl@0: } sl@0: sl@0: void TestELOCD(TDriverCheck& aCheck) sl@0: { sl@0: test.Next(_L("ELOCD")); sl@0: sl@0: test.Start(_L("Trying RLocalDrive with all local drives")); sl@0: TInt i; sl@0: TInt r; sl@0: for(i=0; i pddName=COMM_PDD_NAME; sl@0: for (i=-1; i0) sl@0: pddName[pddName.Length()-1] = (TText)('0'+i); sl@0: r = User::LoadPhysicalDevice(pddName); sl@0: CheckLoaded(r); sl@0: } sl@0: test.Next(_L("Load LDD")); sl@0: r = User::LoadLogicalDevice(_L("ECOMM.LDD")); sl@0: if(!CheckLoaded(r)) sl@0: goto done; sl@0: sl@0: test.Next(_L("Open Channels")); sl@0: for(i=0; i<10; i++) sl@0: { sl@0: RBusDevComm commDevice; sl@0: r = commDevice.Open(i); sl@0: test(aCheck.Check(r)); sl@0: commDevice.Close(); sl@0: } sl@0: done: sl@0: test.End(); sl@0: } sl@0: sl@0: void TestEUSBC(TDriverCheck& aCheck) sl@0: { sl@0: test.Next(_L("EUSBC")); sl@0: sl@0: test.Start(_L("Load LDD")); sl@0: TInt r = User::LoadLogicalDevice(_L("EUSBC.LDD")); sl@0: if(!CheckLoaded(r)) sl@0: goto done; sl@0: test.Next(_L("Open Channel")); sl@0: { sl@0: RDevUsbcClient usbDevice; sl@0: r = usbDevice.Open(0); sl@0: test(aCheck.Check(r)); sl@0: usbDevice.Close(); sl@0: } sl@0: done: sl@0: test.End(); sl@0: } sl@0: sl@0: void TestENET(TDriverCheck& aCheck) sl@0: { sl@0: test.Next(_L("ENET")); sl@0: sl@0: test.Start(_L("Load PDD")); sl@0: TInt r = User::LoadPhysicalDevice(_L("ETHERNET.PDD")); sl@0: if(!CheckLoaded(r)) sl@0: goto done; sl@0: test.Start(_L("Load LDD")); sl@0: r = User::LoadLogicalDevice(_L("ENET.LDD")); sl@0: if(!CheckLoaded(r)) sl@0: goto done; sl@0: test.Next(_L("Open Channel")); sl@0: { sl@0: RBusDevEthernet ethernetDevice; sl@0: r = ethernetDevice.Open(0); sl@0: test(aCheck.Check(r)); sl@0: ethernetDevice.Close(); sl@0: } sl@0: done: sl@0: test.End(); sl@0: } sl@0: sl@0: // SYM_BRANCH: Delete old sound driver sl@0: #if 0 sl@0: void TestESOUND(TDriverCheck& aCheck) sl@0: { sl@0: test.Next(_L("ESOUND")); sl@0: sl@0: test.Start(_L("Load PDD")); sl@0: TInt r = User::LoadPhysicalDevice(_L("ESDRV.PDD")); sl@0: if(!CheckLoaded(r)) sl@0: goto done; sl@0: test.Next(_L("Load LDD")); sl@0: r = User::LoadLogicalDevice(_L("ESOUND.LDD")); sl@0: if(!CheckLoaded(r)) sl@0: goto done; sl@0: test.Next(_L("Open Channel")); sl@0: { sl@0: RMdaDevSound soundDevice; sl@0: r = soundDevice.Open(); sl@0: test(aCheck.Check(r)); sl@0: soundDevice.Close(); sl@0: } sl@0: done: sl@0: test.End(); sl@0: } sl@0: #endif sl@0: sl@0: TDriverCheck DriverList[] = sl@0: { sl@0: {TestELOCD,"ELOCD",ECapabilityTCB}, sl@0: {TestECOMM,"ECOMM",ECapabilityCommDD}, sl@0: {TestEUSBC,"EUSBC",ECapabilityCommDD}, sl@0: {TestENET,"ENET",ECapabilityCommDD}, sl@0: // SYM_BRANCH: Delete old sound driver sl@0: // {TestESOUND,"ESOUND",ECapabilityMultimediaDD}, sl@0: {0} sl@0: }; sl@0: sl@0: LOCAL_C TInt DoTests() sl@0: { sl@0: TInt result=0; sl@0: test.Start(_L("Testing all LDDs...")); sl@0: TInt i=0; sl@0: while(DriverList[i].iTestFunction) sl@0: { sl@0: (*DriverList[i].iTestFunction)(DriverList[i]); sl@0: result |= DriverList[i].iTested<<(i*2); sl@0: result |= DriverList[i].iPolicingVerified<<(i*2+1); sl@0: ++i; sl@0: } sl@0: test.End(); sl@0: return result^0x55555555; sl@0: } sl@0: sl@0: sl@0: enum TTestProcessFunctions sl@0: { sl@0: ETestProcessDoTests, sl@0: }; sl@0: sl@0: sl@0: #include "d_sldd.h" sl@0: #include "u32std.h" sl@0: sl@0: RDevice TestDevice; sl@0: sl@0: TInt TestGetCapsThread(TAny* aDes) sl@0: { sl@0: RThread::Rendezvous(KErrNone); sl@0: TestDevice.GetCaps(*(TDes8*)aDes); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void TestGetCaps() sl@0: { sl@0: TUint memModelAttributes = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL); sl@0: if((memModelAttributes&EMemModelAttrKernProt)==false) sl@0: return; // no kernel protection to test sl@0: sl@0: // open test device... sl@0: test.Start(_L("Open test driver")); sl@0: RLddTest ldd; sl@0: _LIT(KTestDeviceName,"D_SLDD"); sl@0: TInt r = User::LoadLogicalDevice(KTestDeviceName); sl@0: test(r == KErrNone || r == KErrAlreadyExists); sl@0: r = TestDevice.Open(KTestDeviceName); sl@0: test_KErrNone(r); sl@0: r = ldd.OpenLocal(); sl@0: test_KErrNone(r); sl@0: sl@0: // get address of some kernel data... sl@0: TUint32* kernelPtr; sl@0: TUint32 kernelData; sl@0: ldd.KernelTestData(kernelPtr,kernelData); sl@0: sl@0: // check device GetCaps works... sl@0: test.Next(_L("Check GetCaps")); sl@0: _LIT8(KDummyTestData,"Dummy Test Data"); sl@0: TBuf8<256> caps; sl@0: caps.Copy(KDummyTestData); sl@0: test(caps.Compare(KDummyTestData)==0); sl@0: TestDevice.GetCaps(caps); sl@0: test(caps.Compare(KDummyTestData)!=0); sl@0: sl@0: // get another thread to try and call device GetCaps to write to kernel data... sl@0: test.Next(_L("Check GetCaps with bad descriptor")); sl@0: TPtr8 badCaps((TUint8*)kernelPtr,sizeof(TUint32)); sl@0: RThread thread; sl@0: r = thread.Create(_L("TestGetCapsThread"),TestGetCapsThread,KDefaultStackSize,0x2000,0x2000,(TAny*)&badCaps); sl@0: test_KErrNone(r); sl@0: TRequestStatus ls; sl@0: thread.Logon(ls); sl@0: TRequestStatus rs; sl@0: thread.Rendezvous(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: User::WaitForRequest(ls); sl@0: test_Equal(EExitPanic,thread.ExitType()); sl@0: thread.Close(); sl@0: sl@0: // check kernel data is unchanged... sl@0: TUint32 kernelData2; sl@0: ldd.KernelTestData(kernelPtr,kernelData2); sl@0: test_Equal(kernelData,kernelData2); sl@0: sl@0: // get another thread to try and call device GetCaps with descriptor in kernel memory... sl@0: test.Next(_L("Check GetCaps with bad descriptor 2")); sl@0: r = thread.Create(_L("TestGetCapsThread"),TestGetCapsThread,KDefaultStackSize,0x2000,0x2000,(TAny*)kernelPtr); sl@0: test_KErrNone(r); sl@0: thread.Logon(ls); sl@0: thread.Rendezvous(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: User::WaitForRequest(ls); sl@0: test_Equal(EExitPanic,thread.ExitType()); sl@0: thread.Close(); sl@0: sl@0: // check kernel data is unchanged... sl@0: ldd.KernelTestData(kernelPtr,kernelData2); sl@0: test_Equal(kernelData,kernelData2); sl@0: sl@0: // cleanup... sl@0: ldd.Close(); sl@0: TestDevice.Close(); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: sl@0: #include "testprocess.h" sl@0: sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: Capabilities = TSecurityInfo(RProcess()).iCaps; sl@0: sl@0: test.Title(); sl@0: sl@0: if(User::CommandLineLength()) sl@0: { sl@0: TBuf<128> message; sl@0: __ASSERT_COMPILE(ECapability_Limit<64); sl@0: message.AppendFormat(_L("Tests with capabilities %08x%08x"),((TUint32*)&Capabilities)[1],((TUint32*)&Capabilities)[0]); sl@0: test.Start(message); sl@0: TInt result = DoTests(); sl@0: // Don't test.End() so we don't get lots of 'Success's in logs sl@0: return(result); sl@0: } sl@0: sl@0: test.Start(_L("Start")); sl@0: sl@0: test.Next(_L("Check driver GetCaps() vulnerability")); sl@0: TestGetCaps(); sl@0: sl@0: TInt i; sl@0: TInt c; sl@0: for(c=0; c message; sl@0: TCapabilitySet caps; sl@0: caps.SetAllSupported(); sl@0: if(!caps.HasCapability((TCapability)c)) sl@0: continue; sl@0: caps.RemoveCapability((TCapability)c); sl@0: TBuf8<128> capNameBuf; sl@0: capNameBuf.Copy((const TUint8*)CapabilityNames[c]); sl@0: TPtr capName(capNameBuf.Expand()); sl@0: message.AppendFormat(_L("Tests with all capabilities except %S"),&capName); sl@0: test.Next(message); sl@0: p.Create(*(TUint32*)&caps,ETestProcessDoTests); sl@0: p.Logon(s); sl@0: p.Resume(); sl@0: User::WaitForRequest(s); sl@0: test(p.ExitType()==EExitKill); sl@0: TInt result=s.Int()^0x55555555; sl@0: i=0; sl@0: while(DriverList[i].iTestFunction) sl@0: { sl@0: if(result & (1<<(i*2))) sl@0: DriverList[i].iTested = ETrue; sl@0: if(result & (1<<(i*2+1))) sl@0: DriverList[i].iPolicingVerified = ETrue; sl@0: ++i; sl@0: } sl@0: test((result>>(i*2))==0); sl@0: CLOSE_AND_WAIT(p); sl@0: } sl@0: // Show results requiring manual inspection sl@0: _LIT(KSeperatorText,"----------------------------------------------------------------------------\n"); sl@0: test.Printf(_L("\n")); sl@0: test.Printf(_L("RESULTS\n")); sl@0: test.Printf(KSeperatorText); sl@0: i=0; sl@0: while(DriverList[i].iTestFunction) sl@0: { sl@0: DriverList[i].ShowResult(); sl@0: ++i; sl@0: } sl@0: test.Printf(KSeperatorText); sl@0: sl@0: // Wait for a while, or for a key press sl@0: test.Printf(_L("Waiting a short while for key press...\n")); sl@0: TRequestStatus keyStat; sl@0: test.Console()->Read(keyStat); sl@0: RTimer timer; sl@0: test(timer.CreateLocal()==KErrNone); sl@0: TRequestStatus timerStat; sl@0: timer.After(timerStat,20*1000000); sl@0: User::WaitForRequest(timerStat,keyStat); sl@0: TInt key = 0; sl@0: if(keyStat!=KRequestPending) sl@0: key = test.Console()->KeyCode(); sl@0: timer.Cancel(); sl@0: test.Console()->ReadCancel(); sl@0: User::WaitForAnyRequest(); sl@0: sl@0: test.End(); sl@0: return(0); sl@0: } sl@0: