Seg fault error in C - c

Getting seg-fault when I run this code. I commented where I'm getting the seg-fault (in handler() function). I'm not sure, may be I'm wrapping data twice that's why or what's the problem? It's printing correctly till "start_timer" method.
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
typedef struct _data{
char *name;
}data;
struct timer_list{
void* timer_data;
unsigned long expires;
void (*function)(sigval_t);
};
volatile long int second = 0;
void handler(sigval_t val)
{
data *data_handler = val.sival_ptr;
printf("Handler: address of data: %p\n", data_handler);
printf("Handler: address of &data_handler->name: %p\n", &data_handler->name);
printf("Handler entered with value :%s\n", data_handler->name); `**//**SEG-FAULT HERE****`
}
void timer_handler(union sigval val)
{
printf(" ----- Seconds: %ld\n", ++second);
}
/* start timer with all we got as data is timer */
void start_timer(struct timer_list *timer)
{
printf("\nStart_timer...: Timer->data address: %p\n", timer->timer_data);
data *data_handler = timer->timer_data;
printf("Start_timer...: entered with value :%s\n", data_handler->name);
int Ret;
pthread_attr_t attr;
pthread_attr_init( &attr );
//pthread_t tid;
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sigval_t val;
val.sival_ptr = timer->timer_data;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = timer->function;
// sig.sigev_value.sival_int = val;
sig.sigev_value = val;
sig.sigev_notify_attributes = &attr;
data *data_handler1 = (data *)val.sival_ptr;
printf("From sigval...: handler_data address: %p\n", data_handler1);
printf("From sigval...: handler_data->name address: %p\n", &data_handler1->name);
printf("From sigval...: Handler entered with value :%s\n", data_handler1->name);
//create a new timer.
timer_t timerid;
Ret = timer_create(CLOCK_REALTIME, &sig, &timerid);
if (Ret == 0)
{
struct itimerspec in, out;
in.it_value.tv_sec = timer->expires;
in.it_value.tv_nsec = 0;
in.it_interval.tv_sec = 0;
in.it_interval.tv_nsec = 0;
timer_settime(timerid, 0, &in, &out);
}
}
/* Start_timer_on: wrapping up data into one timer structure, and starting timer */
void start_timer_on(data timer_data, unsigned long expires)
{
struct timer_list *timer = (struct timer_list *)malloc(sizeof(struct timer_list)); //Problem was here ... forgot to use malloc
timer->timer_data = &timer_data;
printf("\nTimer->data address: %p\n", &timer_data);
timer->function = handler;
timer->expires = expires;
start_timer(timer);
}
/* Main */
void main()
{
data handler_data1 = {"Handler Data 1"};
//data handler_data2 = {"Handler Data 2"};
//void *data1 = &handler_data1;
//void *data2 = &handler_data2;
pthread_attr_t attr;
pthread_attr_init( &attr );
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = timer_handler;
sig.sigev_notify_attributes = &attr;
//create a new timer - clock.
timer_t timerid;
timer_create(CLOCK_REALTIME, &sig, &timerid);
struct itimerspec in, out;
in.it_value.tv_sec = 1;
in.it_value.tv_nsec = 0;
in.it_interval.tv_sec = 1;
in.it_interval.tv_nsec = 0;
printf("*** *** *** Main clock starts *** *** ***\n");
timer_settime(timerid, 0, &in, &out);
printf("***** Start timer for data1 for 2 sec *****\n");
start_timer_on(handler_data1, 2);
// printf("***** Start timer for data1 for 5 sec *****\n");
// start_timer(data2, 5);
sleep(20);
}

This might be the problem. In the code below, timer_data is local to function start_timer_on. The object is destroyed as soon as the function exits. So, when accessing the name in handler, it will segfault.
void start_timer_on(data timer_data, unsigned long expires)
{
struct timer_list *timer;
timer->timer_data = &timer_data;
printf("\nTimer->data address: %p\n", &timer_data);
timer->function = handler;
timer->expires = expires;
start_timer(timer);
}
You should use void start_timer_on(data *timer_data, unsigned long expires), so that the data is not freed until main exits.

Related

Implementing bcc's killsnoop in C

