|
1 // Copyright (c) 2006-2010 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 // Provides the debug security server session implementation. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalTechnology |
|
21 @released |
|
22 */ |
|
23 |
|
24 // Needed so we get the text strings for capabilities |
|
25 #define __INCLUDE_CAPABILITY_NAMES__ |
|
26 |
|
27 #include <e32std.h> |
|
28 #include <e32std_private.h> |
|
29 #include <e32btrace.h> |
|
30 #include <d32btrace.h> |
|
31 #include <e32base.h> |
|
32 #include <e32base_private.h> |
|
33 #include <e32uid.h> |
|
34 #include <f32file.h> |
|
35 #include <e32capability.h> |
|
36 #include <rm_debug_api.h> |
|
37 |
|
38 // required for direct parsing of e32image/tromimage headers |
|
39 #include <f32image.h> |
|
40 #include <e32rom.h> |
|
41 |
|
42 //added for direct access to media driver |
|
43 #include <partitions.h> |
|
44 #include <ftlcontrolio.h> |
|
45 |
|
46 #include "c_security_svr_session.h" |
|
47 #include "c_security_svr_server.h" |
|
48 #include "c_security_svr_async.h" |
|
49 #include "rm_debug_logging.h" |
|
50 #ifdef _DEBUG |
|
51 #include "low_mem_requests.h" |
|
52 #endif |
|
53 |
|
54 using namespace Debug; |
|
55 |
|
56 CSecuritySvrSession::CSecuritySvrSession(const TProcessId& aDebugAgentProcessId) |
|
57 : iDebugAgentProcessId(aDebugAgentProcessId), |
|
58 iServerNotified(EFalse), |
|
59 iCrashConnected(EFalse) |
|
60 { |
|
61 // Ensure that this debug agent has no target capability override |
|
62 // by default |
|
63 iOEMDebugCapabilities.SetEmpty(); |
|
64 } |
|
65 |
|
66 void CSecuritySvrSession::ServiceError(const RMessage2 &aMessage, TInt aError) |
|
67 { |
|
68 LOG_MSG2("CSecuritySvrSession::ServiceError(), aError: %d\n", aError); |
|
69 |
|
70 //insert ending heap markers |
|
71 HeapWatcher(aMessage.Function(), EFalse); |
|
72 |
|
73 aMessage.Complete(aError); |
|
74 } |
|
75 |
|
76 /** |
|
77 Called by the client/server framework as part of session creation. |
|
78 |
|
79 Notifies the server that a session is being created |
|
80 */ |
|
81 void CSecuritySvrSession::CreateL() |
|
82 { |
|
83 LOG_MSG("CSecuritySvrSession::CreateL()\n"); |
|
84 |
|
85 //notify the server that the session has been opened |
|
86 Server().SessionOpened(); |
|
87 iServerNotified = ETrue; |
|
88 } |
|
89 |
|
90 /** |
|
91 Returns a reference to the DSS |
|
92 |
|
93 @return a reference to the DSS |
|
94 */ |
|
95 CSecuritySvrServer& CSecuritySvrSession::Server() const |
|
96 { |
|
97 return *static_cast<CSecuritySvrServer*>(const_cast<CServer2*>(CSession2::Server())); |
|
98 } |
|
99 |
|
100 /** |
|
101 Session destructor. Performs necessary cleanup and notifies the server that the |
|
102 session is being closed |
|
103 */ |
|
104 CSecuritySvrSession::~CSecuritySvrSession() |
|
105 { |
|
106 LOG_MSG("CSecuritySvrSession::~CSecuritySvrSession!()\n"); |
|
107 |
|
108 // Cancel any outstanding async objects. |
|
109 iAsyncHandlers.ResetAndDestroy(); |
|
110 |
|
111 // Inform the device driver of the agent detach. |
|
112 Server().iKernelDriver.DetachAgent(iDebugAgentProcessId.Id()); |
|
113 |
|
114 LOG_MSG( "CSecuritySvrSession::~CSecuritySvrSession() : -> securityServer.DetachAllProcesses()\n" ); |
|
115 Server().DetachAllProcesses(iDebugAgentProcessId); |
|
116 |
|
117 //notify the server that the session has closed |
|
118 if(iServerNotified) |
|
119 { |
|
120 Server().SessionClosed(); |
|
121 } |
|
122 } |
|
123 |
|
124 void CSecuritySvrSession::ConstructL() |
|
125 { |
|
126 // nothing to do |
|
127 } |
|
128 |
|
129 /** |
|
130 Used to insert heap checking markers. |
|
131 |
|
132 @param aFunction The function that heap markers should be added for |
|
133 @param aEntry if ETrue indicates that heap checking is starting, if EFalse |
|
134 that heap checking is ending. |
|
135 */ |
|
136 void CSecuritySvrSession::HeapWatcher(const TUint32 aFunction, const TBool aEntry) const |
|
137 { |
|
138 switch(aFunction) |
|
139 { |
|
140 case EDebugServAttachExecutable: |
|
141 return; |
|
142 case EDebugServDetachExecutable: |
|
143 return; |
|
144 case EDebugServSuspendThread: |
|
145 return; |
|
146 case EDebugServResumeThread: |
|
147 return; |
|
148 case EDebugServAttachAll: |
|
149 return; |
|
150 case EDebugServDetachAll: |
|
151 return; |
|
152 // used for out-of-memory testing in debug mode |
|
153 #ifdef _DEBUG |
|
154 // start heap marking in on entry, do nothing on exit |
|
155 case EDebugServMarkHeap: |
|
156 { |
|
157 if(aEntry) |
|
158 { |
|
159 __UHEAP_MARK; |
|
160 } |
|
161 return; |
|
162 } |
|
163 // stop heap marking on exit, do nothing on entry |
|
164 case EDebugServMarkEnd: |
|
165 { |
|
166 if(!aEntry) |
|
167 { |
|
168 __UHEAP_MARKEND; |
|
169 } |
|
170 return; |
|
171 } |
|
172 #endif |
|
173 default: |
|
174 if(aEntry) |
|
175 { |
|
176 __UHEAP_MARK; |
|
177 } |
|
178 else |
|
179 { |
|
180 __UHEAP_MARKEND; |
|
181 } |
|
182 return; |
|
183 } |
|
184 } |
|
185 |
|
186 void CSecuritySvrSession::ServiceL(const RMessage2& aMessage) |
|
187 // |
|
188 // Session service handler |
|
189 // |
|
190 { |
|
191 //insert starting heap markers |
|
192 HeapWatcher(aMessage.Function(), ETrue); |
|
193 |
|
194 switch(aMessage.Function()) |
|
195 { |
|
196 case EDebugServResumeThread: |
|
197 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServResumeThread\n" ); |
|
198 ResumeThreadL(aMessage); |
|
199 break; |
|
200 |
|
201 case EDebugServSuspendThread: |
|
202 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSuspendThread\n" ); |
|
203 SuspendThreadL(aMessage); |
|
204 break; |
|
205 |
|
206 case EDebugServReadMemory: |
|
207 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServReadMemory\n" ); |
|
208 ReadMemoryL(aMessage); |
|
209 break; |
|
210 |
|
211 case EDebugServWriteMemory: |
|
212 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServWriteMemory\n" ); |
|
213 WriteMemoryL(aMessage); |
|
214 break; |
|
215 |
|
216 case EDebugServSetBreak: |
|
217 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSetBreak\n" ); |
|
218 SetBreakL(aMessage); |
|
219 break; |
|
220 |
|
221 case EDebugServClearBreak: |
|
222 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServClearBreak\n" ); |
|
223 ClearBreakL(aMessage); |
|
224 break; |
|
225 |
|
226 case EDebugServModifyBreak: |
|
227 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServModifyBreak\n" ); |
|
228 ModifyBreakL(aMessage); |
|
229 break; |
|
230 |
|
231 case EDebugServModifyProcessBreak: |
|
232 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServModifyProcessBreak\n" ); |
|
233 ModifyProcessBreakL(aMessage); |
|
234 break; |
|
235 |
|
236 case EDebugServBreakInfo: |
|
237 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServBreakInfo\n" ); |
|
238 BreakInfoL(aMessage); |
|
239 break; |
|
240 |
|
241 case EDebugServReadRegisters: |
|
242 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServReadRegisters\n" ); |
|
243 ReadRegistersL(aMessage); |
|
244 break; |
|
245 |
|
246 case EDebugServWriteRegisters: |
|
247 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServWriteRegisters\n" ); |
|
248 WriteRegistersL(aMessage); |
|
249 break; |
|
250 |
|
251 case EDebugServGetEvent: |
|
252 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetEvent\n" ); |
|
253 GetEventL(aMessage); |
|
254 break; |
|
255 |
|
256 case EDebugServCancelGetEvent: |
|
257 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServCancelGetEvent\n" ); |
|
258 CancelGetEventL(aMessage); |
|
259 break; |
|
260 |
|
261 case EDebugServAttachExecutable: |
|
262 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServAttachExecutable\n" ); |
|
263 AttachProcessL(aMessage); |
|
264 break; |
|
265 |
|
266 case EDebugServDetachExecutable: |
|
267 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServDetachExecutable\n" ); |
|
268 DetachProcessL(aMessage); |
|
269 break; |
|
270 |
|
271 case EDebugServAttachAll: |
|
272 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServAttachAll\n" ); |
|
273 AttachAllL(aMessage); |
|
274 break; |
|
275 |
|
276 case EDebugServDetachAll: |
|
277 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServDetachAll\n" ); |
|
278 DetachAllL(aMessage); |
|
279 break; |
|
280 |
|
281 case EDebugServGetDebugFunctionalityBufSize: |
|
282 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetDebugFunctionalityBufSize\n" ); |
|
283 GetDebugFunctionalityBufSizeL(aMessage); |
|
284 break; |
|
285 |
|
286 case EDebugServGetDebugFunctionality: |
|
287 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetDebugFunctionality\n" ); |
|
288 GetDebugFunctionalityL(aMessage); |
|
289 break; |
|
290 |
|
291 case EDebugServSetEventAction: |
|
292 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSetEventAction\n" ); |
|
293 SetEventActionL(aMessage); |
|
294 break; |
|
295 |
|
296 case EDebugServGetList: |
|
297 LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetList\n" ); |
|
298 GetListL(aMessage); |
|
299 break; |
|
300 |
|
301 case EDebugServStep: |
|
302 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServStep\n"); |
|
303 StepL(aMessage); |
|
304 break; |
|
305 |
|
306 case EDebugServSetProcessBreak: |
|
307 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServSetProcessBreak\n"); |
|
308 SetProcessBreakL(aMessage); |
|
309 break; |
|
310 |
|
311 case EDebugServProcessBreakInfo: |
|
312 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServProcessBreakInfo\n"); |
|
313 ProcessBreakInfoL(aMessage); |
|
314 break; |
|
315 |
|
316 case EDebugServKillProcess: |
|
317 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServKillProcess\n"); |
|
318 KillProcessL(aMessage); |
|
319 break; |
|
320 |
|
321 #ifdef _DEBUG |
|
322 case EDebugServMarkHeap: |
|
323 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServMarkHeap\n"); |
|
324 // all taken care of in HeapWatcher |
|
325 aMessage.Complete(KErrNone); |
|
326 break; |
|
327 |
|
328 case EDebugServMarkEnd: |
|
329 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServMarkEnd\n"); |
|
330 // all taken care of in HeapWatcher |
|
331 aMessage.Complete(KErrNone); |
|
332 break; |
|
333 |
|
334 case EDebugServFailAlloc: |
|
335 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServFailAlloc\n"); |
|
336 DoFailAlloc(aMessage); |
|
337 break; |
|
338 #endif |
|
339 case EDebugServReadCrashFlash: |
|
340 ReadCrashLogL(aMessage); |
|
341 break; |
|
342 case EDebugServWriteCrashFlash: |
|
343 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServWriteCrashFlash\n"); |
|
344 WriteCrashConfigL(aMessage); |
|
345 break; |
|
346 case EDebugServEraseCrashFlash: |
|
347 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServEraseCrashFlash\n"); |
|
348 EraseCrashLogL(aMessage); |
|
349 break; |
|
350 case EDebugServEraseEntireCrashFlash: |
|
351 LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServEraseEntireCrashFlash\n"); |
|
352 EraseEntireCrashLogL(aMessage); |
|
353 break; |
|
354 default: |
|
355 LOG_MSG( "CSecuritySvrSession::ServiceL() Unknown request, calling User::Leave(KErrNotSupported);\n" ); |
|
356 User::Leave(KErrNotSupported); |
|
357 break; |
|
358 } |
|
359 |
|
360 //insert ending heap markers |
|
361 HeapWatcher(aMessage.Function(), EFalse); |
|
362 |
|
363 LOG_EXIT(); |
|
364 } |
|
365 |
|
366 #ifdef _DEBUG |
|
367 /** |
|
368 Used to control heap failure in debug mode. |
|
369 @param aMessage If aMessage.Int0 is non-zero then heap will be set to fail on that allocation. |
|
370 If aMessage.Int0 is zero then the heap failure count is reset |
|
371 */ |
|
372 void CSecuritySvrSession::DoFailAlloc(const RMessage2& aMessage) |
|
373 { |
|
374 TInt count = aMessage.Int0(); |
|
375 if(count == 0) |
|
376 { |
|
377 __UHEAP_RESET; |
|
378 } |
|
379 else |
|
380 { |
|
381 __UHEAP_FAILNEXT(count); |
|
382 } |
|
383 aMessage.Complete(KErrNone); |
|
384 } |
|
385 #endif |
|
386 |
|
387 /** |
|
388 Suspends execution of the specified thread. |
|
389 |
|
390 @param aMessage contains an integer representation of the target thread's |
|
391 thread ID at offset 0. |
|
392 |
|
393 @leave KErrPermissionDenied if security check fails or KErrArgument if the |
|
394 thread does not exist |
|
395 */ |
|
396 void CSecuritySvrSession::SuspendThreadL(const RMessage2& aMessage) |
|
397 { |
|
398 |
|
399 LOG_MSG( "CSecuritySvrSession::SuspendThreadL()\n" ); |
|
400 |
|
401 //get thread ID |
|
402 TThreadId threadId = ReadTThreadIdL(aMessage, 0); |
|
403 //check attached |
|
404 CheckAttachedL(threadId, aMessage, EFalse); |
|
405 |
|
406 //security check passed so can perform actions |
|
407 User::LeaveIfError(Server().iKernelDriver.SuspendThread(threadId)); |
|
408 |
|
409 aMessage.Complete(KErrNone); |
|
410 } |
|
411 |
|
412 /** |
|
413 Resumes execution of the specified thread. |
|
414 |
|
415 @param aMessage contains an integer representation of the target thread's |
|
416 thread ID at offset 0. |
|
417 |
|
418 @leave KErrPermissionDenied if security check fails or KErrArgument if the |
|
419 thread does not exist |
|
420 */ |
|
421 void CSecuritySvrSession::ResumeThreadL(const RMessage2& aMessage) |
|
422 { |
|
423 LOG_MSG( "CSecuritySvrSession::ResumeThreadL()\n" ); |
|
424 |
|
425 //get thread ID |
|
426 TThreadId threadId = ReadTThreadIdL(aMessage, 0); |
|
427 |
|
428 //check attached |
|
429 CheckAttachedL(threadId, aMessage, EFalse); |
|
430 |
|
431 //security check passed so can perform actions |
|
432 TInt err = Server().iKernelDriver.ResumeThread(threadId); |
|
433 aMessage.Complete(err); |
|
434 } |
|
435 |
|
436 void CSecuritySvrSession::GetDebugFunctionalityBufSizeL(const RMessage2& aMessage) |
|
437 // |
|
438 // Retrieve size of functionality data buffer in bytes which must be allocated |
|
439 // by the client |
|
440 // |
|
441 { |
|
442 LOG_MSG( "CSecuritySvrSession::GetDebugFunctionalityBufSizeL()\n" ); |
|
443 |
|
444 TUint32 result = 0; |
|
445 // Get Buffer size from the kernel driver |
|
446 User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionalityBufSize(result)); |
|
447 |
|
448 TPtr8 stuff((TUint8*)&result,4, 4); |
|
449 |
|
450 aMessage.WriteL(0,stuff); |
|
451 |
|
452 aMessage.Complete(KErrNone); |
|
453 } |
|
454 |
|
455 void CSecuritySvrSession::GetDebugFunctionalityL(const RMessage2& aMessage) |
|
456 // |
|
457 // Retrieve the functionality data and place it in a buffer |
|
458 // allocated by the client. |
|
459 // |
|
460 { |
|
461 LOG_MSG( "CSecuritySvrSession::GetDebugFunctionalityL()\n" ); |
|
462 |
|
463 TUint32 dfsize = 0; |
|
464 |
|
465 // Get Buffer size from the kernel driver |
|
466 User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionalityBufSize(dfsize)); |
|
467 |
|
468 // Allocate space for the functionality data |
|
469 HBufC8* dftext = HBufC8::NewLC(dfsize); |
|
470 |
|
471 const TPtr8& dfPtr = dftext->Des(); |
|
472 |
|
473 // Extract said data from the device driver |
|
474 User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionality((TDes8&)dfPtr)); |
|
475 |
|
476 // Return data to client |
|
477 aMessage.WriteL(0,dfPtr); |
|
478 |
|
479 // Free buffer |
|
480 CleanupStack::PopAndDestroy(dftext); |
|
481 |
|
482 aMessage.Complete(KErrNone); |
|
483 } |
|
484 |
|
485 /** |
|
486 Reads memory from a specified thread using the passed parameters. The user |
|
487 should ensure that the TPtr8 that is passed in has size greater than or equal |
|
488 to the size of the memory that is trying to be read. |
|
489 |
|
490 @param aMessage The RMessage2 object should be constructed as follows: |
|
491 * aMessage.Int0() is the thread ID of the target debug app |
|
492 * aMessage.Ptr1() is a TMemoryInfo object which contains the following: |
|
493 * the address of the memory to be read from the target debug thread |
|
494 * the size of the memory block to be read from the target debug thread |
|
495 * the access size to use |
|
496 * the endianess to interpret the data as |
|
497 * aMessage.Ptr2() is the address of the buffer in the debug agent thread |
|
498 that the data from the target debug app should be written into |
|
499 |
|
500 @leave KErrPermissionDenied if client is not attached to the target |
|
501 thread's process, |
|
502 KErrNoMemory if memory could not be allocated, |
|
503 KErrArgument if there are problems with the aMessage object, |
|
504 KErrBadHandle if the thread represented by aMessage.Ptr0() is invalid, |
|
505 an error value from CSecuritySvrSession::ValidateMemoryInfo if checking |
|
506 the memory attributes failed, |
|
507 or another of the system wide error codes |
|
508 */ |
|
509 void CSecuritySvrSession::ReadMemoryL(const RMessage2& aMessage) |
|
510 { |
|
511 LOG_MSG( "CSecuritySvrSession::ReadMemoryL()\n" ); |
|
512 |
|
513 //get debug app thread ID |
|
514 TThreadId threadId = ReadTThreadIdL(aMessage, 0); |
|
515 |
|
516 CheckAttachedL(threadId, aMessage, ETrue); |
|
517 |
|
518 //create and initialise the memory info object |
|
519 TMemoryInfo targetMemory; |
|
520 TPtr8 targetMemoryPtr( (TUint8 *)&targetMemory, sizeof(TMemoryInfo) ); |
|
521 |
|
522 aMessage.ReadL(1,targetMemoryPtr); |
|
523 |
|
524 //check memory info is acceptable |
|
525 ValidateMemoryInfoL(threadId, targetMemory, ETrue); |
|
526 |
|
527 RBuf8 data; |
|
528 data.CreateL(targetMemory.iSize); |
|
529 data.CleanupClosePushL(); |
|
530 |
|
531 //fill buffer with data from target debug thread |
|
532 User::LeaveIfError(Server().iKernelDriver.ReadMemory(threadId, targetMemory.iAddress, targetMemory.iSize, data)); |
|
533 |
|
534 //attempt to write the data from the target debug thread back to the agent |
|
535 aMessage.WriteL(2, data); |
|
536 |
|
537 //delete temporary buffer |
|
538 CleanupStack::PopAndDestroy(&data); |
|
539 |
|
540 aMessage.Complete(KErrNone); |
|
541 } |
|
542 |
|
543 /** |
|
544 Writes memory to a specified thread using the passed parameters. |
|
545 |
|
546 @param aMessage The RMessage2 object should be constructed as follows: |
|
547 * aMessage.Ptr0() is the thread ID of the target debug app |
|
548 * aMessage.Ptr1() is a TMemoryInfo object which contains the following: |
|
549 * the address of the memory to be written to the target debug thread |
|
550 * the size of the memory block to be written to the target debug thread |
|
551 * the access size to use |
|
552 * the endianess to interpret the data as |
|
553 * aMessage.Ptr2() is the address of the buffer in the debug agent thread |
|
554 that the data to write to the target debug app should be read from |
|
555 |
|
556 @leave KErrPermissionDenied if client is not attached (actively) to the target |
|
557 thread's process, |
|
558 KErrNoMemory if memory could not be allocated, |
|
559 KErrArgument if there are problems with the aMessage object, |
|
560 KErrBadHandle if the thread represented by aMessage.Ptr0() is invalid, |
|
561 an error value from CSecuritySvrSession::ValidateMemoryInfo if checking |
|
562 the memory attributes failed, |
|
563 or another of the system wide error codes |
|
564 */ |
|
565 void CSecuritySvrSession::WriteMemoryL(const RMessage2& aMessage) |
|
566 { |
|
567 LOG_MSG( "CSecuritySvrSession::WriteMemoryL()\n" ); |
|
568 |
|
569 //get debug app thread ID |
|
570 TThreadId threadId = ReadTThreadIdL(aMessage, 0); |
|
571 |
|
572 CheckAttachedL(threadId, aMessage, EFalse); |
|
573 |
|
574 //create and initialise the memory info object |
|
575 TMemoryInfo targetMemory; |
|
576 TPtr8 targetMemoryPtr( (TUint8 *)&targetMemory, sizeof(TMemoryInfo) ); |
|
577 |
|
578 aMessage.ReadL(1,targetMemoryPtr); |
|
579 |
|
580 //check memory info is acceptable |
|
581 ValidateMemoryInfoL(threadId, targetMemory, EFalse); |
|
582 |
|
583 //create temporary buffer and read data from client |
|
584 RBuf8 data; |
|
585 data.CreateL(targetMemory.iSize); |
|
586 data.CleanupClosePushL(); |
|
587 |
|
588 aMessage.ReadL(2, data); |
|
589 |
|
590 // what about telling the driver about endianess/access size? |
|
591 User::LeaveIfError(Server().iKernelDriver.WriteMemory(threadId, targetMemory.iAddress, targetMemory.iSize, data)); |
|
592 |
|
593 //free temporary buffer |
|
594 CleanupStack::PopAndDestroy(&data); |
|
595 |
|
596 aMessage.Complete(KErrNone); |
|
597 } |
|
598 |
|
599 /** |
|
600 @internalTechnology |
|
601 |
|
602 Notes: This call is used to set a thread specific breakpoint. Its input arguments |
|
603 are the thread id, address and architecture type of the breakpoint. It returns success |
|
604 or failure, and if successful, it sets the TBreakId in the Debug Agent to the |
|
605 breakpoint id by which it can be referenced in future calls to ModifyBreak,ClearBreak and |
|
606 BreakInfo. |
|
607 |
|
608 @param aMessage.Ptr0() - aThreadId is thread id of the target debug process |
|
609 @param aMessage.Ptr1() - Address of a TBreakInfo in the Debug Agent |
|
610 @param aMessage.Ptr2() - Address of a TBreakId in the Debug Agent |
|
611 @leave KErrPermissionDenied if the security check fails. |
|
612 KErrAlreadyExists if there is a breakpoint overlapping the desired address. |
|
613 KErrNotSupported if the architecture type is unrecognised. |
|
614 KErrNoMemory if there is no more memory to complete the operation. |
|
615 KErrArgument if the breakpoint address alignment is unsuitable for the requested |
|
616 breakpoint. |
|
617 KErrOverflow if there are too many breakpoints set. |
|
618 */ |
|
619 void CSecuritySvrSession::SetBreakL(const RMessage2& aMessage) |
|
620 { |
|
621 LOG_MSG( "CSecuritySvrSession::SetBreakL!()\n" ); |
|
622 |
|
623 //get debug app thread ID |
|
624 TThreadId threadId = ReadTThreadIdL(aMessage, 0); |
|
625 |
|
626 //check that the agent has attached to the target process |
|
627 CheckAttachedL(threadId, aMessage, EFalse); |
|
628 |
|
629 //create and initialise the break info object |
|
630 TBreakInfo breakInfo; |
|
631 TPtr8 breakInfoPtr( (TUint8 *)&breakInfo, sizeof(TBreakInfo) ); |
|
632 |
|
633 aMessage.ReadL(1,breakInfoPtr); |
|
634 |
|
635 LOG_MSG4( "CSecuritySvrSession::SetBreakL, threadId=0x%lx, addr=0x%x, mode=%d", |
|
636 threadId.Id(), breakInfo.iAddress, breakInfo.iArchitectureMode); |
|
637 |
|
638 //set break in target app |
|
639 TBreakId breakId = 0; |
|
640 User::LeaveIfError(Server().iKernelDriver.SetBreak(breakId, threadId, breakInfo.iAddress, breakInfo.iArchitectureMode)); |
|
641 |
|
642 //attempt to write the break id back to the debug agent |
|
643 WriteDataL(aMessage, 2, &breakId, sizeof(breakId)); |
|
644 |
|
645 aMessage.Complete(KErrNone); |
|
646 } |
|
647 |
|
648 /** |
|
649 Clears a breakpoint previously set by a SetBreak() call. |
|
650 |
|
651 @param aMessage.Int0() - TBreakId of the breakpoint to be removed. |
|
652 */ |
|
653 void CSecuritySvrSession::ClearBreakL(const RMessage2& aMessage) |
|
654 { |
|
655 LOG_MSG( "CSecuritySvrSession::ClearBreakL()\n" ); |
|
656 |
|
657 const TInt breakId = aMessage.Int0(); |
|
658 |
|
659 // Check that the breakpoint exists |
|
660 TUint64 objectId; |
|
661 TUint32 address; |
|
662 TArchitectureMode mode; |
|
663 TBool threadSpecific = EFalse; |
|
664 |
|
665 User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,objectId,address,mode,threadSpecific)); |
|
666 |
|
667 if(threadSpecific) |
|
668 { |
|
669 // Check that the debug agent is attached to the thread for which the |
|
670 // breakpoint is currently set. |
|
671 LOG_MSG4( "CSecuritySvrSession::ClearBreakL( brkId=%d), addr=0x%x, tId=0x%x", |
|
672 breakId, address, I64LOW(objectId) ); |
|
673 CheckAttachedL(TThreadId(objectId), aMessage, EFalse); |
|
674 } |
|
675 else |
|
676 { |
|
677 // Check that the debug agent is attached to the process for which the |
|
678 // breakpoint is currently set. |
|
679 LOG_MSG4( "CSecuritySvrSession::ClearBreakL( brkId=%d), addr=0x%x, pId=0x%x", |
|
680 breakId, address, I64LOW(objectId) ); |
|
681 CheckAttachedL(TProcessId(objectId), aMessage, EFalse); |
|
682 } |
|
683 |
|
684 // Finally clear the breakpoint |
|
685 User::LeaveIfError(Server().iKernelDriver.ClearBreak(breakId)); |
|
686 |
|
687 aMessage.Complete(KErrNone); |
|
688 } |
|
689 |
|
690 /** |
|
691 @param aMessage.Int0() - Breakpoint Id of interest |
|
692 @param aMessage.Ptr1() - Address in Debug Agent to place threadId of the breakpoint |
|
693 @param aMessage.Ptr2() - Address in Debug Agent to place address of the breakpoint |
|
694 @param aMessage.Ptr3() - Address in Debug Agent to place the architecture mode of the breakpoint |
|
695 @leave Any error which may be returned by RSessionBase::SendReceive() |
|
696 */ |
|
697 void CSecuritySvrSession::BreakInfoL(const RMessage2& aMessage) |
|
698 { |
|
699 const TBreakId breakId = (TBreakId)aMessage.Int0(); |
|
700 |
|
701 TThreadId threadId; |
|
702 TUint32 address; |
|
703 TArchitectureMode mode; |
|
704 TBool threadSpecific = ETrue; |
|
705 |
|
706 TUint64 threadIdData; |
|
707 User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,threadIdData,address,mode,threadSpecific)); |
|
708 |
|
709 if(!threadSpecific) |
|
710 { |
|
711 User::Leave(KErrNotFound); |
|
712 } |
|
713 |
|
714 threadId = TThreadId(threadIdData); |
|
715 |
|
716 //check that the agent has attached to the target process |
|
717 CheckAttachedL(threadId, aMessage, EFalse); |
|
718 |
|
719 // return the threadId |
|
720 WriteDataL(aMessage, 1, &threadId, sizeof(threadId)); |
|
721 |
|
722 // return the address |
|
723 WriteDataL(aMessage, 2, &address, sizeof(address)); |
|
724 |
|
725 // return the mode |
|
726 WriteDataL(aMessage, 3, &mode, sizeof(mode)); |
|
727 |
|
728 aMessage.Complete(KErrNone); |
|
729 } |
|
730 |
|
731 /** |
|
732 @internalTechnology |
|
733 |
|
734 Modify a previously set breakpoint. |
|
735 |
|
736 @param aMessage.Int0() - The breakpoint id of the breakpoint to modify |
|
737 @param aMessage.Ptr1() - The new Thread Id for the breakpoint |
|
738 @param aMessage.Int2() - The new virtual memory address for the breakpoint |
|
739 @param aMessage.Int3() - The new architecture mode for the breakpoint |
|
740 @return KErrNone if succesful. KErrPermissionDenied if the security check fails. |
|
741 KErrAlreadyExists if there is a breakpoint overlapping the desired address. |
|
742 KErrNotSupported if the architecture type is unrecognised. |
|
743 KErrNoMemory if there is no more memory to complete the operation. |
|
744 KErrArgument if the breakpoint address alignment is unsuitable for the requested |
|
745 breakpoint. |
|
746 KErrOverflow if there are too many breakpoints set. |
|
747 */ |
|
748 void CSecuritySvrSession::ModifyBreakL(const RMessage2& aMessage) |
|
749 { |
|
750 const TBreakId breakId = (TBreakId)aMessage.Int0(); |
|
751 const TThreadId threadId = ReadTThreadIdL(aMessage, 1); |
|
752 const TUint32 address = aMessage.Int2(); |
|
753 const TArchitectureMode mode = (TArchitectureMode)aMessage.Int3(); |
|
754 |
|
755 // Get information on the breakpoint to check the security status |
|
756 TUint64 checkThreadId; |
|
757 TUint32 checkAddress; |
|
758 TArchitectureMode checkMode; |
|
759 TBool threadSpecific; |
|
760 |
|
761 User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,checkThreadId,checkAddress,checkMode,threadSpecific)); |
|
762 |
|
763 LOG_MSG4( "CSecuritySvrSession::ModifyBreakL(brkId=%d) tId=0x%x, addr=0x%x", |
|
764 breakId, I64LOW(threadId.Id()), address ); |
|
765 |
|
766 // Security check that the thread Id is associated with the debug agent |
|
767 |
|
768 //check that the agent has attached to the target process |
|
769 CheckAttachedL(TThreadId(checkThreadId), aMessage, EFalse); |
|
770 |
|
771 // now check that the thread Id which is being set is permitted |
|
772 //check that the agent has attached to the target process |
|
773 CheckAttachedL(threadId, aMessage, EFalse); |
|
774 |
|
775 User::LeaveIfError(Server().iKernelDriver.ModifyBreak(breakId,threadId,address,mode)); |
|
776 |
|
777 aMessage.Complete(KErrNone); |
|
778 } |
|
779 |
|
780 /** |
|
781 @internalTechnology |
|
782 |
|
783 Notes: This call is used to set a process wide breakpoint. Its input arguments |
|
784 are the process id, address and architecture type of the breakpoint. It returns success |
|
785 or failure, and if successful, it sets the TBreakId in the Debug Agent to the |
|
786 breakpoint id by which it can be referenced in future calls to ModifyBreak,ClearBreak and |
|
787 BreakInfo. |
|
788 |
|
789 @param aMessage.Ptr0() - aProcessId is process id of the target debug process |
|
790 @param aMessage.Ptr1() - Address of a TBreakInfo in the Debug Agent |
|
791 @param aMessage.Ptr2() - Address of a TBreakId in the Debug Agent |
|
792 @leave KErrPermissionDenied if the security check fails. |
|
793 KErrAlreadyExists if there is a breakpoint overlapping the desired address. |
|
794 KErrNotSupported if the architecture type is unrecognised. |
|
795 KErrNoMemory if there is no more memory to complete the operation. |
|
796 KErrArgument if the breakpoint address alignment is unsuitable for the requested |
|
797 breakpoint. |
|
798 KErrOverflow if there are too many breakpoints set. |
|
799 */ |
|
800 void CSecuritySvrSession::SetProcessBreakL(const RMessage2& aMessage) |
|
801 { |
|
802 LOG_MSG( "CSecuritySvrSession::SetProcessBreakL()\n" ); |
|
803 |
|
804 //get debug app thread ID |
|
805 TProcessId procId = ReadTProcessIdL(aMessage, 0); |
|
806 |
|
807 //check that the agent has attached to the target process |
|
808 CheckAttachedL(procId, aMessage, EFalse); |
|
809 |
|
810 //create and initialise the memory info object |
|
811 TBreakInfo breakInfo; |
|
812 TPtr8 breakInfoPtr( (TUint8 *)&breakInfo, sizeof(TBreakInfo) ); |
|
813 |
|
814 aMessage.ReadL(1,breakInfoPtr); |
|
815 |
|
816 LOG_MSG4( "CSecuritySvrSession::SetProcessBreakL pId=0x%x, addr=0x%x, mode=%d ", |
|
817 I64LOW(procId.Id()), breakInfo.iAddress, breakInfo.iArchitectureMode ); |
|
818 |
|
819 //set break in target app |
|
820 TBreakId breakId = 0; |
|
821 User::LeaveIfError(Server().iKernelDriver.SetProcessBreak(breakId, procId, breakInfo.iAddress, breakInfo.iArchitectureMode)); |
|
822 |
|
823 //attempt to write the break id back to the debug agent |
|
824 WriteDataL(aMessage, 2, &breakId, sizeof(breakId)); |
|
825 |
|
826 aMessage.Complete(KErrNone); |
|
827 } |
|
828 |
|
829 /** |
|
830 @internalTechnology |
|
831 |
|
832 Modify a previously set process breakpoint. |
|
833 |
|
834 @param aMessage.Int0() - The breakpoint id of the breakpoint to modify |
|
835 @param aMessage.Ptr1() - The new Process Id for the breakpoint |
|
836 @param aMessage.Int2() - The new virtual memory address for the breakpoint |
|
837 @param aMessage.Int3() - The new architecture mode for the breakpoint |
|
838 @return KErrNone if succesful. KErrPermissionDenied if the security check fails. |
|
839 KErrAlreadyExists if there is a breakpoint overlapping the desired address. |
|
840 KErrNotSupported if the architecture type is unrecognised. |
|
841 KErrNoMemory if there is no more memory to complete the operation. |
|
842 KErrArgument if the breakpoint address alignment is unsuitable for the requested |
|
843 breakpoint. |
|
844 KErrOverflow if there are too many breakpoints set. |
|
845 */ |
|
846 void CSecuritySvrSession::ModifyProcessBreakL(const RMessage2& aMessage) |
|
847 { |
|
848 const TBreakId breakId = (TBreakId)aMessage.Int0(); |
|
849 const TProcessId processId = ReadTProcessIdL(aMessage, 1); |
|
850 const TUint32 address = aMessage.Int2(); |
|
851 const TArchitectureMode mode = (TArchitectureMode)aMessage.Int3(); |
|
852 |
|
853 // Get information on the breakpoint to check the security status |
|
854 TUint64 checkProcessId; |
|
855 TUint32 checkAddress; |
|
856 TArchitectureMode checkMode; |
|
857 TBool threadSpecific; |
|
858 |
|
859 User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,checkProcessId,checkAddress,checkMode,threadSpecific)); |
|
860 |
|
861 LOG_MSG4( "CSecuritySvrSession::ModifyProcessBreakL(brkId=%d) pId=0x%x, addr=0x%x", |
|
862 breakId, I64LOW(processId.Id()), address ); |
|
863 |
|
864 |
|
865 // Security check that the process Id is associated with the debug agent |
|
866 |
|
867 //check that the agent has attached to the target process |
|
868 CheckAttachedL(TProcessId(checkProcessId), aMessage, EFalse); |
|
869 |
|
870 // now check that the process Id which is being set is permitted |
|
871 //check that the agent has attached to the target process |
|
872 CheckAttachedL(processId, aMessage, EFalse); |
|
873 |
|
874 User::LeaveIfError(Server().iKernelDriver.ModifyProcessBreak(breakId,processId,address,mode)); |
|
875 |
|
876 aMessage.Complete(KErrNone); |
|
877 } |
|
878 |
|
879 /** |
|
880 @param aMessage.Int0() - Breakpoint Id of interest |
|
881 @param aMessage.Ptr1() - Address in Debug Agent to place process Id of the breakpoint |
|
882 @param aMessage.Ptr2() - Address in Debug Agent to place address of the breakpoint |
|
883 @param aMessage.Ptr3() - Address in Debug Agent to place the architecture mode of the breakpoint |
|
884 @leave Any error which may be returned by RSessionBase::SendReceive() |
|
885 */ |
|
886 void CSecuritySvrSession::ProcessBreakInfoL(const RMessage2& aMessage) |
|
887 { |
|
888 const TBreakId breakId = (TBreakId)aMessage.Int0(); |
|
889 |
|
890 TProcessId procId; |
|
891 TUint32 address; |
|
892 TArchitectureMode mode; |
|
893 TBool threadSpecific; |
|
894 |
|
895 TUint64 procIdData; |
|
896 User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,procIdData,address,mode,threadSpecific)); |
|
897 if(threadSpecific) |
|
898 { |
|
899 User::Leave(KErrNotFound); |
|
900 } |
|
901 procId = TProcessId(procIdData); |
|
902 |
|
903 //check that the agent has attached to the target process |
|
904 CheckAttachedL(procId, aMessage, EFalse); |
|
905 |
|
906 // return the processId |
|
907 WriteDataL(aMessage, 1, &procId, sizeof(procId)); |
|
908 |
|
909 // return the address |
|
910 WriteDataL(aMessage, 2, &address, sizeof(address)); |
|
911 |
|
912 // return the mode |
|
913 WriteDataL(aMessage, 3, &mode, sizeof(mode)); |
|
914 |
|
915 aMessage.Complete(KErrNone); |
|
916 } |
|
917 |
|
918 /** |
|
919 Read register values. |
|
920 |
|
921 @param aMessage should contain: |
|
922 * at offset 0 a pointer to the thread ID of the target thread |
|
923 * at offset 1 a descriptor representing an array of TRegisterInfo |
|
924 register IDs |
|
925 * at offset 2 a descriptor representing an array into which TRegister |
|
926 register values will be written |
|
927 * at offset 3 a descriptor representing an array into which TUint8 |
|
928 register flags will be written |
|
929 |
|
930 @leave KErrArgument if the max length of the array at offset 1 is not a |
|
931 multiple of sizeof(TRegisterInfo), if the max length of the array |
|
932 at offset 2 is not a multiple of sizeof(TRegister), if the max |
|
933 length of the array at offset 3 is not a multiple of sizeof(TUint8), if |
|
934 any of the descriptors have max length of 0, or if the three |
|
935 descriptors do not represent the same number of registers, |
|
936 KErrNoMemory if there is insufficient memory, |
|
937 KErrDied, if the thread with thread ID aThreadId is dead |
|
938 */ |
|
939 void CSecuritySvrSession::ReadRegistersL(const RMessage2& aMessage) |
|
940 { |
|
941 LOG_MSG( "CSecuritySvrSession::ReadRegistersL()\n" ); |
|
942 |
|
943 const TThreadId threadId = ReadTThreadIdL(aMessage, 0); |
|
944 |
|
945 //check the agent is attached to the thread |
|
946 CheckAttachedL(threadId, aMessage, ETrue); |
|
947 |
|
948 //number of registers being requested |
|
949 TUint32 numberOfRegisters; |
|
950 |
|
951 //check length of descriptors is acceptable |
|
952 ValidateRegisterBuffersL(aMessage, numberOfRegisters); |
|
953 |
|
954 // Passed data will be saved in this descriptor. |
|
955 RBuf8 ids; |
|
956 ids.CreateL(numberOfRegisters * sizeof(TRegisterInfo)); |
|
957 // Do the right cleanup if anything subsequently goes wrong |
|
958 ids.CleanupClosePushL(); |
|
959 |
|
960 //read the data from the client thread |
|
961 aMessage.ReadL(1, ids); |
|
962 |
|
963 //create buffer to fill with data from target debug thread |
|
964 HBufC8 *data = HBufC8::NewLC(aMessage.GetDesMaxLength(2)); |
|
965 TPtr8 values(data->Des()); |
|
966 |
|
967 HBufC8 *flagsData = HBufC8::NewLC(numberOfRegisters * sizeof(TUint8)); |
|
968 TPtr8 flags(flagsData->Des()); |
|
969 |
|
970 //get register info and return relevant parts back to agent |
|
971 User::LeaveIfError(Server().iKernelDriver.ReadRegisters(threadId, ids, values, flags)); |
|
972 aMessage.WriteL(2, values); |
|
973 aMessage.WriteL(3, flags); |
|
974 |
|
975 //delete temporary buffers and return status |
|
976 CleanupStack::PopAndDestroy(flagsData); |
|
977 CleanupStack::PopAndDestroy(data); |
|
978 CleanupStack::PopAndDestroy(&ids); |
|
979 |
|
980 aMessage.Complete(KErrNone); |
|
981 } |
|
982 |
|
983 /** |
|
984 Write register values. |
|
985 |
|
986 @param aMessage should contain: |
|
987 * at offset 0 a pointer to the thread ID of the target thread |
|
988 * at offset 1 a descriptor representing an array of TRegisterInfo |
|
989 register IDs |
|
990 * at offset 2 a descriptor representing an array of TRegister register |
|
991 values |
|
992 * at offset 3 a descriptor representing an array into which TUint8 |
|
993 register flags will be written |
|
994 |
|
995 @leave KErrArgument if the max length of the array at offset 1 is not a |
|
996 multiple of sizeof(TRegisterInfo), if the max length of the array |
|
997 at offset 2 is not a multiple of sizeof(TRegister), if the max |
|
998 length of the array at offset 3 is not a multiple of sizeof(TUint8), if |
|
999 any of the descriptors have max length of 0, or if the three |
|
1000 descriptors do not represent the same number of registers, |
|
1001 KErrNoMemory if there is insufficient memory, |
|
1002 KErrDied, if the thread with thread ID aThreadId is dead |
|
1003 */ |
|
1004 void CSecuritySvrSession::WriteRegistersL(const RMessage2& aMessage) |
|
1005 { |
|
1006 LOG_MSG( "CSecuritySvrSession::WriteRegistersL()\n" ); |
|
1007 |
|
1008 const TThreadId threadId = ReadTThreadIdL(aMessage, 0); |
|
1009 |
|
1010 CheckAttachedL(threadId, aMessage, EFalse); |
|
1011 |
|
1012 //number of registers attempting to set |
|
1013 TUint32 numberOfRegisters; |
|
1014 |
|
1015 //check length of descriptors is acceptable |
|
1016 ValidateRegisterBuffersL(aMessage, numberOfRegisters); |
|
1017 |
|
1018 // Passed register ids will be saved in this descriptor. |
|
1019 RBuf8 ids; |
|
1020 |
|
1021 //allocate buffer |
|
1022 ids.CreateL(numberOfRegisters * sizeof(TRegisterInfo)); |
|
1023 |
|
1024 // Do the right cleanup if anything subsequently goes wrong |
|
1025 ids.CleanupClosePushL(); |
|
1026 |
|
1027 //read the data from the client thread |
|
1028 aMessage.ReadL(1, ids); |
|
1029 |
|
1030 // Passed register values will be saved in this descriptor. |
|
1031 RBuf8 values; |
|
1032 |
|
1033 //allocate buffer |
|
1034 values.CreateL(aMessage.GetDesMaxLength(2)); |
|
1035 // Do the right cleanup if anything subsequently goes wrong |
|
1036 values.CleanupClosePushL(); |
|
1037 //read the data from the client thread |
|
1038 aMessage.ReadL(2,values); |
|
1039 |
|
1040 HBufC8 *flagsData = HBufC8::NewLC(numberOfRegisters*sizeof(TUint8)); |
|
1041 TPtr8 flags(flagsData->Des()); |
|
1042 |
|
1043 //get register info and return relevant parts back to agent |
|
1044 User::LeaveIfError(Server().iKernelDriver.WriteRegisters(threadId, ids, values, flags)); |
|
1045 |
|
1046 //write flags data back |
|
1047 aMessage.WriteL(3, flags); |
|
1048 |
|
1049 CleanupStack::PopAndDestroy(flagsData); |
|
1050 CleanupStack::PopAndDestroy(&values); |
|
1051 CleanupStack::PopAndDestroy(&ids); |
|
1052 |
|
1053 aMessage.Complete(KErrNone); |
|
1054 } |
|
1055 |
|
1056 /** |
|
1057 Processes an attach request from a debug agent. Gets the target debug |
|
1058 processes' original FileName as an argument. The method sets completion |
|
1059 status of the aMessage argument to KErrNone if successfully attached and to |
|
1060 another of the system wide error codes if there were problems. |
|
1061 |
|
1062 @param aMessage contains: |
|
1063 * a boolean at offset 0 which indicates whether the agent wishes to |
|
1064 attach passively |
|
1065 * a buffer at offset 1 which contains the FileName |
|
1066 of the target debug process. |
|
1067 */ |
|
1068 void CSecuritySvrSession::AttachProcessL(const RMessage2& aMessage) |
|
1069 { |
|
1070 LOG_MSG( "CSecuritySvrSession::AttachProcessL()\n" ); |
|
1071 |
|
1072 const TBool passive = aMessage.Int0(); |
|
1073 |
|
1074 TInt deslen = aMessage.GetDesLengthL(1); |
|
1075 |
|
1076 // Passed data will be saved in this descriptor. |
|
1077 RBuf processName; |
|
1078 |
|
1079 // Max length set to the value of "deslen", but current length is zero |
|
1080 processName.CreateL(deslen); |
|
1081 |
|
1082 // Do the right cleanup if anything subsequently goes wrong |
|
1083 processName.CleanupClosePushL(); |
|
1084 |
|
1085 // Copy the client's descriptor data into our buffer. |
|
1086 aMessage.ReadL(1,processName); |
|
1087 |
|
1088 // |
|
1089 // Security Check |
|
1090 // |
|
1091 // It is not permitted to debug the debug security server! |
|
1092 // |
|
1093 // get the secure id of the executable |
|
1094 TUid secureId(TUid::Null()); |
|
1095 GetSecureIdL(processName, secureId); |
|
1096 if (KUidDebugSecurityServer.iUid == secureId.iUid) |
|
1097 { |
|
1098 // The debug agent has requested to debug the Debug Security Server |
|
1099 // This is either an error, or an attempt to breach security. We |
|
1100 // therefore refuse to agree to this request, and return KErrPermissionDenied |
|
1101 LOG_MSG("Debug Agent attempted to debug the Debug Security Server"); |
|
1102 User::Leave(KErrPermissionDenied); |
|
1103 } |
|
1104 |
|
1105 // Check the OEM Debug token capabilities |
|
1106 GetDebugAgentOEMTokenCapsL(); |
|
1107 |
|
1108 // Get the Security info via rlibrary::getinfo |
|
1109 RLibrary::TInfo info; |
|
1110 TPckg<RLibrary::TInfo> infoBuf(info); |
|
1111 |
|
1112 TInt err = RLibrary::GetInfo(processName, infoBuf); |
|
1113 if (err != KErrNone) |
|
1114 { |
|
1115 LOG_MSG2("Cannot parse the target executable header, err=%d", err); |
|
1116 // Could not read the header for this executable :-( |
|
1117 CleanupStack::PopAndDestroy(&processName); |
|
1118 aMessage.Complete(err); |
|
1119 return; |
|
1120 } |
|
1121 |
|
1122 // Special case for AllFiles - OEM Debug tokens MUST have |
|
1123 // AllFiles, as this is what allows them to read contents |
|
1124 // of other executables. |
|
1125 TBool checkDebuggable = ETrue; |
|
1126 |
|
1127 // Does an OEM Debug Token permit debug where it would normally not be |
|
1128 // permitted? |
|
1129 if ( Server().OEMTokenPermitsDebugL(iOEMDebugCapabilities, info.iSecurityInfo.iCaps) ) |
|
1130 { |
|
1131 // OEM Debug token is valid and has sufficient capabilities |
|
1132 LOG_MSG("CSecuritySvrSession::AttachProcessL() - Debug Agent has sufficient capabilites based on OEM Debug Token"); |
|
1133 |
|
1134 checkDebuggable = EFalse; |
|
1135 } |
|
1136 |
|
1137 if (checkDebuggable) |
|
1138 { |
|
1139 // OEM Debug token (if any), does not confer sufficient capabilities to |
|
1140 // debug the specified target executable. Therefore debugging can only |
|
1141 // be permitted if the target executable itself has been built as 'Debuggable' |
|
1142 LOG_MSG("CSecuritySvrSession::AttachProcessL() - Debug Agent has insufficient capabilites based on OEM Debug Token"); |
|
1143 |
|
1144 IsDebuggableL(processName); |
|
1145 } |
|
1146 |
|
1147 User::LeaveIfError(Server().AttachProcessL(processName, iDebugAgentProcessId, passive)); |
|
1148 |
|
1149 // Inform the kernel driver about the attachment, so that it |
|
1150 // can track per-agent data about the process. |
|
1151 RBuf8 processName8; |
|
1152 |
|
1153 processName8.CreateL(deslen); |
|
1154 |
|
1155 processName8.CleanupClosePushL(); |
|
1156 |
|
1157 processName8.Copy(processName); |
|
1158 |
|
1159 User::LeaveIfError(Server().iKernelDriver.AttachProcess(processName8, iDebugAgentProcessId.Id())); |
|
1160 |
|
1161 // Create an Active Object to handle asynchronous calls to GetEvent |
|
1162 CSecuritySvrAsync* handler = CSecuritySvrAsync::NewL(this,processName8,iDebugAgentProcessId); |
|
1163 |
|
1164 err = iAsyncHandlers.Insert(handler,0); |
|
1165 if (err != KErrNone) |
|
1166 { |
|
1167 // If we don't have an asynchronous handler, we should detach |
|
1168 // the driver as well. |
|
1169 Server().iKernelDriver.DetachProcess(processName8,iDebugAgentProcessId.Id()); |
|
1170 Server().DetachProcess(processName, iDebugAgentProcessId); |
|
1171 // The DSS should NEVER panic itself. If the above calls fail, so be it we will attempt to limp on |
|
1172 } |
|
1173 |
|
1174 User::LeaveIfError(err); |
|
1175 |
|
1176 CleanupStack::PopAndDestroy(&processName8); |
|
1177 |
|
1178 CleanupStack::PopAndDestroy(&processName); |
|
1179 |
|
1180 aMessage.Complete(KErrNone); |
|
1181 } |
|
1182 |
|
1183 |
|
1184 /** |
|
1185 Processes an attach request from a debug agent from all processes. |
|
1186 The method sets completion status of the aMessage argument to KErrNone |
|
1187 if successfully attached and to another of the system wide error codes |
|
1188 if there were problems. |
|
1189 |
|
1190 @param aMessage contains no data |
|
1191 */ |
|
1192 void CSecuritySvrSession::AttachAllL(const RMessage2& aMessage) |
|
1193 { |
|
1194 LOG_MSG( "CSecuritySvrSession::AttachAllL()\n" ); |
|
1195 |
|
1196 |
|
1197 // Run the OEM Debug token, if run ok then sets iOEMDebugCapabilities |
|
1198 GetDebugAgentOEMTokenCapsL(); |
|
1199 |
|
1200 // Debug token must have All caps to use AttachToAll |
|
1201 TCapabilitySet allCaps; |
|
1202 allCaps.SetAllSupported(); |
|
1203 if (!Server().OEMTokenPermitsDebugL(iOEMDebugCapabilities, allCaps)) |
|
1204 { |
|
1205 LOG_MSG("Client's OEM token doesn't have capability ALL required for AttachAll()"); |
|
1206 User::Leave(KErrPermissionDenied); |
|
1207 } |
|
1208 |
|
1209 |
|
1210 User::LeaveIfError(Server().AttachProcessL(_L("*"), iDebugAgentProcessId, EFalse)); |
|
1211 |
|
1212 TBuf8<1> KStar8=_L8("*"); |
|
1213 |
|
1214 User::LeaveIfError(Server().iKernelDriver.AttachProcess(KStar8, iDebugAgentProcessId.Id())); |
|
1215 |
|
1216 // Create an Active Object to handle asynchronous calls to GetAllEvent |
|
1217 CSecuritySvrAsync* handler = CSecuritySvrAsync::NewL(this,KStar8,iDebugAgentProcessId); |
|
1218 TInt err = iAsyncHandlers.Insert(handler,0); |
|
1219 if (err != KErrNone) |
|
1220 { |
|
1221 // If we don't have an asynchronous handler, we should detach |
|
1222 // the driver as well. |
|
1223 Server().iKernelDriver.DetachProcess(KStar8,iDebugAgentProcessId.Id()); |
|
1224 Server().DetachProcess(_L("*"), iDebugAgentProcessId); |
|
1225 } |
|
1226 |
|
1227 User::LeaveIfError(err); |
|
1228 |
|
1229 aMessage.Complete(KErrNone); |
|
1230 } |
|
1231 |
|
1232 |
|
1233 /** |
|
1234 Reads the OEM Debug Token associated with the debug agent if any. The OEM Debug Token |
|
1235 allows the Debug Agent to debug certain executables which have not been built as |
|
1236 'Debuggable'. |
|
1237 |
|
1238 This works as follows: The OEM Debug Token is an executable with a special name |
|
1239 of the form "OEMDebug_<DA_SID>.exe" where <DA_SID> is the Secure ID of the Debug Agent |
|
1240 in hexadecimal. For example: "OEMDebug_F123ABCD.exe" would be a valid name. This token executable |
|
1241 must be signed with 'AllFiles' + X, where X is the set of PlatSec capabilities that are |
|
1242 possessed by the target executable to be debugged. |
|
1243 |
|
1244 This function reads the capabilities possessed by the token by creating a process based |
|
1245 on the executable, and reading the TSecurityInfo associated with the process. This ensures |
|
1246 that the loader has validated the token has not been tampered with and that the security |
|
1247 information is valid. |
|
1248 |
|
1249 The security information is then stored for future use as member data in iOEMDebugCapabilities. |
|
1250 |
|
1251 Leaves if there is an error, otherwise simply fills in the capabilities |
|
1252 in iOEMDebugCapabilities. |
|
1253 |
|
1254 It is not an error for the OEM Debug token not to exist. In this case, the function simply returns. |
|
1255 */ |
|
1256 void CSecuritySvrSession::GetDebugAgentOEMTokenCapsL(void) |
|
1257 { |
|
1258 if (iOEMDebugCapabilities.HasCapability(ECapabilityAllFiles)) |
|
1259 { |
|
1260 // Then we've already read the caps - wasteful to read them again |
|
1261 return; |
|
1262 } |
|
1263 |
|
1264 // Obtain the security info about the debug agent process |
|
1265 //get the debug agent's process |
|
1266 RProcess debugAgentProcess; |
|
1267 |
|
1268 CleanupClosePushL(debugAgentProcess); |
|
1269 |
|
1270 debugAgentProcess.Open(iDebugAgentProcessId); |
|
1271 |
|
1272 // We have now obtained a process handle based on the token executable, so we can check its security properties. |
|
1273 TSecurityInfo secInfo(debugAgentProcess); |
|
1274 |
|
1275 // Compute the name of the OEM debug token based on the SID of the debug agent |
|
1276 _LIT(KDSSOEMDebugTokenPrefix,"OEMDebug_"); |
|
1277 _LIT(KDSSOEMDebugTokenAppendFmt,"%08X.exe"); |
|
1278 |
|
1279 RBuf agentTokenName; |
|
1280 agentTokenName.CreateL(KDSSOEMDebugTokenPrefix().Size()+8+1); // allow space for SID+null terminator |
|
1281 agentTokenName.CleanupClosePushL(); |
|
1282 |
|
1283 agentTokenName.SetLength(0); |
|
1284 |
|
1285 // Add OEMDebug_ |
|
1286 agentTokenName.Append(KDSSOEMDebugTokenPrefix()); |
|
1287 |
|
1288 // Add debug agent Secure ID |
|
1289 agentTokenName.AppendFormat(KDSSOEMDebugTokenAppendFmt,secInfo.iSecureId.iId); |
|
1290 |
|
1291 // just log the token name for the moment. |
|
1292 RBuf8 agentTokenName8; |
|
1293 |
|
1294 agentTokenName8.CreateL(agentTokenName.Length()+1); |
|
1295 |
|
1296 agentTokenName8.CleanupClosePushL(); |
|
1297 |
|
1298 agentTokenName8.Copy(agentTokenName); |
|
1299 |
|
1300 agentTokenName8.Append(TChar(0)); |
|
1301 |
|
1302 LOG_MSG2("CSecuritySvrSession::GetDebugAgentOEMTokenCapsL() - OEM Debug Token Name is %s",agentTokenName8.Ptr()); |
|
1303 |
|
1304 // Cleanup |
|
1305 CleanupStack::PopAndDestroy(&agentTokenName8); |
|
1306 |
|
1307 // Now locate and start the executable... |
|
1308 RProcess agentToken; |
|
1309 TInt err = agentToken.Create(agentTokenName, KNullDesC); |
|
1310 if (KErrNone != err) |
|
1311 { |
|
1312 // Failed to create a process based on the token, just give up |
|
1313 LOG_MSG2("CSecuritySvrSession::GetDebugAgentOEMTokenCapsL() - Could not create process based on token due to err 0x%8x\n",err); |
|
1314 |
|
1315 // Cleanup remaining items from the stack |
|
1316 CleanupStack::PopAndDestroy(&agentTokenName); |
|
1317 |
|
1318 CleanupStack::PopAndDestroy(&debugAgentProcess); |
|
1319 return; |
|
1320 } |
|
1321 |
|
1322 // Synchronise with the process to make sure it hasn't died straight away |
|
1323 TRequestStatus stat; |
|
1324 agentToken.Rendezvous(stat); |
|
1325 if (stat != KRequestPending) |
|
1326 { |
|
1327 // logon failed - agentToken is not yet running, so cannot have terminated |
|
1328 agentToken.Kill(0); // Abort startup |
|
1329 } |
|
1330 |
|
1331 // store the OEM Debug Token security data |
|
1332 TSecurityInfo agentSecInfo(agentToken); |
|
1333 |
|
1334 // Note capabilities for future use |
|
1335 iOEMDebugCapabilities=agentSecInfo.iCaps; |
|
1336 |
|
1337 // resume the token. It _should_ just exit, but we don't really care. |
|
1338 agentToken.Resume(); |
|
1339 |
|
1340 // Wait to synchronise with agentToken - if it dies in the meantime, it |
|
1341 // also gets completed |
|
1342 User::WaitForRequest(stat); |
|
1343 |
|
1344 // Just close the handle to it again. |
|
1345 agentToken.Close(); |
|
1346 |
|
1347 // Cleanup remaining items from the stack |
|
1348 CleanupStack::PopAndDestroy(&agentTokenName); |
|
1349 |
|
1350 CleanupStack::PopAndDestroy(&debugAgentProcess); |
|
1351 |
|
1352 } |
|
1353 |
|
1354 /** |
|
1355 Checks whether the file passed in as aExecutable is XIP or not |
|
1356 |
|
1357 @param aExecutable file to check |
|
1358 @return ETrue if the file is XIP, EFalse otherwise |
|
1359 */ |
|
1360 TBool CSecuritySvrSession::IsExecutableXipL(RFile& aExecutable) |
|
1361 { |
|
1362 TUint atts; |
|
1363 User::LeaveIfError(aExecutable.Att(atts)); |
|
1364 |
|
1365 return atts & KEntryAttXIP; |
|
1366 } |
|
1367 |
|
1368 /** |
|
1369 Gets access to the symbian crash partition for crash access operation. |
|
1370 */ |
|
1371 void CSecuritySvrSession::ConnectCrashPartitionL (void) |
|
1372 { |
|
1373 LOG_MSG("CSecuritySvrSession::ConnectCrashPartitionL()"); |
|
1374 |
|
1375 TBool changed; |
|
1376 TInt error = KErrNone; |
|
1377 TInt i=0; |
|
1378 |
|
1379 //Intialising to EFalse |
|
1380 iCrashConnected = EFalse; |
|
1381 |
|
1382 TPckg<TLocalDriveCapsV2> capsBuf(iCaps); |
|
1383 |
|
1384 //check for the symbian crash partition |
|
1385 for (i=0; i<KMaxLocalDrives; i++) |
|
1386 { |
|
1387 error = iLocalDrive.Connect (i, changed); |
|
1388 if ( error == KErrNone) |
|
1389 { |
|
1390 error = iLocalDrive.Caps(capsBuf); |
|
1391 if ( error != KErrNone) |
|
1392 { |
|
1393 //continue if not found |
|
1394 continue; |
|
1395 } |
|
1396 if ( iCaps.iPartitionType == (TUint16)KPartitionTypeSymbianCrashLog) |
|
1397 { |
|
1398 LOG_MSG2("Found Symbian crash log partition on drive: %d",i); |
|
1399 iCrashConnected = ETrue; |
|
1400 break; |
|
1401 } |
|
1402 } |
|
1403 } |
|
1404 if ( i == KMaxLocalDrives) |
|
1405 { |
|
1406 LOG_MSG("No crash log partition found with valid crash log signature found. Exiting..."); |
|
1407 User::Leave (KErrNotFound); |
|
1408 } |
|
1409 |
|
1410 // Nand Flash not currently supported. |
|
1411 if (iCaps.iType == EMediaNANDFlash) |
|
1412 { |
|
1413 LOG_MSG( "CSecuritySvrSession::ConnectCrashPartitionL() Nand Flash not currently supported\n" ); |
|
1414 User::Leave (KErrNotSupported); |
|
1415 } |
|
1416 } |
|
1417 /** Checks that aHeaderData contains enough data to cast it to the |
|
1418 appropriate header type. |
|
1419 |
|
1420 @param aHeaderData buffer containing header data read from a file |
|
1421 @param aXip boolean indicating whether the header data is for an XIP image |
|
1422 |
|
1423 @return ETrue if enough data in buffer, EFalse otherwise |
|
1424 */ |
|
1425 TBool CSecuritySvrSession::CheckSufficientData(const TDesC8& aHeaderData, const TBool aXip) const |
|
1426 { |
|
1427 TUint minimumHeaderSize = aXip ? sizeof(TRomImageHeader) : sizeof(E32ImageHeaderV); |
|
1428 return (aHeaderData.Length() >= minimumHeaderSize); |
|
1429 } |
|
1430 |
|
1431 /** |
|
1432 Opens a file handle to aFileName using aFileHandle |
|
1433 @param aFileName file to open handle to |
|
1434 @param aFs file system to use to open the handle |
|
1435 @param aFileHandle file handle to open |
|
1436 |
|
1437 @leave one of the system wide error codes |
|
1438 */ |
|
1439 void CSecuritySvrSession::OpenFileHandleL(const TDesC& aFileName, RFs& aFs, RFile& aFileHandle) |
|
1440 { |
|
1441 TInt err = aFileHandle.Open(aFs, aFileName, EFileRead | EFileShareReadersOnly); |
|
1442 if (err != KErrNone) |
|
1443 { |
|
1444 // Could not open the file for reading |
|
1445 LOG_MSG("CSecuritySvrSession::OpenFileHandleL - Failed to open executable\n"); |
|
1446 |
|
1447 User::Leave(err); |
|
1448 } |
|
1449 } |
|
1450 |
|
1451 /** |
|
1452 Checks whether an executable has the debug bit set |
|
1453 |
|
1454 @param aHeaderData buffer containing the header of the executable |
|
1455 @param aXip indication of whether the executable is XIP or not |
|
1456 |
|
1457 @return ETrue if debug bit is set, EFalse otherwise |
|
1458 */ |
|
1459 TBool CSecuritySvrSession::IsDebugBitSet(const TDesC8& aHeaderData, const TBool aXip) |
|
1460 { |
|
1461 if(!CheckSufficientData(aHeaderData, aXip)) |
|
1462 { |
|
1463 return EFalse; |
|
1464 } |
|
1465 |
|
1466 if (aXip) |
|
1467 { |
|
1468 TRomImageHeader* hdr = (TRomImageHeader*)aHeaderData.Ptr(); |
|
1469 return (hdr->iFlags & KRomImageDebuggable); |
|
1470 } |
|
1471 else |
|
1472 { |
|
1473 // it is an epoc32 image |
|
1474 E32ImageHeaderV* hdr = (E32ImageHeaderV*)aHeaderData.Ptr(); |
|
1475 return (hdr->iFlags & KImageDebuggable); |
|
1476 } |
|
1477 } |
|
1478 |
|
1479 /** |
|
1480 Determines whether a particular executable is marked as 'debuggable' |
|
1481 |
|
1482 Notes: |
|
1483 This function is currently hard coded to understand the format of e32 and |
|
1484 TRomImage file headers. Ideally this will be replaced by a call to RLibrary::GetInfo |
|
1485 which can return the 'debuggable' information. Unfortunately, this call currently |
|
1486 does not provide the information for XIP executables :-( |
|
1487 |
|
1488 @leave KErrPermissionDenied if the debug bit is not set, or one of the other |
|
1489 system wide error codes |
|
1490 */ |
|
1491 void CSecuritySvrSession::IsDebuggableL(const TDesC& aFileName) |
|
1492 { |
|
1493 #ifndef IGNORE_DEBUGGABLE_BIT |
|
1494 |
|
1495 RFs fs; |
|
1496 User::LeaveIfError(fs.Connect()); |
|
1497 CleanupClosePushL(fs); |
|
1498 |
|
1499 RFile targetExe; |
|
1500 OpenFileHandleL(aFileName, fs, targetExe); |
|
1501 CleanupClosePushL(targetExe); |
|
1502 |
|
1503 // Read in the entire header |
|
1504 RBuf8 e32HdrBuf; |
|
1505 e32HdrBuf.CreateL(RLibrary::KRequiredImageHeaderSize); |
|
1506 e32HdrBuf.CleanupClosePushL(); |
|
1507 |
|
1508 // Read the entire header as far as possible |
|
1509 TInt err = targetExe.Read(e32HdrBuf); |
|
1510 if (err != KErrNone) |
|
1511 { |
|
1512 // Could not read the file |
|
1513 LOG_MSG("CSecuritySvrSession::IsDebuggableL - Failed to read executable\n"); |
|
1514 |
|
1515 User::Leave(err); |
|
1516 } |
|
1517 |
|
1518 if(!CheckSufficientData(e32HdrBuf, IsExecutableXipL(targetExe))) |
|
1519 { |
|
1520 User::Leave(KErrGeneral); |
|
1521 } |
|
1522 |
|
1523 if(! IsDebugBitSet(e32HdrBuf, IsExecutableXipL(targetExe))) |
|
1524 { |
|
1525 User::Leave(KErrPermissionDenied); |
|
1526 } |
|
1527 CleanupStack::PopAndDestroy(3, &fs); |
|
1528 |
|
1529 #else |
|
1530 LOG_MSG("CSecuritySvrSession::IsDebuggableL() Debuggable bit temporarily ignored!!!"); |
|
1531 #endif |
|
1532 } |
|
1533 |
|
1534 /** |
|
1535 Processes a detach request from a debug agent. Gets the target debug |
|
1536 processes' original FileName as an argument. The method sets completion |
|
1537 status of the aMessage argument to KErrNone if successfully detached and to |
|
1538 another of the system wide error codes if there were problems. |
|
1539 |
|
1540 @param aMessage contains: |
|
1541 * a buffer at offset 0 which contains the FileName |
|
1542 of the target debug process. |
|
1543 */ |
|
1544 void CSecuritySvrSession::DetachProcessL(const RMessage2& aMessage) |
|
1545 { |
|
1546 LOG_MSG( "CSecuritySvrSession::DetachProcessL()\n" ); |
|
1547 |
|
1548 TInt deslen = aMessage.GetDesLengthL(0); |
|
1549 // Passed data will be saved in this descriptor. |
|
1550 RBuf processName; |
|
1551 |
|
1552 // Max length set to the value of "deslen", but current length is zero |
|
1553 processName.CreateL(deslen); |
|
1554 |
|
1555 // Do the right cleanup if anything subsequently goes wrong |
|
1556 processName.CleanupClosePushL(); |
|
1557 |
|
1558 // Copy the client's descriptor data into our buffer. |
|
1559 aMessage.ReadL(0,processName); |
|
1560 |
|
1561 User::LeaveIfError(Server().DetachProcess(processName, iDebugAgentProcessId)); |
|
1562 |
|
1563 // Inform the kernel driver about the detachment, so that |
|
1564 // it can stop tracking per-agent data for the debugged process. |
|
1565 RBuf8 processName8; |
|
1566 |
|
1567 processName8.CreateL(deslen); |
|
1568 |
|
1569 processName8.CleanupClosePushL(); |
|
1570 |
|
1571 processName8.Copy(processName); |
|
1572 |
|
1573 // Remove the Asynchronous Object associated with this process |
|
1574 for(TInt i=0; i<iAsyncHandlers.Count(); i++) |
|
1575 { |
|
1576 if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0) |
|
1577 { |
|
1578 delete iAsyncHandlers[i]; |
|
1579 iAsyncHandlers.Remove(i); |
|
1580 |
|
1581 break; |
|
1582 } |
|
1583 } |
|
1584 |
|
1585 // Inform the driver that we are no longer attached to this process |
|
1586 User::LeaveIfError(Server().iKernelDriver.DetachProcess(processName8,iDebugAgentProcessId.Id())); |
|
1587 |
|
1588 CleanupStack::PopAndDestroy(&processName8); |
|
1589 CleanupStack::PopAndDestroy(&processName); |
|
1590 |
|
1591 aMessage.Complete(KErrNone); |
|
1592 } |
|
1593 |
|
1594 /** |
|
1595 Processes a DetachAll request from a debug agent. |
|
1596 The method sets completion status of the aMessage argument to |
|
1597 KErrNone if successfully detached and to |
|
1598 another of the system wide error codes if there were problems. |
|
1599 |
|
1600 @param aMessage contains: |
|
1601 * a buffer at offset 0 which contains the FileName |
|
1602 of the target debug process. |
|
1603 */ |
|
1604 void CSecuritySvrSession::DetachAllL(const RMessage2& aMessage) |
|
1605 { |
|
1606 LOG_MSG( "CSecuritySvrSession::DetachAllL()" ); |
|
1607 |
|
1608 User::LeaveIfError(Server().DetachProcess(_L("*"), iDebugAgentProcessId)); |
|
1609 |
|
1610 TBuf8<1> KStar8=_L8("*"); |
|
1611 |
|
1612 TBool found = EFalse; |
|
1613 |
|
1614 // Remove the Asynchronous Object associated with the AttachAll, not the rest |
|
1615 for(TInt i=0; i<iAsyncHandlers.Count(); i++) |
|
1616 { |
|
1617 if (iAsyncHandlers[i]->ProcessName().Compare(KStar8) == 0) |
|
1618 { |
|
1619 delete iAsyncHandlers[i]; |
|
1620 iAsyncHandlers.Remove(i); |
|
1621 User::LeaveIfError(Server().iKernelDriver.DetachProcess(KStar8,iDebugAgentProcessId.Id())); |
|
1622 found = ETrue; |
|
1623 break; |
|
1624 } |
|
1625 } |
|
1626 |
|
1627 if( !found ) |
|
1628 { |
|
1629 LOG_MSG2( "CSecuritySvrSession::DetachAllL() : Did not find the asynch handler for agent 0x%lx", |
|
1630 iDebugAgentProcessId.Id() ); |
|
1631 User::Leave(KErrNotFound); |
|
1632 } |
|
1633 |
|
1634 aMessage.Complete(KErrNone); |
|
1635 } |
|
1636 |
|
1637 /** |
|
1638 @param aMessage The RMessage2 object is expected to contain: |
|
1639 * aMessage.Int0() - TDes8 Containing the process name. |
|
1640 * aMessage.Int1() - Address of TPtr8 containing TEventInfo |
|
1641 |
|
1642 */ |
|
1643 void CSecuritySvrSession::GetEventL(const RMessage2& aMessage) |
|
1644 { |
|
1645 LOG_MSG( "CSecuritySvrSession::GetEventL()\n" ); |
|
1646 |
|
1647 // Local descriptor to contain target process name |
|
1648 TInt deslen = aMessage.GetDesLengthL(0); |
|
1649 |
|
1650 RBuf processName; |
|
1651 |
|
1652 processName.CreateL(deslen); |
|
1653 |
|
1654 processName.CleanupClosePushL(); |
|
1655 |
|
1656 // Read the target process name into processName |
|
1657 aMessage.ReadL(0,processName); |
|
1658 |
|
1659 // Check if debug agent is attached to process |
|
1660 if(!Server().CheckAttachedProcess(processName, aMessage, EFalse)) |
|
1661 { |
|
1662 LOG_MSG("CSecuritySvrSession::GetEventL() - Not attached to this process\n"); |
|
1663 |
|
1664 // Debug Agent is not attached at all to the requested process |
|
1665 User::Leave(KErrPermissionDenied); |
|
1666 } |
|
1667 |
|
1668 // Identify which process is being debugged, so that |
|
1669 // we can locate the appropriate active object handler. |
|
1670 RBuf8 processName8; |
|
1671 |
|
1672 processName8.CreateL(processName.Length()); |
|
1673 |
|
1674 processName8.CleanupClosePushL(); |
|
1675 |
|
1676 processName8.Copy(processName); |
|
1677 |
|
1678 // Find the Asynchronous Object associated with this process, |
|
1679 // as it is permissible to have an outstanding GetEvent call |
|
1680 // for each attached process. |
|
1681 TBool foundHandler = EFalse; |
|
1682 for(TInt i=0; i<iAsyncHandlers.Count(); i++) |
|
1683 { |
|
1684 if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0) |
|
1685 { |
|
1686 iAsyncHandlers[i]->GetEvent(aMessage); |
|
1687 foundHandler = ETrue; |
|
1688 break; |
|
1689 } |
|
1690 } |
|
1691 |
|
1692 if (foundHandler == EFalse) |
|
1693 { |
|
1694 // could not find an async handler object. Report the problem. |
|
1695 LOG_MSG("CSecuritySvrSessionL - Could not find a handler object\n"); |
|
1696 User::Leave(KErrNotFound); |
|
1697 } |
|
1698 |
|
1699 // Actually make the driver call, passing in the agent Id |
|
1700 // so that the driver knows which per-agent event queue |
|
1701 // to interrogate to retrieve the latest event. |
|
1702 CleanupStack::PopAndDestroy(&processName8); |
|
1703 CleanupStack::PopAndDestroy(&processName); |
|
1704 } |
|
1705 |
|
1706 /** |
|
1707 Cancels a pre-issued GetEvent call for a specific debugged process. |
|
1708 |
|
1709 @param aMessage.Int0() - TDes8 containing aProcessName |
|
1710 */ |
|
1711 void CSecuritySvrSession::CancelGetEventL(const RMessage2& aMessage) |
|
1712 { |
|
1713 LOG_MSG( "CSecuritySvrSession::CancelGetEventL()\n" ); |
|
1714 |
|
1715 // Local descriptor to contain target process name |
|
1716 TInt deslen = aMessage.GetDesLengthL(0); |
|
1717 |
|
1718 RBuf processName; |
|
1719 |
|
1720 processName.CreateL(deslen); |
|
1721 |
|
1722 processName.CleanupClosePushL(); |
|
1723 |
|
1724 // Read the target process name into processName |
|
1725 aMessage.ReadL(0,processName,0); |
|
1726 |
|
1727 // Debug Agent is not an active debugger. Check if the DA is passively attached |
|
1728 if(!Server().CheckAttachedProcess(processName, aMessage, EFalse)) |
|
1729 { |
|
1730 // Debug Agent is not attached at all to the requested process |
|
1731 User::Leave(KErrPermissionDenied); |
|
1732 } |
|
1733 |
|
1734 // Identify the appropriate active object associate |
|
1735 // with this process. |
|
1736 RBuf8 processName8; |
|
1737 |
|
1738 processName8.CreateL(processName.Length()); |
|
1739 |
|
1740 processName8.CleanupClosePushL(); |
|
1741 |
|
1742 processName8.Copy(processName); |
|
1743 |
|
1744 // Find the Asynchronous Object associated with this process |
|
1745 TBool foundHandler = EFalse; |
|
1746 for(TInt i=0; i<iAsyncHandlers.Count(); i++) |
|
1747 { |
|
1748 if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0) |
|
1749 { |
|
1750 |
|
1751 // Found the AO handler, so cancel the outstanding getevent call. |
|
1752 iAsyncHandlers[i]->Cancel(); |
|
1753 foundHandler = ETrue; |
|
1754 break; |
|
1755 } |
|
1756 } |
|
1757 |
|
1758 if(!foundHandler) |
|
1759 { |
|
1760 // We could not found a handler, so report the problem to the debug agent |
|
1761 User::Leave(KErrNotFound); |
|
1762 } |
|
1763 |
|
1764 //do cleanup |
|
1765 CleanupStack::PopAndDestroy(&processName8); |
|
1766 CleanupStack::PopAndDestroy(&processName); |
|
1767 |
|
1768 aMessage.Complete(KErrNone); |
|
1769 } |
|
1770 |
|
1771 /* |
|
1772 Purpose: Sets the required event action to be taken for a specific |
|
1773 process and event combination |
|
1774 |
|
1775 @param aMessage The RMessage2 object is expected to contain: |
|
1776 * aMessage.Int0() - TDes8 Containing the process name. |
|
1777 * aMessage.Int1() - TEventType |
|
1778 * aMessage.Int2() - TKernelEventAction |
|
1779 * |
|
1780 */ |
|
1781 void CSecuritySvrSession::SetEventActionL(const RMessage2& aMessage) |
|
1782 { |
|
1783 LOG_MSG( "CSecuritySvrSession::SetEventActionL()\n" ); |
|
1784 |
|
1785 // Local descriptor to contain target process name |
|
1786 TInt deslen = aMessage.GetDesLengthL(0); |
|
1787 |
|
1788 RBuf processName; |
|
1789 |
|
1790 processName.CreateL(deslen); |
|
1791 |
|
1792 processName.CleanupClosePushL(); |
|
1793 |
|
1794 // Read the target process name into processName |
|
1795 aMessage.ReadL(0,processName); |
|
1796 |
|
1797 //check that the agent has attached to the target process |
|
1798 if(!Server().CheckAttachedProcess(processName, aMessage, EFalse)) |
|
1799 { |
|
1800 // Debug Agent is not attached at all to the requested process |
|
1801 User::Leave(KErrPermissionDenied); |
|
1802 } |
|
1803 |
|
1804 // Extract and validate the arguments from aMessage |
|
1805 TUint32 event = aMessage.Int1(); |
|
1806 if (event >= EEventsLast) |
|
1807 { |
|
1808 // Supplied event Id was not recognised |
|
1809 User::Leave(KErrArgument); |
|
1810 } |
|
1811 |
|
1812 TUint32 action = aMessage.Int2(); |
|
1813 if(action >= EActionLast) |
|
1814 { |
|
1815 // Supplied event action was not recognised |
|
1816 User::Leave(KErrArgument); |
|
1817 } |
|
1818 |
|
1819 RBuf8 processName8; |
|
1820 |
|
1821 processName8.CreateL(processName.Length()); |
|
1822 |
|
1823 processName8.CleanupClosePushL(); |
|
1824 |
|
1825 processName8.Copy(processName); |
|
1826 |
|
1827 // Make the call to the device driver |
|
1828 TInt err = Server().iKernelDriver.SetEventAction(processName8, \ |
|
1829 (TEventType)event,\ |
|
1830 (TKernelEventAction)action,\ |
|
1831 iDebugAgentProcessId.Id()); |
|
1832 |
|
1833 User::LeaveIfError(err); |
|
1834 |
|
1835 CleanupStack::PopAndDestroy(&processName8); |
|
1836 CleanupStack::PopAndDestroy(&processName); |
|
1837 |
|
1838 aMessage.Complete(KErrNone); |
|
1839 } |
|
1840 |
|
1841 /** |
|
1842 Purpose: Single-step a thread for a specified number of instructions |
|
1843 |
|
1844 @param aMessage.Ptr0() - Thread Id of the thread to be stepped |
|
1845 @param aMessage.Int1() - Number of instructions to step. |
|
1846 |
|
1847 @leave one of the system wide error codes |
|
1848 |
|
1849 */ |
|
1850 void CSecuritySvrSession::StepL(const RMessage2& aMessage) |
|
1851 { |
|
1852 LOG_MSG( "CSecuritySvrSession::StepL()\n" ); |
|
1853 |
|
1854 const TThreadId threadId = ReadTThreadIdL(aMessage, 0); |
|
1855 const TInt32 numSteps = aMessage.Int1(); |
|
1856 |
|
1857 CheckAttachedL(threadId, aMessage, EFalse); |
|
1858 |
|
1859 User::LeaveIfError(Server().iKernelDriver.Step( threadId, numSteps )); |
|
1860 |
|
1861 aMessage.Complete(KErrNone); |
|
1862 } |
|
1863 |
|
1864 /** |
|
1865 * This checks whether or not the agent is permitted access to the flash partition |
|
1866 * @return KErrNone if allowed, otherwise one of the system wide error codes |
|
1867 * @leave one of the system wide error codes |
|
1868 */ |
|
1869 TInt CSecuritySvrSession::CheckFlashAccessPermissionL(const RThread& aClientThread) |
|
1870 { |
|
1871 // Read the OEM Debug token capabilities (if any) |
|
1872 GetDebugAgentOEMTokenCapsL(); |
|
1873 |
|
1874 if(Server().OEMTokenPermitsFlashAccessL((iOEMDebugCapabilities))) |
|
1875 { |
|
1876 return KErrNone; |
|
1877 } |
|
1878 |
|
1879 return KErrPermissionDenied; |
|
1880 } |
|
1881 |
|
1882 /** |
|
1883 Purpose: Read the crash log from the crash flash partition |
|
1884 @param aMessage.Int0() - Position to read from. |
|
1885 @param aMessage.Ptr1() - Buffer to hold the data retrieved |
|
1886 @param aMessage.Int2() - Size of the data to read. |
|
1887 |
|
1888 @leave one of the system wide error codes |
|
1889 */ |
|
1890 void CSecuritySvrSession::ReadCrashLogL (const RMessage2& aMessage) |
|
1891 { |
|
1892 //get the debug agent's thread and push handle onto clean up stack |
|
1893 RThread clientThread; |
|
1894 User::LeaveIfError(aMessage.Client(clientThread)); |
|
1895 CleanupClosePushL(clientThread); |
|
1896 |
|
1897 TInt err = CheckFlashAccessPermissionL(clientThread); |
|
1898 |
|
1899 CleanupStack::PopAndDestroy(&clientThread); |
|
1900 |
|
1901 if(KErrNone != err) |
|
1902 { |
|
1903 LOG_MSG2( "CSecuritySvrSession::ReadCrashLogL() Access Not Granted - [%d]\n", err ); |
|
1904 aMessage.Complete(err); |
|
1905 return; |
|
1906 } |
|
1907 |
|
1908 //Check whether drive connected. |
|
1909 if(!iCrashConnected) |
|
1910 ConnectCrashPartitionL(); |
|
1911 |
|
1912 TInt readPosition = aMessage.Int0(); //read position |
|
1913 |
|
1914 TInt readSize = aMessage.Int2(); //read size |
|
1915 |
|
1916 RBuf8 readBuf; |
|
1917 readBuf.CreateL(readSize); |
|
1918 readBuf.CleanupClosePushL(); |
|
1919 |
|
1920 err = iLocalDrive.Read (readPosition, readSize, readBuf); |
|
1921 |
|
1922 //write the list data back |
|
1923 aMessage.WriteL (1, readBuf); |
|
1924 |
|
1925 CleanupStack::PopAndDestroy (&readBuf); |
|
1926 |
|
1927 //Complete message |
|
1928 aMessage.Complete(err); |
|
1929 } |
|
1930 /** |
|
1931 Purpose: Function to write the crash config to the crash flash partition |
|
1932 |
|
1933 @param aMessage.Int0() - write position in bytes from start position in flash partition. |
|
1934 @param aMessage.Ptr1() - Buffer containing the data to be written onto the flash. |
|
1935 The size could be 0 if only flash partition size is needed. |
|
1936 @param aMessage.Int2() - returns the size of the flash partition. |
|
1937 |
|
1938 @leave one of the system wide error codes |
|
1939 */ |
|
1940 void CSecuritySvrSession::WriteCrashConfigL(const RMessage2& aMessage) |
|
1941 { |
|
1942 LOG_MSG( "CSecuritySvrSession::WriteCrashConfigL()\n" ); |
|
1943 |
|
1944 //get the debug agent's thread and push handle onto clean up stack |
|
1945 RThread clientThread; |
|
1946 User::LeaveIfError(aMessage.Client(clientThread)); |
|
1947 CleanupClosePushL(clientThread); |
|
1948 |
|
1949 TInt err = CheckFlashAccessPermissionL(clientThread); |
|
1950 |
|
1951 CleanupStack::PopAndDestroy(&clientThread); |
|
1952 |
|
1953 if(KErrNone != err) |
|
1954 { |
|
1955 LOG_MSG2( "CSecuritySvrSession::WriteCrashConfigL() Access Not Granted - [%d]\n", err ); |
|
1956 aMessage.Complete(err); |
|
1957 return; |
|
1958 } |
|
1959 |
|
1960 //Check whether drive connected. |
|
1961 if(!iCrashConnected) |
|
1962 ConnectCrashPartitionL(); |
|
1963 |
|
1964 // Get the length of the buffer |
|
1965 TInt deslen = aMessage.GetDesLengthL(1); |
|
1966 |
|
1967 RBuf8 dataBuf; |
|
1968 dataBuf.CreateL(deslen); |
|
1969 dataBuf.CleanupClosePushL(); |
|
1970 |
|
1971 // data to be written to flash |
|
1972 aMessage.ReadL(1,dataBuf); |
|
1973 |
|
1974 TUint32 position = aMessage.Int0(); //position to start from |
|
1975 |
|
1976 err = iLocalDrive.Write(position,(const TDesC8&)dataBuf); |
|
1977 |
|
1978 TPtr8 dataSize((TUint8*)&deslen,4, 4); |
|
1979 |
|
1980 //write the size of the data written back |
|
1981 aMessage.WriteL(2,dataSize); |
|
1982 |
|
1983 //destroy buffer |
|
1984 CleanupStack::PopAndDestroy(&dataBuf); |
|
1985 |
|
1986 aMessage.Complete(err); |
|
1987 } |
|
1988 /** |
|
1989 Purpose: Method to erase the crash flash block |
|
1990 |
|
1991 @param aMessage.Int0() - write position in bytes from start position in flash partition. |
|
1992 @param aMessage.Int2() - Number of blocks to erase. |
|
1993 |
|
1994 @leave one of the system wide error codes |
|
1995 */ |
|
1996 |
|
1997 void CSecuritySvrSession::EraseCrashLogL(const RMessage2& aMessage) |
|
1998 { |
|
1999 LOG_MSG( "CSecuritySvrSession::EraseCrashLogL()\n" ); |
|
2000 |
|
2001 //get the debug agent's thread and push handle onto clean up stack |
|
2002 RThread clientThread; |
|
2003 User::LeaveIfError(aMessage.Client(clientThread)); |
|
2004 CleanupClosePushL(clientThread); |
|
2005 |
|
2006 TInt err = CheckFlashAccessPermissionL(clientThread); |
|
2007 |
|
2008 CleanupStack::PopAndDestroy(&clientThread); |
|
2009 |
|
2010 if(KErrNone != err) |
|
2011 { |
|
2012 LOG_MSG2( "CSecuritySvrSession::EraseCrashLogL() Access Not Granted - [%d]\n", err ); |
|
2013 aMessage.Complete(err); |
|
2014 return; |
|
2015 } |
|
2016 |
|
2017 //Check whether drive connected. |
|
2018 if(!iCrashConnected) |
|
2019 ConnectCrashPartitionL(); |
|
2020 |
|
2021 TInt64 position = aMessage.Int0(); |
|
2022 TInt size = aMessage.Int1(); |
|
2023 |
|
2024 //Format drive |
|
2025 err = iLocalDrive.Format(position,size*iCaps.iEraseBlockSize); |
|
2026 |
|
2027 aMessage.Complete(err); |
|
2028 } |
|
2029 |
|
2030 /** |
|
2031 Purpose: Method to erase the entire crash flash block |
|
2032 @leave one of the system wide error codes |
|
2033 */ |
|
2034 |
|
2035 void CSecuritySvrSession::EraseEntireCrashLogL(const RMessage2& aMessage) |
|
2036 { |
|
2037 LOG_MSG( "CSecuritySvrSession::EraseEntireCrashLogL()\n" ); |
|
2038 |
|
2039 //get the debug agent's thread and push handle onto clean up stack |
|
2040 RThread clientThread; |
|
2041 User::LeaveIfError(aMessage.Client(clientThread)); |
|
2042 CleanupClosePushL(clientThread); |
|
2043 |
|
2044 TInt err = CheckFlashAccessPermissionL(clientThread); |
|
2045 |
|
2046 CleanupStack::PopAndDestroy(&clientThread); |
|
2047 |
|
2048 if(KErrNone != err) |
|
2049 { |
|
2050 LOG_MSG2( "CSecuritySvrSession::EraseEntireCrashLogL() Access Not Granted - [%d]\n", err ); |
|
2051 aMessage.Complete(err); |
|
2052 return; |
|
2053 } |
|
2054 |
|
2055 //Check whether drive connected. |
|
2056 if(!iCrashConnected) |
|
2057 ConnectCrashPartitionL(); |
|
2058 |
|
2059 TUint numberBlocks = iCaps.iSize /iCaps.iEraseBlockSize; |
|
2060 |
|
2061 //Format drive |
|
2062 for(TInt i = 0; i < numberBlocks; i++) |
|
2063 { |
|
2064 err = iLocalDrive.Format(i*iCaps.iEraseBlockSize,iCaps.iEraseBlockSize); |
|
2065 if(KErrNone != err) |
|
2066 { |
|
2067 RDebug::Printf("err = %d", err); |
|
2068 aMessage.Complete(err); |
|
2069 return; |
|
2070 } |
|
2071 } |
|
2072 |
|
2073 |
|
2074 aMessage.Complete(err); |
|
2075 } |
|
2076 |
|
2077 |
|
2078 /** |
|
2079 Purpose: Kill a specified process |
|
2080 |
|
2081 @param aMessage.Ptr0() - Process Id of the thread to be stepped |
|
2082 @param aMessage.Int1() - Reason code to supply when killing the process. |
|
2083 |
|
2084 @leave one of the system wide error codes |
|
2085 |
|
2086 */ |
|
2087 void CSecuritySvrSession::KillProcessL(const RMessage2& aMessage) |
|
2088 { |
|
2089 LOG_MSG( "CSecuritySvrSession::KillProcessL()\n" ); |
|
2090 |
|
2091 const TProcessId processId = ReadTProcessIdL(aMessage, 0); |
|
2092 const TInt32 reason = aMessage.Int1(); |
|
2093 |
|
2094 CheckAttachedL(processId, aMessage, EFalse); |
|
2095 |
|
2096 User::LeaveIfError(Server().iKernelDriver.KillProcess( processId, reason )); |
|
2097 |
|
2098 aMessage.Complete(KErrNone); |
|
2099 } |
|
2100 |
|
2101 /** Gets the secure id of aFileName |
|
2102 @param aFileName file name of executable to get SID for |
|
2103 @param aSecureId on return will contain the SID of aFileName |
|
2104 |
|
2105 @leave one of the system wide error codes |
|
2106 */ |
|
2107 void CSecuritySvrSession::GetSecureIdL(const TDesC& aFileName, TUid& aSecureId) |
|
2108 { |
|
2109 RFs fs; |
|
2110 User::LeaveIfError(fs.Connect()); |
|
2111 CleanupClosePushL(fs); |
|
2112 |
|
2113 RFile targetExe; |
|
2114 OpenFileHandleL(aFileName, fs, targetExe); |
|
2115 CleanupClosePushL(targetExe); |
|
2116 |
|
2117 // Read in the entire header |
|
2118 RBuf8 e32HdrBuf; |
|
2119 e32HdrBuf.CreateL(RLibrary::KRequiredImageHeaderSize); |
|
2120 e32HdrBuf.CleanupClosePushL(); |
|
2121 |
|
2122 // Read the entire header as far as possible |
|
2123 TInt err = targetExe.Read(e32HdrBuf); |
|
2124 if (err != KErrNone) |
|
2125 { |
|
2126 // Could not read the file |
|
2127 LOG_MSG("CSecuritySvrSession::GetSecureIdL - Failed to read executable\n"); |
|
2128 |
|
2129 User::Leave(err); |
|
2130 } |
|
2131 |
|
2132 if(!CheckSufficientData(e32HdrBuf, IsExecutableXipL(targetExe))) |
|
2133 { |
|
2134 User::Leave(KErrGeneral); |
|
2135 } |
|
2136 |
|
2137 aSecureId = GetSecureIdL(e32HdrBuf, IsExecutableXipL(targetExe)); |
|
2138 |
|
2139 CleanupStack::PopAndDestroy(3, &fs); |
|
2140 } |
|
2141 |
|
2142 /** Get the secure id from aHeaderData |
|
2143 @param aHeaderData an executable's header data to read SID from |
|
2144 @param aXip indication of whether the header data is from an XIP file |
|
2145 |
|
2146 @return secure ID from aHeaderData |
|
2147 */ |
|
2148 TUid CSecuritySvrSession::GetSecureIdL(const TDesC8& aHeaderData, TBool aXip) |
|
2149 { |
|
2150 if(!CheckSufficientData(aHeaderData, aXip)) |
|
2151 { |
|
2152 User::Leave(KErrGeneral); |
|
2153 } |
|
2154 |
|
2155 if (aXip) |
|
2156 { |
|
2157 TRomImageHeader* hdr = (TRomImageHeader*)aHeaderData.Ptr(); |
|
2158 return TUid::Uid(hdr->iS.iSecureId); |
|
2159 } |
|
2160 else |
|
2161 { |
|
2162 // it is an epoc32 image |
|
2163 E32ImageHeaderV* hdr = (E32ImageHeaderV*)aHeaderData.Ptr(); |
|
2164 return TUid::Uid(hdr->iS.iSecureId); |
|
2165 } |
|
2166 } |
|
2167 |
|
2168 /** |
|
2169 @param aMessage contains: |
|
2170 * aMessage.Ptr0() a TListDetails object |
|
2171 * aMessage.Ptr1() a client supplied TDes8 for the driver to return data in |
|
2172 * aMessage.Ptr2() a TUint32 for the driver to return the size of the requested listing's data in |
|
2173 |
|
2174 @leave KErrTooBig if the buffer passed as argument 1 of aMessage is too |
|
2175 small to contain the requested data, |
|
2176 KErrNoMemory if a temporary buffer could not be allocated, |
|
2177 or one of the other system wide error codes |
|
2178 */ |
|
2179 void CSecuritySvrSession::GetListL(const RMessage2& aMessage) |
|
2180 { |
|
2181 LOG_MSG("CSecuritySvrSession::GetListL()"); |
|
2182 |
|
2183 // buffer to write list data into before copying back to agent |
|
2184 RBuf8 listDetailsBuf; |
|
2185 |
|
2186 //allocate buffer |
|
2187 listDetailsBuf.CreateL(sizeof(TListDetails)); |
|
2188 |
|
2189 // Do the right cleanup if anything subsequently goes wrong |
|
2190 listDetailsBuf.CleanupClosePushL(); |
|
2191 |
|
2192 //read the data from the client thread |
|
2193 aMessage.ReadL(0, listDetailsBuf); |
|
2194 TListDetails* listDetails = (TListDetails*)listDetailsBuf.Ptr(); |
|
2195 |
|
2196 //get the type of list requested |
|
2197 TListId type = (TListId)aMessage.Int0(); |
|
2198 |
|
2199 //create a buffer to store the data in |
|
2200 RBuf8 buffer; |
|
2201 buffer.CreateL(aMessage.GetDesMaxLength(1)); |
|
2202 buffer.CleanupClosePushL(); |
|
2203 |
|
2204 //create a temporary variable to potentially store data length in |
|
2205 TUint32 size = 0; |
|
2206 |
|
2207 TInt err = KErrNone; |
|
2208 |
|
2209 // the executables list is generated in the DSS rather than in the driver |
|
2210 // so is treated separately |
|
2211 if(listDetails->iListId == EExecutables) |
|
2212 { |
|
2213 if(listDetails->iListScope != EScopeGlobal) |
|
2214 { |
|
2215 User::Leave(KErrArgument); |
|
2216 } |
|
2217 if(listDetails->iTargetId != 0) |
|
2218 { |
|
2219 User::Leave(KErrArgument); |
|
2220 } |
|
2221 err = GetExecutablesListL(buffer, size); |
|
2222 } |
|
2223 else |
|
2224 { |
|
2225 err = Server().iKernelDriver.GetList(listDetails->iListId, listDetails->iListScope, listDetails->iTargetId, iDebugAgentProcessId, buffer, size); |
|
2226 } |
|
2227 |
|
2228 if(err == KErrNone) |
|
2229 { |
|
2230 //write the list data back |
|
2231 aMessage.WriteL(1, buffer); |
|
2232 } |
|
2233 |
|
2234 TPtr8 sizePtr((TUint8*)&size, sizeof(TUint32), sizeof(TUint32)); |
|
2235 //write size back to agent |
|
2236 aMessage.WriteL(2, sizePtr); |
|
2237 |
|
2238 CleanupStack::PopAndDestroy(&buffer); |
|
2239 CleanupStack::PopAndDestroy(&listDetailsBuf); |
|
2240 |
|
2241 aMessage.Complete(err); |
|
2242 } |
|
2243 |
|
2244 /** |
|
2245 Gets the executables list and returns it in aBuffer if it's big enough |
|
2246 |
|
2247 @param aBuffer caller supplied buffer to write data into |
|
2248 @param aSize on return contains the size of the data in the buffer, or the |
|
2249 size that the buffer would need to be to contain the data |
|
2250 |
|
2251 @return KErrNone on success, or KErrTooBig if the requested data will not fit in aBuffer |
|
2252 |
|
2253 @leave one of the system wide error codes |
|
2254 */ |
|
2255 TInt CSecuritySvrSession::GetExecutablesListL(TDes8& aBuffer, TUint32& aSize) const |
|
2256 { |
|
2257 LOG_MSG("CSecuritySvrSession::GetExecutablesList()"); |
|
2258 |
|
2259 //initialise values and connect to file system |
|
2260 aSize = 0; |
|
2261 aBuffer.SetLength(0); |
|
2262 RFs fs; |
|
2263 User::LeaveIfError(fs.Connect()); |
|
2264 CleanupClosePushL(fs); |
|
2265 |
|
2266 // uids corresponding to executable image |
|
2267 TUidType uids(KExecutableImageUid, KNullUid, KNullUid); |
|
2268 |
|
2269 //create a string containing the directory name. The drive letter is represented |
|
2270 //by X but will be replaced by the appropriate drive letter for each drive |
|
2271 _LIT(KColonSysBin,":\\sys\\bin\\"); |
|
2272 |
|
2273 //create a modifiable copy of KColonSysBin, preceeded by an empty space for the drive letter |
|
2274 RBuf dirName; |
|
2275 dirName.CreateL(1 + KColonSysBin().Length()); |
|
2276 dirName.CleanupClosePushL(); |
|
2277 |
|
2278 //set the length to 1 (to later fill with the drive letter) and then append KColonSysBin |
|
2279 dirName.SetLength(1); |
|
2280 dirName.Append(KColonSysBin()); |
|
2281 |
|
2282 //get the list of valid drives for the device |
|
2283 TDriveList driveList; |
|
2284 User::LeaveIfError(fs.DriveList(driveList)); |
|
2285 |
|
2286 //check each valid sys/bin directory for executables |
|
2287 for(TInt i=0; i<KMaxDrives; i++) |
|
2288 { |
|
2289 //if the drive is not valid then skip this drive |
|
2290 if(!driveList[i]) |
|
2291 { |
|
2292 //skip processing this drive |
|
2293 continue; |
|
2294 } |
|
2295 |
|
2296 //get the drive letter and insert it as the drive letter for dirName |
|
2297 TChar driveLetter; |
|
2298 User::LeaveIfError(fs.DriveToChar(i, driveLetter)); |
|
2299 dirName[0] = (TUint)driveLetter; |
|
2300 |
|
2301 //get a list of the exes in this drive's sys/bin directory |
|
2302 CDir* localDir = NULL; |
|
2303 TInt err = fs.GetDir(dirName, uids, ESortByName, localDir); |
|
2304 if(KErrNoMemory == err) |
|
2305 { |
|
2306 User::Leave(err); |
|
2307 } |
|
2308 if(!localDir) |
|
2309 { |
|
2310 //skip processing this drive |
|
2311 continue; |
|
2312 } |
|
2313 |
|
2314 //push onto cleanup stack in case we leave |
|
2315 CleanupStack::PushL(localDir); |
|
2316 |
|
2317 //iterate through the files |
|
2318 for(TInt j=0; j<localDir->Count(); j++) |
|
2319 { |
|
2320 //will store x:\sys\bin\<file-name> type string |
|
2321 RBuf fullPathName; |
|
2322 |
|
2323 TUint16 nameLength = dirName.Length() + (*localDir)[j].iName.Length(); |
|
2324 fullPathName.CreateL(nameLength); |
|
2325 fullPathName.CleanupClosePushL(); |
|
2326 fullPathName.Copy(dirName); |
|
2327 fullPathName.Append((*localDir)[j].iName); |
|
2328 |
|
2329 //add the data to the buffer |
|
2330 AppendExecutableData(aBuffer, aSize, fullPathName); |
|
2331 |
|
2332 //do cleanup |
|
2333 CleanupStack::PopAndDestroy(&fullPathName); |
|
2334 } |
|
2335 |
|
2336 //do cleanup |
|
2337 CleanupStack::PopAndDestroy(localDir); |
|
2338 } |
|
2339 |
|
2340 //do cleanup |
|
2341 CleanupStack::PopAndDestroy(2, &fs); |
|
2342 |
|
2343 //return appropriate value as to whether the kernel's data was too big |
|
2344 return (aSize <= aBuffer.MaxLength()) ? KErrNone : KErrTooBig; |
|
2345 } |
|
2346 |
|
2347 |
|
2348 /** |
|
2349 Append data to aBuffer and update size of aSize if the data will fit. If it will |
|
2350 not fit then just puts the nee size in aSize. |
|
2351 |
|
2352 @param aBuffer buffer to append the data to |
|
2353 @param aSize on return contains the new size of the buffer if the data could be |
|
2354 appended, otherwise aSize is updated to reflect the size the buffer would have if |
|
2355 the data had fitted. |
|
2356 @param aEntryName file name of the entry to add to the buffer |
|
2357 */ |
|
2358 void CSecuritySvrSession::AppendExecutableData(TDes8& aBuffer, TUint32& aSize, const TDesC& aEntryName) const |
|
2359 { |
|
2360 //update aSize to include the size of the data for this entry |
|
2361 aSize = Align4(aSize + sizeof(TExecutablesListEntry) + (2*aEntryName.Length()) - sizeof(TUint16)); |
|
2362 |
|
2363 //if the data will fit, and we haven't already stopped putting data in, then append the data, |
|
2364 //if we've stopped putting data in then aSize will be bigger than aBuffer.MaxLength() |
|
2365 if(aSize <= aBuffer.MaxLength()) |
|
2366 { |
|
2367 TExecutablesListEntry& entry = *(TExecutablesListEntry*)(aBuffer.Ptr() + aBuffer.Length()); |
|
2368 //check whether an agent has registered to actively debug fullPathName |
|
2369 TBool activelyDebugged = IsDebugged(aEntryName, EFalse); |
|
2370 entry.iIsActivelyDebugged = activelyDebugged ? 1 : 0; |
|
2371 |
|
2372 //check whether any agents have registered to passively debug fullPathName |
|
2373 TBool passivelyDebugged = IsDebugged(aEntryName, ETrue); |
|
2374 entry.iIsPassivelyDebugged = passivelyDebugged ? 1 : 0; |
|
2375 |
|
2376 entry.iNameLength = aEntryName.Length(); |
|
2377 TPtr name(&(entry.iName[0]), aEntryName.Length(), aEntryName.Length()); |
|
2378 name = aEntryName; |
|
2379 //pad the buffer to a four byte boundary |
|
2380 aBuffer.SetLength(aSize); |
|
2381 } |
|
2382 } |
|
2383 /** |
|
2384 Helper function |
|
2385 |
|
2386 Write data back to the thread that owns aMessage |
|
2387 |
|
2388 @param aMessage the message which is passed between processes |
|
2389 @param aIndex the message slot which the data will be passed back in |
|
2390 @param aPtr pointer to data in this thread to be written into aMessage |
|
2391 @param aPtrSize size in bytes of the data to be written |
|
2392 |
|
2393 @leave one of the system wide error codes |
|
2394 */ |
|
2395 void CSecuritySvrSession::WriteDataL(const RMessage2& aMessage, const TInt aIndex, const TAny* aPtr, const TUint32 aPtrSize) const |
|
2396 { |
|
2397 TPtr8 dataPtr((TUint8*)aPtr, aPtrSize, aPtrSize); |
|
2398 |
|
2399 aMessage.WriteL(aIndex, dataPtr); |
|
2400 } |
|
2401 |
|
2402 /** |
|
2403 Helper function. |
|
2404 |
|
2405 Checks whether the debug agent (the owner of the aMessage) is attached to the |
|
2406 thread with thread id of aThreadId. |
|
2407 |
|
2408 @param aThreadId thread ID of target debug thread |
|
2409 @param aMessage message owned by the debug agent |
|
2410 @param aPassive indicates whether to check if attached passively or actively |
|
2411 |
|
2412 @leave KErrPermissionDenied if the agent is not attached to the process, |
|
2413 KErrNoMemory if the security server could not be accessed |
|
2414 */ |
|
2415 void CSecuritySvrSession::CheckAttachedL(const TThreadId aThreadId, const RMessage2& aMessage, const TBool aPassive) const |
|
2416 { |
|
2417 //check that the agent has attached to the target process |
|
2418 if(! Server().CheckAttached(aThreadId, aMessage, aPassive)) |
|
2419 { |
|
2420 LOG_MSG("CSecuritySvrSession::CheckAttachedL() failed"); |
|
2421 User::Leave(KErrPermissionDenied); |
|
2422 } |
|
2423 } |
|
2424 |
|
2425 /** |
|
2426 Helper function. |
|
2427 |
|
2428 Checks whether the debug agent (the owner of the aMessage) is attached to the |
|
2429 process with process id of aProcessId. |
|
2430 |
|
2431 @param aProcessId process ID of target debug thread |
|
2432 @param aMessage message owned by the debug agent |
|
2433 @param aPassive indicates whether to check if attached passively or actively |
|
2434 |
|
2435 @leave KErrPermissionDenied if the agent is not attached to the process, |
|
2436 KErrNoMemory if the security server could not be accessed |
|
2437 */ |
|
2438 void CSecuritySvrSession::CheckAttachedL(const TProcessId aProcessId, const RMessage2& aMessage, const TBool aPassive) const |
|
2439 { |
|
2440 |
|
2441 //check that the agent has attached to the target process |
|
2442 if(! Server().CheckAttached(aProcessId, aMessage, aPassive)) |
|
2443 { |
|
2444 LOG_MSG("CSecuritySvrSession::CheckAttachedL() (process) failed"); |
|
2445 User::Leave(KErrPermissionDenied); |
|
2446 } |
|
2447 } |
|
2448 |
|
2449 /** |
|
2450 Check whether the debug agent is permitted to attach to the target process. |
|
2451 Note that this function does not actually attach the agent to the process, it |
|
2452 simply tests whether an attach call would potentially be successful. |
|
2453 |
|
2454 Currently this method returns ETrue in all cases but will be updated once |
|
2455 the security checking framework is in place. |
|
2456 |
|
2457 @param aDebugAgentProcessId process id of the debug agent |
|
2458 @param aTargetProcessName original file name of the target process |
|
2459 |
|
2460 @return ETrue if the debug agent would be allowed to attch to the target process, |
|
2461 EFalse otherwise |
|
2462 */ |
|
2463 TBool CSecuritySvrSession::PermitDebugL(const TProcessId aDebugAgentProcessId, const TDesC& aTargetProcessName) const |
|
2464 { |
|
2465 return ETrue; |
|
2466 } |
|
2467 |
|
2468 /** |
|
2469 Helper function |
|
2470 |
|
2471 Validates that the memory info passed in meets the debug driver's requirements |
|
2472 |
|
2473 @param aMemoryInfo memory info passed in from client |
|
2474 |
|
2475 @leave KErrArgument if: |
|
2476 * size is zero |
|
2477 * size is greater than the max block size |
|
2478 * size + address > 0xffffffff |
|
2479 * address is not access size aligned |
|
2480 * size is not a multiple of the access size |
|
2481 KErrNotSupported if: |
|
2482 * iAccess is not TAccess::EAccess32 |
|
2483 * iEndianess is not TEndianess::EEndLE8 |
|
2484 KErrUnknown if: |
|
2485 * the max memory block size cannot be determined |
|
2486 or one of the other system wide error codes |
|
2487 */ |
|
2488 void CSecuritySvrSession::ValidateMemoryInfoL(const TThreadId aThreadId, const TMemoryInfo &aMemoryInfo, const TBool aReadOperation) |
|
2489 { |
|
2490 //check size is not 0 |
|
2491 if(aMemoryInfo.iSize == 0) |
|
2492 User::Leave(KErrArgument); |
|
2493 |
|
2494 //get the max block size supported |
|
2495 TUint32 maxSize = 0; |
|
2496 User::LeaveIfError(Server().iKernelDriver.GetMemoryOperationMaxBlockSize(maxSize)); |
|
2497 |
|
2498 //check that the block size given is less than the max block size |
|
2499 if(aMemoryInfo.iSize > maxSize) |
|
2500 User::Leave(KErrArgument); |
|
2501 |
|
2502 //must ensure that address + size <= 0xffffffff as will attempt to |
|
2503 //read past 0xffffffff, which wouldn't be good |
|
2504 TUint32 maxAddress = (~aMemoryInfo.iSize) + 1; |
|
2505 if(aMemoryInfo.iAddress > maxAddress) |
|
2506 User::Leave(KErrArgument); |
|
2507 |
|
2508 //check that arguments are supported |
|
2509 if(aMemoryInfo.iAccess != EAccess32) |
|
2510 User::Leave(KErrNotSupported); |
|
2511 |
|
2512 if(aMemoryInfo.iEndianess != EEndLE8) |
|
2513 User::Leave(KErrNotSupported); |
|
2514 |
|
2515 //check that address is multiple of access size |
|
2516 TInt addressIndicator = aMemoryInfo.iAddress % aMemoryInfo.iAccess; |
|
2517 if(addressIndicator != 0) |
|
2518 { |
|
2519 User::Leave(KErrArgument); |
|
2520 } |
|
2521 |
|
2522 //check that size is multiple of access size |
|
2523 TInt sizeIndicator = aMemoryInfo.iSize % aMemoryInfo.iAccess; |
|
2524 if(sizeIndicator != 0) |
|
2525 User::Leave(KErrArgument); |
|
2526 } |
|
2527 |
|
2528 /** |
|
2529 Helper function |
|
2530 |
|
2531 Validates that the three buffers relating to reading register data are of |
|
2532 appropriate sizes, and calculates the number of registers being requested. |
|
2533 |
|
2534 @param aMessage message which in offsets 1, 2 and 3 contains descriptors |
|
2535 @param aNumberOfRegisters if the function returns with KErrNone this will |
|
2536 contain the number of registers being requested, guaranteed to be non-zero |
|
2537 |
|
2538 @leave KErrArgument if descriptors do not represent the same number of |
|
2539 registers, if any of the descriptors have max length of 0, if any of |
|
2540 the descriptors have max lengths which are not multiples of their data |
|
2541 type's size or if any of the descriptors have max lengths greater than |
|
2542 the max block size for memory operations |
|
2543 or one of the other system wide error codes if there were problems |
|
2544 in getting the descriptors' lengths. |
|
2545 */ |
|
2546 void CSecuritySvrSession::ValidateRegisterBuffersL(const RMessage2& aMessage, TUint32& aNumberOfRegisters) |
|
2547 { |
|
2548 //get lengths of buffers, if error occurs returned value will be less then zero |
|
2549 TInt idsBufferLength = aMessage.GetDesMaxLength(1); |
|
2550 if(idsBufferLength < 0) |
|
2551 { |
|
2552 User::Leave(idsBufferLength); |
|
2553 } |
|
2554 TInt valuesBufferLength = aMessage.GetDesMaxLength(2); |
|
2555 if(valuesBufferLength < 0) |
|
2556 { |
|
2557 User::Leave(valuesBufferLength); |
|
2558 } |
|
2559 TInt flagsBufferLength = aMessage.GetDesMaxLength(3); |
|
2560 if(flagsBufferLength < 0) |
|
2561 { |
|
2562 User::Leave(flagsBufferLength); |
|
2563 } |
|
2564 |
|
2565 //get the max block size supported |
|
2566 TUint32 maxSize = 0; |
|
2567 User::LeaveIfError(Server().iKernelDriver.GetMemoryOperationMaxBlockSize(maxSize)); |
|
2568 |
|
2569 //check none of the descriptors have size greater than the max block size |
|
2570 if((idsBufferLength > maxSize) || (valuesBufferLength > maxSize) || (flagsBufferLength > maxSize)) |
|
2571 User::Leave(KErrArgument); |
|
2572 |
|
2573 //get sizes of the three types of data the buffers represent arrays of |
|
2574 //and validate that the buffer lengths are multiples of the data sizes |
|
2575 TUint idSize = sizeof(TRegisterInfo); |
|
2576 if(idsBufferLength % idSize != 0) |
|
2577 User::Leave(KErrArgument); |
|
2578 |
|
2579 TUint flagSize = sizeof(TUint8); |
|
2580 if(flagsBufferLength % flagSize != 0) |
|
2581 User::Leave(KErrArgument); |
|
2582 |
|
2583 //perform check on id buffer length |
|
2584 if(idsBufferLength == 0) |
|
2585 User::Leave(KErrArgument); |
|
2586 |
|
2587 //calculate number of registers being requested |
|
2588 aNumberOfRegisters = idsBufferLength / idSize; |
|
2589 |
|
2590 //check flags buffer is of appropriate size |
|
2591 if(flagsBufferLength != (aNumberOfRegisters * flagSize)) |
|
2592 User::Leave(KErrArgument); |
|
2593 } |
|
2594 |
|
2595 /** |
|
2596 Establish whether any agents have registered to debug the specified aFileName |
|
2597 |
|
2598 @param aFileName originating file name of the target process |
|
2599 @param aPassive indicates whether to check if there has been active attachment, |
|
2600 or passive attachment. |
|
2601 |
|
2602 @return ETrue if aFileName is being debugged, EFalse otherwise |
|
2603 |
|
2604 */ |
|
2605 TBool CSecuritySvrSession::IsDebugged(const TDesC& aFileName, const TBool aPassive) const |
|
2606 { |
|
2607 //check whether the target process is being debugged |
|
2608 return Server().IsDebugged(aFileName, aPassive); |
|
2609 } |
|
2610 |
|
2611 /** |
|
2612 Helper function which reads a TThreadId object from a client |
|
2613 |
|
2614 @param aMessage the message object containing the reference to the TThreadId |
|
2615 @param aIndex the message argument containing the reference |
|
2616 |
|
2617 @return the TThreadId passed in by the client |
|
2618 @leave KErrArgument if aIndex is outside of the valid range |
|
2619 */ |
|
2620 TThreadId CSecuritySvrSession::ReadTThreadIdL(const RMessagePtr2& aMessage, const TInt aIndex) const |
|
2621 { |
|
2622 //create a temporary TThreadId to read the data into |
|
2623 TThreadId tempThreadId; |
|
2624 TPtr8 threadIdPtr((TUint8*)&tempThreadId, sizeof(TThreadId)); |
|
2625 |
|
2626 // read the data in from the client |
|
2627 aMessage.ReadL(aIndex, threadIdPtr); |
|
2628 |
|
2629 return tempThreadId; |
|
2630 } |
|
2631 |
|
2632 /** |
|
2633 Helper function which reads a TProcessId object from a client |
|
2634 |
|
2635 @param aMessage the message object containing the reference to the TProcessId |
|
2636 @param aIndex the message argument containing the reference |
|
2637 |
|
2638 @return the TProcessId passed in by the client |
|
2639 @leave KErrArgument if aIndex is outside of the valid range |
|
2640 */ |
|
2641 TProcessId CSecuritySvrSession::ReadTProcessIdL(const RMessagePtr2& aMessage, const TInt aIndex) const |
|
2642 { |
|
2643 //create a temporary TProcessId to read the data into |
|
2644 TProcessId tempProcessId; |
|
2645 TPtr8 processIdPtr((TUint8*)&tempProcessId, sizeof(TProcessId)); |
|
2646 |
|
2647 // read the data in from the client |
|
2648 aMessage.ReadL(aIndex, processIdPtr); |
|
2649 |
|
2650 return tempProcessId; |
|
2651 } |
|
2652 |
|
2653 // End of file - c_security_svr_session.cpp |