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

Subversion リポジトリの参照

Contents of /branches/ccs-patch/security/ccsecurity/signal.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3871 - (show annotations) (download) (as text)
Sun Aug 1 01:42:05 2010 UTC (13 years, 10 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 5559 byte(s)


1 /*
2 * security/ccsecurity/signal.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 *
6 * Version: 1.8.0-pre 2010/08/01
7 *
8 * This file is applicable to both 2.4.30 and 2.6.11 and later.
9 * See README.ccs for ChangeLog.
10 *
11 */
12
13 #include "internal.h"
14
15 /* To support PID namespace. */
16 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
17 #define find_task_by_pid ccsecurity_exports.find_task_by_vpid
18 #endif
19
20 /**
21 * ccs_audit_signal_log - Audit signal log.
22 *
23 * @r: Pointer to "struct ccs_request_info".
24 *
25 * Returns 0 on success, negative value otherwise.
26 */
27 static int ccs_audit_signal_log(struct ccs_request_info *r)
28 {
29 const int sig = r->param.signal.sig;
30 const char *dest_domain = r->param.signal.dest_pattern;
31 ccs_write_log(r, "ipc signal %d %s\n", sig, dest_domain);
32 if (r->granted)
33 return 0;
34 ccs_warn_log(r, "signal %d to %s", sig, ccs_last_word(dest_domain));
35 return ccs_supervisor(r, "ipc signal %d %s\n", sig, dest_domain);
36 }
37
38 static bool ccs_check_signal_acl(struct ccs_request_info *r,
39 const struct ccs_acl_info *ptr)
40 {
41 const struct ccs_signal_acl *acl =
42 container_of(ptr, typeof(*acl), head);
43 if (acl->sig == r->param.signal.sig) {
44 const int len = acl->domainname->total_len;
45 if (!strncmp(acl->domainname->name,
46 r->param.signal.dest_pattern, len)) {
47 switch (r->param.signal.dest_pattern[len]) {
48 case ' ':
49 case '\0':
50 return true;
51 }
52 }
53 }
54 return false;
55 }
56
57 /**
58 * ccs_signal_acl2 - Check permission for signal.
59 *
60 * @sig: Signal number.
61 * @pid: Target's PID.
62 *
63 * Returns 0 on success, negative value otherwise.
64 *
65 * Caller holds ccs_read_lock().
66 */
67 static int ccs_signal_acl2(const int sig, const int pid)
68 {
69 struct ccs_request_info r;
70 struct ccs_domain_info *dest = NULL;
71 int error;
72 const struct ccs_domain_info * const domain = ccs_current_domain();
73 if (ccs_init_request_info(&r, CCS_MAC_SIGNAL) == CCS_CONFIG_DISABLED)
74 return 0;
75 if (!sig)
76 return 0; /* No check for NULL signal. */
77 r.param_type = CCS_TYPE_SIGNAL_ACL;
78 r.param.signal.sig = sig;
79 r.param.signal.dest_pattern = domain->domainname->name;
80 r.granted = true;
81 if (ccsecurity_exports.sys_getpid() == pid) {
82 ccs_audit_signal_log(&r);
83 return 0; /* No check for self process. */
84 }
85 { /* Simplified checking. */
86 struct task_struct *p = NULL;
87 ccs_tasklist_lock();
88 if (pid > 0)
89 p = find_task_by_pid((pid_t) pid);
90 else if (pid == 0)
91 p = current;
92 else if (pid == -1)
93 dest = &ccs_kernel_domain;
94 else
95 p = find_task_by_pid((pid_t) -pid);
96 if (p)
97 dest = ccs_task_domain(p);
98 ccs_tasklist_unlock();
99 }
100 if (!dest)
101 return 0; /* I can't find destinatioin. */
102 if (domain == dest) {
103 ccs_audit_signal_log(&r);
104 return 0; /* No check for self domain. */
105 }
106 r.param.signal.dest_pattern = dest->domainname->name;
107 do {
108 ccs_check_acl(&r, ccs_check_signal_acl);
109 error = ccs_audit_signal_log(&r);
110 } while (error == CCS_RETRY_REQUEST);
111 return error;
112 }
113
114 /**
115 * ccs_signal_acl - Check permission for signal.
116 *
117 * @pid: Target's PID.
118 * @sig: Signal number.
119 *
120 * Returns 0 on success, negative value otherwise.
121 */
122 static int ccs_signal_acl(const int pid, const int sig)
123 {
124 int error;
125 if (!sig)
126 error = 0;
127 else {
128 const int idx = ccs_read_lock();
129 error = ccs_signal_acl2(sig, pid);
130 ccs_read_unlock(idx);
131 }
132 return error;
133 }
134
135 /**
136 * ccs_signal_acl0 - Permission check for signal().
137 *
138 * @tgid: Unused.
139 * @pid: PID
140 * @sig: Signal number.
141 *
142 * Returns 0 on success, negative value otherwise.
143 */
144 static int ccs_signal_acl0(pid_t tgid, pid_t pid, int sig)
145 {
146 return ccs_signal_acl(pid, sig);
147 }
148
149 static bool ccs_same_signal_entry(const struct ccs_acl_info *a,
150 const struct ccs_acl_info *b)
151 {
152 const struct ccs_signal_acl *p1 = container_of(a, typeof(*p1), head);
153 const struct ccs_signal_acl *p2 = container_of(b, typeof(*p2), head);
154 return p1->head.type == p2->head.type && p1->head.cond == p2->head.cond
155 && p1->head.type == CCS_TYPE_SIGNAL_ACL && p1->sig == p2->sig
156 && p1->domainname == p2->domainname;
157 }
158
159 /**
160 * ccs_write_signal - Write "struct ccs_signal_acl" list.
161 *
162 * @data: String to parse.
163 * @domain: Pointer to "struct ccs_domain_info".
164 * @condition: Pointer to "struct ccs_condition". Maybe NULL.
165 * @is_delete: True if it is a delete request.
166 *
167 * Returns 0 on success, negative value otherwise.
168 */
169 static int ccs_write_signal(char *data, struct ccs_domain_info *domain,
170 struct ccs_condition *condition,
171 const bool is_delete)
172 {
173 struct ccs_signal_acl e = { .head.type = CCS_TYPE_SIGNAL_ACL,
174 .head.cond = condition };
175 int error;
176 int sig;
177 char *domainname = strchr(data, ' ');
178 if (sscanf(data, "%d", &sig) != 1 || !domainname ||
179 !ccs_correct_domain(domainname + 1))
180 return -EINVAL;
181 e.sig = sig;
182 e.domainname = ccs_get_name(domainname + 1);
183 if (!e.domainname)
184 return -ENOMEM;
185 error = ccs_update_domain(&e.head, sizeof(e), is_delete, domain,
186 ccs_same_signal_entry, NULL);
187 ccs_put_name(e.domainname);
188 return error;
189 }
190
191 int ccs_write_ipc(char *data, struct ccs_domain_info *domain,
192 struct ccs_condition *condition, const bool is_delete)
193 {
194 if (ccs_str_starts(&data, "signal "))
195 return ccs_write_signal(data, domain, condition, is_delete);
196 return -EINVAL;
197 }
198
199 void __init ccs_signal_init(void)
200 {
201 ccsecurity_ops.kill_permission = ccs_signal_acl;
202 ccsecurity_ops.tgkill_permission = ccs_signal_acl0;
203 ccsecurity_ops.tkill_permission = ccs_signal_acl;
204 ccsecurity_ops.sigqueue_permission = ccs_signal_acl;
205 ccsecurity_ops.tgsigqueue_permission = ccs_signal_acl0;
206 }

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