LINUX.ORG.RU

copy_to_user: не понимаю, как посмотреть данные в kernel space


0

0

Пишу модуль ядра. Нашел в исходниках ядра стандартный обработчки приема udp: udp_recvmsg.

Пытаюсь задампить данные, которые в сокете(я так понимаю они в пространсве ядра, т.к. потом их copy_to_user):

skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb)
  goto out;

for( ; j < skb->len; ++j )
{
  printk("%x ", skb->data[j]);
}
Результат выглядит, откровенно говоря, как дамп неинициализированной памяти(всякие там de, ff etc)

А вот когда уже после skb_copy_datagram_iovec смотрю буфер, который в юзер спейсе находится, то в нем все хорошо:

unsigned char* buf = (unsigned char*)msg->msg_iov->iov_base
for( ; i < msg->msg_iov->iov_len; ++i )
{
  printk("%x ",buf[i]);
}

Посмотрел, как та самая skb_copy_datagram_iovec() работает. Для моего случая там вседа лишь memcpy_toiovec(которая копирует данные в юзер спейс) вызывается, т.е. отрабатывает вот этот кусочек:

/* Copy header. */
if (copy > 0) {
  if (copy > len)
    copy = len;
  if (memcpy_toiovec(to, skb->data + offset, copy))
    goto fault;
  if ((len -= copy) == 0)
    return 0;
  offset += copy;
}

Никак не пойму, как же тогда данные в kernel space посмотреть? Ведь то же самое, что копируется вроде вывожу.

★★
Ответ на: комментарий от mv

дамп sk_buff

8c 60 f7 87 40 60 f7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 81 7b 80 10 81 7b 80 2 81 7b 80 40 85 7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2c 5 0 0 0 0 0 0 0 0 0 0 3c 36 cb e3 0 1 2 0 0 0 0 0 8 0 0 0 dc 5d 1f 80 b8 7 0 0 1 0 0 0 0 80 7b 80 24 81 7b 80 50 86 7b 80 20 87 7b 80 0 0 0 0 0 0 0 0 40 b7 b3 86 60 b0 b3 86 8c 60 f7 87 40 60 f7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 21 7c 80 10 21 7c 80 2 21 7c 80 40 85 7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2c 5 0 0 0 0 0 0 0 0 0 0 3c 36 cb e3 0 1 2 0 0 0 0 0 8 0 0 0 dc 5d 1f 80 b8 7 0 0 1 0 0 0 0 20 7c 80 24 21 7c 80 50 26 7c 80 20 27 7c 80 0 0 0 0 0 0 0 0 60 f5 2a 86 e0 b2 b3 86 8c 60 f7 87 40 60 f7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 c1 7c 80 10 c1 7c 80 2 c1 7c 80 40 85 7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2c 5 0 0 0 0 0 0 0 0 0 0 3c 36 cb e3 0 1 2 0 0 0 0 0 8 0 0 0 dc 5d 1f 80 b8 7 0 0 1 0 0 0 0 c0 7c 80 24 c1 7c 80 50 c6 7c 80 20 c7 7c 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 60 f7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 21 7a 80 10 21 7a 80 2 21 7a 80 40 8e 7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2c 5 0 0 0 0 0 0 0 0 0 0 3c 36 cb e3 0 1 2 0 0 0 0 0 8 0 0 0 dc 5d 1f 80 b8 7 0 0 1 0 0 0 0 20 7a 80 24 21 7a 80 50 26 7a 80 20 27 7a 80 0 0 0 0 0 0 0 0 20 d4 f9 84 c0 74 41 85 8c 60 f7 87 40 60 f7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 c9 7b 80 10 c9 7b 80 2 c9 7b 80 40 85 7 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2c 5 0 0 0 0 0 0 0 0 0 0 3c 36 cb e3 0 1 2 0 0 0 0

дамп msg_iov

