diff options
Diffstat (limited to 'security/tomoyo/mount.c')
| -rw-r--r-- | security/tomoyo/mount.c | 176 | 
1 files changed, 62 insertions, 114 deletions
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 9fc2e15841c..bee09d06205 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -1,28 +1,22 @@  /*   * security/tomoyo/mount.c   * - * Copyright (C) 2005-2010  NTT DATA CORPORATION + * Copyright (C) 2005-2011  NTT DATA CORPORATION   */  #include <linux/slab.h>  #include "common.h" -/* Keywords for mount restrictions. */ - -/* Allow to call 'mount --bind /source_dir /dest_dir' */ -#define TOMOYO_MOUNT_BIND_KEYWORD                        "--bind" -/* Allow to call 'mount --move /old_dir    /new_dir ' */ -#define TOMOYO_MOUNT_MOVE_KEYWORD                        "--move" -/* Allow to call 'mount -o remount /dir             ' */ -#define TOMOYO_MOUNT_REMOUNT_KEYWORD                     "--remount" -/* Allow to call 'mount --make-unbindable /dir'       */ -#define TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD             "--make-unbindable" -/* Allow to call 'mount --make-private /dir'          */ -#define TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD                "--make-private" -/* Allow to call 'mount --make-slave /dir'            */ -#define TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD                  "--make-slave" -/* Allow to call 'mount --make-shared /dir'           */ -#define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD                 "--make-shared" +/* String table for special mount operations. */ +static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = { +	[TOMOYO_MOUNT_BIND]            = "--bind", +	[TOMOYO_MOUNT_MOVE]            = "--move", +	[TOMOYO_MOUNT_REMOUNT]         = "--remount", +	[TOMOYO_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable", +	[TOMOYO_MOUNT_MAKE_PRIVATE]    = "--make-private", +	[TOMOYO_MOUNT_MAKE_SLAVE]      = "--make-slave", +	[TOMOYO_MOUNT_MAKE_SHARED]     = "--make-shared", +};  /**   * tomoyo_audit_mount_log - Audit mount log. @@ -33,50 +27,42 @@   */  static int tomoyo_audit_mount_log(struct tomoyo_request_info *r)  { -	const char *dev = r->param.mount.dev->name; -	const char *dir = r->param.mount.dir->name; -	const char *type = r->param.mount.type->name; -	const unsigned long flags = r->param.mount.flags; -	if (r->granted) -		return 0; -	if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) -		tomoyo_warn_log(r, "mount -o remount %s 0x%lX", dir, flags); -	else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) -		 || !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) -		tomoyo_warn_log(r, "mount %s %s %s 0x%lX", type, dev, dir, -				flags); -	else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) || -		 !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) || -		 !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) || -		 !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) -		tomoyo_warn_log(r, "mount %s %s 0x%lX", type, dir, flags); -	else -		tomoyo_warn_log(r, "mount -t %s %s %s 0x%lX", type, dev, dir, -				flags); -	return tomoyo_supervisor(r, -				 TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", -				 tomoyo_pattern(r->param.mount.dev), -				 tomoyo_pattern(r->param.mount.dir), type, -				 flags); +	return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n", +				 r->param.mount.dev->name, +				 r->param.mount.dir->name, +				 r->param.mount.type->name, +				 r->param.mount.flags);  } +/** + * tomoyo_check_mount_acl - Check permission for path path path number operation. + * + * @r:   Pointer to "struct tomoyo_request_info". + * @ptr: Pointer to "struct tomoyo_acl_info". + * + * Returns true if granted, false otherwise. + */  static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,  				   const struct tomoyo_acl_info *ptr)  {  	const struct tomoyo_mount_acl *acl =  		container_of(ptr, typeof(*acl), head); -	return tomoyo_compare_number_union(r->param.mount.flags, &acl->flags) && -		tomoyo_compare_name_union(r->param.mount.type, &acl->fs_type) && -		tomoyo_compare_name_union(r->param.mount.dir, &acl->dir_name) && +	return tomoyo_compare_number_union(r->param.mount.flags, +					   &acl->flags) && +		tomoyo_compare_name_union(r->param.mount.type, +					  &acl->fs_type) && +		tomoyo_compare_name_union(r->param.mount.dir, +					  &acl->dir_name) &&  		(!r->param.mount.need_dev || -		 tomoyo_compare_name_union(r->param.mount.dev, &acl->dev_name)); +		 tomoyo_compare_name_union(r->param.mount.dev, +					   &acl->dev_name));  }  /**   * tomoyo_mount_acl - Check permission for mount() operation.   *   * @r:        Pointer to "struct tomoyo_request_info". - * @dev_name: Name of device file. + * @dev_name: Name of device file. Maybe NULL.   * @dir:      Pointer to "struct path".   * @type:     Name of filesystem type.   * @flags:    Mount options. @@ -86,8 +72,10 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,   * Caller holds tomoyo_read_lock().   */  static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, -			    struct path *dir, char *type, unsigned long flags) +			    struct path *dir, const char *type, +			    unsigned long flags)  { +	struct tomoyo_obj_info obj = { };  	struct path path;  	struct file_system_type *fstype = NULL;  	const char *requested_type = NULL; @@ -98,6 +86,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,  	struct tomoyo_path_info rdir;  	int need_dev = 0;  	int error = -ENOMEM; +	r->obj = &obj;  	/* Get fstype. */  	requested_type = tomoyo_encode(type); @@ -107,6 +96,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,  	tomoyo_fill_path_info(&rtype);  	/* Get mount point. */ +	obj.path2 = *dir;  	requested_dir_name = tomoyo_realpath_from_path(dir);  	if (!requested_dir_name) {  		error = -ENOMEM; @@ -116,15 +106,15 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,  	tomoyo_fill_path_info(&rdir);  	/* Compare fs name. */ -	if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) { +	if (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) {  		/* dev_name is ignored. */ -	} else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) || -		   !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) || -		   !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) || -		   !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) { +	} else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] || +		   type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] || +		   type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] || +		   type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) {  		/* dev_name is ignored. */ -	} else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) || -		   !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) { +	} else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] || +		   type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) {  		need_dev = -1; /* dev_name is a directory */  	} else {  		fstype = get_fs_type(type); @@ -142,8 +132,8 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,  			error = -ENOENT;  			goto out;  		} +		obj.path1 = path;  		requested_dev_name = tomoyo_realpath_from_path(&path); -		path_put(&path);  		if (!requested_dev_name) {  			error = -ENOENT;  			goto out; @@ -176,22 +166,26 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,  	if (fstype)  		put_filesystem(fstype);  	kfree(requested_type); +	/* Drop refcount obtained by kern_path(). */ +	if (obj.path1.dentry) +		path_put(&obj.path1);  	return error;  }  /**   * tomoyo_mount_permission - Check permission for mount() operation.   * - * @dev_name:  Name of device file. + * @dev_name:  Name of device file. Maybe NULL.   * @path:      Pointer to "struct path". - * @type:      Name of filesystem type. May be NULL. + * @type:      Name of filesystem type. Maybe NULL.   * @flags:     Mount options. - * @data_page: Optional data. May be NULL. + * @data_page: Optional data. Maybe NULL.   *   * Returns 0 on success, negative value otherwise.   */ -int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, -			    unsigned long flags, void *data_page) +int tomoyo_mount_permission(char *dev_name, struct path *path, +			    const char *type, unsigned long flags, +			    void *data_page)  {  	struct tomoyo_request_info r;  	int error; @@ -203,31 +197,31 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,  	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)  		flags &= ~MS_MGC_MSK;  	if (flags & MS_REMOUNT) { -		type = TOMOYO_MOUNT_REMOUNT_KEYWORD; +		type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT];  		flags &= ~MS_REMOUNT;  	}  	if (flags & MS_MOVE) { -		type = TOMOYO_MOUNT_MOVE_KEYWORD; +		type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];  		flags &= ~MS_MOVE;  	}  	if (flags & MS_BIND) { -		type = TOMOYO_MOUNT_BIND_KEYWORD; +		type = tomoyo_mounts[TOMOYO_MOUNT_BIND];  		flags &= ~MS_BIND;  	}  	if (flags & MS_UNBINDABLE) { -		type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD; +		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];  		flags &= ~MS_UNBINDABLE;  	}  	if (flags & MS_PRIVATE) { -		type = TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD; +		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE];  		flags &= ~MS_PRIVATE;  	}  	if (flags & MS_SLAVE) { -		type = TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD; +		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE];  		flags &= ~MS_SLAVE;  	}  	if (flags & MS_SHARED) { -		type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD; +		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];  		flags &= ~MS_SHARED;  	}  	if (!type) @@ -237,49 +231,3 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,  	tomoyo_read_unlock(idx);  	return error;  } - -static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, -				  const struct tomoyo_acl_info *b) -{ -	const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); -	const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); -	return tomoyo_same_acl_head(&p1->head, &p2->head) && -		tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && -		tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && -		tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && -		tomoyo_same_number_union(&p1->flags, &p2->flags); -} - -/** - * tomoyo_write_mount - Write "struct tomoyo_mount_acl" list. - * - * @data:      String to parse. - * @domain:    Pointer to "struct tomoyo_domain_info". - * @is_delete: True if it is a delete request. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, -		       const bool is_delete) -{ -	struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; -	int error = is_delete ? -ENOENT : -ENOMEM; -	char *w[4]; -	if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0]) -		return -EINVAL; -	if (!tomoyo_parse_name_union(w[0], &e.dev_name) || -	    !tomoyo_parse_name_union(w[1], &e.dir_name) || -	    !tomoyo_parse_name_union(w[2], &e.fs_type) || -	    !tomoyo_parse_number_union(w[3], &e.flags)) -		goto out; -	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, -				     tomoyo_same_mount_acl, NULL); - out: -	tomoyo_put_name_union(&e.dev_name); -	tomoyo_put_name_union(&e.dir_name); -	tomoyo_put_name_union(&e.fs_type); -	tomoyo_put_number_union(&e.flags); -	return error; -}  |