Skip to content

Commit

Permalink
TOMOYO: Allow using owner/group etc. of file objects as conditions.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tetsuo Handa authored and James Morris committed Jul 11, 2011
1 parent 2066a36 commit 8761afd
Show file tree
Hide file tree
Showing 4 changed files with 457 additions and 0 deletions.
72 changes: 72 additions & 0 deletions security/tomoyo/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,35 @@
#include "common.h"
#include <linux/slab.h>

/**
* tomoyo_filetype - Get string representation of file type.
*
* @mode: Mode value for stat().
*
* Returns file type string.
*/
static inline const char *tomoyo_filetype(const mode_t mode)
{
switch (mode & S_IFMT) {
case S_IFREG:
case 0:
return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FILE];
case S_IFDIR:
return tomoyo_condition_keyword[TOMOYO_TYPE_IS_DIRECTORY];
case S_IFLNK:
return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SYMLINK];
case S_IFIFO:
return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FIFO];
case S_IFSOCK:
return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SOCKET];
case S_IFBLK:
return tomoyo_condition_keyword[TOMOYO_TYPE_IS_BLOCK_DEV];
case S_IFCHR:
return tomoyo_condition_keyword[TOMOYO_TYPE_IS_CHAR_DEV];
}
return "unknown"; /* This should not happen. */
}

