diff options
Diffstat (limited to 'security/tomoyo/tomoyo.c')
| -rw-r--r-- | security/tomoyo/tomoyo.c | 334 | 
1 files changed, 303 insertions, 31 deletions
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 95d3f957223..f0b756e27fe 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -1,20 +1,35 @@  /*   * security/tomoyo/tomoyo.c   * - * LSM hooks for TOMOYO Linux. - * - * Copyright (C) 2005-2010  NTT DATA CORPORATION + * Copyright (C) 2005-2011  NTT DATA CORPORATION   */  #include <linux/security.h>  #include "common.h" +/** + * tomoyo_cred_alloc_blank - Target for security_cred_alloc_blank(). + * + * @new: Pointer to "struct cred". + * @gfp: Memory allocation flags. + * + * Returns 0. + */  static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)  {  	new->security = NULL;  	return 0;  } +/** + * tomoyo_cred_prepare - Target for security_prepare_creds(). + * + * @new: Pointer to "struct cred". + * @old: Pointer to "struct cred". + * @gfp: Memory allocation flags. + * + * Returns 0. + */  static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,  			       gfp_t gfp)  { @@ -25,11 +40,22 @@ static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,  	return 0;  } +/** + * tomoyo_cred_transfer - Target for security_transfer_creds(). + * + * @new: Pointer to "struct cred". + * @old: Pointer to "struct cred". + */  static void tomoyo_cred_transfer(struct cred *new, const struct cred *old)  {  	tomoyo_cred_prepare(new, old, 0);  } +/** + * tomoyo_cred_free - Target for security_cred_free(). + * + * @cred: Pointer to "struct cred". + */  static void tomoyo_cred_free(struct cred *cred)  {  	struct tomoyo_domain_info *domain = cred->security; @@ -37,6 +63,13 @@ static void tomoyo_cred_free(struct cred *cred)  		atomic_dec(&domain->users);  } +/** + * tomoyo_bprm_set_creds - Target for security_bprm_set_creds(). + * + * @bprm: Pointer to "struct linux_binprm". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)  {  	int rc; @@ -51,12 +84,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)  	 */  	if (bprm->cred_prepared)  		return 0; +#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER  	/*  	 * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested  	 * for the first time.  	 */  	if (!tomoyo_policy_loaded)  		tomoyo_load_policy(bprm->filename); +#endif  	/*  	 * Release reference to "struct tomoyo_domain_info" stored inside  	 * "bprm->cred->security". New reference to "struct tomoyo_domain_info" @@ -73,6 +108,13 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)  	return 0;  } +/** + * tomoyo_bprm_check_security - Target for security_bprm_check(). + * + * @bprm: Pointer to "struct linux_binprm". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_bprm_check_security(struct linux_binprm *bprm)  {  	struct tomoyo_domain_info *domain = bprm->cred->security; @@ -90,43 +132,109 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)  	/*  	 * Read permission is checked against interpreters using next domain.  	 */ -	return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); +	return tomoyo_check_open_permission(domain, &bprm->file->f_path, +					    O_RDONLY);  } +/** + * tomoyo_inode_getattr - Target for security_inode_getattr(). + * + * @mnt:    Pointer to "struct vfsmount". + * @dentry: Pointer to "struct dentry". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) +{ +	struct path path = { mnt, dentry }; +	return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL); +} + +/** + * tomoyo_path_truncate - Target for security_path_truncate(). + * + * @path: Pointer to "struct path". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_truncate(struct path *path)  { -	return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); +	return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL);  } +/** + * tomoyo_path_unlink - Target for security_path_unlink(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)  {  	struct path path = { parent->mnt, dentry }; -	return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path); +	return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL);  } +/** + * tomoyo_path_mkdir - Target for security_path_mkdir(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * @mode:   DAC permission mode. + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, -			     int mode) +			     umode_t mode)  {  	struct path path = { parent->mnt, dentry };  	return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path,  				       mode & S_IALLUGO);  } +/** + * tomoyo_path_rmdir - Target for security_path_rmdir(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)  {  	struct path path = { parent->mnt, dentry }; -	return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path); +	return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL);  } +/** + * tomoyo_path_symlink - Target for security_path_symlink(). + * + * @parent:   Pointer to "struct path". + * @dentry:   Pointer to "struct dentry". + * @old_name: Symlink's content. + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,  			       const char *old_name)  {  	struct path path = { parent->mnt, dentry }; -	return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path); +	return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name);  } +/** + * tomoyo_path_mknod - Target for security_path_mknod(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * @mode:   DAC permission mode. + * @dev:    Device attributes. + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, -			     int mode, unsigned int dev) +			     umode_t mode, unsigned int dev)  {  	struct path path = { parent->mnt, dentry };  	int type = TOMOYO_TYPE_CREATE; @@ -155,6 +263,15 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,  	return tomoyo_path_number_perm(type, &path, perm);  } +/** + * tomoyo_path_link - Target for security_path_link(). + * + * @old_dentry: Pointer to "struct dentry". + * @new_dir:    Pointer to "struct path". + * @new_dentry: Pointer to "struct dentry". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,  			    struct dentry *new_dentry)  { @@ -163,6 +280,16 @@ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,  	return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2);  } +/** + * tomoyo_path_rename - Target for security_path_rename(). + * + * @old_parent: Pointer to "struct path". + * @old_dentry: Pointer to "struct dentry". + * @new_parent: Pointer to "struct path". + * @new_dentry: Pointer to "struct dentry". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_rename(struct path *old_parent,  			      struct dentry *old_dentry,  			      struct path *new_parent, @@ -173,15 +300,33 @@ static int tomoyo_path_rename(struct path *old_parent,  	return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2);  } +/** + * tomoyo_file_fcntl - Target for security_file_fcntl(). + * + * @file: Pointer to "struct file". + * @cmd:  Command for fcntl(). + * @arg:  Argument for @cmd. + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,  			     unsigned long arg)  { -	if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) -		return tomoyo_path_perm(TOMOYO_TYPE_REWRITE, &file->f_path); -	return 0; +	if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))) +		return 0; +	return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path, +					    O_WRONLY | (arg & O_APPEND));  } -static int tomoyo_dentry_open(struct file *f, const struct cred *cred) +/** + * tomoyo_file_open - Target for security_file_open(). + * + * @f:    Pointer to "struct file". + * @cred: Pointer to "struct cred". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_file_open(struct file *f, const struct cred *cred)  {  	int flags = f->f_flags;  	/* Don't check read permission here if called from do_execve(). */ @@ -190,52 +335,170 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred)  	return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags);  } +/** + * tomoyo_file_ioctl - Target for security_file_ioctl(). + * + * @file: Pointer to "struct file". + * @cmd:  Command for ioctl(). + * @arg:  Argument for @cmd. + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,  			     unsigned long arg)  {  	return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd);  } -static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, -			     mode_t mode) +/** + * tomoyo_path_chmod - Target for security_path_chmod(). + * + * @path: Pointer to "struct path". + * @mode: DAC permission mode. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_chmod(struct path *path, umode_t mode)  { -	struct path path = { mnt, dentry }; -	return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, &path, +	return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path,  				       mode & S_IALLUGO);  } -static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) +/** + * tomoyo_path_chown - Target for security_path_chown(). + * + * @path: Pointer to "struct path". + * @uid:  Owner ID. + * @gid:  Group ID. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_chown(struct path *path, kuid_t uid, kgid_t gid)  {  	int error = 0; -	if (uid != (uid_t) -1) -		error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, uid); -	if (!error && gid != (gid_t) -1) -		error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, gid); +	if (uid_valid(uid)) +		error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, +						from_kuid(&init_user_ns, uid)); +	if (!error && gid_valid(gid)) +		error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, +						from_kgid(&init_user_ns, gid));  	return error;  } +/** + * tomoyo_path_chroot - Target for security_path_chroot(). + * + * @path: Pointer to "struct path". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_path_chroot(struct path *path)  { -	return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path); +	return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL);  } -static int tomoyo_sb_mount(char *dev_name, struct path *path, -			   char *type, unsigned long flags, void *data) +/** + * tomoyo_sb_mount - Target for security_sb_mount(). + * + * @dev_name: Name of device file. Maybe NULL. + * @path:     Pointer to "struct path". + * @type:     Name of filesystem type. Maybe NULL. + * @flags:    Mount options. + * @data:     Optional data. Maybe NULL. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_sb_mount(const char *dev_name, struct path *path, +			   const char *type, unsigned long flags, void *data)  {  	return tomoyo_mount_permission(dev_name, path, type, flags, data);  } +/** + * tomoyo_sb_umount - Target for security_sb_umount(). + * + * @mnt:   Pointer to "struct vfsmount". + * @flags: Unmount options. + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)  {  	struct path path = { mnt, mnt->mnt_root }; -	return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path); +	return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL);  } +/** + * tomoyo_sb_pivotroot - Target for security_sb_pivotroot(). + * + * @old_path: Pointer to "struct path". + * @new_path: Pointer to "struct path". + * + * Returns 0 on success, negative value otherwise. + */  static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path)  {  	return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path);  } +/** + * tomoyo_socket_listen - Check permission for listen(). + * + * @sock:    Pointer to "struct socket". + * @backlog: Backlog parameter. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_socket_listen(struct socket *sock, int backlog) +{ +	return tomoyo_socket_listen_permission(sock); +} + +/** + * tomoyo_socket_connect - Check permission for connect(). + * + * @sock:     Pointer to "struct socket". + * @addr:     Pointer to "struct sockaddr". + * @addr_len: Size of @addr. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr, +				 int addr_len) +{ +	return tomoyo_socket_connect_permission(sock, addr, addr_len); +} + +/** + * tomoyo_socket_bind - Check permission for bind(). + * + * @sock:     Pointer to "struct socket". + * @addr:     Pointer to "struct sockaddr". + * @addr_len: Size of @addr. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, +			      int addr_len) +{ +	return tomoyo_socket_bind_permission(sock, addr, addr_len); +} + +/** + * tomoyo_socket_sendmsg - Check permission for sendmsg(). + * + * @sock: Pointer to "struct socket". + * @msg:  Pointer to "struct msghdr". + * @size: Size of message. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, +				 int size) +{ +	return tomoyo_socket_sendmsg_permission(sock, msg, size); +} +  /*   * tomoyo_security_ops is a "struct security_operations" which is used for   * registering TOMOYO. @@ -249,7 +512,7 @@ static struct security_operations tomoyo_security_ops = {  	.bprm_set_creds      = tomoyo_bprm_set_creds,  	.bprm_check_security = tomoyo_bprm_check_security,  	.file_fcntl          = tomoyo_file_fcntl, -	.dentry_open         = tomoyo_dentry_open, +	.file_open           = tomoyo_file_open,  	.path_truncate       = tomoyo_path_truncate,  	.path_unlink         = tomoyo_path_unlink,  	.path_mkdir          = tomoyo_path_mkdir, @@ -258,6 +521,7 @@ static struct security_operations tomoyo_security_ops = {  	.path_mknod          = tomoyo_path_mknod,  	.path_link           = tomoyo_path_link,  	.path_rename         = tomoyo_path_rename, +	.inode_getattr       = tomoyo_inode_getattr,  	.file_ioctl          = tomoyo_file_ioctl,  	.path_chmod          = tomoyo_path_chmod,  	.path_chown          = tomoyo_path_chown, @@ -265,11 +529,20 @@ static struct security_operations tomoyo_security_ops = {  	.sb_mount            = tomoyo_sb_mount,  	.sb_umount           = tomoyo_sb_umount,  	.sb_pivotroot        = tomoyo_sb_pivotroot, +	.socket_bind         = tomoyo_socket_bind, +	.socket_connect      = tomoyo_socket_connect, +	.socket_listen       = tomoyo_socket_listen, +	.socket_sendmsg      = tomoyo_socket_sendmsg,  };  /* Lock for GC. */ -struct srcu_struct tomoyo_ss; +DEFINE_SRCU(tomoyo_ss); +/** + * tomoyo_init - Register TOMOYO Linux as a LSM module. + * + * Returns 0. + */  static int __init tomoyo_init(void)  {  	struct cred *cred = (struct cred *) current_cred(); @@ -277,8 +550,7 @@ static int __init tomoyo_init(void)  	if (!security_module_enable(&tomoyo_security_ops))  		return 0;  	/* register ourselves with the security framework */ -	if (register_security(&tomoyo_security_ops) || -	    init_srcu_struct(&tomoyo_ss)) +	if (register_security(&tomoyo_security_ops))  		panic("Failure registering TOMOYO Linux");  	printk(KERN_INFO "TOMOYO Linux initialized\n");  	cred->security = &tomoyo_kernel_domain;  | 
