--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/secure/t_sserver.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1228 @@
+// Copyright (c) 2001-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_sserver.cpp
+// Overview:
+// Test the security aspects of server connect by handle.
+// API Information:
+// CSession2, CServer2
+// Details:
+// - Test asynchronous server connect in various ways. Verify results
+// are as expected.
+// - Attempt to create a protected server without and without
+// KCapabilityProtServ. Verify results are as expected.
+// - Attempt to connect to a serve with different Secure IDs, Vendor IDs
+// and capabilities. Verify results are as expected.
+// - Test creating a sub-session, sending it messages and closing it.
+// Verify the results.
+// - Test TIpcArgs::Set and IPC argument passing. Verify results are
+// as expected.
+// - Test TIpcArgs:: Also checks the integrity of the server and Kernel if client passes bad descriptor
+// for IPC transfer and the integrity of the client and Kernel if the server does the same.
+// - Test CServer2::RunError and CSession2::ServiceError and session
+// resource counting.
+// Platforms/Drives/Compatibility:
+// All.
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+//
+//
+
+#include <e32test.h>
+#include "../misc/prbs.h"
+
+LOCAL_D RTest test(_L("T_SSERVER"));
+
+_LIT_SECURE_ID(KTestSecureId,0x101f534d);
+_LIT_SECURE_ID(KTestSecureId2,0x101f534e);
+_LIT_VENDOR_ID(KTestVendorId,0x01234567);
+_LIT_VENDOR_ID(KTestVendorId2,0x01234568);
+const TInt KTestRunErrorModifier = 111;
+const TInt KTestServiceErrorModifier = 222;
+_LIT(KProtectedServerName,"!T_SSERVER-protected-server");
+
+
+
+enum TTestProcessFunctions
+ {
+ ETestProcessServer,
+ ETestProcessCreateProtectedServer,
+ };
+
+#include "testprocess.h"
+
+
+
+//
+// RTestThread
+//
+
+class RTestThread : public RThread
+ {
+public:
+ void Create(TThreadFunction aFunction,TAny* aArg=0);
+ };
+
+void RTestThread::Create(TThreadFunction aFunction,TAny* aArg)
+ {
+ TInt r=RThread::Create(_L(""),aFunction,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,aArg);
+ test(r==KErrNone);
+ }
+
+
+
+//
+// CTestSession
+//
+
+enum TTestSessionFuntions
+ {
+ ETestShutdown,EPing,
+ ETestArgUnspecified,ETestArgDesC8,ETestArgDesC16,ETestArgDes8,ETestArgDes16,
+ ETestResourceCountPass=0x01234567,ETestResourceCountFail,ETestServiceLeave,
+ ETestCreateSubSession,ETestCloseSubSession,ETestCloseSubSessionHandle,
+ ETestEchoArgs,ETestEmptySubSessionMessage, ETestBadClientDescRead, ETestBadClientDescWrite,
+ ETestBadServerDescRead, ETestBadServerDescWrite
+ };
+
+class CTestSession : public CSession2
+ {
+public:
+ CTestSession();
+ virtual void ServiceL(const RMessage2& aMessage);
+ virtual void ServiceError(const RMessage2& aMessage,TInt aError);
+private:
+ TInt CountResources();
+private:
+ TInt iResourceCount;
+ TInt iSubSessionCloseHandle;
+ RMessage2 iMessage;
+ };
+
+class CTestSecureServer : public CServer2
+ {
+public:
+ CTestSecureServer(TInt aPriority);
+ virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
+private:
+ void CustomL(const RMessage2& aMessage);
+ void QueryL(const RMessage2& aMessage,HBufC8*& aQueryParams);
+ TInt RunError(TInt aError);
+private:
+ friend class CTestSession;
+ };
+
+CTestSession::CTestSession()
+ : CSession2()
+ {}
+
+void CTestSession::ServiceL(const RMessage2& aMessage)
+ {
+ TInt r = KErrNotSupported;
+ TBuf8<100> buf8;
+ buf8.Append(_L8("12345"));
+ TBuf16<100> buf16;
+ buf16.Append(_L16("12345"));
+ TInt testArg = ((TUint)aMessage.Function())>>28;
+
+ TInt badDescriptorError = PlatSec::ConfigSetting(PlatSec::EPlatSecProcessIsolation)&&PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)
+ ? KErrBadDescriptor : KErrNone;
+
+ switch(aMessage.Function()&0x0fffffff)
+ {
+ case ETestShutdown:
+ CActiveScheduler::Stop();
+ return;
+
+ case EPing:
+ r=aMessage.Int0();
+ break;
+
+ case ETestArgUnspecified:
+ r = aMessage.GetDesLength(testArg);
+ if(r!=KErrBadDescriptor)
+ goto fail;
+ r = aMessage.GetDesMaxLength(testArg);
+ if(r!=KErrBadDescriptor)
+ goto fail;
+ r = aMessage.Read(testArg,buf8);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf8));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Read(testArg,buf16);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf16));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Write(testArg,buf8);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf8));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Write(testArg,buf16);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf16));
+ if(r!=badDescriptorError)
+ goto fail;
+ goto pass;
+
+ case ETestArgDesC8:
+ r = aMessage.GetDesLength(testArg);
+ if(r<0)
+ goto fail;
+ r = aMessage.GetDesMaxLength(testArg);
+ if(r<0)
+ goto fail;
+ r = aMessage.Read(testArg,buf8);
+ if(r!=KErrNone)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf8));
+ if(r!=KErrNone)
+ goto fail;
+ r = aMessage.Read(testArg,buf16);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf16));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Write(testArg,buf8);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf8));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Write(testArg,buf16);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf16));
+ if(r!=badDescriptorError)
+ goto fail;
+ goto pass;
+
+ case ETestArgDesC16:
+ r = aMessage.GetDesLength(testArg);
+ if(r<0)
+ goto fail;
+ r = aMessage.GetDesMaxLength(testArg);
+ if(r<0)
+ goto fail;
+ r = aMessage.Read(testArg,buf8);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf8));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Read(testArg,buf16);
+ if(r!=KErrNone)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf16));
+ if(r!=KErrNone)
+ goto fail;
+ r = aMessage.Write(testArg,buf8);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf8));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Write(testArg,buf16);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf16));
+ if(r!=badDescriptorError)
+ goto fail;
+ goto pass;
+
+ case ETestArgDes8:
+ r = aMessage.GetDesLength(testArg);
+ if(r<0)
+ goto fail;
+ r = aMessage.GetDesMaxLength(testArg);
+ if(r<0)
+ goto fail;
+ r = aMessage.Read(testArg,buf8);
+ if(r!=KErrNone)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf8));
+ if(r!=KErrNone)
+ goto fail;
+ r = aMessage.Read(testArg,buf16);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf16));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Write(testArg,buf8);
+ if(r!=KErrNone)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf8));
+ if(r!=KErrNone)
+ goto fail;
+ r = aMessage.Write(testArg,buf16);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf16));
+ if(r!=badDescriptorError)
+ goto fail;
+ goto pass;
+
+ case ETestArgDes16:
+ r = aMessage.GetDesLength(testArg);
+ if(r<0)
+ goto fail;
+ r = aMessage.GetDesMaxLength(testArg);
+ if(r<0)
+ goto fail;
+ r = aMessage.Read(testArg,buf8);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf8));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Read(testArg,buf16);
+ if(r!=KErrNone)
+ goto fail;
+ TRAP(r,aMessage.ReadL(testArg,buf16));
+ if(r!=KErrNone)
+ goto fail;
+ r = aMessage.Write(testArg,buf8);
+ if(r!=badDescriptorError)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf8));
+ if(r!=badDescriptorError)
+ goto fail;
+ r = aMessage.Write(testArg,buf16);
+ if(r!=KErrNone)
+ goto fail;
+ TRAP(r,aMessage.WriteL(testArg,buf16));
+ if(r!=KErrNone)
+ goto fail;
+ goto pass;
+
+ case ETestBadClientDescRead:
+ //Testing the integrity of the server and Kernel if the client passes bad descriptor for IPC transfer
+ {
+ r = aMessage.GetDesLength(testArg);
+ TUint8* buff;
+ buff = (TUint8*)User::Alloc(r);
+ if (!buff)
+ {
+ r=KErrNoMemory;
+ break;
+ }
+ TPtr8 ptr8(buff, r, r);
+ r=aMessage.Read(testArg,ptr8);
+ User::Free(buff);
+ }
+ break;
+
+ case ETestBadClientDescWrite:
+ //Testing the integrity of the server and Kernel if the client passes bad descriptor for IPC transfer
+ {
+ r = aMessage.GetDesLength(testArg);
+ TUint8* buff;
+ buff = (TUint8*)User::Alloc(r);
+ if (!buff)
+ {
+ r=KErrNoMemory;
+ break;
+ }
+ TPtr8 ptr8(buff, r, r);
+ r=aMessage.Write(testArg,ptr8);
+ User::Free(buff);
+ }
+ break;
+
+ case ETestBadServerDescRead:
+ case ETestBadServerDescWrite:
+ //Testing the integrity of the client and Kernel if server passes bad descriptor for IPC transfer
+ {
+ //Create a chunk with a hole between addresses 0x1000 and 0x2000
+ RChunk c;
+ r=c.CreateDisconnectedLocal(0,0,0x200000);
+ test(r==KErrNone);
+ r=c.Commit(0,0x1000);
+ test(r==KErrNone);
+ r=c.Commit(0x2000,0x1000);
+ test(r==KErrNone);
+
+ TInt base,len;
+ switch(aMessage.Function()>>28)
+ {
+ case 0:base=0x1000;len=0x500;break;
+ case 1:base=0x1001;len=0x500;break;
+ case 2:base=0x1007;len=0x500;break;
+ case 3:base=0x1ff0;len=0x100;break;
+ case 4:base=0x1ff1;len=0x100;break;
+ case 5:base=0x1ff2;len=0x100;break;
+ case 6:base=0xff3;len=0x100;break;
+ default:base=0xfff;len=0x100;break;
+ }
+
+ TPtr8 ptr (c.Base()+base,len,len);
+ if ((aMessage.Function()&0x0fffffff) == ETestBadServerDescRead)
+ aMessage.Read(0,ptr); //The server should panic here
+ else
+ aMessage.Write(0,ptr); //The server should panic here
+ }
+ break;
+
+ case ETestResourceCountPass:
+ r=aMessage.Function();
+ ResourceCountMarkStart();
+ ResourceCountMarkEnd(aMessage);
+ break;
+
+ case ETestResourceCountFail:
+ r=aMessage.Function();
+ ResourceCountMarkStart();
+ ++iResourceCount;
+ ResourceCountMarkEnd(aMessage);
+ break;
+
+ case ETestServiceLeave:
+ iMessage = aMessage;
+ User::Leave(aMessage.Int0());
+ break;
+
+ case ETestCreateSubSession:
+ {
+ TInt reply = aMessage.Int0();
+ r = aMessage.Write(3,TPtrC8((TUint8*)&reply,sizeof(reply)));
+ }
+ break;
+
+ case ETestCloseSubSession:
+ iSubSessionCloseHandle = aMessage.Int3();
+ r = KErrNone;
+ break;
+
+ case ETestCloseSubSessionHandle:
+ r = iSubSessionCloseHandle;
+ iSubSessionCloseHandle = 0;
+ break;
+
+ case ETestEchoArgs:
+ {
+ TInt reply[4];
+ reply[0] = aMessage.Int0();
+ reply[1] = aMessage.Int1();
+ reply[2] = aMessage.Int2();
+ reply[3] = aMessage.Int3();
+ r = aMessage.Write(0,TPtrC8((TUint8*)&reply,sizeof(reply)));
+ }
+ break;
+
+ case ETestEmptySubSessionMessage:
+ r = aMessage.Int3();
+ break;
+
+ default:
+ break;
+ }
+ if(aMessage.Handle())
+ aMessage.Complete(r);
+ return;
+fail:
+ aMessage.Complete(KErrGeneral);
+ return;
+pass:
+ aMessage.Complete(KErrNone);
+ return;
+ }
+
+TInt CTestSession::CountResources()
+ {
+ return iResourceCount;
+ }
+
+void CTestSession::ServiceError(const RMessage2& aMessage,TInt aError)
+ {
+ if(aMessage!=iMessage)
+ aError = KErrGeneral; // We got given the right message
+ else
+ aError += KTestServiceErrorModifier; // Let test harnes know we came through this routine
+ CSession2::ServiceError(aMessage,aError);
+ }
+
+//
+// CTestSecureServer
+//
+
+CTestSecureServer::CTestSecureServer(TInt aPriority)
+ : CServer2(aPriority,EGlobalSharableSessions)
+ {
+ }
+
+CSession2* CTestSecureServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
+ {
+ if(*(TInt*)&aVersion)
+ User::Leave(KErrNotSupported); // Only accept version 0.0.00
+ return new (ELeave) CTestSession();
+ }
+
+TInt CTestSecureServer::RunError(TInt aError)
+ {
+ return CServer2::RunError(aError+KTestRunErrorModifier); // Let test harnes know we came through this routine
+ }
+
+
+//
+// CTestActiveScheduler
+//
+
+class CTestActiveScheduler : public CActiveScheduler
+ {
+public:
+ virtual void Error(TInt anError) const;
+ };
+
+void CTestActiveScheduler::Error(TInt anError) const
+ {
+ User::Panic(_L("TestServer Error"),anError);
+ }
+
+
+
+//
+// Server thread
+//
+
+_LIT(KServerName,"T_SSERVER-server");
+const TInt KServerRendezvous = KRequestPending+1;
+
+void DoStartServer()
+ {
+ CTestActiveScheduler* activeScheduler = new (ELeave) CTestActiveScheduler;
+ CActiveScheduler::Install(activeScheduler);
+ CleanupStack::PushL(activeScheduler);
+
+ CTestSecureServer* server = new (ELeave) CTestSecureServer(0);
+ CleanupStack::PushL(server);
+
+ User::LeaveIfError(server->Start(KServerName));
+
+ RProcess::Rendezvous(KServerRendezvous);
+
+ CActiveScheduler::Start();
+
+ CleanupStack::PopAndDestroy(2);
+ }
+
+TInt StartServer()
+ {
+ CTrapCleanup* cleanupStack = CTrapCleanup::New();
+ if(!cleanupStack)
+ return KErrNoMemory;
+ TRAPD(leaveError,DoStartServer())
+ delete cleanupStack;
+ return leaveError;
+ }
+
+
+
+//
+// RTestSession
+//
+
+class RTestSession : public RSessionBase
+ {
+public:
+ inline TInt Connect()
+ {
+ TInt r=CreateSession(KServerName,TVersion());
+ if(r) return r;
+ return ShareAuto();
+ }
+ inline TInt Connect(const TSecurityPolicy* aPolicy)
+ {
+ return CreateSession(KServerName,TVersion(),-1,EIpcSession_Unsharable,aPolicy,0);
+ }
+ inline TInt Connect(TVersion aVersion,TRequestStatus* aStatus)
+ {
+ return CreateSession(KServerName,aVersion,-1,EIpcSession_Unsharable,0,aStatus);
+ }
+ inline TInt Send(TInt aFunction)
+ { return RSessionBase::SendReceive(aFunction); }
+ inline TInt Send(TInt aFunction,const TIpcArgs& aArgs)
+ { return RSessionBase::SendReceive(aFunction,aArgs); }
+ inline void Send(TInt aFunction,TRequestStatus& aStatus)
+ { RSessionBase::SendReceive(aFunction,aStatus); }
+ inline void Send(TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aStatus)
+ { RSessionBase::SendReceive(aFunction,aArgs,aStatus); }
+ };
+
+
+
+//
+// RTestSubSession
+//
+
+class RTestSubSession : public RSubSessionBase
+ {
+public:
+ inline TInt CreateSubSession(RSessionBase& aSession,TInt aFunction,const TIpcArgs& aArgs)
+ { return RSubSessionBase::CreateSubSession(aSession,aFunction,aArgs); }
+ inline TInt CreateSubSession(RSessionBase& aSession,TInt aFunction)
+ { return RSubSessionBase::CreateSubSession(aSession,aFunction); }
+ inline void CloseSubSession(TInt aFunction)
+ { RSubSessionBase::CloseSubSession(aFunction); }
+ inline TInt Send(TInt aFunction)
+ { return RSubSessionBase::SendReceive(aFunction); }
+ inline TInt Send(TInt aFunction,const TIpcArgs& aArgs)
+ { return RSubSessionBase::SendReceive(aFunction,aArgs); }
+ inline void Send(TInt aFunction,TRequestStatus& aStatus)
+ { RSubSessionBase::SendReceive(aFunction,aStatus); }
+ inline void Send(TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aStatus)
+ { RSubSessionBase::SendReceive(aFunction,aArgs,aStatus); }
+ };
+
+
+
+RTestSession Session;
+TInt TestParam = 0;
+
+TInt TestThreadFunction(TAny* aParam)
+ {
+ return Session.Send((TInt)aParam,TIpcArgs(TestParam));
+ }
+
+void DoTest(TInt aFunction,TExitType aExitType,TInt aExitReason,TInt aParam=0)
+ {
+ TBuf<256> title;
+ title.AppendFormat(_L("Function %d"),aFunction);
+ test.Next(title);
+
+ RTestThread thread;
+ thread.Create(TestThreadFunction,(TAny*)aFunction);
+ TRequestStatus logon;
+ thread.Logon(logon);
+ TestParam = aParam;
+
+ User::SetJustInTime(EFalse);
+ thread.Resume();
+ User::WaitForRequest(logon);
+ User::SetJustInTime(ETrue);
+
+ TExitType exitType=thread.ExitType();
+ TInt exitReason=thread.ExitReason();
+ test(exitType==aExitType);
+ test(exitReason==aExitReason);
+ CLOSE_AND_WAIT(thread);
+ }
+
+//
+// Anonymous server
+//
+
+class RTestAnonymousSession : public RTestSession
+ {
+public:
+ inline TInt Connect(RServer2 aServer)
+ {
+ TInt r=CreateSession(aServer,TVersion());
+ if(r) return r;
+ return ShareProtected();
+ }
+ inline TInt Connect()
+ {
+ return CreateSession(_L(""),TVersion());
+ }
+ };
+
+CTestSecureServer* AnonymousServer;
+
+void DoStartAnonymousServer()
+ {
+ CTestActiveScheduler* activeScheduler = new (ELeave) CTestActiveScheduler;
+ CActiveScheduler::Install(activeScheduler);
+ CleanupStack::PushL(activeScheduler);
+
+ CTestSecureServer* server = new (ELeave) CTestSecureServer(0);
+ CleanupStack::PushL(server);
+
+ User::LeaveIfError(server->Start(KNullDesC));
+
+ AnonymousServer = server;
+ RThread::Rendezvous(KServerRendezvous);
+
+ CActiveScheduler::Start();
+
+ CleanupStack::PopAndDestroy(2);
+ }
+
+TInt StartAnonymousServer(TAny* /*aPtr*/)
+ {
+ CTrapCleanup* cleanupStack = CTrapCleanup::New();
+ if(!cleanupStack)
+ return KErrNoMemory;
+ TRAPD(leaveError,DoStartAnonymousServer())
+ delete cleanupStack;
+ return leaveError;
+ }
+
+void TestConnectByHandle()
+ {
+ RTestAnonymousSession session;
+ TRequestStatus logon;
+ TInt r;
+
+ test.Start(_L("Starting a local server"));
+ RTestThread thread;
+ thread.Create(StartAnonymousServer);
+ TRequestStatus rendezvous;
+ TRequestStatus svrstat;
+ thread.Rendezvous(rendezvous);
+ thread.Logon(logon);
+ thread.NotifyDestruction(svrstat);
+ thread.Resume();
+ User::WaitForRequest(rendezvous);
+ test(rendezvous.Int()==KServerRendezvous);
+ thread.Close();
+
+ test.Next(_L("Check connect with null name fails"));
+ test((r=session.Connect())!=KErrNone);
+
+ test.Next(_L("Connecting to local server"));
+ test((r=session.Connect(AnonymousServer->Server()))==KErrNone);
+
+ test.Next(_L("Test the connection"));
+ test((r=session.Send(EPing,TIpcArgs(1234)))==1234);
+ test((r=session.Send(EPing,TIpcArgs(2345)))==2345);
+
+ test.Next(_L("Shutting server down"));
+ test(logon.Int()==KRequestPending);
+ test((r=session.Send(ETestShutdown))==KErrServerTerminated);
+ test(r==KErrServerTerminated);
+ session.Close();
+ User::WaitForRequest(logon);
+ test(logon.Int()==KErrNone);
+ User::WaitForRequest(svrstat);
+
+ test.End();
+ }
+
+TRequestStatus SvrStat;
+
+void RestartTestServer()
+ {
+ RTestProcess server;
+ TRequestStatus rendezvous;
+ server.Create(0,ETestProcessServer);
+ server.NotifyDestruction(SvrStat);
+ server.Rendezvous(rendezvous);
+ server.Resume();
+ User::WaitForRequest(rendezvous);
+ test(rendezvous==KServerRendezvous);
+ server.Close();
+ test(Session.Connect()==KErrNone);
+ }
+
+void TestIpc()
+ {
+ TBuf8<10> buf8((TUint8*)"abcdefghij");
+ TBuf16<10> buf16((TUint16*)L"abcdefghij");
+ TInt r;
+
+ test.Start(_L("Testing TIpcArgs::Set"));
+ {
+ TIpcArgs a(TIpcArgs::ENothing,123,(TAny*)&buf8);
+ TIpcArgs b;
+ b.Set(0,TIpcArgs::ENothing);
+ b.Set(1,123);
+ b.Set(2,(TAny*)&buf8);
+ test(a.iFlags==b.iFlags);
+ // iArgs[0] is uninitialised so don't test
+ test(a.iArgs[1]==b.iArgs[1]);
+ test(a.iArgs[2]==b.iArgs[2]);
+ }
+ {
+ TIpcArgs a((TDesC8*)&buf8,(TDesC16*)&buf16,&buf8,&buf16);
+ TIpcArgs b;
+ b.Set(0,(TDesC8*)&buf8);
+ b.Set(1,(TDesC16*)&buf16);
+ b.Set(2,&buf8);
+ b.Set(3,&buf16);
+ test(a.iFlags==b.iFlags);
+ test(a.iArgs[0]==b.iArgs[0]);
+ test(a.iArgs[1]==b.iArgs[1]);
+ test(a.iArgs[2]==b.iArgs[2]);
+ test(a.iArgs[3]==b.iArgs[3]);
+ }
+
+ test.Next(_L("Test Unspecified argument"));
+ r = Session.Send(ETestArgUnspecified,TIpcArgs((TAny*)&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgUnspecified+(1<<28),TIpcArgs(0,(TAny*)&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgUnspecified+(2<<28),TIpcArgs(0,0,(TAny*)&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgUnspecified+(3<<28),TIpcArgs(0,0,0,(TAny*)&buf8));
+ test(r==KErrNone);
+
+ test.Next(_L("Test DesC8 argument"));
+ r = Session.Send(ETestArgDesC8,TIpcArgs((TDesC8*)&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDesC8+(1<<28),TIpcArgs(0,(TDesC8*)&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDesC8+(2<<28),TIpcArgs(0,0,(TDesC8*)&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDesC8+(3<<28),TIpcArgs(0,0,0,(TDesC8*)&buf8));
+ test(r==KErrNone);
+
+ test.Next(_L("Test DesC16 argument"));
+ r = Session.Send(ETestArgDesC16,TIpcArgs((TDesC16*)&buf16));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDesC16+(1<<28),TIpcArgs(0,(TDesC16*)&buf16));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDesC16+(2<<28),TIpcArgs(0,0,(TDesC16*)&buf16));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDesC16+(3<<28),TIpcArgs(0,0,0,(TDesC16*)&buf16));
+ test(r==KErrNone);
+
+ test.Next(_L("Test Des8 argument"));
+ r = Session.Send(ETestArgDes8,TIpcArgs(&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDes8+(1<<28),TIpcArgs(0,&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDes8+(2<<28),TIpcArgs(0,0,&buf8));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDes8+(3<<28),TIpcArgs(0,0,0,&buf8));
+ test(r==KErrNone);
+
+ test.Next(_L("Test Des16 argument"));
+ r = Session.Send(ETestArgDes16,TIpcArgs(&buf16));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDes16+(1<<28),TIpcArgs(0,&buf16));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDes16+(2<<28),TIpcArgs(0,0,&buf16));
+ test(r==KErrNone);
+ r = Session.Send(ETestArgDes16+(3<<28),TIpcArgs(0,0,0,&buf16));
+ test(r==KErrNone);
+
+
+ test.Next(_L("Test Bad Client Descriptor"));
+ //The test should ensure that both server and kernel are safe if client passes faulty descriptor to the server.
+ {
+ //Create a chunk with a hole between addresses 0x1000 & 0x2000
+ RChunk c;
+ r=c.CreateDisconnectedLocal(0,0,0x200000);
+ test(r==KErrNone);
+ r=c.Commit(0,0x1000);
+ test(r==KErrNone);
+ r=c.Commit(0x2000,0x1000);
+ test(r==KErrNone);
+
+ //Each of these steps will pass bad descriptor to the server for IPC transfer in both directions.
+ //KErrBadDescriptor should be returned.
+ {
+ TPtr8 ptr (c.Base()+0x1000,0x100,0x100);
+ r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ }
+ {
+ TPtr8 ptr (c.Base()+0x1003,0x100,0x100);
+ r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ }
+ {
+ TPtr8 ptr (c.Base()+0xe00,0x500,0x500);
+ r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ }
+ {
+ TPtr8 ptr (c.Base()+0xdff,0x500,0x500);
+ r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ }
+ {
+ TPtr8 ptr (c.Base()+0x1ff1,0x500,0x500);
+ r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+ test(KErrBadDescriptor == r);
+ }
+
+ //The next step will send random descriptors for IPC transfer. Server should return either KErrNone or
+ //KErrBadDescriptor
+ {
+ TUint seed[2];
+ seed[0]=User::TickCount();
+ seed[1]=0;
+ test.Printf(_L("The initial seed for the random function is: S0=%xh S1=%xh\n"), seed[0], seed[1]);
+
+ TInt i;
+ TPtr8 ptr (0,0,0);
+ TInt noErrors = 0;
+ TInt badDescriptors = 0;
+
+ for (i=0;i<100;i++)
+ {
+ TInt descAddress = (TInt) (c.Base() + (Random(seed) % 0x1000));
+ TInt descSize=Random(seed)%0x1000;
+
+ TUint* descData = (TUint*)&ptr;
+ descData[0] = 0x20000000 + descSize;
+ descData[1] = descSize;
+ descData[2] = descAddress;
+
+ r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+ switch (r)
+ {
+ case KErrNone: noErrors++;break;
+ case KErrBadDescriptor: badDescriptors++;break;
+ default: test.Printf(_L("Error: %d returned"),r);
+ }
+
+ r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+ switch (r)
+ {
+ case KErrNone: noErrors++;break;
+ case KErrBadDescriptor: badDescriptors++;break;
+ default: test.Printf(_L("Error: %d returned"),r);
+ }
+ }
+ test.Printf(_L("KErrNoError: %d KErrBadDescriptor: %d"),noErrors, badDescriptors);
+ }
+
+ test.Next(_L("Test Bad Server Descriptor"));
+ //The test should ensure that kernel is safe if server passes faulty descriptor for IPC transfer
+ {
+ TPtr8 ptr (c.Base(),0x1000,0x1000);
+ TInt i;
+ for (i=0;i<=7;i++)
+ {
+ r = Session.Send(ETestBadServerDescRead | (i<<28),TIpcArgs(&ptr));
+ test(r==KErrServerTerminated);
+ RestartTestServer();
+ r = Session.Send(ETestBadServerDescWrite | (i<<28),TIpcArgs(&ptr));
+ test(r==KErrServerTerminated);
+ User::WaitForRequest(SvrStat);
+ RestartTestServer();
+ }
+ }
+
+ c.Close();
+ }
+ test.End();
+ }
+
+
+
+void TestSubSessions()
+ {
+ const TInt KSubSessionHandle = 0x87654321;
+ RTestSubSession sub;
+ TInt r;
+
+ test.Start(_L("Creating a subsession with no arguments"));
+ r = sub.CreateSubSession(Session,ETestCreateSubSession);
+ test(r==KErrNone);
+ test(((TInt*)&sub)[0] == (*(TInt*)&Session | CObjectIx::ENoClose)); // check sub.iSession
+
+ test.Next(_L("Creating a subsession with arguments"));
+ r = sub.CreateSubSession(Session,ETestCreateSubSession,TIpcArgs(KSubSessionHandle));
+ test(r==KErrNone);
+ test(((TInt*)&sub)[0] == (*(TInt*)&Session | CObjectIx::ENoClose)); // check sub.iSession
+
+ test(((TInt*)&sub)[1]==KSubSessionHandle); // check sub.iSubSessionHandle
+
+ test.Next(_L("Sending message with arguments"));
+ TInt reply[4] = {0};
+ TPtr8 replyDes((TUint8*)&reply,sizeof(reply));
+ r = sub.Send(ETestEchoArgs,TIpcArgs(&replyDes,123,456,789));
+ test(r==KErrNone);
+ test(reply[0]==(TInt)&replyDes);
+ test(reply[1]==123);
+ test(reply[2]==456);
+ test(reply[3]==KSubSessionHandle);
+
+ test.Next(_L("Sending empty message"));
+ r = sub.Send(ETestEmptySubSessionMessage);
+ test(r==KSubSessionHandle);
+
+ test.Next(_L("Closing subsession"));
+ sub.CloseSubSession(ETestCloseSubSession);
+ test(((TInt*)&sub)[0]==0); // check sub.iSession
+ test(((TInt*)&sub)[1]==0); // check sub.iSubSessionHandle
+ r = Session.Send(ETestCloseSubSessionHandle);
+ test(r==KSubSessionHandle);
+
+ test.End();
+ }
+
+
+void TestProtectedServers()
+ {
+ RTestProcess process;
+ TRequestStatus logonStatus;
+
+ test.Start(_L("Trying to create a protected server without KCapabilityProtServ"));
+ process.Create(~(1u<<ECapabilityProtServ),ETestProcessCreateProtectedServer);
+ process.Logon(logonStatus);
+ process.Resume();
+ User::WaitForRequest(logonStatus);
+ if(PlatSec::IsCapabilityEnforced(ECapabilityProtServ))
+ {
+ test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+ test(logonStatus==EPlatformSecurityTrap);
+ }
+ else
+ {
+ test(process.ExitType()==EExitKill);
+ test(logonStatus==KErrNone);
+ }
+ CLOSE_AND_WAIT(process);
+
+ test.Next(_L("Trying to create a protected server with KCapabilityProtServ"));
+ process.Create(1<<ECapabilityProtServ,ETestProcessCreateProtectedServer);
+ process.Logon(logonStatus);
+ process.Resume();
+ User::WaitForRequest(logonStatus);
+ test(process.ExitType()==EExitKill);
+ test(logonStatus==KErrNone);
+ CLOSE_AND_WAIT(process);
+
+ test.End();
+ }
+
+
+void TestIdentifiedServers()
+ {
+ RTestSession session;
+ TInt r;
+
+ test.Start(_L("Trying to connect to a server with wrong Secure ID"));
+ _LIT_SECURITY_POLICY_S0(wrongSid,KTestSecureId2);
+ r=session.Connect(&wrongSid);
+ test(r==(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)?KErrPermissionDenied:KErrNone));
+ session.Close();
+
+ test.Next(_L("Test connecting to a server with correct Secure ID"));
+ _LIT_SECURITY_POLICY_S0(correctSid,KTestSecureId);
+ r=session.Connect(&correctSid);
+ test(r==KErrNone);
+ session.Close();
+
+ test.Next(_L("Trying to connect to a server with wrong Vendor ID"));
+ _LIT_SECURITY_POLICY_V0(wrongVid,KTestVendorId2);
+ r=session.Connect(&wrongVid);
+ test(r==(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)?KErrPermissionDenied:KErrNone));
+ session.Close();
+
+ test.Next(_L("Test connecting to a server with correct Vendor ID"));
+ _LIT_SECURITY_POLICY_V0(correctVid,KTestVendorId);
+ r=session.Connect(&correctVid);
+ test(r==KErrNone);
+ session.Close();
+
+ test.Next(_L("Trying to connect to a server with wrong capabilities"));
+ _LIT_SECURITY_POLICY_C1(wrongCaps,ECapabilityReadUserData);
+ r=session.Connect(&wrongCaps);
+ test(r==(PlatSec::IsCapabilityEnforced(ECapabilityReadUserData)?KErrPermissionDenied:KErrNone));
+ session.Close();
+
+ test.Next(_L("Test connecting to a server with correct capabilities"));
+ _LIT_SECURITY_POLICY_C1(correctCaps,ECapability_None);
+ r=session.Connect(&correctCaps);
+ test(r==KErrNone);
+ session.Close();
+
+ test.Next(_L("Test connecting to a server without specifying a policy"));
+ r=session.Connect(0);
+ test(r==KErrNone);
+ session.Close();
+
+ test.End();
+ }
+
+
+
+#include <e32panic.h>
+
+TInt TestThreadAsyncConnect(TAny*)
+ {
+ RTestSession session;
+ TRequestStatus status;
+ TInt r=session.Connect(TVersion(1,1,1),&status);
+ if(r!=KErrNone)
+ return r;
+ if(status!=KRequestPending) // server can't have created session yet because we have higher priority
+ return status.Int();
+ User::WaitForRequest(status);
+ if(status!=KErrNotSupported)
+ return status.Int();
+ return session.Send(EPing,TIpcArgs(1234)); // Should panic us
+ }
+
+void TestAsynchronousConnect()
+ {
+ RTestSession session;
+ TRequestStatus status;
+ TInt r;
+
+ test.Start(_L("Test successful asynchronous connect"));
+ r=session.Connect(TVersion(0,0,0),&status);
+ test(r==KErrNone);
+ test(status==KRequestPending); // server can't have created session yet because we have higher priority
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+ test((r=session.Send(EPing,TIpcArgs(1234)))==1234);
+ session.Close();
+
+ test.Next(_L("Test unsuccessful asynchronous connect"));
+ r=session.Connect(TVersion(1,1,1),&status);
+ test(r==KErrNone);
+ test(status==KRequestPending); // server can't have created session yet because we have higher priority
+ User::WaitForRequest(status);
+ test(status==KErrNotSupported);
+ session.Close();
+
+ test.Next(_L("Test using unsuccessful asynchronous connect"));
+ RTestThread thread;
+ thread.Create(TestThreadAsyncConnect,0);
+ TRequestStatus logon;
+ thread.Logon(logon);
+ User::SetJustInTime(EFalse);
+ thread.Resume();
+ User::WaitForRequest(logon);
+ User::SetJustInTime(ETrue);
+ TExitType exitType=thread.ExitType();
+ TInt exitReason=thread.ExitReason();
+ test(exitType==EExitPanic);
+ test(exitReason==CServer2::ESessionNotConnected);
+ thread.Close();
+
+ test.End();
+ }
+
+
+
+TInt DoTestProcess(TInt aTestNum,TInt aArg1,TInt aArg2)
+ {
+ (void)aArg1;
+ (void)aArg2;
+ switch(aTestNum)
+ {
+
+ case ETestProcessServer:
+ RProcess().SetPriority(EPriorityLow);
+ return StartServer();
+
+ case ETestProcessCreateProtectedServer:
+ {
+ test.Title();
+ RServer2 server;
+ TInt r = server.CreateGlobal(KProtectedServerName);
+ server.Close();
+ return r;
+ }
+
+ default:
+ User::Panic(_L("T_SSERVER"),1);
+ }
+
+ return KErrNone;
+ }
+
+
+
+GLDEF_C TInt E32Main()
+ {
+ TBuf16<512> cmd;
+ User::CommandLine(cmd);
+ if(cmd.Length() && TChar(cmd[0]).IsDigit())
+ {
+ TInt function = -1;
+ TInt arg1 = -1;
+ TInt arg2 = -1;
+ TLex lex(cmd);
+
+ lex.Val(function);
+ lex.SkipSpace();
+ lex.Val(arg1);
+ lex.SkipSpace();
+ lex.Val(arg2);
+ return DoTestProcess(function,arg1,arg2);
+ }
+
+ TInt r;
+
+ test.Title();
+
+ test.Start(_L("Testing Server Connect by Handle"));
+ TestConnectByHandle();
+
+ test.Next(_L("Starting test server"));
+ RTestProcess server;
+ TRequestStatus rendezvous;
+ server.Create(0,ETestProcessServer);
+ server.Rendezvous(rendezvous);
+ server.Resume();
+ User::WaitForRequest(rendezvous);
+ test(rendezvous==KServerRendezvous);
+ server.Close();
+
+ test.Next(_L("Conecting to test server"));
+ test((r=Session.Connect())==KErrNone);
+
+ test.Next(_L("Test asynchronous server connect"));
+ TestAsynchronousConnect();
+
+ test.Next(_L("Test protected servers"));
+ TestProtectedServers();
+
+ test.Next(_L("Test connecting to identified servers"));
+ TestIdentifiedServers();
+
+ test.Next(_L("Testing SubSessions"));
+ TestSubSessions();
+
+ test.Next(_L("Testing IPC argument checking"));
+ TestIpc();
+
+ test.Next(_L("Testing CServer2::RunError and CSession2::ServiceError()"));
+ const TInt KTestServiceLeaveValue = 555;
+ r = Session.Send(ETestServiceLeave,TIpcArgs(KTestServiceLeaveValue));
+ test(r==KTestServiceLeaveValue+KTestRunErrorModifier+KTestServiceErrorModifier);
+
+ test.Next(_L("Testing session resource counting"));
+ test.Start(_L(""));
+ DoTest(ETestResourceCountPass,EExitKill,ETestResourceCountPass);
+ DoTest(ETestResourceCountFail,EExitPanic,CSession2::ESesFoundResCountHeaven);
+ test.End();
+
+ test.Next(_L("Shutting server down"));
+ {
+ Session.Send(ETestShutdown,TIpcArgs());
+ Session.Close();
+ }
+ User::WaitForRequest(SvrStat);
+
+ test.End();
+ return(0);
+ }
+