Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97fb35e4 authored by Tetsuo Handa's avatar Tetsuo Handa Committed by James Morris
Browse files

TOMOYO: Enable conditional ACL.



Enable conditional ACL by passing object's pointers.

Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 5b636857
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -836,7 +836,8 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
		      struct path *path2);
int tomoyo_path_number_perm(const u8 operation, struct path *path,
			    unsigned long number);
int tomoyo_path_perm(const u8 operation, struct path *path);
int tomoyo_path_perm(const u8 operation, struct path *path,
		     const char *target);
int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
			   const struct tomoyo_path_info *filename);
int tomoyo_poll_control(struct file *file, poll_table *wait);
+30 −23
Original line number Diff line number Diff line
@@ -575,23 +575,27 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
 */
int tomoyo_find_next_domain(struct linux_binprm *bprm)
{
	struct tomoyo_request_info r;
	char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
	struct tomoyo_domain_info *old_domain = tomoyo_domain();
	struct tomoyo_domain_info *domain = NULL;
	const char *original_name = bprm->filename;
	u8 mode;
	bool is_enforce;
	int retval = -ENOMEM;
	bool need_kfree = false;
	bool reject_on_transition_failure = false;
	struct tomoyo_path_info rn = { }; /* real name */

	mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
	is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
	if (!tmp)
		goto out;

	struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS);
	if (!ee)
		return -ENOMEM;
	ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
	if (!ee->tmp) {
		kfree(ee);
		return -ENOMEM;
	}
	/* ee->dump->data is allocated by tomoyo_dump_page(). */
	tomoyo_init_request_info(&ee->r, NULL, TOMOYO_MAC_FILE_EXECUTE);
	ee->r.ee = ee;
	ee->bprm = bprm;
	ee->r.obj = &ee->obj;
	ee->obj.path1 = bprm->file->f_path;
 retry:
	if (need_kfree) {
		kfree(rn.name);
@@ -625,7 +629,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
	}

	/* Check execute permission. */
	retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn);
	retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, &rn);
	if (retval == TOMOYO_RETRY_REQUEST)
		goto retry;
	if (retval < 0)
@@ -636,12 +640,12 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
	 * wildcard) rather than the pathname passed to execve()
	 * (which never contains wildcard).
	 */
	if (r.param.path.matched_path) {
	if (ee->r.param.path.matched_path) {
		if (need_kfree)
			kfree(rn.name);
		need_kfree = false;
		/* This is OK because it is read only. */
		rn = *r.param.path.matched_path;
		rn = *ee->r.param.path.matched_path;
	}

	/* Calculate domain to transit to. */
@@ -649,7 +653,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
				       &rn)) {
	case TOMOYO_TRANSITION_CONTROL_RESET:
		/* Transit to the root of specified namespace. */
		snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name);
		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name);
		/*
		 * Make do_execve() fail if domain transition across namespaces
		 * has failed.
@@ -658,7 +662,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
		break;
	case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
		/* Transit to the child of current namespace's root. */
		snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
			 old_domain->ns->name, rn.name);
		break;
	case TOMOYO_TRANSITION_CONTROL_KEEP:
@@ -677,29 +681,30 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
			domain = old_domain;
		} else {
			/* Normal domain transition. */
			snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
			snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
				 old_domain->domainname->name, rn.name);
		}
		break;
	}
	if (!domain)
		domain = tomoyo_assign_domain(tmp, true);
		domain = tomoyo_assign_domain(ee->tmp, true);
	if (domain)
		retval = 0;
	else if (reject_on_transition_failure) {
		printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", tmp);
		printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n",
		       ee->tmp);
		retval = -ENOMEM;
	} else if (r.mode == TOMOYO_CONFIG_ENFORCING)
	} else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING)
		retval = -ENOMEM;
	else {
		retval = 0;
		if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) {
			old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true;
			r.granted = false;
			tomoyo_write_log(&r, "%s", tomoyo_dif
			ee->r.granted = false;
			tomoyo_write_log(&ee->r, "%s", tomoyo_dif
					 [TOMOYO_DIF_TRANSITION_FAILED]);
			printk(KERN_WARNING
			       "ERROR: Domain '%s' not defined.\n", tmp);
			       "ERROR: Domain '%s' not defined.\n", ee->tmp);
		}
	}
 out:
@@ -710,7 +715,9 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
	bprm->cred->security = domain;
	if (need_kfree)
		kfree(rn.name);
	kfree(tmp);
	kfree(ee->tmp);
	kfree(ee->dump.data);
	kfree(ee);
	return retval;
}

