diff options
author | Johan Hovold <johan@kernel.org> | 2018-06-12 08:43:35 -0400 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2018-06-18 07:26:05 -0400 |
commit | 6c974d4dfafe5e9ee754f2a6fba0eb1864f1649e (patch) | |
tree | 11dc79e35c192a794f6e36e996651f727e5507d0 | |
parent | 4708aa85d50cc6e962dfa8acf5ad4e0d290a21db (diff) |
EDAC, i7core: Fix memleaks and use-after-free on probe and remove
Make sure to free and deregister the addrmatch and chancounts devices
allocated during probe in all error paths. Also fix use-after-free in a
probe error path and in the remove success path where the devices were
being put before before deregistration.
Signed-off-by: Johan Hovold <johan@kernel.org>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: linux-edac <linux-edac@vger.kernel.org>
Fixes: 356f0a30860d ("i7core_edac: change the mem allocation scheme to make Documentation/kobject.txt happy")
Link: http://lkml.kernel.org/r/20180612124335.6420-2-johan@kernel.org
Signed-off-by: Borislav Petkov <bp@suse.de>
-rw-r--r-- | drivers/edac/i7core_edac.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 8ed4dd9c571b..8e120bf60624 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -1177,15 +1177,14 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) | |||
1177 | 1177 | ||
1178 | rc = device_add(pvt->addrmatch_dev); | 1178 | rc = device_add(pvt->addrmatch_dev); |
1179 | if (rc < 0) | 1179 | if (rc < 0) |
1180 | return rc; | 1180 | goto err_put_addrmatch; |
1181 | 1181 | ||
1182 | if (!pvt->is_registered) { | 1182 | if (!pvt->is_registered) { |
1183 | pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), | 1183 | pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), |
1184 | GFP_KERNEL); | 1184 | GFP_KERNEL); |
1185 | if (!pvt->chancounts_dev) { | 1185 | if (!pvt->chancounts_dev) { |
1186 | put_device(pvt->addrmatch_dev); | 1186 | rc = -ENOMEM; |
1187 | device_del(pvt->addrmatch_dev); | 1187 | goto err_del_addrmatch; |
1188 | return -ENOMEM; | ||
1189 | } | 1188 | } |
1190 | 1189 | ||
1191 | pvt->chancounts_dev->type = &all_channel_counts_type; | 1190 | pvt->chancounts_dev->type = &all_channel_counts_type; |
@@ -1199,9 +1198,18 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) | |||
1199 | 1198 | ||
1200 | rc = device_add(pvt->chancounts_dev); | 1199 | rc = device_add(pvt->chancounts_dev); |
1201 | if (rc < 0) | 1200 | if (rc < 0) |
1202 | return rc; | 1201 | goto err_put_chancounts; |
1203 | } | 1202 | } |
1204 | return 0; | 1203 | return 0; |
1204 | |||
1205 | err_put_chancounts: | ||
1206 | put_device(pvt->chancounts_dev); | ||
1207 | err_del_addrmatch: | ||
1208 | device_del(pvt->addrmatch_dev); | ||
1209 | err_put_addrmatch: | ||
1210 | put_device(pvt->addrmatch_dev); | ||
1211 | |||
1212 | return rc; | ||
1205 | } | 1213 | } |
1206 | 1214 | ||
1207 | static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) | 1215 | static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) |
@@ -1211,11 +1219,11 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) | |||
1211 | edac_dbg(1, "\n"); | 1219 | edac_dbg(1, "\n"); |
1212 | 1220 | ||
1213 | if (!pvt->is_registered) { | 1221 | if (!pvt->is_registered) { |
1214 | put_device(pvt->chancounts_dev); | ||
1215 | device_del(pvt->chancounts_dev); | 1222 | device_del(pvt->chancounts_dev); |
1223 | put_device(pvt->chancounts_dev); | ||
1216 | } | 1224 | } |
1217 | put_device(pvt->addrmatch_dev); | ||
1218 | device_del(pvt->addrmatch_dev); | 1225 | device_del(pvt->addrmatch_dev); |
1226 | put_device(pvt->addrmatch_dev); | ||
1219 | } | 1227 | } |
1220 | 1228 | ||
1221 | /**************************************************************************** | 1229 | /**************************************************************************** |