)]}'
{
  "commit": "16fcec35e7d7c4faaa4709f6434a4a25b06d25e3",
  "tree": "5febf4d688f2c32ed55e02bc20246388b74d85e4",
  "parents": [
    "0fb96701376874c9f1f80322f89a5bf4457c709f"
  ],
  "author": {
    "name": "Neil Horman",
    "email": "nhorman@tuxdriver.com",
    "time": "Tue Sep 11 11:28:26 2007 +0200"
  },
  "committer": {
    "name": "David S. Miller",
    "email": "davem@davemloft.net",
    "time": "Tue Sep 11 11:28:26 2007 +0200"
  },
  "message": "[NETFILTER]: Fix/improve deadlock condition on module removal netfilter\n\nSo I\u0027ve had a deadlock reported to me.  I\u0027ve found that the sequence of\nevents goes like this:\n\n1) process A (modprobe) runs to remove ip_tables.ko\n\n2) process B (iptables-restore) runs and calls setsockopt on a netfilter socket,\nincreasing the ip_tables socket_ops use count\n\n3) process A acquires a file lock on the file ip_tables.ko, calls remove_module\nin the kernel, which in turn executes the ip_tables module cleanup routine,\nwhich calls nf_unregister_sockopt\n\n4) nf_unregister_sockopt, seeing that the use count is non-zero, puts the\ncalling process into uninterruptible sleep, expecting the process using the\nsocket option code to wake it up when it exits the kernel\n\n4) the user of the socket option code (process B) in do_ipt_get_ctl, calls\nipt_find_table_lock, which in this case calls request_module to load\nip_tables_nat.ko\n\n5) request_module forks a copy of modprobe (process C) to load the module and\nblocks until modprobe exits.\n\n6) Process C. forked by request_module process the dependencies of\nip_tables_nat.ko, of which ip_tables.ko is one.\n\n7) Process C attempts to lock the request module and all its dependencies, it\nblocks when it attempts to lock ip_tables.ko (which was previously locked in\nstep 3)\n\nTheres not really any great permanent solution to this that I can see, but I\u0027ve\ndeveloped a two part solution that corrects the problem\n\nPart 1) Modifies the nf_sockopt registration code so that, instead of using a\nuse counter internal to the nf_sockopt_ops structure, we instead use a pointer\nto the registering modules owner to do module reference counting when nf_sockopt\ncalls a modules set/get routine.  This prevents the deadlock by preventing set 4\nfrom happening.\n\nPart 2) Enhances the modprobe utilty so that by default it preforms non-blocking\nremove operations (the same way rmmod does), and add an option to explicity\nrequest blocking operation.  So if you select blocking operation in modprobe you\ncan still cause the above deadlock, but only if you explicity try (and since\nroot can do any old stupid thing it would like....  :)  ).\n\nSigned-off-by: Neil Horman \u003cnhorman@tuxdriver.com\u003e\nSigned-off-by: Patrick McHardy \u003ckaber@trash.net\u003e\nSigned-off-by: David S. Miller \u003cdavem@davemloft.net\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "0eed0b7ab2dffedca01a1cebd234f7bbafe2efda",
      "old_mode": 33188,
      "old_path": "include/linux/netfilter.h",
      "new_id": "1dd075eda595a86efe4ca15e8c6d146d63a7ef73",
      "new_mode": 33188,
      "new_path": "include/linux/netfilter.h"
    },
    {
      "type": "modify",
      "old_id": "4169a2a89a39ff11c86c3e99b87558526e441ddb",
      "old_mode": 33188,
      "old_path": "net/bridge/netfilter/ebtables.c",
      "new_id": "6018d0e51938c772863331a134baa05559d02ab0",
      "new_mode": 33188,
      "new_path": "net/bridge/netfilter/ebtables.c"
    },
    {
      "type": "modify",
      "old_id": "902fd578aa3c1853c034bd7e867566dcdde683f3",
      "old_mode": 33188,
      "old_path": "net/ipv4/ipvs/ip_vs_ctl.c",
      "new_id": "f656d41d8d419ef626e0e22e9caf812d70eba3aa",
      "new_mode": 33188,
      "new_path": "net/ipv4/ipvs/ip_vs_ctl.c"
    },
    {
      "type": "modify",
      "old_id": "d1149aba93515abf2a7d2f7629a16b8999e78788",
      "old_mode": 33188,
      "old_path": "net/ipv4/netfilter/arp_tables.c",
      "new_id": "29114a9ccd1d2e047b5d1fa1bfa3b9cf0e0a444f",
      "new_mode": 33188,
      "new_path": "net/ipv4/netfilter/arp_tables.c"
    },
    {
      "type": "modify",
      "old_id": "e1b402c6b855a50072d127974e9002c518fa3872",
      "old_mode": 33188,
      "old_path": "net/ipv4/netfilter/ip_tables.c",
      "new_id": "6486894f450c3137f84777c995a683ab27cdff6c",
      "new_mode": 33188,
      "new_path": "net/ipv4/netfilter/ip_tables.c"
    },
    {
      "type": "modify",
      "old_id": "53cb1772f38ff06bd59ab106b9f3ad9be38e06ea",
      "old_mode": 33188,
      "old_path": "net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c",
      "new_id": "f813e02aab3022d890887f4ae4a50711305a6a2a",
      "new_mode": 33188,
      "new_path": "net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c"
    },
    {
      "type": "modify",
      "old_id": "aeda617246b76ea8a956f171d83a1362fa007071",
      "old_mode": 33188,
      "old_path": "net/ipv6/netfilter/ip6_tables.c",
      "new_id": "cd9df02bb85c212b1e65401937e0226ec1144280",
      "new_mode": 33188,
      "new_path": "net/ipv6/netfilter/ip6_tables.c"
    },
    {
      "type": "modify",
      "old_id": "8b8ece750313b5a401741564c57c4eb3b775b552",
      "old_mode": 33188,
      "old_path": "net/netfilter/nf_sockopt.c",
      "new_id": "e32761ce260cbc8b30216370ddf06871da35d221",
      "new_mode": 33188,
      "new_path": "net/netfilter/nf_sockopt.c"
    }
  ]
}
