On Wed, Mar 16, 2022 at 5:06 PM Krzysztof Kozlowski krzysztof.kozlowski@canonical.com wrote:
...
+int driver_set_override(struct device *dev, const char **override,
const char *s, size_t len)
+{
const char *new, *old;
char *cp;
if (!dev || !override || !s)
return -EINVAL;
Sorry, I didn't pay much attention on this. First of all, I would drop dev checks and simply require that dev should be valid. Do you expect this can be called when dev is invalid? I would like to hear if it's anything but theoretical. Second one, is the !s requirement. Do I understand correctly that the string must be always present? But then how we NULify the override? Is it possible? Third one is absence of len check. See below.
/*
* The stored value will be used in sysfs show callback (sysfs_emit()),
* which has a length limit of PAGE_SIZE and adds a trailing newline.
* Thus we can store one character less to avoid truncation during sysfs
* show.
*/
if (len >= (PAGE_SIZE - 1))
return -EINVAL;
I would relax this to make sure we can use it if \n is within this limit.
cp = strnchr(s, len, '\n');
if (cp)
len = cp - s;
new = kstrndup(s, len, GFP_KERNEL);
Here is a word about the len check.
if (!new)
If len == 0, this won't trigger and you have something very interesting as a result.
One way is to use ZERO_PTR_OR_NULL() another is explicitly check for 0 and issue a (different?) error code.
return -ENOMEM;
device_lock(dev);
old = *override;
if (cp != s) {
*override = new;
} else {
kfree(new);
*override = NULL;
}
device_unlock(dev);
kfree(old);
return 0;
+}