Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 481873d0 authored by James Morris's avatar James Morris
Browse files

Merge branch 'next' of...

parents 60209442 95ee08fa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ Description:

		base: 	func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
				[FIRMWARE_CHECK]
				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
			       [[^]MAY_EXEC]
			fsmagic:= hex value
+23 −51
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/sched.h>
#include <linux/file.h>
#include <linux/list.h>
#include <linux/fs.h>
#include <linux/async.h>
#include <linux/pm.h>
#include <linux/suspend.h>
@@ -291,40 +292,19 @@ static const char * const fw_path[] = {
module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");

static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
static void fw_finish_direct_load(struct device *device,
				  struct firmware_buf *buf)
{
	int size;
	char *buf;
	int rc;

	if (!S_ISREG(file_inode(file)->i_mode))
		return -EINVAL;
	size = i_size_read(file_inode(file));
	if (size <= 0)
		return -EINVAL;
	buf = vmalloc(size);
	if (!buf)
		return -ENOMEM;
	rc = kernel_read(file, 0, buf, size);
	if (rc != size) {
		if (rc > 0)
			rc = -EIO;
		goto fail;
	}
	rc = security_kernel_fw_from_file(file, buf, size);
	if (rc)
		goto fail;
	fw_buf->data = buf;
	fw_buf->size = size;
	return 0;
fail:
	vfree(buf);
	return rc;
	mutex_lock(&fw_lock);
	set_bit(FW_STATUS_DONE, &buf->status);
	complete_all(&buf->completion);
	mutex_unlock(&fw_lock);
}

static int fw_get_filesystem_firmware(struct device *device,
				       struct firmware_buf *buf)
{
	loff_t size;
	int i, len;
	int rc = -ENOENT;
	char *path;
@@ -334,8 +314,6 @@ static int fw_get_filesystem_firmware(struct device *device,
		return -ENOMEM;

	for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
		struct file *file;

		/* skip the unset customized path */
		if (!fw_path[i][0])
			continue;
@@ -347,28 +325,21 @@ static int fw_get_filesystem_firmware(struct device *device,
			break;
		}

		file = filp_open(path, O_RDONLY, 0);
		if (IS_ERR(file))
			continue;
		rc = fw_read_file_contents(file, buf);
		fput(file);
		if (rc)
			dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n",
		buf->size = 0;
		rc = kernel_read_file_from_path(path, &buf->data, &size,
						INT_MAX, READING_FIRMWARE);
		if (rc) {
			dev_warn(device, "loading %s failed with error %d\n",
				 path, rc);
		else
			continue;
		}
		dev_dbg(device, "direct-loading %s\n", buf->fw_id);
		buf->size = size;
		fw_finish_direct_load(device, buf);
		break;
	}
	__putname(path);

	if (!rc) {
		dev_dbg(device, "firmware: direct-loading firmware %s\n",
			buf->fw_id);
		mutex_lock(&fw_lock);
		set_bit(FW_STATUS_DONE, &buf->status);
		complete_all(&buf->completion);
		mutex_unlock(&fw_lock);
	}

	return rc;
}

@@ -685,8 +656,9 @@ static ssize_t firmware_loading_store(struct device *dev,
				dev_err(dev, "%s: map pages failed\n",
					__func__);
			else
				rc = security_kernel_fw_from_file(NULL,
						fw_buf->data, fw_buf->size);
				rc = security_kernel_post_read_file(NULL,
						fw_buf->data, fw_buf->size,
						READING_FIRMWARE);

			/*
			 * Same logic as fw_load_abort, only the DONE bit
@@ -1051,7 +1023,7 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
	}

	if (fw_get_builtin_firmware(firmware, name)) {
		dev_dbg(device, "firmware: using built-in firmware %s\n", name);
		dev_dbg(device, "using built-in %s\n", name);
		return 0; /* assigned */
	}

+92 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@
#include <linux/pipe_fs_i.h>
#include <linux/oom.h>
#include <linux/compat.h>
#include <linux/vmalloc.h>

#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -831,6 +832,97 @@ int kernel_read(struct file *file, loff_t offset,

EXPORT_SYMBOL(kernel_read);

int kernel_read_file(struct file *file, void **buf, loff_t *size,
		     loff_t max_size, enum kernel_read_file_id id)
{
	loff_t i_size, pos;
	ssize_t bytes = 0;
	int ret;

	if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
		return -EINVAL;

	ret = security_kernel_read_file(file, id);
	if (ret)
		return ret;

	i_size = i_size_read(file_inode(file));
	if (max_size > 0 && i_size > max_size)
		return -EFBIG;
	if (i_size <= 0)
		return -EINVAL;

	*buf = vmalloc(i_size);
	if (!*buf)
		return -ENOMEM;

	pos = 0;
	while (pos < i_size) {
		bytes = kernel_read(file, pos, (char *)(*buf) + pos,
				    i_size - pos);
		if (bytes < 0) {
			ret = bytes;
			goto out;
		}

		if (bytes == 0)
			break;
		pos += bytes;
	}

	if (pos != i_size) {
		ret = -EIO;
		goto out;
	}

	ret = security_kernel_post_read_file(file, *buf, i_size, id);
	if (!ret)
		*size = pos;

out:
	if (ret < 0) {
		vfree(*buf);
		*buf = NULL;
	}
	return ret;
}
EXPORT_SYMBOL_GPL(kernel_read_file);

int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
			       loff_t max_size, enum kernel_read_file_id id)
{
	struct file *file;
	int ret;

	if (!path || !*path)
		return -EINVAL;

	file = filp_open(path, O_RDONLY, 0);
	if (IS_ERR(file))
		return PTR_ERR(file);

	ret = kernel_read_file(file, buf, size, max_size, id);
	fput(file);
	return ret;
}
EXPORT_SYMBOL_GPL(kernel_read_file_from_path);

int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
			     enum kernel_read_file_id id)
{
	struct fd f = fdget(fd);
	int ret = -EBADF;

	if (!f.file)
		goto out;

	ret = kernel_read_file(f.file, buf, size, max_size, id);
out:
	fdput(f);
	return ret;
}
EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);

ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
{
	ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);
+15 −0
Original line number Diff line number Diff line
@@ -2576,7 +2576,22 @@ static inline void i_readcount_inc(struct inode *inode)
#endif
extern int do_pipe_flags(int *, int);

enum kernel_read_file_id {
	READING_FIRMWARE = 1,
	READING_MODULE,
	READING_KEXEC_IMAGE,
	READING_KEXEC_INITRAMFS,
	READING_POLICY,
	READING_MAX_ID
};

extern int kernel_read(struct file *, loff_t, char *, unsigned long);
extern int kernel_read_file(struct file *, void **, loff_t *, loff_t,
			    enum kernel_read_file_id);
extern int kernel_read_file_from_path(char *, void **, loff_t *, loff_t,
				      enum kernel_read_file_id);
extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t,
				    enum kernel_read_file_id);
extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
extern struct file * open_exec(const char *);
+6 −4
Original line number Diff line number Diff line
@@ -18,8 +18,9 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_file_check(struct file *file, int mask, int opened);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern int ima_module_check(struct file *file);
extern int ima_fw_from_file(struct file *file, char *buf, size_t size);
extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
			      enum kernel_read_file_id id);

#else
static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -42,12 +43,13 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
	return 0;
}

static inline int ima_module_check(struct file *file)
static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
{
	return 0;
}

static inline int ima_fw_from_file(struct file *file, char *buf, size_t size)
static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
				     enum kernel_read_file_id id)
{
	return 0;
}
Loading