Commit 39eeb4fb authored by Mimi Zohar's avatar Mimi Zohar

security: define kernel_read_file hook

The kernel_read_file security hook is called prior to reading the file
into memory.

Changelog v4+:
- export security_kernel_read_file()
Signed-off-by: default avatarMimi Zohar <zohar@linux.vnet.ibm.com>
Acked-by: default avatarKees Cook <keescook@chromium.org>
Acked-by: default avatarLuis R. Rodriguez <mcgrof@kernel.org>
Acked-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
parent e40ba6d5
...@@ -842,6 +842,10 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, ...@@ -842,6 +842,10 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0) if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
return -EINVAL; return -EINVAL;
ret = security_kernel_read_file(file, id);
if (ret)
return ret;
i_size = i_size_read(file_inode(file)); i_size = i_size_read(file_inode(file));
if (max_size > 0 && i_size > max_size) if (max_size > 0 && i_size > max_size)
return -EFBIG; return -EFBIG;
......
...@@ -19,6 +19,7 @@ extern int ima_file_check(struct file *file, int mask, int opened); ...@@ -19,6 +19,7 @@ extern int ima_file_check(struct file *file, int mask, int opened);
extern void ima_file_free(struct file *file); extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot); extern int ima_file_mmap(struct file *file, unsigned long prot);
extern int ima_module_check(struct file *file); extern int ima_module_check(struct file *file);
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, extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
enum kernel_read_file_id id); enum kernel_read_file_id id);
...@@ -48,6 +49,11 @@ static inline int ima_module_check(struct file *file) ...@@ -48,6 +49,11 @@ static inline int ima_module_check(struct file *file)
return 0; return 0;
} }
static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
{
return 0;
}
static inline int ima_post_read_file(struct file *file, void *buf, loff_t size, static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
enum kernel_read_file_id id) enum kernel_read_file_id id)
{ {
......
...@@ -552,6 +552,12 @@ ...@@ -552,6 +552,12 @@
* the kernel module to load. If the module is being loaded from a blob, * the kernel module to load. If the module is being loaded from a blob,
* this argument will be NULL. * this argument will be NULL.
* Return 0 if permission is granted. * Return 0 if permission is granted.
* @kernel_read_file:
* Read a file specified by userspace.
* @file contains the file structure pointing to the file being read
* by the kernel.
* @id kernel read file identifier
* Return 0 if permission is granted.
* @kernel_post_read_file: * @kernel_post_read_file:
* Read a file specified by userspace. * Read a file specified by userspace.
* @file contains the file structure pointing to the file being read * @file contains the file structure pointing to the file being read
...@@ -1455,6 +1461,7 @@ union security_list_options { ...@@ -1455,6 +1461,7 @@ union security_list_options {
int (*kernel_create_files_as)(struct cred *new, struct inode *inode); int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
int (*kernel_module_request)(char *kmod_name); int (*kernel_module_request)(char *kmod_name);
int (*kernel_module_from_file)(struct file *file); int (*kernel_module_from_file)(struct file *file);
int (*kernel_read_file)(struct file *file, enum kernel_read_file_id id);
int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size, int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
enum kernel_read_file_id id); enum kernel_read_file_id id);
int (*task_fix_setuid)(struct cred *new, const struct cred *old, int (*task_fix_setuid)(struct cred *new, const struct cred *old,
...@@ -1715,6 +1722,7 @@ struct security_hook_heads { ...@@ -1715,6 +1722,7 @@ struct security_hook_heads {
struct list_head cred_transfer; struct list_head cred_transfer;
struct list_head kernel_act_as; struct list_head kernel_act_as;
struct list_head kernel_create_files_as; struct list_head kernel_create_files_as;
struct list_head kernel_read_file;
struct list_head kernel_post_read_file; struct list_head kernel_post_read_file;
struct list_head kernel_module_request; struct list_head kernel_module_request;
struct list_head kernel_module_from_file; struct list_head kernel_module_from_file;
......
...@@ -302,6 +302,7 @@ int security_kernel_act_as(struct cred *new, u32 secid); ...@@ -302,6 +302,7 @@ int security_kernel_act_as(struct cred *new, u32 secid);
int security_kernel_create_files_as(struct cred *new, struct inode *inode); int security_kernel_create_files_as(struct cred *new, struct inode *inode);
int security_kernel_module_request(char *kmod_name); int security_kernel_module_request(char *kmod_name);
int security_kernel_module_from_file(struct file *file); int security_kernel_module_from_file(struct file *file);
int security_kernel_read_file(struct file *file, enum kernel_read_file_id id);
int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
enum kernel_read_file_id id); enum kernel_read_file_id id);
int security_task_fix_setuid(struct cred *new, const struct cred *old, int security_task_fix_setuid(struct cred *new, const struct cred *old,
...@@ -863,6 +864,12 @@ static inline int security_kernel_module_from_file(struct file *file) ...@@ -863,6 +864,12 @@ static inline int security_kernel_module_from_file(struct file *file)
return 0; return 0;
} }
static inline int security_kernel_read_file(struct file *file,
enum kernel_read_file_id id)
{
return 0;
}
static inline int security_kernel_post_read_file(struct file *file, static inline int security_kernel_post_read_file(struct file *file,
char *buf, loff_t size, char *buf, loff_t size,
enum kernel_read_file_id id) enum kernel_read_file_id id)
......
...@@ -337,6 +337,22 @@ int ima_module_check(struct file *file) ...@@ -337,6 +337,22 @@ int ima_module_check(struct file *file)
return process_measurement(file, NULL, 0, MAY_EXEC, MODULE_CHECK, 0); return process_measurement(file, NULL, 0, MAY_EXEC, MODULE_CHECK, 0);
} }
/**
* ima_read_file - pre-measure/appraise hook decision based on policy
* @file: pointer to the file to be measured/appraised/audit
* @read_id: caller identifier
*
* Permit reading a file based on policy. The policy rules are written
* in terms of the policy identifier. Appraising the integrity of
* a file requires a file descriptor.
*
* For permission return 0, otherwise return -EACCES.
*/
int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
{
return 0;
}
/** /**
* ima_post_read_file - in memory collect/appraise/audit measurement * ima_post_read_file - in memory collect/appraise/audit measurement
* @file: pointer to the file to be measured/appraised/audit * @file: pointer to the file to be measured/appraised/audit
......
...@@ -899,6 +899,17 @@ int security_kernel_module_from_file(struct file *file) ...@@ -899,6 +899,17 @@ int security_kernel_module_from_file(struct file *file)
return ima_module_check(file); return ima_module_check(file);
} }
int security_kernel_read_file(struct file *file, enum kernel_read_file_id id)
{
int ret;
ret = call_int_hook(kernel_read_file, 0, file, id);
if (ret)
return ret;
return ima_read_file(file, id);
}
EXPORT_SYMBOL_GPL(security_kernel_read_file);
int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
enum kernel_read_file_id id) enum kernel_read_file_id id)
{ {
...@@ -1696,6 +1707,8 @@ struct security_hook_heads security_hook_heads = { ...@@ -1696,6 +1707,8 @@ struct security_hook_heads security_hook_heads = {
LIST_HEAD_INIT(security_hook_heads.kernel_module_request), LIST_HEAD_INIT(security_hook_heads.kernel_module_request),
.kernel_module_from_file = .kernel_module_from_file =
LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file), LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file),
.kernel_read_file =
LIST_HEAD_INIT(security_hook_heads.kernel_read_file),
.kernel_post_read_file = .kernel_post_read_file =
LIST_HEAD_INIT(security_hook_heads.kernel_post_read_file), LIST_HEAD_INIT(security_hook_heads.kernel_post_read_file),
.task_fix_setuid = .task_fix_setuid =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment