summaryrefslogtreecommitdiff
path: root/drivers/base/core.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@google.com>2019-09-21 08:02:32 +0200
committerGreg Kroah-Hartman <gregkh@google.com>2019-09-21 08:02:32 +0200
commit2b29211873b22f0c1085dad21fb89fe21a907940 (patch)
tree40366ea654e911fd902d89b2ade08f2cd50014c0 /drivers/base/core.c
parentaa6ba1d906be3b47f5854ee3c4a7d3c8dd4f1e5e (diff)
parent5f090d837b1f61ba12780a8b8196b69a00d7cd70 (diff)
Merge 4.4.194 into android-4.4-p
Changes in 4.4.194 bridge/mdb: remove wrong use of NLM_F_MULTI cdc_ether: fix rndis support for Mediatek based smartphones ipv6: Fix the link time qualifier of 'ping_v6_proc_exit_net()' isdn/capi: check message length in capi_write() net: Fix null de-reference of device refcount sch_hhf: ensure quantum and hhf_non_hh_weight are non-zero sctp: Fix the link time qualifier of 'sctp_ctrlsock_exit()' sctp: use transport pf_retrans in sctp_do_8_2_transport_strike tcp: fix tcp_ecn_withdraw_cwr() to clear TCP_ECN_QUEUE_CWR tipc: add NULL pointer check before calling kfree_rcu tun: fix use-after-free when register netdev failed Revert "MIPS: SiByte: Enable swiotlb for SWARM, LittleSur and BigSur" Btrfs: fix assertion failure during fsync and use of stale transaction genirq: Prevent NULL pointer dereference in resend_irqs() KVM: s390: Do not leak kernel stack data in the KVM_S390_INTERRUPT ioctl KVM: x86: work around leak of uninitialized stack contents KVM: nVMX: handle page fault in vmread MIPS: VDSO: Prevent use of smp_processor_id() MIPS: VDSO: Use same -m%-float cflag as the kernel proper clk: rockchip: Don't yell about bad mmc phases when getting driver core: Fix use-after-free and double free on glue directory crypto: talitos - check AES key size crypto: talitos - check data blocksize in ablkcipher. x86/build: Add -Wnoaddress-of-packed-member to REALMODE_CFLAGS, to silence GCC9 build warning MIPS: netlogic: xlr: Remove erroneous check in nlm_fmn_send() ARC: configs: Remove CONFIG_INITRAMFS_SOURCE from defconfigs USB: usbcore: Fix slab-out-of-bounds bug during device reset media: tm6000: double free if usb disconnect while streaming x86/boot: Add missing bootparam that breaks boot on some platforms xen-netfront: do not assume sk_buff_head list is empty in error handling KVM: coalesced_mmio: add bounds checking serial: sprd: correct the wrong sequence of arguments tty/serial: atmel: reschedule TX after RX was started mwifiex: Fix three heap overflow at parsing element in cfg80211_ap_settings s390/bpf: fix lcgr instruction encoding ARM: OMAP2+: Fix omap4 errata warning on other SoCs s390/bpf: use 32-bit index for tail calls NFSv4: Fix return values for nfs4_file_open() NFS: Fix initialisation of I/O result struct in nfs_pgio_rpcsetup Kconfig: Fix the reference to the IDT77105 Phy driver in the description of ATM_NICSTAR_USE_IDT77105 ARM: 8874/1: mm: only adjust sections of valid mm structures r8152: Set memory to all 0xFFs on failed reg reads x86/apic: Fix arch_dynirq_lower_bound() bug for DT enabled machines netfilter: nf_conntrack_ftp: Fix debug output NFSv2: Fix eof handling NFSv2: Fix write regression cifs: set domainName when a domain-key is used in multiuser cifs: Use kzfree() to zero out the password sky2: Disable MSI on yet another ASUS boards (P6Xxxx) tools/power turbostat: fix buffer overrun net: seeq: Fix the function used to release some memory in an error handling path dmaengine: ti: omap-dma: Add cleanup in omap_dma_probe() keys: Fix missing null pointer check in request_key_auth_describe() floppy: fix usercopy direction media: technisat-usb2: break out of loop at end of buffer ARC: export "abort" for modules net_sched: let qdisc_put() accept NULL pointer Linux 4.4.194 Change-Id: I680ac71d33ab7a4fd239de6333ea5b76376521b6 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index cb5718d2669e..af948fedd232 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -857,12 +857,63 @@ static inline struct kobject *get_glue_dir(struct device *dev)
*/
static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
{
+ unsigned int ref;
+
/* see if we live in a "glue" directory */
if (!live_in_glue_dir(glue_dir, dev))
return;
mutex_lock(&gdp_mutex);
- if (!kobject_has_children(glue_dir))
+ /**
+ * There is a race condition between removing glue directory
+ * and adding a new device under the glue directory.
+ *
+ * CPU1: CPU2:
+ *
+ * device_add()
+ * get_device_parent()
+ * class_dir_create_and_add()
+ * kobject_add_internal()
+ * create_dir() // create glue_dir
+ *
+ * device_add()
+ * get_device_parent()
+ * kobject_get() // get glue_dir
+ *
+ * device_del()
+ * cleanup_glue_dir()
+ * kobject_del(glue_dir)
+ *
+ * kobject_add()
+ * kobject_add_internal()
+ * create_dir() // in glue_dir
+ * sysfs_create_dir_ns()
+ * kernfs_create_dir_ns(sd)
+ *
+ * sysfs_remove_dir() // glue_dir->sd=NULL
+ * sysfs_put() // free glue_dir->sd
+ *
+ * // sd is freed
+ * kernfs_new_node(sd)
+ * kernfs_get(glue_dir)
+ * kernfs_add_one()
+ * kernfs_put()
+ *
+ * Before CPU1 remove last child device under glue dir, if CPU2 add
+ * a new device under glue dir, the glue_dir kobject reference count
+ * will be increase to 2 in kobject_get(k). And CPU2 has been called
+ * kernfs_create_dir_ns(). Meanwhile, CPU1 call sysfs_remove_dir()
+ * and sysfs_put(). This result in glue_dir->sd is freed.
+ *
+ * Then the CPU2 will see a stale "empty" but still potentially used
+ * glue dir around in kernfs_new_node().
+ *
+ * In order to avoid this happening, we also should make sure that
+ * kernfs_node for glue_dir is released in CPU1 only when refcount
+ * for glue_dir kobj is 1.
+ */
+ ref = atomic_read(&glue_dir->kref.refcount);
+ if (!kobject_has_children(glue_dir) && !--ref)
kobject_del(glue_dir);
kobject_put(glue_dir);
mutex_unlock(&gdp_mutex);