Устранение адреса ядра путем очистки старших бит?

Есть ли какой-то механизм в Linux, который отравляет адреса, обнуляя старшие 16 бит?

Я отлаживаю сбой ядра на машине Intel x86-64. Инструкция, которая вызывает сбой, пытается получить доступ к адресу 0x880139f3da00:

crash> bt
R10: 0000000000000001  R11: 0000000000000001  R12: 0000880139f3da00
                                              ~~~~~~~~~~~~~~~~~~~~~

crash> p arp_tbl.nht->hash_buckets[255]
$66 = (struct neighbour *) 0x880139f3da00

crash> p *arp_tbl.nht->hash_buckets[255]
Cannot access memory at address 0x880139f3da00

hash_buckets таблица действительна:

crash> p arp_tbl.nht->hash_buckets[253]
$70 = (struct neighbour *) 0xffff88007325ae00
$71 = {
  next = 0x0, 
  tbl = 0xffffffff81abbf20 <arp_tbl>, 

Установка верхнего слова в 0xffff делает адрес действительным и возвращает действительную структуру данных:

crash> p *((struct neighbour *)0xffff880139f3da00)
$73 = {
  next = 0xffff88006de69a00, 
  tbl = 0xffffffff81abbf20 <arp_tbl>, 
  ... rest looks reasonable too ...

Структура обновляется операциями RCU (например, очень вероятно, что в neigh_flush_dev()). Итак, что может быть причиной того, что адрес становится недействительным таким образом?

Я могу исключить аппаратные дефекты (замеченные на двух машинах и с разными адресами). Системы работают под управлением CentOS 7 с ядром от 3.10.0-514.6.1.el7.centos.plus.x86_64 до 3.10.0-514.21.2.el7.centos.plus.x86_64.

Обновить

Из другого аварийного дампа я вижу skb пакета IPv6 с

crash> p *((struct sk_buff *)0xffff880070e25e00)
$57 = {
  transport_header = 54, 
  network_header = 14, 
  mac_header = 0, 
  ...
  head = 0xffff880138e28000 "", 
  data = 0xffff880138e2800e "`", 
  ...
}

Это дает сбой при записи первых 0x8 байтов в

#define HH_DATA_MOD 16

static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb)
{
                if (likely(hh_len <= HH_DATA_MOD)) {
                        memcpy(skb->data - HH_DATA_MOD, hh->hh_data, HH_DATA_MOD);   <<<<<

Это объясняет, почему два байта переопределяются (16 - 14).

1 ответ

Можете ли вы проверить расположение памяти, из которой был прочитан этот адрес? обычно такое чтение "частичного нуля" является результатом запуска memset в этой области. после того, как этот процессор вызвал сбой, было достаточно времени для того, чтобы кто-либо еще модифицировал область, чтобы завершить обнуление и, возможно, даже заполнить ее другими данными.

до сих пор нет причин подозревать, что rcu играет здесь какую-либо роль

это определенно не "отравление" ядром (было бы странно так делать). однако, если сбой воспроизводим (вы говорите, что он произошел как минимум на 2 разных машинах?), тогда может помочь запуск отладочного ядра, особенно с включенной отладкой slab.

Другие вопросы по тегам