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

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
...@@ -836,7 +836,8 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, ...@@ -836,7 +836,8 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
struct path *path2); struct path *path2);
int tomoyo_path_number_perm(const u8 operation, struct path *path, int tomoyo_path_number_perm(const u8 operation, struct path *path,
unsigned long number); 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, int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
const struct tomoyo_path_info *filename); const struct tomoyo_path_info *filename);
int tomoyo_poll_control(struct file *file, poll_table *wait); int tomoyo_poll_control(struct file *file, poll_table *wait);
......
...@@ -575,23 +575,27 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, ...@@ -575,23 +575,27 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
*/ */
int tomoyo_find_next_domain(struct linux_binprm *bprm) 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 *old_domain = tomoyo_domain();
struct tomoyo_domain_info *domain = NULL; struct tomoyo_domain_info *domain = NULL;
const char *original_name = bprm->filename; const char *original_name = bprm->filename;
u8 mode;
bool is_enforce;
int retval = -ENOMEM; int retval = -ENOMEM;
bool need_kfree = false; bool need_kfree = false;
bool reject_on_transition_failure = false; bool reject_on_transition_failure = false;
struct tomoyo_path_info rn = { }; /* real name */ struct tomoyo_path_info rn = { }; /* real name */
struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS);
mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); if (!ee)
is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); return -ENOMEM;
if (!tmp) ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
goto out; 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: retry:
if (need_kfree) { if (need_kfree) {
kfree(rn.name); kfree(rn.name);
...@@ -625,7 +629,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) ...@@ -625,7 +629,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
} }
/* Check execute permission. */ /* 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) if (retval == TOMOYO_RETRY_REQUEST)
goto retry; goto retry;
if (retval < 0) if (retval < 0)
...@@ -636,12 +640,12 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) ...@@ -636,12 +640,12 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
* wildcard) rather than the pathname passed to execve() * wildcard) rather than the pathname passed to execve()
* (which never contains wildcard). * (which never contains wildcard).
*/ */
if (r.param.path.matched_path) { if (ee->r.param.path.matched_path) {
if (need_kfree) if (need_kfree)
kfree(rn.name); kfree(rn.name);
need_kfree = false; need_kfree = false;
/* This is OK because it is read only. */ /* 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. */ /* Calculate domain to transit to. */
...@@ -649,7 +653,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) ...@@ -649,7 +653,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
&rn)) { &rn)) {
case TOMOYO_TRANSITION_CONTROL_RESET: case TOMOYO_TRANSITION_CONTROL_RESET:
/* Transit to the root of specified namespace. */ /* 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 * Make do_execve() fail if domain transition across namespaces
* has failed. * has failed.
...@@ -658,7 +662,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) ...@@ -658,7 +662,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
break; break;
case TOMOYO_TRANSITION_CONTROL_INITIALIZE: case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
/* Transit to the child of current namespace's root. */ /* 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); old_domain->ns->name, rn.name);
break; break;
case TOMOYO_TRANSITION_CONTROL_KEEP: case TOMOYO_TRANSITION_CONTROL_KEEP:
...@@ -677,29 +681,30 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) ...@@ -677,29 +681,30 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
domain = old_domain; domain = old_domain;
} else { } else {
/* Normal domain transition. */ /* 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); old_domain->domainname->name, rn.name);
} }
break; break;
} }
if (!domain) if (!domain)
domain = tomoyo_assign_domain(tmp, true); domain = tomoyo_assign_domain(ee->tmp, true);
if (domain) if (domain)
retval = 0; retval = 0;
else if (reject_on_transition_failure) { 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; retval = -ENOMEM;
} else if (r.mode == TOMOYO_CONFIG_ENFORCING) } else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING)
retval = -ENOMEM; retval = -ENOMEM;
else { else {
retval = 0; retval = 0;
if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) { if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) {
old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true; old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true;
r.granted = false; ee->r.granted = false;
tomoyo_write_log(&r, "%s", tomoyo_dif tomoyo_write_log(&ee->r, "%s", tomoyo_dif
[TOMOYO_DIF_TRANSITION_FAILED]); [TOMOYO_DIF_TRANSITION_FAILED]);
printk(KERN_WARNING printk(KERN_WARNING
"ERROR: Domain '%s' not defined.\n", tmp); "ERROR: Domain '%s' not defined.\n", ee->tmp);
} }
} }
out: out:
...@@ -710,7 +715,9 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) ...@@ -710,7 +715,9 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
bprm->cred->security = domain; bprm->cred->security = domain;
if (need_kfree) if (need_kfree)
kfree(rn.name); kfree(rn.name);
kfree(tmp); kfree(ee->tmp);
kfree(ee->dump.data);
kfree(ee);
return retval; return retval;
} }
......
...@@ -667,6 +667,9 @@ int tomoyo_path_number_perm(const u8 type, struct path *path, ...@@ -667,6 +667,9 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
unsigned long number) unsigned long number)
{ {
struct tomoyo_request_info r; struct tomoyo_request_info r;
struct tomoyo_obj_info obj = {
.path1 = *path,
};
int error = -ENOMEM; int error = -ENOMEM;
struct tomoyo_path_info buf; struct tomoyo_path_info buf;
int idx; int idx;
...@@ -677,6 +680,7 @@ int tomoyo_path_number_perm(const u8 type, struct path *path, ...@@ -677,6 +680,7 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
idx = tomoyo_read_lock(); idx = tomoyo_read_lock();
if (!tomoyo_get_realpath(&buf, path)) if (!tomoyo_get_realpath(&buf, path))
goto out; goto out;
r.obj = &obj;
if (type == TOMOYO_TYPE_MKDIR) if (type == TOMOYO_TYPE_MKDIR)
tomoyo_add_slash(&buf); tomoyo_add_slash(&buf);
r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
...@@ -711,6 +715,9 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, ...@@ -711,6 +715,9 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
int error = 0; int error = 0;
struct tomoyo_path_info buf; struct tomoyo_path_info buf;
struct tomoyo_request_info r; struct tomoyo_request_info r;
struct tomoyo_obj_info obj = {
.path1 = *path,
};
int idx; int idx;
buf.name = NULL; buf.name = NULL;
...@@ -723,6 +730,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, ...@@ -723,6 +730,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
error = -ENOMEM; error = -ENOMEM;
goto out; goto out;
} }
r.obj = &obj;
if (acc_mode & MAY_READ) if (acc_mode & MAY_READ)
error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
&buf); &buf);
...@@ -745,15 +753,21 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, ...@@ -745,15 +753,21 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
* *
* @operation: Type of operation. * @operation: Type of operation.
* @path: Pointer to "struct path". * @path: Pointer to "struct path".
* @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
* NULL otherwise.
* *
* Returns 0 on success, negative value 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_request_info r;
struct tomoyo_obj_info obj = {
.path1 = *path,
};
int error; int error;
struct tomoyo_path_info buf; struct tomoyo_path_info buf;
bool is_enforce; bool is_enforce;
struct tomoyo_path_info symlink_target;
int idx; int idx;
if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
...@@ -765,13 +779,23 @@ int tomoyo_path_perm(const u8 operation, struct path *path) ...@@ -765,13 +779,23 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
idx = tomoyo_read_lock(); idx = tomoyo_read_lock();
if (!tomoyo_get_realpath(&buf, path)) if (!tomoyo_get_realpath(&buf, path))
goto out; goto out;
r.obj = &obj;
switch (operation) { switch (operation) {
case TOMOYO_TYPE_RMDIR: case TOMOYO_TYPE_RMDIR:
case TOMOYO_TYPE_CHROOT: case TOMOYO_TYPE_CHROOT:
tomoyo_add_slash(&buf); tomoyo_add_slash(&buf);
break; 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); error = tomoyo_path_permission(&r, operation, &buf);
if (operation == TOMOYO_TYPE_SYMLINK)
kfree(symlink_target.name);
out: out:
kfree(buf.name); kfree(buf.name);
tomoyo_read_unlock(idx); tomoyo_read_unlock(idx);
...@@ -794,6 +818,9 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path, ...@@ -794,6 +818,9 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path,
const unsigned int mode, unsigned int dev) const unsigned int mode, unsigned int dev)
{ {
struct tomoyo_request_info r; struct tomoyo_request_info r;
struct tomoyo_obj_info obj = {
.path1 = *path,
};
int error = -ENOMEM; int error = -ENOMEM;
struct tomoyo_path_info buf; struct tomoyo_path_info buf;
int idx; int idx;
...@@ -804,6 +831,7 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path, ...@@ -804,6 +831,7 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path,
idx = tomoyo_read_lock(); idx = tomoyo_read_lock();
error = -ENOMEM; error = -ENOMEM;
if (tomoyo_get_realpath(&buf, path)) { if (tomoyo_get_realpath(&buf, path)) {
r.obj = &obj;
dev = new_decode_dev(dev); dev = new_decode_dev(dev);
r.param_type = TOMOYO_TYPE_MKDEV_ACL; r.param_type = TOMOYO_TYPE_MKDEV_ACL;
r.param.mkdev.filename = &buf; r.param.mkdev.filename = &buf;
...@@ -837,6 +865,10 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, ...@@ -837,6 +865,10 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
struct tomoyo_path_info buf1; struct tomoyo_path_info buf1;
struct tomoyo_path_info buf2; struct tomoyo_path_info buf2;
struct tomoyo_request_info r; struct tomoyo_request_info r;
struct tomoyo_obj_info obj = {
.path1 = *path1,
.path2 = *path2,
};
int idx; int idx;
if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
...@@ -861,6 +893,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, ...@@ -861,6 +893,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
tomoyo_add_slash(&buf2); tomoyo_add_slash(&buf2);
break; break;
} }
r.obj = &obj;
r.param_type = TOMOYO_TYPE_PATH2_ACL; r.param_type = TOMOYO_TYPE_PATH2_ACL;
r.param.path2.operation = operation; r.param.path2.operation = operation;
r.param.path2.filename1 = &buf1; r.param.path2.filename1 = &buf1;
......
...@@ -75,6 +75,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, ...@@ -75,6 +75,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
struct path *dir, const char *type, struct path *dir, const char *type,
unsigned long flags) unsigned long flags)
{ {
struct tomoyo_obj_info obj = { };
struct path path; struct path path;
struct file_system_type *fstype = NULL; struct file_system_type *fstype = NULL;
const char *requested_type = NULL; const char *requested_type = NULL;
...@@ -85,6 +86,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, ...@@ -85,6 +86,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
struct tomoyo_path_info rdir; struct tomoyo_path_info rdir;
int need_dev = 0; int need_dev = 0;
int error = -ENOMEM; int error = -ENOMEM;
r->obj = &obj;
/* Get fstype. */ /* Get fstype. */
requested_type = tomoyo_encode(type); requested_type = tomoyo_encode(type);
...@@ -94,6 +96,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, ...@@ -94,6 +96,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
tomoyo_fill_path_info(&rtype); tomoyo_fill_path_info(&rtype);
/* Get mount point. */ /* Get mount point. */
obj.path2 = *dir;
requested_dir_name = tomoyo_realpath_from_path(dir); requested_dir_name = tomoyo_realpath_from_path(dir);
if (!requested_dir_name) { if (!requested_dir_name) {
error = -ENOMEM; error = -ENOMEM;
...@@ -129,8 +132,8 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, ...@@ -129,8 +132,8 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
error = -ENOENT; error = -ENOENT;
goto out; goto out;
} }
obj.path1 = path;
requested_dev_name = tomoyo_realpath_from_path(&path); requested_dev_name = tomoyo_realpath_from_path(&path);
path_put(&path);
if (!requested_dev_name) { if (!requested_dev_name) {
error = -ENOENT; error = -ENOENT;
goto out; goto out;
...@@ -163,6 +166,9 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, ...@@ -163,6 +166,9 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
if (fstype) if (fstype)
put_filesystem(fstype); put_filesystem(fstype);
kfree(requested_type); kfree(requested_type);
/* Drop refcount obtained by kern_path(). */
if (obj.path1.dentry)
path_put(&obj.path1);
return error; return error;
} }
......
...@@ -98,18 +98,18 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) ...@@ -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) static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{ {
struct path path = { mnt, 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) 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) static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
{ {
struct path path = { parent->mnt, 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, 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, ...@@ -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) static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
{ {
struct path path = { parent->mnt, 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, static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
const char *old_name) const char *old_name)
{ {
struct path path = { parent->mnt, dentry }; 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, 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) ...@@ -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) 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, 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, ...@@ -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) static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
{ {
struct path path = { mnt, mnt->mnt_root }; 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) static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment