lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <bf508c29-4a51-5f97-8459-06c1fe74b60f@canonical.com>
Date:   Thu, 11 Mar 2021 11:24:55 +0000
From:   Colin Ian King <colin.king@...onical.com>
To:     Michal Simek <michal.simek@...inx.com>
Cc:     Linus Walleij <linus.walleij@...aro.org>,
        "linux-gpio@...r.kernel.org" <linux-gpio@...r.kernel.org>,
        "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
Subject: Re: pinctrl: core: Handling pinmux and pinconf separately

On 11/03/2021 11:16, Michal Simek wrote:
> 
> 
> On 3/11/21 11:57 AM, Colin Ian King wrote:
>> Hi,
>>
>> Static analysis on linux-next with Coverity has found a potential issue
>> in drivers/pinctrl/core.c with the following commit:
>>
>> commit 0952b7ec1614abf232e921aac0cc2bca8e60e162
>> Author: Michal Simek <michal.simek@...inx.com>
>> Date:   Wed Mar 10 09:16:54 2021 +0100
>>
>>     pinctrl: core: Handling pinmux and pinconf separately
>>
>> The analysis is as follows:
>>
>> 1234 /**
>> 1235  * pinctrl_commit_state() - select/activate/program a pinctrl state
>> to HW
>> 1236  * @p: the pinctrl handle for the device that requests configuration
>> 1237  * @state: the state handle to select/activate/program
>> 1238  */
>> 1239 static int pinctrl_commit_state(struct pinctrl *p, struct
>> pinctrl_state *state)
>> 1240 {
>> 1241        struct pinctrl_setting *setting, *setting2;
>> 1242        struct pinctrl_state *old_state = p->state;
>>
>>     1. var_decl: Declaring variable ret without initializer.
>>
>> 1243        int ret;
>> 1244
>>
>>     2. Condition p->state, taking true branch.
>>
>> 1245        if (p->state) {
>> 1246                /*
>> 1247                 * For each pinmux setting in the old state, forget
>> SW's record
>> 1248                 * of mux owner for that pingroup. Any pingroups
>> which are
>> 1249                 * still owned by the new state will be re-acquired
>> by the call
>> 1250                 * to pinmux_enable_setting() in the loop below.
>> 1251                 */
>>
>>     3. Condition 0 /* !!(!__builtin_types_compatible_p() &&
>> !__builtin_types_compatible_p()) */, taking false branch.
>>     4. Condition !(&setting->node == &p->state->settings), taking true
>> branch.
>>     7. Condition 0 /* !!(!__builtin_types_compatible_p() &&
>> !__builtin_types_compatible_p()) */, taking false branch.
>>     8. Condition !(&setting->node == &p->state->settings), taking true
>> branch.
>>     11. Condition 0 /* !!(!__builtin_types_compatible_p() &&
>> !__builtin_types_compatible_p()) */, taking false branch.
>>     12. Condition !(&setting->node == &p->state->settings), taking false
>> branch.
>>
>> 1252                list_for_each_entry(setting, &p->state->settings,
>> node) {
>>
>>     5. Condition setting->type != PIN_MAP_TYPE_MUX_GROUP, taking true
>> branch.
>>     9. Condition setting->type != PIN_MAP_TYPE_MUX_GROUP, taking true
>> branch.
>> 1253                        if (setting->type != PIN_MAP_TYPE_MUX_GROUP)
>>     6. Continuing loop.
>>     10. Continuing loop.
>>
>> 1254                                continue;
>> 1255                        pinmux_disable_setting(setting);
>> 1256                }
>> 1257        }
>> 1258
>> 1259        p->state = NULL;
>> 1260
>> 1261        /* Apply all the settings for the new state - pinmux first */
>>
>>     13. Condition 0 /* !!(!__builtin_types_compatible_p() &&
>> !__builtin_types_compatible_p()) */, taking false branch.
>>     14. Condition !(&setting->node == &state->settings), taking true branch.
>> 1262        list_for_each_entry(setting, &state->settings, node) {
>>     15. Switch case value PIN_MAP_TYPE_CONFIGS_PIN.
>>
>> 1263                switch (setting->type) {
>> 1264                case PIN_MAP_TYPE_MUX_GROUP:
>> 1265                        ret = pinmux_enable_setting(setting);
>> 1266                        break;
>> 1267                case PIN_MAP_TYPE_CONFIGS_PIN:
>> 1268                case PIN_MAP_TYPE_CONFIGS_GROUP:
>>
>>     16. Breaking from switch.
>>
>> 1269                        break;
>> 1270                default:
>> 1271                        ret = -EINVAL;
>> 1272                        break;
>> 1273                }
>> 1274
>>
>>     Uninitialized scalar variable (UNINIT)
>>     17. uninit_use: Using uninitialized value ret.
>>
>> 1275                if (ret < 0)
>> 1276                        goto unapply_new_state;
>>
>> For the PIN_MAP_TYPE_CONFIGS_PIN and PIN_MAP_TYPE_CONFIGS_GROUP
>> setting->type cases the loop can break out with ret not being set. Since
>> ret has not been initialized it the ret < 0 check is checking against an
>> uninitialized value.
>>
>> I was not sure if the PIN_MAP_TYPE_CONFIGS_PIN and
>> PIN_MAP_TYPE_CONFIGS_GROUP cases should be setting ret and if so, what
>> the value of ret should be set to (is it an error condition or not?). Or
>> should ret be initialized to 0 or a default error value at the start of
>> the function.
>>
>> Hence I'm reporting this issue.
> 
> What about this? Is this passing static analysis?

It will take me 2 hours to re-run the analysis, but from eyeballing the
code I think the assignments will fix this.

Colin

> 
> diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
> index f5c32d2a3c91..136c323d855e 100644
> --- a/drivers/pinctrl/core.c
> +++ b/drivers/pinctrl/core.c
> @@ -1266,6 +1266,7 @@ static int pinctrl_commit_state(struct pinctrl *p,
> struct pinctrl_state *state)
>                         break;
>                 case PIN_MAP_TYPE_CONFIGS_PIN:
>                 case PIN_MAP_TYPE_CONFIGS_GROUP:
> +                       ret = 0;
>                         break;
>                 default:
>                         ret = -EINVAL;
> @@ -1284,6 +1285,7 @@ static int pinctrl_commit_state(struct pinctrl *p,
> struct pinctrl_state *state)
>         list_for_each_entry(setting, &state->settings, node) {
>                 switch (setting->type) {
>                 case PIN_MAP_TYPE_MUX_GROUP:
> +                       ret = 0;
>                         break;
>                 case PIN_MAP_TYPE_CONFIGS_PIN:
>                 case PIN_MAP_TYPE_CONFIGS_GROUP:
> 
> Thanks,
> Michal
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