/*
 * We allow each variable to be edited via rewriting the
 * entire efi variable structure.
 */
static ssize_t
efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
{
    struct efi_variable *new_var, *var = &entry->var;
    efi_char16_t *name;
    unsigned long size;
    efi_guid_t vendor;
    u32 attributes;
    u8 *data;
    int err;

    if (is_compat()) {
        struct compat_efi_variable *compat;

        if (count != sizeof(*compat))
            return -EINVAL;

        compat = (struct compat_efi_variable *)buf;
        attributes = compat->Attributes;
        vendor = compat->VendorGuid;
        name = compat->VariableName;
        size = compat->DataSize;
        data = compat->Data;

        err = sanity_check(var, name, vendor, size, attributes, data);
        if (err)
            return err;

        copy_out_compat(&entry->var, compat);
    } else {
        if (count != sizeof(struct efi_variable))
            return -EINVAL;

        new_var = (struct efi_variable *)buf;

        attributes = new_var->Attributes;
        vendor = new_var->VendorGuid;
        name = new_var->VariableName;
        size = new_var->DataSize;
        data = new_var->Data;

        err = sanity_check(var, name, vendor, size, attributes, data);
        if (err)
            return err;

        memcpy(&entry->var, new_var, count);
    }

    err = efivar_entry_set(entry, attributes, size, data, NULL);
    if (err) {
        printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
        return -EIO;
    }

    return count;
}
Beispiel #2
0
/*
 * We allow each variable to be edited via rewriting the
 * entire efi variable structure.
 */
static ssize_t
efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
{
	struct efi_variable *new_var, *var = &entry->var;
	int err;

	if (count != sizeof(struct efi_variable))
		return -EINVAL;

	new_var = (struct efi_variable *)buf;
	/*
	 * If only updating the variable data, then the name
	 * and guid should remain the same
	 */
	if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) ||
		efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) {
		printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
		return -EINVAL;
	}

	if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){
		printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
		return -EINVAL;
	}

	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
	    efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
		printk(KERN_ERR "efivars: Malformed variable content\n");
		return -EINVAL;
	}

	memcpy(&entry->var, new_var, count);

	err = efivar_entry_set(entry, new_var->Attributes,
			       new_var->DataSize, new_var->Data, false);
	if (err) {
		printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
		return -EIO;
	}

	return count;
}
Beispiel #3
0
static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
			     struct bin_attribute *bin_attr,
			     char *buf, loff_t pos, size_t count)
{
	struct efi_variable *new_var = (struct efi_variable *)buf;
	struct efivar_entry *new_entry;
	int err;

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;

	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
	    efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
		printk(KERN_ERR "efivars: Malformed variable content\n");
		return -EINVAL;
	}

	new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
	if (!new_entry)
		return -ENOMEM;

	memcpy(&new_entry->var, new_var, sizeof(*new_var));

	err = efivar_entry_set(new_entry, new_var->Attributes, new_var->DataSize,
			       new_var->Data, &efivar_sysfs_list);
	if (err) {
		if (err == -EEXIST)
			err = -EINVAL;
		goto out;
	}

	if (efivar_create_sysfs_entry(new_entry)) {
		printk(KERN_WARNING "efivars: failed to create sysfs entry.\n");
		kfree(new_entry);
	}
	return count;

out:
	kfree(new_entry);
	return err;
}
static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
                             struct bin_attribute *bin_attr,
                             char *buf, loff_t pos, size_t count)
{
    struct compat_efi_variable *compat = (struct compat_efi_variable *)buf;
    struct efi_variable *new_var = (struct efi_variable *)buf;
    struct efivar_entry *new_entry;
    bool need_compat = is_compat();
    efi_char16_t *name;
    unsigned long size;
    u32 attributes;
    u8 *data;
    int err;

    if (!capable(CAP_SYS_ADMIN))
        return -EACCES;

    if (need_compat) {
        if (count != sizeof(*compat))
            return -EINVAL;

        attributes = compat->Attributes;
        name = compat->VariableName;
        size = compat->DataSize;
        data = compat->Data;
    } else {
        if (count != sizeof(*new_var))
            return -EINVAL;

        attributes = new_var->Attributes;
        name = new_var->VariableName;
        size = new_var->DataSize;
        data = new_var->Data;
    }

    if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
            efivar_validate(new_var->VendorGuid, name, data,
                            size) == false) {
        printk(KERN_ERR "efivars: Malformed variable content\n");
        return -EINVAL;
    }

    new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
    if (!new_entry)
        return -ENOMEM;

    if (need_compat)
        copy_out_compat(&new_entry->var, compat);
    else
        memcpy(&new_entry->var, new_var, sizeof(*new_var));

    err = efivar_entry_set(new_entry, attributes, size,
                           data, &efivar_sysfs_list);
    if (err) {
        if (err == -EEXIST)
            err = -EINVAL;
        goto out;
    }

    if (efivar_create_sysfs_entry(new_entry)) {
        printk(KERN_WARNING "efivars: failed to create sysfs entry.\n");
        kfree(new_entry);
    }
    return count;

out:
    kfree(new_entry);
    return err;
}