22# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
33#
44
5+ import abc
56import collections .abc
67import logging
78import functools
1819from volatility3 .framework .constants .linux import TCP_STATES , NETLINK_PROTOCOLS
1920from volatility3 .framework .constants .linux import ETH_PROTOCOLS , BLUETOOTH_STATES
2021from volatility3 .framework .constants .linux import BLUETOOTH_PROTOCOLS , SOCKET_STATES
21- from volatility3 .framework .constants .linux import CAPABILITIES , PT_FLAGS
22+ from volatility3 .framework .constants .linux import CAPABILITIES , PT_FLAGS , NSEC_PER_SEC
2223from volatility3 .framework .layers import linear
2324from volatility3 .framework .objects import utility
2425from volatility3 .framework .symbols import generic , linux , intermed
2526from volatility3 .framework .symbols .linux .extensions import elf
2627
28+
2729vollog = logging .getLogger (__name__ )
2830
2931# Keep these in a basic module, to prevent import cycles when symbol providers require them
@@ -431,10 +433,10 @@ def _get_task_start_time(self) -> datetime.timedelta:
431433 if start_time_obj_type_name != "timespec" :
432434 # kernels >= 3.17 real_start_time and start_time are u64
433435 # kernels >= 5.5 uses start_boottime which is also a u64
434- start_time = linux . TimespecVol3 .new_from_nsec (start_time_obj )
436+ start_time = Timespec64Concrete .new_from_nsec (start_time_obj )
435437 else :
436438 # kernels < 3.17 real_start_time and start_time are timespec
437- start_time = linux . TimespecVol3 .new_from_timespec (start_time_obj )
439+ start_time = Timespec64Concrete .new_from_timespec (start_time_obj )
438440
439441 # This is relative to the boot time so it makes sense to be a timedelta.
440442 return start_time .to_timedelta ()
@@ -508,8 +510,8 @@ def _get_time_namespace_boottime_offset(
508510
509511 return time_namespace_offsets .boottime
510512
511- def _get_boottime_raw (self ) -> "linux.TimespecVol3 " :
512- """Returns the boot time in a TimespecVol3 ."""
513+ def _get_boottime_raw (self ) -> "Timespec64Concrete " :
514+ """Returns the boot time in a Timespec64Concrete object ."""
513515
514516 vmlinux = linux .LinuxUtilities .get_module_from_volobj_type (self ._context , self )
515517 if vmlinux .has_symbol ("tk_core" ):
@@ -522,7 +524,7 @@ def _get_boottime_raw(self) -> "linux.TimespecVol3":
522524 else :
523525 # 3.17 <= kernels < 4.10 - Tested on Ubuntu 4.4.0-142
524526 boottime_nsec = timekeeper .offs_real .tv64 - timekeeper .offs_boot .tv64
525- return linux . TimespecVol3 .new_from_nsec (boottime_nsec )
527+ return Timespec64Concrete .new_from_nsec (boottime_nsec )
526528
527529 elif vmlinux .has_symbol ("timekeeper" ) and vmlinux .get_type (
528530 "timekeeper"
@@ -531,7 +533,7 @@ def _get_boottime_raw(self) -> "linux.TimespecVol3":
531533 timekeeper = vmlinux .object_from_symbol ("timekeeper" )
532534
533535 # timekeeper.wall_to_monotonic is timespec
534- boottime = linux . TimespecVol3 .new_from_timespec (
536+ boottime = Timespec64Concrete .new_from_timespec (
535537 timekeeper .wall_to_monotonic
536538 )
537539
@@ -542,7 +544,7 @@ def _get_boottime_raw(self) -> "linux.TimespecVol3":
542544 elif vmlinux .has_symbol ("wall_to_monotonic" ):
543545 # kernels < 3.4 - Tested on Debian7 3.2.0-4 (3.2.57-3+deb7u2)
544546 wall_to_monotonic = vmlinux .object_from_symbol ("wall_to_monotonic" )
545- boottime = linux . TimespecVol3 .new_from_timespec (wall_to_monotonic )
547+ boottime = Timespec64Concrete .new_from_timespec (wall_to_monotonic )
546548 if vmlinux .has_symbol ("total_sleep_time" ):
547549 # 2.6.23 <= kernels < 3.4 7c3f1a573237b90ef331267260358a0ec4ac9079
548550 total_sleep_time = vmlinux .object_from_symbol ("total_sleep_time" )
@@ -2168,12 +2170,124 @@ def get_capabilities(self) -> int:
21682170 return cap_value & self .get_kernel_cap_full ()
21692171
21702172
2171- class timespec64 (objects .StructType ):
2173+ class Timespec64Abstract (abc .ABC ):
2174+ """Abstract class to handle all required timespec64 operations, convertions and
2175+ adjustments."""
2176+
2177+ @classmethod
2178+ def new_from_timespec (cls , other ) -> "Timespec64Concrete" :
2179+ """Creates a new instance from an Timespec64Abstract subclass object"""
2180+ if not isinstance (other , Timespec64Abstract ):
2181+ raise TypeError ("Requires an object subclass of Timespec64Abstract" )
2182+
2183+ tv_sec = int (other .tv_sec )
2184+ tv_nsec = int (other .tv_nsec )
2185+ return Timespec64Concrete (tv_sec = tv_sec , tv_nsec = tv_nsec )
2186+
2187+ @classmethod
2188+ def new_from_nsec (cls , nsec ) -> "Timespec64Concrete" :
2189+ """Creates a new instance from an integer in nanoseconds"""
2190+
2191+ # Based on ns_to_timespec64()
2192+ if nsec > 0 :
2193+ tv_sec = nsec // NSEC_PER_SEC
2194+ tv_nsec = nsec % NSEC_PER_SEC
2195+ elif nsec < 0 :
2196+ tv_sec = - ((- nsec - 1 ) // NSEC_PER_SEC ) - 1
2197+ rem = (- nsec - 1 ) % NSEC_PER_SEC
2198+ tv_nsec = NSEC_PER_SEC - rem - 1
2199+ else :
2200+ tv_sec = tv_nsec = 0
2201+
2202+ return Timespec64Concrete (tv_sec = tv_sec , tv_nsec = tv_nsec )
2203+
21722204 def to_datetime (self ) -> datetime .datetime :
2173- """Returns the respective aware datetime"""
2205+ """Converts this Timespec64Abstract subclass object to a UTC aware datetime"""
2206+
2207+ # pylint: disable=E1101
2208+ return conversion .unixtime_to_datetime (
2209+ self .tv_sec + self .tv_nsec / NSEC_PER_SEC
2210+ )
2211+
2212+ def to_timedelta (self ) -> datetime .timedelta :
2213+ """Converts this Timespec64Abstract subclass object to timedelta"""
2214+ # pylint: disable=E1101
2215+ return datetime .timedelta (seconds = self .tv_sec + self .tv_nsec / NSEC_PER_SEC )
2216+
2217+ def __add__ (self , other ) -> "Timespec64Concrete" :
2218+ """Returns a new Timespec64Concrete object that sums the current values with those
2219+ in the timespec argument"""
2220+ if not isinstance (other , Timespec64Abstract ):
2221+ raise TypeError ("Requires an object subclass of Timespec64Abstract" )
2222+
2223+ # pylint: disable=E1101
2224+ result = Timespec64Concrete (
2225+ tv_sec = self .tv_sec + other .tv_sec ,
2226+ tv_nsec = self .tv_nsec + other .tv_nsec ,
2227+ )
2228+
2229+ result .normalize ()
2230+
2231+ return result
2232+
2233+ def __sub__ (self , other ) -> "Timespec64Concrete" :
2234+ """Returns a new Timespec64Abstract object that subtracts the values in the timespec
2235+ argument from the current object's values"""
2236+ if not isinstance (other , Timespec64Abstract ):
2237+ raise TypeError ("Requires an object subclass of Timespec64Abstract" )
2238+
2239+ # pylint: disable=E1101
2240+ result = Timespec64Concrete (
2241+ tv_sec = self .tv_sec - other .tv_sec ,
2242+ tv_nsec = self .tv_nsec - other .tv_nsec ,
2243+ )
2244+
2245+ result .normalize ()
2246+
2247+ return result
2248+
2249+ def normalize (self ):
2250+ """Normalize any overflow in tv_sec and tv_nsec."""
2251+ # Based on kernel's set_normalized_timespec64()
2252+
2253+ # pylint: disable=E1101
2254+ while self .tv_nsec >= NSEC_PER_SEC :
2255+ self .tv_nsec -= NSEC_PER_SEC
2256+ self .tv_sec += 1
2257+
2258+ while self .tv_nsec < 0 :
2259+ self .tv_nsec += NSEC_PER_SEC
2260+ self .tv_sec -= 1
2261+
2262+ def negate (self ):
2263+ """Returns a new Timespec64Concrete object with the values of the current object negated"""
2264+ # pylint: disable=E1101
2265+ result = Timespec64Concrete (
2266+ tv_sec = - self .tv_sec ,
2267+ tv_nsec = - self .tv_nsec ,
2268+ )
2269+
2270+ result .normalize ()
2271+
2272+ return result
2273+
2274+
2275+ class Timespec64Concrete (Timespec64Abstract ):
2276+ """Handle all required timespec64 operations, convertions and adjustments.
2277+ This is used to dynamically create timespec64-like objects, each its own variables
2278+ and the same methods as a timespec64 object extension.
2279+ """
2280+
2281+ def __init__ (self , tv_sec = 0 , tv_nsec = 0 ):
2282+ self .tv_sec = tv_sec
2283+ self .tv_nsec = tv_nsec
2284+
21742285
2175- dt = conversion .unixtime_to_datetime (self .tv_sec + self .tv_nsec / 1e9 )
2176- return dt
2286+ class timespec64 (Timespec64Abstract , objects .StructType ):
2287+ """Handle all required timespec64 operations, convertions and adjustments.
2288+ This works as an extension of the timespec64 object while maintaining the same methods
2289+ as a Timespec64Concrete object.
2290+ """
21772291
21782292
21792293class inode (objects .StructType ):
0 commit comments