Loading Documentation/ABI/testing/ima_policy +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading drivers/base/firmware_class.c +23 −51 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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 Loading Loading @@ -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 */ } Loading fs/exec.c +92 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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); Loading include/linux/fs.h +15 −0 Original line number Diff line number Diff line Loading @@ -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 *); Loading include/linux/ima.h +6 −4 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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 Loading
Documentation/ABI/testing/ima_policy +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
drivers/base/firmware_class.c +23 −51 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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 Loading Loading @@ -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 */ } Loading
fs/exec.c +92 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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); Loading
include/linux/fs.h +15 −0 Original line number Diff line number Diff line Loading @@ -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 *); Loading
include/linux/ima.h +6 −4 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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