linux header file how to edit gcc code - linux

my vm system is ubuntu 16.04, and i have download the kernel header files,i have write the code,but don't know how to edit gcc code or Makefile
#include <linux/netdevice.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(){
struct net_device *dev = dev_base;
struct in_device *mydevice;
struct in_ifaddr *myifaddr;
while( dev != NULL ){
printf("dev name: %s\n", dev->name);
mydevice = dev->ip_ptr;
myifaddr = mydevice->ifa_list;
while(myifaddr != NULL){
printf("ip: %s\n", inet_ntoa((struct in_addr)(myifaddr->ifa_local)));
myifaddr = myifaddr->ifa_next;
}
dev = dev->next;
}
return 0;
}
if i use gcc test.c it will come out some error like this
yq#ubuntu:~/test$ gcc test.c
In file included from /usr/include/linux/netdevice.h:28:0,
from test.c:1:
/usr/include/linux/if.h:234:19: error: field ‘ifru_addr’ has incomplete type
struct sockaddr ifru_addr;
^
......
test.c: In function ‘main’:
test.c:8:27: error: ‘dev_base’ undeclared (first use in this function)
struct net_device *dev = dev_base;

Related

Duration of child process sleep

Is it possible to determine in Linux as a parent process how much time a child process sleeps, whenever it sleeps using the nanosleep() system call?
Thanks!
You can wrap glibc:
% gcc -fPIC -shared -o nanosleep.so nanosleep.c -ldl
% export LD_PRELOAD=/path/to/your/nanosleep.so /path/to/app/using/test
Wrapper code nanosleep.c:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
int (*real_nanosleep)(const struct timespec *req, struct timespec *rem) = NULL;
/* wrapping nanosleep function call */
int nanosleep(const struct timespec *req, struct timespec *rem)
{
printf("How much %d used\n", req->tv_nsec);
/* Fetch the real nanosleep function from glibc */
real_nanosleep = dlsym(RTLD_NEXT, "nanosleep");
return real_nanosleep(req, rem);
}
Test program test.c:
#include <stdio.h>
#include <time.h>
int main () {
struct timespec req = {0}, rem = {0};
req.tv_sec = 2;
req.tv_nsec = 1000000000;
nanosleep(&req, &rem);
return(0);
}

error:argument type 'xx' is incomplete for hiding call to ptrace example code

I'm testing an antidebug solution with ptrace method; and i compile the program by using ndk21e cross-compile.
The problem is that it compiles successfully with gcc, but fails with ndk cross-compile.
ndk cross-compile compiles all other programs without problems
#include <stdlib.h>
#include <stdio.h>
#include<sys/ptrace.h>
#include <dlfcn.h>
#include <string.h>
int main(int argc, char **argv) {
void *handle;
long (*go)(enum __ptrace_request request, pid_t pid);
// get a handle to the library that contains 'ptrace'
handle = dlopen ("/lib/x86_64-linux-gnu/libc.so.6", RTLD_LAZY);
// reference to the dynamically-resolved function 'ptrace'
go = dlsym(handle, "ptrace");
if (go(PTRACE_TRACEME, 0) < 0) {
puts("being traced");
exit(1);
}
puts("not being traced");
// cleanup
dlclose(handle);
return 0;
}
And it shows the error like the picture as follow:
gcc compileresult and cross-compile error result
How can i solve this problem. Thanks.

how to insmod my netfilter module in ubuntu 18.04

I try to write a simple linux module based on netfilter hooks. My code (pcap.c) is shown as follows:
#include <linux/time.h>
#include <linux/init.h>
#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/netfilter_ipv4.h>
#include <linux/net.h>
#include <net/ip.h>
#include <linux/if_ether.h>
#include <net/protocol.h>
#include <net/icmp.h>
#include <net/tcp.h>
#include <linux/if_vlan.h>
struct net *net;
static unsigned int pcap_func (void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
printk(KERN_INFO "hook\n");
return NF_DROP;
}
static struct nf_hook_ops nfho = {
.hook = pcap_func,
.hooknum = 1,
.pf = PF_INET,
.priority = NF_IP_PRI_FIRST,
};
static int __init pcap_init(void)
{
if (nf_register_net_hook(net, &nfho)) {
printk(KERN_ERR "nf_register_hook() failed\n");
return -1;
}
return 0;
}
static void __exit pcap_exit(void)
{
printk(KERN_INFO "unregister pcap module.\n");
nf_unregister_net_hook(net, &nfho);
}
module_init(pcap_init);
module_exit(pcap_exit);
MODULE_LICENSE("GPL");
My makefile is shown as follows:
obj-m := pcap.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
install:
insmod pcap.ko
uninstall:
-rmmod pcap.ko
rm -rf *.o *.ko *.mod.o *.mod.c *.symvers *.order *.mod
I cannot insmod my module.
And the dmesg shows:
Netfilter: version magic '4.18.11 SMP mod_unload ' should be '5.3.0-59-generic SMP mod_unload '
I cannot fix this problem. Please help me. Thanks a lot.
I fixed the problem. The problem is caused because of the namespace of network device. At first, we should delete the following code:
struct net *net;
Then correct the nf_register_net_hook and nf_unregister_net_hook functions as follows:
nf_register_net_hook(&init_net, &nfho);
nf_unregister_net_hook(&init_net, &nfho);
My final code is shown as follows:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
static struct nf_hook_ops *nfho = NULL;
unsigned int hook_func(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
printk(KERN_INFO "hook\n");
return NF_DROP;
}
static int __init pcap_init(void)
{
nfho = (struct nf_hook_ops*) kcalloc(1, sizeof(struct nf_hook_ops), GFP_KERNEL);
nfho->hook = (nf_hookfn*) hook_func;
nfho->hooknum = NF_INET_PRE_ROUTING;
nfho->pf = PF_INET;
nfho->priority = NF_IP_PRI_FIRST;
nf_register_net_hook(&init_net, nfho);
return 0;
}
static void __exit pcap_exit(void)
{
nf_unregister_net_hook(&init_net, nfho);
kfree(nfho);
}
module_init(pcap_init);
module_exit(pcap_exit);