+34 −1
Original line number Diff line number Diff line
@@ -667,6 +667,9 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
			    unsigned long number)
{
	struct tomoyo_request_info r;
	struct tomoyo_obj_info obj = {
		.path1 = *path,
	};
	int error = -ENOMEM;
	struct tomoyo_path_info buf;
	int idx;
@@ -677,6 +680,7 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
	idx = tomoyo_read_lock();
	if (!tomoyo_get_realpath(&buf, path))
		goto out;
	r.obj = &obj;
	if (type == TOMOYO_TYPE_MKDIR)
		tomoyo_add_slash(&buf);
	r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
@@ -711,6 +715,9 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
	int error = 0;
	struct tomoyo_path_info buf;
	struct tomoyo_request_info r;
	struct tomoyo_obj_info obj = {
		.path1 = *path,
	};
	int idx;

	buf.name = NULL;
@@ -723,6 +730,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
			error = -ENOMEM;
			goto out;
		}
		r.obj = &obj;
		if (acc_mode & MAY_READ)
			error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
						       &buf);
@@ -745,15 +753,21 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 *
 * @operation: Type of operation.
 * @path:      Pointer to "struct path".
 * @target:    Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
 *             NULL otherwise.
 *
 * Returns 0 on success, negative value otherwise.
 */
int tomoyo_path_perm(const u8 operation, struct path *path)
int tomoyo_path_perm(const u8 operation, struct path *path, const char *target)
{
	struct tomoyo_request_info r;
	struct tomoyo_obj_info obj = {
		.path1 = *path,
	};
	int error;
	struct tomoyo_path_info buf;
	bool is_enforce;
	struct tomoyo_path_info symlink_target;
	int idx;

	if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
@@ -765,13 +779,23 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
	idx = tomoyo_read_lock();
	if (!tomoyo_get_realpath(&buf, path))
		goto out;
	r.obj = &obj;
	switch (operation) {
	case TOMOYO_TYPE_RMDIR:
	case TOMOYO_TYPE_CHROOT:
		tomoyo_add_slash(&buf);
		break;
	case TOMOYO_TYPE_SYMLINK:
		symlink_target.name = tomoyo_encode(target);
		if (!symlink_target.name)
			goto out;
		tomoyo_fill_path_info(&symlink_target);
		obj.symlink_target = &symlink_target;
		break;
	}
	error = tomoyo_path_permission(&r, operation, &buf);
	if (operation == TOMOYO_TYPE_SYMLINK)
		kfree(symlink_target.name);
 out:
	kfree(buf.name);
	tomoyo_read_unlock(idx);
@@ -794,6 +818,9 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path,
		      const unsigned int mode, unsigned int dev)
{
	struct tomoyo_request_info r;
	struct tomoyo_obj_info obj = {
		.path1 = *path,
	};
	int error = -ENOMEM;
	struct tomoyo_path_info buf;
	int idx;
@@ -804,6 +831,7 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path,
	idx = tomoyo_read_lock();
	error = -ENOMEM;
	if (tomoyo_get_realpath(&buf, path)) {
		r.obj = &obj;
		dev = new_decode_dev(dev);
		r.param_type = TOMOYO_TYPE_MKDEV_ACL;
		r.param.mkdev.filename = &buf;
@@ -837,6 +865,10 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
	struct tomoyo_path_info buf1;
	struct tomoyo_path_info buf2;
	struct tomoyo_request_info r;
	struct tomoyo_obj_info obj = {
		.path1 = *path1,
		.path2 = *path2,
	};
	int idx;

	if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
@@ -861,6 +893,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
                tomoyo_add_slash(&buf2);
		break;
        }
	r.obj = &obj;
	r.param_type = TOMOYO_TYPE_PATH2_ACL;
	r.param.path2.operation = operation;
	r.param.path2.filename1 = &buf1;
+7 −1
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
			    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;
@@ -85,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);
@@ -94,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;
@@ -129,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;
@@ -163,6 +166,9 @@ 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;
}

+7 −7
Original line number Diff line number Diff line
@@ -98,18 +98,18 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{
	struct path path = { mnt, dentry };
	return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path);
	return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL);
}

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);
}

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);
}

static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
@@ -123,14 +123,14 @@ static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
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);
}

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);
}

static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
@@ -225,7 +225,7 @@ static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid)

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,
@@ -237,7 +237,7 @@ static int tomoyo_sb_mount(char *dev_name, struct path *path,
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);
}

static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path)