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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1561 - (show annotations) (download) (as text)
Tue Sep 9 04:29:07 2008 UTC (15 years, 8 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 6789 byte(s)
Add "try again" response to "delayed enforcing" mode.
1 /*
2 * fs/tomoyo_signal.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.5-pre 2008/09/09
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 #include <linux/realpath.h>
18 #include <linux/version.h>
19
20 /* To support PID namespace. */
21 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
22 #define find_task_by_pid find_task_by_vpid
23 #endif
24
25 /**
26 * audit_signal_log - Audit signal log.
27 *
28 * @signal: Signal number.
29 * @dest_domain: Destination domainname.
30 * @is_granted: True if this is a granted log.
31 * @profile: Profile number used.
32 * @mode: Access control mode used.
33 *
34 * Returns 0 on success, negative value otherwise.
35 */
36 static int audit_signal_log(const int signal,
37 const struct path_info *dest_domain,
38 const bool is_granted, const u8 profile,
39 const u8 mode)
40 {
41 char *buf;
42 int len;
43 int len2;
44 if (ccs_can_save_audit_log(is_granted) < 0)
45 return -ENOMEM;
46 len = dest_domain->total_len + 64;
47 buf = ccs_init_audit_log(&len, profile, mode, NULL);
48 if (!buf)
49 return -ENOMEM;
50 len2 = strlen(buf);
51 snprintf(buf + len2, len - len2 - 1, KEYWORD_ALLOW_SIGNAL "%d %s\n",
52 signal, dest_domain->name);
53 return ccs_write_audit_log(buf, is_granted);
54 }
55
56 /**
57 * update_signal_acl - Update "struct signal_acl_record" list.
58 *
59 * @sig: Signal number.
60 * @dest_pattern: Destination domainname.
61 * @domain: Pointer to "struct domain_info".
62 * @condition: Pointer to "struct condition_list". May be NULL.
63 * @is_delete: True if it is a delete request.
64 *
65 * Returns 0 on success, negative value otherwise.
66 */
67 static int update_signal_acl(const int sig, const char *dest_pattern,
68 struct domain_info *domain,
69 const struct condition_list *condition,
70 const bool is_delete)
71 {
72 struct acl_info *ptr;
73 struct signal_acl_record *acl;
74 const struct path_info *saved_dest_pattern;
75 const u16 hash = sig;
76 int error = -ENOMEM;
77 if (!domain)
78 return -EINVAL;
79 if (!dest_pattern || !ccs_is_correct_domain(dest_pattern, __func__))
80 return -EINVAL;
81 saved_dest_pattern = ccs_save_name(dest_pattern);
82 if (!saved_dest_pattern)
83 return -ENOMEM;
84 mutex_lock(&domain_acl_lock);
85 if (is_delete)
86 goto delete;
87 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
88 if (ccs_acl_type1(ptr) != TYPE_SIGNAL_ACL)
89 continue;
90 if (ccs_get_condition_part(ptr) != condition)
91 continue;
92 acl = container_of(ptr, struct signal_acl_record, head);
93 if (acl->sig != hash ||
94 ccs_pathcmp(acl->domainname, saved_dest_pattern))
95 continue;
96 error = ccs_add_domain_acl(NULL, ptr);
97 goto out;
98 }
99 /* Not found. Append it to the tail. */
100 acl = ccs_alloc_acl_element(TYPE_SIGNAL_ACL, condition);
101 if (!acl)
102 goto out;
103 acl->sig = hash;
104 acl->domainname = saved_dest_pattern;
105 error = ccs_add_domain_acl(domain, &acl->head);
106 goto out;
107 delete:
108 error = -ENOENT;
109 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
110 if (ccs_acl_type2(ptr) != TYPE_SIGNAL_ACL)
111 continue;
112 if (ccs_get_condition_part(ptr) != condition)
113 continue;
114 acl = container_of(ptr, struct signal_acl_record, head);
115 if (acl->sig != hash ||
116 ccs_pathcmp(acl->domainname, saved_dest_pattern))
117 continue;
118 error = ccs_del_domain_acl(ptr);
119 break;
120 }
121 out:
122 mutex_unlock(&domain_acl_lock);
123 return error;
124 }
125
126 /**
127 * ccs_check_signal_acl - Check permission for signal.
128 *
129 * @sig: Signal number.
130 * @pid: Target's PID.
131 *
132 * Returns 0 on success, negative value otherwise.
133 */
134 int ccs_check_signal_acl(const int sig, const int pid)
135 {
136 struct domain_info *domain = current->domain_info;
137 struct domain_info *dest = NULL;
138 const char *dest_pattern;
139 struct acl_info *ptr;
140 const u16 hash = sig;
141 const u8 profile = current->domain_info->profile;
142 const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_SIGNAL);
143 const bool is_enforce = (mode == 3);
144 bool found = false;
145 if (!mode)
146 return 0;
147 if (!sig)
148 return 0; /* No check for NULL signal. */
149 if (current->pid == pid) {
150 audit_signal_log(sig, domain->domainname, true, profile, mode);
151 return 0; /* No check for self process. */
152 }
153 { /* Simplified checking. */
154 struct task_struct *p = NULL;
155 /***** CRITICAL SECTION START *****/
156 read_lock(&tasklist_lock);
157 if (pid > 0)
158 p = find_task_by_pid((pid_t) pid);
159 else if (pid == 0)
160 p = current;
161 else if (pid == -1)
162 dest = &KERNEL_DOMAIN;
163 else
164 p = find_task_by_pid((pid_t) -pid);
165 if (p)
166 dest = p->domain_info;
167 read_unlock(&tasklist_lock);
168 /***** CRITICAL SECTION END *****/
169 if (!dest)
170 return 0; /* I can't find destinatioin. */
171 }
172 if (domain == dest) {
173 audit_signal_log(sig, dest->domainname, true, profile, mode);
174 return 0; /* No check for self domain. */
175 }
176 retry:
177 dest_pattern = dest->domainname->name;
178 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
179 struct signal_acl_record *acl;
180 if (ccs_acl_type2(ptr) != TYPE_SIGNAL_ACL)
181 continue;
182 acl = container_of(ptr, struct signal_acl_record, head);
183 if (acl->sig == hash && ccs_check_condition(ptr, NULL)) {
184 const int len = acl->domainname->total_len;
185 if (strncmp(acl->domainname->name, dest_pattern, len))
186 continue;
187 switch (dest_pattern[len]) {
188 case ' ':
189 case '\0':
190 break;
191 default:
192 continue;
193 }
194 ccs_update_condition(ptr);
195 found = true;
196 break;
197 }
198 }
199 audit_signal_log(sig, dest->domainname, found, profile, mode);
200 if (found)
201 return 0;
202 if (ccs_verbose_mode())
203 printk(KERN_WARNING "TOMOYO-%s: Signal %d "
204 "to %s denied for %s\n", ccs_get_msg(is_enforce), sig,
205 ccs_get_last_name(dest), ccs_get_last_name(domain));
206 if (is_enforce) {
207 int error = ccs_check_supervisor(NULL, KEYWORD_ALLOW_SIGNAL
208 "%d %s\n", sig, dest_pattern);
209 if (error == 1)
210 goto retry;
211 return error;
212 }
213 if (mode == 1 && ccs_check_domain_quota(domain))
214 update_signal_acl(sig, dest_pattern, domain, NULL, false);
215 return 0;
216 }
217
218 /**
219 * ccs_write_signal_policy - Write "struct signal_acl_record" list.
220 *
221 * @data: String to parse.
222 * @domain: Pointer to "struct domain_info".
223 * @condition: Pointer to "struct condition_list". May be NULL.
224 * @is_delete: True if it is a delete request.
225 *
226 * Returns 0 on success, negative value otherwise.
227 */
228 int ccs_write_signal_policy(char *data, struct domain_info *domain,
229 const struct condition_list *condition,
230 const bool is_delete)
231 {
232 int sig;
233 char *domainname = strchr(data, ' ');
234 if (sscanf(data, "%d", &sig) == 1 && domainname &&
235 ccs_is_domain_def(domainname + 1))
236 return update_signal_acl(sig, domainname + 1, domain,
237 condition, is_delete);
238 return -EINVAL;
239 }

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