linux 3.10的list_del

最近看到一个page的数据比较奇怪:

crash> page ffffea002c239c58
struct page {
  flags = 54043195528445952,
  _count = {
    counter = 34-----------------------被引用34次
  },
  {
    _mapcount = {
      counter = -1---------------------没有映射
    },
    {
      inuse = 65535,
      objects = 65535
    }
  },
  {
    {
      private = 0,
      mapping = 0x0------------------为NULL,
    },
    ptl = {
      raw_lock = {
        slock = 0
      }
    },
    slab = 0x0,
    first_page = 0x0
  },
  {
    index = 18446612222659373184,------------index这么大,明显不对
    freelist = 0xffff881508fda880------------转成16进制,这个倒是像对的
  },
  lru = {
    next = 0xdead000000100100,
    prev = 0xdead000000200200
  }
}

查看一下这个地址:

crash> kmem 0xffff881508fda880
CACHE            NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
ffff880c17fb0d00 mm_struct               1408        230       580    116     8k
SLAB              MEMORY            TOTAL  ALLOCATED  FREE
ffff881508fda280  ffff881508fda300      5          2     3
FREE / [ALLOCATED]
   ffff881508fda880

      PAGE         PHYSICAL      MAPPING       INDEX CNT FLAGS
ffffea00499f77b0 1508fda000                0        0  1 c0000000000080 slab

最后看到的是lru的next和prev成员,一开始才疏学浅,觉得这个 0xdead000000100100 和 0xdead000000200200 很奇怪。

后来搜索之后,才发现这个是将一个entry删除之后,设置的标记值:

/*
 * Architectures might want to move the poison pointer offset
 * into some well-recognized area such as 0xdead000000000000,
 * that is also not mappable by user-space exploits:
 */
#ifdef CONFIG_ILLEGAL_POINTER_VALUE
# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
#else
# define POISON_POINTER_DELTA 0
#endif

/*
 * These are non-NULL pointers that will result in page faults
 * under normal circumstances, used to verify that nobody uses
 * non-initialized list entries.
 */
#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)

删除的代码实现如下:

static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = LIST_POISON1;
    entry->prev = LIST_POISON2;
}

不光光是list,hlist也有类似动作:

static inline void hlist_del(struct hlist_node *n)
{
    __hlist_del(n);
    n->next = LIST_POISON1;
    n->pprev = LIST_POISON2;
}

在用户态程序中,我们一般通过判断指针是不是是null来判断能否使用这个指针,在将一个entry从list删除后,一般将prev和next设置为NULL,这样做没有什么问题,但是这样就没有

区分这个entry是从list摘除的,还是本身初始化的,所以为了调试方便,将其设置为一些特殊值,是有意义的。

当开启调试之后,即开启 CONFIG_DEBUG_LIST,则在加入链表和删除的时候都会加入调试warn

void __list_del_entry(struct list_head *entry)
{
    struct list_head *prev, *next;

    prev = entry->prev;
    next = entry->next;

    if (WARN(next == LIST_POISON1,
        "list_del corruption, %p->next is LIST_POISON1 (%p)\n",
        entry, LIST_POISON1) ||
        WARN(prev == LIST_POISON2,
        "list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
        entry, LIST_POISON2) ||
        WARN(prev->next != entry,
        "list_del corruption. prev->next should be %p, "
        "but was %p\n", entry, prev->next) ||
        WARN(next->prev != entry,
        "list_del corruption. next->prev should be %p, "
        "but was %p\n", entry, next->prev))
        return;

    __list_del(prev, next);
}
void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    WARN(next->prev != prev,
        "list_add corruption. next->prev should be "
        "prev (%p), but was %p. (next=%p).\n",
        prev, next->prev, next);
    WARN(prev->next != next,
        "list_add corruption. prev->next should be "
        "next (%p), but was %p. (prev=%p).\n",
        next, prev->next, prev);
    WARN(new == prev || new == next,
         "list_add double add: new=%p, prev=%p, next=%p.\n",
         new, prev, next);
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}

 当然,如果你摘链之后,还要继续挂链的话,还是要初始化的,这个时候就使用:

static inline void
list_del_init(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);-----------------------会重新初始化
}

猜你喜欢

转载自www.cnblogs.com/10087622blog/p/9625455.html
del