LINUX_VERSION_CODE where the value from?

I just make a mistake about the macro LINUX_VERSION_CODE.
Here is what I want to do,when execute the code,the code run different branch due to the machine ,which is running.
I just realized,the result is not change,since I compile my code always in the same server.For example I compile the belw code in kernel version of 2.6.18,then the LINUX_VERSION_CODE marco is always 132626 .
If there is any way ,let the run different branch due to the version of which it runs?
#include <stdio.h>
#include <linux/version.h>
int main()
{
printf("kernel version(2.6.32) = %d\n",KERNEL_VERSION(2,6,32));
printf("LINUX_VERSION_CODE = %d\n",LINUX_VERSION_CODE);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
printf("Hello,world.\n");
#else
printf("Fine,thank you.\n");
#endif
return 0;
}
So you want to run a different code depending on kernel version. But you don't want to decide on that using a compile time constant - you want that at runtime.
Nothing simpler, but a call to uname:
#include <sys/utsname.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
struct utsname name;
if (uname(&name)) {
fprintf(stderr, "Uname failed!\n");
exit(-1);
}
printf("%s\n", name.release);
if (!memcmp(&name.release, "4.18.9-", sizeof("4.18.9-") - 1)) {
printf("Och, kernel 4.18.9 found!\n");
} else {
printf("Och, you've got a different kernel...\n");
}
}
On my machine:
$ cat 1.c | gcc -xc - && ./a.out
4.18.9-arch1-1-ARCH
Och, kernel 4.18.9 found!
On my friends machine:
cat 1.c | ssh friend 'gcc -xc - && ./a.out'
4.12.14-lp150.11-default
Och, you've got a different kernel...
I will leave it to the OP, to call strtoll or sscanf(&name.release, "%d.%d.%d-", &major, &minor, &release) to get the kernel version as integer number.
But you can get way more hardcore than that. On runtime, you can just do anything, so just read the content of /usr/include/linux/version.h file:
#define _GNU_SOURCE 1
#include <linux/version.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE *f;
f = fopen("/usr/include/linux/version.h", "r");
if (f == NULL) return -__LINE__;
char *line = NULL;
size_t linelen = 0;
char *found = NULL;
while (getline(&line, &linelen, f) > 0) {
if ((found = strstr(line, "LINUX_VERSION_CODE")) != NULL) {
break;
}
}
if (found == NULL) return -__LINE__;
fclose(f);
found += sizeof("LINUX_VERSION_CODE") - 1;
errno = 0;
const long long kv = strtoll(found, NULL, 10);
if (errno) return -__LINE__;
free(line);
printf("%ld.%ld.%ld\n", kv>>16&0xff, kv>>8&0xff, kv&0xff);
if (kv > KERNEL_VERSION(4,17,0)) {
printf("Och, kernel api greater then 4.17.0 found!\n");
} else {
printf("Och, kernel api below 4.17.0 found!\n");
}
}
And on my machine this outputs:
$ cat 1.c | gcc -xc - && ./a.out
4.17.11
Och, kernel api greater then 4.17.0 found!
And on my friends:
$ cat 1.c | ssh friend 'gcc -xc - && ./a.out'
4.15.0
Och, kernel api below 4.17.0 found!
We can also see, that uname -a != grep "LINUX_VERSION_CODE" /usr/include/linux/version.h.

How can I get rq structure in linux kernel?

I made a linux module program to get rq structure in CPU like this
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <../kernel/sched/sched.h>
int init_hello(void)
{
int cpu;
for_each_online_cpu(cpu)
{
struct rq *rq = cpu_rq(cpu)
printk( KERN_ALERT "rq->curr->pid = %d", rq->curr->pid);
}
}
...
Both 'Makefile' and 'insmod hello.ko' are done, But I got a error message like this
...
[30557.012624] hello: Unknown symbol runqueues (err 0)
How can I solve this problem?

Resources