Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix broken code and APIs in Linux networking paths #1656

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions volatility3/framework/plugins/linux/ip.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Addr(plugins.PluginInterface):

_required_framework_version = (2, 22, 0)

_version = (1, 0, 1)
_version = (1, 0, 2)

@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
Expand Down Expand Up @@ -47,15 +47,15 @@ def _gather_net_dev_info(self, net_dev: net_extensions.net_device):
prefix_len = in_ifaddr.get_prefix_len()
scope_type = in_ifaddr.get_scope_type()
ip_addr = in_ifaddr.get_address()
yield net_ns_id, iface_ifindex, iface_name, mac_addr, promisc, ip_addr, prefix_len, scope_type, operational_state
yield net_ns_id or renderers.NotAvailableValue(), iface_ifindex, iface_name, mac_addr, promisc, ip_addr, prefix_len, scope_type, operational_state

# Interface IPv6 Addresses
inet6_dev = net_dev.ip6_ptr.dereference().cast("inet6_dev")
for inet6_ifaddr in inet6_dev.get_addresses():
prefix_len = inet6_ifaddr.get_prefix_len()
scope_type = inet6_ifaddr.get_scope_type()
ip6_addr = inet6_ifaddr.get_address()
yield net_ns_id, iface_ifindex, iface_name, mac_addr, promisc, ip6_addr, prefix_len, scope_type, operational_state
yield net_ns_id or renderers.NotAvailableValue(), iface_ifindex, iface_name, mac_addr, promisc, ip6_addr, prefix_len, scope_type, operational_state
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were favouring returning None and then at render time doing or NotAvailableValue()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left this as acceptable here b/c the function is just gathering the data directly sent through the generator. If we make it return None in the line you highlighted then this line in the generator (this is a link to the full file) would need to unpack all those fields (10 or so) versus just passing it through:

for fields in self._gather_net_dev_info(net_dev):

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmmmm, not sure how I feel about that. It's a good reason but given this is going to be reused a lot, I'd prefer we did the unpacking (once) rather than letting the RendererValues sneak further into the API. It's much harder to convince people not to do this stuff, if they can point to a core example doing it... 5:S It's a little more work now, but it'll keep everything future and dependable in the future. Could you make the changes please?


def _generator(self):
vmlinux = self.context.modules[self.config["kernel"]]
Expand Down Expand Up @@ -127,7 +127,7 @@ def _gather_net_dev_link_info(self, net_device):
]
flags_str = ",".join(flags_list)

yield net_ns_id, iface_name, mac_addr, operational_state, mtu, qdisc_name, qlen, flags_str
yield net_ns_id or renderers.NotAvailableValue(), iface_name, mac_addr, operational_state, mtu, qdisc_name or renderers.NotAvailableValue(), qlen, flags_str

def _generator(self):
vmlinux = self.context.modules[self.config["kernel"]]
Expand Down
47 changes: 41 additions & 6 deletions volatility3/framework/symbols/linux/extensions/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def promisc(self) -> bool:
"""
return self.flags & self._get_net_device_flag_value("IFF_PROMISC") != 0

def get_net_namespace_id(self) -> int:
def _do_get_net_namespace_id(self) -> int:
"""Return the network namespace id for this network interface.

Returns:
Expand All @@ -216,6 +216,20 @@ def get_net_namespace_id(self) -> int:

return net_ns_id

def get_net_namespace_id(self) -> Optional[int]:
"""Return the network namespace id for this network interface.

Returns:
int: the network namespace id for this network interface
"""
try:
return self._do_get_net_namespace_id()
except exceptions.InvalidAddressException:
vollog.debug(
f"Encountered an invalid address exception when getting the namespace for {self.vol.offset:#x}"
)
return None

def get_operational_state(self) -> Union[str, interfaces.renderers.BaseAbsentValue]:
"""Return the netwok device oprational state (RFC 2863) string

Expand All @@ -228,13 +242,17 @@ def get_operational_state(self) -> Union[str, interfaces.renderers.BaseAbsentVal
vollog.warning(f"Invalid net_device operational state '{self.operstate}'")
return renderers.UnparsableValue()

def get_qdisc_name(self) -> str:
def get_qdisc_name(self) -> Optional[str]:
"""Return the network device queuing discipline (qdisc) name

Returns:
str: A string with the queuing discipline (qdisc) name
"""
return utility.array_to_string(self.qdisc.ops.id)
try:
return utility.array_to_string(self.qdisc.ops.id)
except exceptions.InvalidAddressException:
vollog.debug(f"Unable to get qdisc name for {self.vol.offset:#x}")
return None

def get_queue_length(self) -> int:
"""Return the netwrok device transmision qeueue length (qlen)
Expand All @@ -247,17 +265,34 @@ def get_queue_length(self) -> int:

class in_device(objects.StructType):
def get_addresses(
self,
self, max_devices=128
) -> Generator[interfaces.objects.ObjectInterface, None, None]:
"""Yield the IPv4 ifaddr addresses

Yields:
in_ifaddr: An IPv4 ifaddr address
"""
cur = self.ifa_list
seen = set()

try:
cur = self.ifa_list
except exceptions.InvalidAddressException:
return

while cur and cur.vol.offset:
if len(seen) > max_devices:
break

if cur.vol.offset in seen:
break
seen.add(cur.vol.offset)

yield cur
cur = cur.ifa_next

try:
cur = cur.ifa_next
except exceptions.InvalidAddressException:
break


class inet6_dev(objects.StructType):
Expand Down
Loading