I'm trying to implement the killsnoop.py program in bcc in C. When executing the program, I'm getting a failed to load: -13 error. Can someone help me to debug this?
Note: For compilation, I've taken the libbpf-bootstrap example from Andrii Nakryiko's blog post.
Error message:
Below is the program that I've used.
killsnoop.bpf.c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "killsnoop.h"
struct val_t {
__u32 uid;
__u32 pid;
int sig;
int tpid;
char comm[TASK_COMM_LEN];
};
struct data_t {
__u32 uid;
__u32 pid;
int tpid;
int sig;
int ret;
char comm[TASK_COMM_LEN];
};
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32);
__type(value, struct val_t);
__uint(max_entries, 10240);
} info_map SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32);
__type(value, struct data_t);
__uint(max_entries, 10240);
} event SEC(".maps");
SEC("kprobe/__x64_sys_kill")
int entry_probe(struct pt_regs *ctx, int tpid, int sig) {
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32) pid_tgid;
__u64 uid_gid = bpf_get_current_uid_gid();
__u32 uid = (__u32) uid_gid;
struct val_t val = {
.uid = uid,
.pid = pid
};
if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
val.tpid = tpid;
val.sig = sig;
bpf_map_update_elem(&info_map, &tid, &val, BPF_ANY);
}
return 0;
}
SEC("kretprobe/__x64_sys_kill")
int return_probe(struct pt_regs *ctx) {
struct data_t data = {};
struct val_t *valp;
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32) pid_tgid;
valp = bpf_map_lookup_elem(&info_map, &tid);
if (!valp) {
return 0; // missed entry
}
bpf_core_read(&data.comm, sizeof(data.comm), valp->comm);
data.pid = pid;
data.tpid = valp->tpid;
data.ret = PT_REGS_RC_CORE(ctx);
data.sig = valp->sig;
data.uid = valp->uid;
bpf_perf_event_output(ctx, &event, BPF_F_CURRENT_CPU, &data, sizeof(data));
bpf_map_delete_elem(&info_map, &tid);
return 0;
}
killsnoop.c
#include <signal.h>
#include "killsnoop.skel.h"
#include "killsnoop.h"
#define OUTPUT_FORMAT "%lld %d %d %s %d %d"
#define PERF_POLL_TIMEOUT_MS 10
#define PERF_BUFFER_PAGES 64
static volatile int shutdown = 0;
static void sig_int(int signal) {
shutdown = 1;
}
void handle_event(void *ctx, int cpu, void *data, u32 data_size) {
const struct event *e = data;
time_t curr_time;
time(&curr_time);
printf(OUTPUT_FORMAT, (long long) curr_time, e->pid, e->tpid, e->comm, e->sig, e->uid);
}
void handle_lost_event(void *ctx, int cpu, u64 lost_cnt) {
fprintf(stderr, "Lost %llu events on CPU #%d!\n", lost_cnt, cpu);
}
int main(int argc, char **argv) {
int err;
struct perf_buffer *perfBuffer;
struct killsnoop_bpf *obj;
obj = killsnoop_bpf__open_and_load();
if (!obj) {
fprintf(stderr, "failed to open/load BPF skeleton!");
goto cleanup;
}
err = killsnoop_bpf__attach(obj);
if (err) {
fprintf(stderr, "failed to attach BPF programs\n");
goto cleanup;
}
perfBuffer = perf_buffer__new(bpf_map__fd(obj->maps.info_map), PERF_BUFFER_PAGES, handle_event, handle_lost_event,
NULL, NULL);
if (!perfBuffer) {
err = -errno;
fprintf(stderr, "failed to open perf buffer: %d\n", err);
goto cleanup;
}
if (signal(SIGINT, sig_int) == SIG_ERR) {
fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
err = 1;
goto cleanup;
}
while (!shutdown) {
err = perf_buffer__poll(perfBuffer, PERF_POLL_TIMEOUT_MS);
if (err < 0 && err != -EINTR) {
fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err));
goto cleanup;
}
/* reset err to return 0 if exiting */
err = 0;
}
cleanup:
perf_buffer__free(perfBuffer);
killsnoop_bpf__destroy(obj);
return err != 0;
}
killsnoop.h
#define TASK_COMM_LEN 16
typedef unsigned int u32;
typedef unsigned long long u64;
struct event {
u32 uid;
u32 pid;
int tpid;
int sig;
int ret;
char comm[TASK_COMM_LEN];
};
BCC tends to do a little bit of background magic which allows you to use the arguments of the attachment point directly in your eBPF program like you are doing:
entry_probe(struct pt_regs *ctx, int tpid, int sig)
However, this is BCC specific. With libbpf you have to use the BPF_KPROBE_SYSCALL macro to get similar behavior. For example: https://elixir.bootlin.com/linux/v5.18.14/source/tools/testing/selftests/bpf/progs/bpf_syscall_macro.c#L68
In your case:
SEC("kprobe/" SYS_PREFIX "sys_kill")
int BPF_KPROBE_SYSCALL(entry_probe, int tpid, int sig) {
...
The reason you are getting this error is because all arguments are saves to the stack once the BPF program is entered. Thus the program attempts to write R3 which is int sig in this case to the stack. But R3 is not defined, only R1 is which is the ctx. And you are not allowed to read from uninitialized registers hence the R3 !read_ok error.

Pass argument to thread

I'm doing my assignment about thread. I need to do 3 thread, first compute temperature value, second compute pressure value and third thread, I need to pass those value and display it. But when I'm compile, I got segmentation fault (core dumped). I need to pass the argument but doesn't know where I did wrong. Can someone help me?
This is my code
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
struct param_t_p{
int temperature;
int LOWER_TEMP_BOUND,UPPER_TEMP_BOUND;
float pressure;
float LOWER_PRESURE_BOUND,UPPER_PRESURE_BOUND;
};
void timespec_add_us (struct timespec *t, long us)
{
t->tv_nsec += us*1000;
while (t->tv_nsec > 1000000000)
{
t->tv_nsec = t->tv_nsec - 1000000000;// + ms*1000000;
t->tv_sec += 1;
}
}
void *temp (void* args)
{
struct param_t_p *ps = (struct param_t_p *)args;
struct timespec time;
clock_gettime (CLOCK_REALTIME, &time);
while (1)
{
timespec_add_us(&time, 4000000);
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME,&time, NULL);
ps->temperature = ps->LOWER_TEMP_BOUND + (int)(ps->UPPER_TEMP_BOUND*rand()/(RAND_MAX+1.0));
printf("First thread for temperature is done\n\n");
}
return NULL;
}
void *press (void* args)
{
struct param_t_p *ps = (struct param_t_p *)args;
struct timespec time;
clock_gettime (CLOCK_REALTIME, &time);
while (1)
{
timespec_add_us(&time, 4000000);
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME,&time, NULL);
ps->pressure = ps->LOWER_PRESURE_BOUND +( int)(ps->UPPER_PRESURE_BOUND*rand()/(RAND_MAX+1.0));
printf("Second thread for temperature is done\n\n");
}
return NULL;
}
void *display (void* args)
{
struct param_t_p *ps = (struct param_t_p *)args;
struct timespec time;
clock_gettime (CLOCK_REALTIME, &time);
while (1)
{
timespec_add_us(&time, 4000000);
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME,&time, NULL);
printf("Value for Temperature and Pressure\n");
printf(" Temperature : %d°C\n", ps->temperature);
printf(" Pressure : %.2fPa\n", ps->pressure);
printf("Third thread is done\n\n");
}
return NULL;
}
int main()
{
pthread_t th1,th2,th3;
pthread_att_t attr;
struct sched_param param1, param2, param3;
struct param_t_p data;
data.LOWER_TEMP_BOUND=20;
data.UPPER_TEMP_BOUND=40;
data.LOWER_PRESURE_BOUND=31.5;
data.UPPER_PRESURE_BOUND=32.5;
data.temperature;
data.pressure;
printf("Process ID: %d\n\n", getpid());
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
param1.sched_priority = 1;
param2.sched_priority = 2;
param3.sched_priority = 3;
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedparam(&attr, &param1);
pthread_create(&th1, &attr, temp, &data);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedparam(&attr, &param2);
pthread_create(&th2, &attr, press, &data);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedparam(&attr, &param3);
pthread_create(&th3, &attr, display, &data);
pthread_attr_destroy(&attr);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_join(th3, NULL);
}
I need to solve it as soon as possible. Thank you in advance