47 1 4e 12 8d 80 85 81 20 39 27 a 22 12 6e 20 40 f7 cb 8d df 55 9d c6 19 35 5d c2 89 d5 1b 77 10 24 1a 28 89 24 44 6d d6 10 7e 44 d5 71 2 1b d3 58 ea 4 7f 24 90 f3 40 79 ee a0 68 b5 77 3a 32 e2 8 c0 75 b5 d4 49 4b ab ac 69 a9 90 c0 0 0 1 20 3a f7 a6 a3 33 16 6e cd ad 6f 56 f3 56 5a 79 29 0 2 ff b5 58 84 81 6e c0 3 3d e4 ec 55 63 29 3a 49 d5 71 3 47 1b 57 18 9b 83 2d e7 5f a6 42 25 35 fe d2 99 90 75 cd f6 3e 49 29 90 b8 71 62 45 dd 60 c7 cd 6b 3e 63 c6 e2 79 bc 8 cf 53 83 e3 64 dc 43 98 e9 ea 97 77 28 1e 3a 37 2a e6 93 6e d0 87 77 68 bf 1d f a3 47 1 4e 13 f6 f7 50 5c 2a c 2c 93 b8 1d 98 20 69 2 ed b2 de ab 99 af 57 50 25 34 75 e2 5 7b 88 18 b cd af 47 fa b8 cd b1 74 75 65 81 a9 97 e aa 1d c0 0 0 1 21 3a 97 d3 21 47 ac 5a da 99 82 2d 3d 38 ec 40 ef 27 1 64 a6 f8 4a 52 41 ab 3b a8 2a ce 29 50 c5 46 65 5e 54 6d b7 41 44 78 d c0 5 89 98 e7 92 7f 30 12 40 f 48 c7 25 24 ff 55 41 71 b5 5f 75 5 cc b0 21 f b4 2e e5 80 64 96 5f 1a 13 f8 ba 3a 42 50 91 57 4c c1 9e 4c 40 75 e b8 80 95 d7 72 d5 dc 40 c0 1d 3d 6a d2 e e9 e7 85 55 46 a8 8 dc 63 17 a3 60 fb a8 10 f1 e6 85 e e6 c9 f9 93 e 20 e 47 1 4e 14 bb 9a fa 6f 9d 9d 52 de e5 5 d7 58 22 d3 6a ae a1 fa 32 b5 5d ac a2 69 98 7 e1 70 de af 3b a9 40 11 63 ed d9 e1 77 2c 81 7e 13 e4 e3 20 d3 9a a7 b8 81 e1 e3 6e ee d0 e8 3f 3c 5b d 7a 36 c b9 63 a2 a0 c1 74 75 2d 4 81 1a 14 1d 39 97 0 0 0 1 22 3a af a6 b3 d6 28 e7 75 a 2b e9 ad 71 38 d7 90 d9 ec db 15 26 e3 71 14 f7 27 e5 41 a0 12 5d b3 c3 0 78 0 2f e0 46 49 21 e2 12 42 40 6e 18 9 80 6 97 0 19 e8 b2 45 32 1 1e 30 5e 4d b bb 3f e 4d c4 b 5 86 e4 74 8c e4 49 14 da a b9 81 5f 73 8d b4 51 81 1a a 96 1d ae 21 45 4e ab b3 63 71 1e 47 1 4e 15 cd ba c1 85 f7 73 93 a8 ff 73 ba e3 4 33 cb bb f6 8a 1 23 91 9c 83 5a 1c 40 bb 89 26 cf 95 19 73 17 ea ae 58 ca ab 6a 6a 3c 40 d1 ed 56 d4 d 53 e9 99 cb 62 b 4f 5c 10 bf eb 90 90 9 9f f7 ca 20 db d0 26 43 9b 18 0 36 86 62 5e c8 3 9f 85 ae bd d4 8 53 5d ae ca 33 55 b5 ad a6 f1 63 80 5 bb 90 21 5c d 5c 60 e0 c0 65 55 ca 3 95 5d 63 15 54 0 0 1 23 3a 6b 33 20 42 b2 a6 42 8f 18 b5 13 34 59 f8 0 6d 72 c6 74 df 50 38 3f dd 5b 5c 4d 2a 48 a 36 c0 99 ff 83 41 34 0 e0 3f a2 92 8 40 f 98 0 66 37 c9 24 a1 e3 6e a0 2f 7d 33 15 78 80 87 ea 47 1 4e 16 36 45 d9 fc 36 ed ab 42 2e d3 b 22 c6 d8 6a 7c 2a e6 34 59 7c 12 3f f5 95 13 49 a4 d1 c0 5f c3 10 8b a8 20 46 f 8a 29 1a d2 9f 3f 8c d7 18 21 24 96 9f 3d cc 57 ab b9 9e 2 da b9 98 12 3 46 93 20 7f 58 4 5a ee 6b ba 6b b4 67 55 5b dc 40 81 64 46 d6 b d9 f4 7d dc 42 c5 d6 f4 14 9b 54 65 da f5 dd 98 15 bc 88 db 7a 16 8 3c 11 0 10 20 13 3f f5 3b e0 8 d5 13 2b 0 90 8a 30 68 11 ba c1 a9 55 ae a5 12 e9 83 4f 9d 50 6e 5d 64 aa 80 0 0 1 24 3a 6b 14 9e 66 63 e2 16 30 b0 17 5d 61 1b 69 ae e2 27 1f ca f1 3a eb 4 9 b9 a7 5d d6 7 ba 80 c7 ef 34 47 1 4e 17 8c 62 40 6 43 58 8b 16 19 d4 cb ba 80 ab 6 ce 1d 6a bb 50 bd c2 ae ef 1a 36 ed c6 be 94 de 6b 95 1e 99 c3 e2 7d c9 a0 37 64 8b 50 f 66 55 dc b1 35 a0 7 ba 5e c0 4f 5c ad 33 85 c7 61 fa e2 c c9 fa 27 eb ac 7e f4 cd 2e 3a e6 70 b8 e1 7a e5 17 9c 3a 24 0 a 51 e2 62 99 3c b a3 8a 45 c6 c 17 9e 6b a8 93 ca eb c aa b9 81 aa 97 35 5c de a9 ea e2 8 5c 3c 81 54 a5 9e 1 1d 5c dc 6c 72 8f 9e 9b ea 7 5a 65 dd b3 4 ec 52 7a 0 f0 d2 22 3f 80 a7 8a e7 d 22 6b 8c 5d 72 3f 3a 40 87 c2 28 2 3d 73 fa b4

