brintos

brintos / linux-shallow public Read only

0
0
Text · 2.4 KiB · 23c51d6 Raw
114 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2012 Red Hat, Inc.4 * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>5 */6 7#include <linux/efi.h>8#include <linux/delay.h>9#include <linux/fs.h>10#include <linux/slab.h>11#include <linux/mount.h>12 13#include "internal.h"14 15static ssize_t efivarfs_file_write(struct file *file,16		const char __user *userbuf, size_t count, loff_t *ppos)17{18	struct efivar_entry *var = file->private_data;19	void *data;20	u32 attributes;21	struct inode *inode = file->f_mapping->host;22	unsigned long datasize = count - sizeof(attributes);23	ssize_t bytes;24	bool set = false;25 26	if (count < sizeof(attributes))27		return -EINVAL;28 29	if (copy_from_user(&attributes, userbuf, sizeof(attributes)))30		return -EFAULT;31 32	if (attributes & ~(EFI_VARIABLE_MASK))33		return -EINVAL;34 35	data = memdup_user(userbuf + sizeof(attributes), datasize);36	if (IS_ERR(data))37		return PTR_ERR(data);38 39	bytes = efivar_entry_set_get_size(var, attributes, &datasize,40					  data, &set);41	if (!set && bytes) {42		if (bytes == -ENOENT)43			bytes = -EIO;44		goto out;45	}46 47	if (bytes == -ENOENT) {48		drop_nlink(inode);49		d_delete(file->f_path.dentry);50		dput(file->f_path.dentry);51	} else {52		inode_lock(inode);53		i_size_write(inode, datasize + sizeof(attributes));54		inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));55		inode_unlock(inode);56	}57 58	bytes = count;59 60out:61	kfree(data);62 63	return bytes;64}65 66static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,67		size_t count, loff_t *ppos)68{69	struct efivar_entry *var = file->private_data;70	unsigned long datasize = 0;71	u32 attributes;72	void *data;73	ssize_t size = 0;74	int err;75 76	while (!__ratelimit(&file->f_cred->user->ratelimit))77		msleep(50);78 79	err = efivar_entry_size(var, &datasize);80 81	/*82	 * efivarfs represents uncommitted variables with83	 * zero-length files. Reading them should return EOF.84	 */85	if (err == -ENOENT)86		return 0;87	else if (err)88		return err;89 90	data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);91 92	if (!data)93		return -ENOMEM;94 95	size = efivar_entry_get(var, &attributes, &datasize,96				data + sizeof(attributes));97	if (size)98		goto out_free;99 100	memcpy(data, &attributes, sizeof(attributes));101	size = simple_read_from_buffer(userbuf, count, ppos,102				       data, datasize + sizeof(attributes));103out_free:104	kfree(data);105 106	return size;107}108 109const struct file_operations efivarfs_file_operations = {110	.open	= simple_open,111	.read	= efivarfs_file_read,112	.write	= efivarfs_file_write,113};114