in domain.c [164:237]
static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct tb *tb = container_of(dev, struct tb, dev);
char *str, *s, *uuid_str;
ssize_t ret = 0;
uuid_t *acl;
int i = 0;
/*
* Make sure the value is not bigger than tb->nboot_acl * UUID
* length + commas and optional "\n". Also the smallest allowable
* string is tb->nboot_acl * ",".
*/
if (count > (UUID_STRING_LEN + 1) * tb->nboot_acl + 1)
return -EINVAL;
if (count < tb->nboot_acl - 1)
return -EINVAL;
str = kstrdup(buf, GFP_KERNEL);
if (!str)
return -ENOMEM;
acl = kcalloc(tb->nboot_acl, sizeof(uuid_t), GFP_KERNEL);
if (!acl) {
ret = -ENOMEM;
goto err_free_str;
}
uuid_str = strim(str);
while ((s = strsep(&uuid_str, ",")) != NULL && i < tb->nboot_acl) {
size_t len = strlen(s);
if (len) {
if (len != UUID_STRING_LEN) {
ret = -EINVAL;
goto err_free_acl;
}
ret = uuid_parse(s, &acl[i]);
if (ret)
goto err_free_acl;
}
i++;
}
if (s || i < tb->nboot_acl) {
ret = -EINVAL;
goto err_free_acl;
}
pm_runtime_get_sync(&tb->dev);
if (mutex_lock_interruptible(&tb->lock)) {
ret = -ERESTARTSYS;
goto err_rpm_put;
}
ret = tb->cm_ops->set_boot_acl(tb, acl, tb->nboot_acl);
if (!ret) {
/* Notify userspace about the change */
kobject_uevent(&tb->dev.kobj, KOBJ_CHANGE);
}
mutex_unlock(&tb->lock);
err_rpm_put:
pm_runtime_mark_last_busy(&tb->dev);
pm_runtime_put_autosuspend(&tb->dev);
err_free_acl:
kfree(acl);
err_free_str:
kfree(str);
return ret ?: count;
}