C, timer_settime, disarm timer and overwrite associated data?

I have to do for University a project about UDP, where i have to guarantee reliable communication; for packets, i want use timer_gettime() and timer_Settime() functions, because i can queue signals and i can associate to them a timer; in particular, struct sigevent has a field which union sigval where i can pass value to handler when signal arrived; I would like to take advantage of this passing to handler number of packets for which timer expired; I have a problem, and I've done a simple program to verify this; when I start timer, i can disarm it setting it_value of struct sigevent to 0; but data doesn't change; if I send 100 signal, header receives only data of first signal. This is my code:
#include <signal.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int d;
void err_exit(char* str)
{
perror(str);
exit(EXIT_FAILURE);
}
void sighandler(int sig, siginfo_t *si, void *uc)
{
(void) sig;
(void) uc;
d = si->si_value.sival_int;
}
void handle_signal(struct sigaction* sa)
{
sa->sa_flags = SA_SIGINFO;
sa->sa_sigaction = sighandler;
sigemptyset(&sa->sa_mask);
if (sigaction(SIGRTMAX,sa,NULL) == -1)
err_exit("sigaction");
}
void create_timer(struct sigevent* sev,timer_t* timer_id,int i)
{
union sigval s;
s.sival_int = i;
printf("value: %d\n",i);
sev->sigev_notify = SIGEV_SIGNAL;
sev->sigev_signo = SIGRTMAX;
sev->sigev_value = s;
timer_create(CLOCK_REALTIME,sev,timer_id);
}
void set_timer(timer_t timer_id,struct itimerspec* ts)
{
if(ts == NULL)
printf("itimerspec null\n");
if (timer_settime(timer_id, 0, ts, NULL) == -1){
printf("errno code: %d\n",errno);
err_exit("timer_settime");
}
}
void initialize_timerspec(struct itimerspec* ts)
{
ts->it_value.tv_sec = 2;
ts->it_value.tv_nsec = 5;
ts->it_interval.tv_sec = 0;
ts->it_interval.tv_nsec = 0;
}
void reset_timer(timer_t timer_id, struct itimerspec* ts)
{
ts->it_value.tv_sec = 0;
ts->it_value.tv_nsec = 0;
ts->it_interval.tv_sec = 0;
ts->it_interval.tv_nsec = 0;
if (timer_settime(timer_id, 0, ts, NULL) == -1){
printf("errno code: %d\n",errno);
err_exit("timer_settime");
}
}
int main()
{
struct sigaction sa;
struct itimerspec ts[2];
struct sigevent sev[2];
timer_t timer_id[2];
handle_signal(&sa);
create_timer(sev,timer_id,0);
initialize_timerspec(ts);
set_timer(timer_id,ts);
reset_timer(timer_id,ts);
create_timer(sev + 1,timer_id + 1,1);
initialize_timerspec(ts + 1);
set_timer(timer_id,ts + 1);
printf("id1: %ju id2: %ju\n",timer_id[0],timer_id[1]);
sleep(10);
printf("d = %d\n",d);
exit(EXIT_SUCCESS);
}
I disarm first timer, and send another signal; but handler receives data associated to first signal, because it prints 0. Is there a way to send to overwrite data, sending to handler data of second signal(in this case 1)?

