• Xiaochen Shen's avatar
    x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak · 75899924
    Xiaochen Shen authored
    On resource group creation via a mkdir an extra kernfs_node reference is
    obtained by kernfs_get() to ensure that the rdtgroup structure remains
    accessible for the rdtgroup_kn_unlock() calls where it is removed on
    deletion. Currently the extra kernfs_node reference count is only
    dropped by kernfs_put() in rdtgroup_kn_unlock() while the rdtgroup
    structure is removed in a few other locations that lack the matching
    reference drop.
    
    In call paths of rmdir and umount, when a control group is removed,
    kernfs_remove() is called to remove the whole kernfs nodes tree of the
    control group (including the kernfs nodes trees of all child monitoring
    groups), and then rdtgroup structure is freed by kfree(). The rdtgroup
    structures of all child monitoring groups under the control group are
    freed by kfree() in free_all_child_rdtgrp().
    
    Before calling kfree() to free the rdtgroup structures, the kernfs node
    of the control group itself as well as the kernfs nodes of all child
    monitoring groups still take the extra references which will never be
    dropped to 0 and the kernfs nodes will never be freed. It leads to
    reference count leak and kernfs_node_cache memory leak.
    
    For example, reference count leak is observed in these two cases:
      (1) mount -t resctrl resctrl /sys/fs/resctrl
          mkdir /sys/fs/resctrl/c1
          mkdir /sys/fs/resctrl/c1/mon_groups/m1
          umount /sys/fs/resctrl
    
      (2) mkdir /sys/fs/resctrl/c1
          mkdir /sys/fs/resctrl/c1/mon_groups/m1
          rmdir /sys/fs/resctrl/c1
    
    The same reference count leak issue also exists in the error exit paths
    of mkdir in mkdir_rdt_prepare() and rdtgroup_mkdir_ctrl_mon().
    
    Fix this issue by following changes to make sure the extra kernfs_node
    reference on rdtgroup is dropped before freeing the rdtgroup structure.
      (1) Introduce rdtgroup removal helper rdtgroup_remove() to wrap up
      kernfs_put() and kfree().
    
      (2) Call rdtgroup_remove() in rdtgroup removal path where the rdtgroup
      structure is about to be freed by kfree().
    
      (3) Call rdtgroup_remove() or kernfs_put() as appropriate in the error
      exit paths of mkdir where an extra reference is taken by kernfs_get().
    
    Fixes: f3cbeaca ("x86/intel_rdt/cqm: Add rmdir support")
    Fixes: e02737d5 ("x86/intel_rdt: Add tasks files")
    Fixes: 60cf5e10 ("x86/intel_rdt: Add mkdir to resctrl file system")
    Reported-by: default avatarWillem de Bruijn <willemb@google.com>
    Signed-off-by: default avatarXiaochen Shen <xiaochen.shen@intel.com>
    Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
    Reviewed-by: default avatarReinette Chatre <reinette.chatre@intel.com>
    Cc: stable@vger.kernel.org
    Link: https://lkml.kernel.org/r/1604085088-31707-1-git-send-email-xiaochen.shen@intel.com
    75899924
rdtgroup.c 79.5 KB