/**
* tomoyo_print_header - Get header line of audit log.
*
Expand All @@ -23,9 +52,11 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
{
struct tomoyo_time stamp;
const pid_t gpid = task_pid_nr(current);
struct tomoyo_obj_info *obj = r->obj;
static const int tomoyo_buffer_len = 4096;
char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
int pos;
u8 i;
if (!buffer)
return NULL;
{
Expand All @@ -44,6 +75,47 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
current_uid(), current_gid(), current_euid(),
current_egid(), current_suid(), current_sgid(),
current_fsuid(), current_fsgid());
if (!obj)
goto no_obj_info;
if (!obj->validate_done) {
tomoyo_get_attributes(obj);
obj->validate_done = true;
}
for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
struct tomoyo_mini_stat *stat;
unsigned int dev;
mode_t mode;
if (!obj->stat_valid[i])
continue;
stat = &obj->stat[i];
dev = stat->dev;
mode = stat->mode;
if (i & 1) {
pos += snprintf(buffer + pos,
tomoyo_buffer_len - 1 - pos,
" path%u.parent={ uid=%u gid=%u "
"ino=%lu perm=0%o }", (i >> 1) + 1,
stat->uid, stat->gid, (unsigned long)
stat->ino, stat->mode & S_IALLUGO);
continue;
}
pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
" path%u={ uid=%u gid=%u ino=%lu major=%u"
" minor=%u perm=0%o type=%s", (i >> 1) + 1,
stat->uid, stat->gid, (unsigned long)
stat->ino, MAJOR(dev), MINOR(dev),
mode & S_IALLUGO, tomoyo_filetype(mode));
if (S_ISCHR(mode) || S_ISBLK(mode)) {
dev = stat->rdev;
pos += snprintf(buffer + pos,
tomoyo_buffer_len - 1 - pos,
" dev_major=%u dev_minor=%u",
MAJOR(dev), MINOR(dev));
}
pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
" }");
}
no_obj_info:
if (pos < tomoyo_buffer_len - 1)
return buffer;
kfree(buffer);
Expand Down
45 changes: 45 additions & 0 deletions security/tomoyo/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,51 @@ const char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = {
[TOMOYO_TASK_FSGID] = "task.fsgid",
[TOMOYO_TASK_PID] = "task.pid",
[TOMOYO_TASK_PPID] = "task.ppid",
[TOMOYO_TYPE_IS_SOCKET] = "socket",
[TOMOYO_TYPE_IS_SYMLINK] = "symlink",
[TOMOYO_TYPE_IS_FILE] = "file",
[TOMOYO_TYPE_IS_BLOCK_DEV] = "block",
[TOMOYO_TYPE_IS_DIRECTORY] = "directory",
[TOMOYO_TYPE_IS_CHAR_DEV] = "char",
[TOMOYO_TYPE_IS_FIFO] = "fifo",
[TOMOYO_MODE_SETUID] = "setuid",
[TOMOYO_MODE_SETGID] = "setgid",
[TOMOYO_MODE_STICKY] = "sticky",
[TOMOYO_MODE_OWNER_READ] = "owner_read",
[TOMOYO_MODE_OWNER_WRITE] = "owner_write",
[TOMOYO_MODE_OWNER_EXECUTE] = "owner_execute",
[TOMOYO_MODE_GROUP_READ] = "group_read",
[TOMOYO_MODE_GROUP_WRITE] = "group_write",
[TOMOYO_MODE_GROUP_EXECUTE] = "group_execute",
[TOMOYO_MODE_OTHERS_READ] = "others_read",
[TOMOYO_MODE_OTHERS_WRITE] = "others_write",
[TOMOYO_MODE_OTHERS_EXECUTE] = "others_execute",
[TOMOYO_PATH1_UID] = "path1.uid",
[TOMOYO_PATH1_GID] = "path1.gid",
[TOMOYO_PATH1_INO] = "path1.ino",
[TOMOYO_PATH1_MAJOR] = "path1.major",
[TOMOYO_PATH1_MINOR] = "path1.minor",
[TOMOYO_PATH1_PERM] = "path1.perm",
[TOMOYO_PATH1_TYPE] = "path1.type",
[TOMOYO_PATH1_DEV_MAJOR] = "path1.dev_major",
[TOMOYO_PATH1_DEV_MINOR] = "path1.dev_minor",
[TOMOYO_PATH2_UID] = "path2.uid",
[TOMOYO_PATH2_GID] = "path2.gid",
[TOMOYO_PATH2_INO] = "path2.ino",
[TOMOYO_PATH2_MAJOR] = "path2.major",
[TOMOYO_PATH2_MINOR] = "path2.minor",
[TOMOYO_PATH2_PERM] = "path2.perm",
[TOMOYO_PATH2_TYPE] = "path2.type",
[TOMOYO_PATH2_DEV_MAJOR] = "path2.dev_major",
[TOMOYO_PATH2_DEV_MINOR] = "path2.dev_minor",
[TOMOYO_PATH1_PARENT_UID] = "path1.parent.uid",
[TOMOYO_PATH1_PARENT_GID] = "path1.parent.gid",
[TOMOYO_PATH1_PARENT_INO] = "path1.parent.ino",
[TOMOYO_PATH1_PARENT_PERM] = "path1.parent.perm",
[TOMOYO_PATH2_PARENT_UID] = "path2.parent.uid",
[TOMOYO_PATH2_PARENT_GID] = "path2.parent.gid",
[TOMOYO_PATH2_PARENT_INO] = "path2.parent.ino",
[TOMOYO_PATH2_PARENT_PERM] = "path2.parent.perm",
};

/* String table for PREFERENCE keyword. */
Expand Down
91 changes: 91 additions & 0 deletions security/tomoyo/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,66 @@ enum tomoyo_conditions_index {
TOMOYO_TASK_FSGID, /* current_fsgid() */
TOMOYO_TASK_PID, /* sys_getpid() */
TOMOYO_TASK_PPID, /* sys_getppid() */
TOMOYO_TYPE_IS_SOCKET, /* S_IFSOCK */
TOMOYO_TYPE_IS_SYMLINK, /* S_IFLNK */
TOMOYO_TYPE_IS_FILE, /* S_IFREG */
TOMOYO_TYPE_IS_BLOCK_DEV, /* S_IFBLK */
TOMOYO_TYPE_IS_DIRECTORY, /* S_IFDIR */
TOMOYO_TYPE_IS_CHAR_DEV, /* S_IFCHR */
TOMOYO_TYPE_IS_FIFO, /* S_IFIFO */
TOMOYO_MODE_SETUID, /* S_ISUID */
TOMOYO_MODE_SETGID, /* S_ISGID */
TOMOYO_MODE_STICKY, /* S_ISVTX */
TOMOYO_MODE_OWNER_READ, /* S_IRUSR */
TOMOYO_MODE_OWNER_WRITE, /* S_IWUSR */
TOMOYO_MODE_OWNER_EXECUTE, /* S_IXUSR */
TOMOYO_MODE_GROUP_READ, /* S_IRGRP */
TOMOYO_MODE_GROUP_WRITE, /* S_IWGRP */
TOMOYO_MODE_GROUP_EXECUTE, /* S_IXGRP */
TOMOYO_MODE_OTHERS_READ, /* S_IROTH */
TOMOYO_MODE_OTHERS_WRITE, /* S_IWOTH */
TOMOYO_MODE_OTHERS_EXECUTE, /* S_IXOTH */
TOMOYO_PATH1_UID,
TOMOYO_PATH1_GID,
TOMOYO_PATH1_INO,
TOMOYO_PATH1_MAJOR,
TOMOYO_PATH1_MINOR,
TOMOYO_PATH1_PERM,
TOMOYO_PATH1_TYPE,
TOMOYO_PATH1_DEV_MAJOR,
TOMOYO_PATH1_DEV_MINOR,
TOMOYO_PATH2_UID,
TOMOYO_PATH2_GID,
TOMOYO_PATH2_INO,
TOMOYO_PATH2_MAJOR,
TOMOYO_PATH2_MINOR,
TOMOYO_PATH2_PERM,
TOMOYO_PATH2_TYPE,
TOMOYO_PATH2_DEV_MAJOR,
TOMOYO_PATH2_DEV_MINOR,
TOMOYO_PATH1_PARENT_UID,
TOMOYO_PATH1_PARENT_GID,
TOMOYO_PATH1_PARENT_INO,
TOMOYO_PATH1_PARENT_PERM,
TOMOYO_PATH2_PARENT_UID,
TOMOYO_PATH2_PARENT_GID,
TOMOYO_PATH2_PARENT_INO,
TOMOYO_PATH2_PARENT_PERM,
TOMOYO_MAX_CONDITION_KEYWORD,
TOMOYO_NUMBER_UNION,
};


