)]}'
{
  "commit": "eedce141cd2dad8d0cefc5468ef41898949a7031",
  "tree": "e7b7c4c69114df9a830ec4c3f8e70dd4b30015ca",
  "parents": [
    "fd6de5300e6fcad5621ef7e78eb227de9d4c8b79"
  ],
  "author": {
    "name": "Thadeu Lima de Souza Cascardo",
    "email": "cascardo@linux.vnet.ibm.com",
    "time": "Thu Oct 25 13:37:51 2012 -0700"
  },
  "committer": {
    "name": "Linus Torvalds",
    "email": "torvalds@linux-foundation.org",
    "time": "Thu Oct 25 14:37:52 2012 -0700"
  },
  "message": "genalloc: stop crashing the system when destroying a pool\n\nThe genalloc code uses the bitmap API from include/linux/bitmap.h and\nlib/bitmap.c, which is based on long values.  Both bitmap_set from\nlib/bitmap.c and bitmap_set_ll, which is the lockless version from\ngenalloc.c, use BITMAP_LAST_WORD_MASK to set the first bits in a long in\nthe bitmap.\n\nThat one uses (1 \u003c\u003c bits) - 1, 0b111, if you are setting the first three\nbits.  This means that the API counts from the least significant bits\n(LSB from now on) to the MSB.  The LSB in the first long is bit 0, then.\nThe same works for the lookup functions.\n\nThe genalloc code uses longs for the bitmap, as it should.  In\ninclude/linux/genalloc.h, struct gen_pool_chunk has unsigned long\nbits[0] as its last member.  When allocating the struct, genalloc should\nreserve enough space for the bitmap.  This should be a proper number of\nlongs that can fit the amount of bits in the bitmap.\n\nHowever, genalloc allocates an integer number of bytes that fit the\namount of bits, but may not be an integer amount of longs.  9 bytes, for\nexample, could be allocated for 70 bits.\n\nThis is a problem in itself if the Least Significat Bit in a long is in\nthe byte with the largest address, which happens in Big Endian machines.\nThis means genalloc is not allocating the byte in which it will try to\nset or check for a bit.\n\nThis may end up in memory corruption, where genalloc will try to set the\nbits it has not allocated.  In fact, genalloc may not set these bits\nbecause it may find them already set, because they were not zeroed since\nthey were not allocated.  And that\u0027s what causes a BUG when\ngen_pool_destroy is called and check for any set bits.\n\nWhat really happens is that genalloc uses kmalloc_node with __GFP_ZERO\non gen_pool_add_virt.  With SLAB and SLUB, this means the whole slab\nwill be cleared, not only the requested bytes.  Since struct\ngen_pool_chunk has a size that is a multiple of 8, and slab sizes are\nmultiples of 8, we get lucky and allocate and clear the right amount of\nbytes.\n\nHower, this is not the case with SLOB or with older code that did memset\nafter allocating instead of using __GFP_ZERO.\n\nSo, a simple module as this (running 3.6.0), will cause a crash when\nrmmod\u0027ed.\n\n  [root@phantom-lp2 foo]# cat foo.c\n  #include \u003clinux/kernel.h\u003e\n  #include \u003clinux/module.h\u003e\n  #include \u003clinux/init.h\u003e\n  #include \u003clinux/genalloc.h\u003e\n\n  MODULE_LICENSE(\"GPL\");\n  MODULE_VERSION(\"0.1\");\n\n  static struct gen_pool *foo_pool;\n\n  static __init int foo_init(void)\n  {\n          int ret;\n          foo_pool \u003d gen_pool_create(10, -1);\n          if (!foo_pool)\n                  return -ENOMEM;\n          ret \u003d gen_pool_add(foo_pool, 0xa0000000, 32 \u003c\u003c 10, -1);\n          if (ret) {\n                  gen_pool_destroy(foo_pool);\n                  return ret;\n          }\n          return 0;\n  }\n\n  static __exit void foo_exit(void)\n  {\n          gen_pool_destroy(foo_pool);\n  }\n\n  module_init(foo_init);\n  module_exit(foo_exit);\n  [root@phantom-lp2 foo]# zcat /proc/config.gz | grep SLOB\n  CONFIG_SLOB\u003dy\n  [root@phantom-lp2 foo]# insmod ./foo.ko\n  [root@phantom-lp2 foo]# rmmod foo\n  ------------[ cut here ]------------\n  kernel BUG at lib/genalloc.c:243!\n  cpu 0x4: Vector: 700 (Program Check) at [c0000000bb0e7960]\n      pc: c0000000003cb50c: .gen_pool_destroy+0xac/0x110\n      lr: c0000000003cb4fc: .gen_pool_destroy+0x9c/0x110\n      sp: c0000000bb0e7be0\n     msr: 8000000000029032\n    current \u003d 0xc0000000bb0e0000\n    paca    \u003d 0xc000000006d30e00   softe: 0        irq_happened: 0x01\n      pid   \u003d 13044, comm \u003d rmmod\n  kernel BUG at lib/genalloc.c:243!\n  [c0000000bb0e7ca0] d000000004b00020 .foo_exit+0x20/0x38 [foo]\n  [c0000000bb0e7d20] c0000000000dff98 .SyS_delete_module+0x1a8/0x290\n  [c0000000bb0e7e30] c0000000000097d4 syscall_exit+0x0/0x94\n  --- Exception: c00 (System Call) at 000000800753d1a0\n  SP (fffd0b0e640) is in userspace\n\nSigned-off-by: Thadeu Lima de Souza Cascardo \u003ccascardo@linux.vnet.ibm.com\u003e\nCc: Paul Gortmaker \u003cpaul.gortmaker@windriver.com\u003e\nCc: Benjamin Gaignard \u003cbenjamin.gaignard@stericsson.com\u003e\nCc: \u003cstable@vger.kernel.org\u003e\nSigned-off-by: Andrew Morton \u003cakpm@linux-foundation.org\u003e\nSigned-off-by: Linus Torvalds \u003ctorvalds@linux-foundation.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "ca208a92628c1b49a6f5c1fece1a81592a65ecaa",
      "old_mode": 33188,
      "old_path": "lib/genalloc.c",
      "new_id": "54920433705adbff385b319574a9f04b50d8ca77",
      "new_mode": 33188,
      "new_path": "lib/genalloc.c"
    }
  ]
}
