> +static ssize_t efivarfs_file_write(struct file *file,
> +             const char __user *userbuf, size_t count, loff_t *ppos)
> +{
> +     struct efivar_entry *var = file->private_data;
> +     struct efivars *efivars;
> +     efi_status_t status;
> +     void *data;
> +     u32 attributes;
> +     struct inode *inode = file->f_mapping->host;
> +     int datasize = count - sizeof(attributes);

long ?

> +
> +     if (count < sizeof(attributes))
> +             return -EINVAL;
> +
> +     data = kmalloc(datasize, GFP_KERNEL);

This allows anyone who can open the file to allocate enormous amounts of
memory ... there should probably be a sanity check size here ?

> +     if (!data)
> +             return -ENOMEM;
> +
> +     efivars = var->efivars;
> +
> +     if (copy_from_user(&attributes, userbuf, sizeof(attributes))) {
> +             count = -EFAULT;

Nope.. size_t is not necessarily signed. ssize_t is. This probably
happens to do the right thing but it's not really right.

> +     switch (status) {
> +     case EFI_SUCCESS:

Would it make sense for EFI to have a generic 'efi_to_errno' ?

> +static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
> +             size_t count, loff_t *ppos)
> +{
> +     struct efivar_entry *var = file->private_data;
> +     struct efivars *efivars = var->efivars;
> +     efi_status_t status;
> +     unsigned long datasize = 0;
> +     u32 attributes;
> +     void *data;
> +     ssize_t size;
> +
> +     status = efivars->ops->get_variable(var->var.VariableName,
> +                                         &var->var.VendorGuid,
> +                                         &attributes, &datasize, NULL);
> +
> +     if (status != EFI_BUFFER_TOO_SMALL)
> +             return 0;

This seems odd - the writer translates error codes this doesnt.
> +
> +     data = kmalloc(datasize + 4, GFP_KERNEL);

Are you sure the firmware will never hand back insane datasize values ?

> +static const struct file_operations efivarfs_file_operations = {
> +     .open   = efivarfs_file_open,
> +     .read   = efivarfs_file_read,
> +     .write  = efivarfs_file_write,
> +     .llseek = default_llseek,

But you don't implement llseek in your read/write methods ?

> +             /* GUID plus trailing NULL */
> +             name = kmalloc(len + 38, GFP_ATOMIC);
> +
> +             for (i = 0; i < len; i++)
> +                     name[i] = entry->var.VariableName[i] & 0xFF;

Unchecked kmalloc - and an atomic one at that.

> +             dentry = d_alloc_name(root, name);

...


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to