aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_configfs.c
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-02-09 18:34:54 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-12 13:32:41 -0500
commit1f6fe7cba1c0a817a8712d7fdd0ec1b4ddd4ea2f (patch)
treed3210e224f8c415d78fbf70883026fa945591b8a /drivers/target/target_core_configfs.c
parente89d15eeadb172bd53ca6362bf9ab6b22077224c (diff)
[SCSI] target: fix use after free detected by SLUB poison
This patch moves a large number of memory release paths inside of the configfs callback target_core_hba_item_ops->release() called from within fs/configfs/item.c: config_item_cleanup() context. This patch resolves the SLUB 'Poison overwritten' warnings. Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/target/target_core_configfs.c')
-rw-r--r--drivers/target/target_core_configfs.c120
1 files changed, 74 insertions, 46 deletions
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index e77001b16063..caf8dc18ee0a 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -1970,13 +1970,35 @@ static void target_core_dev_release(struct config_item *item)
1970{ 1970{
1971 struct se_subsystem_dev *se_dev = container_of(to_config_group(item), 1971 struct se_subsystem_dev *se_dev = container_of(to_config_group(item),
1972 struct se_subsystem_dev, se_dev_group); 1972 struct se_subsystem_dev, se_dev_group);
1973 struct config_group *dev_cg; 1973 struct se_hba *hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item);
1974 1974 struct se_subsystem_api *t = hba->transport;
1975 if (!(se_dev)) 1975 struct config_group *dev_cg = &se_dev->se_dev_group;
1976 return;
1977 1976
1978 dev_cg = &se_dev->se_dev_group;
1979 kfree(dev_cg->default_groups); 1977 kfree(dev_cg->default_groups);
1978 /*
1979 * This pointer will set when the storage is enabled with:
1980 *`echo 1 > $CONFIGFS/core/$HBA/$DEV/dev_enable`
1981 */
1982 if (se_dev->se_dev_ptr) {
1983 printk(KERN_INFO "Target_Core_ConfigFS: Calling se_free_"
1984 "virtual_device() for se_dev_ptr: %p\n",
1985 se_dev->se_dev_ptr);
1986
1987 se_free_virtual_device(se_dev->se_dev_ptr, hba);
1988 } else {
1989 /*
1990 * Release struct se_subsystem_dev->se_dev_su_ptr..
1991 */
1992 printk(KERN_INFO "Target_Core_ConfigFS: Calling t->free_"
1993 "device() for se_dev_su_ptr: %p\n",
1994 se_dev->se_dev_su_ptr);
1995
1996 t->free_device(se_dev->se_dev_su_ptr);
1997 }
1998
1999 printk(KERN_INFO "Target_Core_ConfigFS: Deallocating se_subsystem"
2000 "_dev_t: %p\n", se_dev);
2001 kfree(se_dev);
1980} 2002}
1981 2003
1982static ssize_t target_core_dev_show(struct config_item *item, 2004static ssize_t target_core_dev_show(struct config_item *item,
@@ -2139,7 +2161,16 @@ static struct configfs_attribute *target_core_alua_lu_gp_attrs[] = {
2139 NULL, 2161 NULL,
2140}; 2162};
2141 2163
2164static void target_core_alua_lu_gp_release(struct config_item *item)
2165{
2166 struct t10_alua_lu_gp *lu_gp = container_of(to_config_group(item),
2167 struct t10_alua_lu_gp, lu_gp_group);
2168
2169 core_alua_free_lu_gp(lu_gp);
2170}
2171
2142static struct configfs_item_operations target_core_alua_lu_gp_ops = { 2172static struct configfs_item_operations target_core_alua_lu_gp_ops = {
2173 .release = target_core_alua_lu_gp_release,
2143 .show_attribute = target_core_alua_lu_gp_attr_show, 2174 .show_attribute = target_core_alua_lu_gp_attr_show,
2144 .store_attribute = target_core_alua_lu_gp_attr_store, 2175 .store_attribute = target_core_alua_lu_gp_attr_store,
2145}; 2176};
@@ -2190,9 +2221,11 @@ static void target_core_alua_drop_lu_gp(
2190 printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Logical Unit" 2221 printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Logical Unit"
2191 " Group: core/alua/lu_gps/%s, ID: %hu\n", 2222 " Group: core/alua/lu_gps/%s, ID: %hu\n",
2192 config_item_name(item), lu_gp->lu_gp_id); 2223 config_item_name(item), lu_gp->lu_gp_id);
2193 2224 /*
2225 * core_alua_free_lu_gp() is called from target_core_alua_lu_gp_ops->release()
2226 * -> target_core_alua_lu_gp_release()
2227 */
2194 config_item_put(item); 2228 config_item_put(item);
2195 core_alua_free_lu_gp(lu_gp);
2196} 2229}
2197 2230
2198static struct configfs_group_operations target_core_alua_lu_gps_group_ops = { 2231static struct configfs_group_operations target_core_alua_lu_gps_group_ops = {
@@ -2548,7 +2581,16 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
2548 NULL, 2581 NULL,
2549}; 2582};
2550 2583
2584static void target_core_alua_tg_pt_gp_release(struct config_item *item)
2585{
2586 struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(to_config_group(item),
2587 struct t10_alua_tg_pt_gp, tg_pt_gp_group);
2588
2589 core_alua_free_tg_pt_gp(tg_pt_gp);
2590}
2591
2551static struct configfs_item_operations target_core_alua_tg_pt_gp_ops = { 2592static struct configfs_item_operations target_core_alua_tg_pt_gp_ops = {
2593 .release = target_core_alua_tg_pt_gp_release,
2552 .show_attribute = target_core_alua_tg_pt_gp_attr_show, 2594 .show_attribute = target_core_alua_tg_pt_gp_attr_show,
2553 .store_attribute = target_core_alua_tg_pt_gp_attr_store, 2595 .store_attribute = target_core_alua_tg_pt_gp_attr_store,
2554}; 2596};
@@ -2601,9 +2643,11 @@ static void target_core_alua_drop_tg_pt_gp(
2601 printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Target Port" 2643 printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Target Port"
2602 " Group: alua/tg_pt_gps/%s, ID: %hu\n", 2644 " Group: alua/tg_pt_gps/%s, ID: %hu\n",
2603 config_item_name(item), tg_pt_gp->tg_pt_gp_id); 2645 config_item_name(item), tg_pt_gp->tg_pt_gp_id);
2604 2646 /*
2647 * core_alua_free_tg_pt_gp() is called from target_core_alua_tg_pt_gp_ops->release()
2648 * -> target_core_alua_tg_pt_gp_release().
2649 */
2605 config_item_put(item); 2650 config_item_put(item);
2606 core_alua_free_tg_pt_gp(tg_pt_gp);
2607} 2651}
2608 2652
2609static struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = { 2653static struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = {
@@ -2770,13 +2814,11 @@ static void target_core_drop_subdev(
2770 struct se_subsystem_api *t; 2814 struct se_subsystem_api *t;
2771 struct config_item *df_item; 2815 struct config_item *df_item;
2772 struct config_group *dev_cg, *tg_pt_gp_cg; 2816 struct config_group *dev_cg, *tg_pt_gp_cg;
2773 int i, ret; 2817 int i;
2774 2818
2775 hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); 2819 hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item);
2776 2820
2777 if (mutex_lock_interruptible(&hba->hba_access_mutex)) 2821 mutex_lock(&hba->hba_access_mutex);
2778 goto out;
2779
2780 t = hba->transport; 2822 t = hba->transport;
2781 2823
2782 spin_lock(&se_global->g_device_lock); 2824 spin_lock(&se_global->g_device_lock);
@@ -2790,7 +2832,10 @@ static void target_core_drop_subdev(
2790 config_item_put(df_item); 2832 config_item_put(df_item);
2791 } 2833 }
2792 kfree(tg_pt_gp_cg->default_groups); 2834 kfree(tg_pt_gp_cg->default_groups);
2793 core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp); 2835 /*
2836 * core_alua_free_tg_pt_gp() is called from ->default_tg_pt_gp
2837 * directly from target_core_alua_tg_pt_gp_release().
2838 */
2794 T10_ALUA(se_dev)->default_tg_pt_gp = NULL; 2839 T10_ALUA(se_dev)->default_tg_pt_gp = NULL;
2795 2840
2796 dev_cg = &se_dev->se_dev_group; 2841 dev_cg = &se_dev->se_dev_group;
@@ -2799,38 +2844,12 @@ static void target_core_drop_subdev(
2799 dev_cg->default_groups[i] = NULL; 2844 dev_cg->default_groups[i] = NULL;
2800 config_item_put(df_item); 2845 config_item_put(df_item);
2801 } 2846 }
2802
2803 config_item_put(item);
2804 /* 2847 /*
2805 * This pointer will set when the storage is enabled with: 2848 * The releasing of se_dev and associated se_dev->se_dev_ptr is done
2806 * `echo 1 > $CONFIGFS/core/$HBA/$DEV/dev_enable` 2849 * from target_core_dev_item_ops->release() ->target_core_dev_release().
2807 */ 2850 */
2808 if (se_dev->se_dev_ptr) { 2851 config_item_put(item);
2809 printk(KERN_INFO "Target_Core_ConfigFS: Calling se_free_"
2810 "virtual_device() for se_dev_ptr: %p\n",
2811 se_dev->se_dev_ptr);
2812
2813 ret = se_free_virtual_device(se_dev->se_dev_ptr, hba);
2814 if (ret < 0)
2815 goto hba_out;
2816 } else {
2817 /*
2818 * Release struct se_subsystem_dev->se_dev_su_ptr..
2819 */
2820 printk(KERN_INFO "Target_Core_ConfigFS: Calling t->free_"
2821 "device() for se_dev_su_ptr: %p\n",
2822 se_dev->se_dev_su_ptr);
2823
2824 t->free_device(se_dev->se_dev_su_ptr);
2825 }
2826
2827 printk(KERN_INFO "Target_Core_ConfigFS: Deallocating se_subsystem"
2828 "_dev_t: %p\n", se_dev);
2829
2830hba_out:
2831 mutex_unlock(&hba->hba_access_mutex); 2852 mutex_unlock(&hba->hba_access_mutex);
2832out:
2833 kfree(se_dev);
2834} 2853}
2835 2854
2836static struct configfs_group_operations target_core_hba_group_ops = { 2855static struct configfs_group_operations target_core_hba_group_ops = {
@@ -2913,6 +2932,13 @@ SE_HBA_ATTR(hba_mode, S_IRUGO | S_IWUSR);
2913 2932
2914CONFIGFS_EATTR_OPS(target_core_hba, se_hba, hba_group); 2933CONFIGFS_EATTR_OPS(target_core_hba, se_hba, hba_group);
2915 2934
2935static void target_core_hba_release(struct config_item *item)
2936{
2937 struct se_hba *hba = container_of(to_config_group(item),
2938 struct se_hba, hba_group);
2939 core_delete_hba(hba);
2940}
2941
2916static struct configfs_attribute *target_core_hba_attrs[] = { 2942static struct configfs_attribute *target_core_hba_attrs[] = {
2917 &target_core_hba_hba_info.attr, 2943 &target_core_hba_hba_info.attr,
2918 &target_core_hba_hba_mode.attr, 2944 &target_core_hba_hba_mode.attr,
@@ -2920,6 +2946,7 @@ static struct configfs_attribute *target_core_hba_attrs[] = {
2920}; 2946};
2921 2947
2922static struct configfs_item_operations target_core_hba_item_ops = { 2948static struct configfs_item_operations target_core_hba_item_ops = {
2949 .release = target_core_hba_release,
2923 .show_attribute = target_core_hba_attr_show, 2950 .show_attribute = target_core_hba_attr_show,
2924 .store_attribute = target_core_hba_attr_store, 2951 .store_attribute = target_core_hba_attr_store,
2925}; 2952};
@@ -2996,10 +3023,11 @@ static void target_core_call_delhbafromtarget(
2996 struct config_group *group, 3023 struct config_group *group,
2997 struct config_item *item) 3024 struct config_item *item)
2998{ 3025{
2999 struct se_hba *hba = item_to_hba(item); 3026 /*
3000 3027 * core_delete_hba() is called from target_core_hba_item_ops->release()
3028 * -> target_core_hba_release()
3029 */
3001 config_item_put(item); 3030 config_item_put(item);
3002 core_delete_hba(hba);
3003} 3031}
3004 3032
3005static struct configfs_group_operations target_core_group_ops = { 3033static struct configfs_group_operations target_core_group_ops = {