Skip to content

Commit 408c97c

Browse files
LeviYeoReumSuzuki K Poulose
authored andcommitted
coresight: prevent deactivate active config while enabling the config
While enable active config via cscfg_csdev_enable_active_config(), active config could be deactivated via configfs' sysfs interface. This could make UAF issue in below scenario: CPU0 CPU1 (sysfs enable) load module cscfg_load_config_sets() activate config. // sysfs (sys_active_cnt == 1) ... cscfg_csdev_enable_active_config() lock(csdev->cscfg_csdev_lock) // here load config activate by CPU1 unlock(csdev->cscfg_csdev_lock) deactivate config // sysfs (sys_activec_cnt == 0) cscfg_unload_config_sets() unload module // access to config_desc which freed // while unloading module. cscfg_csdev_enable_config To address this, use cscfg_config_desc's active_cnt as a reference count which will be holded when - activate the config. - enable the activated config. and put the module reference when config_active_cnt == 0. Fixes: f8cce2f ("coresight: syscfg: Add API to activate and enable configurations") Suggested-by: Suzuki K Poulose <[email protected]> Signed-off-by: Yeoreum Yun <[email protected]> Reviewed-by: Leo Yan <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 53b9e26 commit 408c97c

File tree

2 files changed

+35
-16
lines changed

2 files changed

+35
-16
lines changed

drivers/hwtracing/coresight/coresight-config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ struct cscfg_feature_csdev {
228228
* @feats_csdev:references to the device features to enable.
229229
*/
230230
struct cscfg_config_csdev {
231-
const struct cscfg_config_desc *config_desc;
231+
struct cscfg_config_desc *config_desc;
232232
struct coresight_device *csdev;
233233
bool enabled;
234234
struct list_head node;

drivers/hwtracing/coresight/coresight-syscfg.c

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,25 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
869869
}
870870
EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
871871

872+
static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc)
873+
{
874+
if (!atomic_fetch_inc(&config_desc->active_cnt)) {
875+
/* must ensure that config cannot be unloaded in use */
876+
if (unlikely(cscfg_owner_get(config_desc->load_owner))) {
877+
atomic_dec(&config_desc->active_cnt);
878+
return false;
879+
}
880+
}
881+
882+
return true;
883+
}
884+
885+
static void cscfg_config_desc_put(struct cscfg_config_desc *config_desc)
886+
{
887+
if (!atomic_dec_return(&config_desc->active_cnt))
888+
cscfg_owner_put(config_desc->load_owner);
889+
}
890+
872891
/*
873892
* This activate configuration for either perf or sysfs. Perf can have multiple
874893
* active configs, selected per event, sysfs is limited to one.
@@ -892,22 +911,17 @@ static int _cscfg_activate_config(unsigned long cfg_hash)
892911
if (config_desc->available == false)
893912
return -EBUSY;
894913

895-
/* must ensure that config cannot be unloaded in use */
896-
err = cscfg_owner_get(config_desc->load_owner);
897-
if (err)
914+
if (!cscfg_config_desc_get(config_desc)) {
915+
err = -EINVAL;
898916
break;
917+
}
918+
899919
/*
900920
* increment the global active count - control changes to
901921
* active configurations
902922
*/
903923
atomic_inc(&cscfg_mgr->sys_active_cnt);
904924

905-
/*
906-
* mark the descriptor as active so enable config on a
907-
* device instance will use it
908-
*/
909-
atomic_inc(&config_desc->active_cnt);
910-
911925
err = 0;
912926
dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
913927
break;
@@ -922,9 +936,8 @@ static void _cscfg_deactivate_config(unsigned long cfg_hash)
922936

923937
list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
924938
if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
925-
atomic_dec(&config_desc->active_cnt);
926939
atomic_dec(&cscfg_mgr->sys_active_cnt);
927-
cscfg_owner_put(config_desc->load_owner);
940+
cscfg_config_desc_put(config_desc);
928941
dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
929942
break;
930943
}
@@ -1049,7 +1062,7 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
10491062
unsigned long cfg_hash, int preset)
10501063
{
10511064
struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
1052-
const struct cscfg_config_desc *config_desc;
1065+
struct cscfg_config_desc *config_desc;
10531066
unsigned long flags;
10541067
int err = 0;
10551068

@@ -1064,8 +1077,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
10641077
raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
10651078
list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
10661079
config_desc = config_csdev_item->config_desc;
1067-
if ((atomic_read(&config_desc->active_cnt)) &&
1068-
((unsigned long)config_desc->event_ea->var == cfg_hash)) {
1080+
if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
1081+
cscfg_config_desc_get(config_desc)) {
10691082
config_csdev_active = config_csdev_item;
10701083
csdev->active_cscfg_ctxt = (void *)config_csdev_active;
10711084
break;
@@ -1099,7 +1112,11 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
10991112
err = -EBUSY;
11001113
raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
11011114
}
1115+
1116+
if (err)
1117+
cscfg_config_desc_put(config_desc);
11021118
}
1119+
11031120
return err;
11041121
}
11051122
EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
@@ -1138,8 +1155,10 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
11381155
raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
11391156

11401157
/* true if there was an enabled active config */
1141-
if (config_csdev)
1158+
if (config_csdev) {
11421159
cscfg_csdev_disable_config(config_csdev);
1160+
cscfg_config_desc_put(config_csdev->config_desc);
1161+
}
11431162
}
11441163
EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
11451164

0 commit comments

Comments
 (0)