1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """
22 @author: Brendan Dolan-Gavitt
23 @license: GNU General Public License 2.0 or later
24 @contact: brendandg@gatech.edu
25 @organization: Georgia Institute of Technology
26 """
27
28
29 from rekall import obj
30
31 from rekall.plugins.overlays import basic
32 from rekall.plugins.overlays.linux import vfs
33
34 from rekall_lib import utils
35
36
37 linux_overlay = {
38 'task_struct' : [None, {
39 'state': [None, ['Flags', dict(
40 maskmap=utils.MaskMapFromDefines("""
41 # From http://lxr.free-electrons.com/source/include/linux/sched.h#L207
42 #define TASK_RUNNING 0
43 #define TASK_INTERRUPTIBLE 1
44 #define TASK_UNINTERRUPTIBLE 2
45 #define TASK_STOPPED 4
46 #define TASK_TRACED 8
47 #define TASK_DEAD 64
48 #define TASK_WAKEKILL 128
49 #define TASK_WAKING 256
50 #define TASK_PARKED 512
51 #define TASK_STATE_MAX 1024
52 """))]],
53 'exit_state': [None, ['Flags', dict(
54 maskmap=utils.MaskMapFromDefines("""
55 # From http://lxr.free-electrons.com/source/include/linux/sched.h#L207
56 /* in tsk->exit_state */
57 #define EXIT_ZOMBIE 16
58 #define EXIT_DEAD 32
59 /* in tsk->state again */
60 """))]],
61
62
63 'name': lambda x: x.comm,
64 'dtb': lambda x: x.obj_vm.vtop(x.mm.pgd.v()),
65
66 'comm': [None, ['UnicodeString', dict(length=16)]],
67 'uid': lambda x: x.multi_m(
68 "uid", "cred.uid.val", "cred.uid"),
69 'gid': lambda x: x.multi_m(
70 "gid", "cred.gid.val", "cred.gid"),
71 'euid': lambda x: x.multi_m(
72 "euid", "cred.euid.val", "cred.euid"),
73 }],
74
75 'module' : [None, {
76 'name': lambda x: utils.SmartUnicode(
77 x.m("name").cast('UnicodeString', length=60)),
78 'base': lambda x: x.multi_m(
79 "module_core",
80 "core_layout.base",
81 ).v(),
82 'size': lambda x: x.multi_m(
83 "core_size",
84 "core_layout.size"),
85 'end': lambda x: x.base + x.size,
86 'kp': [None, ['Pointer', dict(
87 target='Array',
88 target_args=dict(
89 target='kernel_param',
90 count=lambda x: x.num_kp))]],
91 }],
92
93 'kernel_param': [None, {
94 'name' : [None, ['Pointer', dict(target='UnicodeString')]],
95 'getter_addr': lambda x: x.multi_m("get", "ops.get"),
96 }],
97
98 'kparam_array': [None, {
99 'getter_addr': lambda x: x.multi_m("get", "ops.get"),
100 }],
101
102 'super_block' : [None, {
103 's_id' : [None, ['UnicodeString', dict(length=32)]],
104 'major': lambda x: x.s_dev >> 20,
105 'minor': lambda x: x.s_dev & ((1 << 20) - 1),
106 }],
107
108 'net_device' : [None, {
109 'flags': [None, ['Flags', dict(
110 maskmap=utils.MaskMapFromDefines("""
111 http://lxr.free-electrons.com/source/include/linux/if.h?v=2.6.32#L31
112
113 /* Standard interface flags (netdevice->flags). */
114 30 #define IFF_UP 0x1 /* interface is up */
115 31 #define IFF_BROADCAST 0x2 /* broadcast address valid */
116 32 #define IFF_DEBUG 0x4 /* turn on debugging */
117 33 #define IFF_LOOPBACK 0x8 /* is a loopback net */
118 34 #define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
119 35 #define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
120 36 #define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */
121 37 #define IFF_NOARP 0x80 /* no ARP protocol */
122 38 #define IFF_PROMISC 0x100 /* receive all packets */
123 39 #define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
124 40
125 41 #define IFF_MASTER 0x400 /* master of a load balancer */
126 42 #define IFF_SLAVE 0x800 /* slave of a load balancer */
127 43
128 44 #define IFF_MULTICAST 0x1000 /* Supports multicast */
129 45
130 46 #define IFF_PORTSEL 0x2000 /* can set media type */
131 47 #define IFF_AUTOMEDIA 0x4000 /* auto media select active */
132 48 #define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
133 49
134 50 #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
135 51 #define IFF_DORMANT 0x20000 /* driver signals dormant */
136 52
137 53 #define IFF_ECHO 0x40000 /* echo sent packets */
138 """))]],
139 'name' : [None, ['UnicodeString', dict(length=16)]],
140
141 'ip_ptr': [None, ['Pointer', dict(target="in_device")]],
142 }],
143
144 'in_ifaddr': [None, {
145 'ifa_address': [None, ['Ipv4Address']],
146 'ifa_label': [None, ['String']],
147 }],
148
149 'sockaddr_un' : [None, {
150 'sun_path' : [None, ['UnicodeString', dict(length=108)]],
151 }],
152
153 'cpuinfo_x86' : [None, {
154 'x86_model_id' : [None, ['UnicodeString', dict(length=64)]],
155 'x86_vendor_id' : [None, ['UnicodeString', dict(length=16)]],
156 }],
157
158 'module_sect_attr': [None, {
159 'name': [None, ['Pointer', dict(target='UnicodeString')]]
160 }],
161
162
163 'log': [lambda x: x.m("len"), {
164
165 'message': [lambda x: x.flags.obj_offset + x.flags.obj_size,
166 ['UnicodeString', dict(
167
168
169 length=lambda x: x.text_len + x.dict_len)]],
170
171 'level': [None, ['Enumeration', {
172 'choices': {
173 0: 'LOG_EMERG',
174 1: 'LOG_ALERT',
175 2: 'LOG_CRIT',
176 3: 'LOG_ERR',
177 4: 'LOG_WARNING',
178 5: 'LOG_NOTICE',
179 6: 'LOG_INFO',
180 7: 'LOG_DEBUG'
181 },
182 'target': 'BitField',
183 'target_args': dict(
184 start_bit=0, end_bit=3),
185 }]],
186 }],
187
188 "file": [None, {
189 "dentry": lambda x: x.multi_m("f_dentry", "f_path.dentry"),
190 "vfsmnt": lambda x: x.multi_m("f_vfsmnt", "f_path.mnt"),
191 }],
192
193 'vm_area_struct' : [None, {
194 'vm_flags' : [None, ['PermissionFlags', dict(
195 bitmap={
196 'r': 0,
197 'w': 1,
198 'x': 2
199 }
200 )]],
201 }],
202
203 'dentry': [None, {
204 'd_flags': [None, ['Flags', dict(
205 maskmap={
206
207 "DCACHE_AUTOFS_PENDING": 0x0001,
208
209
210 "DCACHE_NFSFS_RENAMED": 0x0002,
211 "DCACHE_DISCONNECTED": 0x0004,
212
213 "DCACHE_REFERENCED": 0x0008,
214 "DCACHE_UNHASHED": 0x0010,
215
216 "DCACHE_INOTIFY_PARENT_WATCHED": 0x0020,
217
218
219 "DCACHE_FSNOTIFY_PARENT_WATCHED": 0x0080,
220 },
221 target="unsigned int",
222 )]],
223 'is_root': lambda x: x == x.d_parent,
224 }],
225 'd_name': [None, {
226 'd_name': [None, ['Pointer', dict(
227 target="String")]],
228 }],
229
230 'qstr': [None, {
231 'len': lambda x: (x.m("len") or
232 x.m("u1.u1.len") or
233
234 (x.m("u1.hash_len") & 0xFFFFFFFF00000000) >> 32),
235 'name': [None, ['Pointer', dict(
236 target='UnicodeString',
237 target_args=dict(
238
239 length=lambda x: (min(x.len, 255)),
240 )
241 )]],
242 }],
243
244 "files_struct": [None, {
245
246 '_fd': lambda x: x.m("fdt").fd or x.fd,
247
248
249
250
251 'fds': lambda x: x._fd.dereference_as(
252 "Array",
253 target_args=dict(
254 target="Pointer",
255 target_args=dict(
256 target="file"
257 ),
258 count=lambda x: x.m("fdt").max_fds or x.max_fds,
259 )
260 )
261 }],
262
263 "kobject": [None, {
264 'name': [None, ["Pointer", dict(
265 target="String",
266 target_args=dict(length=32),
267 )]],
268 }],
269
270 'gate_struct64': [None, {
271 'address': lambda x: obj.Pointer.integer_to_address(
272 x.offset_low |
273 x.offset_middle << 16 |
274 x.offset_high << 32),
275 'gate_type': [5, ['Enumeration', {
276 'choices': {
277 5: '32-bit Task Gate',
278 6: '16-bit Int Gate',
279 7: '16-bit Trap Gate',
280 14: '32-bit Int Gate',
281 15: '32-bit Trap Gate',
282 },
283 'target': 'BitField',
284 'target_args': dict(
285 start_bit=0, end_bit=4),
286 }]],
287 'present': lambda x: x.m("p"),
288 }],
289
290 'desc_struct': [None, {
291 'address': lambda x: ((x.u1.u1.b & 0xffff0000) |
292 (x.u1.u1.a & 0x0000ffff)),
293 'gate_type': [5, ['Enumeration', {
294 'choices': {
295 5: '32-bit Task Gate',
296 6: '16-bit Int Gate',
297 7: '16-bit Trap Gate',
298 14: '32-bit Int Gate',
299 15: '32-bit Trap Gate',
300 },
301 'target': 'BitField',
302 'target_args': dict(
303 start_bit=0, end_bit=4),
304 }]],
305 'dpl': lambda x: x.m("u1.u2.dpl"),
306 'present': lambda x: x.m("u1.u2.p"),
307 }],
308
309 'tty_driver': [None, {
310 "name": [None, ["Pointer", dict(
311 target="String"
312 )]],
313
314 "ttys": [None, ["Pointer", dict(
315 target="Array",
316 target_args=dict(
317 count=lambda x: x.num,
318 target="Pointer",
319 target_args=dict(
320 target="tty_struct"
321 )
322 )
323 )]],
324 }],
325
326 'tty_struct': [None, {
327 'name': [None, ["String"]],
328 }],
329
330 "resource": [None, {
331 "name": [None, ["Pointer", dict(
332 target="String"
333 )]],
334 }],
335 "sock": [None, {
336
337 "sk_type": [None, ["Enumeration", dict(
338 choices={
339 1:"SOCK_STREAM",
340 2:"SOCK_DGRAM",
341 3:"SOCK_RAW",
342 4:"SOCK_RDM",
343 5:"SOCK_SEQPACKET",
344 6:"SOCK_DCCP",
345 10:"SOCK_PACKET",
346 },
347 target="BitField",
348 target_args=dict(
349 start_bit=16, end_bit=32))]],
350
351 "sk_protocol": [None, ["Enumeration", dict(
352
353 choices={
354 0:"IPPROTO_HOPOPT",
355
356
357 1:"IPPROTO_ICMP",
358
359
360 2:"IPPROTO_IGMP",
361
362
363 4:"IPPROTO_IPV4",
364 6:"IPPROTO_TCP",
365 8:"IPPROTO_EGP",
366 12:"IPPROTO_PUP",
367 17:"IPPROTO_UDP",
368 22:"IPPROTO_IDP",
369 29:"IPPROTO_TP",
370
371
372 33:"IPPROTO_DCCP",
373 41:"IPPROTO_IPV6",
374 46:"IPPROTO_RSVP",
375
376
377 47:"IPPROTO_GRE",
378
379
380 50:"IPPROTO_ESP",
381 51:"IPPROTO_AH",
382
383
384 92:"IPPROTO_MTP",
385
386
387 94:"IPPROTO_BEETPH",
388 98:"IPPROTO_ENCAP",
389 103:"IPPROTO_PIM",
390 108:"IPPROTO_COMP",
391
392
393 132:"IPPROTO_SCTP",
394 136:"IPPROTO_UDPLITE",
395 255:"IPPROTO_RAW",
396 },
397 target="BitField",
398 target_args=dict(
399 start_bit=8, end_bit=16),
400 )]],
401 }],
402 "sock_common": [None, {
403 "skc_state": [None, ["Enumeration", dict(
404
405
406
407
408 choices={
409 1:"ESTABLISHED",
410 2:"SYN_SENT",
411 3:"SYN_RECV",
412 4:"FIN_WAIT1",
413 5:"FIN_WAIT2",
414 6:"TIME_WAIT",
415 7:"CLOSE",
416 8:"CLOSE_WAIT",
417 9:"LAST_ACK",
418 10:"LISTEN",
419 11:"CLOSING",
420 },
421 target="unsigned char",
422 )]],
423
424 "skc_family": [None, ["Enumeration", dict(
425 choices=utils.EnumerationFromDefines("""
426 http://lxr.free-electrons.com/source/include/linux/socket.h#L140
427
428 /* Supported address families. */
429 141 #define AF_UNSPEC 0
430 142 #define AF_UNIX 1 /* Unix domain sockets */
431 143 #define AF_LOCAL 1 /* POSIX name for AF_UNIX */
432 144 #define AF_INET 2 /* Internet IP Protocol */
433 145 #define AF_AX25 3 /* Amateur Radio AX.25 */
434 146 #define AF_IPX 4 /* Novell IPX */
435 147 #define AF_APPLETALK 5 /* AppleTalk DDP */
436 148 #define AF_NETROM 6 /* Amateur Radio NET/ROM */
437 149 #define AF_BRIDGE 7 /* Multiprotocol bridge */
438 150 #define AF_ATMPVC 8 /* ATM PVCs */
439 151 #define AF_X25 9 /* Reserved for X.25 project */
440 152 #define AF_INET6 10 /* IP version 6 */
441 153 #define AF_ROSE 11 /* Amateur Radio X.25 PLP */
442 154 #define AF_DECnet 12 /* Reserved for DECnet project */
443 155 #define AF_NETBEUI 13 /* Reserved for 802.2LLC project*/
444 156 #define AF_SECURITY 14 /* Security callback pseudo AF */
445 157 #define AF_KEY 15 /* PF_KEY key management API */
446 158 #define AF_NETLINK 16
447
448 160 #define AF_PACKET 17 /* Packet family */
449 161 #define AF_ASH 18 /* Ash */
450 162 #define AF_ECONET 19 /* Acorn Econet */
451 163 #define AF_ATMSVC 20 /* ATM SVCs */
452 164 #define AF_RDS 21 /* RDS sockets */
453 165 #define AF_SNA 22 /* Linux SNA Project (nutters!) */
454 166 #define AF_IRDA 23 /* IRDA sockets */
455 167 #define AF_PPPOX 24 /* PPPoX sockets */
456 168 #define AF_WANPIPE 25 /* Wanpipe API Sockets */
457 169 #define AF_LLC 26 /* Linux LLC */
458 170 #define AF_IB 27 /* Native InfiniBand address */
459 171 #define AF_CAN 29 /* Controller Area Network */
460 172 #define AF_TIPC 30 /* TIPC sockets */
461 173 #define AF_BLUETOOTH 31 /* Bluetooth sockets */
462 174 #define AF_IUCV 32 /* IUCV sockets */
463 175 #define AF_RXRPC 33 /* RxRPC sockets */
464 176 #define AF_ISDN 34 /* mISDN sockets */
465 177 #define AF_PHONET 35 /* Phonet sockets */
466 178 #define AF_IEEE802154 36 /* IEEE802154 sockets */
467 179 #define AF_CAIF 37 /* CAIF sockets */
468 180 #define AF_ALG 38 /* Algorithm sockets */
469 181 #define AF_NFC 39 /* NFC sockets */
470 182 #define AF_VSOCK 40 /* vSockets */
471 183 #define AF_MAX 41 /* For now.. */
472 """),
473 target="short unsigned int"
474 )]],
475 }],
476 "mount": [None, {
477 "mnt_devname": [None, ["Pointer", dict(target="String")]],
478 "mnt_root": lambda x: x.m("mnt_root") or x.m("mnt.mnt_root"),
479 }],
480 "vfsmount": [None, {
481 "mnt_devname": [None, ["Pointer", dict(target="String")]],
482 "mnt_flags": [None, ["Flags", dict(
483 maskmap={
484
485 "nosuid": 0x01,
486 "nodev": 0x02,
487 "noexec": 0x04,
488 "noatime": 0x08,
489 "nodiratime": 0x10,
490 "relatime": 0x20,
491 "ro": 0x40,
492 "shrinkable": 0x100,
493 "writehold": 0x200,
494 "shared": 0x1000,
495 "unbindable": 0x2000,
496 },
497 target="unsigned int",
498 )]],
499 "mnt": lambda x: x,
500 }],
501
502 "file_system_type": [None, {
503 "name": [None, ["Pointer", dict(target="String")]],
504 }],
505
506 "inode": [None, {
507 "i_uid": lambda x: x.multi_m("i_uid.val", "i_uid"),
508 "i_gid": lambda x: x.multi_m("i_gid.val", "i_gid"),
509 "i_mode": [None, ["InodePermission", dict(
510 target="unsigned int",
511 )]],
512 "type": lambda x: x.m("i_mode").cast(
513 "Enumeration", choices={
514 1: "S_IFIFO",
515 2: "S_IFCHR",
516 4: "S_IFDIR",
517 6: "S_IFBLK",
518 8: "S_IFREG",
519 10: "S_IFLNK",
520 12: "S_IFSOCK",
521 },
522 target="BitField",
523 target_args=dict(start_bit=12, end_bit=16),
524 ),
525 "mode": lambda x: x.m("i_mode").cast(
526 "Flags",
527 maskmap=utils.MaskMapFromDefines("""
528 # From http://lxr.free-electrons.com/source/include/uapi/linux/stat.h
529 #define S_ISUID 0004000
530 #define S_ISGID 0002000
531 #define S_ISVTX 0001000
532
533 #define S_IRUSR 00400
534 #define S_IWUSR 00200
535 #define S_IXUSR 00100
536
537 #define S_IRGRP 00040
538 #define S_IWGRP 00020
539 #define S_IXGRP 00010
540
541 #define S_IROTH 00004
542 #define S_IWOTH 00002
543 #define S_IXOTH 00001
544 """),
545 target="BitField",
546 target_args=dict(start_bit=0, end_bit=12),
547 ),
548 }],
549 "radix_tree_node": [None, {
550 "rcu_head": lambda x: x.m("rcu_head") or x.m("u1.rcu_head"),
551 }],
552 "tk_core": [None, {
553 "seq": [0, ["seqcount"]],
554 "timekeeper": [8, ["timekeeper"]],
555 }],
556
557 "neigh_hash_table": [None, {
558 "hash_buckets": [None, ["Pointer", dict(
559 target="Array",
560 target_args=dict(
561 count=lambda x: 1 << x.hash_shift,
562 target="Pointer",
563 target_args=dict(
564 target="neighbour",
565 ),
566 )
567 )]],
568 }],
569 }
570
571
572 -class list_head(basic.ListMixIn, obj.Struct):
573 """A list_head makes a doubly linked list."""
574 _forward = "next"
575 _backward = "prev"
576
581
583 _backward = "pprev"
584
593
595 stack = [self]
596 while stack:
597 item = stack.pop()
598 if item not in seen:
599 seen.append(item)
600
601
602 Blink = item.m(self._backward).deref()
603 if Blink.is_valid():
604 stack.append(Blink.dereference())
605
606 Flink = item.m(self._forward)
607 if Flink.is_valid():
608 stack.append(Flink.dereference())
609
612
615 """Class for an internet socket object"""
616
617 @utils.safe_property
619 return (self.m("sport") or self.m("inet_sport")).cast(
620 "unsigned be short")
621
622 @utils.safe_property
624 return ((self.m("dport") or self.m("inet_dport")).cast(
625 "unsigned be short") or self.sk.m("__sk_common.u3.u1.skc_dport") or
626 self.sk.m("__sk_common.u3.skc_dport"))
627 @utils.safe_property
629 if self.sk.m("__sk_common").skc_family == "AF_INET":
630 return (self.m("rcv_saddr") or self.m("inet_rcv_saddr") or
631 self.sk.m("__sk_common.u1.u1.skc_rcv_saddr") or
632 self.m("inet_saddr")).cast(
633 "Ipv4Address")
634
635 else:
636 return self.m("pinet6.saddr").cast("Ipv6Address")
637
638 @utils.safe_property
640 if self.sk.m("__sk_common").skc_family == "AF_INET":
641 return (self.m("daddr") or self.m("inet_daddr") or
642 self.sk.m("__sk_common.u1.u1.skc_daddr") or
643 self.sk.m("__sk_common.skc_daddr")).cast(
644 "Ipv4Address")
645
646 else:
647 return (self.m("pinet6.daddr").cast("Ipv6Address") or
648 self.m("pinet6.daddr_cache").cast("Ipv6Address"))
649
652
654 if hasattr(self, "fdt"):
655 fdt = self.fdt
656 ret = fdt.fd.dereference()
657 else:
658 ret = self.fd.dereference()
659
660 return ret
661
663 if hasattr(self, "fdt"):
664 ret = self.fdt.max_fds
665 else:
666 ret = self.max_fds
667
668 return ret
669
670
671 -class dentry(obj.Struct):
672 @utils.safe_property
674 dentry_ = self
675
676 path_components = []
677
678
679 if self.d_flags.DCACHE_UNHASHED and not self.is_root:
680 return " (deleted) "
681
682 while len(path_components) < 50:
683 if dentry_.is_root:
684 break
685
686 component = utils.SmartUnicode(dentry_.d_name.name.deref())
687 path_components = [component] + path_components
688 dentry_ = dentry_.d_parent
689
690 result = '/'.join(filter(None, path_components))
691
692 if result.startswith(("socket:", "pipe:")):
693 if result.find("]") == -1:
694 result += ":[{0}]".format(self.d_inode.i_ino)
695
696 elif result != "inotify":
697 result = '/' + result
698
699 return result
700
703
704 @utils.safe_property
706 if self.mm:
707
708 proc_as = self.get_process_address_space()
709
710
711 argv = proc_as.read(self.mm.arg_start,
712 self.mm.arg_end - self.mm.arg_start)
713
714 if argv:
715
716 name = " ".join(argv.split("\x00"))
717 else:
718 name = ""
719 else:
720
721 name = "[" + self.comm + "]"
722
723 return name
724
725 @utils.safe_property
727 if self.obj_profile.get_constant("tk_core"):
728
729
730 start_timespec = self.obj_profile.timespec()
731 start_timespec.tv_sec = self.m("start_time") / 1000000000
732 start_timespec.tv_nsec = self.m("start_time") % 1000000000
733 boot_time = self.obj_profile.getboottime()
734 start_time = self.obj_profile.UnixTimeStamp(
735 value = start_timespec.tv_sec - boot_time.tv_sec)
736 return start_time
737 return self.m("start_time").as_timestamp()
738
740 """Resolve the dentry, vfsmount relative to this task's chroot.
741
742 Returns:
743 An absolute path to the global filesystem mount. (I.e. we do not
744 truncate the path at the chroot point as the kernel does).
745 """
746
747
748
749
750 if self.obj_profile.get_obj_offset("vfsmount", "mnt_parent"):
751 return vfs.Linux26VFS(self.obj_profile).get_path(self, filp)
752
753 else:
754 return vfs.Linux3VFS(self.obj_profile).get_path(self, filp)
755
757 directory_table_base = self.obj_vm.vtop(self.mm.pgd.v())
758
759 try:
760 process_as = self.obj_vm.__class__(
761 base=self.obj_vm.base, session=self.obj_vm.session,
762 dtb=directory_table_base, profile=self.obj_profile)
763
764 except AssertionError:
765 return obj.NoneObject("Unable to get process AS")
766
767 process_as.name = "Process {0}".format(self.pid)
768
769 return process_as
770
773
774
775
776
777
778 HZ = 1000
779
780
781 CLOCK_TICK_RATE = PIT_TICK_RATE = 1193182
782
783
784 LATCH = ((CLOCK_TICK_RATE + HZ/2) / HZ)
785
786
787 ACTHZ = (CLOCK_TICK_RATE / LATCH)
788
789
790 TICK_NSEC = 1000000 * 1000 / ACTHZ
791
792 NSEC_PER_SEC = 1000000000
793
797
799 if not isinstance(other, self.__class__):
800 raise TypeError("Can only add timespec to timespec")
801
802 sec = other.tv_sec + self.tv_sec
803 nsec = other.tv_nsec + self.tv_nsec
804
805 result = self.obj_profile.timespec()
806 result.tv_sec = sec
807 result.tv_nsec = nsec
808
809 return result
810
812 ts = self.obj_profile.timespec()
813 ts.tv_sec = -other.tv_sec
814 ts.tv_nsec = -other.tv_nsec
815 return self + ts
816
818 """Normalizes a timespec's secs and nsecs.
819
820 Based on set_normalized_timespec:
821 http://lxr.free-electrons.com/source/kernel/time.c?v=3.11#L358
822 """
823 sec = self.tv_sec + self.tv_nsec / self.NSEC_PER_SEC
824 nsec = self.tv_nsec % self.NSEC_PER_SEC
825
826 result = self.obj_profile.timespec()
827 result.tv_sec = sec
828 result.tv_nsec = nsec
829 return result
830
832 """Returns the time as a UnixTimestamp."""
833 the_time = self - self.obj_profile.getboottime(vm=self.obj_vm)
834 the_time = the_time.normalized_timespec()
835 return self.obj_profile.UnixTimeStamp(value=the_time.tv_sec.v())
836
839 @utils.safe_property
841 addr = self.perm_addr
842 if (addr.obj_vm.read(addr.obj_offset, addr.obj_size) ==
843 "\x00" * addr.obj_size):
844 addr = self.dev_addr.deref()
845
846 return addr.cast("MacAddress")
847
850 """A Flags object for printing vm_area_struct permissions
851 in a format like rwx or r-x"""
852
854 result = []
855 value = self.v()
856 for k, v in sorted(self.maskmap.items()):
857 if value & v:
858 result.append(k)
859 else:
860 result.append("-")
861
862 return ''.join(result)
863
865 return self.v() & (1 << self.bitmap[flag])
866
869
872
875
878 """Newer kernels use this struct instead of an int."""
879
881 return unicode(self.val)
882
884 return long(self.val)
885
888 """Newer kernels use this struct instead of an int."""
889
890
891 -class proc_dir_entry(obj.Struct):
892 @utils.safe_property
894 if self.name.obj_type == "Pointer":
895 return self.name.deref().cast("String", length=self.namelen)
896 else:
897 return self.name.cast("String", length=self.namelen)
898
899
900 -class page(obj.Struct):
901 - def physical_offset(self):
902 """The physical offset of the page represented by this page struct."""
903
904
905 mem_map = self.obj_profile.get_constant_object(
906 "mem_map", "Pointer")
907
908 if mem_map == None:
909 if self.obj_profile.get_constant("mem_section"):
910
911
912 mem_map = obj.Pointer.integer_to_address(0xffffea0000000000)
913 else:
914 self.obj_session.logging.error(
915 "Unable to determine physical address of page. NUMA is not "
916 "supported.")
917 return obj.NoneObject("NUMA is unsupported.")
918
919
920
921
922
923 pfn = (self.obj_offset - mem_map) / self.obj_size
924 phys_offset = pfn << 12
925 return phys_offset
926
927 - def read(self, offset, size):
928 """Reads data from the physical page associated to this page entry.
929
930 It reads PAGE_SIZE at max.
931 """
932
933 phys_offset = self.physical_offset()
934 phys_as = self.obj_session.physical_address_space
935 to_read = max(0, self.obj_vm.PAGE_SIZE - offset)
936 to_read = min(size, to_read)
937 if to_read:
938 data = phys_as.read(phys_offset, to_read)
939 if to_read <= size:
940 data += "\x00" * (size - to_read)
941 return data
942
953
954
955 -class Linux(basic.RelativeOffsetMixin, basic.BasicClasses):
956 METADATA = dict(
957 os="linux",
958 type="Kernel")
959
960 image_base = None
961
962 @classmethod
964 super(Linux, cls).Initialize(profile)
965 profile.add_classes(dict(
966 InodePermission=InodePermission,
967 PermissionFlags=PermissionFlags,
968 dentry=dentry,
969 hlist_head=hlist_head,
970 hlist_node=hlist_node,
971 list_head=list_head,
972 net_device=net_device,
973 page=page, kgid_t=kgid_t, kuid_t=kuid_t,
974 proc_dir_entry=proc_dir_entry,
975 task_struct=task_struct,
976 timespec=timespec, inet_sock=inet_sock,
977 ))
978 profile.add_overlay(linux_overlay)
979 profile.add_constants(dict(default_text_encoding="utf8"))
980
981
982 if not profile.metadata("arch"):
983 try:
984 profile.constant_addresses.find_gt(2**32)
985 profile.set_metadata("arch", "AMD64")
986 except ValueError:
987 profile.set_metadata("arch", "I386")
988
989 if profile.metadata("arch") == "I386":
990 basic.Profile32Bits.Initialize(profile)
991 try:
992 if (not profile.metadata("pae") and
993 profile.get_kernel_config("CONFIG_X86_PAE") == "y"):
994 profile.set_metadata("pae", True)
995 except ValueError:
996 pass
997
998
999
1000
1001 elif profile.metadata("arch") == "ARM":
1002 basic.Profile32Bits.Initialize(profile)
1003
1004 elif profile.metadata("arch") == "MIPS":
1005 basic.ProfileMIPS32Bits.Initialize(profile)
1006
1007 elif profile.metadata("arch") == "AMD64":
1008 basic.ProfileLP64.Initialize(profile)
1009
1015
1017 """Sets up the kernel profile, adding kernel config options."""
1018 super(Linux, self)._SetupProfileFromData(data)
1019 self.kernel_config_options = {}
1020
1021
1022 config = data.get("$CONFIG")
1023 if config:
1024 self.add_kernel_config_options(**config)
1025
1026 try:
1027
1028 if (self.get_kernel_config("CONFIG_X86_PAE") == "y" and
1029 self.metadata("arch") == "I386"):
1030 self.set_metadata("pae", True)
1031 except ValueError:
1032
1033
1034 self.session.logging.debug(
1035 "No kernel config available in the profile, so we cannot "
1036 "detect PAE.")
1037
1039 """Add the kwargs as kernel config options for this profile."""
1040 for k, v in kwargs.iteritems():
1041 self.kernel_config_options[k] = v
1042
1044 """Returns the kernel config option config_option for this profile.
1045
1046 Raises if no kernel configuration is present in the profile.
1047 """
1048
1049 config_options = getattr(self, "kernel_config_options", obj.NoneObject(
1050 "No kernel config options present in the profile."))
1051
1052 return config_options.get(config_option)
1053
1055 wall_addr = self.get_constant("wall_to_monotonic")
1056 if wall_addr:
1057 return self.timespec(vm=vm, offset=wall_addr)
1058
1059
1060 timekeeper_addr = self.get_constant("timekeeper")
1061 if timekeeper_addr:
1062 return self.timekeeper(
1063 vm=vm, offset=timekeeper_addr).wall_to_monotonic
1064
1066 total_sleep_time_addr = self.get_constant(
1067 "total_sleep_time")
1068
1069 if total_sleep_time_addr:
1070 return self.timespec(
1071 vm=vm, offset=total_sleep_time_addr)
1072
1073
1074 timekeeper_addr = self.get_constant("timekeeper")
1075 if timekeeper_addr:
1076 return self.timekeeper(
1077 vm=vm, offset=timekeeper_addr).total_sleep_time
1078
1079
1080 return self.timespec()
1081
1093
1095 """Substracts two ktime_t instances."""
1096 kt = self.ktime()
1097 kt.tv64 = lhs.tv64 - rhs.tv64
1098 return kt
1099
1101 """Transforms a ktime_t to a timespec."""
1102 return self.ns_to_timespec(kt.tv64)
1103
1105 """Transforms nanoseconds to a timespec."""
1106 ts = self.timespec()
1107
1108 if not nsec:
1109 ts.tv_sec = 0
1110 ts.tv_nsec = 0
1111 else:
1112 tv_sec = nsec / timespec.NSEC_PER_SEC
1113 rem = nsec % timespec.NSEC_PER_SEC
1114 ts.tv_sec = tv_sec
1115
1116 if rem < 0:
1117 ts.tv_sec -= 1
1118 rem += timespec.NSEC_PER_SEC
1119
1120 ts.tv_nsec = rem
1121 return ts
1122
1124 """Returns the physical address of a given virtual address va.
1125
1126 Linux has a direct mapping between the kernel virtual address space and
1127 the physical memory. This is the difference between the virtual and
1128 physical addresses (aka PAGE_OFFSET). This is defined by the __va macro:
1129
1130 #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
1131 """
1132 va_addr = obj.Pointer.integer_to_address(va)
1133 page_offset_addr = obj.Pointer.integer_to_address(
1134 self.GetPageOffset())
1135
1136 if va_addr >= page_offset_addr:
1137 return (va_addr - page_offset_addr)
1138 else:
1139 return obj.NoneObject("Unable to translate VA 0x%x", va)
1140
1141 - def GetPageOffset(self):
1142 """Gets the page offset."""
1143
1144
1145
1146 self.session.logging.debug("Calculating page offset...")
1147
1148 if self.metadata("arch") == "I386":
1149 return (self.get_constant("_text", False) -
1150 self.get_constant("phys_startup_32", False))
1151
1152 elif self.metadata("arch") == "AMD64":
1153
1154
1155
1156 phys_startup_64 = (self.get_constant("phys_startup_64", False) or
1157 0x1000000)
1158
1159 return self.get_constant("_text", False) - phys_startup_64
1160
1161 elif self.metadata("arch") == "MIPS":
1162 return 0x80000000
1163
1164 elif self.metadata("arch") == "ARM":
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177 return 0xc0000000
1178
1179 else:
1180 return obj.NoneObject("No profile architecture set.")
1181
1183 """Convers nanoseconds to a clock_t. Introduced in 3.17.
1184
1185 http://lxr.free-electrons.com/source/kernel/time/time.c?v=3.17#L703
1186 """
1187 NSEC_PER_SEC = 1000000000L
1188 USER_HZ = 100
1189
1190 if NSEC_PER_SEC % USER_HZ == 0:
1191 return x / (NSEC_PER_SEC / USER_HZ)
1192 elif USER_HZ % 512 == 0:
1193 return ((x * USER_HZ) / 512) / (NSEC_PER_SEC / 512)
1194 else:
1195 return (x*9) / ((9 * NSEC_PER_SEC + (USER_HZ/2)) / USER_HZ)
1196
1201
1208
1211 """Linux profiles can carry the original Kconfig in the $CONFIG section."""
1212 name = "$CONFIG"
1213
1218