aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/file.c
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2010-05-16 21:11:36 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:33:38 -0400
commit17fcfbd9d45b57f38d40e31f9d28db53f4af5c88 (patch)
treee221937affe4d886706e880f39e1424333490cc0 /security/tomoyo/file.c
parent2106ccd972dcd9fda7df9b181505fac1741b3508 (diff)
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,
478} 478}
479 479
480/** 480/**
481 * tomoyo_get_file_pattern - Get patterned pathname. 481 * tomoyo_file_pattern - Get patterned pathname.
482 * 482 *
483 * @filename: The filename to find patterned pathname. 483 * @filename: The filename to find patterned pathname.
484 * 484 *
@@ -486,8 +486,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
486 * 486 *
487 * Caller holds tomoyo_read_lock(). 487 * Caller holds tomoyo_read_lock().
488 */ 488 */
489const struct tomoyo_path_info * 489const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename)
490tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
491{ 490{
492 struct tomoyo_pattern_entry *ptr; 491 struct tomoyo_pattern_entry *ptr;
493 const struct tomoyo_path_info *pattern = NULL; 492 const struct tomoyo_path_info *pattern = NULL;
@@ -507,7 +506,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
507 } 506 }
508 if (pattern) 507 if (pattern)
509 filename = pattern; 508 filename = pattern;
510 return filename; 509 return filename->name;
511} 510}
512 511
513/** 512/**
@@ -812,23 +811,25 @@ static int tomoyo_file_perm(struct tomoyo_request_info *r,
812 perm = 1 << TOMOYO_TYPE_EXECUTE; 811 perm = 1 << TOMOYO_TYPE_EXECUTE;
813 } else 812 } else
814 BUG(); 813 BUG();
815 error = tomoyo_path_acl(r, filename, perm, mode != 1); 814 do {
816 if (error && mode == 4 && !r->domain->ignore_global_allow_read 815 error = tomoyo_path_acl(r, filename, perm, mode != 1);
817 && tomoyo_is_globally_readable_file(filename)) 816 if (error && mode == 4 && !r->domain->ignore_global_allow_read
817 && tomoyo_is_globally_readable_file(filename))
818 error = 0;
819 if (!error)
820 break;
821 tomoyo_warn_log(r, "%s %s", msg, filename->name);
822 error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
823 mode == 1 ? filename->name :
824 tomoyo_file_pattern(filename));
825 /*
826 * Do not retry for execute request, for alias may have
827 * changed.
828 */
829 } while (error == TOMOYO_RETRY_REQUEST && mode != 1);
830 if (r->mode != TOMOYO_CONFIG_ENFORCING)
818 error = 0; 831 error = 0;
819 if (!error) 832 return error;
820 return 0;
821 tomoyo_warn_log(r, "%s %s", msg, filename->name);
822 if (r->mode == TOMOYO_CONFIG_ENFORCING)
823 return error;
824 if (tomoyo_domain_quota_is_ok(r)) {
825 /* Don't use patterns for execute permission. */
826 const struct tomoyo_path_info *patterned_file = (mode != 1) ?
827 tomoyo_get_file_pattern(filename) : filename;
828 tomoyo_update_file_acl(mode, patterned_file->name, r->domain,
829 false);
830 }
831 return 0;
832} 833}
833 834
834/** 835/**
@@ -1123,21 +1124,21 @@ static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type,
1123static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, 1124static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
1124 const struct tomoyo_path_info *filename) 1125 const struct tomoyo_path_info *filename)
1125{ 1126{
1127 const char *msg;
1126 int error; 1128 int error;
1127 1129
1128 next: 1130 next:
1129 error = tomoyo_path_acl(r, filename, 1 << operation, 1); 1131 do {
1130 if (!error) 1132 error = tomoyo_path_acl(r, filename, 1 << operation, 1);
1131 goto ok; 1133 if (!error)
1132 tomoyo_warn_log(r, "%s %s", tomoyo_path2keyword(operation), 1134 break;
1133 filename->name); 1135 msg = tomoyo_path2keyword(operation);
1134 if (tomoyo_domain_quota_is_ok(r)) { 1136 tomoyo_warn_log(r, "%s %s", msg, filename->name);
1135 const char *name = tomoyo_get_file_pattern(filename)->name; 1137 error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
1136 tomoyo_update_path_acl(operation, name, r->domain, false); 1138 tomoyo_file_pattern(filename));
1137 } 1139 } while (error == TOMOYO_RETRY_REQUEST);
1138 if (r->mode != TOMOYO_CONFIG_ENFORCING) 1140 if (r->mode != TOMOYO_CONFIG_ENFORCING)
1139 error = 0; 1141 error = 0;
1140 ok:
1141 /* 1142 /*
1142 * Since "allow_truncate" doesn't imply "allow_rewrite" permission, 1143 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
1143 * we need to check "allow_rewrite" permission if the filename is 1144 * 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,
1267 char buffer[64]; 1268 char buffer[64];
1268 int error; 1269 int error;
1269 u8 radix; 1270 u8 radix;
1271 const char *msg;
1270 1272
1271 if (!filename) 1273 if (!filename)
1272 return 0; 1274 return 0;
@@ -1286,15 +1288,16 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r,
1286 break; 1288 break;
1287 } 1289 }
1288 tomoyo_print_ulong(buffer, sizeof(buffer), number, radix); 1290 tomoyo_print_ulong(buffer, sizeof(buffer), number, radix);
1289 error = tomoyo_path_number_acl(r, type, filename, number); 1291 do {
1290 if (!error) 1292 error = tomoyo_path_number_acl(r, type, filename, number);
1291 return 0; 1293 if (!error)
1292 tomoyo_warn_log(r, "%s %s %s", tomoyo_path_number2keyword(type), 1294 break;
1293 filename->name, buffer); 1295 msg = tomoyo_path_number2keyword(type);
1294 if (tomoyo_domain_quota_is_ok(r)) 1296 tomoyo_warn_log(r, "%s %s %s", msg, filename->name, buffer);
1295 tomoyo_update_path_number_acl(type, 1297 error = tomoyo_supervisor(r, "allow_%s %s %s\n", msg,
1296 tomoyo_get_file_pattern(filename) 1298 tomoyo_file_pattern(filename),
1297 ->name, buffer, r->domain, false); 1299 buffer);
1300 } while (error == TOMOYO_RETRY_REQUEST);
1298 if (r->mode != TOMOYO_CONFIG_ENFORCING) 1301 if (r->mode != TOMOYO_CONFIG_ENFORCING)
1299 error = 0; 1302 error = 0;
1300 return error; 1303 return error;
@@ -1484,32 +1487,23 @@ static int tomoyo_path_number3_perm2(struct tomoyo_request_info *r,
1484 const unsigned int dev) 1487 const unsigned int dev)
1485{ 1488{
1486 int error; 1489 int error;
1490 const char *msg;
1487 const unsigned int major = MAJOR(dev); 1491 const unsigned int major = MAJOR(dev);
1488 const unsigned int minor = MINOR(dev); 1492 const unsigned int minor = MINOR(dev);
1489 1493
1490 error = tomoyo_path_number3_acl(r, filename, 1 << operation, mode, 1494 do {
1491 major, minor); 1495 error = tomoyo_path_number3_acl(r, filename, 1 << operation,
1492 if (!error) 1496 mode, major, minor);
1493 return 0; 1497 if (!error)
1494 tomoyo_warn_log(r, "%s %s 0%o %u %u", 1498 break;
1495 tomoyo_path_number32keyword(operation), 1499 msg = tomoyo_path_number32keyword(operation);
1496 filename->name, mode, major, minor); 1500 tomoyo_warn_log(r, "%s %s 0%o %u %u", msg, filename->name,
1497 if (tomoyo_domain_quota_is_ok(r)) { 1501 mode, major, minor);
1498 char mode_buf[64]; 1502 error = tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", msg,
1499 char major_buf[64]; 1503 tomoyo_file_pattern(filename), mode,
1500 char minor_buf[64]; 1504 major, minor);
1501 memset(mode_buf, 0, sizeof(mode_buf)); 1505 } while (error == TOMOYO_RETRY_REQUEST);
1502 memset(major_buf, 0, sizeof(major_buf)); 1506 if (r->mode != TOMOYO_CONFIG_ENFORCING)
1503 memset(minor_buf, 0, sizeof(minor_buf));
1504 snprintf(mode_buf, sizeof(mode_buf) - 1, "0%o", mode);
1505 snprintf(major_buf, sizeof(major_buf) - 1, "%u", major);
1506 snprintf(minor_buf, sizeof(minor_buf) - 1, "%u", minor);
1507 tomoyo_update_path_number3_acl(operation,
1508 tomoyo_get_file_pattern(filename)
1509 ->name, mode_buf, major_buf,
1510 minor_buf, r->domain, false);
1511 }
1512 if (r->mode != TOMOYO_CONFIG_ENFORCING)
1513 error = 0; 1507 error = 0;
1514 return error; 1508 return error;
1515} 1509}
@@ -1562,6 +1556,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1562 struct path *path2) 1556 struct path *path2)
1563{ 1557{
1564 int error = -ENOMEM; 1558 int error = -ENOMEM;
1559 const char *msg;
1565 struct tomoyo_path_info *buf1; 1560 struct tomoyo_path_info *buf1;
1566 struct tomoyo_path_info *buf2; 1561 struct tomoyo_path_info *buf2;
1567 struct tomoyo_request_info r; 1562 struct tomoyo_request_info r;
@@ -1591,17 +1586,16 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1591 } 1586 }
1592 } 1587 }
1593 } 1588 }
1594 error = tomoyo_path2_acl(&r, operation, buf1, buf2); 1589 do {
1595 if (!error) 1590 error = tomoyo_path2_acl(&r, operation, buf1, buf2);
1596 goto out; 1591 if (!error)
1597 tomoyo_warn_log(&r, "%s %s %s", tomoyo_path22keyword(operation), 1592 break;
1598 buf1->name, buf2->name); 1593 msg = tomoyo_path22keyword(operation);
1599 if (tomoyo_domain_quota_is_ok(&r)) { 1594 tomoyo_warn_log(&r, "%s %s %s", msg, buf1->name, buf2->name);
1600 const char *name1 = tomoyo_get_file_pattern(buf1)->name; 1595 error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg,
1601 const char *name2 = tomoyo_get_file_pattern(buf2)->name; 1596 tomoyo_file_pattern(buf1),
1602 tomoyo_update_path2_acl(operation, name1, name2, r.domain, 1597 tomoyo_file_pattern(buf2));
1603 false); 1598 } while (error == TOMOYO_RETRY_REQUEST);
1604 }
1605 out: 1599 out:
1606 kfree(buf1); 1600 kfree(buf1);
1607 kfree(buf2); 1601 kfree(buf2);