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] [day] [month] [year] [list]
Message-ID: <670d860b-f6fc-4ef1-ba05-bbce24ed82fd@gmail.com>
Date: Mon, 2 Dec 2024 08:44:57 +0200
From: Matti Vaittinen <mazziesaccount@...il.com>
To: Jonathan Cameron <jic23@...nel.org>
Cc: Matti Vaittinen <matti.vaittinen@...rohmeurope.com>,
 Lars-Peter Clausen <lars@...afoo.de>, linux-iio@...r.kernel.org,
 linux-kernel@...r.kernel.org
Subject: Re: [PATCH 1/3] iio: gts: Simplify using __free

On 30/11/2024 19:51, Jonathan Cameron wrote:
> On Thu, 28 Nov 2024 18:50:24 +0200
> Matti Vaittinen <mazziesaccount@...il.com> wrote:
> 
>> The error path in the gain_to_scaletables() uses goto for unwinding an
>> allocation on failure. This can be slightly simplified by using the
>> automated free when exiting the scope.
>>
>> Use __free(kfree) and drop the goto based error handling.
>>
>> Signed-off-by: Matti Vaittinen <mazziesaccount@...il.com>
>> ---
>> This is derived from the:
>> https://lore.kernel.org/lkml/5efc30d832275778d1f48d7e2c75b1ecc63511d5.1732105157.git.mazziesaccount@gmail.com/
> 
> Hi Matti
> 
> A few comments on specific parts of this below
> 
> Thanks,
> 
> Jonathan
> 
>> +static int build_combined_table(struct iio_gts *gts, int **gains, size_t gain_bytes)
>> +{
>> +	int ret, i, j, new_idx, time_idx;
>> +	int *all_gains __free(kfree) = kcalloc(gts->num_itime, gain_bytes,
>> +					       GFP_KERNEL);
>> +
>>   	if (!all_gains)
>>   		return -ENOMEM;
>>   
>> @@ -232,10 +238,9 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
>>   
>>   	gts->avail_all_scales_table = kcalloc(new_idx, 2 * sizeof(int),
>>   					      GFP_KERNEL);
> 
> I'm not particularly keen in a partial application of __free magic.

I am starting to think the partial application of __free would actually 
be what I preferred... (see below).

> Perhaps you can use a local variable for this and a no_free_ptr() to assign it after we know
> there can't be an error that requires it to be freed.

I am having second thoughts of this whole series. I do love the idea of 
__free() magic, when applied on a simple temporary allocations that are 
intended to be freed at the end of a function. Eg, for cases where we 
know the scope from the very beginning. With a consistent use of __free 
in such cases could make it much more obvious for a reader that this 
stuff is valid only for a duration of this block. I have a feeling that 
mixing the no_free_ptr() is a violation, and will obfuscate this.

I know I used it in this series while trying to simplify the flow - and 
I am already regretting this.

Additionally, I indeed am not okay with introducing variables in middle 
of a function. I do really feel quite strongly about that.

It seems that in many functions it makes sense to have some checks or 
potentially failing operations done before doing memory allocations. So, 
keeping the allocation at the start of a block can often require some 
additional "check/do these things before calling an internal function 
which does alloc + rest of the work" -wrappers.

It will then also mean that the internal function (called from a wrapper 
with checks) will lack of the aforementioned checks, and, is thus 
somehow unsafe. I am not saying such wrappers are always wrong - 
sometimes it may be ok - but it probably should be consistent approach 
and not a mixture of conventions depending on allocations...

Also, sometimes this would result some very strangely split functions 
with no well defined purpose.

As a result, I would definitely only use the "__free magic" in places 
where it does fit well for freeing a memory which is known to be needed 
only for a specific block. And, I would only use it where the alloc can 
be done at the beginning of a function in a rather natural way. This, 
however, is very likely to lead in mixed use of "__free magic" and 
regular allocs.

>> -	if (!gts->avail_all_scales_table) {
>> -		ret = -ENOMEM;
>> -		goto free_out;
>> -	}
>> +	if (!gts->avail_all_scales_table)
>> +		return -ENOMEM;
>> +
>>   	gts->num_avail_all_scales = new_idx;
>>   
>>   	for (i = 0; i < gts->num_avail_all_scales; i++) {
>> @@ -246,14 +251,25 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
>>   		if (ret) {
>>   			kfree(gts->avail_all_scales_table);
>>   			gts->num_avail_all_scales = 0;
>> -			goto free_out;
>> +			return ret;
>>   		}
>>   	}
>>   
>> -free_out:
>> -	kfree(all_gains);
>> +	return 0;
>> +}
>>   
>> -	return ret;
>> +static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
>> +{
>> +	int ret;
>> +	size_t gain_bytes;
>> +
>> +	ret = fill_and_sort_scaletables(gts, gains, scales);
>> +	if (ret)
>> +		return ret;
>> +
>> +	gain_bytes = array_size(gts->num_hwgain, sizeof(int));
> 
> array_size is documented as being for 2D arrays, not an array of a multi byte
> type.  We should not use it for this purpose.

Thanks for pointing this out. I was not familiar with that. I am 
actually pretty sure that using the array_size() has been recommended to 
me :)

> I'd be tempted to not worry about overflow, but if you do want to be sure then
> copy what kcalloc does and use a check_mul_overflow()
> 
> https://elixir.bootlin.com/linux/v6.12.1/source/include/linux/slab.h#L919

Thanks for the direct pointer :) I'll take a look at it!

> 
> You don't have to tidy that up in this patch though.
> 
>> +
>> +	return build_combined_table(gts, gains, gain_bytes);
>>   }
> 
>>   
>> +/**
>> + * iio_gts_build_avail_time_table - build table of available integration times
>> + * @gts:	Gain time scale descriptor
>> + *
>> + * Build the table which can represent the available times to be returned
>> + * to users using the read_avail-callback.
>> + *
>> + * NOTE: Space allocated for the tables must be freed using
>> + * iio_gts_purge_avail_time_table() when the tables are no longer needed.
>> + *
>> + * Return: 0 on success.
>> + */
>> +static int iio_gts_build_avail_time_table(struct iio_gts *gts)
> Hmm. I guess this wrapper exists because perhaps you aren't comfortable
> yet with the __free() handling mid function.  It does not harm so I'm fine
> having this.

Yes. This was the reason for this wrapper. But I'm not really happy 
about the wrappers either (even if I agree with you that it does not 
really hurt here). Furthermore, if you're feeling strongly about not 
mixing the __free and regular allocs, then I simply prefer not using the 
magic one. I don't think using the __free with allocations intended to 
last longer than the scope is clear. Ues, goto sequences may not always 
be simple, but at least people are used to be wary with them.

>> +{
>> +	if (!gts->num_itime)
>> +		return 0;
>> +
>> +	return __iio_gts_build_avail_time_table(gts);
>> +}
>> +
>>   /**
>>    * iio_gts_purge_avail_time_table - free-up the available integration time table
>>    * @gts:	Gain time scale descriptor
> 

Thanks a ton for the review :) It helped me to clarify my thoughts on this!

Yours,
	-- Matti


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