Error in receving data from kernel using netlink at user-space

I writing a kernel module which accepts data(form of a structure) and passes back some data(same structure format) to the user-space. I can successfully receive the message from user but i get segmentation fault while i try tp dereference some of the members of the structure of the data received from kernel. I am using netlink socket API.
Sample code is as below:
user-space.c
#define NETLINK_USER 27
#define MAX_PAYLOAD 10000 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
Response *p;
Response *req;
test r1;
test r2;
int main()
{
char *data;
data = malloc(4096 * sizeof(char));;
data = "data from user";
sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if(sock_fd<0)
return -1;
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_LENGTH(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
p = malloc(2*sizeof(Response));
p[0].index = 1;
p[0].dataSize = 2;
p[0].data = data;
p[0].test2 = 3;
p[0].test3 = 4;
p[0].test4 = 5;
r1.t = 10;
r1.ip_addr = malloc(50*sizeof(char));
r1.ip_addr = "192.168.10.2";
p[0].test = &r1;
/* Extra for testing */
p[1].index = 2;
p[1].dataSize = 3;
//strcpy(p[1].data , "Data2 from User");
p[1].data = data;
p[1].test2 = 4;
p[1].test3 = 5;
p[1].test4 = 6;
r2.t = 20;
r2.ip_addr = malloc(50*sizeof(char));
r2.ip_addr = "192.168.20.2";
p[1].test = &r2;
memcpy(NLMSG_DATA(nlh), (void *)p, 2 * sizeof(*p));
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Sending message to kernel\n");
sendmsg(sock_fd,&msg,0);
printf("Waiting for message from kernel\n");
/* Read message from kernel */
//recvmsg(sock_fd, &msg, 0);
req = (Response*)NLMSG_DATA(nlh);
printf("Recieved from Kernel:\n");
printf("index %d\n", req[0].index);
printf("dataSize %d\n", req[0].dataSize);
printf("data: %s\n", req[0].data); <---Segmentation fault from here
printf("test2 %d\n", req[0].test2);
printf("test3 %d\n", req[0].test3);
printf("test4 %d\n", req[0].test4);
printf("contents of test structure are %d,%s\n",req[0].test->t,req[0].test->ip_addr); <-----Segmentation fault
close(sock_fd);
Kernel_module.c
#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#define NETLINK_USER 27
struct sock *nl_sk = NULL;
typedef struct _Response Response;
typedef struct _test test;
struct _test{
int t;
char *ip_addr;
};
struct _Response
{
int index;
int dataSize;
char *data;
int test2;
int test3;
int test4;
test *test;
};
static void hello_nl_recv_msg(struct sk_buff *skb) {
struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
int res;
Response *req;
Response *req1;
test t;
t.t = 1;
t.ip_addr = kmalloc(50*sizeof(char), GFP_KERNEL);
t.ip_addr = "129.63.45.1";
req1 = (Response *)kmalloc_array(2, sizeof(Response), GFP_KERNEL);
char *data;
data = kmalloc(4096 * sizeof(char), GFP_KERNEL);
data = "data from kernel";
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
msg_size= 2 * sizeof(*req1);
req1[0].index = 100;
req1[0].dataSize = 100;
req1[0].data = data;
req1[0].test2 = 100;
req1[0].test3 = 100;
req1[0].test4 = 100;
req1[0].test = &t;
printk("Sending to Userspace:\n");
/*Second set of message*/
req1[1].index = 102;
req1[1].dataSize = 103;
//strcpy(req1[1].data , "Data from Kernel");
req1[1].data = data;
req1[1].test2 = 100;
req1[1].test3 = 100;
req1[1].test4 = 100;
req1[1].test = &t;
nlh=(struct nlmsghdr*)skb->data;
req = (Response *)NLMSG_DATA(nlh); <--message received from user-space
printk("Recieved from Userspace:\n");
printk("index %d\n", req[0].index);
printk("dataSize %d\n", req[0].dataSize);
printk("data: %s\n", req[0].data);
printk("test2 %d\n", req[0].test2);
printk("test3 %d\n", req[0].test3);
printk("test4 %d\n", req[0].test4);
printk("contents of test are %d, %s\n",req[0].test->t,req[0].test->ip_addr);
printk("Next set of data\n");
printk("Recieved from Userspace:\n");
printk("index %d\n", req[1].index);
printk("dataSize %d\n", req[1].dataSize);
printk("data: %s\n", req[1].data);
printk("test2 %d\n", req[1].test2);
printk("test3 %d\n", req[1].test3);
printk("test4 %d\n", req[1].test4);
printk("contents of test are %d, %s\n",req[1].test->t,req[1].test->ip_addr);
pid = nlh->nlmsg_pid; /*pid of sending process */
skb_out = nlmsg_new(10000,0);
if(!skb_out)
{
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
nlh=nlmsg_put(skb_out,0,0,NLMSG_DONE,10000,0);
NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */
/*End of second set*/
memcpy(NLMSG_DATA(nlh), req1, 2 * sizeof(*req1));
res=nlmsg_unicast(nl_sk,skb_out,pid);
if(res<0)
printk(KERN_INFO "Error while sending bak to user\n");
}
static int __init hello_init(void) {
printk("Entering: %s\n",__FUNCTION__);
struct netlink_kernel_cfg cfg = {
.input = hello_nl_recv_msg,
};
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
if(!nl_sk)
{
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
module_init(hello_init); module_exit(hello_exit);
MODULE_LICENSE("GPL");
}
global.h
#ifndef __GLOBAL_H
#define __GLOBAL_H
typedef struct _Response Response;
typedef struct _test test;
struct _test{
int t;
char *ip_addr;
};
struct _Response
{
int index;
int dataSize;
char *data;
int test2;
int test3;
int test4;
test *test;
};
#endif
Basically the problem is with the pointers. If i use char data[4096] instead of character pointer, i receive the message. But i get segmentation fault while dereferencing the test structure. How to resolve this issue?
Thanks
This code is very wrong and full critique is likely unnecessary, so I'll just point out 2 most obvious types of violations.
char *data;
data = kmalloc(4096 * sizeof(char), GFP_KERNEL);
data = "data from kernel";
First a nit: sizeof(char) is guaranteed to be 1. The real problem though is that this instantly overwrites the value of data, losing the pointer returned by malloc. This is present in multiple places in the code.
req = (Response *)NLMSG_DATA(nlh); <--message received from user-space
printk("Recieved from Userspace:\n");
printk("index %d\n", req[0].index);
printk("dataSize %d\n", req[0].dataSize);
printk("data: %s\n", req[0].data);
This code, while likely "works", is completely wrong. The userspace buffer (.data) cannot be safely accessed in this manner and on some architectures it cannot be accessed at all. It may "work" because the complete address space is divided into both the kernel and userspace and the kernel in principle has access there. Problems arise if the pointer is to something totally bogus or within the kernel, or maybe to something unmapped.
The userspace portion of the code tries to do a reverse trick and unsurprisingly that fails -- you can't access kernel memory or there would be no security whatsoever.
The problem only arises because the protocol is wrong. You should have a buffer allocated in userspace and a variable holding its size. Then you can tell the kernel where to put data (and how much tops).
Either way, I think you are not ready for kernel work at this point and as such strongly suggest sticking to userspace for the time being.

Non blocking timer in linux user space (in C)

Actually I want to implement non-blocking timer, when the timer expires a handler will be called and will do something (for now it prints data). I google and realized that timer_create, timer_settimer are non-blocking timer. BUT still I've issue, I have to wait for my timer to expire (sleep(MAX) or while(1) {;}). But then if I'm calling my start_timer method with different "expiry" time, it should work accordingly, should not block other. e.g. here first time I'm calling timer, and expecting to call handler in 5 sec but before that 2nd call should print its data as, that interval I've given is 1sec only. And of course its not behaving same. Any idea?
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
typedef struct _data{
char *name;
}data;
void handler(union sigval val)
{
data *data_handler = val.sival_ptr;
printf("Handler entered with value :%s\n", data_handler->name);
}
void mod_timer(timer_t timerid, struct sigevent sig, struct itimerspec in, struct itimerspec out)
{
printf("mod_timer\n");
timer_settime(timerid, 0, &in, &out);
while(1)
sleep(1);
//delete the timer.
timer_delete(timerid);
}
void start_timer(void* val, int interval)
{
int Ret;
pthread_attr_t attr;
pthread_attr_init( &attr );
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = handler;
// sig.sigev_value.sival_int = val;
sig.sigev_value.sival_ptr = val;
sig.sigev_notify_attributes = &attr;
//create a new timer.
timer_t timerid;
Ret = timer_create(CLOCK_REALTIME, &sig, &timerid);
if (Ret == 0)
{
struct itimerspec in, out;
in.it_value.tv_sec = 1;
in.it_value.tv_nsec = 0;
in.it_interval.tv_sec = interval;
in.it_interval.tv_nsec = 0;
mod_timer(timerid, sig, in, out);
}
}
void main()
{
// start_timer(1, 5);
// start_timer(2, 1);
data handler_data1 = {"Handler Data 1"};
data handler_data2 = {"Handler Data 2"};
void *data1 = &handler_data1;
void *data2 = &handler_data2;
start_timer(data1, 5);
start_timer(data2, 1);
}
You can use the alarm function to generate a signal, and the signal function to specify the handler to that signal.

Resources