diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-07-08 13:22:41 +0900 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-07-11 11:05:32 +1000 |
commit | 8761afd49ebff8ae04c1a7888af090177441d07d (patch) | |
tree | f43b52e1b8467eeea465762d2f9d0b81a336faa0 /security/tomoyo/condition.c | |
parent | 2066a36125fcbf5220990173b9d8e8bc49ad7538 (diff) |
TOMOYO: Allow using owner/group etc. of file objects as conditions.
This patch adds support for permission checks using file object's DAC
attributes (e.g. owner/group) when checking file's pathnames. Hooks for passing
file object's pointers are in the last patch of this pathset.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo/condition.c')
-rw-r--r-- | security/tomoyo/condition.c | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c index 0692df3cddc..ac7ebeb47d7 100644 --- a/security/tomoyo/condition.c +++ b/security/tomoyo/condition.c @@ -244,6 +244,54 @@ out: } /** + * tomoyo_get_attributes - Revalidate "struct inode". + * + * @obj: Pointer to "struct tomoyo_obj_info". + * + * Returns nothing. + */ +void tomoyo_get_attributes(struct tomoyo_obj_info *obj) +{ + u8 i; + struct dentry *dentry = NULL; + + for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) { + struct inode *inode; + switch (i) { + case TOMOYO_PATH1: + dentry = obj->path1.dentry; + if (!dentry) + continue; + break; + case TOMOYO_PATH2: + dentry = obj->path2.dentry; + if (!dentry) + continue; + break; + default: + if (!dentry) + continue; + dentry = dget_parent(dentry); + break; + } + inode = dentry->d_inode; + if (inode) { + struct tomoyo_mini_stat *stat = &obj->stat[i]; + stat->uid = inode->i_uid; + stat->gid = inode->i_gid; + stat->ino = inode->i_ino; + stat->mode = inode->i_mode; + stat->dev = inode->i_sb->s_dev; + stat->rdev = inode->i_rdev; + obj->stat_valid[i] = true; + } + if (i & 1) /* i == TOMOYO_PATH1_PARENT || + i == TOMOYO_PATH2_PARENT */ + dput(dentry); + } +} + +/** * tomoyo_condition - Check condition part. * * @r: Pointer to "struct tomoyo_request_info". @@ -261,16 +309,19 @@ bool tomoyo_condition(struct tomoyo_request_info *r, unsigned long max_v[2] = { 0, 0 }; const struct tomoyo_condition_element *condp; const struct tomoyo_number_union *numbers_p; + struct tomoyo_obj_info *obj; u16 condc; if (!cond) return true; condc = cond->condc; + obj = r->obj; condp = (struct tomoyo_condition_element *) (cond + 1); numbers_p = (const struct tomoyo_number_union *) (condp + condc); for (i = 0; i < condc; i++) { const bool match = condp->equals; const u8 left = condp->left; const u8 right = condp->right; + bool is_bitop[2] = { false, false }; u8 j; condp++; /* Check numeric or bit-op expressions. */ @@ -308,14 +359,185 @@ bool tomoyo_condition(struct tomoyo_request_info *r, case TOMOYO_TASK_PPID: value = tomoyo_sys_getppid(); break; + case TOMOYO_TYPE_IS_SOCKET: + value = S_IFSOCK; + break; + case TOMOYO_TYPE_IS_SYMLINK: + value = S_IFLNK; + break; + case TOMOYO_TYPE_IS_FILE: + value = S_IFREG; + break; + case TOMOYO_TYPE_IS_BLOCK_DEV: + value = S_IFBLK; + break; + case TOMOYO_TYPE_IS_DIRECTORY: + value = S_IFDIR; + break; + case TOMOYO_TYPE_IS_CHAR_DEV: + value = S_IFCHR; + break; + case TOMOYO_TYPE_IS_FIFO: + value = S_IFIFO; + break; + case TOMOYO_MODE_SETUID: + value = S_ISUID; + break; + case TOMOYO_MODE_SETGID: + value = S_ISGID; + break; + case TOMOYO_MODE_STICKY: + value = S_ISVTX; + break; + case TOMOYO_MODE_OWNER_READ: + value = S_IRUSR; + break; + case TOMOYO_MODE_OWNER_WRITE: + value = S_IWUSR; + break; + case TOMOYO_MODE_OWNER_EXECUTE: + value = S_IXUSR; + break; + case TOMOYO_MODE_GROUP_READ: + value = S_IRGRP; + break; + case TOMOYO_MODE_GROUP_WRITE: + value = S_IWGRP; + break; + case TOMOYO_MODE_GROUP_EXECUTE: + value = S_IXGRP; + break; + case TOMOYO_MODE_OTHERS_READ: + value = S_IROTH; + break; + case TOMOYO_MODE_OTHERS_WRITE: + value = S_IWOTH; + break; + case TOMOYO_MODE_OTHERS_EXECUTE: + value = S_IXOTH; + break; case TOMOYO_NUMBER_UNION: /* Fetch values later. */ break; default: + if (!obj) + goto out; + if (!obj->validate_done) { + tomoyo_get_attributes(obj); + obj->validate_done = true; + } + { + u8 stat_index; + struct tomoyo_mini_stat *stat; + switch (index) { + case TOMOYO_PATH1_UID: + case TOMOYO_PATH1_GID: + case TOMOYO_PATH1_INO: + case TOMOYO_PATH1_MAJOR: + case TOMOYO_PATH1_MINOR: + case TOMOYO_PATH1_TYPE: + case TOMOYO_PATH1_DEV_MAJOR: + case TOMOYO_PATH1_DEV_MINOR: + case TOMOYO_PATH1_PERM: + stat_index = TOMOYO_PATH1; + break; + case TOMOYO_PATH2_UID: + case TOMOYO_PATH2_GID: + case TOMOYO_PATH2_INO: + case TOMOYO_PATH2_MAJOR: + case TOMOYO_PATH2_MINOR: + case TOMOYO_PATH2_TYPE: + case TOMOYO_PATH2_DEV_MAJOR: + case TOMOYO_PATH2_DEV_MINOR: + case TOMOYO_PATH2_PERM: + stat_index = TOMOYO_PATH2; + break; + case TOMOYO_PATH1_PARENT_UID: + case TOMOYO_PATH1_PARENT_GID: + case TOMOYO_PATH1_PARENT_INO: + case TOMOYO_PATH1_PARENT_PERM: + stat_index = + TOMOYO_PATH1_PARENT; + break; + case TOMOYO_PATH2_PARENT_UID: + case TOMOYO_PATH2_PARENT_GID: + case TOMOYO_PATH2_PARENT_INO: + case TOMOYO_PATH2_PARENT_PERM: + stat_index = + TOMOYO_PATH2_PARENT; + break; + default: + goto out; + } + if (!obj->stat_valid[stat_index]) + goto out; + stat = &obj->stat[stat_index]; + switch (index) { + case TOMOYO_PATH1_UID: + case TOMOYO_PATH2_UID: + case TOMOYO_PATH1_PARENT_UID: + case TOMOYO_PATH2_PARENT_UID: + value = stat->uid; + break; + case TOMOYO_PATH1_GID: + case TOMOYO_PATH2_GID: + case TOMOYO_PATH1_PARENT_GID: + case TOMOYO_PATH2_PARENT_GID: + value = stat->gid; + break; + case TOMOYO_PATH1_INO: + case TOMOYO_PATH2_INO: + case TOMOYO_PATH1_PARENT_INO: + case TOMOYO_PATH2_PARENT_INO: + value = stat->ino; + break; + case TOMOYO_PATH1_MAJOR: + case TOMOYO_PATH2_MAJOR: + value = MAJOR(stat->dev); + break; + case TOMOYO_PATH1_MINOR: + case TOMOYO_PATH2_MINOR: + value = MINOR(stat->dev); + break; + case TOMOYO_PATH1_TYPE: + case TOMOYO_PATH2_TYPE: + value = stat->mode & S_IFMT; + break; + case TOMOYO_PATH1_DEV_MAJOR: + case TOMOYO_PATH2_DEV_MAJOR: + value = MAJOR(stat->rdev); + break; + case TOMOYO_PATH1_DEV_MINOR: + case TOMOYO_PATH2_DEV_MINOR: + value = MINOR(stat->rdev); + break; + case TOMOYO_PATH1_PERM: + case TOMOYO_PATH2_PERM: + case TOMOYO_PATH1_PARENT_PERM: + case TOMOYO_PATH2_PARENT_PERM: + value = stat->mode & S_IALLUGO; + break; + } + } break; } max_v[j] = value; min_v[j] = value; + switch (index) { + case TOMOYO_MODE_SETUID: + case TOMOYO_MODE_SETGID: + case TOMOYO_MODE_STICKY: + case TOMOYO_MODE_OWNER_READ: + case TOMOYO_MODE_OWNER_WRITE: + case TOMOYO_MODE_OWNER_EXECUTE: + case TOMOYO_MODE_GROUP_READ: + case TOMOYO_MODE_GROUP_WRITE: + case TOMOYO_MODE_GROUP_EXECUTE: + case TOMOYO_MODE_OTHERS_READ: + case TOMOYO_MODE_OTHERS_WRITE: + case TOMOYO_MODE_OTHERS_EXECUTE: + is_bitop[j] = true; + } } if (left == TOMOYO_NUMBER_UNION) { /* Fetch values now. */ @@ -339,6 +561,33 @@ bool tomoyo_condition(struct tomoyo_request_info *r, } goto out; } + /* + * Bit operation is valid only when counterpart value + * represents permission. + */ + if (is_bitop[0] && is_bitop[1]) { + goto out; + } else if (is_bitop[0]) { + switch (right) { + case TOMOYO_PATH1_PERM: + case TOMOYO_PATH1_PARENT_PERM: + case TOMOYO_PATH2_PERM: + case TOMOYO_PATH2_PARENT_PERM: + if (!(max_v[0] & max_v[1]) == !match) + continue; + } + goto out; + } else if (is_bitop[1]) { + switch (left) { + case TOMOYO_PATH1_PERM: + case TOMOYO_PATH1_PARENT_PERM: + case TOMOYO_PATH2_PERM: + case TOMOYO_PATH2_PARENT_PERM: + if (!(max_v[0] & max_v[1]) == !match) + continue; + } + goto out; + } /* Normal value range comparison. */ if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match) continue; |