kulti ★★
() автор топика
Ответ на: комментарий от mv

offset = sizeof(struct udphdr) = 8

Ну, т.е. там udp заголовок + дамп msg_iov должно быть.

kulti ★★
() автор топика
Ответ на: комментарий от anonymous

Не очень понимаю о чем ты. В исходниках ядра данные из буфера, который в сокете, копируются в буфер, который в пространстве пользозвателя. Разве они не должны совпадать? За исключение udp-заголовка, есно, о чем я забыл упомянуть, но уже отписался чуть выше.

kulti ★★
() автор топика
Ответ на: комментарий от kulti

Разве они не должны совпадать?

Если они должны совпадать, но не совпадают, значит, по факту, ты делаешь что-то неправильно.

mv ★★★★★
()
Ответ на: комментарий от mv

хи) это я понимаю, потому и пришел за помощью, т.к. не ясно мне, ЧЯДНТ. В ядре вызов memcpy_toiovec(to, skb->data + offset, copy), я вывожу тот же самый skb->data и вижу, что там нечто, совсем не похожее на to. Я бы мог предположить, что мб там отложенная(асинхронная) запись какая-нибудь, но проблема в том, что в msg_iov-то данные нормальные, а в skb->data какая-то ересь.

kulti ★★
() автор топика
Ответ на: комментарий от kulti

