オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /branches/ccs-patch/fs/tomoyo_capability.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2763 - (show annotations) (download) (as text)
Tue Jul 14 06:43:53 2009 UTC (14 years, 10 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 7630 byte(s)


1 /*
2 * fs/tomoyo_capability.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 1.7.0-pre 2009/07/03
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
15 #include <linux/ccs_common.h>
16 #include <linux/tomoyo.h>
17
18 /**
19 * ccs_cap2name - Convert capability operation to capability message.
20 *
21 * @operation: Type of operation.
22 *
23 * Returns the name of capability.
24 */
25 static const char *ccs_cap2name(const u8 operation)
26 {
27 static const char *ccs_capability_name[CCS_MAX_CAPABILITY_INDEX] = {
28 [CCS_INET_STREAM_SOCKET_CREATE] =
29 "socket(PF_INET, SOCK_STREAM)",
30 [CCS_INET_STREAM_SOCKET_LISTEN] =
31 "listen(PF_INET, SOCK_STREAM)",
32 [CCS_INET_STREAM_SOCKET_CONNECT] =
33 "connect(PF_INET, SOCK_STREAM)",
34 [CCS_USE_INET_DGRAM_SOCKET] =
35 "socket(PF_INET, SOCK_DGRAM)",
36 [CCS_USE_INET_RAW_SOCKET] =
37 "socket(PF_INET, SOCK_RAW)",
38 [CCS_USE_ROUTE_SOCKET] = "socket(PF_ROUTE)",
39 [CCS_USE_PACKET_SOCKET] = "socket(PF_PACKET)",
40 [CCS_SYS_MOUNT] = "sys_mount()",
41 [CCS_SYS_UMOUNT] = "sys_umount()",
42 [CCS_SYS_REBOOT] = "sys_reboot()",
43 [CCS_SYS_CHROOT] = "sys_chroot()",
44 [CCS_SYS_KILL] = "sys_kill()",
45 [CCS_SYS_VHANGUP] = "sys_vhangup()",
46 [CCS_SYS_SETTIME] = "sys_settimeofday()",
47 [CCS_SYS_NICE] = "sys_nice()",
48 [CCS_SYS_SETHOSTNAME] = "sys_sethostname()",
49 [CCS_USE_KERNEL_MODULE] = "kernel_module",
50 [CCS_CREATE_FIFO] = "mknod(FIFO)",
51 [CCS_CREATE_BLOCK_DEV] = "mknod(BDEV)",
52 [CCS_CREATE_CHAR_DEV] = "mknod(CDEV)",
53 [CCS_CREATE_UNIX_SOCKET] = "mknod(SOCKET)",
54 [CCS_SYS_LINK] = "sys_link()",
55 [CCS_SYS_SYMLINK] = "sys_symlink()",
56 [CCS_SYS_RENAME] = "sys_rename()",
57 [CCS_SYS_UNLINK] = "sys_unlink()",
58 [CCS_SYS_CHMOD] = "sys_chmod()",
59 [CCS_SYS_CHOWN] = "sys_chown()",
60 [CCS_SYS_IOCTL] = "sys_ioctl()",
61 [CCS_SYS_KEXEC_LOAD] = "sys_kexec_load()",
62 [CCS_SYS_PIVOT_ROOT] = "sys_pivot_root()",
63 [CCS_SYS_PTRACE] = "sys_ptrace()",
64 [CCS_CONCEAL_MOUNT] = "conceal-mount",
65 };
66 if (operation < CCS_MAX_CAPABILITY_INDEX)
67 return ccs_capability_name[operation];
68 return NULL;
69 }
70
71 /**
72 * ccs_audit_capability_log - Audit capability log.
73 *
74 * @r: Pointer to "struct ccs_request_info".
75 * @operation: Type of operation.
76 * @is_granted: True if this is a granted log.
77 *
78 * Returns 0 on success, negative value otherwise.
79 */
80 static int ccs_audit_capability_log(struct ccs_request_info *r,
81 const u8 operation, const bool is_granted)
82 {
83 return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_CAPABILITY
84 "%s\n", ccs_cap2keyword(operation));
85 }
86
87 /**
88 * ccs_update_capability_acl - Update "struct ccs_capability_acl_record" list.
89 *
90 * @operation: Type of operation.
91 * @domain: Pointer to "struct ccs_domain_info".
92 * @condition: Pointer to "struct ccs_condition". May be NULL.
93 * @is_delete: True if it is a delete request.
94 *
95 * Returns 0 on success, negative value otherwise.
96 */
97 static int ccs_update_capability_acl(const u8 operation,
98 struct ccs_domain_info *domain,
99 struct ccs_condition *condition,
100 const bool is_delete)
101 {
102 struct ccs_capability_acl_record *entry = NULL;
103 struct ccs_acl_info *ptr;
104 int error = is_delete ? -ENOENT : -ENOMEM;
105 if (!domain)
106 return -EINVAL;
107 if (is_delete)
108 goto delete;
109 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
110 mutex_lock(&ccs_policy_lock);
111 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
112 struct ccs_capability_acl_record *acl;
113 if (ccs_acl_type1(ptr) != TYPE_CAPABILITY_ACL)
114 continue;
115 if (ptr->cond != condition)
116 continue;
117 acl = container_of(ptr, struct ccs_capability_acl_record, head);
118 if (acl->operation != operation)
119 continue;
120 error = ccs_add_domain_acl(NULL, ptr);
121 break;
122 }
123 if (error && ccs_memory_ok(entry, sizeof(*entry))) {
124 entry->head.type = TYPE_CAPABILITY_ACL;
125 entry->head.cond = condition;
126 entry->operation = operation;
127 error = ccs_add_domain_acl(domain, &entry->head);
128 entry = NULL;
129 }
130 mutex_unlock(&ccs_policy_lock);
131 goto out;
132 delete:
133 mutex_lock(&ccs_policy_lock);
134 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
135 struct ccs_capability_acl_record *acl;
136 if (ccs_acl_type2(ptr) != TYPE_CAPABILITY_ACL)
137 continue;
138 if (ptr->cond != condition)
139 continue;
140 acl = container_of(ptr, struct ccs_capability_acl_record, head);
141 if (acl->operation != operation)
142 continue;
143 error = ccs_del_domain_acl(ptr);
144 break;
145 }
146 mutex_unlock(&ccs_policy_lock);
147 out:
148 kfree(entry);
149 return error;
150 }
151
152 /**
153 * ccs_capable - Check permission for capability.
154 *
155 * @operation: Type of operation.
156 *
157 * Returns true on success, false otherwise.
158 *
159 * Caller holds srcu_read_lock(&ccs_ss).
160 */
161 static bool ccs_capable2(const u8 operation)
162 {
163 struct ccs_request_info r;
164 struct ccs_acl_info *ptr;
165 bool is_enforce;
166 bool found = false;
167 if (!ccs_can_sleep())
168 return true;
169 ccs_init_request_info(&r, NULL, CCS_MAX_CONTROL_INDEX + operation);
170 is_enforce = (r.mode == 3);
171 if (!r.mode)
172 return true;
173 retry:
174 list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) {
175 struct ccs_capability_acl_record *acl;
176 if (ccs_acl_type2(ptr) != TYPE_CAPABILITY_ACL)
177 continue;
178 acl = container_of(ptr, struct ccs_capability_acl_record, head);
179 if (acl->operation != operation ||
180 !ccs_check_condition(&r, ptr))
181 continue;
182 r.cond = ptr->cond;
183 found = true;
184 break;
185 }
186 ccs_audit_capability_log(&r, operation, found);
187 if (found)
188 return true;
189 if (ccs_verbose_mode(r.domain))
190 printk(KERN_WARNING "TOMOYO-%s: %s denied for %s\n",
191 ccs_get_msg(is_enforce), ccs_cap2name(operation),
192 ccs_get_last_name(r.domain));
193 if (is_enforce) {
194 int error = ccs_check_supervisor(&r, KEYWORD_ALLOW_CAPABILITY
195 "%s\n",
196 ccs_cap2keyword(operation));
197 if (error == 1)
198 goto retry;
199 return !error;
200 }
201 if (r.mode == 1 && ccs_domain_quota_ok(r.domain)) {
202 struct ccs_condition *cond = ccs_handler_cond();
203 ccs_update_capability_acl(operation, r.domain, cond, false);
204 ccs_put_condition(cond);
205 }
206 return true;
207 }
208
209 /**
210 * ccs_capable - Check permission for capability.
211 *
212 * @operation: Type of operation.
213 *
214 * Returns true on success, false otherwise.
215 *
216 * Caller holds srcu_read_lock(&ccs_ss).
217 */
218 bool ccs_capable(const u8 operation)
219 {
220 const int idx = srcu_read_lock(&ccs_ss);
221 const int error = ccs_capable2(operation);
222 srcu_read_unlock(&ccs_ss, idx);
223 return error;
224 }
225 EXPORT_SYMBOL(ccs_capable); /* for net/unix/af_unix.c */
226
227 /**
228 * ccs_write_capability_policy - Write "struct ccs_capability_acl_record" list.
229 *
230 * @data: String to parse.
231 * @domain: Pointer to "struct ccs_domain_info".
232 * @condition: Pointer to "struct ccs_condition". May be NULL.
233 * @is_delete: True if it is a delete request.
234 *
235 * Returns 0 on success, negative value otherwise.
236 */
237 int ccs_write_capability_policy(char *data, struct ccs_domain_info *domain,
238 struct ccs_condition *condition,
239 const bool is_delete)
240 {
241 u8 capability;
242 for (capability = 0; capability < CCS_MAX_CAPABILITY_INDEX;
243 capability++) {
244 if (strcmp(data, ccs_cap2keyword(capability)))
245 continue;
246 return ccs_update_capability_acl(capability, domain, condition,
247 is_delete);
248 }
249 return -EINVAL;
250 }

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