static inline int sanity_check(struct efi_variable *var, efi_char16_t *name, efi_guid_t vendor, unsigned long size, u32 attributes, u8 *data) { /* * If only updating the variable data, then the name * and guid should remain the same */ if (memcmp(name, var->VariableName, sizeof(var->VariableName)) || efi_guidcmp(vendor, var->VendorGuid)) { printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n"); return -EINVAL; } if ((size <= 0) || (attributes == 0)) { printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n"); return -EINVAL; } if ((attributes & ~EFI_VARIABLE_MASK) != 0 || efivar_validate(vendor, name, data, size) == false) { printk(KERN_ERR "efivars: Malformed variable content\n"); return -EINVAL; } return 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; }
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; }