)]}'
{
  "commit": "f754df2a34732607b84c1c892fc672f86b8bb504",
  "tree": "1da9608789801139db3d1d40cdeb35e09fb65fc0",
  "parents": [
    "ccdae1ab849bbce41542f79b3de9414bbd78814f"
  ],
  "author": {
    "name": "Tejun Heo",
    "email": "tj@kernel.org",
    "time": "Tue Jan 09 11:45:42 2024 -1000"
  },
  "committer": {
    "name": "Tejun Heo",
    "email": "tj@kernel.org",
    "time": "Tue Jan 09 11:45:42 2024 -1000"
  },
  "message": "kernfs: RCU protect kernfs_nodes and avoid kernfs_idr_lock in kernfs_find_and_get_node_by_id()\n\nThe BPF helper bpf_cgroup_from_id() calls kernfs_find_and_get_node_by_id()\nwhich acquires kernfs_idr_lock, which is an non-raw non-IRQ-safe lock. This\ncan lead to deadlocks as bpf_cgroup_from_id() can be called from any BPF\nprograms including e.g. the ones that attach to functions which are holding\nthe scheduler rq lock.\n\nConsider the following BPF program:\n\n  SEC(\"fentry/__set_cpus_allowed_ptr_locked\")\n  int BPF_PROG(__set_cpus_allowed_ptr_locked, struct task_struct *p,\n\t       struct affinity_context *affn_ctx, struct rq *rq, struct rq_flags *rf)\n  {\n\t  struct cgroup *cgrp \u003d bpf_cgroup_from_id(p-\u003ecgroups-\u003edfl_cgrp-\u003ekn-\u003eid);\n\n\t  if (cgrp) {\n\t\t  bpf_printk(\"%d[%s] in %s\", p-\u003epid, p-\u003ecomm, cgrp-\u003ekn-\u003ename);\n\t\t  bpf_cgroup_release(cgrp);\n\t  }\n\t  return 0;\n  }\n\n__set_cpus_allowed_ptr_locked() is called with rq lock held and the above\nBPF program calls bpf_cgroup_from_id() within leading to the following\nlockdep warning:\n\n  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n  WARNING: HARDIRQ-safe -\u003e HARDIRQ-unsafe lock order detected\n  6.7.0-rc3-work-00053-g07124366a1d7-dirty #147 Not tainted\n  -----------------------------------------------------\n  repro/1620 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire:\n  ffffffff833b3688 (kernfs_idr_lock){+.+.}-{2:2}, at: kernfs_find_and_get_node_by_id+0x1e/0x70\n\n\t\tand this task is already holding:\n  ffff888237ced698 (\u0026rq-\u003e__lock){-.-.}-{2:2}, at: task_rq_lock+0x4e/0xf0\n  which would create a new lock dependency:\n   (\u0026rq-\u003e__lock){-.-.}-{2:2} -\u003e (kernfs_idr_lock){+.+.}-{2:2}\n  ...\n   Possible interrupt unsafe locking scenario:\n\n\t CPU0                    CPU1\n\t ----                    ----\n    lock(kernfs_idr_lock);\n\t\t\t\t local_irq_disable();\n\t\t\t\t lock(\u0026rq-\u003e__lock);\n\t\t\t\t lock(kernfs_idr_lock);\n    \u003cInterrupt\u003e\n      lock(\u0026rq-\u003e__lock);\n\n\t\t *** DEADLOCK ***\n  ...\n  Call Trace:\n   dump_stack_lvl+0x55/0x70\n   dump_stack+0x10/0x20\n   __lock_acquire+0x781/0x2a40\n   lock_acquire+0xbf/0x1f0\n   _raw_spin_lock+0x2f/0x40\n   kernfs_find_and_get_node_by_id+0x1e/0x70\n   cgroup_get_from_id+0x21/0x240\n   bpf_cgroup_from_id+0xe/0x20\n   bpf_prog_98652316e9337a5a___set_cpus_allowed_ptr_locked+0x96/0x11a\n   bpf_trampoline_6442545632+0x4f/0x1000\n   __set_cpus_allowed_ptr_locked+0x5/0x5a0\n   sched_setaffinity+0x1b3/0x290\n   __x64_sys_sched_setaffinity+0x4f/0x60\n   do_syscall_64+0x40/0xe0\n   entry_SYSCALL_64_after_hwframe+0x46/0x4e\n\nLet\u0027s fix it by protecting kernfs_node and kernfs_root with RCU and making\nkernfs_find_and_get_node_by_id() acquire rcu_read_lock() instead of\nkernfs_idr_lock.\n\nThis adds an rcu_head to kernfs_node making it larger by 16 bytes on 64bit.\nCombined with the preceding rearrange patch, the net increase is 8 bytes.\n\nSigned-off-by: Tejun Heo \u003ctj@kernel.org\u003e\nCc: Andrea Righi \u003candrea.righi@canonical.com\u003e\nCc: Geert Uytterhoeven \u003cgeert@linux-m68k.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "bce1d7ac95caaa6ae48ba62c094d43c9da27298e",
      "old_mode": 33188,
      "old_path": "fs/kernfs/dir.c",
      "new_id": "458519e416fe75e97cc454a716d29c06b3586b56",
      "new_mode": 33188,
      "new_path": "fs/kernfs/dir.c"
    },
    {
      "type": "modify",
      "old_id": "237f2764b9412d65f2db6be01329d5565169a327",
      "old_mode": 33188,
      "old_path": "fs/kernfs/kernfs-internal.h",
      "new_id": "b42ee6547cdc1cfb1be7bb30ff890ce2d91e0777",
      "new_mode": 33188,
      "new_path": "fs/kernfs/kernfs-internal.h"
    },
    {
      "type": "modify",
      "old_id": "03c3fb83ab9e05e460720393f2b2c1ed43afbe3b",
      "old_mode": 33188,
      "old_path": "include/linux/kernfs.h",
      "new_id": "05dcbae7ecbf2afd3e0f9001cd3b0aebdfa96455",
      "new_mode": 33188,
      "new_path": "include/linux/kernfs.h"
    }
  ]
}