Телепаты традиционно не выходят из отпуска, показывай свой код ;) Или работающий кусок кода, гарантированно воспроизводящий проблему.

mv ★★★★★
()
Ответ на: комментарий от anonymous

[c] skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) goto out; for( ; j < skb->len; ++j ) { printk(«%x », skb->data[j]); } [/c]

В итоге ты получаешь текущий буфер из очереди в ф-ции __skb_recv_datagram .... skb = skb_peek(&sk->sk_receive_queue);

..... static inline struct sk_buff *skb_peek_tail(struct sk_buff_head *list_) { struct sk_buff *list = ((struct sk_buff *)list_)->prev; if (list == (struct sk_buff *)list_) list = NULL; return list;

}

как то не вяжется с тем что хотел перехватывать. я не очень знаком с сетевой подсистемой но имхо перехватывать надо не так :)

anonymous
()
Ответ на: комментарий от anonymous
skb = skb_recv_datagram(sk, flags, noblock, &err); 
if (!skb) 
  goto out; 
 
for( ; j < skb->len; ++j ) 
{ 
  printk("%x ", skb->data[j]); 
}

В итоге ты получаешь текущий буфер из очереди в ф-ции __skb_recv_datagram

....

 skb = skb_peek(&sk->sk_receive_queue);

.....

static inline struct sk_buff *skb_peek_tail(struct sk_buff_head *list_)
{
        struct sk_buff *list = ((struct sk_buff *)list_)->prev;
        if (list == (struct sk_buff *)list_)
                list = NULL;
        return list;

}

как то не вяжется с тем что хотел перехватывать. я не очень знаком с сетевой подсистемой но имхо перехватывать надо не так :)

anonymous
()

Продолжим.

Показывайте весь код перхватчика. При работе с сетевой подсистемой нужно понимать, что функции, которые дергают данные из разнообразных sk_buff-ов двигают данные, соотв. никто вам не гарантирует, что при двукратном вызове одной и той же функции вы получите один и тот-же результат (впрочем такой же результат может быть достигнут с помощью разных функций, но работающих с одним буфером).

P.S. skb_recv_datagram - оставляет данные в буфере если установлен флаг MSG_PEEK.

jr_A
()
Ответ на: комментарий от jr_A

С удовольствием продолжу. На самом деле свой перехватчик я не написал еще, потому что так и не понял, где там в сокете данные лежат, поэтому просто скопировал udp_recvmsg и стал анализировать, как оно работает. Вот никак не пойму, почему после приема датаграммы(skb_recv_datagram), то, что лежит в skb, не похоже на udp-датаграмму? Плюс ко всему, после udp-заголовка(8 байт) должны идти передаваемые данные, а специфика такова, что данные передаются непрерывно и должны начинаться с 0х47, что я как раз и наблюдаю в msg_iov.

kulti ★★
() автор топика
Ответ на: комментарий от jr_A

Вы не там ищете данные. В sk_buff->data действительно сидит заголовок пакета (практически любого, не только udp). Для того, что бы добраться до самих данных вам нужен хвост sk_buff, а именно sk_buff->end, который приводится к skb_shared_info и обрабатывается следующим образом:

for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                int end;

                BUG_TRAP(start <= offset + len);
                end = start + skb_shinfo(skb)->frags[i].size;
                if ((copy = end - offset) > 0) {
                        int err;
                        u8  *vaddr;
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
                        struct page *page = frag->page;

                        if (copy > len)
                                copy = len;
                        vaddr = kmap(page);
                        err = memcpy_toiovec(to, vaddr + frag->page_offset +
                                             offset - start, copy);
                        kunmap(page);
                        if (err)
                                goto fault;
                        if (!(len -= copy))
                                return 0;
                        offset += copy;
                }
                start = end;
        }

Фактически - это цикл по всем фрагментам пакета с копированием данных пакета из соответствующих страниц. В вашем перехватчике лучше сделать тоже самое. Или же воспользоваться уже подготовленным msg->msg_iov.

