C Linux内核中遍历sk_write_队列时的Oops
我的Linux 3.8.8内核在内核中遍历tcp sk_write_队列时会出现Oops,如下所示:C Linux内核中遍历sk_write_队列时的Oops,c,linux,oop,tcp,kernel,C,Linux,Oop,Tcp,Kernel,我的Linux 3.8.8内核在内核中遍历tcp sk_write_队列时会出现Oops,如下所示: BUG: unable to handle kernel paging request at 00b85055 我在内核中的代码逻辑如下: 从套接字文件描述符获取结构套接字 从结构套接字获取结构套接字 锁紧袜子() 从struct sock获取sk_write_队列 遍历SKU写队列,读取链接skb缓冲区 松开_-sock() 返回用户空间 在步骤(5)中,有时会触发上述Oops,问题代码为:
BUG: unable to handle kernel paging request at 00b85055
我在内核中的代码逻辑如下:
skb_is_nonlinear(skb);
这意味着skb指针现在无效或为空,锁sock不能保护遍历过程吗
代码:
asmlong-sys\u-tcp\u-get(int-fd,int*id)
{
int-err,i,j;
结构套接字*sock;
结构sock*sk;
结构sk_buff_head*队列;
结构sk_buff*skb;
无符号字符buf[4]={0};
sock=sockfd_查找(fd和err);
if(sock==NULL)返回-1;
sk=sock->sk;
if(sk==NULL){
误差=-1;
转到自由_插座;
}
锁紧短袜(sk);
如果((1个sk_州)和建立了TCPF_)||
(sk->sk|U错误(sk->sk|U关闭和发送|U关闭))){
误差=-1;
转到释放插座;
}
队列=&(sk->sk_写入_队列);
如果(tcp_发送_头(sk)==NULL){
误差=-1;
转到释放插座;
}
对于(skb=tcp\u发送头(sk);skb!=(struct sk\u buff*)(队列);skb=skb->next){
if(skb_是非线性的(skb)){
误差=-1;
转到释放插座;
}
i=0;
j=0;
而(ilen){
buf[j++]=skb->data[i++];
如果(j==4){
if(buf[0]==1&&buf[1]==2&&buf[2]==3){
*id=buf[3];
误差=0;
转到释放插座;
}否则{
j=0;
}
}
}
}
释放U形插座:
释放袜子(sk);
自由U形插座:
短袜;
返回错误;
}
您能在这里发布您的代码吗?其中的细节可能很重要。我已经列出了上面的代码,skb_是非线性函数。
asmlinkage long sys_tcp_get(int fd, int *id)
{
int err, i, j;
struct socket *sock;
struct sock *sk;
struct sk_buff_head *queue;
struct sk_buff *skb;
unsigned char buf[4] = {0};
sock = sockfd_lookup(fd, &err);
if (sock == NULL) return -1;
sk = sock->sk;
if (sk == NULL) {
err = -1;
goto free_socket;
}
lock_sock(sk);
if (((1 << sk->sk_state) & ~TCPF_ESTABLISHED) ||
(sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))) {
err = -1;
goto release_socket;
}
queue = &(sk->sk_write_queue);
if (tcp_send_head(sk) == NULL) {
err = -1;
goto release_socket;
}
for(skb = tcp_send_head(sk); skb != (struct sk_buff *)(queue); skb = skb->next) {
if (skb_is_nonlinear(skb)) {
err = -1;
goto release_socket;
}
i = 0;
j = 0;
while(i < skb->len) {
buf[j++] = skb->data[i++];
if (j == 4) {
if (buf[0] == 1 && buf[1] == 2 && buf[2] == 3) {
*id = buf[3];
err = 0;
goto release_socket;
} else {
j = 0;
}
}
}
}
release_socket:
release_sock(sk);
free_socket:
sockfd_put(sock);
return err;
}