os/kernelhwsrv/kerneltest/e32test/secure/t_sprioritycap.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\secure\t_sprioritycap.cpp
    15 // Overview:
    16 // Test the platform security aspects of the RThread class as affected by the process priority
    17 // specified in the MMP file, mainly capping of higher thread priorities without ProtServ.
    18 // API Information:
    19 // Process priorities windowserver, fileserver, supervisor and realtimeserver set with
    20 //
    21 
    22 // # 'epocprocesspriority' keyword in MMP files
    23 // # 'priority' keyword in OBEY (OBY/IBY) files
    24 // Details:
    25 // - Tests that the desired thread prioritisation results are obtained for process priorities
    26 // SystemServer and RealTimeServer (established by separate MMP files):
    27 // # without ECapabilityProtServ - priorities capped to SystemServer/More.
    28 // # with ECapabilityProtServ - higher, "real-time" priorities obtainable.
    29 // - Tests effect of reduction of SystemServer/More from nanothread priority 24 to 23,
    30 // i.e. same priority as AbsoluteHigh
    31 // Platforms/Drives/Compatibility:
    32 // All.
    33 // Assumptions/Requirement/Pre-requisites:
    34 // Failures and causes:
    35 // Base Port information:
    36 //
    37 
    38 #include <e32test.h>
    39 
    40 LOCAL_D RTest test(_L("T_SPRIORITYCAP"));
    41 RMutex SyncMutex;
    42 TInt threadMutexAcquireOrder; // where 132 = thread 1 acquires mutex, then thread 3 then thread 2
    43 _LIT(KTestPanicCategory,"TEST PANIC");
    44 
    45 class RTestThread : public RThread
    46 	{
    47 public:
    48 	void Create(TThreadFunction aFunction,TAny* aArg=0);
    49 	};
    50 
    51 void RTestThread::Create(TThreadFunction aFunction,TAny* aThreadNumber)
    52 	{
    53 	TInt threadNumber = reinterpret_cast<TInt>(aThreadNumber);
    54 	ASSERT((threadNumber > 0) && (threadNumber < 10));
    55 	TBuf<20> threadName = _L("TestThread_");
    56 	threadName.AppendNum(threadNumber);
    57 	TInt r=RThread::Create(threadName,aFunction,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,aThreadNumber);
    58 	test(r==KErrNone);
    59 	}
    60 
    61 TInt TestThreadWaitMutex(TAny* aThreadNumber)
    62 	{
    63 	TInt threadNumber = reinterpret_cast<TInt>(aThreadNumber);
    64 	ASSERT((threadNumber > 0) && (threadNumber < 10));
    65 	RThread thisThread;
    66 	thisThread.Rendezvous(KErrNone);
    67 	SyncMutex.Wait();
    68 	threadMutexAcquireOrder = threadMutexAcquireOrder*10 + threadNumber;
    69 	SyncMutex.Signal();
    70 	return KErrNone;
    71 	}
    72 
    73 // Create three threads with priority 1, 2 and 1, each waiting on a mutex that is already held by the
    74 // main thread. Signal the mutex from the main thread and return the order the threads acquire it
    75 // as an integer where 132 = thread 1 acquires mutex, then thread 3 then thread 2.
    76 //
    77 // In order to work this test requires the three threads to wait on the mutex in the order listed.
    78 // This cannot be guaranteed, but the following points make it a near-certainty:
    79 // (1) This main thread runs at lowest priority
    80 // (2) The three threads initially resume at higher, decreasing priorities.
    81 // (3) We Rendezvous() with the thread just before it waits on the mutex
    82 // (4) Wait some time before creating next thread
    83 // (5) Actual priorities are set after all test threads are waiting
    84 TInt TestThreadMutexAcquireOrder(TThreadPriority aPriorityThread1, TThreadPriority aPriorityThread2)
    85 	{
    86 	RTestThread thread1;
    87 	RTestThread thread2;
    88 	RTestThread thread3;
    89 	TRequestStatus logonStatus1;
    90 	TRequestStatus logonStatus2;
    91 	TRequestStatus logonStatus3;
    92 	TRequestStatus rendezvousStatus;
    93 
    94 	threadMutexAcquireOrder = 0; // global variable to hold order in which threads obtain mutex
    95 
    96 	RThread thisThread;
    97 	thisThread.SetPriority(EPriorityAbsoluteVeryLow);
    98 	
    99 	// create the SyncMutex global variable and hold it initially
   100 	if(SyncMutex.CreateLocal()!=KErrNone)
   101 		User::Invariant();
   102 	SyncMutex.Wait();
   103 
   104 	thread1.Create(TestThreadWaitMutex, reinterpret_cast<TAny*>(1));
   105 	thread1.Logon(logonStatus1);
   106 	thread1.SetPriority(EPriorityAbsoluteHigh);
   107 	thread1.Rendezvous(rendezvousStatus);
   108 	thread1.Resume();
   109 	User::WaitForRequest(rendezvousStatus);
   110 	User::After(500000);
   111 
   112 	thread2.Create(TestThreadWaitMutex, reinterpret_cast<TAny*>(2));
   113 	thread2.Logon(logonStatus2);
   114 	thread2.SetPriority(EPriorityAbsoluteForeground);
   115 	thread2.Rendezvous(rendezvousStatus);
   116 	thread2.Resume();
   117 	User::WaitForRequest(rendezvousStatus);
   118 	User::After(500000);
   119 
   120 	thread3.Create(TestThreadWaitMutex, reinterpret_cast<TAny*>(3));
   121 	thread3.Logon(logonStatus3);
   122 	thread3.SetPriority(EPriorityAbsoluteBackground);
   123 	thread3.Rendezvous(rendezvousStatus);
   124 	thread3.Resume();
   125 	User::WaitForRequest(rendezvousStatus);
   126 	User::After(500000);
   127 
   128 	thread1.SetPriority(aPriorityThread1);
   129 	thread2.SetPriority(aPriorityThread2);
   130 	thread3.SetPriority(aPriorityThread1);
   131 
   132 	SyncMutex.Signal();
   133 
   134 	User::WaitForRequest(logonStatus1);
   135 	User::WaitForRequest(logonStatus2);
   136 	User::WaitForRequest(logonStatus3);
   137 	test(thread1.ExitType()==EExitKill);
   138 	test(logonStatus1==KErrNone);
   139 	test(thread2.ExitType()==EExitKill);
   140 	test(logonStatus2==KErrNone);
   141 	test(thread3.ExitType()==EExitKill);
   142 	test(logonStatus3==KErrNone);
   143 
   144 	thread1.Close();
   145 	thread2.Close();
   146 	thread3.Close();
   147 	SyncMutex.Close();
   148 
   149 	return threadMutexAcquireOrder;
   150 	}
   151 
   152 
   153 enum TTestProcessFunctions
   154 	{
   155 	ETestProcessThreadPrioritiesEqual,
   156 	ETestProcessThreadPrioritiesHighLow
   157 	};
   158 
   159 #include "testprocess.h"
   160 
   161 TInt DoTestProcess(TInt aTestNum,TInt aArg1,TInt aArg2)
   162 	{
   163 	RThread thread;
   164 
   165 	switch(aTestNum)
   166 		{
   167 
   168 	case ETestProcessThreadPrioritiesEqual:
   169 		{
   170 		TInt acquireOrder = TestThreadMutexAcquireOrder((TThreadPriority)aArg1, (TThreadPriority)aArg2);
   171 		if (acquireOrder != 123)
   172 			{
   173 			thread.Panic(KTestPanicCategory,999);
   174 			}
   175 		break;
   176 		}
   177 
   178 	case ETestProcessThreadPrioritiesHighLow:
   179 		{
   180 		TInt acquireOrder = TestThreadMutexAcquireOrder((TThreadPriority)aArg1, (TThreadPriority)aArg2);
   181 		if (acquireOrder != 132)
   182 			{
   183 			thread.Panic(KTestPanicCategory,999);
   184 			}
   185 		break;
   186 		}
   187 
   188 	default:
   189 		User::Panic(_L("T_SPRIORITYCAP"),1);
   190 		}
   191 
   192 	return KErrNone;
   193 	}
   194 
   195 
   196 //---------------------------------------------
   197 //! @SYMTestCaseID KBASE-T_SPRIORITYCAP-0121
   198 //! @SYMTestCaseDesc Check prioritisation of threads with ProtServ capability
   199 //! @SYMTestType UT
   200 //! @SYMREQ PREQ955
   201 //! @SYMTestActions Create sets of three threads with various priorities and have them wait on
   202 //!     a mutex. Signal the mutex to see whether the threads obtain it in priority or wait order.
   203 //!     Note: 2 MMP files build test exe with RealTimeServer and WindowServer process priorities.
   204 //!     Test creates copy of this executable with/without required capabilities.
   205 //! @SYMTestExpectedResults All thread priorities are obtainable to processes with ProtServ, so
   206 //!     confirm they are correctly mapped to absolute priorities, that MuchMore > More etc. and
   207 //!     that SystemServer/More is correctly mapped for SYMBIAN_CURB_SYSTEMSERVER_PRIORITIES macro.
   208 //! @SYMTestPriority Critical
   209 //! @SYMTestStatus Implemented
   210 //---------------------------------------------
   211 void TestPriorityMappingWithProtServ()
   212 	{
   213 	const TUint32 capability = 1u<<ECapabilityProtServ; // only ProtServ capability
   214 	RTestProcess process;
   215 
   216 	TProcessPriority processPriority = process.Priority();
   217 	// only call with the following process priorities
   218 	ASSERT((processPriority == EPriorityWindowServer) || (processPriority == EPriorityFileServer)
   219 		|| (processPriority == EPrioritySupervisor) || (processPriority == EPriorityRealTimeServer));
   220 
   221 	test.Start(_L("Test EPriorityRealTime is greater than EPriorityMuchMore"));
   222 	process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityRealTime,EPriorityMuchMore);
   223 	process.Run();
   224 
   225 	test.Next(_L("Test EPriorityMuchMore is greater than EPriorityMore"));
   226 	process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityMuchMore,EPriorityMore);
   227 	process.Run();
   228 
   229 	test.Next(_L("Test EPriorityMore is greater than EPriorityNormal"));
   230 	process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityMore,EPriorityNormal);
   231 	process.Run();
   232 
   233 	test.Next(_L("Test EPriorityNormal is greater than EPriorityLess"));
   234 	process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityNormal,EPriorityLess);
   235 	process.Run();
   236 
   237 	test.Next(_L("Test EPriorityLess is greater than EPriorityMuchLess"));
   238 	process.Create(capability,ETestProcessThreadPrioritiesHighLow,EPriorityLess,EPriorityMuchLess);
   239 	process.Run();
   240 
   241 	test.Next(_L("Test EPriorityMore versus independent capping priority"));
   242 	process.Create(capability,
   243 		(processPriority == EPriorityRealTimeServer) ? ETestProcessThreadPrioritiesHighLow : ETestProcessThreadPrioritiesEqual,
   244 		EPriorityMore,
   245 #ifdef SYMBIAN_CURB_SYSTEMSERVER_PRIORITIES
   246 		EPriorityAbsoluteHigh
   247 #else
   248 		EPriorityAbsoluteRealTime1
   249 #endif	
   250 		);
   251 	process.Run();
   252 
   253 	test.End();
   254 	}
   255 
   256 
   257 //---------------------------------------------
   258 //! @SYMTestCaseID KBASE-T_SPRIORITYCAP-0122
   259 //! @SYMTestCaseDesc Check prioritisation of threads without ProtServ capability
   260 //! @SYMTestType UT
   261 //! @SYMREQ PREQ955
   262 //! @SYMTestActions Create sets of three threads with various priorities and have them wait on
   263 //!     a mutex. Signal the mutex to see whether the threads obtain it in priority or wait order.
   264 //!     Note: 2 MMP files build test exe with RealTimeServer and WindowServer process priorities.
   265 //!     Test creates copy of this executable with/without required capabilities.
   266 //! @SYMTestExpectedResults Confirm thread priorities are capped at SystemServer/More without ProtServ,
   267 //!     so many priority enumerations will map to the same absolute priority. Confirm that
   268 //!     SystemServer/More is correctly mapped for SYMBIAN_CURB_SYSTEMSERVER_PRIORITIES macro.
   269 //! @SYMTestPriority Critical
   270 //! @SYMTestStatus Implemented
   271 //---------------------------------------------
   272 void TestPriorityMappingWithoutProtServ()
   273 	{
   274 	const TUint32 capability = ~(1u<<ECapabilityProtServ); // all capabilities except ProtServ
   275 	RTestProcess process;
   276 
   277 	TProcessPriority processPriority = process.Priority();
   278 	// only call with the following process priorities
   279 	ASSERT((processPriority == EPriorityWindowServer) || (processPriority == EPriorityFileServer)
   280 		|| (processPriority == EPrioritySupervisor) || (processPriority == EPriorityRealTimeServer));
   281 
   282 	test.Start(_L("Test EPriorityRealTime and EPriorityMuchMore are capped and equal"));
   283 	process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityRealTime,EPriorityMuchMore);
   284 	process.Run();
   285 
   286 	test.Next(_L("Test EPriorityMuchMore and EPriorityMore are capped and equal"));
   287 	process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityMuchMore,EPriorityMore);
   288 	process.Run();
   289 
   290 	if (processPriority == EPriorityRealTimeServer)
   291 		{
   292 		test.Next(_L("Test EPriorityMore and EPriorityMuchLess are capped and equal"));
   293 		process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityMore,EPriorityMuchLess);
   294 		process.Run();
   295 
   296 		test.Next(_L("Test EPriorityNormal and EPriorityMuchLess are capped and equal"));
   297 		process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityNormal,EPriorityMuchLess);
   298 		process.Run();
   299 
   300 		test.Next(_L("Test EPriorityLess and EPriorityMuchLess are capped and equal"));
   301 		process.Create(capability,ETestProcessThreadPrioritiesEqual,EPriorityLess,EPriorityMuchLess);
   302 		process.Run();
   303 		}
   304 
   305 	test.Next(_L("Test EPriorityMore versus EPriorityAbsoluteHigh"));
   306 	process.Create(capability,
   307 #ifdef SYMBIAN_CURB_SYSTEMSERVER_PRIORITIES
   308 		ETestProcessThreadPrioritiesEqual,
   309 #else
   310 		ETestProcessThreadPrioritiesHighLow,
   311 #endif	
   312 		EPriorityMore,EPriorityAbsoluteHigh);
   313 	process.Run();
   314 
   315 	test.End();
   316 	}
   317 
   318 
   319 GLDEF_C TInt E32Main()
   320     {
   321 	TBuf16<512> cmd;
   322 	User::CommandLine(cmd);
   323 	if(cmd.Length() && TChar(cmd[0]).IsDigit())
   324 		{
   325 		TInt function = -1;
   326 		TInt arg1 = -1;
   327 		TInt arg2 = -1;
   328 		TLex lex(cmd);
   329 
   330 		lex.Val(function);
   331 		lex.SkipSpace();
   332 		lex.Val(arg1);
   333 		lex.SkipSpace();
   334 		lex.Val(arg2);
   335 		return DoTestProcess(function,arg1,arg2);
   336 		}
   337 
   338 	test.Title();
   339 
   340 	if(!PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement))
   341 		{
   342 		test.Start(_L("TESTS NOT RUN - EPlatSecEnforcement is OFF"));
   343 		test.End();
   344 		return 0;
   345 		}
   346 
   347 	test.Next(_L("Test thread priority mappings for processes with ECapabilityProtServ"));
   348 	TestPriorityMappingWithProtServ();
   349 
   350 	test.Start(_L("Test thread priority mappings for processes without ECapabilityProtServ"));
   351 	TestPriorityMappingWithoutProtServ();
   352 
   353 	test.End();
   354 
   355 	return(0);
   356     }
   357