How to printk with IP address or MAC address in Linux Kernel Source Code - linux

I have to change TCP Congestion Control algorithm a little bit by modifying Linux Kernel Source Code. But to check if the result is correct, I need to log info of MAC or IP address.
I used PRINTK function to print messages for kernel. But I feel hard to print out MAC/IP address of hosts.
printk("%pM \n", mac)
But what is mac refer to?
In TCP source code, I often work with skbuff or sock struct.
Thank you.
UPDATE:
struct iphdr *iph = ip_hdr(skb);
printk(KERN_DEBUG "%pI4", iph->saddr);

Linux documents the printk format specifier extensions in the file Documentation/printk-formats.txt available as part of the kernel's source code. For your example,
IPv4 addresses:
%pI4 1.2.3.4
%pi4 001.002.003.004
%p[Ii][hnbl]
For printing IPv4 dot-separated decimal addresses. The 'I4' and 'i4'
specifiers result in a printed address with ('i4') or without ('I4')
leading zeros.
The parameter passed would be a pointer to the IP address to print (skbuff, socket structure, etc).

Are you looking for something like this?
from arch/xtensa/platforms/iss/network.c:
printk("(%pM) ", lp->mac);
i found it using this command
grep -R "mac)" * | grep printk
It might be easier to help if you could tell us which file/line you are currently working on.

Related

Kernel API to know up address of interface

Is there any kernel side/space API to know the ip address of an interface , given it's name?
I think you're looking for rtnetlink (man page)
Rtnetlink allows the kernel's routing tables to be read and altered.
It is used within the kernel to communicate between various
subsystems, though this usage is not documented here, and for
communication with user-space programs. Network routes, IP addresses,
link parameters, neighbor setups, queueing disciplines, traffic
classes and packet classifiers may all be controlled through
NETLINK_ROUTE sockets.
According to strace, tt's the api ip addr show dev XXX uses:
strace ip addr sh dev lo 2>&1 | grep sendmsg
sendmsg(4, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=48, type=RTM_GETLINK, flags=NLM_F_REQUEST, seq=1596838225, pid=0}, {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0}, [{{nla_len=8, nla_type=IFLA_EXT_MASK}, 9}, {{nla_len=7, nla_type=IFLA_IFNAME}, "lo"}]}, iov_len=48}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 48
sendmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=40, type=RTM_GETLINK, flags=NLM_F_REQUEST, seq=1596838225, pid=0}, {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=if_nametoindex("lo"), ifi_flags=0, ifi_change=0}, {{nla_len=8, nla_type=IFLA_EXT_MASK}, 9}}, iov_len=40}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 40
However, it looks like a non-trivial api so if you don't need it often, it might be easier to just run ip addr sh dev XXX and parse the response.
Edit:
Looks like it's also possible using netdevice (man page), specifically, the SIOCGIFADDR ioctl:
SIOCGIFADDR, SIOCSIFADDR
Get or set the address of the device using ifr_addr. Setting the interface address is a privileged operation. For compatibility, only
AF_INET addresses are accepted or returned.
There's example code here

How to find the address of a not imported libc function when ASLR is on?

I have a 32bit elf program that I have to exploit remotely (for academic purposes).
The final goal is to spawn a shell. I have a stack that I can fill with any data I want and I can abuse one of the printf format strings. The only problem is that system/execv/execvp is not imported. The .got.plt segment is full of not-very-useful functions and I want to replace atoi with system because of how similar their signature is and the flow of the code indicates that that is the right function to replace. For the following attempts, I used IDA remote debug, so bad stack alignment and not proper format string is out of question. I wanted to make sure it is doable and apparently for me it isn't yet.
At first I tried to replace atoi#.got.plt with the unrandomized address of system. Got SIGSEGV.
Alright, it's probably because of ASLR, so let's try something else. I loaded up gdb and looked up system#0xb7deeda0 and atoi#0xb7de1250. Then I calculated the diff, which is 0xDB50. So the next time when I changed the address of atoi to system in the .got.plt segment, I actually just added diff to that value to get the address of system. Got SIGSEGV again.
My logic:
0xb7deeda0 <__libc_system>
0xb7de1250 <atoi>
diff = 0xb7deeda0 - 0xb7de1250
system#.got.plt = atoi#.got.plt + diff
example: 0x08048726 + DB50 = 0x08056276
Can anyone tell me what I did wrong and how can I jump to a "valid system()" with the help of leaking a function address from .got.plt?
Answering to my own question. Measuring the distance between functions in your
l̲o̲c̲a̲l̲ libc does not guarantee that the r̲e̲m̲o̲t̲e̲ libc will have the same alignment.
You have to find the libc version somehow, then you can get the address difference like so:
readelf -s /lib32/libc-2.19.so | grep printf
Possible ways to find the libc version if you know two addresses:
Libc binary collection
libcdb.com
pwnlib
... or you have access to the shell on the remote machine and can peek into the library with readelf yourself

