blob: a94900ea387777e30b99805b1ff9d7e96bfb44cd [file] [log] [blame]
/******************************************************************************/
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/******************************************************************************/
/*
* tomoyo_policy_memory_test.c
*
* Testing program for security/tomoyo/
*
* Copyright (C) 2005-2010 NTT DATA CORPORATION
*/
/*
* Usage: Run this program using init= boot option.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mount.h>
static void BUG(const char *msg)
{
printf("%s", msg);
fflush(stdout);
while (1)
sleep(100);
}
static const char *policy_file = NULL;
static const char *policy = NULL;
static void get_meminfo(unsigned int *policy_memory)
{
FILE *fp = fopen("/sys/kernel/security/tomoyo/meminfo", "r");
if (!fp || fscanf(fp, "Policy: %u", policy_memory) != 1 || fclose(fp))
BUG("BUG: Policy read error\n");
}
static void check_policy_common(const int found_expected, const int id)
{
FILE *fp = fopen(policy_file, "r");
char buffer[8192];
int policy_found = 0;
memset(buffer, 0, sizeof(buffer));
if (!fp)
BUG("BUG: Policy read error\n");
while (fgets(buffer, sizeof(buffer) - 1, fp)) {
char *cp = strchr(buffer, '\n');
if (cp)
*cp = '\0';
if (strcmp(buffer, policy))
continue;
policy_found = 1;
break;
}
fclose(fp);
if (policy_found != found_expected) {
printf("BUG: Policy write error: %s %s at %d\n", policy,
found_expected ? "not added" : "not deleted", id);
BUG("");
}
}
static inline void check_policy_written(FILE *fp, const int id)
{
fflush(fp);
check_policy_common(1, id);
}
static inline void check_policy_deleted(FILE *fp, const int id)
{
fflush(fp);
check_policy_common(0, id);
}
static const char *domain_testcases[] = {
"allow_create /tmp/mknod_reg_test 0600",
"allow_create /tmp/open_test 0600",
"allow_create /tmp/open_test 0600",
"allow_create /tmp/open_test 0600",
"allow_execute /bin/true",
"allow_execute /bin/true",
"allow_execute /bin/true0",
"allow_execute /bin/true1",
"allow_execute /bin/true2",
"allow_execute /bin/true3",
"allow_execute /bin/true4",
"allow_execute /bin/true5",
"allow_execute /bin/true6",
"allow_execute /bin/true7",
"allow_execute /bin/true7",
"allow_execute /bin/true7",
"allow_execute /bin/true8",
"allow_ioctl socket:[family=2:type=2:protocol=17] 0-35122",
"allow_ioctl socket:[family=2:type=2:protocol=17] 35122-35124",
"allow_link /tmp/link_source_test /tmp/link_dest_test",
"allow_mkblock /tmp/mknod_blk_test 0600 1 0",
"allow_mkchar /tmp/mknod_chr_test 0600 1 3",
"allow_mkdir /tmp/mkdir_test/ 0755",
"allow_mkfifo /tmp/mknod_fifo_test 0600",
"allow_mkfifo /tmp/mknod_fifo_test 0600",
"allow_mksock /tmp/mknod_sock_test 0600",
"allow_mksock /tmp/socket_test 0600",
"allow_read /bin/true",
"allow_read /bin/true",
"allow_read /dev/null",
"allow_read /dev/null",
"allow_read /dev/null",
"allow_read /dev/null",
"allow_read /dev/null",
"allow_read /dev/null",
"allow_read /foo",
"allow_read /proc/sys/net/ipv4/ip_local_port_range",
"allow_read /proc/sys/net/ipv4/ip_local_port_range",
"allow_read/write /bar",
"allow_read/write /dev/null",
"allow_read/write /dev/null",
"allow_read/write /proc/sys/net/ipv4/ip_local_port_range",
"allow_read/write /proc/sys/net/ipv4/ip_local_port_range",
"allow_read/write /tmp/fifo",
"allow_read/write /tmp/fifo",
"allow_read/write /tmp/rewrite_test",
"allow_rename /tmp/rename_source_test /tmp/rename_dest_test",
"allow_rmdir /tmp/rmdir_test/",
"allow_symlink /symlink",
"allow_symlink /symlink",
"allow_symlink /symlink",
"allow_symlink /symlink",
"allow_symlink /tmp/symlink_source_test",
"allow_symlink /tmp/symlink_source_test",
"allow_symlink /tmp/symlink_source_test",
"allow_symlink /tmp/symlink_source_test",
"allow_symlink /tmp/symlink_source_test",
"allow_truncate /tmp/rewrite_test",
"allow_truncate /tmp/truncate_test",
"allow_truncate /tmp/truncate_test",
"allow_unlink /tmp/unlink_test",
"allow_write /123",
"allow_write /dev/null",
"allow_write /dev/null",
"allow_write /devfile",
"allow_write /devfile",
"allow_write /proc/sys/net/ipv4/ip_local_port_range",
"allow_write /proc/sys/net/ipv4/ip_local_port_range",
"allow_write /tmp/open_test",
"allow_write /tmp/open_test",
"allow_write /tmp/open_test",
"allow_write /tmp/truncate_test",
"allow_write /tmp/truncate_test",
"allow_rewrite /tmp/rewrite_test",
"allow_rewrite /tmp/rewrite_test",
"allow_mount /dev/sda1 /mnt/sda1/ ext3 0x123",
"allow_mount /dev/sda1 /mnt/sda1/ ext3 123",
"allow_mount /dev/sda1 /mnt/sda1/ ext3 0123",
"allow_mount /dev/sda1 /mnt/sda1/ ext3 0x123",
"allow_mount /dev/sda1 /mnt/sda1/ ext3 123",
"allow_mount /dev/sda1 /mnt/sda1/ ext3 0123",
"allow_chroot /",
"allow_chroot /",
"allow_chroot /mnt/",
"allow_pivot_root / /proc/",
"allow_pivot_root /mnt/ /proc/mnt/",
"allow_unmount /",
"allow_unmount /proc/",
NULL
};
static void domain_policy_test(const unsigned int before)
{
unsigned int after;
int j;
policy_file = "/sys/kernel/security/tomoyo/domain_policy";
for (j = 0; domain_testcases[j]; j++) {
int i;
FILE *fp = fopen(policy_file, "w");
if (!fp)
BUG("BUG: Policy write error\n");
fprintf(fp, "<kernel>\n");
policy = domain_testcases[j];
printf("Processing: %s\n", policy);
for (i = 0; i < 100; i++) {
fprintf(fp, "%s\n", policy);
if (!i)
check_policy_written(fp, 1);
fprintf(fp, "delete %s\n", policy);
}
check_policy_deleted(fp, 1);
for (i = 0; i < 100; i++)
fprintf(fp, "%s\n", policy);
check_policy_written(fp, 2);
fprintf(fp, "delete %s\n", policy);
check_policy_deleted(fp, 2);
fclose(fp);
for (i = 0; i < 30; i++) {
usleep(100000);
get_meminfo(&after);
if (before == after)
break;
}
if (before != after) {
printf("Policy: %d\n", after - before);
BUG("Policy read/write test: Fail\n");
}
}
for (j = 0; j < 10; j++) {
int i;
FILE *fp = fopen(policy_file, "w");
if (!fp)
BUG("BUG: Policy write error\n");
fprintf(fp, "<kernel> /sbin/init\n");
for (i = 0; domain_testcases[i]; i++)
fprintf(fp, "%s\n", domain_testcases[i]);
fprintf(fp, "delete <kernel> /sbin/init\n");
fclose(fp);
for (i = 0; i < 50; i++) {
usleep(100000);
get_meminfo(&after);
if (before == after)
break;
}
if (before != after) {
printf("Policy: %d\n", after - before);
BUG("Policy read/write test: Fail\n");
}
}
}
static const char *exception_testcases[] = {
"allow_read /tmp/mknod_reg_test",
"allow_env HOME",
"path_group PG1 /",
"path_group PG2 /",
"address_group AG3 0.0.0.0",
"address_group AG3 1.2.3.4-5.6.7.8",
"address_group AG3 f:ee:ddd:cccc:b:aa:999:8888",
"address_group AG4 0:1:2:3:4:5:6:7-8:90:a00:b000:c00:d0:e:f000",
"number_group NG1 1000",
"number_group NG2 10-0x100000",
"number_group NG3 01234567-0xABCDEF89",
"deny_autobind 1024",
"deny_autobind 32668-65535",
"deny_autobind 0-1023",
"initialize_domain /usr/sbin/sshd",
"no_initialize_domain /usr/sbin/sshd",
"initialize_domain /usr/sbin/sshd from /bin/bash",
"no_initialize_domain /usr/sbin/sshd from /bin/bash",
"initialize_domain /usr/sbin/sshd from "
"<kernel> /bin/mingetty/bin/bash",
"no_initialize_domain /usr/sbin/sshd from "
"<kernel> /bin/mingetty/bin/bash",
"keep_domain <kernel> /usr/sbin/sshd /bin/bash",
"no_keep_domain <kernel> /usr/sbin/sshd /bin/bash",
"keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash",
"no_keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash",
"keep_domain /bin/pwd from /bin/bash",
"no_keep_domain /bin/pwd from /bin/bash",
"file_pattern /proc/\\$/task/\\$/environ",
"file_pattern /proc/\\$/task/\\$/auxv",
"allow_read /etc/ld.so.cache",
"allow_read /proc/meminfo",
"allow_read /proc/sys/kernel/version",
"allow_read /etc/localtime",
"allow_read /proc/self/task/\\$/attr/current",
"allow_read /proc/self/task/\\$/oom_score",
"allow_read /proc/self/wchan",
"allow_read /lib/ld-2.5.so",
"file_pattern pipe:[\\$]",
"file_pattern socket:[\\$]",
"file_pattern /var/cache/logwatch/logwatch.\\*/",
"file_pattern /var/cache/logwatch/logwatch.\\*/\\*",
"deny_rewrite /var/log/\\*",
"deny_rewrite /var/log/\\*/\\*",
"aggregator /etc/rc.d/rc\\?.d/\\?\\+\\+smb /etc/rc.d/init.d/smb",
"aggregator /etc/rc.d/rc\\?.d/\\?\\+\\+crond /etc/rc.d/init.d/crond",
NULL
};
static void exception_policy_test(const unsigned int before)
{
unsigned int after;
int j;
policy_file = "/sys/kernel/security/tomoyo/exception_policy";
for (j = 0; exception_testcases[j]; j++) {
int i;
FILE *fp = fopen(policy_file, "w");
if (!fp)
BUG("BUG: Policy write error\n");
policy = exception_testcases[j];
printf("Processing: %s\n", policy);
for (i = 0; i < 100; i++) {
fprintf(fp, "%s\n", policy);
if (!i)
check_policy_written(fp, 1);
fprintf(fp, "delete %s\n", policy);
}
check_policy_deleted(fp, 1);
for (i = 0; i < 100; i++)
fprintf(fp, "%s\n", policy);
check_policy_written(fp, 2);
fprintf(fp, "delete %s\n", policy);
check_policy_deleted(fp, 2);
fclose(fp);
for (i = 0; i < 30; i++) {
usleep(100000);
get_meminfo(&after);
if (before == after)
break;
}
if (before != after) {
printf("Policy: %d\n", after - before);
BUG("Policy read/write test: Fail\n");
}
}
for (j = 0; j < 10; j++) {
int i;
FILE *fp = fopen(policy_file, "w");
if (!fp)
BUG("BUG: Policy write error\n");
for (i = 0; exception_testcases[i]; i++)
fprintf(fp, "%s\n", exception_testcases[i]);
for (i = 0; exception_testcases[i]; i++)
fprintf(fp, "delete %s\n", exception_testcases[i]);
fclose(fp);
for (i = 0; i < 50; i++) {
usleep(100000);
get_meminfo(&after);
if (before == after)
break;
}
if (before != after) {
printf("Policy: %d\n", after - before);
BUG("Policy read/write test: Fail\n");
}
}
}
int main(int argc, char *argv[])
{
unsigned int before;
mount("/proc", "/proc/", "proc", 0, NULL);
get_meminfo(&before);
domain_policy_test(before);
exception_policy_test(before);
BUG("Policy read/write test: Success\n");
return 0;
}