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