From 1d197374f04642f9a5e71cc013d65d5438c35dc3 Mon Sep 17 00:00:00 2001 Message-Id: <1d197374f04642f9a5e71cc013d65d5438c35dc3.1527544850.git.Jim.Somerville@windriver.com> In-Reply-To: References: From: Kam Nasim Date: Wed, 23 Aug 2017 17:58:12 -0400 Subject: [PATCH 22/26] US101216: IMA support in Titanium kernel facilitate building the IMA subsytem out-of-the-kernel tree as a Kernel module (for which CONFIG_IMA and CONFIG_INTEGRITY will be undefined) by: - exporting certain function symbols which will be linked to the kernel module. This includes redefining the export symbols for kernel functions such that when the kernel module loads, it dynamically points to those new function definations and reverts to Kernel default definitions on module deinit - enabling inode readcount - modification to ima_file_check to pass in file OPEN status Signed-off-by: Jim Somerville --- fs/namei.c | 2 +- fs/nfsd/vfs.c | 2 +- fs/xattr.c | 1 + include/linux/fs.h | 15 +------ include/linux/ima.h | 77 +++++++------------------------- include/linux/integrity.h | 22 ++++----- security/security.c | 111 +++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 140 insertions(+), 90 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 9f90b63..bf91ea0 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3225,7 +3225,7 @@ opened: error = open_check_o_direct(file); if (error) goto exit_fput; - error = ima_file_check(file, op->acc_mode); + error = ima_file_check(file, op->acc_mode, *opened); if (error) goto exit_fput; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 00e98c3..cb9250e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -898,7 +898,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, goto out_nfserr; } - host_err = ima_file_check(file, may_flags); + host_err = ima_file_check(file, may_flags, 0); if (host_err) { fput(file); goto out_nfserr; diff --git a/fs/xattr.c b/fs/xattr.c index e540aca..cc307ec 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -207,6 +207,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, *xattr_value = value; return error; } +EXPORT_SYMBOL_GPL(vfs_getxattr_alloc); /* Compare an extended attribute value with the given value */ int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name, diff --git a/include/linux/fs.h b/include/linux/fs.h index eb6f994..2dbaf80 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -677,9 +677,8 @@ struct inode { struct fsnotify_mark_connector __rcu *i_fsnotify_marks) #endif -#ifdef CONFIG_IMA atomic_t i_readcount; /* struct files open RO */ -#endif + void *i_private; /* fs or device private pointer */ }; @@ -2830,7 +2829,6 @@ static inline bool inode_is_open_for_write(const struct inode *inode) return atomic_read(&inode->i_writecount) > 0; } -#ifdef CONFIG_IMA static inline void i_readcount_dec(struct inode *inode) { BUG_ON(!atomic_read(&inode->i_readcount)); @@ -2840,16 +2838,7 @@ static inline void i_readcount_inc(struct inode *inode) { atomic_inc(&inode->i_readcount); } -#else -static inline void i_readcount_dec(struct inode *inode) -{ - return; -} -static inline void i_readcount_inc(struct inode *inode) -{ - return; -} -#endif + extern int do_pipe_flags(int *, int); extern int kernel_read(struct file *, loff_t, char *, unsigned long); diff --git a/include/linux/ima.h b/include/linux/ima.h index 1b7f268..9fee45c 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -13,64 +13,21 @@ #include struct linux_binprm; -#ifdef CONFIG_IMA -extern int ima_bprm_check(struct linux_binprm *bprm); -extern int ima_file_check(struct file *file, int mask); -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); - -#else -static inline int ima_bprm_check(struct linux_binprm *bprm) -{ - return 0; -} - -static inline int ima_file_check(struct file *file, int mask) -{ - return 0; -} - -static inline void ima_file_free(struct file *file) -{ - return; -} - -static inline int ima_file_mmap(struct file *file, unsigned long prot) -{ - return 0; -} - -static inline int ima_module_check(struct file *file) -{ - return 0; -} - -#endif /* CONFIG_IMA */ - -#ifdef CONFIG_IMA_APPRAISE -extern void ima_inode_post_setattr(struct dentry *dentry); -extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, +/* + * The IMA Kernel module has to redefine these symbols so that + * the kernel module can link a dynamic function, as a hook into + * the Kernel FS calls (which use these) + */ +/* ifdef CONFIG_IMA */ +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); + +/* ifdef CONFIG_IMA_APPRAISE */ +extern void (*ima_inode_post_setattr)(struct dentry *dentry); +extern int (*ima_inode_setxattr)(struct dentry *dentry, const char *xattr_name, const void *xattr_value, size_t xattr_value_len); -extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name); -#else -static inline void ima_inode_post_setattr(struct dentry *dentry) -{ - return; -} - -static inline int ima_inode_setxattr(struct dentry *dentry, - const char *xattr_name, - const void *xattr_value, - size_t xattr_value_len) -{ - return 0; -} - -static inline int ima_inode_removexattr(struct dentry *dentry, - const char *xattr_name) -{ - return 0; -} -#endif /* CONFIG_IMA_APPRAISE */ -#endif /* _LINUX_IMA_H */ +extern int (*ima_inode_removexattr)(struct dentry *dentry, const char *xattr_name); +#endif diff --git a/include/linux/integrity.h b/include/linux/integrity.h index 83222ce..a5040b6 100644 --- a/include/linux/integrity.h +++ b/include/linux/integrity.h @@ -21,20 +21,14 @@ enum integrity_status { }; /* List of EVM protected security xattrs */ -#ifdef CONFIG_INTEGRITY -extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode); -extern void integrity_inode_free(struct inode *inode); +/* + * The Integrity Kernel module has to redefine these symbols so that + * the kernel module can link a dynamic function, as a hook into + * the Kernel Security subsystem (which use these) + */ -#else -static inline struct integrity_iint_cache * - integrity_inode_get(struct inode *inode) -{ - return NULL; -} +/* #ifdef CONFIG_INTEGRITY */ +extern struct integrity_iint_cache *(*integrity_inode_get)(struct inode *inode); +extern void (*integrity_inode_free)(struct inode *inode); -static inline void integrity_inode_free(struct inode *inode) -{ - return; -} -#endif /* CONFIG_INTEGRITY */ #endif /* _LINUX_INTEGRITY_H */ diff --git a/security/security.c b/security/security.c index f069482..646a0e3 100644 --- a/security/security.c +++ b/security/security.c @@ -161,6 +161,110 @@ EXPORT_SYMBOL(unregister_lsm_notifier); /* Security operations */ +/* + * Export these symbols since the IMA and Integrity + * modules will redefine it. We do this EXPORT in + * the security endpoint as this is the last Kernel + * hook into the Integrity / IMA modules + */ +#ifndef CONFIG_INTEGRITY +static struct integrity_iint_cache* integrity_inode_get_kmod(struct inode *inode) +{ + return NULL; +} + +static void integrity_inode_free_kmod(struct inode *inode) +{ + return; +} + +struct integrity_iint_cache * + (*integrity_inode_get)(struct inode *) = &integrity_inode_get_kmod; +void + (*integrity_inode_free)(struct inode*) = &integrity_inode_free_kmod; + +EXPORT_SYMBOL_GPL(integrity_inode_get); +EXPORT_SYMBOL_GPL(integrity_inode_free); +#endif + +#ifndef CONFIG_IMA +static int ima_bprm_check_kmod(struct linux_binprm *bprm) +{ + return 0; +} + +static int ima_file_check_kmod(struct file *file, int mask, int opened) +{ + return 0; +} + +static void ima_file_free_kmod(struct file *file) +{ + return; +} + +static int ima_file_mmap_kmod(struct file *file, unsigned long prot) +{ + return 0; +} + +static int ima_module_check_kmod(struct file *file) +{ + return 0; +} + +int + (*ima_bprm_check)(struct linux_binprm *) = &ima_bprm_check_kmod; +int + (*ima_file_check)(struct file *, int, int) = &ima_file_check_kmod; +void + (*ima_file_free)(struct file *) = &ima_file_free_kmod; +int + (*ima_file_mmap)(struct file*, unsigned long) = &ima_file_mmap_kmod; +int + (*ima_module_check)(struct file *) = &ima_module_check_kmod; + +EXPORT_SYMBOL_GPL(ima_bprm_check); +EXPORT_SYMBOL_GPL(ima_file_check); +EXPORT_SYMBOL_GPL(ima_file_free); +EXPORT_SYMBOL_GPL(ima_file_mmap); +EXPORT_SYMBOL_GPL(ima_module_check); +#endif + +#ifndef CONFIG_IMA_APPRAISE +static void ima_inode_post_setattr_kmod(struct dentry *dentry) +{ + return; +} + +static int ima_inode_setxattr_kmod(struct dentry *dentry, + const char *xattr_name, + const void *xattr_value, + size_t xattr_value_len) +{ + return 0; +} + +static int ima_inode_removexattr_kmod(struct dentry *dentry, + const char *xattr_name) +{ + return 0; +} + +void + (*ima_inode_post_setattr)(struct dentry *) = &ima_inode_post_setattr_kmod; +int + (*ima_inode_setxattr)(struct dentry *, const char *, + const void *, size_t) = &ima_inode_setxattr_kmod; +int + (*ima_inode_removexattr)(struct dentry *, + const char *) = &ima_inode_removexattr_kmod; + +EXPORT_SYMBOL_GPL(ima_inode_post_setattr); +EXPORT_SYMBOL_GPL(ima_inode_setxattr); +EXPORT_SYMBOL_GPL(ima_inode_removexattr); +#endif + int security_ptrace_access_check(struct task_struct *child, unsigned int mode) { #ifdef CONFIG_SECURITY_YAMA_STACKED @@ -720,8 +824,11 @@ EXPORT_SYMBOL(security_inode_listsecurity); void security_inode_getsecid(struct inode *inode, u32 *secid) { - security_ops->inode_getsecid(inode, secid); + if (unlikely(IS_PRIVATE(inode))) + return; + security_ops->inode_getsecid(inode, secid); } +EXPORT_SYMBOL_GPL(security_inode_getsecid); int security_inode_copy_up(struct dentry *src, struct cred **new) { @@ -1530,6 +1637,7 @@ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) { return security_ops->audit_rule_init(field, op, rulestr, lsmrule); } +EXPORT_SYMBOL_GPL(security_audit_rule_init); int security_audit_rule_known(struct audit_krule *krule) { @@ -1546,6 +1654,7 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, { return security_ops->audit_rule_match(secid, field, op, lsmrule, actx); } +EXPORT_SYMBOL_GPL(security_audit_rule_match); #endif /* CONFIG_AUDIT */ -- 1.8.3.1