jr_A
()
Ответ на: комментарий от jr_A

Спасибо, с утреца на свежую голову попытаюсь получше разобраться. Просто у меня была мысль, что видимо работает кусочек кода, приведенный вами, но я проверил всякие copy, len, offset и получил, что работает только первый кусочек, где копирование хидера, а не аппендикс. Разумеется все равно проверю - а вдруг?)

Подготовленный msg->msg_iov тоже пробовал менять, но почему-то никакой реакции со стороны железяки не наблюдал. Видимо после memcpy_toiovec происходит переключение контекста и просыпается вызов recv, а когда уже в ядро управление возвращается, буфер отработан принимающим приложением и менять его смысла нет.

kulti ★★
() автор топика
Ответ на: комментарий от jr_A

Неа, нифига не помогло( Написал такой дампер, который ничего не выводит, что как бы намекает:

static __inline__ void dumpk_skb_2(struct sk_buff* skb, int len)
{
  int start = skb_headlen(skb);
  int offset = sizeof(struct udphdr);
  int i, copy = start - offset;

  /* Copy header. */
  if (copy > 0) {
    if (copy > len)
      copy = len;

    if ((len -= copy) == 0)
      return;
    offset += copy;
    }
    
  for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
  { 
    int end;
    char* buf;

    BUG_TRAP(start <= offset + len); 
    end = start + skb_shinfo(skb)->frags[i].size; 
    if ((copy = end - offset) > 0) { 
      int err; 
      u8  *vaddr; 
      skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 
      struct page *page = frag->page; 

      if (copy > len) 
        copy = len; 
      vaddr = kmap(page);
      
      buf = (char*)kmalloc(copy + 1,GFP_KERNEL);
      memcpy(buf, vaddr + frag->page_offset + 
             offset - start, copy);
      buf[copy] = '\0';
      printk("%x\n", buf[0]);
      kfree(buf);
      kunmap(page); 

      if (!(len -= copy)) 
        return; 
      offset += copy; 
    } 
    start = end; 
  } 
}
Вызываю его тут:
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
                goto out;
  
        copied = skb->len - sizeof(struct udphdr);
        if (copied > len) {
                copied = len;
                msg->msg_flags |= MSG_TRUNC;
        }

        dumpk_skb_2(skb, copied);
В общем, видимо и правда придется впадать в отчаяние...

kulti ★★
() автор топика
Ответ на: комментарий от kulti

А вы учитываете что msg->msg_iov->iov_base - это указатель на участок памяти в пространстве пользователя, а не ядра? И если указатели на эти участки памяти использовать напрямую, то вы получите мусор в дампе?

jr_A
()
Ответ на: комментарий от jr_A

Первое я понимаю, только мусор-то мы получаем для sk_buff, а не для msg_iov. А вот второго не знал. Спасибо) Пойду гуглить, но может подскажите, как из простарнства пользователя увидеть данные в пространсве ядра и наоборот?

kulti ★★
() автор топика
Ответ на: комментарий от jr_A

> что бы добраться до самих данных вам нужен хвост sk_buff, а именно sk_buff->end

Ой ли? ))

Данные торчат на отрезке skb->data - skb->tail.

LamerOk ★★★★★
()
Ответ на: комментарий от jr_A

ммм... что-то не помогает, или я не правильно понял. Во-первых, модуль ядра не в юзер-спейсе же выполняется, значит должно быть, как вы говорите: мусор в дампе msg->msg_iov->iov_base(но я наблюдаю обратное). Во-вторых, решил skb->data в юзер-спейс тоже скопировать и посмотреть, что будет:

  buf = (unsigned char*)kmalloc(skb->len, GFP_USER);
  copy_to_user(buf, skb->data, skb->len);

  printk("\n==========dumping skb==================\n");
  for( ; j < skb->len; ++j )
  {
    printk("%x ", buf[j]);
  }
  printk("\n=======================================\n");
Все тот же мусор. Ради интереса попробовал так:
  buf = (unsigned char*)kmalloc(skb->len, GFP_KERNEL);
  copy_from_user(buf, skb->data, skb->len);

kulti ★★
() автор топика
Ответ на: комментарий от kulti

млин) в общем, все равно мусор) либо мозг под конец рабочего дня схлопнулся, либо я действительно не могу этого понять.

kulti ★★
() автор топика
Ответ на: комментарий от LamerOk

Хм, верно, но не совсем. Часть данных, да, там находится (заголовок точно там). Загляните в функцию alloc_skb:

data = ____kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
...
skb->head = data;
skb->data = data;
skb->tail = data;
skb->end  = data + size;

skb->end как раз указывает на фрагментированые данные пакета.

To kulti: на данные которые сидят в sk_buff->data + sizeof (updhdr) смотрели?

jr_A
()
Ответ на: комментарий от jr_A

Во избежаний спекуляций. Если размер данных меньше sk_buff->truesize - sizeof (sk_buff), то все данные сидят в sk_buff->data.

jr_A
()
Ответ на: комментарий от jr_A

> skb->end как раз указывает на фрагментированые данные пакета.

Нет, skb->end указывает на конец выделенной памяти, что ясно видно из приведнного отрывка. ))

Если быть более точным - то _за_ конец выделенной памяти.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Не на конец, а на sizeof(struct skb_shared_info) байта раньше конца выделенной памяти. Посмотрите функцию skb_copy_datagram_iovec.

jr_A
()
Ответ на: комментарий от jr_A

Да, вывод того же «качества», что я приводил раньше, что с копированием в юзер-спейс, что нет...

kulti ★★
() автор топика
Ответ на: комментарий от jr_A

Чтобы потом поправлять на лоре за тобой косяки? Нет, уж. Учись сам по-маленьку. )))

LamerOk ★★★★★
()

В общем, я сделал такую штуку:

{
  int ret, i;
  unsigned char* buf;
  struct iovec* iov;
  struct iovec* iov_tmp;
  struct msghdr* msg_tmp = (struct msghdr*)kmalloc(sizeof(struct msghdr), GFP_USER);
  
  msg_tmp->msg_name = msg->msg_name;
  msg_tmp->msg_namelen = msg->msg_namelen;

  msg_tmp->msg_iov = (struct iovec*)kmalloc( msg->msg_iovlen*sizeof(struct iovec), GFP_USER );
  msg_tmp->msg_iovlen = msg->msg_iovlen;
  iov = msg->msg_iov;
  iov_tmp = msg_tmp->msg_iov;
  for( i = 0; i < msg->msg_iovlen; ++i )
  {
    iov_tmp->iov_base = kmalloc( iov->iov_len, GFP_USER );
    memcpy( iov_tmp->iov_base, iov->iov_base, iov->iov_len );
    iov_tmp->iov_len = iov->iov_len;
    ++iov; ++iov_tmp;
  }

  msg_tmp->msg_control = msg->msg_control;
  msg_tmp->msg_controllen = msg->msg_controllen;
  msg_tmp->msg_flags = msg->msg_flags;
  
  ret = orginalRecv( iocb, sk, msg_tmp, len, noblock, flags, addr_len );

  //здесь должно модифицироваться msg_tmp, но ret == -14

  iov = msg->msg_iov;
  iov_tmp = msg_tmp->msg_iov;
  for( i = 0; i < msg->msg_iovlen; ++i )
  {
    memcpy( iov->iov_base, iov_tmp->iov_base, iov->iov_len );
    ++iov; ++iov_tmp;
  }

  msg->msg_flags = msg_tmp->msg_flags;

  return ret;
}
но нифига не работает, т.к. originalRecv возвращает -14, т.е. -EFAULT, которое возвращается, т.к. сopy_to_user() возвращает 0. Значит, ничего не копируется. Проверил access_ok() - вернулась 1. Почему оно еще может не копироваться, я ведь выделяю память в пространстве пользователя?

kulti ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.