/* Index numbers for stat(). */
enum tomoyo_path_stat_index {
/* Do not change this order. */
TOMOYO_PATH1,
TOMOYO_PATH1_PARENT,
TOMOYO_PATH2,
TOMOYO_PATH2_PARENT,
TOMOYO_MAX_PATH_STAT
};

/* Index numbers for operation mode. */
enum tomoyo_mode_index {
TOMOYO_CONFIG_DISABLED,
Expand Down Expand Up @@ -290,6 +346,11 @@ struct tomoyo_policy_namespace;

/* Structure for request info. */
struct tomoyo_request_info {
/*
* For holding parameters specific to operations which deal files.
* NULL if not dealing files.
*/
struct tomoyo_obj_info *obj;
struct tomoyo_domain_info *domain;
/* For holding parameters. */
union {
Expand Down Expand Up @@ -388,6 +449,35 @@ struct tomoyo_number_group {
struct tomoyo_number_union number;
};

/* Subset of "struct stat". Used by conditional ACL and audit logs. */
struct tomoyo_mini_stat {
uid_t uid;
gid_t gid;
ino_t ino;
mode_t mode;
dev_t dev;
dev_t rdev;
};

/* Structure for attribute checks in addition to pathname checks. */
struct tomoyo_obj_info {
/*
* True if tomoyo_get_attributes() was already called, false otherwise.
*/
bool validate_done;
/* True if @stat[] is valid. */
bool stat_valid[TOMOYO_MAX_PATH_STAT];
/* First pathname. Initialized with { NULL, NULL } if no path. */
struct path path1;
/* Second pathname. Initialized with { NULL, NULL } if no path. */
struct path path2;
/*
* Information on @path1, @path1's parent directory, @path2, @path2's
* parent directory.
*/
struct tomoyo_mini_stat stat[TOMOYO_MAX_PATH_STAT];
};

/* Structure for entries which follows "struct tomoyo_condition". */
struct tomoyo_condition_element {
/* Left hand operand. */
Expand Down Expand Up @@ -733,6 +823,7 @@ void tomoyo_check_profile(void);
void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp);
void tomoyo_del_condition(struct list_head *element);
void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
void tomoyo_get_attributes(struct tomoyo_obj_info *obj);
void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns);
void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
__printf(2, 3);
Expand Down
Loading

0 comments on commit 8761afd

Please sign in to comment.