kernel module crashing on reading sock information
Hey guys,
Ive been writing a kernel module to print per socket per process tcp stats using tcp_get_info function. The issue is i can get until the sock structure...but later due to probably locking issues I am unable to get the module fully functional. It runs for about 10 minutes and then crashes off....Any help would be highly appreciated.
The function code is pasted below.
int process_tcpInfo(struct seq_file *s, struct task_struct *task){
struct file *fArray;
struct files_struct * files;
struct dentry *dPointer;
struct inode *iPointer;
struct socket *stPointer;
struct sock *skPointer;
//struct tcp_info* tiTcpInfo;
struct inet_sock *inSock;
u16 dport;
u16 sport;
u32 daddr;
u32 recvaddr;
int wscale;
int sack;
unsigned int hash;
struct inet_ehash_bucket *head;
struct fdtable *fdt=NULL;
struct tcp_info *tiTcpInfo;
unsigned long flags;
unsigned long readflags;
int i=0;
u8 rcv_wscale=0;
u8 snd_wscale=0;
tiTcpInfo=kmalloc(sizeof(struct tcp_info), GFP_KERNEL);
if (!tiTcpInfo ){ // fatal kernel allocation error
return -1;
}
if(task){
get_task_struct(task);
}
files=get_files_struct(task);
if(!files){
put_task_struct(task);
return 0;
}
//filp=fcheck_files(files, fd);
if(files){
//printk(KERN_INFO "seqtcpmod: reached line %d\n", __LINE__);
fdt = files_fdtable(files);
//printk(KERN_INFO "seqtcpmod: reached line %d\n", __LINE__);
}
if(fdt==NULL){
//printk(KERN_INFO "seqtcpmod: reached line %d\n", __LINE__);
put_files_struct(files);
put_task_struct(task);
return 0;
}
for(i=0;imax_fds;i++){
spin_lock_irqsave(&files->file_lock, flags);
fArray=rcu_dereference(fdt->fd[i]);
if(!fArray){
spin_unlock_irqrestore(&files->file_lock,flags);
break;
}
get_file(fArray);
dPointer = rcu_dereference(fArray->f_dentry);
if(dPointer == NULL){
spin_unlock_irqrestore(&files->file_lock,flags);
fput(fArray);
continue;
}
dPointer=dget(dPointer);
iPointer = rcu_dereference(dPointer->d_inode);
if(iPointer == NULL){
spin_unlock_irqrestore(&files->file_lock,flags);
put(dPointer);
fput(fArray);
continue;
}
igrab(iPointer);
stPointer=rcu_dereference(SOCKET_I(iPointer));
if(stPointer==NULL){
spin_unlock_irqrestore(&files->file_lock,flags);
iput(iPointer);
dput(dPointer);
fput(fArray);
continue;
}
skPointer=rcu_dereference(stPointer->sk);
if(skPointer == NULL){
spin_unlock_irqrestore(&files->file_lock,flags);
iput(SOCK_INODE(stPointer));
dput(dPointer);
fput(fArray);
continue;
}
spin_unlock_irqrestore(&files->file_lock,flags);
iput(SOCK_INODE(stPointer));
dput(dPointer);
fput(fArray);
// PROBLEM CAUSING IF BLOCK
if((stPointer->type == 1)&&((skPointer->sk_family==PF_INET)||(skPointer->sk_family==PF_INET6)||(skPointer->sk_family==AF_INET)||(skPointer->sk_family==AF_INET6))&& (skPointer)){
local_bh_disable();
head = inet_ehash_bucket(&tcp_hashinfo, hash);
read_lock_irqsave(&head->lock,readflags);
inSock=inet_sk(skPointer);
dport=ntohs(inSock->dport);
sport=ntohs(inSock->sport);
daddr=ntohl(inSock->daddr);
recvaddr=ntohl(inSock->rcv_saddr);
tcp_get_info(skPointer, tiTcpInfo);
read_unlock_irqrestore(&head->lock,readflags);
local_bh_enable();
if((tiTcpInfo->tcpi_options & TCPI_OPT_WSCALE )== TCPI_OPT_WSCALE){
wscale=1;
}else{
wscale=0;
}
if((tiTcpInfo->tcpi_options & TCPI_OPT_SACK )== TCPI_OPT_SACK){
sack=1;
}else{
sack=0;
}
rcv_wscale|=tiTcpInfo->tcpi_rcv_wscale;
snd_wscale|=tiTcpInfo->tcpi_snd_wscale;
if(tiTcpInfo!=NULL){
seq_printf(s,"%d %s %d %d %d %u:%hu %u:%hu %hd %hd %hd %hd %hd %hd %hd %hd %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n",task->pid, task->comm, i, wscale,sack,recvaddr,sport,daddr,dport, tiTcpInfo->tcpi_state, tiTcpInfo->tcpi_ca_state, tiTcpInfo->tcpi_retransmits, tiTcpInfo->tcpi_probes, tiTcpInfo->tcpi_backoff, tiTcpInfo->tcpi_options, snd_wscale, rcv_wscale, tiTcpInfo->tcpi_rto, tiTcpInfo->tcpi_ato, tiTcpInfo->tcpi_snd_mss, tiTcpInfo->tcpi_rcv_mss, tiTcpInfo->tcpi_unacked, tiTcpInfo->tcpi_sacked, tiTcpInfo->tcpi_lost, tiTcpInfo->tcpi_retrans, tiTcpInfo->tcpi_fackets, tiTcpInfo->tcpi_last_data_sent, tiTcpInfo->tcpi_last_ack_sent, tiTcpInfo->tcpi_last_data_recv, tiTcpInfo->tcpi_last_ack_recv, tiTcpInfo->tcpi_pmtu, tiTcpInfo->tcpi_rcv_ssthresh, tiTcpInfo->tcpi_rtt, tiTcpInfo->tcpi_rttvar, tiTcpInfo->tcpi_snd_ssthresh, tiTcpInfo->tcpi_snd_cwnd, tiTcpInfo->tcpi_advmss, tiTcpInfo->tcpi_reordering, tiTcpInfo->tcpi_rcv_rtt, tiTcpInfo->tcpi_rcv_space, tiTcpInfo->tcpi_total_retrans);
}
}
} // FOR LOOP ENDS HERE
put_files_struct(files);
put_task_struct(task);
kfree(tiTcpInfo);
return 1;
}