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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\system\t_prot.cpp
16 // Tests that the kernel panics the user rather than dying in
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
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:
38 // Assumptions/Requirement/Pre-requisites:
39 // Failures and causes:
40 // Base Port information:
47 #include "../mmu/mmudetect.h"
49 void DoUndefinedInstruction();
51 const TInt KHeapSize=0x200;
52 const TInt KThreadReturnValue=9999;
54 _LIT(KLitKernExec,"KERN-EXEC");
56 class RSessionTest : public RSessionBase
63 void RSessionTest::DoSend()
65 Send(34,TIpcArgs(78));
69 LOCAL_D RTest test(_L("T_PROT"));
70 LOCAL_D RTest t(_L("T_PROT thread"));
76 EUndefinedInstruction=2,
79 typedef void (*PFV)(void);
82 void DoUndefinedInstruction()
92 LOCAL_C TInt ExceptionThread(TAny* anAction)
94 TAction action=(TAction)((TInt) anAction);
103 PFV f=(PFV)0x80000; // don't use NULL since it is readable on Snowdrop
107 case EUndefinedInstruction:
108 DoUndefinedInstruction();
114 LOCAL_C void RunTestThread(TAction anAction)
117 TInt r=t.Create(_L("TestThread"),ExceptionThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)anAction);
121 test(s==KRequestPending);
123 User::WaitForRequest(s);
124 test(t.ExitType()==EExitPanic);
125 test(t.ExitCategory()==_L("KERN-EXEC"));
126 test(t.ExitReason()==ECausedException);
130 LOCAL_C TInt UnintThread(TAny* )
148 test.Next(_L("Create UnintThread"));
149 TInt r=thread.Create(_L("UnintThread"),UnintThread,KDefaultStackSize,KHeapSize,KHeapSize,0);
153 test(thread.ExitType()==EExitPending);
154 test.Next(_L("Resume UnintThread"));
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);
169 // Dennis - modified this to panic a dead thread rather than a bad handle
174 TInt r=thread.Create(_L("dummy"),dummy,KDefaultStackSize,KHeapSize,KHeapSize,0);
177 test(thread.ExitType()==EExitPending);
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);
189 void testPanicDeadThread()
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
198 test.Next(_L("Create PanicDeadThread"));
199 TInt r=thread.Create(_L("PanicDeadThread"),pdThread,KDefaultStackSize,KHeapSize,KHeapSize,0);
202 test(thread.ExitType()==EExitPending);
203 test.Next(_L("Resume PanicDeadThread"));
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);
213 TInt doDeadThreadStuff(TAny*)
217 TInt r=thread.Create(_L("dummy2"),dummy,KDefaultStackSize,KHeapSize,KHeapSize,0);
220 test(thread.ExitType()==EExitPending);
222 User::WaitForRequest(stat);
224 thread.SetPriority(EPriorityNormal);
226 CLOSE_AND_WAIT(thread);
230 void testDeadThread()
232 // Create the thread which panics a bad handle
233 // Check that it isn't panicked for doing this
238 test.Next(_L("Create doDeadThreadStuff"));
239 TInt r=thread.Create(_L("doDeadThreadStuff"),doDeadThreadStuff,KDefaultStackSize,KHeapSize,KHeapSize,0);
242 test(thread.ExitType()==EExitPending);
243 test.Next(_L("Resume doDeadThreadStuff"));
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);
253 TInt MinimalThread(TAny*)
255 // Minimal thread, used in test 5
261 LOCAL_C TInt ExceptThread(TAny* )
265 *nullPtr=0xdead; // BANG!!
272 // Test thread causing exception is panicked
279 test.Next(_L("Create ExceptThread"));
280 TInt r=thread.Create(_L("ExceptThread"),ExceptThread,KDefaultStackSize,KHeapSize,KHeapSize,0);
284 test(thread.ExitType()==EExitPending);
285 test.Next(_L("Resume ExceptThread"));
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);
295 LOCAL_C TInt StackThread(TAny* )
298 TFileName heresAnotherOne;
299 StackThread((TAny*)heresAnotherOne.Ptr()); // go recursive
303 void testStackOverflow()
305 // Thread overflowing its stack is panicked
312 test.Next(_L("Create StackThread"));
313 TInt r=thread.Create(_L("StackThread"),StackThread,KDefaultStackSize,KHeapSize,KHeapSize,0);
317 test(thread.ExitType()==EExitPending);
318 test.Next(_L("Resume StackThread"));
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);
328 LOCAL_C TInt KernWriter(TAny* )
331 TUint* kernPtr=(TUint*)KernData();
332 *kernPtr=0xdead; // BANG!!
336 LOCAL_C TInt RamDiskWriter(TAny* )
339 TFindChunk fChunk(_L("*TheRamDriveChunk*"));
341 TInt r=fChunk.Next(n);
346 TUint8* rdPtr=ch.Base();
347 *rdPtr=0xaa; // BANG!!
352 void testKernelWriter()
354 // Thread writing to kernel data is panicked
361 test.Next(_L("Create KernWriter"));
362 TInt r=thread.Create(_L("KernWriter"),KernWriter,KDefaultStackSize,KHeapSize,KHeapSize,0);
366 test(thread.ExitType()==EExitPending);
367 test.Next(_L("Resume KernWriter"));
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);
377 void testRamDiskAccess()
383 test.Next(_L("Create RamDiskWriter"));
384 TInt r=thread.Create(_L("RamDiskWriter"),RamDiskWriter,KDefaultStackSize,KHeapSize,KHeapSize,0);
388 test(thread.ExitType()==EExitPending);
389 test.Next(_L("Resume RamDiskWriter"));
391 User::WaitForRequest(stat);
392 if((!PlatSec::ConfigSetting(PlatSec::EPlatSecProcessIsolation))||(!PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)))
394 test.Next(_L("Check RamDiskWriter panicked"));
395 test(thread.ExitCategory()==_L("KERN-EXEC"));
396 test(thread.ExitReason()==ECausedException);
397 test(thread.ExitType()==EExitPanic);
401 test.Next(_L("Check RamDiskWriter was refused access"));
402 test(thread.ExitReason()==KErrPermissionDenied);
403 test(thread.ExitType()==EExitKill);
405 CLOSE_AND_WAIT(thread);
410 TInt RequestCompleteThread(TAny* aPtr)
412 TRequestStatus** pS=(TRequestStatus**)aPtr;
413 MainThread.RequestComplete(*pS,123);
417 _LIT(KReqCompThreadName,"ReqCompThread");
418 void StartRequestCompleteThread(RThread& aThread, TRequestStatus** aStatus)
420 TInt r=aThread.Create(KReqCompThreadName,RequestCompleteThread,0x1000,0x1000,0x10000,aStatus);
422 aThread.SetPriority(EPriorityMore);
426 User::WaitForRequest(s);
429 _LIT(KLitUserCBase,"E32USER-CBase");
430 GLDEF_C TInt E32Main()
436 // don't want just in time debugging as we trap panics
437 TBool justInTime=User::JustInTime();
438 User::SetJustInTime(EFalse);
441 test.Start(_L("Test protection & panicking"));
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"));
454 test.Next(_L("Stack overflow shoots the thread not the kernel"));
458 test.Next(_L("Panicking a closed thread doesn't panic the panicker!!"));
459 testPanicDeadThread();
461 test.Next(_L("Dead thread tests"));
464 test.Next(_L("RSession send from uninitialised handle"));
467 test.Next(_L("Thread causing exception is killed"));
471 RunTestThread(EDataAbort);
472 RunTestThread(EPrefetchAbort);
475 RunTestThread(EUndefinedInstruction);
478 #if defined(__EPOC32__)
479 if (HaveDirectKernProt())
481 test.Next(_L("Thread writing to kernel data is killed"));
485 if (HaveProcessProt())
487 test.Next(_L("Check access to RamDisk is denied"));
493 test.Next(_L("RequestComplete() with bad address"));
494 TInt rqc=RThread().RequestCount();
495 test(MainThread.Duplicate(RThread())==KErrNone);
497 TRequestStatus s=KRequestPending;
498 TRequestStatus* pS=&s;
499 StartRequestCompleteThread(t,&pS);
500 test(t.ExitType()==EExitKill);
501 test(t.ExitReason()==KErrNone);
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);
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);
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);
530 test(RThread().RequestCount()==rqc+1);
536 User::SetJustInTime(justInTime);