Where did Wireshark/tcpdump/libpcap intercept packet inside Linux kernel?

According to this, wireshark is able to get the packet before it is dropped (therefore I cannot get such packets by myself). And I'm still wondering the exact location in linux kernel for wireshark to fetch the packets.
The answer goes as "On UN*Xes, it uses libpcap, which, on Linux, uses AF_PACKET sockets." Does anyone have more concrete example to use "AF_PACKET sockets"? If I understand wireshark correctly, the network interface card (NIC) will make a copy of all incoming packets and send it to a filter (berkeley packet filter) defined by the user. But where does this happen? Or am I wrong with that understanding and do I miss anything here?
Thanks in advance!
But where does this happen?
If I understood you correctly - you want to know, where is initialized such socket.
There is pcap_create function, that tries to determine type of source interface, creates duplicate of it and activates it.
For network see pcap_create_interface function => pcap_create_common function => pcap_activate_linux function.
All initialization happens in pcap_activate_linux => activate_new function => iface_bind function
( copy descriptor of device with handlep->device = strdup(device);,
create socket with socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)),
bind socket to device with bind(fd, (struct sockaddr *) &sll, sizeof(sll)) ).
For more detailed information read comments in source files of mentioned functions - they are very detailed.
After initialization all work happens in a group of functions such as pcap_read_linux, etc.
On Linux, you should be able to simply use tcpdump (which leverages the libpcap library) to do this. This can be done with a file or to STDOUT and you specify the filter at the end of the tcpdump command..

skb_dst() returns NULL

I'm trying to write a virtual netdevice driver on linux kernel 3.3.2. Some features of my driver need the route info when transmitting packets, so I use function skb_dst(struct sk_buff *) to get the dst_entry pointer. But whatever I do, wherever I ping, whenever I try, skb_dst() always returns NULL. I don't know why, and the bug confused me for more than a week. Can anyone help me?
I've found the reason! It's because of a flag added to kernel: IFF_XMIT_DST_RELEASE, if a virtual device is allocated with the flag set to 0, the kernel will drop the routing information when sending the sk_buff to the device. Thanks for Kristof Provost's reply all the same and sorry for ending the question so late.
Ping uses RAW sockets. They probably bypass part of the routing infrastructure.
Try looking at raw_send_hdrinc and raw_sendmsg in net/ipv4/raw.c
To be clear, add dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; to setup function

Is there a kernel module that returns exactly what a simple 'ifconfig' does?

I'm writing a kernel module that needs information about the local machine's interfaces just like the ones retuned by a simple 'ifconfig' command, I've searched a lot for it, but couldn't find anything
You can get all of that information through the struct net_device one way or another.
As Albert Veli said, you can get this struct net_device pointer using __dev_get_by_name().
If you tell us what information you need specifically we might even be able to point you to the correct fields.
Finding the MAC address is fairly simple:
struct net_device *dev = __dev_get_by_name("eth0");
dev->dev_addr; // is the MAC address
dev->stats.rx_dropped; // RX dropped packets. (stats has more statistics)
Finding the IP address is rather harder, but not impossible:
struct in_device *in_dev = rcu_dereference(dev->ip_ptr);
// in_dev has a list of IP addresses (because an interface can have multiple)
struct in_ifaddr *ifap;
for (ifap = in_dev->ifa_list; ifap != NULL;
ifap = ifap->ifa_next) {
ifap->ifa_address; // is the IPv4 address
}
(None of this was compile tested, so typos are possible.)
See for example the in6_dump_addrs function in net/ipv6/addrconf.c for how to get at addresses. For link properties like link layer address, see core/rtnetlink.c instead. ifconfig and its ioctls are obsolete (on Linux), so better don't think in terms of that now-bug-ridden program.

Resources