diff options
Diffstat (limited to 'security/security.c')
| -rw-r--r-- | security/security.c | 108 | 
1 files changed, 79 insertions, 29 deletions
| diff --git a/security/security.c b/security/security.c index c4c673240c1..687c6fd14bb 100644 --- a/security/security.c +++ b/security/security.c @@ -16,15 +16,19 @@  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/security.h> +#include <linux/ima.h>  /* Boot-time LSM user choice */ -static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1]; +static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = +	CONFIG_DEFAULT_SECURITY;  /* things that live in capability.c */ -extern struct security_operations default_security_ops;  extern void security_fixup_ops(struct security_operations *ops); -struct security_operations *security_ops;	/* Initialized to NULL */ +static struct security_operations *security_ops; +static struct security_operations default_security_ops = { +	.name	= "default", +};  static inline int verify(struct security_operations *ops)  { @@ -61,6 +65,11 @@ int __init security_init(void)  	return 0;  } +void reset_security_ops(void) +{ +	security_ops = &default_security_ops; +} +  /* Save user chosen LSM */  static int __init choose_lsm(char *str)  { @@ -79,8 +88,10 @@ __setup("security=", choose_lsm);   *   * Return true if:   *	-The passed LSM is the one chosen by user at boot time, - *	-or user didn't specify a specific LSM and we're the first to ask - *	 for registration permission, + *	-or the passed LSM is configured as the default and the user did not + *	 choose an alternate LSM at boot time, + *	-or there is no default LSM set and the user didn't specify a + *	 specific LSM and we're the first to ask for registration permission,   *	-or the passed LSM is currently loaded.   * Otherwise, return false.   */ @@ -199,9 +210,9 @@ int security_quota_on(struct dentry *dentry)  	return security_ops->quota_on(dentry);  } -int security_syslog(int type) +int security_syslog(int type, bool from_file)  { -	return security_ops->syslog(type); +	return security_ops->syslog(type, from_file);  }  int security_settime(struct timespec *ts, struct timezone *tz) @@ -235,7 +246,12 @@ int security_bprm_set_creds(struct linux_binprm *bprm)  int security_bprm_check(struct linux_binprm *bprm)  { -	return security_ops->bprm_check_security(bprm); +	int ret; + +	ret = security_ops->bprm_check_security(bprm); +	if (ret) +		return ret; +	return ima_bprm_check(bprm);  }  void security_bprm_committing_creds(struct linux_binprm *bprm) @@ -352,12 +368,21 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);  int security_inode_alloc(struct inode *inode)  { +	int ret; +  	inode->i_security = NULL; -	return security_ops->inode_alloc_security(inode); +	ret =  security_ops->inode_alloc_security(inode); +	if (ret) +		return ret; +	ret = ima_inode_alloc(inode); +	if (ret) +		security_inode_free(inode); +	return ret;  }  void security_inode_free(struct inode *inode)  { +	ima_inode_free(inode);  	security_ops->inode_free_security(inode);  } @@ -371,42 +396,42 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,  EXPORT_SYMBOL(security_inode_init_security);  #ifdef CONFIG_SECURITY_PATH -int security_path_mknod(struct path *path, struct dentry *dentry, int mode, +int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,  			unsigned int dev)  { -	if (unlikely(IS_PRIVATE(path->dentry->d_inode))) +	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))  		return 0; -	return security_ops->path_mknod(path, dentry, mode, dev); +	return security_ops->path_mknod(dir, dentry, mode, dev);  }  EXPORT_SYMBOL(security_path_mknod); -int security_path_mkdir(struct path *path, struct dentry *dentry, int mode) +int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)  { -	if (unlikely(IS_PRIVATE(path->dentry->d_inode))) +	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))  		return 0; -	return security_ops->path_mkdir(path, dentry, mode); +	return security_ops->path_mkdir(dir, dentry, mode);  } -int security_path_rmdir(struct path *path, struct dentry *dentry) +int security_path_rmdir(struct path *dir, struct dentry *dentry)  { -	if (unlikely(IS_PRIVATE(path->dentry->d_inode))) +	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))  		return 0; -	return security_ops->path_rmdir(path, dentry); +	return security_ops->path_rmdir(dir, dentry);  } -int security_path_unlink(struct path *path, struct dentry *dentry) +int security_path_unlink(struct path *dir, struct dentry *dentry)  { -	if (unlikely(IS_PRIVATE(path->dentry->d_inode))) +	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))  		return 0; -	return security_ops->path_unlink(path, dentry); +	return security_ops->path_unlink(dir, dentry);  } -int security_path_symlink(struct path *path, struct dentry *dentry, +int security_path_symlink(struct path *dir, struct dentry *dentry,  			  const char *old_name)  { -	if (unlikely(IS_PRIVATE(path->dentry->d_inode))) +	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))  		return 0; -	return security_ops->path_symlink(path, dentry, old_name); +	return security_ops->path_symlink(dir, dentry, old_name);  }  int security_path_link(struct dentry *old_dentry, struct path *new_dir, @@ -434,6 +459,26 @@ int security_path_truncate(struct path *path, loff_t length,  		return 0;  	return security_ops->path_truncate(path, length, time_attrs);  } + +int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, +			mode_t mode) +{ +	if (unlikely(IS_PRIVATE(dentry->d_inode))) +		return 0; +	return security_ops->path_chmod(dentry, mnt, mode); +} + +int security_path_chown(struct path *path, uid_t uid, gid_t gid) +{ +	if (unlikely(IS_PRIVATE(path->dentry->d_inode))) +		return 0; +	return security_ops->path_chown(path, uid, gid); +} + +int security_path_chroot(struct path *path) +{ +	return security_ops->path_chroot(path); +}  #endif  int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) @@ -592,14 +637,14 @@ int security_inode_killpriv(struct dentry *dentry)  int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)  {  	if (unlikely(IS_PRIVATE(inode))) -		return 0; +		return -EOPNOTSUPP;  	return security_ops->inode_getsecurity(inode, name, buffer, alloc);  }  int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)  {  	if (unlikely(IS_PRIVATE(inode))) -		return 0; +		return -EOPNOTSUPP;  	return security_ops->inode_setsecurity(inode, name, value, size, flags);  } @@ -639,7 +684,12 @@ int security_file_mmap(struct file *file, unsigned long reqprot,  			unsigned long prot, unsigned long flags,  			unsigned long addr, unsigned long addr_only)  { -	return security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); +	int ret; + +	ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); +	if (ret) +		return ret; +	return ima_file_mmap(file, prot);  }  int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, @@ -719,9 +769,9 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)  	return security_ops->kernel_create_files_as(new, inode);  } -int security_kernel_module_request(void) +int security_kernel_module_request(char *kmod_name)  { -	return security_ops->kernel_module_request(); +	return security_ops->kernel_module_request(kmod_name);  }  int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 
