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 893 - (show annotations) (download) (as text)
Tue Jan 15 01:30:33 2008 UTC (16 years, 4 months ago) by kumaneko
Original Path: trunk/1.5.x/ccs-patch/fs/tomoyo_capability.c
File MIME type: text/x-csrc
File size: 10351 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.5.3-pre 2008/01/15
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) 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 struct capability_acl_record_with_condition *p;
159 int error = -ENOMEM;
160 if (!domain) return -EINVAL;
161 mutex_lock(&domain_acl_lock);
162 if (!is_delete) {
163 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
164 switch (ptr->type) {
165 case TYPE_CAPABILITY_ACL:
166 if (condition) continue;
167 acl = container_of(ptr, struct capability_acl_record, head);
168 break;
169 case TYPE_CAPABILITY_ACL_WITH_CONDITION:
170 p = container_of(ptr, struct capability_acl_record_with_condition, record.head);
171 if (p->condition != condition) continue;
172 acl = &p->record;
173 break;
174 default:
175 continue;
176 }
177 if (acl->operation != operation) continue;
178 acl->is_deleted = 0;
179 /* Found. Nothing to do. */
180 error = 0;
181 goto out;
182 }
183 /* Not found. Append it to the tail. */
184 if (condition) {
185 if ((p = alloc_element(sizeof(*p))) == NULL) goto out;
186 acl = &p->record;
187 p->condition = condition;
188 acl->head.type = TYPE_CAPABILITY_ACL_WITH_CONDITION;
189 } else {
190 if ((acl = alloc_element(sizeof(*acl))) == NULL) goto out;
191 acl->head.type = TYPE_CAPABILITY_ACL;
192 }
193 acl->operation = operation;
194 error = AddDomainACL(domain, &acl->head);
195 } else {
196 error = -ENOENT;
197 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
198 switch (ptr->type) {
199 case TYPE_CAPABILITY_ACL:
200 if (condition) continue;
201 acl = container_of(ptr, struct capability_acl_record, head);
202 break;
203 case TYPE_CAPABILITY_ACL_WITH_CONDITION:
204 p = container_of(ptr, struct capability_acl_record_with_condition, record.head);
205 if (p->condition != condition) continue;
206 acl = &p->record;
207 break;
208 default:
209 continue;
210 }
211 if (acl->is_deleted || acl->operation != operation) continue;
212 acl->is_deleted = 1;
213 error = DelDomainACL();
214 break;
215 }
216 }
217 out: ;
218 mutex_unlock(&domain_acl_lock);
219 return error;
220 }
221
222 int CheckCapabilityACL(const u8 operation)
223 {
224 struct domain_info * const domain = current->domain_info;
225 struct acl_info *ptr;
226 const u8 profile = current->domain_info->profile;
227 const u8 mode = CheckCapabilityFlags(operation);
228 const bool is_enforce = (mode == 3);
229 bool found = 0;
230 if (!mode) return 0;
231 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
232 struct capability_acl_record *acl;
233 struct capability_acl_record_with_condition *p;
234 const struct condition_list *cond;
235 switch (ptr->type) {
236 default:
237 continue;
238 case TYPE_CAPABILITY_ACL:
239 acl = container_of(ptr, struct capability_acl_record, head);
240 cond = NULL;
241 break;
242 case TYPE_CAPABILITY_ACL_WITH_CONDITION:
243 p = container_of(ptr, struct capability_acl_record_with_condition, record.head);
244 acl = &p->record;
245 cond = p->condition;
246 break;
247 }
248 if (acl->is_deleted || acl->operation != operation || !CheckCondition(cond, NULL)) continue;
249 found = 1;
250 break;
251 }
252 AuditCapabilityLog(operation, found, profile, mode);
253 if (found) return 0;
254 if (TomoyoVerboseMode()) {
255 printk("TOMOYO-%s: %s denied for %s\n", GetMSG(is_enforce), cap_operation2name(operation), GetLastName(domain));
256 }
257 if (is_enforce) return CheckSupervisor("%s\n" KEYWORD_ALLOW_CAPABILITY "%s\n", domain->domainname->name, cap_operation2keyword(operation));
258 else if (mode == 1 && CheckDomainQuota(domain)) AddCapabilityACL(operation, domain, NULL, 0);
259 return 0;
260 }
261 EXPORT_SYMBOL(CheckCapabilityACL);
262
263 int AddCapabilityPolicy(char *data, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)
264 {
265 u8 capability;
266 for (capability = 0; capability < TOMOYO_MAX_CAPABILITY_INDEX; capability++) {
267 if (strcmp(data, capability_control_array[capability].keyword) == 0) {
268 return AddCapabilityACL(capability, domain, condition, is_delete);
269 }
270 }
271 return -EINVAL;
272 }
273
274 /***** TOMOYO Linux end. *****/

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