On Friday, January 25, 2019 8:23:07 AM CET Viresh Kumar wrote: > The cpufreq_global_kobject is created using kobject_create_and_add() > helper, which assigns the kobj_type as dynamic_kobj_ktype and show/store > routines are set to kobj_attr_show() and kobj_attr_store(). > > These routines pass struct kobj_attribute as an argument to the > show/store callbacks. But all the cpufreq files created using the > cpufreq_global_kobject expect the argument to be of type struct > attribute. Things work fine currently as no one accesses the "attr" > argument. We may not see issues even if the argument is used, as struct > kobj_attribute has struct attribute as its first element and so they > will both get same address. > > But this is logically incorrect and we should rather use struct > kobj_attribute instead of struct global_attr in the cpufreq core and > drivers and the show/store callbacks should take struct kobj_attribute > as argument instead. > > This bug is caught using CFI CLANG builds in android kernel which > catches mismatch in function prototypes for such callbacks. > > Reported-by: Donghee Han <dh....@samsung.com> > Reported-by: Sangkyu Kim <skwith....@samsung.com> > Signed-off-by: Viresh Kumar <viresh.ku...@linaro.org> > --- > drivers/cpufreq/cpufreq.c | 6 +++--- > drivers/cpufreq/intel_pstate.c | 23 ++++++++++++----------- > include/linux/cpufreq.h | 12 ++---------- > 3 files changed, 17 insertions(+), 24 deletions(-) > > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c > index e35a886e00bc..ef0e33e21b98 100644 > --- a/drivers/cpufreq/cpufreq.c > +++ b/drivers/cpufreq/cpufreq.c > @@ -545,13 +545,13 @@ EXPORT_SYMBOL_GPL(cpufreq_policy_transition_delay_us); > * SYSFS INTERFACE * > *********************************************************************/ > static ssize_t show_boost(struct kobject *kobj, > - struct attribute *attr, char *buf) > + struct kobj_attribute *attr, char *buf) > { > return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled); > } > > -static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, > - const char *buf, size_t count) > +static ssize_t store_boost(struct kobject *kobj, struct kobj_attribute *attr, > + const char *buf, size_t count) > { > int ret, enable; > > diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c > index dd66decf2087..5ab6a4fe93aa 100644 > --- a/drivers/cpufreq/intel_pstate.c > +++ b/drivers/cpufreq/intel_pstate.c > @@ -895,7 +895,7 @@ static void intel_pstate_update_policies(void) > /************************** sysfs begin ************************/ > #define show_one(file_name, object) \ > static ssize_t show_##file_name \ > - (struct kobject *kobj, struct attribute *attr, char *buf) \ > + (struct kobject *kobj, struct kobj_attribute *attr, char *buf) \ > { \ > return sprintf(buf, "%u\n", global.object); \ > } > @@ -904,7 +904,7 @@ static ssize_t intel_pstate_show_status(char *buf); > static int intel_pstate_update_status(const char *buf, size_t size); > > static ssize_t show_status(struct kobject *kobj, > - struct attribute *attr, char *buf) > + struct kobj_attribute *attr, char *buf) > { > ssize_t ret; > > @@ -915,7 +915,7 @@ static ssize_t show_status(struct kobject *kobj, > return ret; > } > > -static ssize_t store_status(struct kobject *a, struct attribute *b, > +static ssize_t store_status(struct kobject *a, struct kobj_attribute *b, > const char *buf, size_t count) > { > char *p = memchr(buf, '\n', count); > @@ -929,7 +929,7 @@ static ssize_t store_status(struct kobject *a, struct > attribute *b, > } > > static ssize_t show_turbo_pct(struct kobject *kobj, > - struct attribute *attr, char *buf) > + struct kobj_attribute *attr, char *buf) > { > struct cpudata *cpu; > int total, no_turbo, turbo_pct; > @@ -955,7 +955,7 @@ static ssize_t show_turbo_pct(struct kobject *kobj, > } > > static ssize_t show_num_pstates(struct kobject *kobj, > - struct attribute *attr, char *buf) > + struct kobj_attribute *attr, char *buf) > { > struct cpudata *cpu; > int total; > @@ -976,7 +976,7 @@ static ssize_t show_num_pstates(struct kobject *kobj, > } > > static ssize_t show_no_turbo(struct kobject *kobj, > - struct attribute *attr, char *buf) > + struct kobj_attribute *attr, char *buf) > { > ssize_t ret; > > @@ -998,7 +998,7 @@ static ssize_t show_no_turbo(struct kobject *kobj, > return ret; > } > > -static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, > +static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b, > const char *buf, size_t count) > { > unsigned int input; > @@ -1045,7 +1045,7 @@ static ssize_t store_no_turbo(struct kobject *a, struct > attribute *b, > return count; > } > > -static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, > +static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute > *b, > const char *buf, size_t count) > { > unsigned int input; > @@ -1075,7 +1075,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, > struct attribute *b, > return count; > } > > -static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, > +static ssize_t store_min_perf_pct(struct kobject *a, struct kobj_attribute > *b, > const char *buf, size_t count) > { > unsigned int input; > @@ -1107,12 +1107,13 @@ static ssize_t store_min_perf_pct(struct kobject *a, > struct attribute *b, > } > > static ssize_t show_hwp_dynamic_boost(struct kobject *kobj, > - struct attribute *attr, char *buf) > + struct kobj_attribute *attr, char *buf) > { > return sprintf(buf, "%u\n", hwp_boost); > } > > -static ssize_t store_hwp_dynamic_boost(struct kobject *a, struct attribute > *b, > +static ssize_t store_hwp_dynamic_boost(struct kobject *a, > + struct kobj_attribute *b, > const char *buf, size_t count) > { > unsigned int input; > diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h > index c86d6d8bdfed..0b427d5df0fe 100644 > --- a/include/linux/cpufreq.h > +++ b/include/linux/cpufreq.h > @@ -254,20 +254,12 @@ __ATTR(_name, 0644, show_##_name, store_##_name) > static struct freq_attr _name = \ > __ATTR(_name, 0200, NULL, store_##_name) > > -struct global_attr { > - struct attribute attr; > - ssize_t (*show)(struct kobject *kobj, > - struct attribute *attr, char *buf); > - ssize_t (*store)(struct kobject *a, struct attribute *b, > - const char *c, size_t count); > -}; > - > #define define_one_global_ro(_name) \ > -static struct global_attr _name = \ > +static struct kobj_attribute _name = \ > __ATTR(_name, 0444, show_##_name, NULL) > > #define define_one_global_rw(_name) \ > -static struct global_attr _name = \ > +static struct kobj_attribute _name = \ > __ATTR(_name, 0644, show_##_name, store_##_name) > > >
Applied, thanks!