Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

Contents of /trunk/1.6.x/ccs-patch/fs/tomoyo_capability.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 994 - (show annotations) (download) (as text)
Mon Feb 18 08:36:51 2008 UTC (16 years, 3 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 9328 byte(s)


1 /*
2 * fs/tomoyo_capability.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2008 NTT DATA CORPORATION
7 *
8 * Version: 1.6.0-pre 2008/02/18
9 *
10 * This file is applicable to both 2.4.30 and 2.6.11 and later.
11 * See README.ccs for ChangeLog.
12 *
13 */
14 /***** TOMOYO Linux start. *****/
15
16 #include <linux/ccs_common.h>
17 #include <linux/tomoyo.h>
18 #include <linux/realpath.h>
19
20 /************************* VARIABLES *************************/
21
22 extern struct mutex domain_acl_lock;
23 extern bool sbin_init_started;
24
25 static struct {
26 const char *keyword;
27 u8 current_value;
28 const char *capability_name;
29 } capability_control_array[TOMOYO_MAX_CAPABILITY_INDEX] = { /* domain_policy.conf */
30 [TOMOYO_INET_STREAM_SOCKET_CREATE] = { "inet_tcp_create", 0, "socket(PF_INET, SOCK_STREAM)" },
31 [TOMOYO_INET_STREAM_SOCKET_LISTEN] = { "inet_tcp_listen", 0, "listen(PF_INET, SOCK_STREAM)" },
32 [TOMOYO_INET_STREAM_SOCKET_CONNECT] = { "inet_tcp_connect", 0, "connect(PF_INET, SOCK_STREAM)" },
33 [TOMOYO_USE_INET_DGRAM_SOCKET] = { "use_inet_udp", 0, "socket(PF_INET, SOCK_DGRAM)" },
34 [TOMOYO_USE_INET_RAW_SOCKET] = { "use_inet_ip", 0, "socket(PF_INET, SOCK_RAW)" },
35 [TOMOYO_USE_ROUTE_SOCKET] = { "use_route", 0, "socket(PF_ROUTE)" },
36 [TOMOYO_USE_PACKET_SOCKET] = { "use_packet", 0, "socket(PF_PACKET)" },
37 [TOMOYO_SYS_MOUNT] = { "SYS_MOUNT", 0, "sys_mount()" },
38 [TOMOYO_SYS_UMOUNT] = { "SYS_UMOUNT", 0, "sys_umount()" },
39 [TOMOYO_SYS_REBOOT] = { "SYS_REBOOT", 0, "sys_reboot()" },
40 [TOMOYO_SYS_CHROOT] = { "SYS_CHROOT", 0, "sys_chroot()" },
41 [TOMOYO_SYS_KILL] = { "SYS_KILL", 0, "sys_kill()" },
42 [TOMOYO_SYS_VHANGUP] = { "SYS_VHANGUP", 0, "sys_vhangup()" },
43 [TOMOYO_SYS_SETTIME] = { "SYS_TIME", 0, "sys_settimeofday()" },
44 [TOMOYO_SYS_NICE] = { "SYS_NICE", 0, "sys_nice()" },
45 [TOMOYO_SYS_SETHOSTNAME] = { "SYS_SETHOSTNAME", 0, "sys_sethostname()" },
46 [TOMOYO_USE_KERNEL_MODULE] = { "use_kernel_module", 0, "kernel_module" },
47 [TOMOYO_CREATE_FIFO] = { "create_fifo", 0, "mknod(FIFO)" },
48 [TOMOYO_CREATE_BLOCK_DEV] = { "create_block_dev", 0, "mknod(BDEV)" },
49 [TOMOYO_CREATE_CHAR_DEV] = { "create_char_dev", 0, "mknod(CDEV)" },
50 [TOMOYO_CREATE_UNIX_SOCKET] = { "create_unix_socket", 0, "mknod(SOCKET)" },
51 [TOMOYO_SYS_LINK] = { "SYS_LINK", 0, "sys_link()" },
52 [TOMOYO_SYS_SYMLINK] = { "SYS_SYMLINK", 0, "sys_symlink()" },
53 [TOMOYO_SYS_RENAME] = { "SYS_RENAME", 0, "sys_rename()" },
54 [TOMOYO_SYS_UNLINK] = { "SYS_UNLINK", 0, "sys_unlink()" },
55 [TOMOYO_SYS_CHMOD] = { "SYS_CHMOD", 0, "sys_chmod()" },
56 [TOMOYO_SYS_CHOWN] = { "SYS_CHOWN", 0, "sys_chown()" },
57 [TOMOYO_SYS_IOCTL] = { "SYS_IOCTL", 0, "sys_ioctl()" },
58 [TOMOYO_SYS_KEXEC_LOAD] = { "SYS_KEXEC_LOAD", 0, "sys_kexec_load()" },
59 [TOMOYO_SYS_PIVOT_ROOT] = { "SYS_PIVOT_ROOT", 0, "sys_pivot_root()" },
60 [TOMOYO_SYS_PTRACE] = { "SYS_PTRACE", 0, "sys_ptrace()" },
61 };
62
63 struct profile {
64 unsigned char value[TOMOYO_MAX_CAPABILITY_INDEX];
65 };
66
67 static struct profile *profile_ptr[MAX_PROFILES];
68
69 /************************* UTILITY FUNCTIONS *************************/
70
71 const char *cap_operation2keyword(const u8 operation)
72 {
73 return operation < TOMOYO_MAX_CAPABILITY_INDEX ? capability_control_array[operation].keyword : NULL;
74 }
75
76 static const char *cap_operation2name(const u8 operation)
77 {
78 return operation < TOMOYO_MAX_CAPABILITY_INDEX ? capability_control_array[operation].capability_name : NULL;
79 }
80
81 /* Check whether the given capability control is enabled. */
82 static u8 CheckCapabilityFlags(const u8 index)
83 {
84 const u8 profile = current->domain_info->profile;
85 return sbin_init_started && index < TOMOYO_MAX_CAPABILITY_INDEX
86 #if MAX_PROFILES != 256
87 && profile < MAX_PROFILES
88 #endif
89 && profile_ptr[profile] ? profile_ptr[profile]->value[index] : 0;
90 }
91
92 static struct profile *FindOrAssignNewProfile(const u8 profile)
93 {
94 static DEFINE_MUTEX(profile_lock);
95 struct profile *ptr = NULL;
96 mutex_lock(&profile_lock);
97 if (
98 #if MAX_PROFILES != 256
99 profile < MAX_PROFILES &&
100 #endif
101 (ptr = profile_ptr[profile]) == NULL) {
102 if ((ptr = alloc_element(sizeof(*ptr))) != NULL) {
103 u8 i;
104 for (i = 0; i < TOMOYO_MAX_CAPABILITY_INDEX; i++) ptr->value[i] = capability_control_array[i].current_value;
105 mb(); /* Avoid out-of-order execution. */
106 profile_ptr[profile] = ptr;
107 }
108 }
109 mutex_unlock(&profile_lock);
110 return ptr;
111 }
112
113 int SetCapabilityStatus(const char *data, u8 value, const u8 profile)
114 {
115 u8 i;
116 struct profile *ptr = FindOrAssignNewProfile(profile);
117 if (!ptr) return -EINVAL;
118 for (i = 0; i < TOMOYO_MAX_CAPABILITY_INDEX; i++) {
119 if (strcmp(data, capability_control_array[i].keyword)) continue;
120 if (value > 3) value = 3;
121 ptr->value[i] = value;
122 return 0;
123 }
124 return -EINVAL;
125 }
126
127 int ReadCapabilityStatus(struct io_buffer *head)
128 {
129 int step;
130 for (step = head->read_step; step < MAX_PROFILES * TOMOYO_MAX_CAPABILITY_INDEX; step++) {
131 const int i = step / TOMOYO_MAX_CAPABILITY_INDEX, j = step % TOMOYO_MAX_CAPABILITY_INDEX;
132 const struct profile *profile = profile_ptr[i];
133 head->read_step = step;
134 if (!profile) continue;
135 if (io_printf(head, "%u-" KEYWORD_MAC_FOR_CAPABILITY "%s=%u\n", i, capability_control_array[j].keyword, profile->value[j])) break;
136 }
137 return step < MAX_PROFILES * TOMOYO_MAX_CAPABILITY_INDEX ? -ENOMEM : 0;
138 }
139
140 /************************* AUDIT FUNCTIONS *************************/
141
142 static int AuditCapabilityLog(const u8 operation, const bool is_granted, const u8 profile, const u8 mode)
143 {
144 char *buf;
145 int len = 64;
146 if (CanSaveAuditLog(is_granted) < 0) return -ENOMEM;
147 if ((buf = InitAuditLog(&len, profile, mode, NULL)) == NULL) return -ENOMEM;
148 snprintf(buf + strlen(buf), len - strlen(buf) - 1, KEYWORD_ALLOW_CAPABILITY "%s\n", cap_operation2keyword(operation));
149 return WriteAuditLog(buf, is_granted);
150 }
151
152 /************************* CAPABILITY ACL HANDLER *************************/
153
154 static int AddCapabilityACL(const u8 operation, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)
155 {
156 struct acl_info *ptr;
157 struct capability_acl_record *acl;
158 int error = -ENOMEM;
159 if (!domain) return -EINVAL;
160 mutex_lock(&domain_acl_lock);
161 if (!is_delete) {
162 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
163 if ((ptr->type & ~(ACL_DELETED | ACL_WITH_CONDITION)) != TYPE_CAPABILITY_ACL) continue;
164 if (GetConditionPart(ptr) != condition) continue;
165 acl = container_of(ptr, struct capability_acl_record, head);
166 if (acl->operation != operation) continue;
167 error = AddDomainACL(NULL, ptr);
168 goto out;
169 }
170 /* Not found. Append it to the tail. */
171 if ((acl = alloc_acl_element(TYPE_CAPABILITY_ACL, condition)) == NULL) goto out;
172 acl->operation = operation;
173 error = AddDomainACL(domain, &acl->head);
174 } else {
175 error = -ENOENT;
176 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
177 if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_CAPABILITY_ACL) continue;
178 if (GetConditionPart(ptr) != condition) continue;
179 acl = container_of(ptr, struct capability_acl_record, head);
180 if (acl->operation != operation) continue;
181 error = DelDomainACL(ptr);
182 break;
183 }
184 }
185 out: ;
186 mutex_unlock(&domain_acl_lock);
187 return error;
188 }
189
190 int CheckCapabilityACL(const u8 operation)
191 {
192 struct domain_info * const domain = current->domain_info;
193 struct acl_info *ptr;
194 const u8 profile = current->domain_info->profile;
195 const u8 mode = CheckCapabilityFlags(operation);
196 const bool is_enforce = (mode == 3);
197 bool found = 0;
198 if (!mode) return 0;
199 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
200 struct capability_acl_record *acl;
201 if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_CAPABILITY_ACL) continue;
202 acl = container_of(ptr, struct capability_acl_record, head);
203 if (acl->operation != operation || !CheckCondition(ptr, NULL)) continue;
204 UpdateCondition(ptr);
205 found = 1;
206 break;
207 }
208 AuditCapabilityLog(operation, found, profile, mode);
209 if (found) return 0;
210 if (TomoyoVerboseMode()) {
211 printk("TOMOYO-%s: %s denied for %s\n", GetMSG(is_enforce), cap_operation2name(operation), GetLastName(domain));
212 }
213 if (is_enforce) return CheckSupervisor("%s\n" KEYWORD_ALLOW_CAPABILITY "%s\n", domain->domainname->name, cap_operation2keyword(operation));
214 else if (mode == 1 && CheckDomainQuota(domain)) AddCapabilityACL(operation, domain, NULL, 0);
215 return 0;
216 }
217 EXPORT_SYMBOL(CheckCapabilityACL);
218
219 int AddCapabilityPolicy(char *data, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)
220 {
221 u8 capability;
222 for (capability = 0; capability < TOMOYO_MAX_CAPABILITY_INDEX; capability++) {
223 if (strcmp(data, capability_control_array[capability].keyword) == 0) {
224 return AddCapabilityACL(capability, domain, condition, is_delete);
225 }
226 }
227 return -EINVAL;
228 }
229
230 /***** TOMOYO Linux end. *****/

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26