Package rekall :: Package plugins :: Package overlays :: Package linux :: Module linux
[frames] | no frames]

Source Code for Module rekall.plugins.overlays.linux.linux

   1  # Rekall Memory Forensics 
   2  # Copyright (C) 2010 Brendan Dolan-Gavitt 
   3  # Copyright (c) 2011 Michael Cohen <scudette@gmail.com> 
   4  # Copyright 2013 Google Inc. All Rights Reserved. 
   5  # 
   6  # This program is free software; you can redistribute it and/or modify 
   7  # it under the terms of the GNU General Public License as published by 
   8  # the Free Software Foundation; either version 2 of the License, or (at 
   9  # your option) any later version. 
  10  # 
  11  # This program is distributed in the hope that it will be useful, but 
  12  # WITHOUT ANY WARRANTY; without even the implied warranty of 
  13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
  14  # General Public License for more details. 
  15  # 
  16  # You should have received a copy of the GNU General Public License 
  17  # along with this program; if not, write to the Free Software 
  18  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
  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  # pylint: disable=protected-access 
  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          # Common pseudo fields to provide cross OS compatibility. 
  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      # The size of the log record is stored in the len member. 
 163      'log': [lambda x: x.m("len"), { 
 164          # The log message starts after the level member. 
 165          'message': [lambda x: x.flags.obj_offset + x.flags.obj_size, 
 166                      ['UnicodeString', dict( 
 167                          # The length of the message is the text and an optional 
 168                          # dict. 
 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                  # /* autofs: "under construction" */ 
 207                  "DCACHE_AUTOFS_PENDING": 0x0001, 
 208                  #     /* this dentry has been "silly renamed" and 
 209                  #     has to be deleted on the last dput() */ 
 210                  "DCACHE_NFSFS_RENAMED":  0x0002, 
 211                  "DCACHE_DISCONNECTED":  0x0004, 
 212                  #  /* Recently used, don't discard. */ 
 213                  "DCACHE_REFERENCED": 0x0008, 
 214                  "DCACHE_UNHASHED": 0x0010, 
 215                  #  /* Parent inode is watched by inotify */ 
 216                  "DCACHE_INOTIFY_PARENT_WATCHED": 0x0020, 
 217                  #  /* Parent inode is watched by some fsnotify 
 218                  #  listener */ 
 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                            # Worst case scenario, when dwarf parsing epicfailed. 
 234                            (x.m("u1.hash_len") & 0xFFFFFFFF00000000) >> 32), 
 235          'name': [None, ['Pointer', dict( 
 236              target='UnicodeString', 
 237              target_args=dict( 
 238                  # include/linux/limits.h 
 239                  length=lambda x: (min(x.len, 255)), 
 240                  ) 
 241              )]], 
 242          }], 
 243   
 244      "files_struct": [None, { 
 245          # Version independent pointer to the fd table. 
 246          '_fd': lambda x: x.m("fdt").fd or x.fd, 
 247   
 248          # The fds table is an array of pointers to file structs. The index 
 249          # into the array is known in user space as a file descriptor. If the 
 250          # pointer in the array is invalid, the file descriptor is closed. 
 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          # http://lxr.free-electrons.com/source/include/linux/net.h#L58 
 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              # http://lxr.free-electrons.com/source/include/uapi/linux/in.h?#L26 
 353              choices={ 
 354                  0:"IPPROTO_HOPOPT", # Dummy protocol forTCP 
 355   
 356                  # Internet Control Message Protocol 
 357                  1:"IPPROTO_ICMP", 
 358   
 359                  # Internet Group Management Protocol 
 360                  2:"IPPROTO_IGMP", 
 361   
 362                  # IPIP tunnels (older KA9Q tunnels use 94) 
 363                  4:"IPPROTO_IPV4", 
 364                  6:"IPPROTO_TCP", # Transmission Control Protocol 
 365                  8:"IPPROTO_EGP", # Exterior Gateway Protocol 
 366                  12:"IPPROTO_PUP", # PUP protocol 
 367                  17:"IPPROTO_UDP", # User Datagram Protocol 
 368                  22:"IPPROTO_IDP", # XNS IDP protocol 
 369                  29:"IPPROTO_TP", # SO Transport Protocol Class 4 
 370   
 371                  # Datagram Congestion Control Protocol 
 372                  33:"IPPROTO_DCCP", 
 373                  41:"IPPROTO_IPV6", # IPv6-in-IPv4 tunnelling 
 374                  46:"IPPROTO_RSVP", # RSVP Protocol 
 375   
 376                  # Cisco GRE tunnels (rfc 1701",1702) 
 377                  47:"IPPROTO_GRE", 
 378   
 379                  # Encapsulation Security Payload protocol 
 380                  50:"IPPROTO_ESP", 
 381                  51:"IPPROTO_AH", # Authentication Header protocol 
 382   
 383                  # Multicast Transport Protocol 
 384                  92:"IPPROTO_MTP", 
 385   
 386                  # IP option pseudo header for BEET 
 387                  94:"IPPROTO_BEETPH", 
 388                  98:"IPPROTO_ENCAP", # Encapsulation Header 
 389                  103:"IPPROTO_PIM", # Protocol Independent Multicast 
 390                  108:"IPPROTO_COMP", # Compression Header Protocol 
 391   
 392                  # Stream Control Transport Protocol 
 393                  132:"IPPROTO_SCTP", 
 394                  136:"IPPROTO_UDPLITE", # UDP-Lite (RFC 3828) 
 395                  255:"IPPROTO_RAW", # Raw IP packets 
 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              # http://lxr.free-electrons.com/source/include/net/tcp_states.h#L16 
 405              # Because these states are not only used by AF_INET* 
 406              # with TCP proto, we removed the TCP_ prefix to make 
 407              # them more readable. 
 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                  # include/linux/mount.h 
 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
577 578 -class hlist_head(list_head):
579 - def list_of_type(self, type, member):
580 return self.first.list_of_type(type, member)
581
582 -class hlist_node(list_head):
583 _backward = "pprev" 584
585 - def list_of_type(self, type, member):
586 head = self 587 node = head 588 if node: 589 yield basic.container_of(node, type, member) 590 while node and node != head: 591 yield basic.container_of(node, type, member) 592 node = node.next.deref()
593
594 - def find_all_lists(self, seen):
595 stack = [self] 596 while stack: 597 item = stack.pop() 598 if item not in seen: 599 seen.append(item) 600 601 # In hlist, prev is a ** 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
610 - def __empty__(self):
611 return self.m(self._forward) == self.m(self._backward).deref()
612
613 614 -class inet_sock(obj.Struct):
615 """Class for an internet socket object""" 616 617 @utils.safe_property
618 - def src_port(self):
619 return (self.m("sport") or self.m("inet_sport")).cast( 620 "unsigned be short")
621 622 @utils.safe_property
623 - def dst_port(self):
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
628 - def src_addr(self):
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
639 - def dst_addr(self):
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
650 651 -class files_struct(obj.Struct):
652
653 - def get_fds(self):
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
662 - def get_max_fds(self):
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
673 - def path(self):
674 dentry_ = self 675 676 path_components = [] 677 678 # Check for deleted dentry_. 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
701 702 -class task_struct(obj.Struct):
703 704 @utils.safe_property
705 - def commandline(self):
706 if self.mm: 707 # The argv string is initialized inside the process's address space. 708 proc_as = self.get_process_address_space() 709 710 # read argv from userland 711 argv = proc_as.read(self.mm.arg_start, 712 self.mm.arg_end - self.mm.arg_start) 713 714 if argv: 715 # split the \x00 buffer into args 716 name = " ".join(argv.split("\x00")) 717 else: 718 name = "" 719 else: 720 # kernel thread 721 name = "[" + self.comm + "]" 722 723 return name
724 725 @utils.safe_property
726 - def task_start_time(self):
727 if self.obj_profile.get_constant("tk_core"): 728 # Kernel 3.17 changes how start_time is stored. Now it's 729 # in nsecs monotonic or boot based. 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
739 - def get_path(self, filp):
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 # The specific implementation depends on the kernel version. 747 748 # Newer kernels have mnt_parent in the mount struct, not in the 749 # vfsmount struct. 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
756 - def get_process_address_space(self):
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
771 772 -class timespec(obj.Struct):
773 # The following calculates the number of ns each tick is. 774 # http://lxr.free-electrons.com/source/include/linux/jiffies.h?v=2.6.32#L12 775 776 # The HZ value should be obtained from the auxilary vector but for now we 777 # hard code it. TODO: http://lwn.net/Articles/519085/ 778 HZ = 1000 779 780 # The clock frequency of the i8253/i8254 PIT 781 CLOCK_TICK_RATE = PIT_TICK_RATE = 1193182 782 783 # LATCH is used in the interval timer and ftape setup. 784 LATCH = ((CLOCK_TICK_RATE + HZ/2) / HZ) 785 786 # HZ is the requested value. ACTHZ is actual HZ 787 ACTHZ = (CLOCK_TICK_RATE / LATCH) 788 789 # TICK_NSEC is the time between ticks in nsec assuming real ACTHZ 790 TICK_NSEC = 1000000 * 1000 / ACTHZ 791 792 NSEC_PER_SEC = 1000000000 793
794 - def __init__(self, *args, **kwargs):
795 super(timespec, self).__init__(*args, **kwargs) 796 self.HZ = self.obj_profile.get_kernel_config("CONFIG_HZ") or self.HZ
797
798 - def __add__(self, other):
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
811 - def __sub__(self, other):
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
817 - def normalized_timespec(self):
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
831 - def as_timestamp(self):
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
837 838 -class net_device(obj.Struct):
839 @utils.safe_property
840 - def mac_addr(self):
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
848 849 -class PermissionFlags(basic.Flags):
850 """A Flags object for printing vm_area_struct permissions 851 in a format like rwx or r-x""" 852
853 - def __unicode__(self):
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
864 - def is_flag(self, flag):
865 return self.v() & (1 << self.bitmap[flag])
866
867 - def is_executable(self):
868 return self.is_flag('x')
869
870 - def is_readable(self):
871 return self.is_flag('r')
872
873 - def is_writable(self):
874 return self.is_flag('w')
875
876 877 -class kgid_t(obj.Struct):
878 """Newer kernels use this struct instead of an int.""" 879
880 - def __unicode__(self):
881 return unicode(self.val)
882
883 - def __long__(self):
884 return long(self.val)
885
886 887 -class kuid_t(kgid_t):
888 """Newer kernels use this struct instead of an int."""
889
890 891 -class proc_dir_entry(obj.Struct):
892 @utils.safe_property
893 - def Name(self):
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 # mem_map is used in 32-bit kernels. 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 # The VMEMMAP starts at this address in 64-bit kernels. 911 # arch/x86/include/asm/pgtable_64_types.h 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 # Linux stores an array of struct page starting at mem_map. 920 # To find the physical address of a given page, we need to find its 921 # index within the array which corresponds to the Page Frame Number 922 # and shift it left by the PAGE_SIZE. 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
943 944 -class InodePermission(basic.Flags):
945 - def __getattr__(self, attr):
946 mask = super(InodePermission, self).__getattr__(attr) 947 if not mask: 948 return obj.NoneObject("Mask {0} not known".format(attr)) 949 950 if attr.startswith("S_IF"): 951 return (self.v() & 0xF000) == mask 952 return self.v() & mask
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
963 - def Initialize(cls, profile):
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 # Autoguessing for old profiles that don't provide an arch. 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 # ARM systems are just normal 32 bit systems with a weird MMU. Per 999 # http://elinux.org/images/6/6a/Elce11_marinas.pdf, there's also LPAE 1000 # but we do not support this. 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
1010 - def GetImageBase(self):
1011 if self.image_base is None: 1012 self.image_base = obj.Pointer.integer_to_address( 1013 self.session.GetParameter("kernel_slide", 0)) 1014 return self.image_base
1015
1016 - def _SetupProfileFromData(self, data):
1017 """Sets up the kernel profile, adding kernel config options.""" 1018 super(Linux, self)._SetupProfileFromData(data) 1019 self.kernel_config_options = {} 1020 1021 # Add the kernel configuration 1022 config = data.get("$CONFIG") 1023 if config: 1024 self.add_kernel_config_options(**config) 1025 1026 try: 1027 # Set the pae flag if we're a 32bit PAE profile 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 # We cannot autoguess PAE at the moment if we don't know the config 1033 # option value for it. 1034 self.session.logging.debug( 1035 "No kernel config available in the profile, so we cannot " 1036 "detect PAE.")
1037
1038 - def add_kernel_config_options(self, **kwargs):
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
1043 - def get_kernel_config(self, config_option):
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
1054 - def get_wall_to_monotonic(self, vm=None):
1055 wall_addr = self.get_constant("wall_to_monotonic") 1056 if wall_addr: 1057 return self.timespec(vm=vm, offset=wall_addr) 1058 1059 # After Kernel 3.3 wall_to_monotonic is stored inside the timekeeper. 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
1065 - def get_total_sleep_time(self, vm=None):
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 # After Kernel 3.3 wall_to_monotonic is stored inside the timekeeper. 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 # Just return an empty timespec. 1080 return self.timespec()
1081
1082 - def getboottime(self, vm=None):
1083 """Returns the real time of system boot.""" 1084 if self.get_constant("tk_core"): 1085 tk_core = self.get_constant_object("tk_core", "tk_core") 1086 tk = tk_core.timekeeper 1087 t = self.ktime_sub(tk.offs_real, tk.offs_boot) 1088 return self.ktime_to_timespec(t) 1089 else: 1090 boottime = (self.get_wall_to_monotonic(vm=vm) + 1091 self.get_total_sleep_time(vm=vm)) 1092 return boottime.normalized_timespec()
1093
1094 - def ktime_sub(self, lhs, rhs):
1095 """Substracts two ktime_t instances.""" 1096 kt = self.ktime() 1097 kt.tv64 = lhs.tv64 - rhs.tv64 1098 return kt
1099
1100 - def ktime_to_timespec(self, kt):
1101 """Transforms a ktime_t to a timespec.""" 1102 return self.ns_to_timespec(kt.tv64)
1103
1104 - def ns_to_timespec(self, nsec):
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
1123 - def phys_addr(self, va):
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 # This calculation needs to be here instead of the LinuxPageOffset 1144 # parameter hook because it is used during profile autodetection, where 1145 # a profile is not yet set on the session object. 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 # We use the symbol phys_startup_64. If it's not present in the 1154 # profile and it's different than the default, we should be able 1155 # to autodetect the difference via kernel_slide. 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 # This might not be always the same. According to arm/Kconfig, 1166 # this only seems to be accurate with the default split in linux 1167 # (VMSPLIT_3G). See arm/Kconfig. TODO: Use the VMSPLIT_3G config 1168 # variable here. 1169 1170 # 1563 config PAGE_OFFSET 1171 # 1564 hex 1172 # 1565 default PHYS_OFFSET if !MMU 1173 # 1566 default 0x40000000 if VMSPLIT_1G 1174 # 1567 default 0x80000000 if VMSPLIT_2G 1175 # 1568 default 0xC0000000 1176 1177 return 0xc0000000 1178 1179 else: 1180 return obj.NoneObject("No profile architecture set.")
1181
1182 - def nsec_to_clock_t(self, x):
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
1197 1198 # Legacy for old profiles 1199 -class Linux32(Linux):
1200 pass
1201
1202 1203 -class Linux64(Linux):
1204 @classmethod
1205 - def Initialize(cls, profile):
1206 profile.set_metadata("arch", "AMD64") 1207 super(Linux64, cls).Initialize(profile)
1208
1209 1210 -class LinuxConfigProfileLoader(obj.ProfileSectionLoader):
1211 """Linux profiles can carry the original Kconfig in the $CONFIG section.""" 1212 name = "$CONFIG" 1213
1214 - def LoadIntoProfile(self, session, profile, config):
1215 profile.kernel_config_options = config 1216 1217 return profile
1218