80 |
[CCS_ALLOW_ENFORCE_GRACE] = { "ALLOW_ENFORCE_GRACE", 0, 1 }, |
[CCS_ALLOW_ENFORCE_GRACE] = { "ALLOW_ENFORCE_GRACE", 0, 1 }, |
81 |
}; |
}; |
82 |
|
|
83 |
typedef struct { |
struct profile { |
84 |
unsigned int value[CCS_MAX_CONTROL_INDEX]; |
unsigned int value[CCS_MAX_CONTROL_INDEX]; |
85 |
const struct path_info *comment; |
const struct path_info *comment; |
86 |
} PROFILE; |
}; |
87 |
|
|
88 |
static PROFILE *profile_ptr[MAX_PROFILES]; |
static struct profile *profile_ptr[MAX_PROFILES]; |
89 |
|
|
90 |
/************************* UTILITY FUNCTIONS *************************/ |
/************************* UTILITY FUNCTIONS *************************/ |
91 |
|
|
429 |
} |
} |
430 |
|
|
431 |
/* |
/* |
432 |
* Transactional printf() to IO_BUFFER structure. |
* Transactional printf() to struct io_buffer structure. |
433 |
* snprintf() will truncate, but io_printf() won't. |
* snprintf() will truncate, but io_printf() won't. |
434 |
* Returns zero on success, nonzero otherwise. |
* Returns zero on success, nonzero otherwise. |
435 |
*/ |
*/ |
436 |
int io_printf(IO_BUFFER *head, const char *fmt, ...) |
int io_printf(struct io_buffer *head, const char *fmt, ...) |
437 |
{ |
{ |
438 |
va_list args; |
va_list args; |
439 |
int len, pos = head->read_avail, size = head->readbuf_size - pos; |
int len, pos = head->read_avail, size = head->readbuf_size - pos; |
499 |
return CheckCCSFlags(index) == 1; |
return CheckCCSFlags(index) == 1; |
500 |
} |
} |
501 |
|
|
502 |
static PROFILE *FindOrAssignNewProfile(const unsigned int profile) |
static struct profile *FindOrAssignNewProfile(const unsigned int profile) |
503 |
{ |
{ |
504 |
static DECLARE_MUTEX(profile_lock); |
static DECLARE_MUTEX(profile_lock); |
505 |
PROFILE *ptr = NULL; |
struct profile *ptr = NULL; |
506 |
down(&profile_lock); |
down(&profile_lock); |
507 |
if (profile < MAX_PROFILES && (ptr = profile_ptr[profile]) == NULL) { |
if (profile < MAX_PROFILES && (ptr = profile_ptr[profile]) == NULL) { |
508 |
if ((ptr = (PROFILE *) alloc_element(sizeof(PROFILE))) != NULL) { |
if ((ptr = alloc_element(sizeof(*ptr))) != NULL) { |
509 |
int i; |
int i; |
510 |
for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) ptr->value[i] = ccs_control_array[i].current_value; |
for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) ptr->value[i] = ccs_control_array[i].current_value; |
511 |
mb(); /* Instead of using spinlock. */ |
mb(); /* Instead of using spinlock. */ |
518 |
|
|
519 |
static int profile_loaded = 0; |
static int profile_loaded = 0; |
520 |
|
|
521 |
static int SetStatus(IO_BUFFER *head) |
static int SetStatus(struct io_buffer *head) |
522 |
{ |
{ |
523 |
char *data = head->write_buf; |
char *data = head->write_buf; |
524 |
unsigned int i, value; |
unsigned int i, value; |
525 |
char *cp; |
char *cp; |
526 |
PROFILE *profile; |
struct profile *profile; |
527 |
if (!isRoot()) return -EPERM; |
if (!isRoot()) return -EPERM; |
528 |
i = simple_strtoul(data, &cp, 10); |
i = simple_strtoul(data, &cp, 10); |
529 |
if (data != cp) { |
if (data != cp) { |
556 |
return -EINVAL; |
return -EINVAL; |
557 |
} |
} |
558 |
|
|
559 |
static int ReadStatus(IO_BUFFER *head) |
static int ReadStatus(struct io_buffer *head) |
560 |
{ |
{ |
561 |
if (!head->read_eof) { |
if (!head->read_eof) { |
562 |
if (!isRoot()) return -EPERM; |
if (!isRoot()) return -EPERM; |
564 |
int step; |
int step; |
565 |
for (step = head->read_step; step < MAX_PROFILES * CCS_MAX_CONTROL_INDEX; step++) { |
for (step = head->read_step; step < MAX_PROFILES * CCS_MAX_CONTROL_INDEX; step++) { |
566 |
const int i = step / CCS_MAX_CONTROL_INDEX, j = step % CCS_MAX_CONTROL_INDEX; |
const int i = step / CCS_MAX_CONTROL_INDEX, j = step % CCS_MAX_CONTROL_INDEX; |
567 |
const PROFILE *profile = profile_ptr[i]; |
const struct profile *profile = profile_ptr[i]; |
568 |
head->read_step = step; |
head->read_step = step; |
569 |
if (!profile) continue; |
if (!profile) continue; |
570 |
switch (j) { |
switch (j) { |
614 |
} |
} |
615 |
} |
} |
616 |
if (step == MAX_PROFILES * CCS_MAX_CONTROL_INDEX) { |
if (step == MAX_PROFILES * CCS_MAX_CONTROL_INDEX) { |
617 |
head->read_var2 = (void *) ""; |
head->read_var2 = ""; |
618 |
head->read_step = 0; |
head->read_step = 0; |
619 |
} |
} |
620 |
} |
} |
631 |
|
|
632 |
/************************* POLICY MANAGER HANDLER *************************/ |
/************************* POLICY MANAGER HANDLER *************************/ |
633 |
|
|
634 |
typedef struct policy_manager_entry { |
struct policy_manager_entry { |
635 |
struct policy_manager_entry *next; |
struct policy_manager_entry *next; |
636 |
const struct path_info *manager; |
const struct path_info *manager; |
637 |
u8 is_domain; |
u8 is_domain; |
638 |
u8 is_deleted; |
u8 is_deleted; |
639 |
} POLICY_MANAGER_ENTRY; |
}; |
640 |
|
|
641 |
static POLICY_MANAGER_ENTRY *policy_manager_list = NULL; |
static struct policy_manager_entry *policy_manager_list = NULL; |
642 |
|
|
643 |
static int AddManagerEntry(const char *manager, u8 is_delete) |
static int AddManagerEntry(const char *manager, u8 is_delete) |
644 |
{ |
{ |
645 |
POLICY_MANAGER_ENTRY *new_entry, *ptr; |
struct policy_manager_entry *new_entry, *ptr; |
646 |
static DECLARE_MUTEX(lock); |
static DECLARE_MUTEX(lock); |
647 |
const struct path_info *saved_manager; |
const struct path_info *saved_manager; |
648 |
int error = -ENOMEM; |
int error = -ENOMEM; |
667 |
error = -ENOENT; |
error = -ENOENT; |
668 |
goto out; |
goto out; |
669 |
} |
} |
670 |
if ((new_entry = (POLICY_MANAGER_ENTRY *) alloc_element(sizeof(POLICY_MANAGER_ENTRY))) == NULL) goto out; |
if ((new_entry = alloc_element(sizeof(*new_entry))) == NULL) goto out; |
671 |
new_entry->manager = saved_manager; |
new_entry->manager = saved_manager; |
672 |
new_entry->is_domain = is_domain; |
new_entry->is_domain = is_domain; |
673 |
mb(); /* Instead of using spinlock. */ |
mb(); /* Instead of using spinlock. */ |
683 |
return error; |
return error; |
684 |
} |
} |
685 |
|
|
686 |
static int AddManagerPolicy(IO_BUFFER *head) |
static int AddManagerPolicy(struct io_buffer *head) |
687 |
{ |
{ |
688 |
const char *data = head->write_buf; |
const char *data = head->write_buf; |
689 |
int is_delete = 0; |
int is_delete = 0; |
695 |
return AddManagerEntry(data, is_delete); |
return AddManagerEntry(data, is_delete); |
696 |
} |
} |
697 |
|
|
698 |
static int ReadManagerPolicy(IO_BUFFER *head) |
static int ReadManagerPolicy(struct io_buffer *head) |
699 |
{ |
{ |
700 |
if (!head->read_eof) { |
if (!head->read_eof) { |
701 |
POLICY_MANAGER_ENTRY *ptr = (POLICY_MANAGER_ENTRY *) head->read_var2; |
struct policy_manager_entry *ptr = head->read_var2; |
702 |
if (!isRoot()) return -EPERM; |
if (!isRoot()) return -EPERM; |
703 |
if (!ptr) ptr = policy_manager_list; |
if (!ptr) ptr = policy_manager_list; |
704 |
while (ptr) { |
while (ptr) { |
705 |
head->read_var2 = (void *) ptr; |
head->read_var2 = ptr; |
706 |
if (!ptr->is_deleted && io_printf(head, "%s\n", ptr->manager->name)) break; |
if (!ptr->is_deleted && io_printf(head, "%s\n", ptr->manager->name)) break; |
707 |
ptr = ptr->next; |
ptr = ptr->next; |
708 |
} |
} |
714 |
/* Check whether the current process is a policy manager. */ |
/* Check whether the current process is a policy manager. */ |
715 |
static int IsPolicyManager(void) |
static int IsPolicyManager(void) |
716 |
{ |
{ |
717 |
POLICY_MANAGER_ENTRY *ptr; |
struct policy_manager_entry *ptr; |
718 |
const char *exe; |
const char *exe; |
719 |
const struct path_info *domainname = current->domain_info->domainname; |
const struct path_info *domainname = current->domain_info->domainname; |
720 |
if (!sbin_init_started) return 1; |
if (!sbin_init_started) return 1; |
741 |
|
|
742 |
/************************* DOMAIN POLICY HANDLER *************************/ |
/************************* DOMAIN POLICY HANDLER *************************/ |
743 |
|
|
744 |
static int AddDomainPolicy(IO_BUFFER *head) |
static int AddDomainPolicy(struct io_buffer *head) |
745 |
{ |
{ |
746 |
char *data = head->write_buf; |
char *data = head->write_buf; |
747 |
struct domain_info *domain = head->write_var1; |
struct domain_info *domain = head->write_var1; |
800 |
return -EINVAL; |
return -EINVAL; |
801 |
} |
} |
802 |
|
|
803 |
static int ReadDomainPolicy(IO_BUFFER *head) |
static int ReadDomainPolicy(struct io_buffer *head) |
804 |
{ |
{ |
805 |
if (!head->read_eof) { |
if (!head->read_eof) { |
806 |
struct domain_info *domain = head->read_var1; |
struct domain_info *domain = head->read_var1; |
819 |
head->read_var2 = NULL; head->read_step = 1; |
head->read_var2 = NULL; head->read_step = 1; |
820 |
step1: |
step1: |
821 |
if (io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n%s\n", domain->domainname->name, domain->profile, domain->quota_warned ? "quota_exceeded\n" : "")) break; |
if (io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n%s\n", domain->domainname->name, domain->profile, domain->quota_warned ? "quota_exceeded\n" : "")) break; |
822 |
head->read_var2 = (void *) domain->first_acl_ptr; head->read_step = 2; |
head->read_var2 = domain->first_acl_ptr; head->read_step = 2; |
823 |
step2: |
step2: |
824 |
for (ptr = (struct acl_info *) head->read_var2; ptr; ptr = ptr->next) { |
for (ptr = head->read_var2; ptr; ptr = ptr->next) { |
825 |
const u8 acl_type = ptr->type; |
const u8 acl_type = ptr->type; |
826 |
const int pos = head->read_avail; |
const int pos = head->read_avail; |
827 |
head->read_var2 = (void *) ptr; |
head->read_var2 = ptr; |
828 |
if (ptr->is_deleted) continue; |
if (ptr->is_deleted) continue; |
829 |
if (0) { |
if (0) { |
830 |
#ifdef CONFIG_TOMOYO_MAC_FOR_FILE |
#ifdef CONFIG_TOMOYO_MAC_FOR_FILE |
831 |
} else if (acl_type == TYPE_FILE_ACL) { |
} else if (acl_type == TYPE_FILE_ACL) { |
832 |
const unsigned char b = ptr->u.b[1]; |
const unsigned char b = ptr->u.b[1]; |
833 |
if (io_printf(head, "%d %s%s", ptr->u.b[0], b ? "@" : "", b ? ((FILE_ACL_RECORD *) ptr)->u.group->group_name->name : ((FILE_ACL_RECORD *) ptr)->u.filename->name) |
if (io_printf(head, "%d %s%s", ptr->u.b[0], b ? "@" : "", b ? ((struct file_acl_record *) ptr)->u.group->group_name->name : ((struct file_acl_record *) ptr)->u.filename->name) |
834 |
|| DumpCondition(head, ptr->cond)) { |
|| DumpCondition(head, ptr->cond)) { |
835 |
head->read_avail = pos; break; |
head->read_avail = pos; break; |
836 |
} |
} |
837 |
#endif |
#endif |
838 |
#ifdef CONFIG_TOMOYO_MAC_FOR_ARGV0 |
#ifdef CONFIG_TOMOYO_MAC_FOR_ARGV0 |
839 |
} else if (acl_type == TYPE_ARGV0_ACL) { |
} else if (acl_type == TYPE_ARGV0_ACL) { |
840 |
if (io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s", ((ARGV0_ACL_RECORD *) ptr)->filename->name, ((ARGV0_ACL_RECORD *) ptr)->argv0->name) || |
if (io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s", ((struct argv0_acl_record *) ptr)->filename->name, ((struct argv0_acl_record *) ptr)->argv0->name) || |
841 |
DumpCondition(head, ptr->cond)) { |
DumpCondition(head, ptr->cond)) { |
842 |
head->read_avail = pos; break; |
head->read_avail = pos; break; |
843 |
} |
} |
854 |
if (io_printf(head, KEYWORD_ALLOW_NETWORK "%s ", network2keyword(ptr->u.b[0]))) break; |
if (io_printf(head, KEYWORD_ALLOW_NETWORK "%s ", network2keyword(ptr->u.b[0]))) break; |
855 |
switch (ptr->u.b[1]) { |
switch (ptr->u.b[1]) { |
856 |
case IP_RECORD_TYPE_ADDRESS_GROUP: |
case IP_RECORD_TYPE_ADDRESS_GROUP: |
857 |
if (io_printf(head, "@%s", ((IP_NETWORK_ACL_RECORD *) ptr)->u.group->group_name->name)) goto print_ip_record_out; |
if (io_printf(head, "@%s", ((struct ip_network_acl_record *) ptr)->u.group->group_name->name)) goto print_ip_record_out; |
858 |
break; |
break; |
859 |
case IP_RECORD_TYPE_IPv4: |
case IP_RECORD_TYPE_IPv4: |
860 |
{ |
{ |
861 |
const u32 min_address = ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv4.min, max_address = ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv4.max; |
const u32 min_address = ((struct ip_network_acl_record *) ptr)->u.ipv4.min, max_address = ((struct ip_network_acl_record *) ptr)->u.ipv4.max; |
862 |
if (io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address))) goto print_ip_record_out; |
if (io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address))) goto print_ip_record_out; |
863 |
if (min_address != max_address && io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address))) goto print_ip_record_out; |
if (min_address != max_address && io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address))) goto print_ip_record_out; |
864 |
} |
} |
866 |
case IP_RECORD_TYPE_IPv6: |
case IP_RECORD_TYPE_IPv6: |
867 |
{ |
{ |
868 |
char buf[64]; |
char buf[64]; |
869 |
const u16 *min_address = ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv6.min, *max_address = ((IP_NETWORK_ACL_RECORD *) ptr)->u.ipv6.max; |
const u16 *min_address = ((struct ip_network_acl_record *) ptr)->u.ipv6.min, *max_address = ((struct ip_network_acl_record *) ptr)->u.ipv6.max; |
870 |
print_ipv6(buf, sizeof(buf), min_address); |
print_ipv6(buf, sizeof(buf), min_address); |
871 |
if (io_printf(head, "%s", buf)) goto print_ip_record_out; |
if (io_printf(head, "%s", buf)) goto print_ip_record_out; |
872 |
if (memcmp(min_address, max_address, 16)) { |
if (memcmp(min_address, max_address, 16)) { |
877 |
break; |
break; |
878 |
} |
} |
879 |
{ |
{ |
880 |
const u16 min_port = ((IP_NETWORK_ACL_RECORD *) ptr)->min_port, max_port = ((IP_NETWORK_ACL_RECORD *) ptr)->max_port; |
const u16 min_port = ((struct ip_network_acl_record *) ptr)->min_port, max_port = ((struct ip_network_acl_record *) ptr)->max_port; |
881 |
if (io_printf(head, " %u", min_port)) goto print_ip_record_out; |
if (io_printf(head, " %u", min_port)) goto print_ip_record_out; |
882 |
if (min_port != max_port && io_printf(head, "-%u", max_port)) goto print_ip_record_out; |
if (min_port != max_port && io_printf(head, "-%u", max_port)) goto print_ip_record_out; |
883 |
} |
} |
888 |
#endif |
#endif |
889 |
#ifdef CONFIG_TOMOYO_MAC_FOR_SIGNAL |
#ifdef CONFIG_TOMOYO_MAC_FOR_SIGNAL |
890 |
} else if (acl_type == TYPE_SIGNAL_ACL) { |
} else if (acl_type == TYPE_SIGNAL_ACL) { |
891 |
if (io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s", ptr->u.w, ((SIGNAL_ACL_RECORD *) ptr)->domainname->name) || |
if (io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s", ptr->u.w, ((struct signal_acl_record *) ptr)->domainname->name) || |
892 |
DumpCondition(head, ptr->cond)) { |
DumpCondition(head, ptr->cond)) { |
893 |
head->read_avail = pos; break; |
head->read_avail = pos; break; |
894 |
} |
} |
899 |
if (keyword) { |
if (keyword) { |
900 |
if (acltype2paths(acl_type) == 2) { |
if (acltype2paths(acl_type) == 2) { |
901 |
const u8 b0 = ptr->u.b[0], b1 = ptr->u.b[1]; |
const u8 b0 = ptr->u.b[0], b1 = ptr->u.b[1]; |
902 |
if (io_printf(head, "allow_%s %s%s %s%s", keyword, b0 ? "@" : "", b0 ? ((DOUBLE_ACL_RECORD *) ptr)->u1.group1->group_name->name : ((DOUBLE_ACL_RECORD *) ptr)->u1.filename1->name, b1 ? "@" : "", b1 ? ((DOUBLE_ACL_RECORD *) ptr)->u2.group2->group_name->name : ((DOUBLE_ACL_RECORD *) ptr)->u2.filename2->name) |
if (io_printf(head, "allow_%s %s%s %s%s", keyword, b0 ? "@" : "", b0 ? ((struct double_acl_record *) ptr)->u1.group1->group_name->name : ((struct double_acl_record *) ptr)->u1.filename1->name, b1 ? "@" : "", b1 ? ((struct double_acl_record *) ptr)->u2.group2->group_name->name : ((struct double_acl_record *) ptr)->u2.filename2->name) |
903 |
|| DumpCondition(head, ptr->cond)) { |
|| DumpCondition(head, ptr->cond)) { |
904 |
head->read_avail = pos; break; |
head->read_avail = pos; break; |
905 |
} |
} |
906 |
} else { |
} else { |
907 |
const u8 b = ptr->u.b[0]; |
const u8 b = ptr->u.b[0]; |
908 |
if (io_printf(head, "allow_%s %s%s", keyword, b ? "@" : "", b ? ((SINGLE_ACL_RECORD *) ptr)->u.group->group_name->name : ((SINGLE_ACL_RECORD *) ptr)->u.filename->name) |
if (io_printf(head, "allow_%s %s%s", keyword, b ? "@" : "", b ? ((struct single_acl_record *) ptr)->u.group->group_name->name : ((struct single_acl_record *) ptr)->u.filename->name) |
909 |
|| DumpCondition(head, ptr->cond)) { |
|| DumpCondition(head, ptr->cond)) { |
910 |
head->read_avail = pos; break; |
head->read_avail = pos; break; |
911 |
} |
} |
924 |
return 0; |
return 0; |
925 |
} |
} |
926 |
|
|
927 |
static int ReadDomainProfile(IO_BUFFER *head) |
static int ReadDomainProfile(struct io_buffer *head) |
928 |
{ |
{ |
929 |
if (!head->read_eof) { |
if (!head->read_eof) { |
930 |
struct domain_info *domain; |
struct domain_info *domain; |
943 |
return 0; |
return 0; |
944 |
} |
} |
945 |
|
|
946 |
static int WritePID(IO_BUFFER *head) |
static int WritePID(struct io_buffer *head) |
947 |
{ |
{ |
948 |
head->read_step = (int) simple_strtoul(head->write_buf, NULL, 10); |
head->read_step = (int) simple_strtoul(head->write_buf, NULL, 10); |
949 |
head->read_eof = 0; |
head->read_eof = 0; |
950 |
return 0; |
return 0; |
951 |
} |
} |
952 |
|
|
953 |
static int ReadPID(IO_BUFFER *head) |
static int ReadPID(struct io_buffer *head) |
954 |
{ |
{ |
955 |
if (head->read_avail == 0 && !head->read_eof) { |
if (head->read_avail == 0 && !head->read_eof) { |
956 |
const int pid = head->read_step; |
const int pid = head->read_step; |
968 |
return 0; |
return 0; |
969 |
} |
} |
970 |
|
|
971 |
static int UpdateDomainProfile(IO_BUFFER *head) |
static int UpdateDomainProfile(struct io_buffer *head) |
972 |
{ |
{ |
973 |
char *data = head->write_buf; |
char *data = head->write_buf; |
974 |
char *cp = strchr(data, ' '); |
char *cp = strchr(data, ' '); |
990 |
|
|
991 |
#ifdef CONFIG_TOMOYO |
#ifdef CONFIG_TOMOYO |
992 |
|
|
993 |
static int AddExceptionPolicy(IO_BUFFER *head) |
static int AddExceptionPolicy(struct io_buffer *head) |
994 |
{ |
{ |
995 |
char *data = head->write_buf; |
char *data = head->write_buf; |
996 |
int is_delete = 0; |
int is_delete = 0; |
1034 |
return -EINVAL; |
return -EINVAL; |
1035 |
} |
} |
1036 |
|
|
1037 |
static int ReadExceptionPolicy(IO_BUFFER *head) |
static int ReadExceptionPolicy(struct io_buffer *head) |
1038 |
{ |
{ |
1039 |
if (!head->read_eof) { |
if (!head->read_eof) { |
1040 |
switch (head->read_step) { |
switch (head->read_step) { |
1092 |
|
|
1093 |
#ifdef CONFIG_SAKURA |
#ifdef CONFIG_SAKURA |
1094 |
|
|
1095 |
static int AddSystemPolicy(IO_BUFFER *head) |
static int AddSystemPolicy(struct io_buffer *head) |
1096 |
{ |
{ |
1097 |
char *data = head->write_buf; |
char *data = head->write_buf; |
1098 |
int is_delete = 0; |
int is_delete = 0; |
1125 |
return -EINVAL; |
return -EINVAL; |
1126 |
} |
} |
1127 |
|
|
1128 |
static int ReadSystemPolicy(IO_BUFFER *head) |
static int ReadSystemPolicy(struct io_buffer *head) |
1129 |
{ |
{ |
1130 |
if (!head->read_eof) { |
if (!head->read_eof) { |
1131 |
switch (head->read_step) { |
switch (head->read_step) { |
1206 |
} |
} |
1207 |
|
|
1208 |
#ifdef CONFIG_SAKURA |
#ifdef CONFIG_SAKURA |
1209 |
printk("SAKURA: 1.4+ 2007/05/07\n"); |
printk("SAKURA: 1.4+ 2007/05/16\n"); |
1210 |
#endif |
#endif |
1211 |
#ifdef CONFIG_TOMOYO |
#ifdef CONFIG_TOMOYO |
1212 |
printk("TOMOYO: 1.4+ 2007/05/07\n"); |
printk("TOMOYO: 1.4+ 2007/05/16\n"); |
1213 |
#endif |
#endif |
1214 |
if (!profile_loaded) panic("No profiles loaded. Run policy loader using 'init=' option.\n"); |
if (!profile_loaded) panic("No profiles loaded. Run policy loader using 'init=' option.\n"); |
1215 |
printk("Mandatory Access Control activated.\n"); |
printk("Mandatory Access Control activated.\n"); |
1231 |
|
|
1232 |
static spinlock_t query_lock = SPIN_LOCK_UNLOCKED; |
static spinlock_t query_lock = SPIN_LOCK_UNLOCKED; |
1233 |
|
|
1234 |
typedef struct query_entry { |
struct query_entry { |
1235 |
struct list_head list; |
struct list_head list; |
1236 |
char *query; |
char *query; |
1237 |
int query_len; |
int query_len; |
1238 |
unsigned int serial; |
unsigned int serial; |
1239 |
int timer; |
int timer; |
1240 |
int answer; |
int answer; |
1241 |
} QUERY_ENTRY; |
}; |
1242 |
|
|
1243 |
static LIST_HEAD(query_list); |
static LIST_HEAD(query_list); |
1244 |
static atomic_t queryd_watcher = ATOMIC_INIT(0); |
static atomic_t queryd_watcher = ATOMIC_INIT(0); |
1249 |
int error = -EPERM; |
int error = -EPERM; |
1250 |
int pos, len; |
int pos, len; |
1251 |
static unsigned int serial = 0; |
static unsigned int serial = 0; |
1252 |
QUERY_ENTRY *query_entry; |
struct query_entry *query_entry; |
1253 |
if (!CheckCCSFlags(CCS_ALLOW_ENFORCE_GRACE)) return -EPERM; |
if (!CheckCCSFlags(CCS_ALLOW_ENFORCE_GRACE)) return -EPERM; |
1254 |
if (!atomic_read(&queryd_watcher)) return -EPERM; |
if (!atomic_read(&queryd_watcher)) return -EPERM; |
1255 |
va_start(args, fmt); |
va_start(args, fmt); |
1256 |
len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32; |
len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32; |
1257 |
va_end(args); |
va_end(args); |
1258 |
if ((query_entry = (QUERY_ENTRY *) ccs_alloc(sizeof(QUERY_ENTRY))) == NULL || |
if ((query_entry = ccs_alloc(sizeof(*query_entry))) == NULL || |
1259 |
(query_entry->query = ccs_alloc(len)) == NULL) goto out; |
(query_entry->query = ccs_alloc(len)) == NULL) goto out; |
1260 |
INIT_LIST_HEAD(&query_entry->list); |
INIT_LIST_HEAD(&query_entry->list); |
1261 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
1324 |
return 0; |
return 0; |
1325 |
} |
} |
1326 |
|
|
1327 |
static int ReadQuery(IO_BUFFER *head) |
static int ReadQuery(struct io_buffer *head) |
1328 |
{ |
{ |
1329 |
struct list_head *tmp; |
struct list_head *tmp; |
1330 |
int pos = 0, len = 0; |
int pos = 0, len = 0; |
1337 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
1338 |
spin_lock(&query_lock); |
spin_lock(&query_lock); |
1339 |
list_for_each(tmp, &query_list) { |
list_for_each(tmp, &query_list) { |
1340 |
QUERY_ENTRY *ptr = list_entry(tmp, QUERY_ENTRY, list); |
struct query_entry *ptr = list_entry(tmp, struct query_entry, list); |
1341 |
if (pos++ == head->read_step) { |
if (pos++ == head->read_step) { |
1342 |
len = ptr->query_len; |
len = ptr->query_len; |
1343 |
break; |
break; |
1349 |
head->read_step = 0; |
head->read_step = 0; |
1350 |
return 0; |
return 0; |
1351 |
} |
} |
1352 |
if ((buf = (char *) ccs_alloc(len)) != NULL) { |
if ((buf = ccs_alloc(len)) != NULL) { |
1353 |
pos = 0; |
pos = 0; |
1354 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
1355 |
spin_lock(&query_lock); |
spin_lock(&query_lock); |
1356 |
list_for_each(tmp, &query_list) { |
list_for_each(tmp, &query_list) { |
1357 |
QUERY_ENTRY *ptr = list_entry(tmp, QUERY_ENTRY, list); |
struct query_entry *ptr = list_entry(tmp, struct query_entry, list); |
1358 |
if (pos++ == head->read_step) { |
if (pos++ == head->read_step) { |
1359 |
/* Some query can be skiipped since query_list can change, but I don't care. */ |
/* Some query can be skiipped since query_list can change, but I don't care. */ |
1360 |
if (len == ptr->query_len) memmove(buf, ptr->query, len); |
if (len == ptr->query_len) memmove(buf, ptr->query, len); |
1374 |
return 0; |
return 0; |
1375 |
} |
} |
1376 |
|
|
1377 |
static int WriteAnswer(IO_BUFFER *head) |
static int WriteAnswer(struct io_buffer *head) |
1378 |
{ |
{ |
1379 |
char *data = head->write_buf; |
char *data = head->write_buf; |
1380 |
struct list_head *tmp; |
struct list_head *tmp; |
1382 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
1383 |
spin_lock(&query_lock); |
spin_lock(&query_lock); |
1384 |
list_for_each(tmp, &query_list) { |
list_for_each(tmp, &query_list) { |
1385 |
QUERY_ENTRY *ptr = list_entry(tmp, QUERY_ENTRY, list); |
struct query_entry *ptr = list_entry(tmp, struct query_entry, list); |
1386 |
ptr->timer = 0; |
ptr->timer = 0; |
1387 |
} |
} |
1388 |
spin_unlock(&query_lock); |
spin_unlock(&query_lock); |
1391 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
1392 |
spin_lock(&query_lock); |
spin_lock(&query_lock); |
1393 |
list_for_each(tmp, &query_list) { |
list_for_each(tmp, &query_list) { |
1394 |
QUERY_ENTRY *ptr = list_entry(tmp, QUERY_ENTRY, list); |
struct query_entry *ptr = list_entry(tmp, struct query_entry, list); |
1395 |
if (ptr->serial != serial) continue; |
if (ptr->serial != serial) continue; |
1396 |
if (!ptr->answer) ptr->answer = answer; |
if (!ptr->answer) ptr->answer = answer; |
1397 |
break; |
break; |
1416 |
/***** CRITICAL SECTION END *****/ |
/***** CRITICAL SECTION END *****/ |
1417 |
} |
} |
1418 |
|
|
1419 |
static int ReadUpdatesCounter(IO_BUFFER *head) |
static int ReadUpdatesCounter(struct io_buffer *head) |
1420 |
{ |
{ |
1421 |
if (!head->read_eof) { |
if (!head->read_eof) { |
1422 |
unsigned int counter[MAX_CCS_UPDATES_COUNTER]; |
unsigned int counter[MAX_CCS_UPDATES_COUNTER]; |
1448 |
return 0; |
return 0; |
1449 |
} |
} |
1450 |
|
|
1451 |
static int ReadMemoryCounter(IO_BUFFER *head) |
static int ReadMemoryCounter(struct io_buffer *head) |
1452 |
{ |
{ |
1453 |
if (!head->read_eof) { |
if (!head->read_eof) { |
1454 |
const int shared = GetMemoryUsedForSaveName(), private = GetMemoryUsedForElements(), dynamic = GetMemoryUsedForDynamic(); |
const int shared = GetMemoryUsedForSaveName(), private = GetMemoryUsedForElements(), dynamic = GetMemoryUsedForDynamic(); |
1459 |
|
|
1460 |
int CCS_OpenControl(const int type, struct file *file) |
int CCS_OpenControl(const int type, struct file *file) |
1461 |
{ |
{ |
1462 |
IO_BUFFER *head = (IO_BUFFER *) ccs_alloc(sizeof(IO_BUFFER)); |
struct io_buffer *head = ccs_alloc(sizeof(*head)); |
1463 |
if (!head) return -ENOMEM; |
if (!head) return -ENOMEM; |
1464 |
init_MUTEX(&head->read_sem); |
init_MUTEX(&head->read_sem); |
1465 |
init_MUTEX(&head->write_sem); |
init_MUTEX(&head->write_sem); |
1549 |
return 0; |
return 0; |
1550 |
} |
} |
1551 |
|
|
1552 |
static int CopyToUser(IO_BUFFER *head, char __user * buffer, int buffer_len) |
static int CopyToUser(struct io_buffer *head, char __user * buffer, int buffer_len) |
1553 |
{ |
{ |
1554 |
int len = head->read_avail; |
int len = head->read_avail; |
1555 |
char *cp = head->read_buf; |
char *cp = head->read_buf; |
1564 |
|
|
1565 |
int CCS_PollControl(struct file *file, poll_table *wait) |
int CCS_PollControl(struct file *file, poll_table *wait) |
1566 |
{ |
{ |
1567 |
IO_BUFFER *head = (IO_BUFFER *) file->private_data; |
struct io_buffer *head = file->private_data; |
1568 |
if (!head->poll) return -ENOSYS; |
if (!head->poll) return -ENOSYS; |
1569 |
return head->poll(file, wait); |
return head->poll(file, wait); |
1570 |
} |
} |
1572 |
int CCS_ReadControl(struct file *file, char __user *buffer, const int buffer_len) |
int CCS_ReadControl(struct file *file, char __user *buffer, const int buffer_len) |
1573 |
{ |
{ |
1574 |
int len = 0; |
int len = 0; |
1575 |
IO_BUFFER *head = (IO_BUFFER *) file->private_data; |
struct io_buffer *head = file->private_data; |
1576 |
if (!head->read) return -ENOSYS; |
if (!head->read) return -ENOSYS; |
1577 |
if (!access_ok(VERIFY_WRITE, buffer, buffer_len)) return -EFAULT; |
if (!access_ok(VERIFY_WRITE, buffer, buffer_len)) return -EFAULT; |
1578 |
if (down_interruptible(&head->read_sem)) return -EINTR; |
if (down_interruptible(&head->read_sem)) return -EINTR; |
1584 |
|
|
1585 |
int CCS_WriteControl(struct file *file, const char __user *buffer, const int buffer_len) |
int CCS_WriteControl(struct file *file, const char __user *buffer, const int buffer_len) |
1586 |
{ |
{ |
1587 |
IO_BUFFER *head = (IO_BUFFER *) file->private_data; |
struct io_buffer *head = file->private_data; |
1588 |
int error = buffer_len; |
int error = buffer_len; |
1589 |
int avail_len = buffer_len; |
int avail_len = buffer_len; |
1590 |
char *cp0 = head->write_buf; |
char *cp0 = head->write_buf; |
1619 |
|
|
1620 |
int CCS_CloseControl(struct file *file) |
int CCS_CloseControl(struct file *file) |
1621 |
{ |
{ |
1622 |
IO_BUFFER *head = file->private_data; |
struct io_buffer *head = file->private_data; |
1623 |
if (head->write == WriteAnswer) atomic_dec(&queryd_watcher); |
if (head->write == WriteAnswer) atomic_dec(&queryd_watcher); |
1624 |
ccs_free(head->read_buf); head->read_buf = NULL; |
ccs_free(head->read_buf); head->read_buf = NULL; |
1625 |
ccs_free(head->write_buf); head->write_buf = NULL; |
ccs_free(head->write_buf); head->write_buf = NULL; |