--- /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 <e32test.h>
+#include <e32svr.h>
+// SYM_BRANCH: Delete old sound driver
+// #include <mdasound.h>
+#include <d32comm.h>
+#include <d32usbc.h>
+#include <d32ethernet.h>
+
+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<KMaxLocalDrives; i++)
+ {
+ RLocalDrive localDrive;
+ TInt changedFlag = 0;
+ r = localDrive.Connect(i,changedFlag);
+ test(aCheck.Check(r));
+ localDrive.Close();
+ }
+ test.End();
+ }
+
+#if defined (__WINS__)
+#define COMM_PDD_NAME _L("ECDRV.PDD")
+const TInt KMaxCommPdds=0;
+#else
+#define COMM_PDD_NAME _L("EUART")
+const TInt KMaxCommPdds=10;
+#endif
+
+void TestECOMM(TDriverCheck& aCheck)
+ {
+ test.Next(_L("ECOMM"));
+
+ test.Start(_L("Load PDDs"));
+ TInt i;
+ TInt r;
+ TBuf<10> pddName=COMM_PDD_NAME;
+ for (i=-1; i<KMaxCommPdds; ++i)
+ {
+ if (i==0)
+ pddName.Append(TChar('0'));
+ else if (i>0)
+ 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<ECapability_Limit; c++)
+ {
+ RTestProcess p;
+ TRequestStatus s;
+ TBuf<128> 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);
+ }
+