diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-02-09 18:34:54 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-12 13:32:41 -0500 |
commit | 1f6fe7cba1c0a817a8712d7fdd0ec1b4ddd4ea2f (patch) | |
tree | d3210e224f8c415d78fbf70883026fa945591b8a /drivers/target/target_core_configfs.c | |
parent | e89d15eeadb172bd53ca6362bf9ab6b22077224c (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.c | 120 |
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 | ||
1982 | static ssize_t target_core_dev_show(struct config_item *item, | 2004 | static 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 | ||
2164 | static 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 | |||
2142 | static struct configfs_item_operations target_core_alua_lu_gp_ops = { | 2172 | static 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 | ||
2198 | static struct configfs_group_operations target_core_alua_lu_gps_group_ops = { | 2231 | static 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 | ||
2584 | static 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 | |||
2551 | static struct configfs_item_operations target_core_alua_tg_pt_gp_ops = { | 2592 | static 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 | ||
2609 | static struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = { | 2653 | static 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 | |||
2830 | hba_out: | ||
2831 | mutex_unlock(&hba->hba_access_mutex); | 2852 | mutex_unlock(&hba->hba_access_mutex); |
2832 | out: | ||
2833 | kfree(se_dev); | ||
2834 | } | 2853 | } |
2835 | 2854 | ||
2836 | static struct configfs_group_operations target_core_hba_group_ops = { | 2855 | static struct configfs_group_operations target_core_hba_group_ops = { |
@@ -2913,6 +2932,13 @@ SE_HBA_ATTR(hba_mode, S_IRUGO | S_IWUSR); | |||
2913 | 2932 | ||
2914 | CONFIGFS_EATTR_OPS(target_core_hba, se_hba, hba_group); | 2933 | CONFIGFS_EATTR_OPS(target_core_hba, se_hba, hba_group); |
2915 | 2934 | ||
2935 | static 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 | |||
2916 | static struct configfs_attribute *target_core_hba_attrs[] = { | 2942 | static 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 | ||
2922 | static struct configfs_item_operations target_core_hba_item_ops = { | 2948 | static 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 | ||
3005 | static struct configfs_group_operations target_core_group_ops = { | 3033 | static struct configfs_group_operations target_core_group_ops = { |