os/kernelhwsrv/kerneltest/e32test/system/t_prot.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1996-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\system\t_prot.cpp
    15 // Overview:
    16 // Tests that the kernel panics the user rather than dying in 
    17 // various situations
    18 // API Information:
    19 // N/A
    20 // Details:
    21 // - Verify that printing a long string does not panic.
    22 // - Verify that a stack overflow in a thread causes a panic.
    23 // - Create the thread which panics a dead thread, verify that 
    24 // it isn't panicked for doing this.
    25 // - Create the thread which panics a bad handle, verify that 
    26 // it isn't panicked for doing this.
    27 // - Verify that an RSession send from an uninitialised handle
    28 // causes a panic.
    29 // - Verify that the thread causing an exception, for a variety
    30 // of reasons, is panicked.
    31 // - Verify thread writing to kernel data is panicked.
    32 // - Verify that RAM disk access either causes a panic or is
    33 // denied, based on the platform security settings.
    34 // - Verify that an RThread::RequestComplete() with an invalid
    35 // address causes a panic. Verify results are as expected.
    36 // Platforms/Drives/Compatibility:
    37 // All.
    38 // Assumptions/Requirement/Pre-requisites:
    39 // Failures and causes:
    40 // Base Port information:
    41 // 
    42 //
    43 
    44 #include <e32test.h>
    45 #include "u32std.h"
    46 #include <e32panic.h>
    47 #include "../mmu/mmudetect.h"
    48 
    49 void DoUndefinedInstruction();
    50 
    51 const TInt KHeapSize=0x200;
    52 const TInt KThreadReturnValue=9999;
    53 
    54 _LIT(KLitKernExec,"KERN-EXEC");
    55 
    56 class RSessionTest : public RSessionBase
    57 	{
    58 public:
    59 	void DoSend();
    60 	};
    61 
    62 
    63 void RSessionTest::DoSend()
    64 	{
    65     Send(34,TIpcArgs(78));
    66 	//Send(34,(TAny*)78);
    67 	};
    68 
    69 LOCAL_D RTest test(_L("T_PROT"));
    70 LOCAL_D RTest t(_L("T_PROT thread"));
    71 
    72 enum TAction
    73 	{
    74 	EDataAbort=0,
    75 	EPrefetchAbort=1,
    76 	EUndefinedInstruction=2,
    77 	};
    78 
    79 typedef void (*PFV)(void);
    80 
    81 #ifndef __MARM__
    82 void DoUndefinedInstruction()
    83 	{
    84 #ifdef __GCC32__	
    85 	asm("int 6");
    86 #else
    87 	_asm int 6;
    88 #endif
    89 	}
    90 #endif
    91 
    92 LOCAL_C TInt ExceptionThread(TAny* anAction)
    93 	{
    94 	TAction action=(TAction)((TInt) anAction);
    95 	switch (action)
    96 		{
    97 		case EDataAbort:
    98 			*(TInt*)0=0;
    99 			break;
   100 		case EPrefetchAbort:
   101 			{
   102 //			PFV f=(PFV)NULL;
   103 			PFV f=(PFV)0x80000;	// don't use NULL since it is readable on Snowdrop
   104 			(*f)();
   105 			break;
   106 			}
   107 		case EUndefinedInstruction:
   108 			DoUndefinedInstruction();
   109 			break;
   110 		};
   111 	return 0;
   112 	}
   113 
   114 LOCAL_C void RunTestThread(TAction anAction)
   115 	{
   116 	RThread t;
   117 	TInt r=t.Create(_L("TestThread"),ExceptionThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)anAction);
   118 	test(r==KErrNone);
   119 	TRequestStatus s;
   120 	t.Logon(s);
   121 	test(s==KRequestPending);
   122 	t.Resume();
   123 	User::WaitForRequest(s);
   124 	test(t.ExitType()==EExitPanic);
   125 	test(t.ExitCategory()==_L("KERN-EXEC"));
   126 	test(t.ExitReason()==ECausedException);
   127 	CLOSE_AND_WAIT(t);
   128 	}
   129 
   130 LOCAL_C TInt UnintThread(TAny* )
   131 	{
   132 
   133 	RSessionTest rsb;
   134 	rsb.DoSend();
   135 	FOREVER
   136 		;
   137 	}
   138 
   139 void testSession()
   140 //
   141 // Test 1
   142 //
   143 	{
   144 	
   145 	RThread thread;
   146 	TRequestStatus stat;
   147 
   148 	test.Next(_L("Create UnintThread"));
   149 	TInt r=thread.Create(_L("UnintThread"),UnintThread,KDefaultStackSize,KHeapSize,KHeapSize,0);
   150 	test(r==KErrNone);
   151 
   152 	thread.Logon(stat);
   153 	test(thread.ExitType()==EExitPending);
   154 	test.Next(_L("Resume UnintThread"));
   155 	thread.Resume();
   156 	User::WaitForRequest(stat);
   157 	test.Next(_L("Check UnintThread panicked"));
   158 	test(thread.ExitCategory()==_L("KERN-EXEC"));
   159 //	test(thread.ExitReason()==EBadHandle);
   160 	test(thread.ExitType()==EExitPanic);
   161 	CLOSE_AND_WAIT(thread);
   162 	}
   163 
   164 TInt dummy(TAny*)
   165 	{
   166 	return(KErrNone);
   167 	}
   168 
   169 // Dennis - modified this to panic a dead thread rather than a bad handle
   170 TInt pdThread(TAny*)
   171 	{
   172 	RThread thread;
   173 	TRequestStatus stat;
   174 	TInt r=thread.Create(_L("dummy"),dummy,KDefaultStackSize,KHeapSize,KHeapSize,0);
   175 	test(r==KErrNone);
   176 	thread.Logon(stat);
   177 	test(thread.ExitType()==EExitPending);
   178 	thread.Resume();
   179 	User::WaitForRequest(stat);
   180 	test(thread.ExitType()==EExitKill);
   181 	test(stat.Int()==KErrNone);
   182 	thread.Panic(_L("MYPANIC"),0x666); // this shouldn't panic pdThread
   183 	test(thread.ExitType()==EExitKill);
   184 	test(thread.ExitReason()==KErrNone);
   185 	CLOSE_AND_WAIT(thread);
   186 	return(KErrNone);
   187 	}
   188 
   189 void testPanicDeadThread()
   190 //
   191 // Dennis - modified this to panic a dead thread rather than a bad handle
   192 // Create the thread which panics a dead thread /*bad handle*/
   193 // Check that it isn't panicked for doing this
   194 //
   195 	{
   196 	RThread thread;
   197 	TRequestStatus stat;
   198 	test.Next(_L("Create PanicDeadThread"));
   199 	TInt r=thread.Create(_L("PanicDeadThread"),pdThread,KDefaultStackSize,KHeapSize,KHeapSize,0);
   200 	test(r==KErrNone);
   201 	thread.Logon(stat);
   202 	test(thread.ExitType()==EExitPending);
   203 	test.Next(_L("Resume PanicDeadThread"));
   204 	thread.Resume();
   205 	User::WaitForRequest(stat);
   206 	test.Next(_L("Check PanicDeadThread did not panic"));
   207 	test(thread.ExitReason()==KErrNone);
   208 	test(thread.ExitType()==EExitKill);
   209 	test(thread.ExitCategory()==_L("Kill"));
   210 	CLOSE_AND_WAIT(thread);
   211 	}
   212 
   213 TInt doDeadThreadStuff(TAny*)
   214 	{
   215 	RThread thread;
   216 	TRequestStatus stat;
   217 	TInt r=thread.Create(_L("dummy2"),dummy,KDefaultStackSize,KHeapSize,KHeapSize,0);
   218 	test(r==KErrNone);
   219 	thread.Logon(stat);
   220 	test(thread.ExitType()==EExitPending);
   221 	thread.Resume();
   222 	User::WaitForRequest(stat);
   223 
   224 	thread.SetPriority(EPriorityNormal);
   225 
   226 	CLOSE_AND_WAIT(thread);
   227 	return(KErrNone);
   228 	}
   229 
   230 void testDeadThread()
   231 //
   232 // Create the thread which panics a bad handle
   233 // Check that it isn't panicked for doing this
   234 //
   235 	{
   236 	RThread thread;
   237 	TRequestStatus stat;
   238 	test.Next(_L("Create doDeadThreadStuff"));
   239 	TInt r=thread.Create(_L("doDeadThreadStuff"),doDeadThreadStuff,KDefaultStackSize,KHeapSize,KHeapSize,0);
   240 	test(r==KErrNone);
   241 	thread.Logon(stat);
   242 	test(thread.ExitType()==EExitPending);
   243 	test.Next(_L("Resume doDeadThreadStuff"));
   244 	thread.Resume();
   245 	User::WaitForRequest(stat);
   246 	test.Next(_L("Check doDeadThreadStuff did not panic"));
   247 	test(thread.ExitReason()==KErrNone);
   248 	test(thread.ExitType()==EExitKill);
   249 	test(thread.ExitCategory()==_L("Kill"));
   250 	CLOSE_AND_WAIT(thread);
   251 	}
   252 
   253 TInt MinimalThread(TAny*)
   254 //
   255 // Minimal thread, used in test 5
   256 //
   257 	{
   258 	return(KErrNone);
   259 	}
   260 
   261 LOCAL_C TInt ExceptThread(TAny* )
   262 	{
   263 
   264 	TUint* nullPtr=0;
   265 	*nullPtr=0xdead; // BANG!!
   266 	return KErrNone;
   267 	}
   268 
   269 
   270 void testExcept()
   271 //
   272 // Test thread causing exception is panicked
   273 //
   274 	{
   275 	
   276 	RThread thread;
   277 	TRequestStatus stat;
   278 
   279 	test.Next(_L("Create ExceptThread"));
   280 	TInt r=thread.Create(_L("ExceptThread"),ExceptThread,KDefaultStackSize,KHeapSize,KHeapSize,0);
   281 	test(r==KErrNone);
   282 
   283 	thread.Logon(stat);
   284 	test(thread.ExitType()==EExitPending);
   285 	test.Next(_L("Resume ExceptThread"));
   286 	thread.Resume();
   287 	User::WaitForRequest(stat);
   288 	test.Next(_L("Check ExceptThread panicked"));
   289 	test(thread.ExitCategory()==_L("KERN-EXEC"));
   290 	test(thread.ExitReason()==ECausedException);
   291 	test(thread.ExitType()==EExitPanic);
   292 	CLOSE_AND_WAIT(thread);
   293 	}
   294 
   295 LOCAL_C TInt StackThread(TAny* )
   296 	{
   297 
   298 	TFileName heresAnotherOne;
   299 	StackThread((TAny*)heresAnotherOne.Ptr()); // go recursive
   300 	return KErrNone;
   301 	}
   302 
   303 void testStackOverflow()
   304 //
   305 // Thread overflowing its stack is panicked
   306 //
   307 	{
   308 
   309 	RThread thread;
   310 	TRequestStatus stat;
   311 
   312 	test.Next(_L("Create StackThread"));
   313 	TInt r=thread.Create(_L("StackThread"),StackThread,KDefaultStackSize,KHeapSize,KHeapSize,0);
   314 	test(r==KErrNone);
   315 
   316 	thread.Logon(stat);
   317 	test(thread.ExitType()==EExitPending);
   318 	test.Next(_L("Resume StackThread"));
   319 	thread.Resume();
   320 	User::WaitForRequest(stat);
   321 	test.Next(_L("Check StackThread panicked"));
   322 	test(thread.ExitCategory()==_L("KERN-EXEC"));
   323 	test(thread.ExitReason()==ECausedException);
   324 	test(thread.ExitType()==EExitPanic);
   325 	CLOSE_AND_WAIT(thread);
   326 	}
   327 
   328 LOCAL_C TInt KernWriter(TAny* )
   329 	{
   330 
   331 	TUint* kernPtr=(TUint*)KernData();
   332 	*kernPtr=0xdead; // BANG!!
   333 	return KErrNone;
   334 	}
   335 
   336 LOCAL_C TInt RamDiskWriter(TAny* )
   337 	{
   338 
   339 	TFindChunk fChunk(_L("*TheRamDriveChunk*"));
   340 	TFullName n;
   341 	TInt r=fChunk.Next(n);
   342 	RChunk ch;
   343 	r=ch.Open(fChunk);
   344 	if(r!=KErrNone)
   345 		return r;
   346 	TUint8* rdPtr=ch.Base();
   347 	*rdPtr=0xaa; // BANG!!
   348 	return KErrNone;
   349 	}
   350 
   351 
   352 void testKernelWriter()
   353 //
   354 // Thread writing to kernel data is panicked
   355 //
   356 	{
   357 
   358 	RThread thread;
   359 	TRequestStatus stat;
   360 
   361 	test.Next(_L("Create KernWriter"));
   362 	TInt r=thread.Create(_L("KernWriter"),KernWriter,KDefaultStackSize,KHeapSize,KHeapSize,0);
   363 	test(r==KErrNone);
   364 
   365 	thread.Logon(stat);
   366 	test(thread.ExitType()==EExitPending);
   367 	test.Next(_L("Resume KernWriter"));
   368 	thread.Resume();
   369 	User::WaitForRequest(stat);
   370 	test.Next(_L("Check KernWriter panicked"));
   371 	test(thread.ExitCategory()==_L("KERN-EXEC"));
   372 	test(thread.ExitReason()==ECausedException);
   373 	test(thread.ExitType()==EExitPanic);
   374 	CLOSE_AND_WAIT(thread);
   375 	}
   376 
   377 void testRamDiskAccess()
   378 	{
   379 
   380 	RThread thread;
   381 	TRequestStatus stat;
   382 
   383 	test.Next(_L("Create RamDiskWriter"));
   384 	TInt r=thread.Create(_L("RamDiskWriter"),RamDiskWriter,KDefaultStackSize,KHeapSize,KHeapSize,0);
   385 	test(r==KErrNone);
   386 
   387 	thread.Logon(stat);
   388 	test(thread.ExitType()==EExitPending);
   389 	test.Next(_L("Resume RamDiskWriter"));
   390 	thread.Resume();
   391 	User::WaitForRequest(stat);
   392 	if((!PlatSec::ConfigSetting(PlatSec::EPlatSecProcessIsolation))||(!PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)))
   393 		{
   394 		test.Next(_L("Check RamDiskWriter panicked"));
   395 		test(thread.ExitCategory()==_L("KERN-EXEC"));
   396 		test(thread.ExitReason()==ECausedException);
   397 		test(thread.ExitType()==EExitPanic);
   398 		}
   399 	else
   400 		{
   401 		test.Next(_L("Check RamDiskWriter was refused access"));
   402 		test(thread.ExitReason()==KErrPermissionDenied);
   403 		test(thread.ExitType()==EExitKill);
   404 		}
   405 	CLOSE_AND_WAIT(thread);
   406 	}
   407 
   408 RThread MainThread;
   409 
   410 TInt RequestCompleteThread(TAny* aPtr)
   411 	{
   412 	TRequestStatus** pS=(TRequestStatus**)aPtr;
   413 	MainThread.RequestComplete(*pS,123);
   414 	return 0;
   415 	}
   416 
   417 _LIT(KReqCompThreadName,"ReqCompThread");
   418 void StartRequestCompleteThread(RThread& aThread, TRequestStatus** aStatus)
   419 	{
   420 	TInt r=aThread.Create(KReqCompThreadName,RequestCompleteThread,0x1000,0x1000,0x10000,aStatus);
   421 	test (r==KErrNone);
   422 	aThread.SetPriority(EPriorityMore);
   423 	TRequestStatus s;
   424 	aThread.Logon(s);
   425 	aThread.Resume();
   426 	User::WaitForRequest(s);
   427 	}
   428 
   429 _LIT(KLitUserCBase,"E32USER-CBase");
   430 GLDEF_C TInt E32Main()
   431 //
   432 // Main
   433 //
   434 	{	
   435 
   436 	// don't want just in time debugging as we trap panics
   437 	TBool justInTime=User::JustInTime(); 
   438 	User::SetJustInTime(EFalse); 
   439 
   440 	test.Title();
   441 	test.Start(_L("Test protection & panicking"));
   442 
   443 #if defined(__EPOC32__)
   444 	// this next test doesn't work under WINS because the string needs to be converted
   445 	// from UNICODE to ascii for printing to STDOUT, and that requires the string to be
   446 	// zero-terminated which panics because the string is too long.
   447 	test.Next(_L("Printing long string doesn't get me shot"));
   448 	test.Printf(_L("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"));
   449 	test.Printf(_L("\n"));
   450 #endif
   451 
   452 	if (HaveVirtMem())
   453 		{
   454 		test.Next(_L("Stack overflow shoots the thread not the kernel"));
   455 		testStackOverflow();
   456 		}
   457 
   458 	test.Next(_L("Panicking a closed thread doesn't panic the panicker!!"));
   459 	testPanicDeadThread();
   460 
   461 	test.Next(_L("Dead thread tests"));
   462 	testDeadThread();
   463 
   464 	test.Next(_L("RSession send from uninitialised handle"));
   465 	testSession();
   466 
   467 	test.Next(_L("Thread causing exception is killed"));
   468 	if (HaveVirtMem())
   469 		{
   470 		testExcept();
   471 		RunTestThread(EDataAbort);
   472 		RunTestThread(EPrefetchAbort);
   473 		}
   474 #ifndef __WINS__
   475 	RunTestThread(EUndefinedInstruction);
   476 #endif
   477 
   478 #if defined(__EPOC32__)
   479 	if (HaveDirectKernProt())
   480 		{
   481 		test.Next(_L("Thread writing to kernel data is killed"));
   482 		testKernelWriter();
   483 		}
   484 
   485 	if (HaveProcessProt())
   486 		{
   487 		test.Next(_L("Check access to RamDisk is denied"));
   488 		testRamDiskAccess();
   489 		}
   490 
   491 	if (HaveMMU())
   492 		{
   493 		test.Next(_L("RequestComplete() with bad address"));
   494 		TInt rqc=RThread().RequestCount();
   495 		test(MainThread.Duplicate(RThread())==KErrNone);
   496 		RThread t;
   497 		TRequestStatus s=KRequestPending;
   498 		TRequestStatus* pS=&s;
   499 		StartRequestCompleteThread(t,&pS);
   500 		test(t.ExitType()==EExitKill);
   501 		test(t.ExitReason()==KErrNone);
   502 		CLOSE_AND_WAIT(t);
   503 		test(s==123);
   504 		test(pS==NULL);
   505 		test(RThread().RequestCount()==rqc+1);
   506 		TRequestStatus** bad=(TRequestStatus**)0x80000000;	// kernel space
   507 		StartRequestCompleteThread(t,bad);
   508 		test(t.ExitType()==EExitPanic);
   509 		test(t.ExitReason()==ECausedException);
   510 		test(t.ExitCategory()==KLitKernExec);
   511 		CLOSE_AND_WAIT(t);
   512 		test(RThread().RequestCount()==rqc+1);
   513 		pS=(TRequestStatus*)0x80000000;
   514 		StartRequestCompleteThread(t,&pS);
   515 		// Request status poked user side, so we expect a KERN-EXEC 3...
   516 		test(t.ExitType()==EExitPanic);
   517 		test(t.ExitReason()==ECausedException);
   518 		test(t.ExitCategory()==KLitKernExec);
   519 		CLOSE_AND_WAIT(t);
   520 		test(pS==NULL);
   521 		test(RThread().RequestCount()==rqc+1);
   522 		pS=(TRequestStatus*)(((TUint8*)&s)+0x80000);		// aligned, within chunk max size but invalid
   523 		StartRequestCompleteThread(t,&pS);
   524 		// Request status poked user side, so we expect a KERN-EXEC 3...
   525 		test(t.ExitType()==EExitPanic);
   526 		test(t.ExitReason()==ECausedException);
   527 		test(t.ExitCategory()==KLitKernExec);
   528 		CLOSE_AND_WAIT(t);
   529 		test(pS==NULL);
   530 		test(RThread().RequestCount()==rqc+1);
   531 		}
   532 #endif
   533 
   534 	test.End();
   535 
   536 	User::SetJustInTime(justInTime);
   537 	return(KErrNone);
   538 	}
   539