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