summaryrefslogtreecommitdiff
path: root/security/tomoyo/file.c
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2010-05-17 05:11:36 +0400
committerJames Morris <jmorris@namei.org>2010-08-02 09:33:38 +0400
commit17fcfbd9d45b57f38d40e31f9d28db53f4af5c88 (patch)
treee221937affe4d886706e880f39e1424333490cc0 /security/tomoyo/file.c
parent2106ccd972dcd9fda7df9b181505fac1741b3508 (diff)
downloadlinux-17fcfbd9d45b57f38d40e31f9d28db53f4af5c88.tar.xz
TOMOYO: Add interactive enforcing mode.
Since the behavior of the system is restricted by policy, we may need to update policy when you update packages. We need to update policy in the following cases. * The pathname of files has changed. * The dependency of files has changed. * The access permissions required has increased. The ideal way to update policy is to rebuild from the scratch using learning mode. But it is not desirable to change from enforcing mode to other mode if the system has once entered in production state. Suppose MAC could support per-application enforcing mode, the MAC becomes useless if an application that is not running in enforcing mode was cracked. For example, the whole system becomes vulnerable if only HTTP server application is running in learning mode to rebuild policy for the application. So, in TOMOYO Linux, updating policy is done while the system is running in enforcing mode. This patch implements "interactive enforcing mode" which allows administrators to judge whether to accept policy violation in enforcing mode or not. A demo movie is available at http://www.youtube.com/watch?v=b9q1Jo25LPA . 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/file.c')
-rw-r--r--security/tomoyo/file.c140
1 files changed, 67 insertions, 73 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index ae32cab8ec7e..c629cb4e2c66 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -478,7 +478,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
}
/**
- * tomoyo_get_file_pattern - Get patterned pathname.
+ * tomoyo_file_pattern - Get patterned pathname.
*
* @filename: The filename to find patterned pathname.
*
@@ -486,8 +486,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
*
* Caller holds tomoyo_read_lock().
*/
-const struct tomoyo_path_info *
-tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
+const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename)
{
struct tomoyo_pattern_entry *ptr;
const struct tomoyo_path_info *pattern = NULL;
@@ -507,7 +506,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
}
if (pattern)
filename = pattern;
- return filename;
+ return filename->name;
}
/**
@@ -812,23 +811,25 @@ static int tomoyo_file_perm(struct tomoyo_request_info *r,
perm = 1 << TOMOYO_TYPE_EXECUTE;
} else
BUG();
- error = tomoyo_path_acl(r, filename, perm, mode != 1);
- if (error && mode == 4 && !r->domain->ignore_global_allow_read
- && tomoyo_is_globally_readable_file(filename))
+ do {
+ error = tomoyo_path_acl(r, filename, perm, mode != 1);
+ if (error && mode == 4 && !r->domain->ignore_global_allow_read
+ && tomoyo_is_globally_readable_file(filename))
+ error = 0;
+ if (!error)
+ break;
+ tomoyo_warn_log(r, "%s %s", msg, filename->name);
+ error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
+ mode == 1 ? filename->name :
+ tomoyo_file_pattern(filename));
+ /*
+ * Do not retry for execute request, for alias may have
+ * changed.
+ */
+ } while (error == TOMOYO_RETRY_REQUEST && mode != 1);
+ if (r->mode != TOMOYO_CONFIG_ENFORCING)
error = 0;
- if (!error)
- return 0;
- tomoyo_warn_log(r, "%s %s", msg, filename->name);
- if (r->mode == TOMOYO_CONFIG_ENFORCING)
- return error;
- if (tomoyo_domain_quota_is_ok(r)) {
- /* Don't use patterns for execute permission. */
- const struct tomoyo_path_info *patterned_file = (mode != 1) ?
- tomoyo_get_file_pattern(filename) : filename;
- tomoyo_update_file_acl(mode, patterned_file->name, r->domain,
- false);
- }
- return 0;
+ return error;
}
/**
@@ -1123,21 +1124,21 @@ static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type,
static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
const struct tomoyo_path_info *filename)
{
+ const char *msg;
int error;
next:
- error = tomoyo_path_acl(r, filename, 1 << operation, 1);
- if (!error)
- goto ok;
- tomoyo_warn_log(r, "%s %s", tomoyo_path2keyword(operation),
- filename->name);
- if (tomoyo_domain_quota_is_ok(r)) {
- const char *name = tomoyo_get_file_pattern(filename)->name;
- tomoyo_update_path_acl(operation, name, r->domain, false);
- }
+ do {
+ error = tomoyo_path_acl(r, filename, 1 << operation, 1);
+ if (!error)
+ break;
+ msg = tomoyo_path2keyword(operation);
+ tomoyo_warn_log(r, "%s %s", msg, filename->name);
+ error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
+ tomoyo_file_pattern(filename));
+ } while (error == TOMOYO_RETRY_REQUEST);
if (r->mode != TOMOYO_CONFIG_ENFORCING)
error = 0;
- ok:
/*
* Since "allow_truncate" doesn't imply "allow_rewrite" permission,
* we need to check "allow_rewrite" permission if the filename is
@@ -1267,6 +1268,7 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r,
char buffer[64];
int error;
u8 radix;
+ const char *msg;
if (!filename)
return 0;
@@ -1286,15 +1288,16 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r,
break;
}
tomoyo_print_ulong(buffer, sizeof(buffer), number, radix);
- error = tomoyo_path_number_acl(r, type, filename, number);
- if (!error)
- return 0;
- tomoyo_warn_log(r, "%s %s %s", tomoyo_path_number2keyword(type),
- filename->name, buffer);
- if (tomoyo_domain_quota_is_ok(r))
- tomoyo_update_path_number_acl(type,
- tomoyo_get_file_pattern(filename)
- ->name, buffer, r->domain, false);
+ do {
+ error = tomoyo_path_number_acl(r, type, filename, number);
+ if (!error)
+ break;
+ msg = tomoyo_path_number2keyword(type);
+ tomoyo_warn_log(r, "%s %s %s", msg, filename->name, buffer);
+ error = tomoyo_supervisor(r, "allow_%s %s %s\n", msg,
+ tomoyo_file_pattern(filename),
+ buffer);
+ } while (error == TOMOYO_RETRY_REQUEST);
if (r->mode != TOMOYO_CONFIG_ENFORCING)
error = 0;
return error;
@@ -1484,32 +1487,23 @@ static int tomoyo_path_number3_perm2(struct tomoyo_request_info *r,
const unsigned int dev)
{
int error;
+ const char *msg;
const unsigned int major = MAJOR(dev);
const unsigned int minor = MINOR(dev);
- error = tomoyo_path_number3_acl(r, filename, 1 << operation, mode,
- major, minor);
- if (!error)
- return 0;
- tomoyo_warn_log(r, "%s %s 0%o %u %u",
- tomoyo_path_number32keyword(operation),
- filename->name, mode, major, minor);
- if (tomoyo_domain_quota_is_ok(r)) {
- char mode_buf[64];
- char major_buf[64];
- char minor_buf[64];
- memset(mode_buf, 0, sizeof(mode_buf));
- memset(major_buf, 0, sizeof(major_buf));
- memset(minor_buf, 0, sizeof(minor_buf));
- snprintf(mode_buf, sizeof(mode_buf) - 1, "0%o", mode);
- snprintf(major_buf, sizeof(major_buf) - 1, "%u", major);
- snprintf(minor_buf, sizeof(minor_buf) - 1, "%u", minor);
- tomoyo_update_path_number3_acl(operation,
- tomoyo_get_file_pattern(filename)
- ->name, mode_buf, major_buf,
- minor_buf, r->domain, false);
- }
- if (r->mode != TOMOYO_CONFIG_ENFORCING)
+ do {
+ error = tomoyo_path_number3_acl(r, filename, 1 << operation,
+ mode, major, minor);
+ if (!error)
+ break;
+ msg = tomoyo_path_number32keyword(operation);
+ tomoyo_warn_log(r, "%s %s 0%o %u %u", msg, filename->name,
+ mode, major, minor);
+ error = tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", msg,
+ tomoyo_file_pattern(filename), mode,
+ major, minor);
+ } while (error == TOMOYO_RETRY_REQUEST);
+ if (r->mode != TOMOYO_CONFIG_ENFORCING)
error = 0;
return error;
}
@@ -1562,6 +1556,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
struct path *path2)
{
int error = -ENOMEM;
+ const char *msg;
struct tomoyo_path_info *buf1;
struct tomoyo_path_info *buf2;
struct tomoyo_request_info r;
@@ -1591,17 +1586,16 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
}
}
}
- error = tomoyo_path2_acl(&r, operation, buf1, buf2);
- if (!error)
- goto out;
- tomoyo_warn_log(&r, "%s %s %s", tomoyo_path22keyword(operation),
- buf1->name, buf2->name);
- if (tomoyo_domain_quota_is_ok(&r)) {
- const char *name1 = tomoyo_get_file_pattern(buf1)->name;
- const char *name2 = tomoyo_get_file_pattern(buf2)->name;
- tomoyo_update_path2_acl(operation, name1, name2, r.domain,
- false);
- }
+ do {
+ error = tomoyo_path2_acl(&r, operation, buf1, buf2);
+ if (!error)
+ break;
+ msg = tomoyo_path22keyword(operation);
+ tomoyo_warn_log(&r, "%s %s %s", msg, buf1->name, buf2->name);
+ error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg,
+ tomoyo_file_pattern(buf1),
+ tomoyo_file_pattern(buf2));
+ } while (error == TOMOYO_RETRY_REQUEST);
out:
kfree(buf1);
kfree(buf2);