質問

プロジェクトの場合、LinuxカーネルスペースからUDPパケットを送信しようとしています。現在、コードをカーネルに「ハードコーディング」していますが(これは最良/最も近い方法ではありません)、簡単なテストを実行しようとしています(" TEST"を送信)。カーネルハッキングの初心者であることに言及する必要があります-私は多くの原則とテクニックに固執しているわけではありません!

コードを実行するたびにシステムがハングし、再起動する必要があります-マウス/キーボードの応答がなく、スクロールとキャップロックのキーライトが一緒に点滅します-これが何を意味するのか分かりませんが、カーネルパニック?

このテストコードではrepeat_sendコードは不要ですが、動作しているときに複数の「送信」を必要とする可能性のある大きなメッセージを送信したい-私が問題の原因になるかどうかわかりませんか?

N.B。このコードはlinux-source / net / core / originのneighbour.cに挿入されているため、NEIGH_PRINTK1を使用しています。これは単なるprintkのマクロラッパーです。

ここで本当に頭をレンガの壁にぶつけているのですが、明らかなものは見当たりません、誰かが正しい方向に私を向けることができますか(または目がくらむほど明らかなエラーを見つけてください!)

これまでの所持品は次のとおりです。

void mymethod()
{
    struct socket sock;
    struct sockaddr_in addr_in;
    int ret_val;
    unsigned short port = htons(2048);
    unsigned int host = in_aton("192.168.1.254");
    unsigned int length = 5;
    char *buf = "TEST\0";
    struct msghdr msg;
    struct iovec iov;
    int len = 0, written = 0, left = length;
    mm_segment_t oldmm;

    NEIGH_PRINTK1("forwarding sk_buff at: %p.\n", skb);

    if ((ret_val = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
        NEIGH_PRINTK1("Error during creation of socket; terminating. code: %d\n", ret_val);
        return;
    }

    memset(&addr_in, 0, sizeof(struct sockaddr_in));
    addr_in.sin_family=AF_INET;
    addr_in.sin_port = port;
    addr_in.sin_addr.s_addr = host;

    if((ret_val = sock.ops->bind(&sock, (struct sockaddr *)&addr_in, sizeof(struct sockaddr_in))) < 0) {
    NEIGH_PRINTK1("Error trying to bind socket. code: %d\n", ret_val);
    goto close;
    }

    memset(&msg, 0, sizeof(struct msghdr));
    msg.msg_flags = 0;
    msg.msg_name = &addr_in;
    msg.msg_namelen = sizeof(struct sockaddr_in);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;

repeat_send:
    msg.msg_iov->iov_len = left;
    msg.msg_iov->iov_base = (char *)buf + written;

    oldmm = get_fs(); 
    set_fs(KERNEL_DS);
    len = sock_sendmsg(&sock, &msg, left);
    set_fs(oldmm);

    if (len == -ERESTARTSYS)
        goto repeat_send;
    if (len > 0) {
        written += len;
        left -= len;
        if (left)
            goto repeat_send;
    }

close:
    sock_release(&sock);
}

どんな助けでも大歓迎です、ありがとう!

役に立ちましたか?

解決

netpoll API UDPの場合。方法の例については、 netconsole をご覧ください。使用されています。使用しているAPIは、ユーザー空間向けです(ネットワークデータを送信するためにセグメント記述子で遊ぶ必要はありません!)

他のヒント

テキストモードコンソールでコードを実行します(つまり、Ctrl + Alt + F1を押してテキストコンソールに移動します)。このようにして、カーネルパニックはスタックトレースと何が問題なのかに関する追加情報を出力します。

それでも解決しない場合は、スタックトレースで質問を更新してください。

私はあまりLinuxカーネル開発者ではありませんが、printkをそこに入れて、ダウンする前にdmesgを見ることができますか?または、カーネルデバッガーとの接続について考えたことがありますか?

すべての変数をmymethod()関数の外に置いて、静的にする必要があると思います。カーネルスタックのサイズは8KiBに制限されているため、ローカル変数が多すぎる/大きすぎると、スタックオーバーフローとシステムのハングアップが発生する可能性があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top