kerneltest/e32test/secure/t_sdrivers.cpp
changeset 0 a41df078684a
child 102 ef2a444a7410
child 121 661475905584
--- /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);
+    }
+