• R/O
  • SSH
  • HTTPS

tomoyo: Commit


Commit MetaInfo

Revision755 (tree)
Time2007-12-03 18:08:17
Authorkumaneko

Log Message

2.1.1

Change Summary

Incremental Difference

--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-exec.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-exec.diff (revision 755)
@@ -0,0 +1,233 @@
1+argv[0] check functions for TOMOYO Linux.
2+If the executed program name and argv[0] is different,
3+TOMOYO Linux checks permission.
4+
5+Each permission can be automatically accumulated into
6+the policy of each domain using 'learning mode'.
7+
8+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
9+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
10+ security/tomoyo/exec.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++
11+ 1 file changed, 218 insertions(+)
12+
13+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
14++++ linux-2.6.23/security/tomoyo/exec.c 2007-11-09 17:16:26.000000000 +0900
15+@@ -0,0 +1,218 @@
16++/*
17++ * security/tomoyo/exec.c
18++ *
19++ * Argv0 access control functions for TOMOYO Linux.
20++ */
21++
22++#include "tomoyo.h"
23++#include "realpath.h"
24++
25++/************************* AUDIT FUNCTIONS *************************/
26++
27++static int tmy_audit_argv0_log(const struct path_info *filename,
28++ const char *argv0,
29++ const bool is_granted,
30++ const u8 profile,
31++ const unsigned int mode)
32++{
33++ char *buf;
34++ int len;
35++
36++ if (is_granted) {
37++ if (!tmy_audit_grant())
38++ return 0;
39++ } else {
40++ if (!tmy_audit_reject())
41++ return 0;
42++ }
43++
44++ len = filename->total_len + strlen(argv0) + 8;
45++ buf = tmy_init_audit_log(&len, profile, mode);
46++
47++ if (!buf)
48++ return -ENOMEM;
49++
50++ snprintf(buf + strlen(buf),
51++ len - strlen(buf) - 1,
52++ TMY_ALLOW_ARGV0 "%s %s",
53++ filename->name,
54++ argv0);
55++
56++ return tmy_write_audit_log(buf, is_granted);
57++}
58++
59++/************************* ARGV0 MISMATCH HANDLER *************************/
60++
61++static int tmy_add_argv0_entry(const char *filename,
62++ const char *argv0,
63++ struct domain_info *domain,
64++ const struct condition_list *cond,
65++ const bool is_delete)
66++{
67++ struct acl_info *ptr;
68++ struct argv0_acl *acl;
69++ const struct path_info *saved_filename;
70++ const struct path_info *saved_argv0;
71++ int error = -ENOMEM;
72++
73++ if (!tmy_correct_path(filename, 1, 0, -1, __FUNCTION__) ||
74++ !tmy_correct_path(argv0, -1, 0, -1, __FUNCTION__) ||
75++ strchr(argv0, '/'))
76++ return -EINVAL;
77++
78++ saved_filename = tmy_save_name(filename);
79++ saved_argv0 = tmy_save_name(argv0);
80++ if (!saved_filename || !saved_argv0)
81++ return -ENOMEM;
82++
83++ mutex_lock(&domain_acl_lock);
84++
85++ if (is_delete)
86++ goto remove;
87++
88++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
89++ acl = (struct argv0_acl *) ptr;
90++ if (ptr->type == TMY_TYPE_ARGV0_ACL && ptr->cond == cond &&
91++ acl->filename == saved_filename &&
92++ acl->argv0 == saved_argv0) {
93++ ptr->is_deleted = 0;
94++ /* Found. Nothing to do. */
95++ error = 0;
96++ goto ok;
97++ }
98++ }
99++
100++ /* Not found. Append it to the tail. */
101++ acl = tmy_alloc_element(sizeof(*acl));
102++ if (!acl)
103++ goto ok;
104++
105++ acl->head.type = TMY_TYPE_ARGV0_ACL;
106++ acl->head.cond = cond;
107++ acl->filename = saved_filename;
108++ acl->argv0 = saved_argv0;
109++ error = tmy_add_acl(domain,
110++ (struct acl_info *) acl);
111++ goto ok;
112++remove: ;
113++ error = -ENOENT;
114++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
115++ acl = (struct argv0_acl *) ptr;
116++ if (ptr->type != TMY_TYPE_ARGV0_ACL ||
117++ ptr->cond != cond || ptr->is_deleted ||
118++ acl->filename != saved_filename ||
119++ acl->argv0 != saved_argv0)
120++ continue;
121++
122++ error = tmy_del_acl(ptr);
123++ break;
124++ }
125++ok: ;
126++ mutex_unlock(&domain_acl_lock);
127++
128++ return error;
129++}
130++
131++static int tmy_argv0_acl(const struct path_info *filename,
132++ const char *argv0_)
133++{
134++ const struct domain_info *domain = TMY_SECURITY->domain;
135++ int error = -EPERM;
136++ struct acl_info *ptr;
137++ struct path_info argv0;
138++
139++ if (!tmy_flags(TMY_MAC_FOR_ARGV0))
140++ return 0;
141++
142++ argv0.name = argv0_;
143++ tmy_fill_path_info(&argv0);
144++
145++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
146++ struct argv0_acl *acl = (struct argv0_acl *) ptr;
147++
148++ if (ptr->type == TMY_TYPE_ARGV0_ACL &&
149++ ptr->is_deleted == 0 &&
150++ tmy_check_condition(ptr->cond, NULL) == 0 &&
151++ tmy_path_match(filename, acl->filename) &&
152++ tmy_path_match(&argv0, acl->argv0)) {
153++ error = 0;
154++ break;
155++ }
156++ }
157++
158++ return error;
159++}
160++
161++/**
162++ * tmy_argv0_perm - check for argv[0] permission.
163++ * @filename: pointer to filename.
164++ * @argv0: pointer to basename of argv[0].
165++ *
166++ * Returns zero if permission granted.
167++ * Returns nonzero if permission denied.
168++ */
169++int tmy_argv0_perm(const struct path_info *filename, const char *argv0)
170++{
171++ int error = 0;
172++ const u8 profile = TMY_SECURITY->domain->profile;
173++ const unsigned int mode = tmy_flags(TMY_MAC_FOR_ARGV0);
174++ const bool is_enforce = (mode == 3);
175++
176++ if (!mode)
177++ return 0;
178++ if (!filename || !argv0 || !*argv0)
179++ return 0;
180++
181++ error = tmy_argv0_acl(filename, argv0);
182++
183++ tmy_audit_argv0_log(filename, argv0, !error, profile, mode);
184++
185++ if (error) {
186++ struct domain_info * const domain = TMY_SECURITY->domain;
187++
188++ if (tmy_flags(TMY_VERBOSE))
189++ tmy_audit("TOMOYO-%s: Run %s as %s denied for %s\n",
190++ tmy_getmsg(is_enforce), filename->name, argv0,
191++ tmy_lastname(domain));
192++
193++ if (is_enforce)
194++ error = tmy_supervisor("%s\n" TMY_ALLOW_ARGV0 "%s %s\n",
195++ domain->domainname->name,
196++ filename->name, argv0);
197++
198++ else if (mode == 1 && tmy_quota())
199++ tmy_add_argv0_entry(filename->name, argv0, domain,
200++ NULL, 0);
201++
202++ if (!is_enforce)
203++ error = 0;
204++ }
205++
206++ return error;
207++}
208++
209++/**
210++ * tmy_add_argv0_policy - add or delete argv[0] policy.
211++ * @data: a line to parse.
212++ * @domain: pointer to "struct domain_info".
213++ * @cond: pointer to "struct condition_list". May be NULL.
214++ * @is_delete: is this delete request?
215++ *
216++ * Returns zero on success.
217++ * Returns nonzero on failure.
218++ */
219++int tmy_add_argv0_policy(char *data,
220++ struct domain_info *domain,
221++ const struct condition_list *cond,
222++ const bool is_delete)
223++{
224++ char *argv0 = strchr(data, ' ');
225++
226++ if (!argv0)
227++ return -EINVAL;
228++
229++ *argv0++ = '\0';
230++
231++ return tmy_add_argv0_entry(data, argv0, domain, cond,
232++ is_delete);
233++}
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-net.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-net.diff (revision 755)
@@ -0,0 +1,976 @@
1+Network access control functions for TOMOYO Linux.
2+TOMOYO Linux checks permission by the following four parameters.
3+ * protocol type (TCP, UDP, RAW)
4+ * access type (bind, listen, connect, accept)
5+ * IP address (Both IPv4 and IPv6 are available)
6+ * port number
7+In order to check 'TCP accept' and 'UDP connect',
8+LSM expansion patch ([TOMOYO /]) is needed.
9+
10+Each permission can be automatically accumulated into
11+the policy of each domain using 'learning mode'.
12+
13+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
14+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
15+ security/tomoyo/net.c | 956 ++++++++++++++++++++++++++++++++++++++++++++++++++
16+ 1 file changed, 956 insertions(+)
17+
18+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
19++++ linux-2.6.23/security/tomoyo/net.c 2007-11-21 09:31:12.812105824 +0900
20+@@ -0,0 +1,956 @@
21++/*
22++ * security/tomoyo/net.c
23++ *
24++ * Network access control functions for TOMOYO Linux.
25++ */
26++
27++#include "tomoyo.h"
28++#include "realpath.h"
29++
30++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
31++#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
32++#endif
33++
34++/************************* AUDIT FUNCTIONS *************************/
35++
36++static int tmy_audit_network_log(const bool is_ipv6,
37++ const char *operation,
38++ const u32 *address,
39++ const u16 port,
40++ const bool is_granted,
41++ const u8 profile,
42++ const unsigned int mode)
43++{
44++ char *buf;
45++ int len = 256;
46++
47++ if (is_granted) {
48++ if (!tmy_audit_grant())
49++ return 0;
50++ } else {
51++ if (!tmy_audit_reject())
52++ return 0;
53++ }
54++
55++ buf = tmy_init_audit_log(&len, profile, mode);
56++ if (!buf)
57++ return -ENOMEM;
58++
59++ snprintf(buf + strlen(buf), len - strlen(buf) - 1,
60++ TMY_ALLOW_NETWORK "%s ", operation);
61++
62++ if (is_ipv6)
63++ tmy_print_ipv6(buf + strlen(buf), len - strlen(buf),
64++ (const u16 *) address);
65++ else {
66++ u32 ip = *address;
67++ snprintf(buf + strlen(buf), len - strlen(buf) - 1,
68++ NIPQUAD_FMT, NIPQUAD(ip));
69++ }
70++
71++ snprintf(buf + strlen(buf), len - strlen(buf) - 1, " %u\n", port);
72++
73++ return tmy_write_audit_log(buf, is_granted);
74++}
75++
76++/************************* ADDRESS GROUP HANDLER *************************/
77++
78++/* List of address group. */
79++static LIST_HEAD(address_group_list);
80++
81++static int tmy_add_address_group_entry(const char *group_name,
82++ const bool is_ipv6,
83++ const u16 *min_address,
84++ const u16 *max_address,
85++ const bool is_delete)
86++{
87++ static DEFINE_MUTEX(mutex);
88++ struct address_group_entry *new_group;
89++ struct address_group_entry *group;
90++ struct address_group_member *new_member;
91++ struct address_group_member *member;
92++ const struct path_info *saved_group_name;
93++ int error = -ENOMEM;
94++ bool found = 0;
95++
96++ if (!tmy_correct_path(group_name, 0, 0, 0, __FUNCTION__) ||
97++ !group_name[0])
98++ return -EINVAL;
99++
100++ saved_group_name = tmy_save_name(group_name);
101++ if (!saved_group_name)
102++ return -ENOMEM;
103++
104++ mutex_lock(&mutex);
105++
106++ list_for_each_entry(group, &address_group_list, list) {
107++ if (saved_group_name != group->group_name)
108++ continue;
109++ list_for_each_entry(member, &group->address_group_member_list,
110++ list) {
111++ if (member->is_ipv6 != is_ipv6)
112++ continue;
113++ if (is_ipv6) {
114++ if (memcmp(member->min.ipv6, min_address, 16) ||
115++ memcmp(member->max.ipv6, max_address, 16))
116++ continue;
117++ } else {
118++ if (member->min.ipv4 != *(u32 *) min_address ||
119++ member->max.ipv4 != *(u32 *) max_address)
120++ continue;
121++ }
122++ member->is_deleted = is_delete;
123++ error = 0;
124++ goto out;
125++ }
126++ found = 1;
127++ break;
128++ }
129++
130++ if (is_delete) {
131++ error = -ENOENT;
132++ goto out;
133++ }
134++
135++ if (!found) {
136++ new_group = tmy_alloc_element(sizeof(*new_group));
137++ if (!new_group)
138++ goto out;
139++ INIT_LIST_HEAD(&new_group->address_group_member_list);
140++ new_group->group_name = saved_group_name;
141++ list_add_tail_mb(&new_group->list, &address_group_list);
142++ group = new_group;
143++ }
144++
145++ new_member = tmy_alloc_element(sizeof(*new_member));
146++ if (!new_member)
147++ goto out;
148++
149++ new_member->is_ipv6 = is_ipv6;
150++
151++ if (is_ipv6) {
152++ memmove(new_member->min.ipv6, min_address, 16);
153++ memmove(new_member->max.ipv6, max_address, 16);
154++ } else {
155++ new_member->min.ipv4 = *(u32 *) min_address;
156++ new_member->max.ipv4 = *(u32 *) max_address;
157++ }
158++
159++ list_add_tail_mb(&new_member->list, &group->address_group_member_list);
160++ error = 0;
161++out: ;
162++ mutex_unlock(&mutex);
163++
164++ return error;
165++}
166++
167++/**
168++ * tmy_add_address_group_policy - add or delete address group policy.
169++ * @data: a line to parse.
170++ * @is_delete: is this delete request?
171++ *
172++ * Returns zero on success.
173++ * Returns nonzero on failure.
174++ */
175++int tmy_add_address_group_policy(char *data, const bool is_delete)
176++{
177++ int count;
178++ bool is_ipv6;
179++ u16 min_address[8];
180++ u16 max_address[8];
181++ unsigned int min[8];
182++ unsigned int max[8];
183++ char *cp = strchr(data, ' ');
184++
185++ if (!cp)
186++ return -EINVAL;
187++
188++ *cp++ = '\0';
189++ count = sscanf(cp,
190++ NIP6_FMT "-" NIP6_FMT,
191++ &min[0], &min[1], &min[2], &min[3],
192++ &min[4], &min[5], &min[6], &min[7],
193++ &max[0], &max[1], &max[2], &max[3],
194++ &max[4], &max[5], &max[6], &max[7]);
195++
196++ if (count == 8 || count == 16) {
197++
198++ int i;
199++
200++ for (i = 0; i < 8; i++) {
201++ min_address[i] = htons((u16) min[i]);
202++ max_address[i] = htons((u16) max[i]);
203++ }
204++ if (count == 8)
205++ memmove(max_address, min_address, sizeof(min_address));
206++ is_ipv6 = 1;
207++
208++ goto ok;
209++
210++ }
211++
212++ count = sscanf(cp,
213++ NIPQUAD_FMT "-" NIPQUAD_FMT,
214++ &min[0], &min[1],
215++ &min[2], &min[3],
216++ &max[0], &max[1],
217++ &max[2], &max[3]);
218++
219++ if (count == 4 || count == 8) {
220++ u32 ip = ((((u8) min[0]) << 24) +
221++ (((u8) min[1]) << 16) +
222++ (((u8) min[2]) << 8) +
223++ (u8) min[3]);
224++
225++ *(u32 *) min_address = ip;
226++
227++ if (count == 8)
228++ ip = ((((u8) max[0]) << 24) +
229++ (((u8) max[1]) << 16) +
230++ (((u8) max[2]) << 8) +
231++ (u8) max[3]);
232++
233++ *(u32 *) max_address = ip;
234++ is_ipv6 = 0;
235++
236++ goto ok;
237++
238++ }
239++
240++ return -EINVAL;
241++
242++ok: ;
243++ return tmy_add_address_group_entry(data, is_ipv6, min_address,
244++ max_address, is_delete);
245++}
246++
247++static struct address_group_entry *tmy_new_address_group(const char *name)
248++{
249++ int i;
250++ struct address_group_entry *group;
251++
252++ for (i = 0; i <= 1; i++) {
253++ list_for_each_entry(group, &address_group_list, list) {
254++ if (strcmp(name, group->group_name->name) == 0)
255++ return group;
256++ }
257++
258++ if (i == 0) {
259++ /*
260++ * Add a dummy entry to create new address group
261++ * and delete that entry.
262++ */
263++ const u16 dum[2] = { 0, 0 };
264++ tmy_add_address_group_entry(name, 0, dum, dum, 0);
265++ tmy_add_address_group_entry(name, 0, dum, dum, 1);
266++ }
267++ }
268++
269++ return NULL;
270++}
271++
272++static int tmy_address_match_group(const bool is_ipv6,
273++ const u32 *address,
274++ const struct address_group_entry *group)
275++{
276++ struct address_group_member *member;
277++ const u32 ip = ntohl(*address);
278++
279++ list_for_each_entry(member, &group->address_group_member_list, list) {
280++ if (member->is_deleted)
281++ continue;
282++
283++ if (member->is_ipv6) {
284++
285++ if (is_ipv6 &&
286++ memcmp(member->min.ipv6, address, 16) <= 0 &&
287++ memcmp(address, member->max.ipv6, 16) <= 0)
288++ return 1;
289++
290++ } else {
291++
292++ if (!is_ipv6 &&
293++ member->min.ipv4 <= ip &&
294++ ip <= member->max.ipv4)
295++ return 1;
296++
297++ }
298++ }
299++
300++ return 0;
301++}
302++
303++static int tmy_read_address_group(struct io_buffer *head,
304++ struct address_group_entry *group,
305++ struct address_group_member *member)
306++{
307++ char buf[128];
308++ if (!member)
309++ return 0;
310++
311++ if (member->is_ipv6) {
312++
313++ const u16 *min_addr = member->min.ipv6;
314++ const u16 *max_addr = member->max.ipv6;
315++
316++ tmy_print_ipv6(buf, sizeof(buf), min_addr);
317++
318++ if (memcmp(min_addr, max_addr, 16)) {
319++ char *cp = strchr(buf, '\0');
320++ int len = sizeof(buf) - strlen(buf) - 1;
321++
322++ *cp++ = '-';
323++ tmy_print_ipv6(cp, len, max_addr);
324++ }
325++
326++ } else {
327++
328++ const u32 min_addr = member->min.ipv4;
329++ const u32 max_addr = member->max.ipv4;
330++
331++ memset(buf, 0, sizeof(buf));
332++ snprintf(buf, sizeof(buf) - 1,
333++ NIPQUAD_FMT, HIPQUAD(min_addr));
334++
335++ if (min_addr != max_addr) {
336++ const int len = strlen(buf);
337++
338++ snprintf(buf + len, sizeof(buf) - 1 - len,
339++ "-" NIPQUAD_FMT, HIPQUAD(max_addr));
340++ }
341++
342++ }
343++
344++ return tmy_io_printf(head, TMY_ADDRESS_GROUP "%s %s\n",
345++ group->group_name->name, buf);
346++}
347++
348++/**
349++ * tmy_read_address_group_policy - read address group policy
350++ * @head: pointer to "struct io_buffer".
351++ *
352++ * Returns nonzero if reading incomplete.
353++ * Returns zero otherwise.
354++ */
355++int tmy_read_address_group_policy(struct io_buffer *head)
356++{
357++ struct list_head *gpos;
358++ struct list_head *mpos;
359++ list_for_each_cookie(gpos, head->read_var1, &address_group_list) {
360++ struct address_group_entry *group;
361++ group = list_entry(gpos, struct address_group_entry, list);
362++ list_for_each_cookie(mpos, head->read_var2,
363++ &group->address_group_member_list) {
364++ struct address_group_member *member;
365++ member = list_entry(mpos, struct address_group_member,
366++ list);
367++ if (member->is_deleted)
368++ continue;
369++ if (tmy_read_address_group(head, group, member))
370++ return -ENOMEM;
371++ }
372++ }
373++ return 0;
374++}
375++
376++/*********************** NETWORK NETWORK ACL HANDLER ***********************/
377++
378++/**
379++ * tmy_print_ipv6 - print ipv6 address
380++ * @buffer: pointer to buffer to save the result.
381++ * @buffer_len: sizeof @buffer .
382++ * @ip: pointer to an IPv6 address in network byte order.
383++ *
384++ * Returns @buffer .
385++ */
386++char *tmy_print_ipv6(char *buffer, const int buffer_len, const u16 *ip)
387++{
388++ memset(buffer, 0, buffer_len);
389++ snprintf(buffer, buffer_len - 1, NIP6_FMT,
390++ ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]),
391++ ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]));
392++ return buffer;
393++}
394++
395++/**
396++ * tmy_network2keyword - get keyword from access control index.
397++ * @operation: index number.
398++ *
399++ * Returns keyword that corresponds with @operation .
400++ */
401++const char *tmy_network2keyword(const unsigned int operation)
402++{
403++ const char *keyword = "unknown";
404++ switch (operation) {
405++ case TMY_NETWORK_ACL_UDP_BIND:
406++ keyword = "UDP bind";
407++ break;
408++ case TMY_NETWORK_ACL_UDP_CONNECT:
409++ keyword = "UDP connect";
410++ break;
411++ case TMY_NETWORK_ACL_TCP_BIND:
412++ keyword = "TCP bind";
413++ break;
414++ case TMY_NETWORK_ACL_TCP_LISTEN:
415++ keyword = "TCP listen";
416++ break;
417++ case TMY_NETWORK_ACL_TCP_CONNECT:
418++ keyword = "TCP connect";
419++ break;
420++ case TMY_NETWORK_ACL_TCP_ACCEPT:
421++ keyword = "TCP accept";
422++ break;
423++ case TMY_NETWORK_ACL_RAW_BIND:
424++ keyword = "RAW bind";
425++ break;
426++ case TMY_NETWORK_ACL_RAW_CONNECT:
427++ keyword = "RAW connect";
428++ break;
429++ }
430++ return keyword;
431++}
432++
433++/* Compare IPv4/IPv6 address. */
434++static int tmy_cmp_network_entry(const u8 record_type,
435++ struct net_acl *acl,
436++ const struct address_group_entry *group,
437++ const u32 min_ip,
438++ const u32 max_ip,
439++ const u32 *min_address,
440++ const u32 *max_address)
441++{
442++ int found = 0;
443++
444++ switch (record_type) {
445++
446++ case TMY_TYPE_ADDRESS_GROUP:
447++ if (acl->u.group == group)
448++ found = 1;
449++ break;
450++
451++ case TMY_TYPE_IPv4:
452++ if (acl->u.ipv4.min == min_ip &&
453++ max_ip == acl->u.ipv4.max)
454++ found = 1;
455++ break;
456++
457++ case TMY_TYPE_IPv6:
458++ if (memcmp(acl->u.ipv6.min, min_address, 16) == 0 &&
459++ memcmp(max_address, acl->u.ipv6.max, 16) == 0)
460++ found = 1;
461++ break;
462++
463++ }
464++
465++ return found;
466++}
467++
468++static int tmy_add_network_entry(const u8 operation,
469++ const u8 record_type,
470++ const struct address_group_entry *group,
471++ const u32 *min_address,
472++ const u32 *max_address,
473++ const u16 min_port,
474++ const u16 max_port,
475++ struct domain_info *domain,
476++ const struct condition_list *cond,
477++ const bool is_delete)
478++{
479++ struct acl_info *ptr;
480++ struct net_acl *acl;
481++ int error = -ENOMEM;
482++ /* using host byte order to allow u32 comparison than memcmp().*/
483++ const u32 min_ip = ntohl(*min_address);
484++ const u32 max_ip = ntohl(*max_address);
485++
486++ if (!domain)
487++ return -EINVAL;
488++
489++ mutex_lock(&domain_acl_lock);
490++
491++ if (is_delete)
492++ goto remove;
493++
494++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
495++ acl = (struct net_acl *) ptr;
496++ if (ptr->type == TMY_TYPE_IP_NETWORK_ACL &&
497++ ptr->cond == cond &&
498++ acl->operation_type == operation &&
499++ acl->record_type == record_type &&
500++ acl->min_port == min_port &&
501++ max_port == acl->max_port &&
502++ tmy_cmp_network_entry(record_type, acl,
503++ group, min_ip, max_ip,
504++ min_address,
505++ max_address)) {
506++ ptr->is_deleted = 0;
507++ error = 0;
508++ goto ok;
509++ }
510++ }
511++ /* Not found. Append it to the tail. */
512++ acl = tmy_alloc_element(sizeof(*acl));
513++ if (!acl)
514++ goto ok;
515++
516++ acl->head.type = TMY_TYPE_IP_NETWORK_ACL;
517++ acl->head.cond = cond;
518++ acl->operation_type = operation;
519++ acl->record_type = record_type;
520++
521++ if (record_type == TMY_TYPE_ADDRESS_GROUP)
522++ acl->u.group = group;
523++ else if (record_type == TMY_TYPE_IPv4) {
524++ acl->u.ipv4.min = min_ip;
525++ acl->u.ipv4.max = max_ip;
526++ } else {
527++ memmove(acl->u.ipv6.min, min_address, 16);
528++ memmove(acl->u.ipv6.max, max_address, 16);
529++ }
530++
531++ acl->min_port = min_port;
532++ acl->max_port = max_port;
533++ error = tmy_add_acl(domain,
534++ (struct acl_info *) acl);
535++ goto ok;
536++remove: ;
537++ error = -ENOENT;
538++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
539++ acl = (struct net_acl *) ptr;
540++ if (ptr->type != TMY_TYPE_IP_NETWORK_ACL ||
541++ ptr->cond != cond ||
542++ ptr->is_deleted ||
543++ acl->operation_type != operation ||
544++ acl->record_type != record_type ||
545++ acl->min_port != min_port ||
546++ acl->max_port != max_port ||
547++ !tmy_cmp_network_entry(record_type, acl,
548++ group, min_ip, max_ip,
549++ min_address,
550++ max_address))
551++ continue;
552++ error = tmy_del_acl(ptr);
553++ break;
554++ }
555++ok: ;
556++ mutex_unlock(&domain_acl_lock);
557++
558++ return error;
559++}
560++
561++/* Check network permission. */
562++static int tmy_network_entry(const bool is_ipv6,
563++ const int operation,
564++ const u32 *address,
565++ const u16 port)
566++{
567++ struct domain_info * const domain = TMY_SECURITY->domain;
568++ const u8 profile = domain->profile;
569++ const unsigned int mode = tmy_flags(TMY_MAC_FOR_NETWORK);
570++ struct acl_info *ptr;
571++ const char *keyword = tmy_network2keyword(operation);
572++ const bool is_enforce = (mode == 3);
573++ /* using host byte order to allow u32 comparison than memcmp().*/
574++ const u32 ip = ntohl(*address);
575++ bool found = 0;
576++
577++ if (!mode)
578++ return 0;
579++
580++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
581++ struct net_acl *acl = (struct net_acl *) ptr;
582++ if (ptr->type != TMY_TYPE_IP_NETWORK_ACL ||
583++ ptr->is_deleted ||
584++ acl->operation_type != operation ||
585++ port < acl->min_port ||
586++ acl->max_port < port ||
587++ tmy_check_condition(ptr->cond, NULL))
588++ continue;
589++
590++ if (acl->record_type == TMY_TYPE_ADDRESS_GROUP) {
591++ if (tmy_address_match_group(is_ipv6, address,
592++ acl->u.group)) {
593++ found = 1;
594++ break;
595++ }
596++ } else if (acl->record_type == TMY_TYPE_IPv4) {
597++ if (!is_ipv6 &&
598++ (acl->u.ipv4.min <= ip && ip <= acl->u.ipv4.max)) {
599++ found = 1;
600++ break;
601++ }
602++ } else {
603++ if (is_ipv6 &&
604++ memcmp(acl->u.ipv6.min, address, 16) <= 0 &&
605++ memcmp(address, acl->u.ipv6.max, 16) <= 0) {
606++ found = 1;
607++ break;
608++ }
609++ }
610++ }
611++
612++ tmy_audit_network_log(is_ipv6, keyword, address,
613++ port, found, profile, mode);
614++
615++ if (found)
616++ return 0;
617++
618++ if (tmy_flags(TMY_VERBOSE)) {
619++ if (is_ipv6) {
620++ char buf[64];
621++ tmy_print_ipv6(buf, sizeof(buf), (const u16 *) address);
622++ tmy_audit("TOMOYO-%s: %s to %s %u denied for %s\n",
623++ tmy_getmsg(is_enforce), keyword, buf, port,
624++ tmy_lastname(domain));
625++ } else {
626++ tmy_audit("TOMOYO-%s: %s to %u.%u.%u.%u %u denied for "
627++ "%s\n", tmy_getmsg(is_enforce), keyword,
628++ HIPQUAD(ip), port, tmy_lastname(domain));
629++ }
630++ }
631++
632++ if (is_enforce) {
633++
634++ if (is_ipv6) {
635++
636++ char buf[64];
637++
638++ tmy_print_ipv6(buf, sizeof(buf), (const u16 *) address);
639++ return tmy_supervisor("%s\n" TMY_ALLOW_NETWORK
640++ "%s %s %u\n",
641++ domain->domainname->name, keyword,
642++ buf, port);
643++
644++ }
645++
646++ return tmy_supervisor("%s\n" TMY_ALLOW_NETWORK
647++ "%s " NIPQUAD_FMT " %u\n",
648++ domain->domainname->name, keyword,
649++ HIPQUAD(ip), port);
650++
651++ }
652++
653++ if (mode == 1 && tmy_quota())
654++ tmy_add_network_entry(operation,
655++ is_ipv6 ? TMY_TYPE_IPv6 : TMY_TYPE_IPv4,
656++ NULL, address, address,
657++ port, port, domain, NULL, 0);
658++
659++ return 0;
660++}
661++
662++/**
663++ * tmy_add_signal_policy - add or delete signal policy.
664++ * @data: a line to parse.
665++ * @domain: pointer to "struct domain_info".
666++ * @cond: pointer to "struct condition_list". May be NULL.
667++ * @is_delete: is this delete request?
668++ *
669++ * Returns zero on success.
670++ * Returns nonzero on failure.
671++ */
672++int tmy_add_network_policy(char *data,
673++ struct domain_info *domain,
674++ const struct condition_list *cond,
675++ const bool is_delete)
676++{
677++ u8 sock_type;
678++ u8 operation;
679++ u8 record_type;
680++ u16 min_address[8];
681++ u16 max_address[8];
682++ unsigned int min[8];
683++ unsigned int max[8];
684++ struct address_group_entry *group = NULL;
685++ u16 min_port;
686++ u16 max_port;
687++ int count;
688++ char *cp1 = NULL;
689++ char *cp2 = NULL;
690++
691++ cp1 = strchr(data, ' ');
692++ if (!cp1)
693++ goto out;
694++ cp1++;
695++
696++ if (strncmp(data, "TCP ", 4) == 0)
697++ sock_type = SOCK_STREAM;
698++ else if (strncmp(data, "UDP ", 4) == 0)
699++ sock_type = SOCK_DGRAM;
700++ else if (strncmp(data, "RAW ", 4) == 0)
701++ sock_type = SOCK_RAW;
702++ else
703++ goto out;
704++
705++ cp2 = strchr(cp1, ' ');
706++ if (!cp2)
707++ goto out;
708++ cp2++;
709++
710++ if (strncmp(cp1, "bind ", 5) == 0) {
711++ switch (sock_type) {
712++ case SOCK_STREAM:
713++ operation = TMY_NETWORK_ACL_TCP_BIND;
714++ break;
715++ case SOCK_DGRAM:
716++ operation = TMY_NETWORK_ACL_UDP_BIND;
717++ break;
718++ default:
719++ operation = TMY_NETWORK_ACL_RAW_BIND;
720++ break;
721++ }
722++ } else if (strncmp(cp1, "connect ", 8) == 0) {
723++ switch (sock_type) {
724++ case SOCK_STREAM:
725++ operation = TMY_NETWORK_ACL_TCP_CONNECT;
726++ break;
727++ case SOCK_DGRAM:
728++ operation = TMY_NETWORK_ACL_UDP_CONNECT;
729++ break;
730++ default:
731++ operation = TMY_NETWORK_ACL_RAW_CONNECT;
732++ break;
733++ }
734++ } else if (sock_type == SOCK_STREAM &&
735++ strncmp(cp1, "listen ", 7) == 0)
736++ operation = TMY_NETWORK_ACL_TCP_LISTEN;
737++
738++ else if (sock_type == SOCK_STREAM &&
739++ strncmp(cp1, "accept ", 7) == 0)
740++ operation = TMY_NETWORK_ACL_TCP_ACCEPT;
741++
742++ else
743++ goto out;
744++
745++ cp1 = strchr(cp2, ' ');
746++ if (!cp1)
747++ goto out;
748++ *cp1++ = '\0';
749++
750++ count = sscanf(cp2,
751++ NIP6_FMT "-" NIP6_FMT,
752++ &min[0], &min[1], &min[2], &min[3],
753++ &min[4], &min[5], &min[6], &min[7],
754++ &max[0], &max[1], &max[2], &max[3],
755++ &max[4], &max[5], &max[6], &max[7]);
756++
757++ if (count == 8 || count == 16) {
758++
759++ int i;
760++
761++ for (i = 0; i < 8; i++) {
762++ min_address[i] = htons((u16) min[i]);
763++ max_address[i] = htons((u16) max[i]);
764++ }
765++
766++ if (count == 8)
767++ memmove(max_address, min_address, sizeof(min_address));
768++ record_type = TMY_TYPE_IPv6;
769++
770++ goto ok;
771++
772++ }
773++
774++ count = sscanf(cp2,
775++ NIPQUAD_FMT "-" NIPQUAD_FMT,
776++ &min[0], &min[1], &min[2], &min[3],
777++ &max[0], &max[1], &max[2], &max[3]);
778++
779++ if (count == 4 || count == 8) {
780++
781++ u32 ip = htonl((((u8) min[0]) << 24) +
782++ (((u8) min[1]) << 16) +
783++ (((u8) min[2]) << 8) +
784++ (u8) min[3]);
785++ *(u32 *) min_address = ip;
786++
787++ if (count == 8)
788++ ip = htonl((((u8) max[0]) << 24) +
789++ (((u8) max[1]) << 16) +
790++ (((u8) max[2]) << 8) +
791++ (u8) max[3]);
792++ *(u32 *) max_address = ip;
793++ record_type = TMY_TYPE_IPv4;
794++
795++ goto ok;
796++
797++ }
798++
799++ if (*cp2 == '@') {
800++
801++ group = tmy_new_address_group(cp2 + 1);
802++ if (!group)
803++ return -ENOMEM;
804++ record_type = TMY_TYPE_ADDRESS_GROUP;
805++
806++ goto ok;
807++ }
808++
809++ goto out;
810++
811++ok: ;
812++ if (strchr(cp1, ' '))
813++ goto out;
814++
815++ count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);
816++ if (count != 1 && count != 2)
817++ goto out;
818++
819++ if (count == 1)
820++ max_port = min_port;
821++
822++ return tmy_add_network_entry(operation, record_type, group,
823++ (u32 *) min_address,
824++ (u32 *) max_address,
825++ min_port, max_port, domain,
826++ cond, is_delete);
827++
828++out: ;
829++ return -EINVAL;
830++}
831++
832++/**
833++ * tmy_network_listen_acl - check permission for listen(2) operation.
834++ * @is_ipv6: is @address an IPv6 address?
835++ * @address: pointer to IPv4/IPv6 address in network byte order.
836++ * @port: TCP or UDP's port number.
837++ *
838++ * Returns zero if permission granted.
839++ * Returns nonzero if permission denied.
840++ */
841++int tmy_network_listen_acl(const bool is_ipv6,
842++ const u8 *address,
843++ const u16 port)
844++{
845++ return tmy_network_entry(is_ipv6,
846++ TMY_NETWORK_ACL_TCP_LISTEN,
847++ (const u32 *) address,
848++ ntohs(port));
849++}
850++
851++/**
852++ * tmy_network_connect_acl - check permission for connect(2) operation.
853++ * @is_ipv6: is @address an IPv6 address?
854++ * @sock_type: socket type (TCP, UDP or IP).
855++ * @address: pointer to IPv4/IPv6 address in network byte order.
856++ * @port: TCP or UDP's port number or IP's protocol number.
857++ *
858++ * Returns zero if permission granted.
859++ * Returns nonzero if permission denied.
860++ */
861++int tmy_network_connect_acl(const bool is_ipv6,
862++ const int sock_type,
863++ const u8 *address,
864++ const u16 port)
865++{
866++ int type;
867++
868++ switch (sock_type) {
869++ case SOCK_STREAM:
870++ type = TMY_NETWORK_ACL_TCP_CONNECT;
871++ break;
872++ case SOCK_DGRAM:
873++ type = TMY_NETWORK_ACL_UDP_CONNECT;
874++ break;
875++ default:
876++ type = TMY_NETWORK_ACL_RAW_CONNECT;
877++ break;
878++ }
879++
880++ return tmy_network_entry(is_ipv6, type,
881++ (const u32 *) address, ntohs(port));
882++}
883++
884++/**
885++ * tmy_network_bind_acl - check permission for bind(2) operation.
886++ * @is_ipv6: is @address an IPv6 address?
887++ * @sock_type: socket type (TCP, UDP or IP).
888++ * @address: pointer to IPv4/IPv6 address in network byte order.
889++ * @port: TCP or UDP's port number or IP's protocol number.
890++ *
891++ * Returns zero if permission granted.
892++ * Returns nonzero if permission denied.
893++ */
894++int tmy_network_bind_acl(const bool is_ipv6,
895++ const int sock_type,
896++ const u8 *address,
897++ const u16 port)
898++{
899++ int type;
900++
901++ switch (sock_type) {
902++ case SOCK_STREAM:
903++ type = TMY_NETWORK_ACL_TCP_BIND;
904++ break;
905++ case SOCK_DGRAM:
906++ type = TMY_NETWORK_ACL_UDP_BIND;
907++ break;
908++ default:
909++ type = TMY_NETWORK_ACL_RAW_BIND;
910++ break;
911++ }
912++
913++ return tmy_network_entry(is_ipv6, type,
914++ (const u32 *) address, ntohs(port));
915++}
916++
917++/**
918++ * tmy_network_sendmsg_acl - check permission for sendmsg(2) operation.
919++ * @is_ipv6: is @address an IPv6 address?
920++ * @sock_type: socket type (UDP or IP).
921++ * @address: pointer to IPv4/IPv6 address in network byte order.
922++ * @port: UDP's port number or IP's protocol number.
923++ *
924++ * Returns zero if permission granted.
925++ * Returns nonzero if permission denied.
926++ */
927++int tmy_network_sendmsg_acl(const bool is_ipv6,
928++ const int sock_type,
929++ const u8 *address,
930++ const u16 port)
931++{
932++ int type;
933++
934++ if (sock_type == SOCK_DGRAM)
935++ type = TMY_NETWORK_ACL_UDP_CONNECT;
936++ else
937++ type = TMY_NETWORK_ACL_RAW_CONNECT;
938++
939++ return tmy_network_entry(is_ipv6, type,
940++ (const u32 *) address, ntohs(port));
941++}
942++
943++/**
944++ * tmy_network_accept_acl - check permission for accept(2) operation.
945++ * @is_ipv6: is @address an IPv6 address?
946++ * @address: pointer to IPv4/IPv6 address in network byte order.
947++ * @port: TCP client's port number.
948++ *
949++ * Returns zero if permission granted.
950++ * Returns nonzero if permission denied.
951++ */
952++int tmy_network_accept_acl(const bool is_ipv6, const u8 *address,
953++ const u16 port)
954++{
955++ return tmy_network_entry(is_ipv6, TMY_NETWORK_ACL_TCP_ACCEPT,
956++ (const u32 *) address, ntohs(port));
957++}
958++
959++/**
960++ * tmy_network_recvmsg_acl - check permission for recvmsg(2) operation.
961++ * @is_ipv6: is @address an IPv6 address?
962++ * @sock_type: socket type (UDP or IP).
963++ * @address: pointer to IPv4/IPv6 address in network byte order.
964++ * @port: UDP's port number or IP's protocol number.
965++ *
966++ * Returns zero if permission granted.
967++ * Returns nonzero if permission denied.
968++ */
969++int tmy_network_recvmsg_acl(const bool is_ipv6, const int sock_type,
970++ const u8 *address, const u16 port)
971++{
972++ return tmy_network_entry(is_ipv6, sock_type == SOCK_DGRAM ?
973++ TMY_NETWORK_ACL_UDP_CONNECT :
974++ TMY_NETWORK_ACL_RAW_CONNECT,
975++ (const u32 *) address, ntohs(port));
976++}
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-condition.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-condition.diff (revision 755)
@@ -0,0 +1,692 @@
1+This patch allows administrators use conditional permission.
2+TOMOYO Linux supports conditional permission based on
3+process's UID,GID etc. and/or requested pathname's UID/GID.
4+
5+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
6+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
7+ security/tomoyo/condition.c | 680 ++++++++++++++++++++++++++++++++++++++++++++
8+ 1 file changed, 680 insertions(+)
9+
10+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
11++++ linux-2.6.23/security/tomoyo/condition.c 2007-11-02 13:48:04.000000000 +0900
12+@@ -0,0 +1,680 @@
13++/*
14++ * security/tomoyo/condition.c
15++ *
16++ * Functions to support conditional access control for TOMOYO Linux.
17++ */
18++
19++#include "tomoyo.h"
20++#include "realpath.h"
21++
22++/**
23++ * tmy_find_condition_part - check whether a line contains condition part.
24++ * @data: a line to check.
25++ *
26++ * Returns pointer to condition part if found.
27++ * Returns NULL if not found.
28++ *
29++ * Since the trailing spaces are removed by tmy_normalize_line(),
30++ * the last "\040if\040" sequence corresponds to condition part.
31++ */
32++char *tmy_find_condition_part(char *data)
33++{
34++ char *cp = strstr(data, " if ");
35++ if (cp) {
36++ char *cp2;
37++ while ((cp2 = strstr(cp + 3, " if ")) != NULL)
38++ cp = cp2;
39++ *cp++ = '\0';
40++ }
41++ return cp;
42++}
43++
44++#define VALUE_TYPE_DECIMAL 1 /* 01 */
45++#define VALUE_TYPE_OCTAL 2 /* 10 */
46++#define VALUE_TYPE_HEXADECIMAL 3 /* 11 */
47++
48++static int tmy_parse_ulong(unsigned long *result, const char **str)
49++{
50++ const char *cp = *str;
51++ char *ep;
52++ int base = 10;
53++ if (*cp == '0') {
54++ char c = *(cp + 1);
55++ if (c == 'x' || c == 'X') {
56++ base = 16; cp += 2;
57++ } else if (c >= '0' && c <= '7') {
58++ base = 8; cp++;
59++ }
60++ }
61++ *result = simple_strtoul(cp, &ep, base);
62++ if (cp == ep) return 0; /* 00 */
63++ *str = ep;
64++ return (base == 16 ? VALUE_TYPE_HEXADECIMAL :
65++ (base == 8 ? VALUE_TYPE_OCTAL : VALUE_TYPE_DECIMAL));
66++}
67++
68++static void tmy_print_ulong(char *buffer, const int buffer_len,
69++ const unsigned long value, const int type)
70++{
71++ if (type == VALUE_TYPE_DECIMAL)
72++ snprintf(buffer, buffer_len, "%lu", value);
73++ else if (type == VALUE_TYPE_OCTAL)
74++ snprintf(buffer, buffer_len, "0%lo", value);
75++ else
76++ snprintf(buffer, buffer_len, "0x%lX", value);
77++}
78++
79++/* List of conditins. */
80++static struct condition_list {
81++ struct condition_list *next;
82++ int length;
83++ /* "unsigned long condition[length]" comes here.*/
84++} head;
85++
86++#define TASK_UID 0
87++#define TASK_EUID 1
88++#define TASK_SUID 2
89++#define TASK_FSUID 3
90++#define TASK_GID 4
91++#define TASK_EGID 5
92++#define TASK_SGID 6
93++#define TASK_FSGID 7
94++#define TASK_PID 8
95++#define TASK_PPID 9
96++#define PATH1_UID 10
97++#define PATH1_GID 11
98++#define PATH1_INO 12
99++#define PATH1_PARENT_UID 13
100++#define PATH1_PARENT_GID 14
101++#define PATH1_PARENT_INO 15
102++#define PATH2_PARENT_UID 16
103++#define PATH2_PARENT_GID 17
104++#define PATH2_PARENT_INO 18
105++#define MAX_KEYWORD 19
106++
107++static struct {
108++ const char *keyword;
109++ const int keyword_len; /* strlen(keyword) */
110++} cc_keyword[MAX_KEYWORD] = {
111++ [TASK_UID] = { "task.uid", 8 },
112++ [TASK_EUID] = { "task.euid", 9 },
113++ [TASK_SUID] = { "task.suid", 9 },
114++ [TASK_FSUID] = { "task.fsuid", 10 },
115++ [TASK_GID] = { "task.gid", 8 },
116++ [TASK_EGID] = { "task.egid", 9 },
117++ [TASK_SGID] = { "task.sgid", 9 },
118++ [TASK_FSGID] = { "task.fsgid", 10 },
119++ [TASK_PID] = { "task.pid", 8 },
120++ [TASK_PPID] = { "task.ppid", 9 },
121++ [PATH1_UID] = { "path1.uid", 9 },
122++ [PATH1_GID] = { "path1.gid", 9 },
123++ [PATH1_INO] = { "path1.ino", 9 },
124++ [PATH1_PARENT_UID] = { "path1.parent.uid", 16 },
125++ [PATH1_PARENT_GID] = { "path1.parent.gid", 16 },
126++ [PATH1_PARENT_INO] = { "path1.parent.ino", 16 },
127++ [PATH2_PARENT_UID] = { "path2.parent.uid", 16 },
128++ [PATH2_PARENT_GID] = { "path2.parent.gid", 16 },
129++ [PATH2_PARENT_INO] = { "path2.parent.ino", 16 }
130++};
131++
132++/**
133++ * tmy_assign_condition - create condition part.
134++ * @condition: pointer to condition part.
135++ *
136++ * Returns pointer to "struct condition_list" on success.
137++ * Returns NULL on failure.
138++ */
139++const struct condition_list *tmy_assign_condition(const char *condition)
140++{
141++ const char *start;
142++ struct condition_list *ptr;
143++ struct condition_list *new_ptr;
144++ unsigned long *ptr2;
145++ int counter = 0;
146++ int size;
147++ int left;
148++ int right;
149++ unsigned long left_min = 0;
150++ unsigned long left_max = 0;
151++ unsigned long right_min = 0;
152++ unsigned long right_max = 0;
153++ if (strncmp(condition, "if ", 3))
154++ return NULL;
155++ condition += 3;
156++ start = condition;
157++ while (*condition) {
158++ if (*condition == ' ')
159++ condition++;
160++ for (left = 0; left < MAX_KEYWORD; left++) {
161++ if (strncmp(condition, cc_keyword[left].keyword,
162++ cc_keyword[left].keyword_len))
163++ continue;
164++ condition += cc_keyword[left].keyword_len;
165++ break;
166++ }
167++ if (left == MAX_KEYWORD) {
168++ if (!tmy_parse_ulong(&left_min, &condition))
169++ goto out;
170++ counter++; /* body */
171++ if (*condition != '-')
172++ goto not_range1;
173++ condition++;
174++ if (!tmy_parse_ulong(&left_max, &condition)
175++ || left_min > left_max)
176++ goto out;
177++ counter++; /* body */
178++not_range1: ;
179++ }
180++ if (strncmp(condition, "!=", 2) == 0)
181++ condition += 2;
182++ else if (*condition == '=')
183++ condition++;
184++ else
185++ goto out;
186++ counter++; /* header */
187++ for (right = 0; right < MAX_KEYWORD; right++) {
188++ if (strncmp(condition, cc_keyword[right].keyword,
189++ cc_keyword[right].keyword_len))
190++ continue;
191++ condition += cc_keyword[right].keyword_len;
192++ break;
193++ }
194++ if (right == MAX_KEYWORD) {
195++ if (!tmy_parse_ulong(&right_min, &condition))
196++ goto out;
197++ counter++; /* body */
198++ if (*condition != '-')
199++ goto not_range2;
200++ condition++;
201++ if (!tmy_parse_ulong(&right_max, &condition)
202++ || right_min > right_max)
203++ goto out;
204++ counter++; /* body */
205++not_range2: ;
206++ }
207++ }
208++ size = sizeof(*new_ptr) + counter * sizeof(unsigned long);
209++ new_ptr = tmy_alloc(size);
210++ if (!new_ptr)
211++ return NULL;
212++ new_ptr->length = counter;
213++ ptr2 = (unsigned long *) (((u8 *) new_ptr) + sizeof(*new_ptr));
214++ condition = start;
215++ while (*condition) {
216++ unsigned int match = 0;
217++ if (*condition == ' ')
218++ condition++;
219++ for (left = 0; left < MAX_KEYWORD; left++) {
220++ if (strncmp(condition, cc_keyword[left].keyword,
221++ cc_keyword[left].keyword_len))
222++ continue;
223++ condition += cc_keyword[left].keyword_len;
224++ break;
225++ }
226++ if (left == MAX_KEYWORD) {
227++ match |= tmy_parse_ulong(&left_min, &condition) << 2;
228++ counter--; /* body */
229++ if (*condition != '-')
230++ goto not_range3;
231++ condition++;
232++ match |= tmy_parse_ulong(&left_max, &condition) << 4;
233++ counter--; /* body */
234++ left++;
235++not_range3: ;
236++ }
237++ if (strncmp(condition, "!=", 2) == 0)
238++ condition += 2;
239++ else if (*condition == '=') {
240++ match |= 1; condition++;
241++ } else
242++ goto out2;
243++ counter--; /* header */
244++ for (right = 0; right < MAX_KEYWORD; right++) {
245++ if (strncmp(condition, cc_keyword[right].keyword,
246++ cc_keyword[right].keyword_len))
247++ continue;
248++ condition += cc_keyword[right].keyword_len;
249++ break;
250++ }
251++ if (right == MAX_KEYWORD) {
252++ match |= tmy_parse_ulong(&right_min, &condition) << 6;
253++ counter--; /* body */
254++ if (*condition != '-')
255++ goto not_range4;
256++ condition++;
257++ match |= tmy_parse_ulong(&right_max, &condition) << 8;
258++ counter--; /* body */
259++ right++;
260++not_range4: ;
261++ }
262++ if (counter < 0)
263++ goto out2;
264++ *ptr2++ = (match << 16) | (left << 8) | right;
265++ if (left >= MAX_KEYWORD)
266++ *ptr2++ = left_min;
267++ if (left == MAX_KEYWORD + 1)
268++ *ptr2++ = left_max;
269++ if (right >= MAX_KEYWORD)
270++ *ptr2++ = right_min;
271++ if (right == MAX_KEYWORD + 1)
272++ *ptr2++ = right_max;
273++ }
274++ {
275++ static DEFINE_MUTEX(mutex);
276++ struct condition_list *prev = NULL;
277++ mutex_lock(&mutex);
278++ for (ptr = &head; ptr; prev = ptr, ptr = ptr->next) {
279++ /* Don't compare if size differs. */
280++ if (ptr->length != new_ptr->length)
281++ continue;
282++ /*
283++ * Compare ptr and new_ptr
284++ * except ptr->next and new_ptr->next .
285++ */
286++ if (memcmp(((u8 *) ptr) + sizeof(ptr->next),
287++ ((u8 *) new_ptr) + sizeof(new_ptr->next),
288++ size - sizeof(ptr->next)))
289++ continue;
290++ /* Same entry found. Share this entry. */
291++ tmy_free(new_ptr);
292++ new_ptr = ptr;
293++ goto ok;
294++ }
295++ /* Same entry not found. Save this entry. */
296++ ptr = tmy_alloc_element(size);
297++ if (ptr)
298++ memmove(ptr, new_ptr, size);
299++ tmy_free(new_ptr);
300++ new_ptr = ptr;
301++ /* Append to chain. */
302++ prev->next = new_ptr;
303++ok: ;
304++ mutex_unlock(&mutex);
305++ }
306++ return new_ptr;
307++out2: ;
308++ tmy_free(new_ptr);
309++out: ;
310++ return NULL;
311++}
312++
313++/* Get inode's attribute information. */
314++static void tmy_get_attributes(struct obj_info *obj)
315++{
316++ struct vfsmount *mnt;
317++ struct dentry *dentry;
318++ struct inode *inode;
319++ struct kstat stat;
320++
321++ mnt = obj->path1_vfsmnt;
322++ dentry = obj->path1_dentry;
323++ inode = dentry->d_inode;
324++ if (inode) {
325++ if (!inode->i_op || vfs_getattr(mnt, dentry, &stat)) {
326++ /* Nothing to do. */
327++ } else {
328++ obj->path1_stat.uid = stat.uid;
329++ obj->path1_stat.gid = stat.gid;
330++ obj->path1_stat.ino = stat.ino;
331++ obj->path1_valid = 1;
332++ }
333++ }
334++
335++ dentry = dget_parent(obj->path1_dentry);
336++ inode = dentry->d_inode;
337++ if (inode) {
338++ if (!inode->i_op || vfs_getattr(mnt, dentry, &stat)) {
339++ /* Nothing to do. */
340++ } else {
341++ obj->path1_parent_stat.uid = stat.uid;
342++ obj->path1_parent_stat.gid = stat.gid;
343++ obj->path1_parent_stat.ino = stat.ino;
344++ obj->path1_parent_valid = 1;
345++ }
346++ }
347++ dput(dentry);
348++
349++ mnt = obj->path2_vfsmnt;
350++ if (mnt) {
351++ dentry = dget_parent(obj->path2_dentry);
352++ inode = dentry->d_inode;
353++ if (inode) {
354++ if (!inode->i_op || vfs_getattr(mnt, dentry, &stat)) {
355++ /* Nothing to do. */
356++ } else {
357++ obj->path2_parent_stat.uid = stat.uid;
358++ obj->path2_parent_stat.gid = stat.gid;
359++ obj->path2_parent_stat.ino = stat.ino;
360++ obj->path2_parent_valid = 1;
361++ }
362++ }
363++ dput(dentry);
364++ }
365++}
366++
367++/**
368++ * tmy_check_condition - check condition part.
369++ * @ptr: pointer to "struct condition_list".
370++ * @obj: pointer to "struct obj_info". May be NULL.
371++ *
372++ * Returns zero on success.
373++ * Returns nonzero on failure.
374++ */
375++int tmy_check_condition(const struct condition_list *ptr, struct obj_info *obj)
376++{
377++ struct task_struct *task = current;
378++ int i;
379++ unsigned long left_min = 0;
380++ unsigned long left_max = 0;
381++ unsigned long right_min = 0;
382++ unsigned long right_max = 0;
383++ const unsigned long *ptr2;
384++ if (!ptr)
385++ return 0;
386++ ptr2 = (unsigned long *) (((u8 *) ptr) + sizeof(*ptr));
387++ for (i = 0; i < ptr->length; i++) {
388++ const bool match = ((*ptr2) >> 16) & 1;
389++ const u8 left = (*ptr2) >> 8;
390++ const u8 right = *ptr2;
391++ ptr2++;
392++ if ((left >= PATH1_UID && left < MAX_KEYWORD)
393++ || (right >= PATH1_UID && right < MAX_KEYWORD)) {
394++ if (!obj)
395++ goto out;
396++ if (!obj->validate_done) {
397++ tmy_get_attributes(obj);
398++ obj->validate_done = 1;
399++ }
400++ }
401++ switch (left) {
402++ case TASK_UID:
403++ left_min = task->uid;
404++ left_max = left_min;
405++ break;
406++ case TASK_EUID:
407++ left_min = task->euid;
408++ left_max = left_min;
409++ break;
410++ case TASK_SUID:
411++ left_min = task->suid;
412++ left_max = left_min;
413++ break;
414++ case TASK_FSUID:
415++ left_min = task->fsuid;
416++ left_max = left_min;
417++ break;
418++ case TASK_GID:
419++ left_min = task->gid;
420++ left_max = left_min;
421++ break;
422++ case TASK_EGID:
423++ left_min = task->egid;
424++ left_max = left_min;
425++ break;
426++ case TASK_SGID:
427++ left_min = task->sgid;
428++ left_max = left_min;
429++ break;
430++ case TASK_FSGID:
431++ left_min = task->fsgid;
432++ left_max = left_min;
433++ break;
434++ case TASK_PID:
435++ left_min = task->pid;
436++ left_max = left_min;
437++ break;
438++ case TASK_PPID:
439++ left_min = sys_getppid();
440++ left_max = left_min;
441++ break;
442++ case PATH1_UID:
443++ if (!obj->path1_valid)
444++ goto out;
445++ left_min = obj->path1_stat.uid;
446++ left_max = left_min;
447++ break;
448++ case PATH1_GID:
449++ if (!obj->path1_valid)
450++ goto out;
451++ left_min = obj->path1_stat.gid;
452++ left_max = left_min;
453++ break;
454++ case PATH1_INO:
455++ if (!obj->path1_valid)
456++ goto out;
457++ left_min = obj->path1_stat.ino;
458++ left_max = left_min;
459++ break;
460++ case PATH1_PARENT_UID:
461++ if (!obj->path1_parent_valid)
462++ goto out;
463++ left_min = obj->path1_parent_stat.uid;
464++ left_max = left_min;
465++ break;
466++ case PATH1_PARENT_GID:
467++ if (!obj->path1_parent_valid)
468++ goto out;
469++ left_min = obj->path1_parent_stat.gid;
470++ left_max = left_min;
471++ break;
472++ case PATH1_PARENT_INO:
473++ if (!obj->path1_parent_valid)
474++ goto out;
475++ left_min = obj->path1_parent_stat.ino;
476++ left_max = left_min;
477++ break;
478++ case PATH2_PARENT_UID:
479++ if (!obj->path2_parent_valid)
480++ goto out;
481++ left_min = obj->path2_parent_stat.uid;
482++ left_max = left_min;
483++ break;
484++ case PATH2_PARENT_GID:
485++ if (!obj->path2_parent_valid)
486++ goto out;
487++ left_min = obj->path2_parent_stat.gid;
488++ left_max = left_min;
489++ break;
490++ case PATH2_PARENT_INO:
491++ if (!obj->path2_parent_valid)
492++ goto out;
493++ left_min = obj->path2_parent_stat.ino;
494++ left_max = left_min;
495++ break;
496++ case MAX_KEYWORD:
497++ left_min = *ptr2++;
498++ left_max = left_min;
499++ i++;
500++ break;
501++ case MAX_KEYWORD + 1:
502++ left_min = *ptr2++;
503++ left_max = *ptr2++;
504++ i += 2;
505++ break;
506++ }
507++ switch (right) {
508++ case TASK_UID:
509++ right_min = task->uid;
510++ right_max = right_min;
511++ break;
512++ case TASK_EUID:
513++ right_min = task->euid;
514++ right_max = right_min;
515++ break;
516++ case TASK_SUID:
517++ right_min = task->suid;
518++ right_max = right_min;
519++ break;
520++ case TASK_FSUID:
521++ right_min = task->fsuid;
522++ right_max = right_min;
523++ break;
524++ case TASK_GID:
525++ right_min = task->gid;
526++ right_max = right_min;
527++ break;
528++ case TASK_EGID:
529++ right_min = task->egid;
530++ right_max = right_min;
531++ break;
532++ case TASK_SGID:
533++ right_min = task->sgid;
534++ right_max = right_min;
535++ break;
536++ case TASK_FSGID:
537++ right_min = task->fsgid;
538++ right_max = right_min;
539++ break;
540++ case TASK_PID:
541++ right_min = task->pid;
542++ right_max = right_min;
543++ break;
544++ case TASK_PPID:
545++ right_min = sys_getppid();
546++ right_max = right_min;
547++ break;
548++ case PATH1_UID:
549++ if (!obj->path1_valid)
550++ goto out;
551++ right_min = obj->path1_stat.uid;
552++ right_max = right_min;
553++ break;
554++ case PATH1_GID:
555++ if (!obj->path1_valid)
556++ goto out;
557++ right_min = obj->path1_stat.gid;
558++ right_max = right_min;
559++ break;
560++ case PATH1_INO:
561++ if (!obj->path1_valid)
562++ goto out;
563++ right_min = obj->path1_stat.ino;
564++ right_max = right_min;
565++ break;
566++ case PATH1_PARENT_UID:
567++ if (!obj->path1_parent_valid)
568++ goto out;
569++ right_min = obj->path1_parent_stat.uid;
570++ right_max = right_min;
571++ break;
572++ case PATH1_PARENT_GID:
573++ if (!obj->path1_parent_valid)
574++ goto out;
575++ right_min = obj->path1_parent_stat.gid;
576++ right_max = right_min;
577++ break;
578++ case PATH1_PARENT_INO:
579++ if (!obj->path1_parent_valid)
580++ goto out;
581++ right_min = obj->path1_parent_stat.ino;
582++ right_max = right_min;
583++ break;
584++ case PATH2_PARENT_UID:
585++ if (!obj->path2_parent_valid)
586++ goto out;
587++ right_min = obj->path2_parent_stat.uid;
588++ right_max = right_min;
589++ break;
590++ case PATH2_PARENT_GID:
591++ if (!obj->path2_parent_valid)
592++ goto out;
593++ right_min = obj->path2_parent_stat.gid;
594++ right_max = right_min;
595++ break;
596++ case PATH2_PARENT_INO:
597++ if (!obj->path2_parent_valid)
598++ goto out;
599++ right_min = obj->path2_parent_stat.ino;
600++ right_max = right_min;
601++ break;
602++ case MAX_KEYWORD:
603++ right_min = *ptr2++;
604++ right_max = right_min;
605++ i++;
606++ break;
607++ case MAX_KEYWORD + 1:
608++ right_min = *ptr2++;
609++ right_max = *ptr2++;
610++ i += 2;
611++ break;
612++ }
613++ if (match) {
614++ if (left_min <= right_max && left_max >= right_min)
615++ continue;
616++ } else {
617++ if (left_min > right_max || left_max < right_min)
618++ continue;
619++ }
620++out: ;
621++ return -EPERM;
622++ }
623++ return 0;
624++}
625++
626++/**
627++ * tmy_dump_condition - dump condition part.
628++ * @head: pointer to "struct io_buffer".
629++ * @ptr: pointer to "struct condition_list". May be NULL.
630++ *
631++ * Returns nonzero if reading incomplete.
632++ * Returns zero otherwise.
633++ */
634++int tmy_dump_condition(struct io_buffer *head, const struct condition_list *ptr)
635++{
636++ int i;
637++ const unsigned long *ptr2;
638++ char buffer[32];
639++ if (!ptr)
640++ goto last;
641++ ptr2 = (unsigned long *) (((u8 *) ptr) + sizeof(*ptr));
642++ memset(buffer, 0, sizeof(buffer));
643++ for (i = 0; i < ptr->length; i++) {
644++ const u16 match = (*ptr2) >> 16;
645++ const u8 left = (*ptr2) >> 8;
646++ const u8 right = *ptr2;
647++ ptr2++;
648++ if (tmy_io_printf(head, "%s", i ? " " : " if "))
649++ break;
650++ if (left < MAX_KEYWORD) {
651++ if (tmy_io_printf(head, "%s", cc_keyword[left].keyword))
652++ break;
653++ } else {
654++ tmy_print_ulong(buffer, sizeof(buffer) - 1, *ptr2++,
655++ (match >> 2) & 3);
656++ if (tmy_io_printf(head, "%s", buffer))
657++ break;
658++ i++;
659++ if (left == MAX_KEYWORD + 1) {
660++ tmy_print_ulong(buffer, sizeof(buffer) - 1,
661++ *ptr2++, (match >> 4) & 3);
662++ if (tmy_io_printf(head, "-%s", buffer))
663++ break;
664++ i++;
665++ }
666++ }
667++ if (tmy_io_printf(head, "%s", (match & 1) ? "=" : "!="))
668++ break;
669++ if (right < MAX_KEYWORD) {
670++ if (tmy_io_printf(head, "%s",
671++ cc_keyword[right].keyword))
672++ break;
673++ } else {
674++ tmy_print_ulong(buffer, sizeof(buffer) - 1, *ptr2++,
675++ (match >> 6) & 3);
676++ if (tmy_io_printf(head, "%s", buffer))
677++ break;
678++ i++;
679++ if (right == MAX_KEYWORD + 1) {
680++ tmy_print_ulong(buffer, sizeof(buffer) - 1,
681++ *ptr2++, (match >> 8) & 3);
682++ if (tmy_io_printf(head, "-%s", buffer))
683++ break;
684++ i++;
685++ }
686++ }
687++ }
688++ if (i < ptr->length)
689++ return -ENOMEM;
690++last: ;
691++ return tmy_io_printf(head, "\n") ? -ENOMEM : 0;
692++}
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-common.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-common.diff (revision 755)
@@ -0,0 +1,2456 @@
1+Common functions for TOMOYO Linux.
2+
3+TOMOYO Linux uses /sys/kernel/security/tomoyo interface for configuration.
4+
5+/sys/kernel/security/tomoyo/domain_policy is the domain-based access policy.
6+Access control list for files, networks, argv[0], capabilities and signal is
7+stored in domain_policy.
8+
9+/sys/kernel/security/tomoyo/system_policy is the system-wide access policy.
10+Access control list for mount, umount and pivot_root is
11+stored in system_policy.
12+
13+/sys/kernel/security/tomoyo/exception_policy is the other settings such as
14+globally readable files, domain transition configurations
15+or pre-defined patterned pathnames.
16+
17+/sys/kernel/security/tomoyo/profile has some profiles, which configure
18+the access control level of TOMOYO Linux. A profile is assigned to a domain.
19+
20+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
21+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
22+ security/tomoyo/common.c | 2429 +++++++++++++++++++++++++++++++++++++++++++++++
23+ 1 file changed, 2429 insertions(+)
24+
25+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
26++++ linux-2.6.23/security/tomoyo/common.c 2007-11-21 09:31:43.462446264 +0900
27+@@ -0,0 +1,2429 @@
28++/*
29++ * security/tomoyo/common.c
30++ *
31++ * Common functions for TOMOYO Linux.
32++ */
33++
34++#include "tomoyo.h"
35++#include "realpath.h"
36++
37++#define MAX_ACCEPT_ENTRY 2048
38++
39++static int tmy_read_control(struct file *file,
40++ char __user *buffer,
41++ const int buffer_len);
42++
43++/************************* VARIABLES *************************/
44++
45++/* /sbin/init started? */
46++bool sbin_init_started;
47++
48++static struct {
49++ const char *keyword;
50++ unsigned int current_value;
51++ const unsigned int max_value;
52++} tmy_control[TMY_MAX_CONTROL_INDEX] = {
53++ [TMY_COMMENT] = { "COMMENT", 0, 0 },
54++ [TMY_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
55++ [TMY_MAC_FOR_ARGV0] = { "MAC_FOR_ARGV0", 0, 3 },
56++ [TMY_MAC_FOR_NETWORK] = { "MAC_FOR_NETWORK", 0, 3 },
57++ [TMY_MAC_FOR_SIGNAL] = { "MAC_FOR_SIGNAL", 0, 3 },
58++ [TMY_DENY_CONCEAL_MOUNT] = { "DENY_CONCEAL_MOUNT", 0, 3 },
59++ [TMY_RESTRICT_MOUNT] = { "RESTRICT_MOUNT", 0, 3 },
60++ [TMY_RESTRICT_UMOUNT] = { "RESTRICT_UNMOUNT", 0, 3 },
61++ [TMY_RESTRICT_PIVOT_ROOT] = { "RESTRICT_PIVOT_ROOT", 0, 3 },
62++ [TMY_MAX_ACCEPT_ENTRY] =
63++ { "MAX_ACCEPT_ENTRY", MAX_ACCEPT_ENTRY, INT_MAX },
64++ [TMY_MAX_GRANT_LOG] = { "MAX_GRANT_LOG", 1024, INT_MAX },
65++ [TMY_MAX_REJECT_LOG] = { "MAX_REJECT_LOG", 1024, INT_MAX },
66++ [TMY_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
67++ [TMY_ALLOW_ENFORCE_GRACE] = { "ALLOW_ENFORCE_GRACE", 0, 1 },
68++};
69++
70++struct profile {
71++ unsigned int value[TMY_MAX_CONTROL_INDEX];
72++ const struct path_info *comment;
73++};
74++
75++static struct profile *profile_ptr[TMY_MAX_PROFILES];
76++
77++/************************* UTILITY FUNCTIONS *************************/
78++
79++/* Is the current process running as root? */
80++static int tmy_is_root(void)
81++{
82++ return !current->uid && !current->euid;
83++}
84++
85++/**
86++ * tmy_normalize_line - make a line tidy.
87++ * @buffer: the line to make tidy.
88++ *
89++ * All tokens (such as pathnames) used in TOMOYO Linux contains
90++ * only ASCII printable (i.e. 0x21-0x7E) range characters.
91++ * This allows policy files and auditing logs split monotonically
92++ * using space (i.e. ' ') and new line (i.e. '\n') characters.
93++ *
94++ * Remove leading and trailing non ASCII printable chracters and
95++ * replace one or more non ASCII printable chracters with single space.
96++ */
97++static void tmy_normalize_line(unsigned char *buffer)
98++{
99++ unsigned char *sp = buffer;
100++ unsigned char *dp = buffer;
101++ int first = 1;
102++
103++ while (*sp && (*sp <= 0x20 || *sp >= 0x7F))
104++ sp++;
105++
106++ while (*sp) {
107++ if (!first)
108++ *dp++ = ' ';
109++ first = 0;
110++ while (*sp > 0x20 && *sp < 0x7F)
111++ *dp++ = *sp++;
112++ while (*sp && (*sp <= 0x20 || *sp >= 0x7F))
113++ sp++;
114++ }
115++
116++ *dp = '\0';
117++}
118++
119++/* Is @c the first letter of "\ooo" expression? */
120++static int tmy_char_is_0to3(const unsigned char c)
121++{
122++ return c >= '0' && c <= '3';
123++}
124++
125++/* Is @c the second or third letter of "\ooo" expression? */
126++static int tmy_char_is_0to7(const unsigned char c)
127++{
128++ return c >= '0' && c <= '7';
129++}
130++
131++/* Is @c a decimal letter? */
132++static int tmy_char_is_0to9(const unsigned char c)
133++{
134++ return c >= '0' && c <= '9';
135++}
136++
137++/* Is @c a hexadecimal letter? */
138++static int tmy_char_is_hex(const unsigned char c)
139++{
140++ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
141++ || (c >= 'a' && c <= 'f');
142++}
143++
144++/* Is @c an alphabet letter? */
145++static int tmy_char_is_alpha(const unsigned char c)
146++{
147++ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
148++}
149++
150++/* Convert \ooo style expression to a byte. */
151++static unsigned char tmy_str2chr(const unsigned char c,
152++ const unsigned char d,
153++ const unsigned char e)
154++{
155++ return (((unsigned char) (c - '0')) << 6) +
156++ (((unsigned char) (d - '0')) << 3) +
157++ (((unsigned char) (e - '0')));
158++}
159++
160++/* Does the @src starts with @find? */
161++static int tmy_strstarts(char **src, const char *find)
162++{
163++ const int len = strlen(find);
164++ char *tmp = *src;
165++
166++ if (strncmp(tmp, find, len) == 0) {
167++ tmp += len;
168++ *src = tmp;
169++ return 1;
170++ }
171++
172++ return 0;
173++}
174++
175++/**
176++ * tmy_correct_path - validate a pathname.
177++ * @filename: the pathname to check
178++ * @start_type: 1 if the pathname must start with '/'
179++ * -1 if the pathname must not start with '/'
180++ * 0 if it does not matter
181++ * @pattern_type: 1 if the pathname must contain patterns
182++ * -1 if the pathname must not contain patterns
183++ * 0 if it does not matter
184++ * @end_type: 1 if the pathname must end with '/'
185++ * -1 if the pathname must not end with '/'
186++ * 0 if it does not matter
187++ * @function: string to display if the @filename is invalid
188++ *
189++ * Returns true if the pathname is valid.
190++ * Returns false otherwise.
191++ *
192++ * Check whether the given pathname follows the naming rules.
193++ */
194++bool tmy_correct_path(const char *filename,
195++ const int start_type,
196++ const int pattern_type,
197++ const int end_type,
198++ const char *function)
199++{
200++ int contains_pattern = 0;
201++ char c;
202++ char d;
203++ char e;
204++ const char *original_filename = filename;
205++
206++ if (!filename)
207++ goto out;
208++
209++ c = *filename;
210++ if (start_type == 1) { /* Must start with '/' */
211++ if (c != '/')
212++ goto out;
213++ } else if (start_type == -1) { /* Must not start with '/' */
214++ if (c == '/')
215++ goto out;
216++ }
217++
218++ if (c)
219++ c = *(strchr(filename, '\0') - 1);
220++ if (end_type == 1) { /* Must end with '/' */
221++ if (c != '/')
222++ goto out;
223++ } else if (end_type == -1) { /* Must not end with '/' */
224++ if (c == '/')
225++ goto out;
226++ }
227++
228++ while ((c = *filename++) != '\0') {
229++ if (c == '\\') {
230++ unsigned char f;
231++ switch ((c = *filename++)) {
232++ case '\\': /* "\\" */
233++ continue;
234++ case '$': /* "\$" */
235++ case '+': /* "\+" */
236++ case '?': /* "\?" */
237++ case '*': /* "\*" */
238++ case '@': /* "\@" */
239++ case 'x': /* "\x" */
240++ case 'X': /* "\X" */
241++ case 'a': /* "\a" */
242++ case 'A': /* "\A" */
243++ case '-': /* "\-" */
244++ if (pattern_type == -1)
245++ goto out; /* Must not contain pattern */
246++ contains_pattern = 1;
247++ continue;
248++ case '0': /* "\ooo" */
249++ case '1':
250++ case '2':
251++ case '3':
252++ d = *filename++;
253++ if (!tmy_char_is_0to7(d))
254++ goto out;
255++ e = *filename++;
256++ if (!tmy_char_is_0to7(e))
257++ goto out;
258++ f = tmy_str2chr(c, d, e);
259++ if (f && (f <= 0x20 || f >= 0x7F))
260++ /* valid \ooo expression */
261++ continue;
262++ }
263++ goto out;
264++ } else if (c <= 0x20 || c >= 0x7F)
265++ goto out;
266++ }
267++
268++ if (pattern_type == 1) { /* Must contain pattern */
269++ if (!contains_pattern)
270++ goto out;
271++ }
272++
273++ return 1;
274++
275++out: ;
276++ printk(KERN_DEBUG "%s: Invalid pathname '%s'\n",
277++ function, original_filename);
278++ return 0;
279++}
280++
281++/**
282++ * tmy_is_correct_domain - validate a domainname.
283++ * @domainname: the domainname to check.
284++ * @function: string to display if the @domainname is invalid.
285++ *
286++ * Returns true if the domainname is valid.
287++ * Returns false otherwise.
288++ *
289++ * Check whether the given domainname follows the naming rules.
290++ */
291++bool tmy_is_correct_domain(const unsigned char *domainname,
292++ const char *function)
293++{
294++ unsigned char c;
295++ unsigned char d;
296++ unsigned char e;
297++ const char *org_domainname = domainname;
298++
299++ if (!domainname || !tmy_strstarts((char **) &domainname, TMY_ROOT_NAME))
300++ goto out;
301++
302++ if (!*domainname)
303++ return 1;
304++
305++ do {
306++ /* 0x20 is a domainname separator. */
307++ if (*domainname++ != ' ')
308++ goto out;
309++ /* Must starts with '/'. */
310++ if (*domainname++ != '/')
311++ goto out;
312++ while ((c = *domainname) != '\0' && c != ' ') {
313++ domainname++;
314++ if (c == '\\') {
315++ unsigned char f;
316++ switch ((c = *domainname++)) {
317++ case '\\': /* "\\" */
318++ continue;
319++ case '0': /* "\ooo" */
320++ case '1':
321++ case '2':
322++ case '3':
323++ d = *domainname++;
324++ if (!tmy_char_is_0to7(d))
325++ goto out;
326++ e = *domainname++;
327++ if (!tmy_char_is_0to7(e))
328++ goto out;
329++ f = tmy_str2chr(c, d, e);
330++ if (f && (f <= 0x20 || f >= 0x7F))
331++ continue;
332++ }
333++ goto out;
334++ } else if (c < 0x20 || c >= 0x7F)
335++ /* 0x20 is a domainname separator. */
336++ goto out;
337++ }
338++ } while (*domainname);
339++
340++ return 1;
341++
342++out: ;
343++ printk(KERN_DEBUG "%s: Invalid domainname '%s'\n",
344++ function, org_domainname);
345++ return 0;
346++}
347++
348++/**
349++ * tmy_path_depth - evaluate the number of '/' characters in a token.
350++ * @pathname: the token to evaluate.
351++ *
352++ * Each '/' character but the trailing '/' scores 2.
353++ * The trailing '/' scores 1.
354++ *
355++ * If @pathname ends with '/', the return value is an odd integer.
356++ * If @pathname does not end with '/', the return value is an even integer.
357++ */
358++static int tmy_path_depth(const char *pathname)
359++{
360++ int i = 0;
361++
362++ if (pathname) {
363++ char *ep = strchr(pathname, '\0');
364++
365++ if (pathname < ep--) {
366++ if (*ep != '/')
367++ i++;
368++ while (pathname <= ep)
369++ if (*ep-- == '/')
370++ i += 2;
371++ }
372++ }
373++
374++ return i;
375++}
376++
377++/**
378++ * tmy_const_part_length - calculate the constant part in a token.
379++ * @filename: the token to calculate.
380++ *
381++ * Returns leading length of @filename that can be compared using strncmp().
382++ */
383++static int tmy_const_part_length(const char *filename)
384++{
385++ int len = 0;
386++
387++ if (filename) {
388++ char c;
389++
390++ while ((c = *filename++) != '\0') {
391++ if (c != '\\') {
392++ len++;
393++ continue;
394++ }
395++ switch (c = *filename++) {
396++ case '\\': /* "\\" */
397++ len += 2;
398++ continue;
399++ case '0': /* "\ooo" */
400++ case '1':
401++ case '2':
402++ case '3':
403++ if (!tmy_char_is_0to7(*filename++))
404++ break;
405++ if (!tmy_char_is_0to7(*filename++))
406++ break;
407++ len += 4;
408++ continue;
409++ }
410++ break;
411++ }
412++ }
413++
414++ return len;
415++}
416++
417++/**
418++ * tmy_fill_path_info - fill "struct path_info" entry.
419++ * @ptr: pointer to "struct path_info".
420++ *
421++ * Caller stores a token in "struct path_info"->name .
422++ * This function will fill rest of "struct path_info" members.
423++ */
424++void tmy_fill_path_info(struct path_info *ptr)
425++{
426++ const char *name = ptr->name;
427++ const int len = strlen(name);
428++ ptr->total_len = len;
429++ ptr->const_len = tmy_const_part_length(name);
430++ ptr->is_dir = len && (name[len - 1] == '/');
431++ ptr->is_patterned = (ptr->const_len < len);
432++ ptr->hash = full_name_hash(name, len);
433++ ptr->depth = tmy_path_depth(name);
434++}
435++
436++/**
437++ * tmy_file_match2 - internal function for tmy_path_match().
438++ * @filename: start address of the token.
439++ * @filename_end: end address of the token.
440++ * @pattern: start address of the pattern.
441++ * @pattern_end: end address of the pattern.
442++ *
443++ * Handle all patterns other than '\-' pattern.
444++ * Returns true if matches.
445++ * Returns false otherwise.
446++ *
447++ * @filename and @pattern do not contain '/'.
448++ * @filename and @pattern are not '\0'-terminated.
449++ * @pattern does not contain '\-'.
450++ */
451++static bool tmy_file_match2(const char *filename,
452++ const char *filename_end,
453++ const char *pattern,
454++ const char *pattern_end)
455++{
456++ while (filename < filename_end && pattern < pattern_end) {
457++ char c;
458++ int i;
459++ int j;
460++
461++ if (*pattern != '\\') {
462++ if (*filename++ != *pattern++)
463++ goto out;
464++ continue;
465++ }
466++
467++ c = *filename;
468++ pattern++;
469++
470++ switch (*pattern) {
471++ case '?':
472++ if (c == '/')
473++ goto out;
474++ if (c != '\\')
475++ break;
476++ /* filename[0] != '\0' */
477++ c = filename[1];
478++ if (c == '\\')
479++ filename++;
480++ else if (tmy_char_is_0to3(c) &&
481++ /* filename[1] != '\0' */
482++ tmy_char_is_0to7(filename[2]) &&
483++ /* filename[2] != '\0' */
484++ tmy_char_is_0to7(filename[3]))
485++ /* filename[3] != '\0' */
486++ filename += 3;
487++ /*
488++ * Why not "filename += 4;" here
489++ * because it processed 4 (i.e. "\ooo") bytes?
490++ * - Because "filename++;" is done
491++ * after "break;".
492++ */
493++ else
494++ goto out;
495++ break;
496++ case '\\':
497++ if (c != '\\')
498++ goto out;
499++ /* filename[0] != '\0' */
500++ if (*++filename != '\\')
501++ goto out;
502++ break;
503++ case '+':
504++ if (!tmy_char_is_0to9(c))
505++ goto out;
506++ break;
507++ case 'x':
508++ if (!tmy_char_is_hex(c))
509++ goto out;
510++ break;
511++ case 'a':
512++ if (!tmy_char_is_alpha(c))
513++ goto out;
514++ break;
515++ case '0':
516++ case '1':
517++ case '2':
518++ case '3':
519++ if (c != '\\')
520++ goto out;
521++ /* filename[0] != '\0' */
522++ c = filename[1];
523++ if (!tmy_char_is_0to3(c) || c != *pattern)
524++ goto out;
525++ /* filename[1] != '\0' */
526++ c = filename[2];
527++ /* pattern[0] != '\0' */
528++ if (!tmy_char_is_0to7(c) || c != pattern[1])
529++ goto out;
530++ /* filename[2] != '\0' */
531++ c = filename[3];
532++ /* pattern[1] != '\0' */
533++ if (!tmy_char_is_0to7(c) || c != pattern[2])
534++ goto out;
535++ /* filename[3] != '\0' */
536++ filename += 3;
537++ /* pattern[2] != '\0' */
538++ pattern += 2;
539++ break;
540++ case '*':
541++ case '@':
542++ for (i = 0; i <= filename_end - filename; i++) {
543++ if (tmy_file_match2(filename + i,
544++ filename_end,
545++ pattern + 1,
546++ pattern_end))
547++ return 1;
548++ c = filename[i];
549++ if (c == '.' && *pattern == '@')
550++ break;
551++ if (c != '\\')
552++ continue;
553++ /* filename[i] != '\0' */
554++ c = filename[i + 1];
555++ if (c == '\\')
556++ /* filename[i + 1] != '\0' */
557++ i++;
558++ else if (tmy_char_is_0to3(c) &&
559++ /* filename[i + 1] != '\0' */
560++ tmy_char_is_0to7(filename[i + 2]) &&
561++ /* filename[i + 2] != '\0' */
562++ tmy_char_is_0to7(filename[i + 3]))
563++ /* filename[i + 3] != '\0' */
564++ i += 3;
565++ else
566++ break; /* Bad pattern. */
567++ }
568++ goto out;
569++ default:
570++ j = 0;
571++ /*
572++ * If j == 0, for() loop does nothing.
573++ * So I can use while() without checking first letter.
574++ */
575++ c = *pattern;
576++ if (c == '$')
577++ while (tmy_char_is_0to9(filename[j]))
578++ j++;
579++ else if (c == 'X')
580++ while (tmy_char_is_hex(filename[j]))
581++ j++;
582++ else if (c == 'A')
583++ while (tmy_char_is_alpha(filename[j]))
584++ j++;
585++ for (i = 1; i <= j; i++)
586++ if (tmy_file_match2(filename + i,
587++ filename_end,
588++ pattern + 1,
589++ pattern_end))
590++ return 1;
591++ goto out; /* Not matched or bad pattern. */
592++ }
593++ filename++; /* filename[0] != '\0' */
594++ pattern++; /* pattern[0] != '\0' */
595++ }
596++
597++ /* Skip trailing "\*" and "\@" patterns. */
598++ while (*pattern == '\\' &&
599++ (*(pattern + 1) == '*' ||
600++ *(pattern + 1) == '@'))
601++ pattern += 2;
602++
603++ /* If both are at ending position, they are equals. */
604++ return (filename == filename_end && pattern == pattern_end);
605++out: ;
606++ return 0;
607++}
608++
609++/**
610++ * tmy_file_match - internal function for tmy_path_match().
611++ * @filename: start address of the token.
612++ * @filename_end: end address of the token.
613++ * @pattern: start address of the pattern.
614++ * @pattern_end: end address of the pattern.
615++ *
616++ * Handle patterns containing '\-' pattern.
617++ * Returns true if matches.
618++ * Returns false otherwise.
619++ *
620++ * @filename and @pattern do not contain '/'.
621++ * @filename and @pattern are not '\0'-terminated.
622++ */
623++static bool tmy_file_match(const char *filename,
624++ const char *filename_end,
625++ const char *pattern,
626++ const char *pattern_end)
627++{
628++ const char *pattern_start = pattern;
629++ bool first = 1;
630++ bool result;
631++
632++ while (pattern < pattern_end - 1) {
633++ /* Split at "\-" pattern. */
634++ if (*pattern++ != '\\' || *pattern++ != '-')
635++ continue;
636++ result = tmy_file_match2(filename,
637++ filename_end,
638++ pattern_start,
639++ pattern - 2);
640++ /* If before "\-" pattern, invert the result. */
641++ if (first)
642++ result = !result;
643++ /*
644++ * If not matched before first "\-" pattern, return 0.
645++ * If matched after first "\-" pattern, return 0.
646++ */
647++ if (result)
648++ return 0;
649++ first = 0;
650++ pattern_start = pattern;
651++ }
652++
653++ result = tmy_file_match2(filename,
654++ filename_end, pattern_start, pattern_end);
655++ /* If after first "\-" pattern, invert the result. */
656++ return first ? result : !result;
657++}
658++
659++/**
660++ * tmy_path_match - do a pattern matching.
661++ * @pathname0: pointer to a token to compare.
662++ * @pattern0: pointer to a pattern to compare.
663++ *
664++ * Returns true if @pathname0 matches to @pattern0 .
665++ * Returns false otherwise.
666++ *
667++ *
668++ * Check whether the given token matches to the given pattern.
669++ *
670++ * The following patterns are available.
671++ * \\ \ itself.
672++ * \ooo Octal representation of a byte.
673++ * \* More than or equals to 0 character other than '/'.
674++ * \@ More than or equals to 0 character other than '/' or '.'.
675++ * \? 1 byte character other than '/'.
676++ * \$ More than or equals to 1 decimal digit.
677++ * \+ 1 decimal digit.
678++ * \X More than or equals to 1 hexadecimal digit.
679++ * \x 1 hexadecimal digit.
680++ * \A More than or equals to 1 alphabet character.
681++ * \a 1 alphabet character.
682++ * \- Subtraction operator.
683++ */
684++bool tmy_path_match(const struct path_info *pathname0,
685++ const struct path_info *pattern0)
686++{
687++ const char *pathname = pathname0->name;
688++ const char *pattern = pattern0->name;
689++ const int len = pattern0->const_len;
690++
691++ /* If it doesn't contains patterns, I can use tmy_pathcmp() */
692++ if (!pattern0->is_patterned)
693++ return !tmy_pathcmp(pathname0, pattern0);
694++ /* Check the depth of directory. */
695++ if (pathname0->depth != pattern0->depth)
696++ return 0;
697++ /* Use strncmp() for constant part. */
698++ if (strncmp(pathname, pattern, len))
699++ return 0;
700++
701++ pathname += len;
702++ pattern += len;
703++
704++ /* Split at '/' character, and compare. */
705++ while (*pathname && *pattern) {
706++ const char *pathname_delimiter = strchr(pathname, '/');
707++ const char *pattern_delimiter = strchr(pattern, '/');
708++
709++ if (!pathname_delimiter)
710++ pathname_delimiter = strchr(pathname, '\0');
711++ if (!pattern_delimiter)
712++ pattern_delimiter = strchr(pattern, '\0');
713++ if (!tmy_file_match(pathname,
714++ pathname_delimiter,
715++ pattern,
716++ pattern_delimiter))
717++ return 0;
718++
719++ pathname = *pathname_delimiter ?
720++ pathname_delimiter + 1 :
721++ pathname_delimiter;
722++ pattern = *pattern_delimiter ?
723++ pattern_delimiter + 1 :
724++ pattern_delimiter;
725++ }
726++
727++ /* Skip trailing "\*" and "\@" patterns. */
728++ while (*pattern == '\\' &&
729++ (*(pattern + 1) == '*' ||
730++ *(pattern + 1) == '@'))
731++ pattern += 2;
732++
733++ /* If both are at '\0' position, they are equals. */
734++ return (!*pathname && !*pattern);
735++}
736++
737++/**
738++ * tmy_io_printf - transactional printf() for "struct io_buffer".
739++ * @head: pointer to "struct io_buffer".
740++ * @fmt: format strings for printf().
741++ *
742++ * Returns zero on success.
743++ * Returns nonzero otherwise.
744++ *
745++ * Transactional printf() to "struct io_buffer" structure.
746++ * snprintf() will truncate, but tmy_io_printf() won't.
747++ * This is needed because dumping partially truncated tokens
748++ * is not acceptable for TOMOYO Linux.
749++ */
750++int tmy_io_printf(struct io_buffer *head, const char *fmt, ...)
751++{
752++ va_list args;
753++ int len;
754++ int pos = head->read_avail;
755++ int size = head->readbuf_size - pos;
756++
757++ if (size <= 0)
758++ return -ENOMEM;
759++
760++ va_start(args, fmt);
761++ len = vsnprintf(head->read_buf + pos, size, fmt, args);
762++ va_end(args);
763++
764++ if (pos + len >= head->readbuf_size)
765++ return -ENOMEM;
766++
767++ head->read_avail += len;
768++
769++ return 0;
770++}
771++
772++/**
773++ * tmy_get_exe - get realpath of current process.
774++ *
775++ * Returns realpath(3) of current process on success.
776++ * Returns NULL on failure.
777++ *
778++ * This function uses tmy_alloc(), so caller must tmy_free()
779++ * if this function didn't return NULL.
780++ */
781++const char *tmy_get_exe(void)
782++{
783++ struct vm_area_struct *vma;
784++
785++ if (!current->mm)
786++ return NULL;
787++ for (vma = current->mm->mmap; vma; vma = vma->vm_next)
788++ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
789++ return tmy_realpath_dentry(vma->vm_file->f_dentry,
790++ vma->vm_file->f_vfsmnt);
791++
792++ return NULL;
793++}
794++
795++/**
796++ * tmy_lastname - get last part of domainname.
797++ *
798++ * Returns last part of domainname.
799++ */
800++const char *tmy_lastname(const struct domain_info *domain)
801++{
802++ const char *cp0 = domain->domainname->name;
803++ const char *cp1 = strrchr(cp0, ' ');
804++ if (cp1)
805++ return cp1 + 1;
806++ return cp0;
807++}
808++
809++/**
810++ * tmy_get_msg - get message from mode.
811++ * @is_enforce: enforcing flag.
812++ *
813++ * Returns "ERROR" if enforcing, "WARNING" otherwise.
814++ */
815++const char *tmy_getmsg(bool is_enforce)
816++{
817++ return is_enforce ? "ERROR" : "WARNING";
818++}
819++
820++/************************* DOMAIN POLICY HANDLER *************************/
821++
822++/**
823++ * tmy_flags - get flags of given access control.
824++ * @index: index to retrieve flags.
825++ *
826++ * Returns current value of given access control.
827++ */
828++unsigned int tmy_flags(const unsigned int index)
829++{
830++ const u8 profile =
831++ TMY_SECURITY->domain->profile;
832++
833++ /* All operations might sleep. See tmy_supervisor(). */
834++ might_sleep();
835++ if (in_interrupt())
836++ return 0;
837++ return sbin_init_started && index < TMY_MAX_CONTROL_INDEX
838++ && profile_ptr[profile] ?
839++ profile_ptr[profile]->value[index] :
840++ 0;
841++}
842++
843++/**
844++ * tmy_quota - check quota.
845++ *
846++ * Returns true if not quota has not exceeded.
847++ * Returns false otherwise.
848++ *
849++ * This is a safeguard for "learning mode", for appending entries
850++ * without limit dulls the system response and consumes much memory.
851++ */
852++bool tmy_quota(void)
853++{
854++ unsigned int count = 0;
855++ struct acl_info *ptr;
856++ struct domain_info * const domain = TMY_SECURITY->domain;
857++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
858++ if (!ptr->is_deleted)
859++ count++;
860++ }
861++ /* If there are so many entries, don't append any more. */
862++ if (count < tmy_flags(TMY_MAX_ACCEPT_ENTRY))
863++ return 1;
864++ if (!domain->quota_warned) {
865++ domain->quota_warned = 1;
866++ printk(KERN_INFO
867++ "TOMOYO-WARNING: Domain '%s' has so many ACLs "
868++ "to hold. Stopped learning mode.\n",
869++ domain->domainname->name);
870++ }
871++ return 0;
872++}
873++
874++/* Create a new profile. */
875++static struct profile *tmy_find_new_profile(const unsigned int profile)
876++{
877++ static DEFINE_MUTEX(profile_lock);
878++ struct profile *ptr = NULL;
879++
880++ mutex_lock(&profile_lock);
881++
882++ ptr = profile_ptr[profile];
883++ if (profile < TMY_MAX_PROFILES && ptr == NULL) {
884++ ptr = tmy_alloc_element(sizeof(*ptr));
885++ if (ptr != NULL) {
886++ int i;
887++ for (i = 0; i < TMY_MAX_CONTROL_INDEX; i++)
888++ ptr->value[i] = tmy_control[i].current_value;
889++ mb(); /* Instead of using spinlock. */
890++ profile_ptr[profile] = ptr;
891++ }
892++ }
893++
894++ mutex_unlock(&profile_lock);
895++
896++ return ptr;
897++}
898++
899++/* Loading policy done? */
900++static int profile_loaded;
901++
902++/* Update profile values. */
903++static int tmy_set_profile(struct io_buffer *head)
904++{
905++ char *data = head->write_buf;
906++ unsigned int i;
907++ unsigned int value;
908++ char *cp;
909++ struct profile *profile;
910++
911++ if (!tmy_is_root())
912++ return -EPERM;
913++
914++ /* If profile index is not given, assume 0. */
915++ i = simple_strtoul(data, &cp, 10);
916++ if (data != cp) {
917++ if (*cp != '-')
918++ return -EINVAL;
919++ data = cp + 1;
920++ }
921++
922++ profile = tmy_find_new_profile(i);
923++ if (!profile)
924++ return -EINVAL;
925++ cp = strchr(data, '=');
926++ if (!cp)
927++ return -EINVAL;
928++
929++ *cp = '\0';
930++ profile_loaded = 1;
931++ tmy_update_counter(TMY_UPDATE_PROFILE);
932++ if (strcmp(data, tmy_control[TMY_COMMENT].keyword) == 0) {
933++ profile->comment = tmy_save_name(cp + 1);
934++ return 0;
935++ }
936++
937++ if (sscanf(cp + 1, "%u", &value) != 1)
938++ return -EINVAL;
939++
940++ if (tmy_strstarts(&data, TMY_MAC_FOR_CAPABILITY))
941++ return tmy_set_capability_profile(data, value, i);
942++
943++ for (i = 0; i < TMY_MAX_CONTROL_INDEX; i++) {
944++ if (strcmp(data, tmy_control[i].keyword))
945++ continue;
946++ if (value > tmy_control[i].max_value)
947++ value = tmy_control[i].max_value;
948++ profile->value[i] = value;
949++ return 0;
950++ }
951++
952++ return -EINVAL;
953++}
954++
955++/* Read profile values. */
956++static int tmy_read_profile(struct io_buffer *head)
957++{
958++ int step;
959++
960++ if (head->read_eof)
961++ return 0;
962++ if (!tmy_is_root())
963++ return -EPERM;
964++
965++ if (head->read_var1)
966++ goto capability;
967++
968++ for (step = head->read_step;
969++ step < TMY_MAX_PROFILES * TMY_MAX_CONTROL_INDEX;
970++ step++) {
971++ const int i = step / TMY_MAX_CONTROL_INDEX;
972++ const int j = step % TMY_MAX_CONTROL_INDEX;
973++ const struct profile *profile = profile_ptr[i];
974++
975++ head->read_step = step;
976++ if (!profile)
977++ continue;
978++ if (j != TMY_COMMENT)
979++ goto non_comment;
980++ if (tmy_io_printf(head, "%u-%s=%s\n",
981++ i, tmy_control[TMY_COMMENT].keyword,
982++ profile->comment ?
983++ profile->comment->name : ""))
984++ break;
985++ goto comment_ok;
986++non_comment: ;
987++ if (tmy_io_printf(head, "%u-%s=%u\n",
988++ i, tmy_control[j].keyword,
989++ profile->value[j]))
990++ break;
991++comment_ok: ;
992++ }
993++
994++ if (step == TMY_MAX_PROFILES * TMY_MAX_CONTROL_INDEX) {
995++ head->read_var1 = (void *) "";
996++ head->read_step = 0;
997++ goto capability;
998++ }
999++ return 0;
1000++capability: ;
1001++ if (tmy_read_capability_profile(head) == 0)
1002++ head->read_eof = 1;
1003++ return 0;
1004++}
1005++
1006++/************************* POLICY MANAGER HANDLER *************************/
1007++
1008++struct policy_manager_entry {
1009++ struct list_head list;
1010++ const struct path_info *manager;
1011++ bool is_domain;
1012++ bool is_deleted;
1013++};
1014++
1015++static LIST_HEAD(policy_manager_list);
1016++
1017++/* Update manager list. */
1018++static int tmy_add_manager_entry(const char *manager, const bool is_delete)
1019++{
1020++ struct policy_manager_entry *new_entry;
1021++ struct policy_manager_entry *ptr;
1022++ static DEFINE_MUTEX(mutex);
1023++ const struct path_info *saved_manager;
1024++ int error = -ENOMEM;
1025++
1026++ bool is_domain = 0;
1027++ if (!tmy_is_root())
1028++ return -EPERM;
1029++ if (tmy_is_domain_def(manager)) {
1030++ if (!tmy_is_correct_domain(manager, __FUNCTION__))
1031++ return -EINVAL;
1032++ is_domain = 1;
1033++ } else {
1034++ if (!tmy_correct_path(manager, 1, -1, -1, __FUNCTION__))
1035++ return -EINVAL;
1036++ }
1037++
1038++ saved_manager = tmy_save_name(manager);
1039++ if (saved_manager == NULL)
1040++ return -ENOMEM;
1041++
1042++ mutex_lock(&mutex);
1043++
1044++ list_for_each_entry(ptr, &policy_manager_list, list) {
1045++ if (ptr->manager == saved_manager) {
1046++ ptr->is_deleted = is_delete;
1047++ error = 0;
1048++ goto out;
1049++ }
1050++ }
1051++
1052++ if (is_delete) {
1053++ error = -ENOENT;
1054++ goto out;
1055++ }
1056++
1057++ new_entry = tmy_alloc_element(sizeof(*new_entry));
1058++ if (new_entry == NULL)
1059++ goto out;
1060++ new_entry->manager = saved_manager;
1061++ new_entry->is_domain = is_domain;
1062++ list_add_tail_mb(&new_entry->list, &policy_manager_list);
1063++ error = 0;
1064++out: ;
1065++
1066++ mutex_unlock(&mutex);
1067++
1068++ if (!error)
1069++ tmy_update_counter(TMY_UPDATE_MANAGER);
1070++ return error;
1071++}
1072++
1073++/* Update manager list. */
1074++static int tmy_add_manager_policy(struct io_buffer *head)
1075++{
1076++ char *data = head->write_buf;
1077++ bool is_delete = 0;
1078++
1079++ if (!tmy_is_root())
1080++ return -EPERM;
1081++ if (tmy_strstarts(&data, TMY_DELETE))
1082++ is_delete = 1;
1083++ return tmy_add_manager_entry(data, is_delete);
1084++}
1085++
1086++/* Read manager list.*/
1087++static int tmy_read_manager_policy(struct io_buffer *head)
1088++{
1089++ struct list_head *pos;
1090++ if (head->read_eof)
1091++ return 0;
1092++ if (!tmy_is_root())
1093++ return -EPERM;
1094++ list_for_each_cookie(pos, head->read_var2, &policy_manager_list) {
1095++ struct policy_manager_entry *ptr;
1096++ ptr = list_entry(pos, struct policy_manager_entry, list);
1097++ if (!ptr->is_deleted &&
1098++ tmy_io_printf(head, "%s\n", ptr->manager->name))
1099++ break;
1100++ }
1101++ if (!head->read_var2)
1102++ head->read_eof = 1;
1103++ return 0;
1104++}
1105++
1106++/**
1107++ * tmy_is_policy_manager - check whether modifying policy is permitted.
1108++ *
1109++ * Returns nonzero if modifying policy is permitted.
1110++ * Returns zero otherwise.
1111++ *
1112++ * Only programs or domains registers as manager are permitted to modify
1113++ * policy via /sys/kernel/security/tomoyo/ interface.
1114++ * This function checks whether the current process is a policy manager.
1115++ * But policy manager is not the only processes that can modify policy;
1116++ * other process are permitted to add policy
1117++ * if their domains are assigned a profile for learning mode.
1118++ */
1119++static int tmy_is_policy_manager(void)
1120++{
1121++ struct policy_manager_entry *ptr;
1122++ const char *exe;
1123++ const struct path_info *domainname =
1124++ TMY_SECURITY->domain->domainname;
1125++ bool found = 0;
1126++
1127++ /* Everyone can modify policy before /sbin/init starts. */
1128++ if (!sbin_init_started)
1129++ return 1;
1130++
1131++ list_for_each_entry(ptr, &policy_manager_list, list) {
1132++ if (!ptr->is_deleted &&
1133++ ptr->is_domain &&
1134++ !tmy_pathcmp(domainname, ptr->manager))
1135++ return 1;
1136++ }
1137++
1138++ exe = tmy_get_exe();
1139++ if (!exe)
1140++ return 0;
1141++
1142++ list_for_each_entry(ptr, &policy_manager_list, list) {
1143++ if (!ptr->is_deleted &&
1144++ !ptr->is_domain &&
1145++ !strcmp(exe, ptr->manager->name)) {
1146++ found = 1;
1147++ break;
1148++ }
1149++ }
1150++
1151++ if (!found) { /* Reduce error messages. */
1152++ static pid_t last_pid;
1153++ const pid_t pid = current->pid;
1154++ if (last_pid != pid) {
1155++ printk(KERN_INFO
1156++ "%s is not permitted to update policies.\n",
1157++ exe);
1158++ last_pid = pid;
1159++ }
1160++ }
1161++
1162++ tmy_free(exe);
1163++ return found;
1164++}
1165++
1166++/************************* DOMAIN POLICY HANDLER *************************/
1167++
1168++/* Update domain policy. */
1169++static int tmy_add_domain_policy(struct io_buffer *head)
1170++{
1171++ char *data = head->write_buf;
1172++ char *cp;
1173++ const struct condition_list *cond = NULL;
1174++ struct domain_info *domain = head->write_var1;
1175++ bool is_delete = 0;
1176++ bool is_select = 0;
1177++ bool is_undelete = 0;
1178++ unsigned int profile;
1179++
1180++ if (!tmy_is_root())
1181++ return -EPERM;
1182++
1183++ if (tmy_strstarts(&data, TMY_DELETE))
1184++ is_delete = 1;
1185++ else if (tmy_strstarts(&data, TMY_SELECT))
1186++ is_select = 1;
1187++ else if (tmy_strstarts(&data, TMY_UNDELETE))
1188++ is_undelete = 1;
1189++
1190++ tmy_update_counter(TMY_UPDATE_DOMAINPOLICY);
1191++
1192++ if (tmy_is_domain_def(data)) {
1193++ if (is_delete) {
1194++ tmy_delete_domain(data);
1195++ domain = NULL;
1196++ } else if (is_select)
1197++ domain = tmy_find_domain(data);
1198++ else if (is_undelete)
1199++ domain = tmy_undelete_domain(data);
1200++ else
1201++ domain = tmy_new_domain(data, 0);
1202++ head->write_var1 = domain;
1203++ return 0;
1204++ }
1205++
1206++ if (!domain)
1207++ return -EINVAL;
1208++
1209++ if (sscanf(data, TMY_USE_PROFILE "%u", &profile) == 1 &&
1210++ profile < TMY_MAX_PROFILES) {
1211++ if (profile_ptr[profile] || !sbin_init_started)
1212++ domain->profile = (u8) profile;
1213++ return 0;
1214++ }
1215++ cp = tmy_find_condition_part(data);
1216++ if (cp) {
1217++ cond = tmy_assign_condition(cp);
1218++ if (!cond)
1219++ return -EINVAL;
1220++ }
1221++ if (tmy_strstarts(&data, TMY_ALLOW_NETWORK))
1222++ return tmy_add_network_policy(data, domain, cond, is_delete);
1223++ else if (tmy_strstarts(&data, TMY_ALLOW_ARGV0))
1224++ return tmy_add_argv0_policy(data, domain, cond, is_delete);
1225++ else if (tmy_strstarts(&data, TMY_ALLOW_SIGNAL))
1226++ return tmy_add_signal_policy(data, domain, cond, is_delete);
1227++ else if (tmy_strstarts(&data, TMY_ALLOW_CAPABILITY))
1228++ return tmy_add_capability_policy(data, domain, cond, is_delete);
1229++ else
1230++ return tmy_add_file_policy(data, domain, cond, is_delete);
1231++
1232++ return -EINVAL;
1233++}
1234++
1235++/* Dump file's open ACL. */
1236++static inline int print_file_rwx_acl(struct io_buffer *head,
1237++ struct acl_info *ptr)
1238++{
1239++ struct file_acl *ptr2 = (struct file_acl *) ptr;
1240++ const unsigned char b = ptr2->u_is_group;
1241++
1242++ if (tmy_io_printf(head, "%d %s%s",
1243++ ptr2->perm, b ? "@" : "",
1244++ b ? ptr2->u.group->group_name->name :
1245++ ptr2->u.filename->name))
1246++ return -ENOMEM;
1247++ return 0;
1248++}
1249++
1250++/* Dump argv[0]'s ACL. */
1251++static inline int print_argv0_acl(struct io_buffer *head,
1252++ struct acl_info *ptr)
1253++{
1254++ struct argv0_acl *ptr2 = (struct argv0_acl *) ptr;
1255++
1256++ if (tmy_io_printf(head, TMY_ALLOW_ARGV0 "%s %s",
1257++ ptr2->filename->name, ptr2->argv0->name))
1258++ return -ENOMEM;
1259++ return 0;
1260++}
1261++
1262++/* Dump network's ACL. */
1263++static inline int print_network_acl(struct io_buffer *head,
1264++ struct acl_info *ptr)
1265++{
1266++ struct net_acl *ptr2 = (struct net_acl *) ptr;
1267++ u8 record_type = ptr2->record_type;
1268++ u32 min_address;
1269++ u32 max_address;
1270++ char buf[64];
1271++ const u16 *min_address_ptr;
1272++ const u16 *max_address_ptr;
1273++ u16 min_port;
1274++ u16 max_port;
1275++
1276++ if (tmy_io_printf(head, TMY_ALLOW_NETWORK "%s ",
1277++ tmy_network2keyword(ptr2->operation_type)))
1278++ goto out;
1279++ if (record_type != TMY_TYPE_ADDRESS_GROUP)
1280++ goto non_address_group;
1281++
1282++ if (tmy_io_printf(head, "@%s", ptr2->u.group->group_name->name))
1283++ goto out;
1284++ goto print_port;
1285++
1286++non_address_group: ;
1287++ if (record_type != TMY_TYPE_IPv4)
1288++ goto ipv6_address;
1289++
1290++ min_address = ptr2->u.ipv4.min;
1291++ max_address = ptr2->u.ipv4.max;
1292++ if (tmy_io_printf(head, NIPQUAD_FMT, HIPQUAD(min_address)))
1293++ goto out;
1294++ if (min_address != max_address &&
1295++ tmy_io_printf(head, "-" NIPQUAD_FMT, HIPQUAD(max_address)))
1296++ goto out;
1297++ goto print_port;
1298++
1299++ipv6_address: ;
1300++ min_address_ptr = ptr2->u.ipv6.min;
1301++ max_address_ptr = ptr2->u.ipv6.max;
1302++ tmy_print_ipv6(buf, sizeof(buf), min_address_ptr);
1303++ if (tmy_io_printf(head, "%s", buf))
1304++ goto out;
1305++ if (memcmp(min_address_ptr, max_address_ptr, 16)) {
1306++ tmy_print_ipv6(buf, sizeof(buf), max_address_ptr);
1307++ if (tmy_io_printf(head, "-%s", buf))
1308++ goto out;
1309++ }
1310++
1311++print_port: ;
1312++ min_port = ptr2->min_port;
1313++ max_port = ptr2->max_port;
1314++ if (tmy_io_printf(head, " %u", min_port))
1315++ goto out;
1316++ if (min_port != max_port && tmy_io_printf(head, "-%u", max_port))
1317++ goto out;
1318++ return 0;
1319++out: ;
1320++ return -ENOMEM;
1321++}
1322++
1323++/* Dump signal's ACL. */
1324++static inline int print_signal_acl(struct io_buffer *head,
1325++ struct acl_info *ptr)
1326++{
1327++ struct signal_acl *ptr2 = (struct signal_acl *) ptr;
1328++
1329++ if (tmy_io_printf(head, TMY_ALLOW_SIGNAL "%u %s",
1330++ ptr2->sig, ptr2->domainname->name))
1331++ return -ENOMEM;
1332++ return 0;
1333++}
1334++
1335++/* Dump capability's ACL. */
1336++static inline int print_capability_acl(struct io_buffer *head,
1337++ struct acl_info *ptr)
1338++{
1339++ struct capability_acl *ptr2 = (struct capability_acl *) ptr;
1340++
1341++ if (tmy_io_printf(head, TMY_ALLOW_CAPABILITY "%s",
1342++ tmy_capability2keyword(ptr2->capability)))
1343++ return -ENOMEM;
1344++ return 0;
1345++}
1346++
1347++/* Dump file's non-open ACL. */
1348++static inline int print_file_other_acl(struct io_buffer *head,
1349++ struct acl_info *ptr)
1350++{
1351++ const u8 acl_type = ptr->type;
1352++ const char *keyword = tmy_acltype2keyword(acl_type);
1353++
1354++ if (!keyword)
1355++ return 0; /* This must not happen. */
1356++
1357++ if (tmy_acltype2paths(acl_type) == 2) {
1358++ struct double_acl *ptr2 = (struct double_acl *) ptr;
1359++ const bool b1 = ptr2->u1_is_group;
1360++ const bool b2 = ptr2->u2_is_group;
1361++
1362++ if (tmy_io_printf(head,
1363++ "allow_%s %s%s %s%s",
1364++ keyword,
1365++ b1 ? "@" : "",
1366++ b1 ? ptr2->u1.group1->group_name->name :
1367++ ptr2->u1.filename1->name,
1368++ b2 ? "@" : "",
1369++ b2 ? ptr2->u2.group2->group_name->name :
1370++ ptr2->u2.filename2->name))
1371++ return -ENOMEM;
1372++ } else {
1373++ struct single_acl *ptr2 = (struct single_acl *) ptr;
1374++ const bool b = ptr2->u_is_group;
1375++
1376++ if (tmy_io_printf(head,
1377++ "allow_%s %s%s",
1378++ keyword,
1379++ b ? "@" : "",
1380++ b ? ptr2->u.group->group_name->name :
1381++ ptr2->u.filename->name))
1382++ return -ENOMEM;
1383++ }
1384++ return 0;
1385++}
1386++
1387++/* Read domain policy. */
1388++static int tmy_read_domain_policy(struct io_buffer *head)
1389++{
1390++ struct list_head *dpos;
1391++ struct list_head *apos;
1392++
1393++ if (head->read_eof)
1394++ return 0;
1395++
1396++ if (head->read_step == 0) {
1397++ if (!tmy_is_root())
1398++ return -EPERM;
1399++ head->read_step = 1;
1400++ }
1401++ list_for_each_cookie(dpos, head->read_var1, &domain_list) {
1402++ struct domain_info *domain;
1403++ domain = list_entry(dpos, struct domain_info, list);
1404++ if (head->read_step != 1)
1405++ goto acl_loop;
1406++ if (domain->is_deleted)
1407++ continue;
1408++ if (tmy_io_printf(head,
1409++ "%s\n" TMY_USE_PROFILE "%u\n%s\n",
1410++ domain->domainname->name,
1411++ domain->profile,
1412++ domain->quota_warned ?
1413++ "quota_exceeded\n" : ""))
1414++ return 0;
1415++ head->read_step = 2;
1416++acl_loop: ;
1417++ if (head->read_step == 3)
1418++ goto tail_mark;
1419++ list_for_each_cookie(apos, head->read_var2,
1420++ &domain->acl_info_list) {
1421++ struct acl_info *ptr;
1422++ int pos;
1423++ u8 acl_type;
1424++ ptr = list_entry(apos, struct acl_info, list);
1425++ if (ptr->is_deleted)
1426++ continue;
1427++ pos = head->read_avail;
1428++ acl_type = ptr->type;
1429++ if (acl_type == TMY_TYPE_FILE_ACL) {
1430++ if (print_file_rwx_acl(head, ptr))
1431++ goto print_acl_rollback;
1432++ } else if (acl_type == TMY_TYPE_ARGV0_ACL) {
1433++ if (print_argv0_acl(head, ptr))
1434++ goto print_acl_rollback;
1435++ } else if (acl_type == TMY_TYPE_IP_NETWORK_ACL) {
1436++ if (print_network_acl(head, ptr))
1437++ goto print_acl_rollback;
1438++ } else if (acl_type == TMY_TYPE_SIGNAL_ACL) {
1439++ if (print_signal_acl(head, ptr))
1440++ goto print_acl_rollback;
1441++ } else if (acl_type == TMY_TYPE_CAPABILITY_ACL) {
1442++ if (print_capability_acl(head, ptr))
1443++ goto print_acl_rollback;
1444++ } else
1445++ if (print_file_other_acl(head, ptr))
1446++ goto print_acl_rollback;
1447++ if (tmy_dump_condition(head, ptr->cond)) {
1448++print_acl_rollback: ;
1449++ head->read_avail = pos;
1450++ return 0;
1451++ }
1452++ }
1453++ head->read_step = 3;
1454++tail_mark: ;
1455++ if (tmy_io_printf(head, "\n"))
1456++ return 0;
1457++ head->read_step = 1;
1458++ }
1459++ head->read_eof = 1;
1460++ return 0;
1461++}
1462++
1463++/* Read domainname and its profile values. */
1464++static int tmy_read_domain_profile(struct io_buffer *head)
1465++{
1466++ struct list_head *pos;
1467++ if (head->read_eof)
1468++ return 0;
1469++ if (!tmy_is_root())
1470++ return -EPERM;
1471++ list_for_each_cookie(pos, head->read_var1, &domain_list) {
1472++ struct domain_info *domain;
1473++ domain = list_entry(pos, struct domain_info, list);
1474++ if (domain->is_deleted)
1475++ continue;
1476++ if (tmy_io_printf(head, "%u %s\n",
1477++ domain->profile, domain->domainname->name))
1478++ return 0;
1479++ }
1480++ head->read_eof = 1;
1481++ return 0;
1482++}
1483++
1484++/* Set PID to report. Non manager process is permitted to call this function. */
1485++static int tmy_write_pid(struct io_buffer *head)
1486++{
1487++ head->read_step = (int) simple_strtoul(head->write_buf, NULL, 10);
1488++ head->read_eof = 0;
1489++ return 0;
1490++}
1491++
1492++/* Read domainname and its profile values. */
1493++static int tmy_read_pid(struct io_buffer *head)
1494++{
1495++ const int pid = head->read_step;
1496++ struct task_struct *p;
1497++ struct domain_info *domain = NULL;
1498++
1499++ /* If PID is not set via tmy_write_pid(), do nothing. */
1500++ if (head->read_avail || head->read_eof)
1501++ return 0;
1502++
1503++ /***** CRITICAL SECTION START *****/
1504++ read_lock(&tasklist_lock);
1505++ p = find_task_by_pid(pid);
1506++ if (p) {
1507++ /* "struct task_struct"->security is not NULL. */
1508++ domain = ((struct tmy_security *) p->security)->domain;
1509++ }
1510++ read_unlock(&tasklist_lock);
1511++ /***** CRITICAL SECTION END *****/
1512++
1513++ if (domain)
1514++ tmy_io_printf(head, "%d %u %s",
1515++ pid, domain->profile, domain->domainname->name);
1516++ head->read_eof = 1;
1517++
1518++ return 0;
1519++}
1520++
1521++/* Update profile values for domains. */
1522++static int tmy_update_domain_profile(struct io_buffer *head)
1523++{
1524++ char *data = head->write_buf;
1525++ char *cp = strchr(data, ' ');
1526++ struct domain_info *domain;
1527++ unsigned int profile;
1528++
1529++ if (!tmy_is_root())
1530++ return -EPERM;
1531++ if (!cp)
1532++ return -EINVAL;
1533++
1534++ *cp = '\0';
1535++ domain = tmy_find_domain(cp + 1);
1536++ profile = simple_strtoul(data, NULL, 10);
1537++ if (domain && profile < TMY_MAX_PROFILES &&
1538++ (profile_ptr[profile] || !sbin_init_started))
1539++ domain->profile = (u8) profile;
1540++ tmy_update_counter(TMY_UPDATE_DOMAINPOLICY);
1541++
1542++ return 0;
1543++}
1544++
1545++/************************* SYSTEM POLICY HANDLER *************************/
1546++
1547++/* Update system policy. */
1548++static int tmy_add_system_policy(struct io_buffer *head)
1549++{
1550++ char *data = head->write_buf;
1551++ bool is_delete = 0;
1552++
1553++ if (!tmy_is_root())
1554++ return -EPERM;
1555++
1556++ tmy_update_counter(TMY_UPDATE_SYSTEMPOLICY);
1557++
1558++ if (tmy_strstarts(&data, TMY_DELETE))
1559++ is_delete = 1;
1560++ if (tmy_strstarts(&data, TMY_ALLOW_MOUNT))
1561++ return tmy_add_mount_policy(data, is_delete);
1562++ if (tmy_strstarts(&data, TMY_DENY_UNMOUNT))
1563++ return tmy_add_no_umount_policy(data, is_delete);
1564++ if (tmy_strstarts(&data, TMY_ALLOW_PIVOT_ROOT))
1565++ return tmy_add_pivot_root_policy(data, is_delete);
1566++
1567++ return -EINVAL;
1568++}
1569++
1570++/* Read system policy. */
1571++static int tmy_read_system_policy(struct io_buffer *head)
1572++{
1573++ if (head->read_eof)
1574++ return 0;
1575++ switch (head->read_step) {
1576++ case 0:
1577++ if (!tmy_is_root())
1578++ return -EPERM;
1579++ head->read_step = 1;
1580++ case 1:
1581++ if (tmy_read_mount_policy(head))
1582++ break;
1583++ head->read_step = 2;
1584++ case 2:
1585++ if (tmy_read_no_umount_policy(head))
1586++ break;
1587++ head->read_step = 3;
1588++ case 3:
1589++ if (tmy_read_pivot_root_policy(head))
1590++ break;
1591++ head->read_eof = 1;
1592++ break;
1593++ default:
1594++ return -EINVAL;
1595++ }
1596++ return 0;
1597++}
1598++
1599++/************************* EXCEPTION POLICY HANDLER *************************/
1600++/* Update exception policy. */
1601++static int tmy_add_exception_policy(struct io_buffer *head)
1602++{
1603++ char *data = head->write_buf;
1604++ bool is_delete = 0;
1605++
1606++ if (!tmy_is_root())
1607++ return -EPERM;
1608++
1609++ tmy_update_counter(TMY_UPDATE_EXCEPTIONPOLICY);
1610++
1611++ if (tmy_strstarts(&data, TMY_DELETE))
1612++ is_delete = 1;
1613++ if (tmy_strstarts(&data, TMY_KEEP_DOMAIN))
1614++ return tmy_add_domain_keeper_policy(data, 0, is_delete);
1615++ if (tmy_strstarts(&data, TMY_NO_KEEP_DOMAIN))
1616++ return tmy_add_domain_keeper_policy(data, 1, is_delete);
1617++ if (tmy_strstarts(&data, TMY_INITIALIZE_DOMAIN))
1618++ return tmy_add_domain_initializer_policy(data, 0, is_delete);
1619++ if (tmy_strstarts(&data, TMY_NO_INITIALIZE_DOMAIN))
1620++ return tmy_add_domain_initializer_policy(data, 1, is_delete);
1621++ if (tmy_strstarts(&data, TMY_ALIAS))
1622++ return tmy_add_alias_policy(data, is_delete);
1623++ if (tmy_strstarts(&data, TMY_AGGREGATOR))
1624++ return tmy_add_aggregator_policy(data, is_delete);
1625++ if (tmy_strstarts(&data, TMY_ALLOW_READ))
1626++ return tmy_add_globally_readable_policy(data, is_delete);
1627++ if (tmy_strstarts(&data, TMY_FILE_PATTERN))
1628++ return tmy_add_pattern_policy(data, is_delete);
1629++ if (tmy_strstarts(&data, TMY_PATH_GROUP))
1630++ return tmy_add_group_policy(data, is_delete);
1631++ if (tmy_strstarts(&data, TMY_DENY_REWRITE))
1632++ return tmy_add_no_rewrite_policy(data, is_delete);
1633++ if (tmy_strstarts(&data, TMY_ADDRESS_GROUP))
1634++ return tmy_add_address_group_policy(data, is_delete);
1635++
1636++ return -EINVAL;
1637++}
1638++
1639++/* Read exception policy. */
1640++static int tmy_read_exception_policy(struct io_buffer *head)
1641++{
1642++ if (head->read_eof)
1643++ return 0;
1644++ switch (head->read_step) {
1645++ case 0:
1646++ if (!tmy_is_root())
1647++ return -EPERM;
1648++ head->read_step = 1;
1649++ case 1:
1650++ if (tmy_read_domain_keeper_policy(head))
1651++ break;
1652++ head->read_step = 2;
1653++ case 2:
1654++ if (tmy_read_globally_readable_policy(head))
1655++ break;
1656++ head->read_step = 3;
1657++ case 3:
1658++ if (tmy_read_domain_initializer_policy(head))
1659++ break;
1660++ head->read_step = 4;
1661++ case 4:
1662++ if (tmy_read_alias_policy(head))
1663++ break;
1664++ head->read_step = 5;
1665++ case 5:
1666++ if (tmy_read_aggregator_policy(head))
1667++ break;
1668++ head->read_step = 6;
1669++ case 6:
1670++ if (tmy_read_pattern_policy(head))
1671++ break;
1672++ head->read_step = 7;
1673++ case 7:
1674++ if (tmy_read_no_rewrite_policy(head))
1675++ break;
1676++ head->read_step = 8;
1677++ case 8:
1678++ if (tmy_read_path_group_policy(head))
1679++ break;
1680++ head->read_step = 9;
1681++ case 9:
1682++ if (tmy_read_address_group_policy(head))
1683++ break;
1684++ head->read_eof = 1;
1685++ break;
1686++ default:
1687++ return -EINVAL;
1688++ }
1689++ return 0;
1690++}
1691++
1692++/************************* POLICY LOADER *************************/
1693++
1694++/**
1695++ * tmy_load_policy - load policy and activate access control.
1696++ * @filename: program to be executed.
1697++ *
1698++ * This function calls /sbin/tomoyo-init using call_usermodehelper()
1699++ * to load policy
1700++ * if "execution of /sbin/init is requested" and "/sbin/tomoyo-init exists".
1701++ */
1702++void tmy_load_policy(const char *filename)
1703++{
1704++ if (sbin_init_started)
1705++ return;
1706++ if (strcmp(filename, "/sbin/init") != 0)
1707++ return;
1708++
1709++ /*
1710++ * Don't activate MAC if the path '/sbin/tomoyo-init' doesn't exist.
1711++ * If initrd.img includes /sbin/init but real-root-dev has not
1712++ * mounted on / yet, activating MAC will block the system
1713++ * since policies are not loaded yet.
1714++ * So let do_execve() call this function everytime.
1715++ */
1716++ if (!profile_loaded) {
1717++ const char *tmy_loader = "/sbin/tomoyo-init";
1718++ struct nameidata nd;
1719++ char *argv[2];
1720++ char *envp[3];
1721++
1722++ if (path_lookup(tmy_loader, LOOKUP_FOLLOW, &nd)) {
1723++ printk("TOMOYO: Not activating Mandatory Access Control"
1724++ " now since %s doesn't exist.\n", tmy_loader);
1725++ return;
1726++ }
1727++ path_release(&nd);
1728++ argv[0] = (char *) tmy_loader;
1729++ argv[1] = NULL;
1730++ envp[0] = "HOME=/";
1731++ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
1732++ envp[2] = NULL;
1733++ call_usermodehelper(argv[0], argv, envp, 1);
1734++ }
1735++
1736++ printk(KERN_INFO "TOMOYO: %s 2007/11/23\n", TOMOYO_VERSION_CODE);
1737++
1738++ if (!profile_loaded)
1739++ panic("TOMOYO: No profiles loaded.\n");
1740++
1741++ printk(KERN_INFO "TOMOYO: Mandatory Access Control activated.\n");
1742++ sbin_init_started = 1;
1743++
1744++ { /* Check all profiles currently assigned to domains are defined. */
1745++ struct domain_info *domain;
1746++ list_for_each_entry(domain, &domain_list, list) {
1747++ const u8 profile = domain->profile;
1748++ if (profile_ptr[profile])
1749++ continue;
1750++ panic("TOMOYO: Profile %u (used by '%s') "
1751++ "not defined.\n",
1752++ profile,
1753++ domain->domainname->name);
1754++ }
1755++ }
1756++}
1757++
1758++
1759++/************************* MAC Decision Delayer *************************/
1760++
1761++static DECLARE_WAIT_QUEUE_HEAD(query_wait);
1762++
1763++static DEFINE_SPINLOCK(query_lock);
1764++
1765++struct query_entry {
1766++ struct list_head list;
1767++ char *query;
1768++ int query_len;
1769++ unsigned int serial;
1770++ int timer;
1771++ int answer;
1772++};
1773++
1774++static LIST_HEAD(query_list);
1775++static atomic_t queryd_watcher = ATOMIC_INIT(0);
1776++
1777++/**
1778++ * tmy_supervisor - ask for supervisors decision.
1779++ * @fmt: format strings for printf().
1780++ *
1781++ * Returns zero if administrator allowed.
1782++ * Returns nonzero otherwise.
1783++ *
1784++ * This is one of TOMOYO Linux's feature.
1785++ * Normally, access requests that violates policy is rejected immediately.
1786++ * But this behavior is inconvenient when developing policy.
1787++ * TOMOYO Linux allows administrators handle access requests that violated
1788++ * policy in enforce mode to adjust policy.
1789++ *
1790++ * This function blocks a process who is requesting access that violated policy
1791++ * and tell it via /sys/kernel/security/tomoyo/query and wait for supervisor's
1792++ * decision.
1793++ */
1794++int tmy_supervisor(const char *fmt, ...)
1795++{
1796++ va_list args;
1797++ int error = -EPERM;
1798++ int pos;
1799++ int len;
1800++ static unsigned int serial;
1801++ struct query_entry *query_entry;
1802++
1803++ if (!tmy_flags(TMY_ALLOW_ENFORCE_GRACE))
1804++ return -EPERM;
1805++ if (!atomic_read(&queryd_watcher))
1806++ return -EPERM;
1807++
1808++ va_start(args, fmt);
1809++ len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
1810++ va_end(args);
1811++
1812++ query_entry = tmy_alloc(sizeof(*query_entry));
1813++ if (!query_entry)
1814++ goto out;
1815++ query_entry->query = tmy_alloc(len);
1816++ if (!query_entry->query)
1817++ goto out;
1818++
1819++ INIT_LIST_HEAD(&query_entry->list);
1820++
1821++ /***** CRITICAL SECTION START *****/
1822++ spin_lock(&query_lock);
1823++ query_entry->serial = serial++;
1824++ spin_unlock(&query_lock);
1825++ /***** CRITICAL SECTION END *****/
1826++
1827++ pos = snprintf(query_entry->query, len - 1,
1828++ "Q%u\n", query_entry->serial);
1829++ va_start(args, fmt);
1830++ vsnprintf(query_entry->query + pos, len - 1 - pos, fmt, args);
1831++ query_entry->query_len = strlen(query_entry->query) + 1;
1832++ va_end(args);
1833++
1834++ /***** CRITICAL SECTION START *****/
1835++ spin_lock(&query_lock);
1836++ list_add_tail(&query_entry->list, &query_list);
1837++ spin_unlock(&query_lock);
1838++ /***** CRITICAL SECTION END *****/
1839++
1840++ tmy_update_counter(TMY_UPDATE_QUERY);
1841++
1842++ /* Give 10 seconds for supervisor's opinion. */
1843++ for (query_entry->timer = 0;
1844++ atomic_read(&queryd_watcher) &&
1845++ tmy_flags(TMY_ALLOW_ENFORCE_GRACE) &&
1846++ query_entry->timer < 100;
1847++ query_entry->timer++) {
1848++ wake_up(&query_wait);
1849++ set_current_state(TASK_INTERRUPTIBLE);
1850++ schedule_timeout(HZ / 10);
1851++ if (query_entry->answer)
1852++ break;
1853++ }
1854++
1855++ tmy_update_counter(TMY_UPDATE_QUERY);
1856++
1857++ /***** CRITICAL SECTION START *****/
1858++ spin_lock(&query_lock);
1859++ list_del(&query_entry->list);
1860++ spin_unlock(&query_lock);
1861++ /***** CRITICAL SECTION END *****/
1862++
1863++ switch (query_entry->answer) {
1864++ case 1:
1865++ /* Granted by administrator. */
1866++ error = 0;
1867++ break;
1868++ case 0:
1869++ /* Timed out. */
1870++ break;
1871++ default:
1872++ /* Rejected by administrator. */
1873++ break;
1874++ }
1875++
1876++out: ;
1877++ if (query_entry)
1878++ tmy_free(query_entry->query);
1879++ tmy_free(query_entry);
1880++ return error;
1881++}
1882++
1883++/* Check for pending access requests. */
1884++static int tmy_poll_query(struct file *file, poll_table *wait)
1885++{
1886++ int found;
1887++
1888++ /***** CRITICAL SECTION START *****/
1889++ spin_lock(&query_lock);
1890++ found = !list_empty(&query_list);
1891++ spin_unlock(&query_lock);
1892++ /***** CRITICAL SECTION END *****/
1893++
1894++ if (found)
1895++ return POLLIN | POLLRDNORM;
1896++ poll_wait(file, &query_wait, wait);
1897++
1898++ /***** CRITICAL SECTION START *****/
1899++ spin_lock(&query_lock);
1900++ found = !list_empty(&query_list);
1901++ spin_unlock(&query_lock);
1902++ /***** CRITICAL SECTION END *****/
1903++
1904++ if (found)
1905++ return POLLIN | POLLRDNORM;
1906++ return 0;
1907++}
1908++
1909++/* Read pending access requests. */
1910++static int tmy_read_query(struct io_buffer *head)
1911++{
1912++ struct list_head *tmp;
1913++ int pos = 0;
1914++ int len = 0;
1915++ char *buf;
1916++
1917++ if (head->read_avail)
1918++ return 0;
1919++ if (head->read_buf) {
1920++ tmy_free(head->read_buf);
1921++ head->read_buf = NULL;
1922++ head->readbuf_size = 0;
1923++ }
1924++
1925++ /***** CRITICAL SECTION START *****/
1926++ spin_lock(&query_lock);
1927++ list_for_each(tmp, &query_list) {
1928++ struct query_entry *ptr
1929++ = list_entry(tmp, struct query_entry, list);
1930++ if (pos++ == head->read_step) {
1931++ len = ptr->query_len;
1932++ break;
1933++ }
1934++ }
1935++ spin_unlock(&query_lock);
1936++ /***** CRITICAL SECTION END *****/
1937++
1938++ if (!len) {
1939++ head->read_step = 0;
1940++ return 0;
1941++ }
1942++ buf = tmy_alloc(len);
1943++ if (buf) {
1944++ pos = 0;
1945++
1946++ /***** CRITICAL SECTION START *****/
1947++ spin_lock(&query_lock);
1948++ list_for_each(tmp, &query_list) {
1949++ struct query_entry *ptr
1950++ = list_entry(tmp, struct query_entry, list);
1951++ if (pos++ == head->read_step) {
1952++ /* Some query can be skiipped because
1953++ * query_list can change, but I don't care.
1954++ */
1955++ if (len == ptr->query_len)
1956++ memmove(buf, ptr->query, len);
1957++ break;
1958++ }
1959++ }
1960++ spin_unlock(&query_lock);
1961++ /***** CRITICAL SECTION END *****/
1962++
1963++ if (buf[0]) {
1964++ head->readbuf_size = len;
1965++ head->read_avail = len;
1966++ head->read_buf = buf;
1967++ head->read_step++;
1968++ } else
1969++ tmy_free(buf);
1970++ }
1971++
1972++ return 0;
1973++}
1974++
1975++/* Reply to pending access requests. */
1976++static int tmy_write_answer(struct io_buffer *head)
1977++{
1978++ char *data = head->write_buf;
1979++ struct list_head *tmp;
1980++ unsigned int serial;
1981++ unsigned int answer;
1982++
1983++ /***** CRITICAL SECTION START *****/
1984++ spin_lock(&query_lock);
1985++ list_for_each(tmp, &query_list) {
1986++ struct query_entry *ptr
1987++ = list_entry(tmp, struct query_entry, list);
1988++ ptr->timer = 0;
1989++ }
1990++ spin_unlock(&query_lock);
1991++ /***** CRITICAL SECTION END *****/
1992++
1993++ if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
1994++ return -EINVAL;
1995++
1996++ /***** CRITICAL SECTION START *****/
1997++ spin_lock(&query_lock);
1998++ list_for_each(tmp, &query_list) {
1999++ struct query_entry *ptr
2000++ = list_entry(tmp, struct query_entry, list);
2001++ if (ptr->serial != serial)
2002++ continue;
2003++ if (!ptr->answer)
2004++ ptr->answer = answer;
2005++ break;
2006++ }
2007++ spin_unlock(&query_lock);
2008++ /***** CRITICAL SECTION END *****/
2009++
2010++ return 0;
2011++}
2012++
2013++/****************** /sys/kernel/security INTERFACE HANDLER ******************/
2014++
2015++/* Policy updates counter. */
2016++static unsigned int updates_counter[TMY_MAX_UPDATES_COUNTER];
2017++static DEFINE_SPINLOCK(updates_counter_lock);
2018++
2019++/**
2020++ * tmy_update_counter - notify userland that policy is changed.
2021++ * @index: index to update counter.
2022++ *
2023++ * This is for userland process who is monitoring policy changes.
2024++ */
2025++void tmy_update_counter(const unsigned char index)
2026++{
2027++ /***** CRITICAL SECTION START *****/
2028++ spin_lock(&updates_counter_lock);
2029++ if (index < TMY_MAX_UPDATES_COUNTER)
2030++ updates_counter[index]++;
2031++ spin_unlock(&updates_counter_lock);
2032++ /***** CRITICAL SECTION END *****/
2033++}
2034++
2035++/* Read policy update counter. */
2036++static int tmy_read_updates_counter(struct io_buffer *head)
2037++{
2038++ unsigned int counter[TMY_MAX_UPDATES_COUNTER];
2039++ if (head->read_eof)
2040++ return 0;
2041++
2042++ /***** CRITICAL SECTION START *****/
2043++ spin_lock(&updates_counter_lock);
2044++ memmove(counter, updates_counter, sizeof(updates_counter));
2045++ memset(updates_counter, 0, sizeof(updates_counter));
2046++ spin_unlock(&updates_counter_lock);
2047++ /***** CRITICAL SECTION END *****/
2048++
2049++ tmy_io_printf(head,
2050++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
2051++ "/proc/tomoyo/system_policy: %10u\n"
2052++ "/proc/tomoyo/domain_policy: %10u\n"
2053++ "/proc/tomoyo/exception_policy: %10u\n"
2054++ "/proc/tomoyo/profile: %10u\n"
2055++ "/proc/tomoyo/query: %10u\n"
2056++ "/proc/tomoyo/manager: %10u\n"
2057++ "/proc/tomoyo/grant_log: %10u\n"
2058++ "/proc/tomoyo/reject_log: %10u\n",
2059++#else
2060++ "/sys/kernel/security/tomoyo/system_policy: %10u\n"
2061++ "/sys/kernel/security/tomoyo/domain_policy: %10u\n"
2062++ "/sys/kernel/security/tomoyo/exception_policy: %10u\n"
2063++ "/sys/kernel/security/tomoyo/profile: %10u\n"
2064++ "/sys/kernel/security/tomoyo/query: %10u\n"
2065++ "/sys/kernel/security/tomoyo/manager: %10u\n"
2066++ "/sys/kernel/security/tomoyo/grant_log: %10u\n"
2067++ "/sys/kernel/security/tomoyo/reject_log: %10u\n",
2068++#endif
2069++ counter[TMY_UPDATE_SYSTEMPOLICY],
2070++ counter[TMY_UPDATE_DOMAINPOLICY],
2071++ counter[TMY_UPDATE_EXCEPTIONPOLICY],
2072++ counter[TMY_UPDATE_PROFILE],
2073++ counter[TMY_UPDATE_QUERY],
2074++ counter[TMY_UPDATE_MANAGER],
2075++ counter[TMY_UPDATE_GRANT_LOG],
2076++ counter[TMY_UPDATE_REJECT_LOG]);
2077++
2078++ head->read_eof = 1;
2079++
2080++ return 0;
2081++}
2082++
2083++/* Read how much memory is used. */
2084++static int tmy_read_memory_counter(struct io_buffer *head)
2085++{
2086++ int shared;
2087++ int private;
2088++ int dynamic;
2089++
2090++ if (head->read_eof)
2091++ return 0;
2092++ shared = tmy_get_memory_used_for_save_name();
2093++ private = tmy_get_memory_used_for_elements();
2094++ dynamic = tmy_get_memory_used_for_dynamic();
2095++ if (tmy_io_printf(head,
2096++ "Shared: %10u\n"
2097++ "Private: %10u\n"
2098++ "Dynamic: %10u\n"
2099++ "Total: %10u\n",
2100++ shared,
2101++ private,
2102++ dynamic,
2103++ shared + private + dynamic) == 0)
2104++ head->read_eof = 1;
2105++ return 0;
2106++}
2107++
2108++/* Read TOMOYO Linux's version. */
2109++static int tmy_read_version(struct io_buffer *head)
2110++{
2111++ if (!head->read_eof) {
2112++ tmy_io_printf(head, TOMOYO_VERSION_CODE "\n");
2113++ head->read_eof = 1;
2114++ }
2115++ return 0;
2116++}
2117++
2118++/* Read current process's domainname. */
2119++static int tmy_read_self_domain(struct io_buffer *head)
2120++{
2121++ if (!head->read_eof) {
2122++ tmy_io_printf(head,
2123++ "%s",
2124++ TMY_SECURITY->domain->domainname->name);
2125++ head->read_eof = 1;
2126++ }
2127++
2128++ return 0;
2129++}
2130++
2131++/* This is /sys/kernel/security/tomoyo/ interface. */
2132++static int tmy_open_control(const int type, struct file *file)
2133++{
2134++ struct io_buffer *head = tmy_alloc(sizeof(*head));
2135++
2136++ if (!head)
2137++ return -ENOMEM;
2138++ mutex_init(&head->read_mutex);
2139++ mutex_init(&head->write_mutex);
2140++
2141++ switch (type) {
2142++ case TMY_DOMAINPOLICY:
2143++ head->write = tmy_add_domain_policy;
2144++ head->read = tmy_read_domain_policy;
2145++ break;
2146++ case TMY_SYSTEMPOLICY:
2147++ head->write = tmy_add_system_policy;
2148++ head->read = tmy_read_system_policy;
2149++ break;
2150++ case TMY_EXCEPTIONPOLICY:
2151++ head->write = tmy_add_exception_policy;
2152++ head->read = tmy_read_exception_policy;
2153++ break;
2154++ case TMY_DOMAIN_STATUS:
2155++ head->write = tmy_update_domain_profile;
2156++ head->read = tmy_read_domain_profile;
2157++ break;
2158++ case TMY_PROCESS_STATUS:
2159++ head->write = tmy_write_pid;
2160++ head->read = tmy_read_pid;
2161++ break;
2162++ case TMY_SELFDOMAIN:
2163++ head->read = tmy_read_self_domain;
2164++ break;
2165++ case TMY_MEMINFO:
2166++ head->read = tmy_read_memory_counter;
2167++ head->readbuf_size = 128;
2168++ break;
2169++ case TMY_PROFILE:
2170++ head->write = tmy_set_profile;
2171++ head->read = tmy_read_profile;
2172++ break;
2173++ case TMY_QUERY:
2174++ head->poll = tmy_poll_query;
2175++ head->write = tmy_write_answer;
2176++ head->read = tmy_read_query;
2177++ break;
2178++ case TMY_MANAGER:
2179++ head->write = tmy_add_manager_policy;
2180++ head->read = tmy_read_manager_policy;
2181++ break;
2182++ case TMY_UPDATESCOUNTER:
2183++ head->read = tmy_read_updates_counter;
2184++ break;
2185++ case TMY_VERSION:
2186++ head->read = tmy_read_version;
2187++ break;
2188++ case TMY_GRANT_LOG:
2189++ head->read = tmy_read_grant_log;
2190++ head->poll = tmy_poll_grant_log;
2191++ break;
2192++ case TMY_REJECT_LOG:
2193++ head->read = tmy_read_reject_log;
2194++ head->poll = tmy_poll_reject_log;
2195++ break;
2196++ }
2197++
2198++ if (type != TMY_QUERY) {
2199++ if (!head->readbuf_size)
2200++ head->readbuf_size = PAGE_SIZE * 2;
2201++ head->read_buf = tmy_alloc(head->readbuf_size);
2202++ if (!head->read_buf) {
2203++ tmy_free(head);
2204++ return -ENOMEM;
2205++ }
2206++ }
2207++
2208++ if (head->write) {
2209++ head->writebuf_size = PAGE_SIZE * 2;
2210++ head->write_buf = tmy_alloc(head->writebuf_size);
2211++ if (!head->write_buf) {
2212++ tmy_free(head->read_buf);
2213++ tmy_free(head);
2214++ return -ENOMEM;
2215++ }
2216++ }
2217++
2218++ file->private_data = head;
2219++
2220++ if (type == TMY_SELFDOMAIN)
2221++ tmy_read_control(file, NULL, 0);
2222++ else if (head->write == tmy_write_answer)
2223++ atomic_inc(&queryd_watcher);
2224++
2225++ return 0;
2226++}
2227++
2228++/* Copy read data to userland buffer. */
2229++static int tmy_copy_to_user(struct io_buffer *head, char __user *buffer,
2230++ int buffer_len)
2231++{
2232++ int len = head->read_avail;
2233++ char *cp = head->read_buf;
2234++
2235++ if (len > buffer_len)
2236++ len = buffer_len;
2237++ if (len) {
2238++ if (copy_to_user(buffer, cp, len))
2239++ return -EFAULT;
2240++ head->read_avail -= len;
2241++ memmove(cp, cp + len, head->read_avail);
2242++ }
2243++
2244++ return len;
2245++}
2246++
2247++/* Check for pending requests. */
2248++static int tmy_poll_control(struct file *file, poll_table *wait)
2249++{
2250++ struct io_buffer *head = (struct io_buffer *) file->private_data;
2251++ if (!head->poll)
2252++ return -ENOSYS;
2253++ return head->poll(file, wait);
2254++}
2255++
2256++/* Read policy. */
2257++static int tmy_read_control(struct file *file, char __user *buffer,
2258++ const int buffer_len)
2259++{
2260++ int len = 0;
2261++ struct io_buffer *head = (struct io_buffer *) file->private_data;
2262++
2263++ if (!head->read)
2264++ return -ENOSYS;
2265++ if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2266++ return -EFAULT;
2267++ if (mutex_lock_interruptible(&head->read_mutex))
2268++ return -EINTR;
2269++ len = head->read(head);
2270++ if (len >= 0)
2271++ len = tmy_copy_to_user(head, buffer, buffer_len);
2272++ mutex_unlock(&head->read_mutex);
2273++
2274++ return len;
2275++}
2276++
2277++/* Update policy. */
2278++static int tmy_write_control(struct file *file, const char __user *buffer,
2279++ const int buffer_len)
2280++{
2281++ struct io_buffer *head = (struct io_buffer *) file->private_data;
2282++ int error = buffer_len;
2283++ int avail_len = buffer_len;
2284++ char *cp0 = head->write_buf;
2285++
2286++ if (!head->write)
2287++ return -ENOSYS;
2288++ if (!access_ok(VERIFY_READ, buffer, buffer_len))
2289++ return -EFAULT;
2290++ if (!tmy_is_root())
2291++ return -EPERM;
2292++ if (head->write != tmy_write_pid && !tmy_is_policy_manager())
2293++ /* Forbid updating policies for non manager programs. */
2294++ return -EPERM;
2295++
2296++ if (mutex_lock_interruptible(&head->write_mutex))
2297++ return -EINTR;
2298++ while (avail_len > 0) {
2299++ char c;
2300++ if (head->write_avail >= head->writebuf_size - 1) {
2301++ error = -ENOMEM;
2302++ break;
2303++ } else if (get_user(c, buffer)) {
2304++ error = -EFAULT;
2305++ break;
2306++ }
2307++ buffer++;
2308++ avail_len--;
2309++ cp0[head->write_avail++] = c;
2310++ if (c != '\n')
2311++ continue;
2312++ cp0[head->write_avail - 1] = '\0';
2313++ head->write_avail = 0;
2314++ tmy_normalize_line(cp0);
2315++ head->write(head);
2316++ }
2317++ mutex_unlock(&head->write_mutex);
2318++
2319++ return error;
2320++}
2321++
2322++/* Close /sys/kernel/security/tomoyo/ interface. */
2323++static int tmy_close_control(struct file *file)
2324++{
2325++ struct io_buffer *head = file->private_data;
2326++
2327++ if (head->write == tmy_write_answer)
2328++ atomic_dec(&queryd_watcher);
2329++
2330++ tmy_free(head->read_buf);
2331++ head->read_buf = NULL;
2332++ tmy_free(head->write_buf);
2333++ head->write_buf = NULL;
2334++ tmy_free(head);
2335++ head = NULL;
2336++ file->private_data = NULL;
2337++ return 0;
2338++}
2339++
2340++/* open() operation for /sys/kernel/security/tomoyo/ interface. */
2341++static int tmy_open(struct inode *inode, struct file *file)
2342++{
2343++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
2344++ return tmy_open_control(((u8 *) PDE(inode)->data) - ((u8 *) NULL),
2345++ file);
2346++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
2347++ return tmy_open_control(((u8 *) file->f_dentry->d_inode->u.generic_ip)
2348++ - ((u8 *) NULL), file);
2349++#else
2350++ return tmy_open_control(((u8 *) file->f_dentry->d_inode->i_private)
2351++ - ((u8 *) NULL), file);
2352++#endif
2353++}
2354++
2355++/* close() operation for /sys/kernel/security/tomoyo/ interface. */
2356++static int tmy_release(struct inode *inode, struct file *file)
2357++{
2358++ return tmy_close_control(file);
2359++}
2360++
2361++/* poll() operation for /sys/kernel/security/tomoyo/ interface. */
2362++static unsigned int tmy_poll(struct file *file, poll_table *wait)
2363++{
2364++ return tmy_poll_control(file, wait);
2365++}
2366++
2367++/* read() operation for /sys/kernel/security/tomoyo/ interface. */
2368++static ssize_t tmy_read(struct file *file, char __user *buf,
2369++ size_t count, loff_t *ppos)
2370++{
2371++ return tmy_read_control(file, buf, count);
2372++}
2373++
2374++/* write() operation for /sys/kernel/security/tomoyo/ interface. */
2375++static ssize_t tmy_write(struct file *file, const char __user *buf,
2376++ size_t count, loff_t *ppos)
2377++{
2378++ return tmy_write_control(file, buf, count);
2379++}
2380++
2381++static struct file_operations tmy_operations = {
2382++ .open = tmy_open,
2383++ .release = tmy_release,
2384++ .poll = tmy_poll,
2385++ .read = tmy_read,
2386++ .write = tmy_write
2387++};
2388++
2389++/* Associate /sys/kernel/security/tomoyo/ interface with key. */
2390++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
2391++static void __init tmy_create_entry(const char *name,
2392++ const mode_t mode,
2393++ struct proc_dir_entry *parent,
2394++ const int key)
2395++{
2396++ struct proc_dir_entry *entry = create_proc_entry(name, mode, parent);
2397++ if (entry) {
2398++ entry->proc_fops = &tmy_operations;
2399++ entry->data = ((u8 *) NULL) + key;
2400++ }
2401++}
2402++#else
2403++static void __init tmy_create_entry(const char *name,
2404++ const mode_t mode,
2405++ struct dentry *parent,
2406++ const int key)
2407++{
2408++ securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
2409++ &tmy_operations);
2410++}
2411++#endif
2412++
2413++/**
2414++ * tmy_interface_init - initialize /sys/kernel/security/tomoyo/ interface.
2415++ */
2416++static int __init tmy_interface_init(void)
2417++{
2418++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
2419++ struct proc_dir_entry *tmy_dir;
2420++ tmy_dir = proc_mkdir("tomoyo", NULL);
2421++#else
2422++ struct dentry *tmy_dir;
2423++ tmy_dir = securityfs_create_dir("tomoyo", NULL);
2424++#endif
2425++ tmy_create_entry("query", 0600, tmy_dir,
2426++ TMY_QUERY);
2427++ tmy_create_entry("domain_policy", 0600, tmy_dir,
2428++ TMY_DOMAINPOLICY);
2429++ tmy_create_entry("system_policy", 0600, tmy_dir,
2430++ TMY_SYSTEMPOLICY);
2431++ tmy_create_entry("exception_policy", 0600, tmy_dir,
2432++ TMY_EXCEPTIONPOLICY);
2433++ tmy_create_entry(".domain_status", 0600, tmy_dir,
2434++ TMY_DOMAIN_STATUS);
2435++ tmy_create_entry(".process_status", 0400, tmy_dir,
2436++ TMY_PROCESS_STATUS);
2437++ tmy_create_entry("self_domain", 0400, tmy_dir,
2438++ TMY_SELFDOMAIN);
2439++ tmy_create_entry("meminfo", 0400, tmy_dir,
2440++ TMY_MEMINFO);
2441++ tmy_create_entry("profile", 0600, tmy_dir,
2442++ TMY_PROFILE);
2443++ tmy_create_entry("manager", 0600, tmy_dir,
2444++ TMY_MANAGER);
2445++ tmy_create_entry(".updates_counter", 0400, tmy_dir,
2446++ TMY_UPDATESCOUNTER);
2447++ tmy_create_entry("version", 0400, tmy_dir,
2448++ TMY_VERSION);
2449++ tmy_create_entry("grant_log", 0400, tmy_dir,
2450++ TMY_GRANT_LOG);
2451++ tmy_create_entry("reject_log", 0400, tmy_dir,
2452++ TMY_REJECT_LOG);
2453++ return 0;
2454++}
2455++
2456++postcore_initcall(tmy_interface_init);
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-lsm-expansion.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-lsm-expansion.diff (revision 755)
@@ -0,0 +1,378 @@
1+LSM expansion for TOMOYO Linux.
2+
3+LSM hooks for sending signal:
4+ * task_kill_unlocked is added in sys_kill
5+ * task_tkill_unlocked is added in sys_tkill
6+ * task_tgkill_unlocked is added in sys_tgkill
7+LSM hooks for network accept and recv:
8+ * socket_post_accept is modified to return int.
9+ * post_recv_datagram is added in skb_recv_datagram.
10+
11+You can try TOMOYO Linux without this patch, but in that case, you
12+can't use access control functionality for restricting signal
13+transmission and incoming network data.
14+
15+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
16+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
17+ include/linux/security.h | 91 +++++++++++++++++++++++++++++++++++++++++++----
18+ kernel/signal.c | 17 ++++++++
19+ net/core/datagram.c | 22 +++++++++++
20+ net/socket.c | 7 ++-
21+ security/dummy.c | 32 ++++++++++++++--
22+ 5 files changed, 157 insertions(+), 12 deletions(-)
23+
24+--- linux-2.6.23.orig/include/linux/security.h 2007-10-10 05:31:38.000000000 +0900
25++++ linux-2.6.23/include/linux/security.h 2007-11-01 17:16:15.000000000 +0900
26+@@ -628,6 +628,22 @@ struct request_sock;
27+ * @sig contains the signal value.
28+ * @secid contains the sid of the process where the signal originated
29+ * Return 0 if permission is granted.
30++ * @task_kill_unlocked:
31++ * Check permission before sending signal @sig to the process of @pid
32++ * with sys_kill.
33++ * @pid contains the pid of target process.
34++ * @sig contains the signal value.
35++ * @task_tkill_unlocked:
36++ * Check permission before sending signal @sig to the process of @pid
37++ * with sys_tkill.
38++ * @pid contains the pid of target process.
39++ * @sig contains the signal value.
40++ * @task_tgkill_unlocked:
41++ * Check permission before sending signal @sig to the process of @pid
42++ * with sys_tgkill.
43++ * @tgid contains the thread group id.
44++ * @pid contains the pid of target process.
45++ * @sig contains the signal value.
46+ * @task_wait:
47+ * Check permission before allowing a process to reap a child process @p
48+ * and collect its status information.
49+@@ -749,8 +765,12 @@ struct request_sock;
50+ * @socket_post_accept:
51+ * This hook allows a security module to copy security
52+ * information into the newly created socket's inode.
53++ * This hook also allows a security module to filter connections
54++ * from unwanted peers.
55++ * The connection will be aborted if this hook returns nonzero.
56+ * @sock contains the listening socket structure.
57+ * @newsock contains the newly created server socket for connection.
58++ * Return 0 if permission is granted.
59+ * @socket_sendmsg:
60+ * Check permission before transmitting a message to another socket.
61+ * @sock contains the socket structure.
62+@@ -764,6 +784,11 @@ struct request_sock;
63+ * @size contains the size of message structure.
64+ * @flags contains the operational flags.
65+ * Return 0 if permission is granted.
66++ * @post_recv_datagram:
67++ * Check permission after receiving a datagram.
68++ * @sk contains the socket.
69++ * @skb contains the socket buffer (may be NULL).
70++ * @flags contains the operational flags.
71+ * @socket_getsockname:
72+ * Check permission before the local address (name) of the socket object
73+ * @sock is retrieved.
74+@@ -1279,6 +1304,9 @@ struct security_operations {
75+ int (*task_movememory) (struct task_struct * p);
76+ int (*task_kill) (struct task_struct * p,
77+ struct siginfo * info, int sig, u32 secid);
78++ int (*task_kill_unlocked) (int pid, int sig);
79++ int (*task_tkill_unlocked) (int pid, int sig);
80++ int (*task_tgkill_unlocked) (int tgid, int pid, int sig);
81+ int (*task_wait) (struct task_struct * p);
82+ int (*task_prctl) (int option, unsigned long arg2,
83+ unsigned long arg3, unsigned long arg4,
84+@@ -1346,12 +1374,16 @@ struct security_operations {
85+ struct sockaddr * address, int addrlen);
86+ int (*socket_listen) (struct socket * sock, int backlog);
87+ int (*socket_accept) (struct socket * sock, struct socket * newsock);
88+- void (*socket_post_accept) (struct socket * sock,
89+- struct socket * newsock);
90++#define TMY_LSM_EXPANSION
91++ int (*socket_post_accept) (struct socket *sock,
92++ struct socket *newsock);
93+ int (*socket_sendmsg) (struct socket * sock,
94+ struct msghdr * msg, int size);
95+ int (*socket_recvmsg) (struct socket * sock,
96+ struct msghdr * msg, int size, int flags);
97++ int (*post_recv_datagram) (struct sock *sk,
98++ struct sk_buff *skb,
99++ unsigned int flags);
100+ int (*socket_getsockname) (struct socket * sock);
101+ int (*socket_getpeername) (struct socket * sock);
102+ int (*socket_getsockopt) (struct socket * sock, int level, int optname);
103+@@ -1967,6 +1999,21 @@ static inline int security_task_kill (st
104+ return security_ops->task_kill (p, info, sig, secid);
105+ }
106+
107++static inline int security_task_kill_unlocked(int pid, int sig)
108++{
109++ return security_ops->task_kill_unlocked(pid, sig);
110++}
111++
112++static inline int security_task_tkill_unlocked(int pid, int sig)
113++{
114++ return security_ops->task_tkill_unlocked(pid, sig);
115++}
116++
117++static inline int security_task_tgkill_unlocked(int tgid, int pid, int sig)
118++{
119++ return security_ops->task_tgkill_unlocked(tgid, pid, sig);
120++}
121++
122+ static inline int security_task_wait (struct task_struct *p)
123+ {
124+ return security_ops->task_wait (p);
125+@@ -2645,6 +2692,21 @@ static inline int security_task_kill (st
126+ return 0;
127+ }
128+
129++static inline int security_task_kill_unlocked(int pid, int sig)
130++{
131++ return 0;
132++}
133++
134++static inline int security_task_tkill_unlocked(int pid, int sig)
135++{
136++ return 0;
137++}
138++
139++static inline int security_task_tgkill_unlocked(int tgid, int pid, int sig)
140++{
141++ return 0;
142++}
143++
144+ static inline int security_task_wait (struct task_struct *p)
145+ {
146+ return 0;
147+@@ -2870,10 +2932,10 @@ static inline int security_socket_accept
148+ return security_ops->socket_accept(sock, newsock);
149+ }
150+
151+-static inline void security_socket_post_accept(struct socket * sock,
152+- struct socket * newsock)
153++static inline int security_socket_post_accept(struct socket *sock,
154++ struct socket *newsock)
155+ {
156+- security_ops->socket_post_accept(sock, newsock);
157++ return security_ops->socket_post_accept(sock, newsock);
158+ }
159+
160+ static inline int security_socket_sendmsg(struct socket * sock,
161+@@ -2889,6 +2951,13 @@ static inline int security_socket_recvms
162+ return security_ops->socket_recvmsg(sock, msg, size, flags);
163+ }
164+
165++static inline int security_post_recv_datagram(struct sock *sk,
166++ struct sk_buff *skb,
167++ unsigned int flags)
168++{
169++ return security_ops->post_recv_datagram(sk, skb, flags);
170++}
171++
172+ static inline int security_socket_getsockname(struct socket * sock)
173+ {
174+ return security_ops->socket_getsockname(sock);
175+@@ -3033,9 +3102,10 @@ static inline int security_socket_accept
176+ return 0;
177+ }
178+
179+-static inline void security_socket_post_accept(struct socket * sock,
180+- struct socket * newsock)
181++static inline int security_socket_post_accept(struct socket *sock,
182++ struct socket *newsock)
183+ {
184++ return 0;
185+ }
186+
187+ static inline int security_socket_sendmsg(struct socket * sock,
188+@@ -3051,6 +3121,13 @@ static inline int security_socket_recvms
189+ return 0;
190+ }
191+
192++static inline int security_post_recv_datagram(struct sock *sk,
193++ struct sk_buff *skb,
194++ unsigned int flags);
195++{
196++ return 0;
197++}
198++
199+ static inline int security_socket_getsockname(struct socket * sock)
200+ {
201+ return 0;
202+--- linux-2.6.23.orig/kernel/signal.c 2007-10-10 05:31:38.000000000 +0900
203++++ linux-2.6.23/kernel/signal.c 2007-11-01 17:16:15.000000000 +0900
204+@@ -2196,6 +2196,11 @@ asmlinkage long
205+ sys_kill(int pid, int sig)
206+ {
207+ struct siginfo info;
208++ int ret;
209++
210++ ret = security_task_kill_unlocked(pid, sig);
211++ if (ret)
212++ return ret;
213+
214+ info.si_signo = sig;
215+ info.si_errno = 0;
216+@@ -2251,10 +2256,16 @@ static int do_tkill(int tgid, int pid, i
217+ */
218+ asmlinkage long sys_tgkill(int tgid, int pid, int sig)
219+ {
220++ int ret;
221++
222+ /* This is only valid for single tasks */
223+ if (pid <= 0 || tgid <= 0)
224+ return -EINVAL;
225+
226++ ret = security_task_tgkill_unlocked(tgid, pid, sig);
227++ if (ret)
228++ return ret;
229++
230+ return do_tkill(tgid, pid, sig);
231+ }
232+
233+@@ -2264,10 +2275,16 @@ asmlinkage long sys_tgkill(int tgid, int
234+ asmlinkage long
235+ sys_tkill(int pid, int sig)
236+ {
237++ int ret;
238++
239+ /* This is only valid for single tasks */
240+ if (pid <= 0)
241+ return -EINVAL;
242+
243++ ret = security_task_tkill_unlocked(pid, sig);
244++ if (ret)
245++ return ret;
246++
247+ return do_tkill(0, pid, sig);
248+ }
249+
250+--- linux-2.6.23.orig/net/socket.c 2007-10-10 05:31:38.000000000 +0900
251++++ linux-2.6.23/net/socket.c 2007-11-01 17:16:15.000000000 +0900
252+@@ -1434,13 +1434,16 @@ asmlinkage long sys_accept(int fd, struc
253+ goto out_fd;
254+ }
255+
256++ /* Filter connections from unwanted peers like TCP Wrapper. */
257++ err = security_socket_post_accept(sock, newsock);
258++ if (err)
259++ goto out_fd;
260++
261+ /* File flags are not inherited via accept() unlike another OSes. */
262+
263+ fd_install(newfd, newfile);
264+ err = newfd;
265+
266+- security_socket_post_accept(sock, newsock);
267+-
268+ out_put:
269+ fput_light(sock->file, fput_needed);
270+ out:
271+--- linux-2.6.23.orig/security/dummy.c 2007-10-10 05:31:38.000000000 +0900
272++++ linux-2.6.23/security/dummy.c 2007-11-01 17:16:15.000000000 +0900
273+@@ -564,6 +564,21 @@ static int dummy_task_kill (struct task_
274+ return 0;
275+ }
276+
277++static int dummy_task_kill_unlocked(int pid, int sig)
278++{
279++ return 0;
280++}
281++
282++static int dummy_task_tkill_unlocked(int pid, int sig)
283++{
284++ return 0;
285++}
286++
287++static int dummy_task_tgkill_unlocked(int tgid, int pid, int sig)
288++{
289++ return 0;
290++}
291++
292+ static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
293+ unsigned long arg4, unsigned long arg5)
294+ {
295+@@ -741,10 +756,10 @@ static int dummy_socket_accept (struct s
296+ return 0;
297+ }
298+
299+-static void dummy_socket_post_accept (struct socket *sock,
300+- struct socket *newsock)
301++static int dummy_socket_post_accept(struct socket *sock,
302++ struct socket *newsock)
303+ {
304+- return;
305++ return 0;
306+ }
307+
308+ static int dummy_socket_sendmsg (struct socket *sock, struct msghdr *msg,
309+@@ -759,6 +774,13 @@ static int dummy_socket_recvmsg (struct
310+ return 0;
311+ }
312+
313++static int dummy_post_recv_datagram(struct sock *sk,
314++ struct sk_buff *skb,
315++ unsigned int flags)
316++{
317++ return 0;
318++}
319++
320+ static int dummy_socket_getsockname (struct socket *sock)
321+ {
322+ return 0;
323+@@ -1053,6 +1075,9 @@ void security_fixup_ops (struct security
324+ set_to_dummy_if_null(ops, task_movememory);
325+ set_to_dummy_if_null(ops, task_wait);
326+ set_to_dummy_if_null(ops, task_kill);
327++ set_to_dummy_if_null(ops, task_kill_unlocked);
328++ set_to_dummy_if_null(ops, task_tkill_unlocked);
329++ set_to_dummy_if_null(ops, task_tgkill_unlocked);
330+ set_to_dummy_if_null(ops, task_prctl);
331+ set_to_dummy_if_null(ops, task_reparent_to_init);
332+ set_to_dummy_if_null(ops, task_to_inode);
333+@@ -1096,6 +1121,7 @@ void security_fixup_ops (struct security
334+ set_to_dummy_if_null(ops, socket_post_accept);
335+ set_to_dummy_if_null(ops, socket_sendmsg);
336+ set_to_dummy_if_null(ops, socket_recvmsg);
337++ set_to_dummy_if_null(ops, post_recv_datagram);
338+ set_to_dummy_if_null(ops, socket_getsockname);
339+ set_to_dummy_if_null(ops, socket_getpeername);
340+ set_to_dummy_if_null(ops, socket_setsockopt);
341+--- linux-2.6.23.orig/net/core/datagram.c 2007-10-10 05:31:38.000000000 +0900
342++++ linux-2.6.23/net/core/datagram.c 2007-11-01 17:16:15.000000000 +0900
343+@@ -55,6 +55,7 @@
344+ #include <net/checksum.h>
345+ #include <net/sock.h>
346+ #include <net/tcp_states.h>
347++#include <linux/security.h>
348+
349+ /*
350+ * Is a socket 'connection oriented' ?
351+@@ -178,6 +179,27 @@ struct sk_buff *skb_recv_datagram(struct
352+ } else
353+ skb = skb_dequeue(&sk->sk_receive_queue);
354+
355++ error = security_post_recv_datagram(sk, skb, flags);
356++ if (error) {
357++ unsigned long cpu_flags;
358++
359++ if (!(flags & MSG_PEEK))
360++ goto no_peek;
361++
362++ spin_lock_irqsave(&sk->sk_receive_queue.lock,
363++ cpu_flags);
364++ if (skb == skb_peek(&sk->sk_receive_queue)) {
365++ __skb_unlink(skb,
366++ &sk->sk_receive_queue);
367++ atomic_dec(&skb->users);
368++ }
369++ spin_unlock_irqrestore(&sk->sk_receive_queue.lock,
370++ cpu_flags);
371++no_peek:
372++ skb_free_datagram(sk, skb);
373++ goto no_packet;
374++ }
375++
376+ if (skb)
377+ return skb;
378+
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-realpath.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-realpath.diff (revision 755)
@@ -0,0 +1,682 @@
1+Basic functions to get canonicalized absolute pathnames
2+for TOMOYO Linux. Even the requested pathname is symlink()ed
3+or chroot()ed, TOMOYO Linux uses the original pathname.
4+
5+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
6+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
7+ security/tomoyo/realpath.c | 670 +++++++++++++++++++++++++++++++++++++++++++++
8+ 1 file changed, 670 insertions(+)
9+
10+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
11++++ linux-2.6.23/security/tomoyo/realpath.c 2007-11-02 13:48:04.000000000 +0900
12+@@ -0,0 +1,670 @@
13++/*
14++ * security/tomoyo/realpath.c
15++ *
16++ * Get the canonicalized absolute pathnames.
17++ * The basis for TOMOYO Linux.
18++ */
19++
20++#include "tomoyo.h"
21++#include "realpath.h"
22++
23++/***** realpath handler *****/
24++
25++static int tmy_print_ascii(const char *sp, const char *cp,
26++ int *buflen0, char **end0)
27++{
28++ int buflen = *buflen0;
29++ char *end = *end0;
30++
31++ while (sp <= cp) {
32++ unsigned char c;
33++
34++ c = *(unsigned char *) cp;
35++ if (c == '\\') {
36++ buflen -= 2;
37++ if (buflen < 0)
38++ goto out;
39++ *--end = '\\';
40++ *--end = '\\';
41++ } else if (c > ' ' && c < 127) {
42++ if (--buflen < 0)
43++ goto out;
44++ *--end = (char) c;
45++ } else {
46++ buflen -= 4;
47++ if (buflen < 0)
48++ goto out;
49++ *--end = (c & 7) + '0';
50++ *--end = ((c >> 3) & 7) + '0';
51++ *--end = (c >> 6) + '0';
52++ *--end = '\\';
53++ }
54++ cp--;
55++ }
56++
57++ *buflen0 = buflen;
58++ *end0 = end;
59++
60++ return 0;
61++out: ;
62++ return -ENOMEM;
63++}
64++
65++/**
66++ * tmy_get_absolute_path - return the realpath of a dentry.
67++ * @dentry: pointer to "struct dentry".
68++ * @vfsmnt: pointer to "struct vfsmount" to which the @dentry belongs.
69++ * @buffer: size of buffer to save the result.
70++ * @buflen: size of @buffer .
71++ *
72++ * Returns zero on success.
73++ * Returns nonzero on failure.
74++ *
75++ * Caller holds the dcache_lock.
76++ * Based on __d_path() in fs/dcache.c
77++ *
78++ * Unlike d_path(), this function traverses upto the root directory of
79++ * process's namespace.
80++ *
81++ * If @dentry is a directory, trailing '/' is appended.
82++ * Characters other than ' ' < c < 127 are converted to \ooo style octal string.
83++ * Character \ is converted to \\ string.
84++ */
85++static int tmy_get_absolute_path(struct dentry *dentry,
86++ struct vfsmount *vfsmnt,
87++ char *buffer,
88++ int buflen)
89++{
90++ char *start = buffer;
91++ char *end = buffer + buflen;
92++ bool is_dir = (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode));
93++ const char *sp;
94++ const char *cp;
95++
96++ if (buflen < 256)
97++ goto out;
98++
99++ *--end = '\0';
100++ buflen--;
101++
102++ while (1) {
103++ struct dentry *parent;
104++
105++ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
106++ /* Global root? */
107++ spin_lock(&vfsmount_lock);
108++ if (vfsmnt->mnt_parent == vfsmnt) {
109++ spin_unlock(&vfsmount_lock);
110++ break;
111++ }
112++ dentry = vfsmnt->mnt_mountpoint;
113++ vfsmnt = vfsmnt->mnt_parent;
114++ spin_unlock(&vfsmount_lock);
115++ continue;
116++ }
117++
118++ if (is_dir) {
119++ is_dir = 0;
120++ *--end = '/';
121++ buflen--;
122++ }
123++
124++ parent = dentry->d_parent;
125++ sp = dentry->d_name.name;
126++ cp = sp + dentry->d_name.len - 1;
127++
128++ /* Exception: Use /proc/self/ rather than */
129++ /* /proc/\$/ for current process. */
130++ if (IS_ROOT(parent) &&
131++ *sp > '0' && *sp <= '9' && parent->d_sb &&
132++ parent->d_sb->s_magic == PROC_SUPER_MAGIC) {
133++
134++ char *ep;
135++ const pid_t pid = (pid_t) simple_strtoul(sp, &ep, 10);
136++
137++ if (!*ep && pid == current->tgid) {
138++ sp = "self";
139++ cp = sp + 3;
140++ }
141++
142++ }
143++
144++ if (tmy_print_ascii(sp, cp, &buflen, &end))
145++ goto out;
146++
147++ if (--buflen < 0)
148++ goto out;
149++ *--end = '/';
150++
151++ dentry = parent;
152++ }
153++ if (*end == '/') {
154++ buflen++;
155++ end++;
156++ }
157++
158++ sp = dentry->d_name.name;
159++ cp = sp + dentry->d_name.len - 1;
160++
161++ if (tmy_print_ascii(sp, cp, &buflen, &end))
162++ goto out;
163++
164++ /* Move the pathname to the top of the buffer. */
165++ memmove(start, end, strlen(end) + 1);
166++ return 0;
167++out: ;
168++ return -ENOMEM;
169++}
170++
171++/**
172++ * tmy_realpath_dentry2 - return the realpath of a dentry.
173++ * @dentry: pointer to "struct dentry".
174++ * @mnt: pointer to "struct vfsmount" to which the @dentry belongs.
175++ * @newname: buffer to save the result.
176++ * @newname_len: size of @newname .
177++ *
178++ * Returns zero on success.
179++ * Returns nonzero on failure.
180++ */
181++int tmy_realpath_dentry2(struct dentry *dentry,
182++ struct vfsmount *mnt,
183++ char *newname,
184++ int newname_len)
185++{
186++ int error;
187++ struct dentry *d_dentry;
188++ struct vfsmount *d_mnt;
189++
190++ if (!dentry || !mnt || !newname || newname_len <= 0)
191++ return -EINVAL;
192++
193++ d_dentry = dget(dentry);
194++ d_mnt = mntget(mnt);
195++
196++ /***** CRITICAL SECTION START *****/
197++ spin_lock(&dcache_lock);
198++ error = tmy_get_absolute_path(d_dentry, d_mnt, newname, newname_len);
199++ spin_unlock(&dcache_lock);
200++ /***** CRITICAL SECTION END *****/
201++
202++ dput(d_dentry);
203++ mntput(d_mnt);
204++ return error;
205++}
206++
207++/**
208++ * tmy_realpath_dentry - return the realpath of a dentry.
209++ * @dentry: pointer to "struct dentry".
210++ * @mnt: pointer to "struct vfsmount" to which the @dentry belongs.
211++ *
212++ * Returns realpath(3) of the @dentry on success.
213++ * Returns NULL on failure.
214++ *
215++ * This function uses tmy_alloc(), so caller must call tmy_free()
216++ * if this function didn't return NULL.
217++ */
218++char *tmy_realpath_dentry(struct dentry *dentry, struct vfsmount *mnt)
219++{
220++ char *buf = tmy_alloc(TMY_MAX_PATHNAME_LEN);
221++
222++ if (buf &&
223++ tmy_realpath_dentry2(dentry, mnt, buf,
224++ TMY_MAX_PATHNAME_LEN - 1) == 0)
225++ return buf;
226++
227++ tmy_free(buf);
228++ return NULL;
229++}
230++
231++/**
232++ * tmy_realpath - return the realpath of a pathname.
233++ * @pathname: pathname to report.
234++ *
235++ * Returns realpath(3) of the @pathname on success.
236++ * Returns NULL on failure.
237++ *
238++ * This function uses tmy_alloc(), so caller must call tmy_free()
239++ * if this function didn't return NULL.
240++ */
241++char *tmy_realpath(const char *pathname)
242++{
243++ struct nameidata nd;
244++
245++ if (pathname && path_lookup(pathname, LOOKUP_FOLLOW, &nd) == 0) {
246++ char *buf = tmy_realpath_dentry(nd.dentry, nd.mnt);
247++
248++ path_release(&nd);
249++ return buf;
250++ }
251++
252++ return NULL;
253++}
254++
255++/**
256++ * tmy_realpath_nofollow - return the realpath of a pathname.
257++ * @pathname: pathname to report.
258++ *
259++ * Returns realpath(3) of the @pathname on success.
260++ * Returns NULL on failure.
261++ *
262++ * Unlike tmy_realpath(), this function doesn't follow if @pathname is
263++ * a symbolic link.
264++ *
265++ * This function uses tmy_alloc(), so caller must call tmy_free()
266++ * if this function didn't return NULL.
267++ */
268++char *tmy_realpath_nofollow(const char *pathname)
269++{
270++ struct nameidata nd;
271++
272++ if (pathname && path_lookup(pathname, 0, &nd) == 0) {
273++ char *buf = tmy_realpath_dentry(nd.dentry, nd.mnt);
274++
275++ path_release(&nd);
276++ return buf;
277++ }
278++
279++ return NULL;
280++}
281++
282++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)
283++/* tmy_get_absolute_path() for "struct ctl_table". */
284++static int tmy_sysctl_path(struct ctl_table *table, char *buffer, int buflen)
285++{
286++ char *end = buffer + buflen;
287++
288++ if (buflen < 256)
289++ goto out;
290++
291++ *--end = '\0';
292++ buflen--;
293++
294++ buflen -= 9; /* for "/proc/sys" prefix */
295++
296++ while (table) {
297++ char buf[32];
298++ const char *sp = table->procname;
299++ const char *cp;
300++
301++ if (!sp) {
302++ memset(buf, 0, sizeof(buf));
303++ snprintf(buf, sizeof(buf) - 1, "=%d=", table->ctl_name);
304++ sp = buf;
305++ }
306++ cp = strchr(sp, '\0') - 1;
307++
308++ if (tmy_print_ascii(sp, cp, &buflen, &end))
309++ goto out;
310++
311++ if (--buflen < 0)
312++ goto out;
313++
314++ *--end = '/';
315++ table = table->parent;
316++ }
317++
318++ /* Move the pathname to the top of the buffer. */
319++ memmove(buffer, "/proc/sys", 9);
320++ memmove(buffer + 9, end, strlen(end) + 1);
321++ return 0;
322++out: ;
323++ return -ENOMEM;
324++}
325++
326++/**
327++ * sysctlpath_from_table - return the realpath of a ctl_table.
328++ * @table: pointer to "struct ctl_table".
329++ *
330++ * Returns realpath(3) of the @table on success.
331++ * Returns NULL on failure.
332++ *
333++ * This function uses tmy_alloc(), so caller must call tmy_free()
334++ * if this function didn't return NULL.
335++ */
336++char *sysctlpath_from_table(struct ctl_table *table)
337++{
338++ char *buf = tmy_alloc(TMY_MAX_PATHNAME_LEN);
339++
340++ if (buf && tmy_sysctl_path(table, buf, TMY_MAX_PATHNAME_LEN - 1) == 0)
341++ return buf;
342++
343++ tmy_free(buf);
344++ return NULL;
345++}
346++#endif
347++
348++/***** Private memory allocator. *****/
349++
350++/*
351++ * Round up an integer so that the returned pointers are appropriately aligned.
352++ * FIXME: Are there more requirements that is needed for assigning value
353++ * atomically?
354++ */
355++static inline unsigned int tmy_roundup(const unsigned int size)
356++{
357++ if (sizeof(void *) >= sizeof(long))
358++ return ((size + sizeof(void *) - 1) / sizeof(void *))
359++ * sizeof(void *);
360++
361++ return ((size + sizeof(long) - 1) / sizeof(long)) * sizeof(long);
362++}
363++
364++static unsigned int allocated_memory_for_elements;
365++
366++/**
367++ * tmy_get_memory_used_for_elements - get memory usage for private data.
368++ *
369++ * Returns size of memory allocated for keeping individual ACL elements.
370++ */
371++unsigned int tmy_get_memory_used_for_elements(void)
372++{
373++ return allocated_memory_for_elements;
374++}
375++
376++/**
377++ * tmy_alloc_element - allocate memory for structures.
378++ * @size: requested size in bytes.
379++ *
380++ * Returns '\0'-initialized memory region on success.
381++ * Returns NULL on failure.
382++ *
383++ * This function allocates memory for keeping ACL entries.
384++ * The RAM is chunked, so NEVER try to kfree() the returned pointer.
385++ */
386++void *tmy_alloc_element(const unsigned int size)
387++{
388++ static DEFINE_MUTEX(mutex);
389++ static char *buf;
390++ static unsigned int buf_used_len = PAGE_SIZE;
391++ char *ptr = NULL;
392++ const unsigned int word_aligned_size = tmy_roundup(size);
393++
394++ if (word_aligned_size > PAGE_SIZE)
395++ return NULL;
396++
397++ mutex_lock(&mutex);
398++
399++ if (buf_used_len + word_aligned_size > PAGE_SIZE) {
400++ ptr = kzalloc(PAGE_SIZE, GFP_KERNEL);
401++
402++ if (!ptr) {
403++ printk(KERN_INFO "ERROR: "
404++ "Out of memory for tmy_alloc_element().\n");
405++ if (!sbin_init_started)
406++ panic("MAC Initialization failed.\n");
407++ } else {
408++ buf = ptr;
409++ allocated_memory_for_elements += PAGE_SIZE;
410++ buf_used_len = word_aligned_size;
411++ ptr = buf;
412++ }
413++
414++ } else if (word_aligned_size) {
415++ unsigned int i;
416++
417++ ptr = buf + buf_used_len;
418++ buf_used_len += word_aligned_size;
419++
420++ for (i = 0; i < word_aligned_size; i++) {
421++ if (ptr[i]) { /* This must not happen! */
422++ printk(KERN_ERR
423++ "WARNING: Reserved memory was tainted! "
424++ "The system might go wrong.\n");
425++ ptr[i] = '\0';
426++ }
427++ }
428++
429++ }
430++
431++ mutex_unlock(&mutex);
432++ return ptr;
433++}
434++
435++/***** Shared memory allocator. *****/
436++
437++static unsigned int allocated_memory_for_savename;
438++
439++/**
440++ * tmy_get_memory_used_for_save_name - get memory usage for shared data.
441++ *
442++ * Returns size of memory allocated for keeping string tokens.
443++ */
444++unsigned int tmy_get_memory_used_for_save_name(void)
445++{
446++ return allocated_memory_for_savename;
447++}
448++
449++#define MAX_HASH 256
450++
451++/* List of tokens. */
452++struct name_entry {
453++ struct list_head list;
454++ struct path_info entry;
455++};
456++
457++/* List of free memory. */
458++struct free_memory_block {
459++ struct list_head list;
460++ char *ptr; /* Pointer to a free area. */
461++ int len; /* Length of the area. */
462++};
463++
464++/**
465++ * tmy_save_name - keep the given token on the RAM.
466++ * @name: the string token to remember.
467++ *
468++ * Returns pointer to memory region on success.
469++ * Returns NULL on failure.
470++ *
471++ * This function allocates memory for keeping any string data.
472++ * The RAM is shared, so NEVER try to modify or kfree() the returned name.
473++ */
474++const struct path_info *tmy_save_name(const char *name)
475++{
476++ static bool first_call = 1;
477++ static DEFINE_MUTEX(mutex);
478++ static LIST_HEAD(fmb_list);
479++ struct free_memory_block *fmb;
480++ static struct list_head name_list[MAX_HASH]; /* The list of names. */
481++ struct name_entry *ptr;
482++ unsigned int hash;
483++ int len;
484++ bool found = 0;
485++ if (!name)
486++ return NULL;
487++ len = strlen(name) + 1;
488++ if (len > TMY_MAX_PATHNAME_LEN) {
489++ printk(KERN_INFO "ERROR: Name too long for tmy_save_name().\n");
490++ return NULL;
491++ }
492++ hash = full_name_hash((const unsigned char *) name, len - 1);
493++ /* List access in this function is protected by mutex. */
494++ mutex_lock(&mutex);
495++ if (first_call) {
496++ int i;
497++ first_call = 0;
498++ for (i = 0; i < MAX_HASH; i++)
499++ INIT_LIST_HEAD(&name_list[i]);
500++ if (TMY_MAX_PATHNAME_LEN > PAGE_SIZE)
501++ panic("Bad size.");
502++ }
503++ list_for_each_entry(ptr, &name_list[hash % MAX_HASH], list) {
504++ if (hash == ptr->entry.hash &&
505++ strcmp(name, ptr->entry.name) == 0)
506++ goto out;
507++ }
508++ list_for_each_entry(fmb, &fmb_list, list) {
509++ if (len <= fmb->len) {
510++ found = 1;
511++ break;
512++ }
513++ }
514++ if (!found) {
515++ char *cp;
516++ cp = kzalloc(PAGE_SIZE, GFP_KERNEL);
517++ if (!cp)
518++ goto out2;
519++ fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
520++ if (!fmb) {
521++ kfree(cp);
522++out2: ;
523++ printk(KERN_INFO
524++ "ERROR: Out of memory for tmy_save_name().\n");
525++ if (!sbin_init_started)
526++ panic("MAC Initialization failed.\n");
527++ ptr = NULL;
528++ goto out;
529++ }
530++ allocated_memory_for_savename += PAGE_SIZE;
531++ fmb->ptr = cp;
532++ fmb->len = PAGE_SIZE;
533++ list_add_tail(&fmb->list, &fmb_list);
534++ }
535++ ptr = tmy_alloc_element(sizeof(*ptr));
536++ if (!ptr)
537++ goto out;
538++ ptr->entry.name = fmb->ptr;
539++ memmove(fmb->ptr, name, len);
540++ tmy_fill_path_info(&ptr->entry);
541++ fmb->ptr += len;
542++ fmb->len -= len;
543++ list_add_tail(&ptr->list, &name_list[hash % MAX_HASH]);
544++ if (fmb->len == 0) {
545++ list_del(&fmb->list); /* Protected by mutex. */
546++ kfree(fmb);
547++ }
548++out: ;
549++ mutex_unlock(&mutex);
550++ return ptr ? &ptr->entry : NULL;
551++}
552++
553++/***** Dynamic memory allocator. *****/
554++
555++/* List of temporary memory blocks. */
556++struct cache_entry {
557++ struct list_head list;
558++ void *ptr;
559++ int size;
560++};
561++
562++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
563++static struct kmem_cache *tmy_cachep;
564++#else
565++static kmem_cache_t *tmy_cachep;
566++#endif
567++
568++/**
569++ * tmy_realpath_init - initialize memory allocator.
570++ */
571++static int __init tmy_realpath_init(void)
572++{
573++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
574++ tmy_cachep = kmem_cache_create("tomoyo_cache",
575++ sizeof(struct cache_entry),
576++ 0, SLAB_PANIC, NULL);
577++#else
578++ tmy_cachep = kmem_cache_create("tomoyo_cache",
579++ sizeof(struct cache_entry),
580++ 0, SLAB_PANIC, NULL, NULL);
581++#endif
582++ return 0;
583++}
584++postcore_initcall(tmy_realpath_init);
585++
586++static LIST_HEAD(cache_list);
587++static DEFINE_SPINLOCK(cache_list_lock);
588++static unsigned int dynamic_memory_size;
589++
590++/**
591++ * tmy_get_memory_used_for_dynamic - get memory usage for temporary purpose.
592++ *
593++ * Returns size of memory allocated for keeping temporary purpose.
594++ */
595++unsigned int tmy_get_memory_used_for_dynamic(void)
596++{
597++ return dynamic_memory_size;
598++}
599++
600++/**
601++ * tmy_alloc - allocate memory for temporary purpose.
602++ * @size: requested size in bytes.
603++ *
604++ * Returns '\0'-initialized memory region on success.
605++ * Returns NULL on failure.
606++ *
607++ * This function allocates memory for keeping ACL entries.
608++ * The caller has to call tmy_free() the returned pointer
609++ * when memory is no longer needed.
610++ */
611++void *tmy_alloc(const size_t size)
612++{
613++ void *ret = kzalloc(size, GFP_KERNEL);
614++ struct cache_entry *new_entry;
615++
616++ if (!ret) {
617++ printk(KERN_INFO "ERROR: "
618++ "kmalloc(): Out of memory for tmy_alloc().\n");
619++ return ret;
620++ }
621++
622++ new_entry = kmem_cache_alloc(tmy_cachep, GFP_KERNEL);
623++
624++ if (!new_entry) {
625++ printk(KERN_INFO "ERROR: "
626++ "kmem_cache_alloc(): Out of memory for tmy_alloc().\n");
627++ kfree(ret);
628++ ret = NULL;
629++ } else {
630++ INIT_LIST_HEAD(&new_entry->list);
631++ new_entry->ptr = ret;
632++ new_entry->size = ksize(ret);
633++
634++ /***** CRITICAL SECTION START *****/
635++ spin_lock(&cache_list_lock);
636++ list_add_tail(&new_entry->list, &cache_list);
637++ dynamic_memory_size += new_entry->size;
638++ spin_unlock(&cache_list_lock);
639++ /***** CRITICAL SECTION END *****/
640++ }
641++
642++ return ret;
643++}
644++
645++/**
646++ * tmy_free - free memory allocated by tmy_alloc().
647++ * @p: pointer to memory block allocated by tmy_alloc().
648++ *
649++ * If caller calls this function for multiple times (i.e. double-free() bug) or
650++ * calls this function with invalid pointer, warning message will appear.
651++ * If caller forgets to call this function,
652++ * tmy_get_memory_used_for_dynamic() will indicate memory leaks.
653++ */
654++void tmy_free(const void *p)
655++{
656++ struct list_head *v;
657++ struct cache_entry *entry = NULL;
658++ if (!p)
659++ return;
660++
661++ /***** CRITICAL SECTION START *****/
662++ spin_lock(&cache_list_lock);
663++ list_for_each_prev(v, &cache_list) {
664++ entry = list_entry(v, struct cache_entry, list);
665++ if (entry->ptr != p) {
666++ entry = NULL;
667++ continue;
668++ }
669++ list_del(&entry->list);
670++ dynamic_memory_size -= entry->size;
671++ break;
672++ }
673++ spin_unlock(&cache_list_lock);
674++ /***** CRITICAL SECTION END *****/
675++
676++ if (entry) {
677++ kfree(p);
678++ kmem_cache_free(tmy_cachep, entry);
679++ } else
680++ printk(KERN_INFO "BUG: tmy_free() with invalid pointer.\n");
681++
682++}
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-mount.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-mount.diff (revision 755)
@@ -0,0 +1,944 @@
1+Mount access control functions for TOMOYO Linux.
2+TOMOYO Linux checks permission according to
3+device name, mount point, filesystem type and optional flags.
4+TOMOYO Linux also checks permission in umount and pivot_root.
5+
6+Each permission can be automatically accumulated into
7+the policy using 'learning mode'.
8+
9+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
10+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
11+ security/tomoyo/mount.c | 928 ++++++++++++++++++++++++++++++++++++++++++++++++
12+ 1 file changed, 928 insertions(+)
13+
14+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
15++++ linux-2.6.23/security/tomoyo/mount.c 2007-11-09 17:17:06.000000000 +0900
16+@@ -0,0 +1,928 @@
17++/*
18++ * security/tomoyo/mount.c
19++ *
20++ * Mount access control functions for TOMOYO Linux.
21++ */
22++
23++#include "tomoyo.h"
24++#include "realpath.h"
25++
26++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
27++static inline void put_filesystem(struct file_system_type *fs)
28++{
29++ module_put(fs->owner);
30++}
31++#endif
32++
33++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
34++#define MS_UNBINDABLE (1<<17) /* change to unbindable */
35++#define MS_PRIVATE (1<<18) /* change to private */
36++#define MS_SLAVE (1<<19) /* change to slave */
37++#define MS_SHARED (1<<20) /* change to shared */
38++#endif
39++
40++/***** KEYWORDS for mount restrictions. *****/
41++
42++#define MOUNT_BIND_KEYWORD "--bind"
43++#define MOUNT_MOVE_KEYWORD "--move"
44++#define MOUNT_REMOUNT_KEYWORD "--remount"
45++#define MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable"
46++#define MOUNT_MAKE_PRIVATE_KEYWORD "--make-private"
47++#define MOUNT_MAKE_SLAVE_KEYWORD "--make-slave"
48++#define MOUNT_MAKE_SHARED_KEYWORD "--make-shared"
49++
50++/***** The structure for mount restrictions. *****/
51++
52++struct mount_entry {
53++ struct list_head list;
54++ const struct path_info *dev_name;
55++ const struct path_info *dir_name;
56++ const struct path_info *fs_type;
57++ unsigned int flags; /* Mount flags. */
58++ bool is_deleted;
59++};
60++
61++struct no_umount_entry {
62++ struct list_head list;
63++ const struct path_info *dir;
64++ bool is_deleted;
65++};
66++
67++/************************ MOUNT RESTRICTION HANDLER ************************/
68++
69++static LIST_HEAD(mount_list);
70++
71++/* Add or remove a mount entry. */
72++static int tmy_add_mount_acl(const char *dev_name,
73++ const char *dir_name,
74++ const char *fs_type,
75++ const unsigned int flags,
76++ const bool is_delete)
77++{
78++ struct mount_entry *new_entry;
79++ struct mount_entry *ptr;
80++ const struct path_info *fs;
81++ const struct path_info *dev;
82++ const struct path_info *dir;
83++ static DEFINE_MUTEX(mutex);
84++ int error = -ENOMEM;
85++
86++ fs = tmy_save_name(fs_type);
87++ if (!fs)
88++ return -EINVAL;
89++
90++ if (!dev_name)
91++ /* Map dev_name to "<NULL>" for if no dev_name given. */
92++ dev_name = "<NULL>";
93++ if (strcmp(fs->name, MOUNT_REMOUNT_KEYWORD) == 0)
94++ /* Fix dev_name to "any" for remount permission. */
95++ dev_name = "any";
96++ if (strcmp(fs->name, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
97++ strcmp(fs->name, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
98++ strcmp(fs->name, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
99++ strcmp(fs->name, MOUNT_MAKE_SHARED_KEYWORD) == 0)
100++ dev_name = "any";
101++
102++ if (!tmy_correct_path(dev_name, 0, 0, 0, __FUNCTION__) ||
103++ !tmy_correct_path(dir_name, 1, 0, 1, __FUNCTION__))
104++ return -EINVAL;
105++
106++ dev = tmy_save_name(dev_name);
107++ if (!dev)
108++ return -ENOMEM;
109++ dir = tmy_save_name(dir_name);
110++ if (!dir)
111++ return -ENOMEM;
112++
113++ mutex_lock(&mutex);
114++
115++ list_for_each_entry(ptr, &mount_list, list) {
116++ if (ptr->flags != flags ||
117++ tmy_pathcmp(ptr->dev_name, dev) ||
118++ tmy_pathcmp(ptr->dir_name, dir) ||
119++ tmy_pathcmp(ptr->fs_type, fs))
120++ continue;
121++ ptr->is_deleted = is_delete;
122++ error = 0;
123++ goto out;
124++ }
125++
126++ if (is_delete) {
127++ error = -ENOENT;
128++ goto out;
129++ }
130++
131++ new_entry = tmy_alloc_element(sizeof(*new_entry));
132++ if (!new_entry)
133++ goto out;
134++
135++ new_entry->dev_name = dev;
136++ new_entry->dir_name = dir;
137++ new_entry->fs_type = fs;
138++ new_entry->flags = flags;
139++ list_add_tail_mb(&new_entry->list, &mount_list);
140++ error = 0;
141++out: ;
142++ mutex_unlock(&mutex);
143++ return error;
144++}
145++
146++/* Print error message for mount request. */
147++static inline int tmy_mount_perm_error(char *dev_name,
148++ char *dir_name,
149++ char *type,
150++ unsigned long flags,
151++ const u8 profile,
152++ const unsigned int mode)
153++{
154++ int error = -EPERM;
155++ const char *realname1 = tmy_realpath(dev_name);
156++ const char *realname2 = tmy_realpath(dir_name);
157++ const char *exename = tmy_get_exe();
158++ const bool is_enforce = (mode == 3);
159++
160++ if (!strcmp(type, MOUNT_REMOUNT_KEYWORD)) {
161++ tmy_audit(KERN_WARNING "TOMOYO-%s: mount -o remount %s 0x%lX "
162++ "(pid=%d:exe=%s): Permission denied.\n",
163++ tmy_getmsg(is_enforce),
164++ realname2 ? realname2 : dir_name, flags,
165++ current->pid, exename);
166++ if (is_enforce &&
167++ !tmy_supervisor("# %s is requesting\nmount -o remount %s\n",
168++ exename, realname2 ? realname2 : dir_name))
169++ error = 0;
170++
171++ } else if (!strcmp(type, MOUNT_BIND_KEYWORD) ||
172++ !strcmp(type, MOUNT_MOVE_KEYWORD)) {
173++ tmy_audit(KERN_WARNING "TOMOYO-%s: mount %s %s %s 0x%lX "
174++ "(pid=%d:exe=%s): Permission denied.\n",
175++ tmy_getmsg(is_enforce), type,
176++ realname1 ? realname1 : dev_name,
177++ realname2 ? realname2 : dir_name,
178++ flags, current->pid, exename);
179++ if (is_enforce &&
180++ tmy_supervisor("# %s is requesting\nmount %s %s %s 0x%lX\n",
181++ exename, type,
182++ realname1 ? realname1 : dev_name,
183++ realname2 ? realname2 : dir_name,
184++ flags) == 0)
185++ error = 0;
186++
187++ } else if (!strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
188++ !strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) ||
189++ !strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) ||
190++ !strcmp(type, MOUNT_MAKE_SHARED_KEYWORD)) {
191++ tmy_audit(KERN_WARNING "TOMOYO-%s: mount %s %s 0x%lX "
192++ "(pid=%d:exe=%s): Permission denied.\n",
193++ tmy_getmsg(is_enforce), type,
194++ realname2 ? realname2 : dir_name,
195++ flags, current->pid, exename);
196++ if (is_enforce &&
197++ tmy_supervisor("# %s is requesting\nmount %s %s 0x%lX",
198++ exename, type,
199++ realname2 ? realname2 : dir_name,
200++ flags) == 0)
201++ error = 0;
202++
203++ } else {
204++ tmy_audit(KERN_WARNING "TOMOYO-%s: mount -t %s %s %s 0x%lX "
205++ "(pid=%d:exe=%s): Permission denied.\n",
206++ tmy_getmsg(is_enforce), type,
207++ realname1 ? realname1 : dev_name,
208++ realname2 ? realname2 : dir_name,
209++ flags, current->pid, exename);
210++ if (is_enforce &&
211++ tmy_supervisor("# %s is requesting\n"
212++ "mount -t %s %s %s 0x%lX\n",
213++ exename, type,
214++ realname1 ? realname1 : dev_name,
215++ realname2 ? realname2 : dir_name,
216++ flags) == 0)
217++ error = 0;
218++
219++ }
220++
221++ tmy_free(exename);
222++ tmy_free(realname2);
223++ tmy_free(realname1);
224++ return error;
225++}
226++
227++/**
228++ * tmy_mount_perm - check for mount permission.
229++ * @dev_name: pointer to device name. May be NULL.
230++ * @dir_name: pointer to mount point.
231++ * @type: pointer to filesystem. May be NULL.
232++ * @flags: mount flags.
233++ *
234++ * Returns zero if permission granted.
235++ * Returns nonzero if permission denied.
236++ */
237++int tmy_mount_perm(char *dev_name,
238++ char *dir_name,
239++ char *type,
240++ unsigned long flags)
241++{
242++ const u8 profile = TMY_SECURITY->domain->profile;
243++ const unsigned int mode = tmy_flags(TMY_RESTRICT_MOUNT);
244++ const bool is_enforce = (mode == 3);
245++ int error = -EPERM;
246++
247++ if (!mode)
248++ return 0;
249++ if (!type)
250++ type = "<NULL>";
251++ if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
252++ flags &= ~MS_MGC_MSK;
253++
254++ switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) {
255++ case MS_REMOUNT:
256++ case MS_MOVE:
257++ case MS_BIND:
258++ case 0:
259++ break;
260++ default:
261++ tmy_audit(KERN_WARNING "TOMOYO-ERROR: %s%s%sare given "
262++ "for single mount operation.\n",
263++ flags & MS_REMOUNT ? "'remount' " : "",
264++ flags & MS_MOVE ? "'move' " : "",
265++ flags & MS_BIND ? "'bind' " : "");
266++ return -EINVAL;
267++ }
268++
269++ switch (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED)) {
270++ case MS_UNBINDABLE:
271++ case MS_PRIVATE:
272++ case MS_SLAVE:
273++ case MS_SHARED:
274++ case 0:
275++ break;
276++ default:
277++ tmy_audit(KERN_WARNING "TOMOYO-ERROR: %s%s%s%sare given "
278++ "for single mount operation.\n",
279++ flags & MS_UNBINDABLE ? "'unbindable' " : "",
280++ flags & MS_PRIVATE ? "'private' " : "",
281++ flags & MS_SLAVE ? "'slave' " : "",
282++ flags & MS_SHARED ? "'shared' " : "");
283++ return -EINVAL;
284++ }
285++
286++ if (flags & MS_REMOUNT)
287++ error = tmy_mount_perm(dev_name, dir_name,
288++ MOUNT_REMOUNT_KEYWORD,
289++ flags & ~MS_REMOUNT);
290++ else if (flags & MS_MOVE)
291++ error = tmy_mount_perm(dev_name, dir_name,
292++ MOUNT_MOVE_KEYWORD,
293++ flags & ~MS_MOVE);
294++ else if (flags & MS_BIND)
295++ error = tmy_mount_perm(dev_name, dir_name,
296++ MOUNT_BIND_KEYWORD,
297++ flags & ~MS_BIND);
298++ else if (flags & MS_UNBINDABLE)
299++ error = tmy_mount_perm(dev_name, dir_name,
300++ MOUNT_MAKE_UNBINDABLE_KEYWORD,
301++ flags & ~MS_UNBINDABLE);
302++ else if (flags & MS_PRIVATE)
303++ error = tmy_mount_perm(dev_name, dir_name,
304++ MOUNT_MAKE_PRIVATE_KEYWORD,
305++ flags & ~MS_PRIVATE);
306++ else if (flags & MS_SLAVE)
307++ error = tmy_mount_perm(dev_name, dir_name,
308++ MOUNT_MAKE_SLAVE_KEYWORD,
309++ flags & ~MS_SLAVE);
310++ else if (flags & MS_SHARED)
311++ error = tmy_mount_perm(dev_name, dir_name,
312++ MOUNT_MAKE_SHARED_KEYWORD,
313++ flags & ~MS_SHARED);
314++ else {
315++ struct mount_entry *ptr;
316++ struct file_system_type *fstype = NULL;
317++ const char *requested_dir_name = NULL;
318++ const char *requested_dev_name = NULL;
319++ struct path_info rdev;
320++ struct path_info rdir;
321++ int need_dev = 0;
322++
323++ requested_dir_name = tmy_realpath(dir_name);
324++ if (!requested_dir_name) {
325++ error = -ENOENT;
326++ goto cleanup;
327++ }
328++ rdir.name = requested_dir_name;
329++ tmy_fill_path_info(&rdir);
330++
331++ /* Compare fs name. */
332++ fstype = get_fs_type(type);
333++ if (strcmp(type, MOUNT_REMOUNT_KEYWORD) == 0)
334++ /* Needn't to resolve dev_name */;
335++ else if (strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
336++ strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
337++ strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
338++ strcmp(type, MOUNT_MAKE_SHARED_KEYWORD) == 0)
339++ /* Needn't to resolve dev_name */;
340++ else if (strcmp(type, MOUNT_BIND_KEYWORD) == 0 ||
341++ strcmp(type, MOUNT_MOVE_KEYWORD) == 0) {
342++ requested_dev_name = tmy_realpath(dev_name);
343++ if (!requested_dev_name) {
344++ error = -ENOENT;
345++ goto cleanup;
346++ }
347++ rdev.name = requested_dev_name;
348++ tmy_fill_path_info(&rdev);
349++ need_dev = -1;
350++ } else if (fstype) {
351++ if (fstype->fs_flags & FS_REQUIRES_DEV) {
352++ requested_dev_name = tmy_realpath(dev_name);
353++ if (!requested_dev_name) {
354++ error = -ENOENT;
355++ goto cleanup;
356++ }
357++ rdev.name = requested_dev_name;
358++ tmy_fill_path_info(&rdev);
359++ need_dev = 1;
360++ }
361++ } else {
362++ error = -ENODEV;
363++ goto cleanup;
364++ }
365++
366++ list_for_each_entry(ptr, &mount_list, list) {
367++ if (ptr->is_deleted)
368++ continue;
369++
370++ /* Compare options */
371++ if (ptr->flags != flags)
372++ continue;
373++
374++ /* Compare fs name. */
375++ if (strcmp(type, ptr->fs_type->name))
376++ continue;
377++
378++ /* Compare mount point. */
379++ if (tmy_path_match(&rdir, ptr->dir_name) == 0)
380++ continue;
381++
382++ /* Compare device name. */
383++ if (requested_dev_name &&
384++ tmy_path_match(&rdev, ptr->dev_name) == 0)
385++ continue;
386++
387++ /* OK. */
388++ error = 0;
389++
390++ if (need_dev > 0)
391++ tmy_audit(KERN_DEBUG "TOMOYO-NOTICE: "
392++ "'mount -t %s %s %s 0x%lX' "
393++ "accepted.\n",
394++ type, requested_dev_name,
395++ requested_dir_name, flags);
396++ else if (need_dev < 0)
397++ tmy_audit(KERN_DEBUG "TOMOYO-NOTICE: "
398++ "'mount %s %s %s 0x%lX' accepted.\n",
399++ type, requested_dev_name,
400++ requested_dir_name, flags);
401++ else if (!strcmp(type, MOUNT_REMOUNT_KEYWORD))
402++ tmy_audit(KERN_DEBUG "TOMOYO-NOTICE: "
403++ "'mount -o remount %s 0x%lX' "
404++ "accepted.\n",
405++ requested_dir_name, flags);
406++ else if (!strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
407++ !strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) ||
408++ !strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) ||
409++ !strcmp(type, MOUNT_MAKE_SHARED_KEYWORD))
410++ tmy_audit(KERN_DEBUG "TOMOYO-NOTICE: "
411++ "'mount %s %s 0x%lX' accepted.\n",
412++ type, requested_dir_name, flags);
413++ else
414++ tmy_audit(KERN_DEBUG "TOMOYO-NOTICE: "
415++ "'mount %s on %s 0x%lX' accepted.\n",
416++ type, requested_dir_name, flags);
417++ break;
418++ }
419++
420++ if (error)
421++ error = tmy_mount_perm_error(dev_name, dir_name, type,
422++ flags, profile, mode);
423++
424++ if (error && mode == 1) {
425++ tmy_add_mount_acl(need_dev ?
426++ requested_dev_name : dev_name,
427++ requested_dir_name, type, flags, 0);
428++ tmy_update_counter(TMY_UPDATE_SYSTEMPOLICY);
429++ }
430++
431++cleanup:
432++ tmy_free(requested_dev_name);
433++ tmy_free(requested_dir_name);
434++ if (fstype)
435++ put_filesystem(fstype);
436++
437++ }
438++
439++ if (!is_enforce)
440++ error = 0;
441++ return error;
442++
443++}
444++
445++/**
446++ * tmy_add_mount_policy - add or delete mount policy.
447++ * @data: a line to parse.
448++ * @is_delete: is this delete request?
449++ *
450++ * Returns zero on success.
451++ * Returns nonzero on failure.
452++ */
453++int tmy_add_mount_policy(char *data, const bool is_delete)
454++{
455++ char *cp;
456++ char *cp2;
457++ const char *fs;
458++ const char *dev;
459++ const char *dir;
460++ unsigned int flags = 0;
461++
462++ cp2 = data;
463++ cp = strchr(cp2, ' ');
464++ if (!cp)
465++ return -EINVAL;
466++ *cp = '\0';
467++ dev = cp2;
468++
469++ cp2 = cp + 1;
470++ cp = strchr(cp2, ' ');
471++ if (!cp)
472++ return -EINVAL;
473++ *cp = '\0';
474++ dir = cp2;
475++
476++ cp2 = cp + 1;
477++ cp = strchr(cp2, ' ');
478++ if (!cp)
479++ return -EINVAL;
480++ *cp = '\0';
481++ fs = cp2;
482++
483++ flags = simple_strtoul(cp + 1, NULL, 0);
484++ return tmy_add_mount_acl(dev, dir, fs, flags, is_delete);
485++}
486++
487++/**
488++ * tmy_read_mount_policy - read mount policy.
489++ * @head: pointer to "struct io_buffer".
490++ *
491++ * Returns nonzero if reading incomplete.
492++ * Returns zero otherwise.
493++ */
494++int tmy_read_mount_policy(struct io_buffer *head)
495++{
496++ struct list_head *pos;
497++ list_for_each_cookie(pos, head->read_var2, &mount_list) {
498++ struct mount_entry *ptr;
499++ ptr = list_entry(pos, struct mount_entry, list);
500++ if (ptr->is_deleted)
501++ continue;
502++ if (tmy_io_printf(head, TMY_ALLOW_MOUNT "%s %s %s 0x%x\n",
503++ ptr->dev_name->name, ptr->dir_name->name,
504++ ptr->fs_type->name, ptr->flags))
505++ return -ENOMEM;
506++ }
507++ return 0;
508++}
509++
510++static int tmy_find_conceal(struct nameidata *nd,
511++ struct vfsmount *vfsmnt,
512++ struct dentry *dentry)
513++{
514++ int flag = 0;
515++
516++ if (IS_ROOT(dentry) || !d_unhashed(dentry)) {
517++ while (1) {
518++
519++ if (nd->mnt->mnt_root == vfsmnt->mnt_root &&
520++ nd->dentry == dentry) {
521++ flag = 1;
522++ break;
523++ }
524++
525++ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
526++
527++ spin_lock(&vfsmount_lock);
528++
529++ if (vfsmnt->mnt_parent == vfsmnt) {
530++ spin_unlock(&vfsmount_lock);
531++ break;
532++ }
533++ dentry = vfsmnt->mnt_mountpoint;
534++ vfsmnt = vfsmnt->mnt_parent;
535++
536++ spin_unlock(&vfsmount_lock);
537++
538++ continue;
539++ }
540++ dentry = dentry->d_parent;
541++
542++ }
543++ }
544++
545++ return flag;
546++}
547++
548++/**
549++ * tmy_conceal_mount - check for conceal mount permission.
550++ * @nd: pointer to "struct nameidata".
551++ *
552++ * Returns zero if permission granted.
553++ * Returns nonzero if permission denied.
554++ *
555++ * People seldom mount on directries that have submounts.
556++ * For example, you don't mount on /usr/ directory if /usr/local/ directory
557++ * is already mounted, do you?
558++ * This function forbids such mount requests.
559++ */
560++int tmy_conceal_mount(struct nameidata *nd)
561++{
562++ int flag = 0;
563++ const unsigned int mode = tmy_flags(TMY_DENY_CONCEAL_MOUNT);
564++ const bool is_enforce = (mode == 3);
565++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
566++ struct namespace *namespace = current->namespace;
567++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
568++ struct namespace *namespace = current->nsproxy->namespace;
569++#else
570++ struct mnt_namespace *namespace = current->nsproxy->mnt_ns;
571++#endif
572++
573++ if (!mode)
574++ return 0;
575++
576++ if (namespace) {
577++ struct list_head *p;
578++
579++ list_for_each(p, &namespace->list) {
580++ struct vfsmount *vfsmnt =
581++ list_entry(p, struct vfsmount, mnt_list);
582++ struct dentry *dentry = vfsmnt->mnt_root;
583++
584++ spin_lock(&dcache_lock);
585++
586++ flag = tmy_find_conceal(nd, vfsmnt, dentry);
587++
588++ spin_unlock(&dcache_lock);
589++
590++ if (flag)
591++ break;
592++ }
593++ }
594++
595++
596++ if (flag) {
597++ int error = -EPERM;
598++ char *dir;
599++ dir = tmy_realpath_dentry(nd->dentry, nd->mnt);
600++ if (dir) {
601++ const char *exename = tmy_get_exe();
602++ tmy_audit("TOMOYO-%s: mount %s (pid=%d:exe=%s): "
603++ "Permission denied.\n",
604++ tmy_getmsg(is_enforce),
605++ dir, current->pid, exename);
606++ if (is_enforce &&
607++ tmy_supervisor("# %s is requesting\nmount on %s\n",
608++ exename, dir) == 0)
609++ error = 0;
610++
611++ tmy_free(exename);
612++ }
613++ tmy_free(dir);
614++
615++ if (is_enforce)
616++ return error;
617++ }
618++
619++ return 0;
620++}
621++
622++/************************ UMOUNT RESTRICTION HANDLER ************************/
623++
624++static LIST_HEAD(no_umount_list);
625++
626++/* Add or remove a no-unmount entry. */
627++static int tmy_add_no_umount_acl(const char *dir, const bool is_delete)
628++{
629++ struct no_umount_entry *new_entry;
630++ struct no_umount_entry *ptr;
631++ const struct path_info *saved_dir;
632++ static DEFINE_MUTEX(mutex);
633++ int error = -ENOMEM;
634++
635++ if (!tmy_correct_path(dir, 1, 0, 1, __FUNCTION__))
636++ return -EINVAL;
637++ saved_dir = tmy_save_name(dir);
638++ if (!saved_dir)
639++ return -ENOMEM;
640++
641++ mutex_lock(&mutex);
642++
643++ list_for_each_entry(ptr, &no_umount_list, list) {
644++ if (ptr->dir == saved_dir) {
645++ ptr->is_deleted = is_delete;
646++ error = 0;
647++ goto out;
648++ }
649++ }
650++
651++ if (is_delete) {
652++ error = -ENOENT;
653++ goto out;
654++ }
655++
656++ new_entry = tmy_alloc_element(sizeof(*new_entry));
657++ if (!new_entry)
658++ goto out;
659++
660++ new_entry->dir = saved_dir;
661++ list_add_tail_mb(&new_entry->list, &no_umount_list);
662++ error = 0;
663++out: ;
664++
665++ mutex_unlock(&mutex);
666++
667++ return error;
668++}
669++
670++/**
671++ * tmy_umount_perm - check for no-unmount permission.
672++ * @mnt: pointer to "struct vfsmount".
673++ *
674++ * Returns zero if permission granted.
675++ * Returns nonzero if permission denied.
676++ */
677++int tmy_umount_perm(struct vfsmount *mnt)
678++{
679++ int error = -EPERM;
680++ const char *dir0;
681++ const unsigned int mode = tmy_flags(TMY_RESTRICT_UMOUNT);
682++ const bool is_enforce = (mode == 3);
683++
684++ if (!mode)
685++ return 0;
686++
687++ dir0 = tmy_realpath_dentry(mnt->mnt_root, mnt);
688++
689++ if (dir0) {
690++ struct no_umount_entry *ptr;
691++ struct path_info dir;
692++ bool found = 0;
693++
694++ dir.name = dir0;
695++ tmy_fill_path_info(&dir);
696++
697++ list_for_each_entry(ptr, &no_umount_list, list) {
698++ if (ptr->is_deleted)
699++ continue;
700++ if (tmy_path_match(&dir, ptr->dir)) {
701++ found = 1;
702++ break;
703++ }
704++ }
705++
706++ if (found) {
707++ const char *exename = tmy_get_exe();
708++ tmy_audit("TOMOYO-%s: umount %s (pid=%d:exe=%s): "
709++ "Permission denied.\n",
710++ tmy_getmsg(is_enforce),
711++ dir0, current->pid, exename);
712++ if (is_enforce &&
713++ tmy_supervisor("# %s is requesting\nunmount %s\n",
714++ exename, dir0) == 0)
715++ error = 0;
716++
717++ tmy_free(exename);
718++ } else {
719++ error = 0;
720++ }
721++
722++ tmy_free(dir0);
723++ }
724++
725++ if (!is_enforce)
726++ error = 0;
727++ return error;
728++}
729++
730++/**
731++ * tmy_add_no_umount_policy - add or delete no-unmount policy.
732++ * @data: a line to parse.
733++ * @is_delete: is this delete request?
734++ *
735++ * Returns zero on success.
736++ * Returns nonzero on failure.
737++ */
738++int tmy_add_no_umount_policy(char *data, const bool is_delete)
739++{
740++ return tmy_add_no_umount_acl(data, is_delete);
741++}
742++
743++/**
744++ * tmy_read_no_umount_policy - read no-unmount policy.
745++ * @head: pointer to "struct io_buffer".
746++ *
747++ * Returns nonzero if reading incomplete.
748++ * Returns zero otherwise.
749++ */
750++int tmy_read_no_umount_policy(struct io_buffer *head)
751++{
752++ struct list_head *pos;
753++ list_for_each_cookie(pos, head->read_var2, &no_umount_list) {
754++ struct no_umount_entry *ptr;
755++ ptr = list_entry(pos, struct no_umount_entry, list);
756++ if (ptr->is_deleted)
757++ continue;
758++ if (tmy_io_printf(head, TMY_DENY_UNMOUNT "%s\n",
759++ ptr->dir->name))
760++ return -ENOMEM;
761++ }
762++ return 0;
763++}
764++
765++/***** The structure for pivot_root restrictions. *****/
766++
767++struct pivot_root_entry {
768++ struct list_head list;
769++ const struct path_info *old_root;
770++ const struct path_info *new_root;
771++ bool is_deleted;
772++};
773++
774++/********************** PIVOT_ROOT RESTRICTION HANDLER **********************/
775++
776++static LIST_HEAD(pivot_root_list);
777++
778++/* Add or remove a pivot_root entry. */
779++static int tmy_add_pivot_root_acl(const char *old_root,
780++ const char *new_root,
781++ const bool is_delete)
782++{
783++ struct pivot_root_entry *new_entry;
784++ struct pivot_root_entry *ptr;
785++ const struct path_info *saved_old_root;
786++ const struct path_info *saved_new_root;
787++ static DEFINE_MUTEX(mutex);
788++ int error = -ENOMEM;
789++
790++ if (!tmy_correct_path(old_root, 1, 0, 1, __FUNCTION__) ||
791++ !tmy_correct_path(new_root, 1, 0, 1, __FUNCTION__))
792++ return -EINVAL;
793++
794++ saved_old_root = tmy_save_name(old_root);
795++ if (!saved_old_root)
796++ return -ENOMEM;
797++ saved_new_root = tmy_save_name(new_root);
798++ if (!saved_new_root)
799++ return -ENOMEM;
800++
801++ mutex_lock(&mutex);
802++
803++ list_for_each_entry(ptr, &pivot_root_list, list) {
804++ if (ptr->old_root == saved_old_root &&
805++ ptr->new_root == saved_new_root) {
806++ ptr->is_deleted = is_delete;
807++ error = 0;
808++ goto out;
809++ }
810++ }
811++
812++ if (is_delete) {
813++ error = -ENOENT;
814++ goto out;
815++ }
816++
817++ new_entry = tmy_alloc_element(sizeof(*new_entry));
818++ if (!new_entry)
819++ goto out;
820++
821++ new_entry->old_root = saved_old_root;
822++ new_entry->new_root = saved_new_root;
823++ list_add_tail_mb(&new_entry->list, &pivot_root_list);
824++ error = 0;
825++out: ;
826++
827++ mutex_unlock(&mutex);
828++
829++ return error;
830++}
831++
832++/**
833++ * tmy_pivot_root_perm - check for pivot_root permission.
834++ * @old_nd: pointer to "struct nameidata".
835++ * @new_nd: pointer to "struct nameidata".
836++ *
837++ * Returns zero if permission granted.
838++ * Returns nonzero if permission denied.
839++ */
840++int tmy_pivot_root_perm(struct nameidata *old_nd, struct nameidata *new_nd)
841++{
842++ int error = -EPERM;
843++ const unsigned int mode = tmy_flags(TMY_RESTRICT_PIVOT_ROOT);
844++ const bool is_enforce = (mode == 3);
845++ char *old_root;
846++ char *new_root;
847++ struct path_info old_root_dir;
848++ struct path_info new_root_dir;
849++
850++ if (!mode)
851++ return 0;
852++
853++ old_root = tmy_realpath_dentry(old_nd->dentry, old_nd->mnt);
854++ new_root = tmy_realpath_dentry(new_nd->dentry, new_nd->mnt);
855++
856++ if (!old_root || !new_root)
857++ goto out;
858++
859++ old_root_dir.name = old_root;
860++ tmy_fill_path_info(&old_root_dir);
861++ new_root_dir.name = new_root;
862++ tmy_fill_path_info(&new_root_dir);
863++
864++ if (old_root_dir.is_dir && new_root_dir.is_dir) {
865++ struct pivot_root_entry *ptr;
866++ list_for_each_entry(ptr, &pivot_root_list, list) {
867++ if (ptr->is_deleted)
868++ continue;
869++ if (tmy_path_match(&old_root_dir, ptr->old_root) &&
870++ tmy_path_match(&new_root_dir, ptr->new_root)) {
871++ error = 0;
872++ break;
873++ }
874++ }
875++ }
876++
877++out: ;
878++ if (error) {
879++ const char *exename = tmy_get_exe();
880++ tmy_audit("TOMOYO-%s: pivot_root %s %s (pid=%d:exe=%s): "
881++ "Permission denied.\n", tmy_getmsg(is_enforce),
882++ new_root, old_root, current->pid, exename);
883++ if (is_enforce &&
884++ tmy_supervisor("# %s is requesting\npivot_root %s %s\n",
885++ exename, new_root, old_root) == 0)
886++ error = 0;
887++
888++ if (exename)
889++ tmy_free(exename);
890++
891++ if (!is_enforce && mode == 1 && old_root && new_root) {
892++ tmy_add_pivot_root_acl(old_root, new_root, 0);
893++ tmy_update_counter(TMY_UPDATE_SYSTEMPOLICY);
894++ }
895++
896++ if (!is_enforce)
897++ error = 0;
898++ }
899++
900++ tmy_free(old_root);
901++ tmy_free(new_root);
902++ return error;
903++}
904++
905++/**
906++ * tmy_add_pivot_root_policy - add or delete pivot_root policy.
907++ * @data: a line to parse.
908++ * @is_delete: is this delete request?
909++ *
910++ * Returns zero on success.
911++ * Returns nonzero on failure.
912++ */
913++int tmy_add_pivot_root_policy(char *data, const bool is_delete)
914++{
915++ char *cp = strchr(data, ' ');
916++
917++ if (!cp)
918++ return -EINVAL;
919++ *cp++ = '\0';
920++
921++ return tmy_add_pivot_root_acl(cp, data, is_delete);
922++}
923++
924++/**
925++ * tmy_read_pivot_root_policy - read pivot_root policy.
926++ * @head: pointer to "struct io_buffer".
927++ *
928++ * Returns nonzero if reading incomplete.
929++ * Returns zero otherwise.
930++ */
931++int tmy_read_pivot_root_policy(struct io_buffer *head)
932++{
933++ struct list_head *pos;
934++ list_for_each_cookie(pos, head->read_var2, &pivot_root_list) {
935++ struct pivot_root_entry *ptr;
936++ ptr = list_entry(pos, struct pivot_root_entry, list);
937++ if (ptr->is_deleted)
938++ continue;
939++ if (tmy_io_printf(head, TMY_ALLOW_PIVOT_ROOT "%s %s\n",
940++ ptr->new_root->name, ptr->old_root->name))
941++ return -ENOMEM;
942++ }
943++ return 0;
944++}
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-audit.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-audit.diff (revision 755)
@@ -0,0 +1,260 @@
1+TOMOYO Linux uses /sys/kernel/security/tomoyo/ interface
2+for reporting access logs in domain policy format.
3+One is 'grant_log', used for auditing accesses which are
4+granted in the TOMOYO Linux policy.
5+The other is 'reject_log', used for auditing accesses which
6+are not granted in the TOMOYO Linux policy.
7+The userland daemon /usr/lib/ccs/ccs-auditd will save these logs.
8+
9+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
10+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
11+ security/tomoyo/audit.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++
12+ 1 file changed, 244 insertions(+)
13+
14+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
15++++ linux-2.6.23/security/tomoyo/audit.c 2007-11-09 18:09:28.000000000 +0900
16+@@ -0,0 +1,244 @@
17++/*
18++ * security/tomoyo/audit.c
19++ *
20++ * Audit functions for TOMOYO Linux
21++ */
22++
23++#include "tomoyo.h"
24++
25++#ifdef CONFIG_SECURITY_TOMOYO_USE_AUDITD
26++/**
27++ * tmy_audit - write audit log.
28++ * @fmt: format strings for printf().
29++ *
30++ * Returns zero on success.
31++ * Returns nonzero on failure.
32++ *
33++ * Write audit log.
34++ */
35++int tmy_audit(const char *fmt, ...)
36++{
37++ struct audit_buffer *ab;
38++ int len;
39++ va_list args;
40++ char *buf;
41++ char *cp;
42++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
43++ ab = audit_log_start(current->audit_context);
44++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
45++ ab = audit_log_start(current->audit_context, AUDIT_KERNEL);
46++#else
47++ ab = audit_log_start(current->audit_context, GFP_KERNEL, AUDIT_KERNEL);
48++#endif
49++ if (!ab)
50++ return -ENOMEM;
51++ buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
52++ if (!buf)
53++ goto out;
54++ va_start(args, fmt);
55++ len = vsnprintf(buf, PAGE_SIZE - 1, fmt, args);
56++ va_end(args);
57++ if (len > PAGE_SIZE - 1) {
58++ kfree(buf);
59++ buf = kzalloc(len + 16, GFP_KERNEL);
60++ if (!buf)
61++ goto out;
62++ va_start(args, fmt);
63++ vsnprintf(buf, len + 15, fmt, args);
64++ va_end(args);
65++ }
66++ cp = strchr(buf, '\0') - 1;
67++ if (cp >= buf && *cp == '\n')
68++ *cp = '\0';
69++ audit_log_format(ab, "TOMOYO: %s", buf);
70++ kfree(buf);
71++out: ;
72++ audit_log_end(ab);
73++ return buf ? 0 : -ENOMEM;
74++}
75++#endif
76++
77++static DECLARE_WAIT_QUEUE_HEAD(grant_log_wait);
78++static DECLARE_WAIT_QUEUE_HEAD(reject_log_wait);
79++
80++static DEFINE_SPINLOCK(audit_log_lock);
81++
82++struct log_entry {
83++ struct list_head list;
84++ char *log;
85++};
86++
87++static LIST_HEAD(grant_log);
88++static LIST_HEAD(reject_log);
89++
90++static int grant_log_count;
91++static int reject_log_count;
92++
93++/**
94++ * tmy_audit_grant - get flags of auditing grant logs.
95++ *
96++ * Returns current value of auditing grant log flags.
97++ */
98++bool tmy_audit_grant(void)
99++{
100++ return grant_log_count < tmy_flags(TMY_MAX_GRANT_LOG);
101++}
102++
103++/**
104++ * tmy_audit_reject - get flags of auditing reject logs.
105++ *
106++ * Returns current value of auditing reject log flags.
107++ */
108++bool tmy_audit_reject(void)
109++{
110++ return reject_log_count < tmy_flags(TMY_MAX_REJECT_LOG);
111++}
112++
113++/**
114++ * tmy_init_audit_log - allocate and initialize audit buffer.
115++ * @len: pointer to length of requested size.
116++ * @profile: profile number for this log.
117++ * @mode: profile value for this log.
118++ *
119++ * Returns pointer to audit buffer on success. @len received allocated size.
120++ * Returns NULL on failure.
121++ *
122++ * @len must not be a NULL.
123++ */
124++char *tmy_init_audit_log(int *len, const u8 profile, const unsigned int mode)
125++{
126++ char *buf;
127++ struct timeval tv;
128++ struct task_struct *task = current;
129++ const char *domainname = TMY_SECURITY->domain->domainname->name;
130++ do_gettimeofday(&tv);
131++ *len += strlen(domainname) + 256;
132++ buf = tmy_alloc(*len);
133++ if (!buf)
134++ return NULL;
135++ snprintf(buf, (*len) - 1, "#timestamp=%lu profile=%u mode=%u "
136++ "pid=%d uid=%d gid=%d euid=%d egid=%d "
137++ "suid=%d sgid=%d fsuid=%d fsgid=%d \n%s\n",
138++ tv.tv_sec, profile, mode,
139++ task->pid, task->uid, task->gid, task->euid, task->egid,
140++ task->suid, task->sgid, task->fsuid, task->fsgid, domainname);
141++ return buf;
142++}
143++
144++/**
145++ * tmy_write_audit_log - write audit log.
146++ * @buf: pointer to access log contents.
147++ * @is_granted: is the access request granted?
148++ *
149++ * Returns zero on success.
150++ * Returns nonzero on failure.
151++ *
152++ * Write audit log.
153++ * Caller must allocate @buf with tmy_init_audit_log().
154++ */
155++int tmy_write_audit_log(char *buf, const bool is_granted)
156++{
157++ struct log_entry *new_entry;
158++ new_entry = tmy_alloc(sizeof(*new_entry));
159++ if (!new_entry) {
160++ tmy_free(buf);
161++ return -ENOMEM;
162++ }
163++ INIT_LIST_HEAD(&new_entry->list);
164++ new_entry->log = buf;
165++ /***** CRITICAL SECTION START *****/
166++ spin_lock(&audit_log_lock);
167++ if (is_granted) {
168++ list_add_tail(&new_entry->list, &grant_log);
169++ grant_log_count++;
170++ buf = NULL;
171++ tmy_update_counter(TMY_UPDATE_GRANT_LOG);
172++ } else {
173++ list_add_tail(&new_entry->list, &reject_log);
174++ reject_log_count++;
175++ buf = NULL;
176++ tmy_update_counter(TMY_UPDATE_REJECT_LOG);
177++ }
178++ spin_unlock(&audit_log_lock);
179++ /***** CRITICAL SECTION END *****/
180++ if (is_granted)
181++ wake_up(&grant_log_wait);
182++ else
183++ wake_up(&reject_log_wait);
184++ return 0;
185++}
186++
187++int tmy_read_grant_log(struct io_buffer *head)
188++{
189++ struct log_entry *ptr = NULL;
190++ if (head->read_avail) return 0;
191++ if (head->read_buf) {
192++ tmy_free(head->read_buf);
193++ head->read_buf = NULL;
194++ head->readbuf_size = 0;
195++ }
196++ /***** CRITICAL SECTION START *****/
197++ spin_lock(&audit_log_lock);
198++ if (!list_empty(&grant_log)) {
199++ ptr = list_entry(grant_log.next, struct log_entry, list);
200++ list_del(&ptr->list);
201++ grant_log_count--;
202++ }
203++ spin_unlock(&audit_log_lock);
204++ /***** CRITICAL SECTION END *****/
205++ if (ptr) {
206++ head->read_buf = ptr->log;
207++ head->read_avail = strlen(ptr->log) + 1;
208++ head->readbuf_size = head->read_avail;
209++ tmy_free(ptr);
210++ }
211++ return 0;
212++}
213++
214++int tmy_poll_grant_log(struct file *file, poll_table *wait)
215++{
216++ if (grant_log_count)
217++ return POLLIN | POLLRDNORM;
218++ poll_wait(file, &grant_log_wait, wait);
219++ if (grant_log_count)
220++ return POLLIN | POLLRDNORM;
221++ return 0;
222++}
223++
224++int tmy_read_reject_log(struct io_buffer *head)
225++{
226++ struct log_entry *ptr = NULL;
227++ if (head->read_avail)
228++ return 0;
229++ if (head->read_buf) {
230++ tmy_free(head->read_buf);
231++ head->read_buf = NULL;
232++ head->readbuf_size = 0;
233++ }
234++ /***** CRITICAL SECTION START *****/
235++ spin_lock(&audit_log_lock);
236++ if (!list_empty(&reject_log)) {
237++ ptr = list_entry(reject_log.next, struct log_entry, list);
238++ list_del(&ptr->list);
239++ reject_log_count--;
240++ }
241++ spin_unlock(&audit_log_lock);
242++ /***** CRITICAL SECTION END *****/
243++ if (ptr) {
244++ head->read_buf = ptr->log;
245++ head->read_avail = strlen(ptr->log) + 1;
246++ head->readbuf_size = head->read_avail;
247++ tmy_free(ptr);
248++ }
249++ return 0;
250++}
251++
252++int tmy_poll_reject_log(struct file *file, poll_table *wait)
253++{
254++ if (reject_log_count)
255++ return POLLIN | POLLRDNORM;
256++ poll_wait(file, &reject_log_wait, wait);
257++ if (reject_log_count)
258++ return POLLIN | POLLRDNORM;
259++ return 0;
260++}
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-domain.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-domain.diff (revision 755)
@@ -0,0 +1,1183 @@
1+Domain transition functions for TOMOYO Linux.
2+Every process belongs to a domain in TOMOYO Linux.
3+Domain transition occurs when execve(2) is called
4+and the domain is expressed as 'process invocation history',
5+such as '<kernel> /sbin/init /etc/init.d/rc'.
6+Domain information is stored in task_struct->security.
7+
8+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
9+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
10+ security/tomoyo/domain.c | 1168 +++++++++++++++++++++++++++++++++++++++++++++++
11+ 1 file changed, 1168 insertions(+)
12+
13+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
14++++ linux-2.6.23/security/tomoyo/domain.c 2007-11-02 13:48:04.000000000 +0900
15+@@ -0,0 +1,1168 @@
16++/*
17++ * security/tomoyo/domain.c
18++ *
19++ * Domain transition functions for TOMOYO Linux.
20++ */
21++
22++#include "tomoyo.h"
23++#include "realpath.h"
24++
25++/************************* VARIABLES *************************/
26++
27++/* The initial domain. */
28++struct domain_info KERNEL_DOMAIN;
29++
30++/* Lock for appending domain's ACL. */
31++DEFINE_MUTEX(domain_acl_lock);
32++
33++/* Domain creation lock. */
34++static DEFINE_MUTEX(new_domain_assign_lock);
35++
36++/***** The structure for program files to force domain reconstruction. *****/
37++
38++struct domain_initializer_entry {
39++ struct list_head list;
40++ const struct path_info *domainname; /* This may be NULL */
41++ const struct path_info *program;
42++ bool is_deleted;
43++ bool is_not;
44++ bool is_last_name;
45++};
46++
47++/***** The structure for domains to not to transit domains. *****/
48++
49++struct domain_keeper_entry {
50++ struct list_head list;
51++ const struct path_info *domainname;
52++ const struct path_info *program; /* This may be NULL */
53++ bool is_deleted;
54++ bool is_not;
55++ bool is_last_name;
56++};
57++
58++/***** The structure for program files that should be aggregated. *****/
59++
60++struct aggregator_entry {
61++ struct list_head list;
62++ const struct path_info *original_name;
63++ const struct path_info *aggregated_name;
64++ bool is_deleted;
65++};
66++
67++/***** The structure for program files that should be aliased. *****/
68++
69++struct alias_entry {
70++ struct list_head list;
71++ const struct path_info *original_name;
72++ const struct path_info *aliased_name;
73++ bool is_deleted;
74++};
75++
76++/************************* UTILITY FUNCTIONS *************************/
77++
78++/**
79++ * tmy_is_domain_def - check if the line is likely a domain definition.
80++ * @buffer: the line to check.
81++ *
82++ * Returns true if @buffer is likely a domain definition.
83++ * Returns false otherwise.
84++ *
85++ * For complete validation check, use tmy_is_correct_domain().
86++ */
87++bool tmy_is_domain_def(const unsigned char *buffer)
88++{
89++ return strncmp(buffer, TMY_ROOT_NAME, TMY_ROOT_NAME_LEN) == 0;
90++}
91++
92++/**
93++ * tmy_add_acl - add an entry to a domain.
94++ * @domain: pointer to "struct domain_info".
95++ * @acl: pointer to "struct acl_info" to add.
96++ *
97++ * Returns zero.
98++ */
99++int tmy_add_acl(struct domain_info *domain,
100++ struct acl_info *acl)
101++{
102++ list_add_tail_mb(&acl->list, &domain->acl_info_list);
103++ tmy_update_counter(TMY_UPDATE_DOMAINPOLICY);
104++ return 0;
105++}
106++
107++/**
108++ * tmy_del_acl - remove an entry from a domain
109++ * @ptr: pointer to "struct acl_info" to remove.
110++ *
111++ * Returns zero.
112++ *
113++ * TOMOYO Linux doesn't free memory used by policy because policies are not
114++ * so frequently changed after entring into enforcing mode.
115++ * This makes the code free of read-lock.
116++ * The caller uses "down(&domain_acl_lock);" as write-lock.
117++ */
118++int tmy_del_acl(struct acl_info *ptr)
119++{
120++ ptr->is_deleted = 1;
121++ tmy_update_counter(TMY_UPDATE_DOMAINPOLICY);
122++ return 0;
123++}
124++
125++/************************ DOMAIN INITIALIZER HANDLER ************************/
126++
127++static LIST_HEAD(domain_initializer_list);
128++
129++/* Update domain initializer list. */
130++static int tmy_add_domain_initializer_entry(const char *domainname,
131++ const char *program,
132++ const bool is_not,
133++ const bool is_delete)
134++{
135++ struct domain_initializer_entry *new_entry;
136++ struct domain_initializer_entry *ptr;
137++ static DEFINE_MUTEX(mutex);
138++ const struct path_info *saved_program;
139++ const struct path_info *saved_domainname = NULL;
140++ int error = -ENOMEM;
141++ bool is_last_name = 0;
142++
143++ if (!tmy_correct_path(program, 1, -1, -1, __FUNCTION__))
144++ return -EINVAL; /* No patterns allowed. */
145++
146++ if (domainname) {
147++ if (!tmy_is_domain_def(domainname) &&
148++ tmy_correct_path(domainname, 1, -1, -1, __FUNCTION__))
149++ is_last_name = 1;
150++
151++ else if (!tmy_is_correct_domain(domainname, __FUNCTION__))
152++ return -EINVAL;
153++
154++ saved_domainname = tmy_save_name(domainname);
155++ if (!saved_domainname)
156++ return -ENOMEM;
157++ }
158++
159++ saved_program = tmy_save_name(program);
160++ if (!saved_program)
161++ return -ENOMEM;
162++
163++ mutex_lock(&mutex);
164++
165++ list_for_each_entry(ptr, &domain_initializer_list, list) {
166++ if (ptr->is_not == is_not &&
167++ ptr->domainname == saved_domainname &&
168++ ptr->program == saved_program) {
169++ ptr->is_deleted = is_delete;
170++ error = 0;
171++ goto out;
172++ }
173++ }
174++
175++ if (is_delete) {
176++ error = -ENOENT;
177++ goto out;
178++ }
179++
180++ new_entry = tmy_alloc_element(sizeof(*new_entry));
181++ if (!new_entry)
182++ goto out;
183++
184++ new_entry->domainname = saved_domainname;
185++ new_entry->program = saved_program;
186++ new_entry->is_not = is_not;
187++ new_entry->is_last_name = is_last_name;
188++ list_add_tail_mb(&new_entry->list, &domain_initializer_list);
189++ error = 0;
190++out: ;
191++
192++ mutex_unlock(&mutex);
193++ return error;
194++}
195++
196++/**
197++ * tmy_read_domain_initializer_policy - read domain initializer policy.
198++ * @head: pointer to "struct io_buffer".
199++ *
200++ * Returns nonzero if reading incomplete.
201++ * Returns zero otherwise.
202++ */
203++int tmy_read_domain_initializer_policy(struct io_buffer *head)
204++{
205++ struct list_head *pos;
206++ list_for_each_cookie(pos, head->read_var2, &domain_initializer_list) {
207++ struct domain_initializer_entry *ptr;
208++ ptr = list_entry(pos, struct domain_initializer_entry, list);
209++ if (ptr->is_deleted)
210++ continue;
211++ if (ptr->domainname) {
212++ if (tmy_io_printf(head, "%s" TMY_INITIALIZE_DOMAIN
213++ "%s from %s\n",
214++ ptr->is_not ? "no_" : "",
215++ ptr->program->name,
216++ ptr->domainname->name))
217++ return -ENOMEM;
218++ } else {
219++ if (tmy_io_printf(head, "%s" TMY_INITIALIZE_DOMAIN
220++ "%s\n",
221++ ptr->is_not ? "no_" : "",
222++ ptr->program->name))
223++ return -ENOMEM;
224++ }
225++ }
226++ return 0;
227++}
228++
229++/**
230++ * tmy_add_domain_initializer_policy - add domain initializer policy
231++ * @data: a line to parse.
232++ * @is_not: is this overriding?
233++ * @is_delete: is this remove request?
234++ *
235++ * Returns zero on success.
236++ * Returns nonzero on failure.
237++ *
238++ * This function adds or removes a domain initializer entry.
239++ */
240++int tmy_add_domain_initializer_policy(char *data,
241++ const bool is_not,
242++ const bool is_delete)
243++{
244++ char *cp = strstr(data, " from ");
245++
246++ if (cp) {
247++ *cp = '\0';
248++ return tmy_add_domain_initializer_entry(cp + 6, data, is_not,
249++ is_delete);
250++ }
251++
252++ return tmy_add_domain_initializer_entry(NULL, data, is_not, is_delete);
253++}
254++
255++/* Should I transit to a domain under "<kernel>" domain? */
256++static int tmy_is_domain_initializer(const struct path_info *domainname,
257++ const struct path_info *program,
258++ const struct path_info *last_name)
259++{
260++ struct domain_initializer_entry *ptr;
261++ int flag = 0;
262++ list_for_each_entry(ptr, &domain_initializer_list, list) {
263++ if (ptr->is_deleted)
264++ continue;
265++ if (ptr->domainname) {
266++ if (!ptr->is_last_name) {
267++ if (ptr->domainname != domainname)
268++ continue;
269++ } else {
270++ if (tmy_pathcmp(ptr->domainname, last_name))
271++ continue;
272++ }
273++ }
274++ if (tmy_pathcmp(ptr->program, program))
275++ continue;
276++ if (ptr->is_not)
277++ return 0;
278++ flag = 1;
279++ }
280++ return flag;
281++}
282++
283++/************************* DOMAIN KEEPER HANDLER *************************/
284++
285++static LIST_HEAD(domain_keeper_list);
286++
287++/* Update domain keeper list. */
288++static int tmy_add_domain_keeper_entry(const char *domainname,
289++ const char *program,
290++ const bool is_not,
291++ const bool is_delete)
292++{
293++ struct domain_keeper_entry *new_entry;
294++ struct domain_keeper_entry *ptr;
295++ const struct path_info *saved_domainname;
296++ const struct path_info *saved_program = NULL;
297++ static DEFINE_MUTEX(mutex);
298++ int error = -ENOMEM;
299++ bool is_last_name = 0;
300++
301++ if (!tmy_is_domain_def(domainname) &&
302++ tmy_correct_path(domainname, 1, -1, -1, __FUNCTION__))
303++ is_last_name = 1;
304++
305++ else if (!tmy_is_correct_domain(domainname, __FUNCTION__))
306++ return -EINVAL;
307++
308++ if (program) {
309++ if (!tmy_correct_path(program, 1, -1, -1, __FUNCTION__))
310++ return -EINVAL;
311++
312++ saved_program = tmy_save_name(program);
313++ if (!saved_program)
314++ return -ENOMEM;
315++ }
316++
317++ saved_domainname = tmy_save_name(domainname);
318++ if (!saved_domainname)
319++ return -ENOMEM;
320++
321++ mutex_lock(&mutex);
322++ list_for_each_entry(ptr, &domain_keeper_list, list) {
323++ if (ptr->is_not == is_not &&
324++ ptr->domainname == saved_domainname &&
325++ ptr->program == saved_program) {
326++ ptr->is_deleted = is_delete;
327++ error = 0;
328++ goto out;
329++ }
330++ }
331++
332++ if (is_delete) {
333++ error = -ENOENT;
334++ goto out;
335++ }
336++
337++ new_entry = tmy_alloc_element(sizeof(*new_entry));
338++ if (!new_entry)
339++ goto out;
340++
341++ new_entry->domainname = saved_domainname;
342++ new_entry->program = saved_program;
343++ new_entry->is_not = is_not;
344++ new_entry->is_last_name = is_last_name;
345++ list_add_tail_mb(&new_entry->list, &domain_keeper_list);
346++ error = 0;
347++
348++out: ;
349++
350++ mutex_unlock(&mutex);
351++ return error;
352++}
353++
354++/**
355++ * tmy_add_domain_keeper_policy - add domain keeper policy.
356++ * @data: a line to parse.
357++ * @is_not: is this overriding?
358++ * @is_delete: is this remove request?
359++ *
360++ * Returns zero on success.
361++ * Returns nonzero on failure.
362++ *
363++ * This function adds or removes a domain keeper entry.
364++ *
365++ */
366++int tmy_add_domain_keeper_policy(char *data,
367++ const bool is_not,
368++ const bool is_delete)
369++{
370++ char *cp = strstr(data, " from ");
371++
372++ if (cp) {
373++ *cp = '\0';
374++ return tmy_add_domain_keeper_entry(cp + 6, data,
375++ is_not, is_delete);
376++ }
377++
378++ return tmy_add_domain_keeper_entry(data, NULL, is_not, is_delete);
379++}
380++
381++/**
382++ * tmy_read_domain_keeper_policy - read domain keeper policy.
383++ * @head: pointer to "struct io_buffer".
384++ *
385++ * Returns nonzero if reading incomplete.
386++ * Returns zero otherwise.
387++ */
388++int tmy_read_domain_keeper_policy(struct io_buffer *head)
389++{
390++ struct list_head *pos;
391++ list_for_each_cookie(pos, head->read_var2, &domain_keeper_list) {
392++ struct domain_keeper_entry *ptr;
393++ ptr = list_entry(pos, struct domain_keeper_entry, list);
394++ if (ptr->is_deleted)
395++ continue;
396++ if (ptr->program) {
397++ if (tmy_io_printf(head,
398++ "%s" TMY_KEEP_DOMAIN
399++ "%s from %s\n",
400++ ptr->is_not ? "no_" : "",
401++ ptr->program->name,
402++ ptr->domainname->name))
403++ return -ENOMEM;
404++ } else {
405++ if (tmy_io_printf(head,
406++ "%s" TMY_KEEP_DOMAIN
407++ "%s\n",
408++ ptr->is_not ? "no_" : "",
409++ ptr->domainname->name))
410++ return -ENOMEM;
411++ }
412++ }
413++ return 0;
414++}
415++
416++/* Should I remain in current domain? */
417++static int tmy_is_domain_keeper(const struct path_info *domainname,
418++ const struct path_info *program,
419++ const struct path_info *last_name)
420++{
421++ struct domain_keeper_entry *ptr;
422++ int flag = 0;
423++ list_for_each_entry(ptr, &domain_keeper_list, list) {
424++ if (ptr->is_deleted)
425++ continue;
426++ if (!ptr->is_last_name) {
427++ if (ptr->domainname != domainname)
428++ continue;
429++ } else {
430++ if (tmy_pathcmp(ptr->domainname, last_name))
431++ continue;
432++ }
433++ if (ptr->program && tmy_pathcmp(ptr->program, program))
434++ continue;
435++ if (ptr->is_not)
436++ return 0;
437++ flag = 1;
438++ }
439++ return flag;
440++}
441++
442++/********************* SYMBOLIC LINKED PROGRAM HANDLER *********************/
443++
444++static LIST_HEAD(alias_list);
445++
446++/* Update alias list. */
447++static int tmy_add_alias_entry(const char *original_name,
448++ const char *aliased_name,
449++ const bool is_delete)
450++{
451++ struct alias_entry *new_entry;
452++ struct alias_entry *ptr;
453++ static DEFINE_MUTEX(mutex);
454++ const struct path_info *saved_original_name;
455++ const struct path_info *saved_aliased_name;
456++ int error = -ENOMEM;
457++
458++ if (!tmy_correct_path(original_name, 1, -1, -1, __FUNCTION__) ||
459++ !tmy_correct_path(aliased_name, 1, -1, -1, __FUNCTION__))
460++ return -EINVAL; /* No patterns allowed. */
461++
462++ saved_original_name = tmy_save_name(original_name);
463++ saved_aliased_name = tmy_save_name(aliased_name);
464++ if (!saved_original_name || !saved_aliased_name)
465++ return -ENOMEM;
466++
467++ mutex_lock(&mutex);
468++
469++ list_for_each_entry(ptr, &alias_list, list) {
470++ if (ptr->original_name == saved_original_name &&
471++ ptr->aliased_name == saved_aliased_name) {
472++ ptr->is_deleted = is_delete;
473++ error = 0;
474++ goto out;
475++ }
476++ }
477++
478++ if (is_delete) {
479++ error = -ENOENT;
480++ goto out;
481++ }
482++
483++ new_entry = tmy_alloc_element(sizeof(*new_entry));
484++ if (!new_entry)
485++ goto out;
486++
487++ new_entry->original_name = saved_original_name;
488++ new_entry->aliased_name = saved_aliased_name;
489++ list_add_tail_mb(&new_entry->list, &alias_list);
490++ error = 0;
491++out: ;
492++ mutex_unlock(&mutex);
493++ return error;
494++}
495++
496++/**
497++ * tmy_read_alias_policy - read alias policy.
498++ * @head: pointer to "struct io_buffer".
499++ *
500++ * Returns nonzero if reading incomplete.
501++ * Returns zero otherwise.
502++ */
503++int tmy_read_alias_policy(struct io_buffer *head)
504++{
505++ struct list_head *pos;
506++ list_for_each_cookie(pos, head->read_var2, &alias_list) {
507++ struct alias_entry *ptr;
508++ ptr = list_entry(pos, struct alias_entry, list);
509++ if (ptr->is_deleted)
510++ continue;
511++ if (tmy_io_printf(head,
512++ TMY_ALIAS "%s %s\n",
513++ ptr->original_name->name,
514++ ptr->aliased_name->name))
515++ return -ENOMEM;
516++ }
517++ return 0;
518++}
519++
520++/**
521++ * tmy_add_alias_policy - add alias policy.
522++ * @data: a line to parse.
523++ * @is_delete: is this remove request?
524++ *
525++ * Returns zero on success.
526++ * Returns nonzero on failure.
527++ *
528++ * This function adds or removes an alias entry.
529++ */
530++int tmy_add_alias_policy(char *data, const bool is_delete)
531++{
532++ char *cp = strchr(data, ' ');
533++
534++ if (!cp)
535++ return -EINVAL;
536++ *cp++ = '\0';
537++
538++ return tmy_add_alias_entry(data, cp, is_delete);
539++}
540++
541++/************************ DOMAIN AGGREGATOR HANDLER ************************/
542++
543++static LIST_HEAD(aggregator_list);
544++
545++/* Update aggregator list. */
546++static int tmy_add_aggregator_entry(const char *original_name,
547++ const char *aggregated_name,
548++ const bool is_delete)
549++{
550++ struct aggregator_entry *new_entry;
551++ struct aggregator_entry *ptr;
552++ static DEFINE_MUTEX(mutex);
553++ const struct path_info *saved_original_name;
554++ const struct path_info *saved_aggregated_name;
555++ int error = -ENOMEM;
556++
557++ if (!tmy_correct_path(original_name, 1, 0, -1, __FUNCTION__) ||
558++ !tmy_correct_path(aggregated_name, 1, -1, -1, __FUNCTION__))
559++ return -EINVAL;
560++
561++ saved_original_name = tmy_save_name(original_name);
562++ saved_aggregated_name = tmy_save_name(aggregated_name);
563++ if (!saved_original_name || !saved_aggregated_name)
564++ return -ENOMEM;
565++
566++ mutex_lock(&mutex);
567++
568++ list_for_each_entry(ptr, &aggregator_list, list) {
569++ if (ptr->original_name == saved_original_name &&
570++ ptr->aggregated_name == saved_aggregated_name) {
571++ ptr->is_deleted = is_delete;
572++ error = 0;
573++ goto out;
574++ }
575++ }
576++
577++ if (is_delete) {
578++ error = -ENOENT;
579++ goto out;
580++ }
581++
582++ new_entry = tmy_alloc_element(sizeof(*new_entry));
583++ if (!new_entry)
584++ goto out;
585++
586++ new_entry->original_name = saved_original_name;
587++ new_entry->aggregated_name = saved_aggregated_name;
588++ list_add_tail_mb(&new_entry->list, &aggregator_list);
589++ error = 0;
590++out: ;
591++
592++ mutex_unlock(&mutex);
593++
594++ return error;
595++}
596++
597++/**
598++ * tmy_read_aggregator_policy - read aggregator policy.
599++ * @head: pointer to "struct io_buffer".
600++ *
601++ * Returns nonzero if reading incomplete.
602++ * Returns zero otherwise.
603++ */
604++int tmy_read_aggregator_policy(struct io_buffer *head)
605++{
606++ struct list_head *pos;
607++ list_for_each_cookie(pos, head->read_var2, &aggregator_list) {
608++ struct aggregator_entry *ptr;
609++ ptr = list_entry(pos, struct aggregator_entry, list);
610++ if (ptr->is_deleted)
611++ continue;
612++ if (tmy_io_printf(head,
613++ TMY_AGGREGATOR "%s %s\n",
614++ ptr->original_name->name,
615++ ptr->aggregated_name->name))
616++ return -ENOMEM;
617++ }
618++ return 0;
619++}
620++
621++/**
622++ * tmy_add_aggregator_policy - add aggregator policy.
623++ * @data: a line to parse.
624++ * @is_delete: is this remove request?
625++ *
626++ * Returns zero on success.
627++ * Returns nonzero on failure.
628++ *
629++ * This function adds or removes an aggregator entry.
630++ */
631++int tmy_add_aggregator_policy(char *data, const bool is_delete)
632++{
633++ char *cp = strchr(data, ' ');
634++
635++ if (!cp)
636++ return -EINVAL;
637++ *cp++ = '\0';
638++
639++ return tmy_add_aggregator_entry(data, cp, is_delete);
640++}
641++
642++/************************* DOMAIN DELETION HANDLER *************************/
643++
644++/**
645++ * tmy_delete_domain - delete a domain.
646++ * @domainname0: domainname to delete.
647++ *
648++ * Returns zero.
649++ *
650++ * This function deletes domains.
651++ * The behavior of deleting domain is like deleting files on Linux's
652++ * filesystem. A process transits to different domain upon do_execve(),
653++ * and the process can refer the deleted domains after the domain is deleted,
654++ * like a process opens a file and the process can read()/write() the deleted
655++ * file after the file is deleted.
656++ * This avoids processes from crashing due to referring non-existent domains.
657++ * Administrator manually terminates processes thet are referring deleted
658++ * domains after deleting domains.
659++ * Also, undeleting domains is supported. See tmy_undelete_domain().
660++ */
661++int tmy_delete_domain(char *domainname0)
662++{
663++ struct domain_info *domain;
664++ struct path_info domainname;
665++
666++ domainname.name = domainname0;
667++ tmy_fill_path_info(&domainname);
668++
669++ mutex_lock(&new_domain_assign_lock);
670++ /* Is there an active domain? */ /* Never delete KERNEL_DOMAIN */
671++ list_for_each_entry(domain, &domain_list, list) {
672++ struct domain_info *domain2;
673++ if (domain == &KERNEL_DOMAIN ||
674++ domain->is_deleted ||
675++ tmy_pathcmp(domain->domainname, &domainname))
676++ continue;
677++ /* Mark already deleted domains as non undeletable. */
678++ list_for_each_entry(domain2, &domain_list, list) {
679++ if (!domain2->is_deleted ||
680++ tmy_pathcmp(domain2->domainname, &domainname))
681++ continue;
682++ domain2->is_deleted = 255;
683++ }
684++ /* Delete and mark active domain as undeletable. */
685++ domain->is_deleted = 1;
686++ break;
687++ }
688++ mutex_unlock(&new_domain_assign_lock);
689++ return 0;
690++}
691++
692++/**
693++ * tmy_undelete_domain - undelete a domain.
694++ * @domainname0: domainname to undelete.
695++ *
696++ * Returns pointer to undeleted "struct domain_info" on success.
697++ * Returns NULL on failure.
698++ *
699++ * This function undeletes domains.
700++ * Not only the domain previously deleted by tmy_delete_domain()
701++ * but also all domains deleted by tmy_delete_domain() are undeletable.
702++ * If there is no deleted domain named @domainname0 or
703++ * a not-yet-deleted domain named @domainname0 exists, undelete fails.
704++ * Otherwise, previously deleted domain named @domainname0 is undeleted.
705++ */
706++struct domain_info *tmy_undelete_domain(const char *domainname0)
707++{
708++ struct domain_info *domain;
709++ struct domain_info *candidate_domain = NULL;
710++ struct path_info domainname;
711++
712++ domainname.name = domainname0;
713++ tmy_fill_path_info(&domainname);
714++
715++ mutex_lock(&new_domain_assign_lock);
716++
717++ list_for_each_entry(domain, &domain_list, list) {
718++ if (tmy_pathcmp(&domainname, domain->domainname))
719++ continue;
720++
721++ if (!domain->is_deleted) {
722++ /* This domain is active. I can't undelete. */
723++ candidate_domain = NULL;
724++ break;
725++ }
726++
727++ /* Is this domain undeletable? */
728++ if (domain->is_deleted == 1)
729++ candidate_domain = domain;
730++ }
731++ if (candidate_domain)
732++ candidate_domain->is_deleted = 0;
733++
734++ mutex_unlock(&new_domain_assign_lock);
735++
736++ return candidate_domain;
737++}
738++
739++/************************ DOMAIN TRANSITION HANDLER ************************/
740++
741++/**
742++ * tmy_find_domain - find a domain with given domainname.
743++ * @domainname0: the domainname to find.
744++ *
745++ * Returns pointer to "struct domain_info" on success.
746++ * Returns NULL on failure.
747++ *
748++ * This function does not create a new domain
749++ * if a domain named @domainname0 does not exist.
750++ */
751++struct domain_info *tmy_find_domain(const char *domainname0)
752++{
753++ struct domain_info *domain;
754++ static int first = 1;
755++ struct path_info domainname;
756++
757++ domainname.name = domainname0;
758++ tmy_fill_path_info(&domainname);
759++
760++ if (first) {
761++ KERNEL_DOMAIN.domainname = tmy_save_name(TMY_ROOT_NAME);
762++ first = 0;
763++ }
764++
765++ list_for_each_entry(domain, &domain_list, list) {
766++ if (!domain->is_deleted &&
767++ !tmy_pathcmp(&domainname, domain->domainname))
768++ return domain;
769++ }
770++
771++ return NULL;
772++}
773++
774++/**
775++ * tmy_new_domain - find or assign a domain with given domainname.
776++ * @domainname: the domainname to find.
777++ * @profile: profile number to assign if newly created.
778++ *
779++ * Returns pointer to "struct domain_info" on success.
780++ * Returns NULL on failure.
781++ *
782++ * This function creates a new domain if a domain named @domainname0
783++ * does not exist.
784++ */
785++struct domain_info *tmy_new_domain(const char *domainname,
786++ const u8 profile)
787++{
788++ struct domain_info *domain = NULL;
789++ const struct path_info *saved_domainname;
790++
791++ mutex_lock(&new_domain_assign_lock);
792++
793++ domain = tmy_find_domain(domainname);
794++ if (domain)
795++ goto out;
796++
797++ if (!tmy_is_correct_domain(domainname, __FUNCTION__))
798++ goto out;
799++
800++ saved_domainname = tmy_save_name(domainname);
801++ if (!saved_domainname)
802++ goto out;
803++
804++ /* Can I reuse memory of deleted domain? */
805++ list_for_each_entry(domain, &domain_list, list) {
806++ struct task_struct *p;
807++ struct acl_info *ptr;
808++ int flag;
809++
810++ if (!domain->is_deleted ||
811++ domain->domainname != saved_domainname)
812++ continue;
813++ flag = 0;
814++
815++ /***** CRITICAL SECTION START *****/
816++ read_lock(&tasklist_lock);
817++ for_each_process(p) {
818++ /* "struct task_struct"->security is not NULL. */
819++ if (((struct tmy_security *) p->security)->domain
820++ == domain) {
821++ flag = 1;
822++ break;
823++ }
824++ }
825++ read_unlock(&tasklist_lock);
826++ /***** CRITICAL SECTION END *****/
827++
828++ /* Somebody is still referring this deleted domain. */
829++ if (flag)
830++ continue;
831++
832++ /* OK. Let's reuse memory for this deleted domain. */
833++
834++ /* Delete all entries in this deleted domain. */
835++ list_for_each_entry(ptr, &domain->acl_info_list, list)
836++ ptr->is_deleted = 1;
837++
838++ domain->profile = profile;
839++ domain->quota_warned = 0;
840++
841++ mb(); /* Avoid out-of-order execution. */
842++ /* Undelete this deleted domain. */
843++ domain->is_deleted = 0;
844++ goto out;
845++ }
846++
847++ /* No memory reusable. Create using new memory. */
848++ domain = tmy_alloc_element(sizeof(*domain));
849++ if (domain) {
850++ INIT_LIST_HEAD(&domain->acl_info_list);
851++ domain->domainname = saved_domainname;
852++ domain->profile = profile;
853++ list_add_tail_mb(&domain->list, &domain_list);
854++ }
855++out: ;
856++ mutex_unlock(&new_domain_assign_lock);
857++
858++ return domain;
859++}
860++
861++/* Convert non ASCII printable characters to ASCII printable characters. */
862++static int tmy_escape(char *dest, const char *src, int dest_len)
863++{
864++ while (*src) {
865++ const unsigned char c = *(const unsigned char *) src;
866++
867++ if (c == '\\') {
868++ dest_len -= 2;
869++ if (dest_len <= 0)
870++ goto out;
871++ *dest++ = '\\';
872++ *dest++ = '\\';
873++ } else if (c > ' ' && c < 127) {
874++ if (--dest_len <= 0)
875++ goto out;
876++ *dest++ = c;
877++ } else {
878++ dest_len -= 4;
879++ if (dest_len <= 0)
880++ goto out;
881++ *dest++ = '\\';
882++ *dest++ = (c >> 6) + '0';
883++ *dest++ = ((c >> 3) & 7) + '0';
884++ *dest++ = (c & 7) + '0';
885++ }
886++ src++;
887++ }
888++
889++ if (--dest_len <= 0)
890++ goto out;
891++ *dest = '\0';
892++
893++ return 0;
894++out: ;
895++ return -ENOMEM;
896++}
897++
898++/* Get argv[0] of "struct linux_binprm". */
899++static char *tmy_get_argv0(struct linux_binprm *bprm)
900++{
901++ char *arg_ptr;
902++ int arg_len = 0;
903++ unsigned long pos = bprm->p;
904++ int i = pos / PAGE_SIZE;
905++ int offset = pos % PAGE_SIZE;
906++
907++ if (bprm->argc <= 0)
908++ return NULL;
909++
910++ arg_ptr = tmy_alloc(PAGE_SIZE);
911++
912++ if (!arg_ptr)
913++ goto out;
914++
915++ while (1) {
916++ struct page *page;
917++ const char *kaddr;
918++ char *tmp_arg;
919++
920++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
921++ if (get_user_pages(current, bprm->mm, pos,
922++ 1, 0, 1, &page, NULL) <= 0)
923++ goto out;
924++#else
925++ page = bprm->page[i];
926++#endif
927++ kaddr = kmap(page);
928++ if (!kaddr) { /* Mapping failed. */
929++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
930++ put_page(page);
931++#endif
932++ goto out;
933++ }
934++
935++ memmove(arg_ptr + arg_len, kaddr + offset, PAGE_SIZE - offset);
936++ kunmap(page);
937++
938++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
939++ put_page(page);
940++ pos += PAGE_SIZE - offset;
941++#endif
942++
943++ arg_len += PAGE_SIZE - offset;
944++
945++ if (memchr(arg_ptr, '\0', arg_len))
946++ break;
947++
948++ tmp_arg = tmy_alloc(arg_len + PAGE_SIZE);
949++ if (!tmp_arg)
950++ goto out;
951++
952++ memmove(tmp_arg, arg_ptr, arg_len);
953++ tmy_free(arg_ptr);
954++ arg_ptr = tmp_arg;
955++ i++;
956++ offset = 0;
957++ }
958++ return arg_ptr;
959++out: ;
960++ tmy_free(arg_ptr);
961++
962++ return NULL;
963++}
964++
965++/**
966++ * tmy_find_next_domain - find a domain to transit to if do_execve() succeeds.
967++ * @bprm: pointer to "struct linux_binprm".
968++ * @next_domain: pointer to pointer to "struct domain_info".
969++ *
970++ * Returns zero if success. @next_domain receives new domain to transit to.
971++ * Returns nonzero on failure.
972++ *
973++ * This function handles TOMOYO Linux's domain transition.
974++ * New domains are automatically created unless the domain the caller process
975++ * belongs to is assigned a profile for enforcing mode.
976++ */
977++int tmy_find_next_domain(struct linux_binprm *bprm,
978++ struct domain_info **next_domain)
979++{
980++ /* This function assumes that the size of buffer returned */
981++ /* by tmy_realpath() = TMY_MAX_PATHNAME_LEN. */
982++ struct domain_info *old_domain = TMY_SECURITY->domain;
983++ struct domain_info *domain = NULL;
984++ const char *old_domain_name = old_domain->domainname->name;
985++ const char *original_name = bprm->filename;
986++ struct file *filp = bprm->file;
987++ char *new_domain_name = NULL;
988++ char *real_program_name = NULL;
989++ char *symlink_program_name = NULL;
990++ const bool is_enforce = (tmy_flags(TMY_MAC_FOR_FILE) == 3);
991++ int retval;
992++ struct path_info r;
993++ struct path_info s;
994++ struct path_info l;
995++
996++ /*
997++ * Built-in initializers.
998++ * This is needed because policies are not loaded
999++ * until starting /sbin/init .
1000++ */
1001++ static int first = 1;
1002++ if (first) {
1003++ tmy_add_domain_initializer_entry(NULL, "/sbin/hotplug", 0, 0);
1004++ tmy_add_domain_initializer_entry(NULL, "/sbin/modprobe", 0, 0);
1005++ tmy_add_domain_initializer_entry(NULL, "/sbin/udevd", 0, 0);
1006++ first = 0;
1007++ }
1008++
1009++ /* Get realpath of program. */
1010++ /* I hope tmy_realpath() won't fail with -ENOMEM. */
1011++ retval = -ENOENT;
1012++ real_program_name = tmy_realpath(original_name);
1013++
1014++ if (!real_program_name)
1015++ goto out;
1016++
1017++ /* Get realpath of symbolic link. */
1018++ symlink_program_name = tmy_realpath_nofollow(original_name);
1019++ if (!symlink_program_name)
1020++ goto out;
1021++
1022++ r.name = real_program_name;
1023++ tmy_fill_path_info(&r);
1024++ s.name = symlink_program_name;
1025++ tmy_fill_path_info(&s);
1026++ l.name = strrchr(old_domain_name, ' ');
1027++
1028++ if (l.name)
1029++ l.name++;
1030++ else
1031++ l.name = old_domain_name;
1032++ tmy_fill_path_info(&l);
1033++
1034++ /* Check 'alias' directive. */
1035++ if (tmy_pathcmp(&r, &s)) {
1036++ struct alias_entry *ptr;
1037++
1038++ /* Is this program allowed to be called via symbolic links? */
1039++ list_for_each_entry(ptr, &alias_list, list) {
1040++ if (ptr->is_deleted ||
1041++ tmy_pathcmp(&r, ptr->original_name) ||
1042++ tmy_pathcmp(&s, ptr->aliased_name))
1043++ continue;
1044++ memset(real_program_name, 0, TMY_MAX_PATHNAME_LEN);
1045++ strncpy(real_program_name,
1046++ ptr->aliased_name->name,
1047++ TMY_MAX_PATHNAME_LEN - 1);
1048++ tmy_fill_path_info(&r);
1049++ break;
1050++ }
1051++ }
1052++
1053++ /* Compare basename of real_program_name and argv[0] */
1054++ if (bprm->argc > 0 && tmy_flags(TMY_MAC_FOR_ARGV0)) {
1055++
1056++ char *org_argv0 = tmy_get_argv0(bprm);
1057++
1058++ retval = -ENOMEM;
1059++ if (org_argv0) {
1060++
1061++ const int len = strlen(org_argv0);
1062++ char *printable_argv0 = tmy_alloc(len * 4 + 8);
1063++
1064++ if (printable_argv0 &&
1065++ !tmy_escape(printable_argv0, org_argv0,
1066++ len * 4 + 8)) {
1067++ const char *base_argv0;
1068++ const char *base_filename;
1069++
1070++ base_argv0 = strrchr(printable_argv0, '/');
1071++ if (!base_argv0)
1072++ base_argv0 = printable_argv0;
1073++ else
1074++ base_argv0++;
1075++
1076++ base_filename = strrchr(real_program_name, '/');
1077++ if (!base_filename)
1078++ base_filename = real_program_name;
1079++ else
1080++ base_filename++;
1081++
1082++ if (strcmp(base_argv0, base_filename))
1083++ retval = tmy_argv0_perm(&r, base_argv0);
1084++ else
1085++ retval = 0;
1086++ }
1087++
1088++ tmy_free(printable_argv0);
1089++ tmy_free(org_argv0);
1090++ }
1091++
1092++ if (retval)
1093++ goto out;
1094++
1095++ }
1096++
1097++
1098++ /* Check 'aggregator' directive. */
1099++ {
1100++ struct aggregator_entry *ptr;
1101++
1102++ /* Is this program allowed to be aggregated? */
1103++ list_for_each_entry(ptr, &aggregator_list, list) {
1104++ if (ptr->is_deleted ||
1105++ !tmy_path_match(&r, ptr->original_name))
1106++ continue;
1107++ memset(real_program_name, 0, TMY_MAX_PATHNAME_LEN);
1108++ strncpy(real_program_name,
1109++ ptr->aggregated_name->name,
1110++ TMY_MAX_PATHNAME_LEN - 1);
1111++ tmy_fill_path_info(&r);
1112++ break;
1113++ }
1114++ }
1115++
1116++ /* Check execute permission. */
1117++ retval = tmy_exec_perm(&r, filp);
1118++ if (retval < 0)
1119++ goto out;
1120++
1121++ /* Allocate memory for calcurating domain name. */
1122++ retval = -ENOMEM;
1123++ new_domain_name = tmy_alloc(TMY_MAX_PATHNAME_LEN + 16);
1124++ if (!new_domain_name)
1125++ goto out;
1126++
1127++ if (tmy_is_domain_initializer(old_domain->domainname, &r, &l))
1128++ /* Transit to the child of KERNEL_DOMAIN domain. */
1129++ snprintf(new_domain_name, TMY_MAX_PATHNAME_LEN + 1,
1130++ TMY_ROOT_NAME " " "%s", real_program_name);
1131++ else if (old_domain == &KERNEL_DOMAIN && !sbin_init_started)
1132++ /*
1133++ * Needn't to transit from kernel domain
1134++ * before starting /sbin/init .
1135++ * But transit from kernel domain if executing initializers,
1136++ * for they might start before /sbin/init .
1137++ */
1138++ domain = old_domain;
1139++ else if (tmy_is_domain_keeper(old_domain->domainname, &r, &l))
1140++ /* Keep current domain. */
1141++ domain = old_domain;
1142++ else
1143++ /* Normal domain transition. */
1144++ snprintf(new_domain_name,
1145++ TMY_MAX_PATHNAME_LEN + 1,
1146++ "%s %s",
1147++ old_domain_name,
1148++ real_program_name);
1149++
1150++ if (domain || strlen(new_domain_name) >= TMY_MAX_PATHNAME_LEN)
1151++ goto ok;
1152++
1153++ if (is_enforce) {
1154++ domain = tmy_find_domain(new_domain_name);
1155++ if (!domain &&
1156++ tmy_supervisor("#Need to create domain\n%s\n",
1157++ new_domain_name) == 0) {
1158++ const u8 profile = TMY_SECURITY->domain->profile;
1159++ domain = tmy_new_domain(new_domain_name, profile);
1160++ }
1161++ } else {
1162++ const u8 profile = TMY_SECURITY->domain->profile;
1163++ domain = tmy_new_domain(new_domain_name, profile);
1164++ }
1165++
1166++ok: ;
1167++
1168++ if (!domain) {
1169++ printk(KERN_INFO "TOMOYO-ERROR: Domain '%s' not defined.\n",
1170++ new_domain_name);
1171++ if (is_enforce)
1172++ retval = -EPERM;
1173++ } else
1174++ retval = 0;
1175++out: ;
1176++
1177++ tmy_free(new_domain_name);
1178++ tmy_free(real_program_name);
1179++ tmy_free(symlink_program_name);
1180++ *next_domain = domain ? domain : old_domain;
1181++
1182++ return retval;
1183++}
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-headers.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-headers.diff (revision 755)
@@ -0,0 +1,776 @@
1+Data structures and prototype defitions for TOMOYO Linux.
2+
3+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
4+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5+ security/tomoyo/include/realpath.h | 45 ++
6+ security/tomoyo/include/tomoyo.h | 717 +++++++++++++++++++++++++++++++++++++
7+ 2 files changed, 762 insertions(+)
8+
9+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
10++++ linux-2.6.23/security/tomoyo/include/realpath.h 2007-11-21 09:30:48.805755344 +0900
11+@@ -0,0 +1,45 @@
12++/*
13++ * security/tomoyo/include/realpath.h
14++ *
15++ * Get the canonicalized absolute pathnames.
16++ * The basis for TOMOYO.
17++ */
18++
19++#ifndef _TMY_REALPATH_H
20++#define _TMY_REALPATH_H
21++
22++#include "tomoyo.h"
23++
24++struct path_info;
25++
26++/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
27++int tmy_realpath_dentry2(struct dentry *dentry,
28++ struct vfsmount *mnt,
29++ char *newname,
30++ int newname_len);
31++
32++/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
33++/* These functions use tmy_alloc(), so caller must tmy_free() */
34++/* if these functions didn't return NULL. */
35++char *tmy_realpath(const char *pathname);
36++char *tmy_realpath_nofollow(const char *pathname);
37++char *tmy_realpath_dentry(struct dentry *dentry, struct vfsmount *mnt);
38++
39++/* Allocate memory for structures. */
40++/* The RAM is chunked, so NEVER try to kfree() the returned pointer. */
41++void *tmy_alloc_element(const unsigned int size);
42++
43++/* Get used RAM size for tmy_alloc_elements(). */
44++unsigned int tmy_get_memory_used_for_elements(void);
45++
46++/* Keep the given name on the RAM. */
47++/* The RAM is shared, so NEVER try to modify or kfree() the returned name. */
48++const struct path_info *tmy_save_name(const char *name);
49++
50++/* Get used RAM size for tmy_save_name(). */
51++unsigned int tmy_get_memory_used_for_save_name(void);
52++
53++unsigned int tmy_get_memory_used_for_dynamic(void);
54++char *sysctlpath_from_table(struct ctl_table *table);
55++
56++#endif
57+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
58++++ linux-2.6.23/security/tomoyo/include/tomoyo.h 2007-11-21 09:31:22.958563328 +0900
59+@@ -0,0 +1,717 @@
60++/*
61++ * security/tomoyo/include/tomoyo.h
62++ *
63++ * Header for TOMOYO Linux.
64++ */
65++
66++#ifndef _TOMOYO_H
67++#define _TOMOYO_H
68++
69++#define TOMOYO_VERSION_CODE "2.1.1"
70++
71++#include <linux/kernel.h>
72++#include <linux/sched.h>
73++
74++#include <asm/ioctls.h>
75++#include <linux/audit.h>
76++#include <linux/binfmts.h>
77++#include <linux/delay.h>
78++#include <linux/file.h>
79++#include <linux/highmem.h>
80++#include <linux/init.h>
81++#include <linux/mm.h>
82++#include <linux/module.h>
83++#include <linux/mount.h>
84++#include <linux/namei.h>
85++#include <linux/net.h>
86++#include <linux/poll.h>
87++#include <linux/proc_fs.h>
88++#include <linux/security.h>
89++#include <linux/seq_file.h>
90++#include <linux/slab.h>
91++#include <linux/smp_lock.h>
92++#include <linux/string.h>
93++#include <linux/sysctl.h>
94++#include <linux/utime.h>
95++#include <linux/version.h>
96++#include <net/ip.h>
97++#include <net/ipv6.h>
98++#include <stdarg.h>
99++
100++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
101++#include <asm/uaccess.h>
102++#else
103++#include <linux/uaccess.h>
104++#endif
105++
106++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
107++#include <asm/irq.h>
108++#else
109++#include <linux/hardirq.h>
110++#endif
111++
112++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
113++#include <linux/namespace.h>
114++#else
115++#include <linux/mount.h>
116++#include <linux/mnt_namespace.h>
117++#endif
118++
119++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
120++typedef _Bool bool;
121++#endif
122++
123++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
124++#define mutex semaphore
125++#define mutex_init(mutex) init_MUTEX(mutex)
126++#define mutex_lock(mutex) down(mutex)
127++#define mutex_unlock(mutex) up(mutex)
128++#define mutex_lock_interruptible(mutex) down_interruptible(mutex)
129++#define DEFINE_MUTEX(mutexname) DECLARE_MUTEX(mutexname)
130++#endif
131++
132++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
133++#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
134++#endif
135++
136++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
137++static inline void *kzalloc(size_t size, int flags)
138++{
139++ void *ret = kmalloc(size, flags);
140++ if (ret)
141++ memset(ret, 0, size);
142++ return ret;
143++}
144++#endif
145++
146++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
147++#define NIPQUAD_FMT "%u.%u.%u.%u"
148++#endif
149++
150++/**
151++ * list_for_each_cookie - iterate over a list with cookie.
152++ * @pos: the &struct list_head to use as a loop cursor.
153++ * @cookie: the &struct list_head to use as a cookie.
154++ * @head: the head for your list.
155++ *
156++ * Same with list_for_each except that this primitive uses cookie
157++ * so that we can continue iteration.
158++ */
159++#define list_for_each_cookie(pos, cookie, head) \
160++ for ((cookie) || ((cookie) = (head)), pos = (cookie)->next; \
161++ prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
162++ (cookie) = pos, pos = pos->next)
163++
164++/**
165++ * list_add_tail_mb - add a new entry with memory barrier.
166++ * @new: new entry to be added.
167++ * @head: list head to add it before.
168++ *
169++ * Same with list_add_tail_rcu() except that this primitive uses mb()
170++ * so that we can traverse forwards using list_for_each() and
171++ * list_for_each_cookie().
172++ */
173++static inline void list_add_tail_mb(struct list_head *new,
174++ struct list_head *head)
175++{
176++ struct list_head *prev = head->prev;
177++ struct list_head *next = head;
178++ new->next = next;
179++ new->prev = prev;
180++ mb(); /* Avoid out-of-order execution. */
181++ next->prev = new;
182++ prev->next = new;
183++}
184++
185++extern struct seq_operations mounts_op;
186++extern struct mutex domain_acl_lock;
187++extern bool sbin_init_started;
188++
189++struct tmy_security {
190++ struct domain_info *domain;
191++ struct domain_info *prev_domain;
192++ u32 flags;
193++};
194++
195++#define TMY_SECURITY ((struct tmy_security *) current->security)
196++
197++struct path_info {
198++ const char *name;
199++ u32 hash; /* = full_name_hash(name, strlen(name)) */
200++ u16 total_len; /* = strlen(name) */
201++ u16 const_len; /* = tmy_const_part_length(name) */
202++ bool is_dir; /* = tmy_strendswith(name, "/") */
203++ bool is_patterned; /* = PathContainsPattern(name) */
204++ u16 depth; /* = tmy_path_depth(name) */
205++};
206++
207++#define TMY_MAX_PATHNAME_LEN 4000
208++
209++struct path_group_member {
210++ struct list_head list;
211++ const struct path_info *member_name;
212++ bool is_deleted;
213++};
214++
215++struct path_group_entry {
216++ struct list_head list;
217++ const struct path_info *group_name;
218++ struct list_head path_group_member_list;
219++};
220++
221++
222++struct mini_stat {
223++ uid_t uid;
224++ gid_t gid;
225++ ino_t ino;
226++};
227++struct dentry;
228++struct vfsmount;
229++struct obj_info {
230++ bool validate_done;
231++ bool path1_valid;
232++ bool path1_parent_valid;
233++ bool path2_parent_valid;
234++ struct dentry *path1_dentry;
235++ struct vfsmount *path1_vfsmnt;
236++ struct dentry *path2_dentry;
237++ struct vfsmount *path2_vfsmnt;
238++ struct mini_stat path1_stat;
239++ /* I don't handle path2_stat for rename operation. */
240++ struct mini_stat path1_parent_stat;
241++ struct mini_stat path2_parent_stat;
242++};
243++struct condition_list;
244++
245++struct linux_binprm;
246++struct pt_regs;
247++
248++/*
249++ * TOMOYO uses the following structures.
250++ * Memory allocated for these structures are never kfree()ed.
251++ * Since no locks are used for reading,
252++ * assignment must be performed atomically.
253++ */
254++
255++/************************ The structure for domains. ************************/
256++
257++struct acl_info {
258++ struct list_head list;
259++ const struct condition_list *cond;
260++ u8 type;
261++ bool is_deleted;
262++} __attribute__((__packed__));
263++
264++struct domain_info {
265++ struct list_head list;
266++ struct list_head acl_info_list;
267++ const struct path_info *domainname; /* Never NULL. */
268++ u8 profile;
269++ u8 is_deleted; /* 0: active, 1:deleted, 255:deleted-permanently */
270++ bool quota_warned;
271++};
272++
273++#define TMY_MAX_PROFILES 256
274++
275++struct file_acl {
276++ /* type = TMY_TYPE_FILE_ACL */
277++ struct acl_info head;
278++ u8 perm;
279++ bool u_is_group;
280++ union {
281++ const struct path_info *filename;
282++ const struct path_group_entry *group;
283++ } u;
284++};
285++
286++struct argv0_acl {
287++ /* type = TMY_TYPE_ARGV0_ACL */
288++ struct acl_info head;
289++ const struct path_info *filename; /* Pointer to single pathname. */
290++ const struct path_info *argv0; /* strrchr(argv[0], '/') + 1 */
291++};
292++
293++struct single_acl {
294++ /* type = TMY_TYPE_* */
295++ struct acl_info head;
296++ bool u_is_group;
297++ union {
298++ const struct path_info *filename;
299++ const struct path_group_entry *group;
300++ } u;
301++};
302++
303++struct double_acl {
304++ /* type = TMY_TYPE_RENAME_ACL or TMY_TYPE_LINK_ACL, */
305++ struct acl_info head;
306++ bool u1_is_group;
307++ bool u2_is_group;
308++ union {
309++ const struct path_info *filename1;
310++ const struct path_group_entry *group1;
311++ } u1;
312++ union {
313++ const struct path_info *filename2;
314++ const struct path_group_entry *group2;
315++ } u2;
316++};
317++
318++struct address_group_member {
319++ struct list_head list;
320++ union {
321++ u32 ipv4; /* Host byte order */
322++ u16 ipv6[8]; /* Network byte order */
323++ } min, max;
324++ bool is_deleted;
325++ bool is_ipv6;
326++};
327++
328++struct address_group_entry {
329++ struct list_head list;
330++ const struct path_info *group_name;
331++ struct list_head address_group_member_list;
332++};
333++
334++#define TMY_TYPE_ADDRESS_GROUP 0
335++#define TMY_TYPE_IPv4 1
336++#define TMY_TYPE_IPv6 2
337++
338++struct net_acl {
339++ /* type = TYPE_IP_NETWORK_ACL */
340++ struct acl_info head;
341++ u8 operation_type;
342++ u8 record_type;
343++ union {
344++ struct {
345++ u32 min;
346++ u32 max;
347++ } ipv4;
348++ struct {
349++ u16 min[8];
350++ u16 max[8];
351++ } ipv6;
352++ const struct address_group_entry *group;
353++ } u;
354++ u16 min_port; /* Start of port number range. */
355++ u16 max_port; /* End of port number range. */
356++};
357++
358++struct signal_acl {
359++ /* type = TYPE_SIGNAL_ACL */
360++ struct acl_info head;
361++ u16 sig;
362++ /* Pointer to destination pattern. */
363++ const struct path_info *domainname;
364++};
365++
366++struct capability_acl {
367++ /* type = TYPE_CAPABILITY_ACL */
368++ struct acl_info head;
369++ u16 capability;
370++};
371++
372++/************************* Keywords for ACLs. *************************/
373++
374++#define TMY_AGGREGATOR "aggregator "
375++#define TMY_AGGREGATOR_LEN (sizeof(TMY_AGGREGATOR) - 1)
376++#define TMY_ALIAS "alias "
377++#define TMY_ALIAS_LEN (sizeof(TMY_ALIAS) - 1)
378++#define TMY_ALLOW_READ "allow_read "
379++#define TMY_ALLOW_READ_LEN (sizeof(TMY_ALLOW_READ) - 1)
380++#define TMY_DELETE "delete "
381++#define TMY_DELETE_LEN (sizeof(TMY_DELETE) - 1)
382++#define TMY_DENY_REWRITE "deny_rewrite "
383++#define TMY_DENY_REWRITE_LEN (sizeof(TMY_DENY_REWRITE) - 1)
384++#define TMY_FILE_PATTERN "file_pattern "
385++#define TMY_FILE_PATTERN_LEN (sizeof(TMY_FILE_PATTERN) - 1)
386++#define TMY_INITIALIZE_DOMAIN "initialize_domain "
387++#define TMY_INITIALIZE_DOMAIN_LEN (sizeof(TMY_INITIALIZE_DOMAIN) - 1)
388++#define TMY_KEEP_DOMAIN "keep_domain "
389++#define TMY_KEEP_DOMAIN_LEN (sizeof(TMY_KEEP_DOMAIN) - 1)
390++#define TMY_NO_INITIALIZE_DOMAIN "no_initialize_domain "
391++#define TMY_NO_INITIALIZE_DOMAIN_LEN (sizeof(TMY_NO_INITIALIZE_DOMAIN) - 1)
392++#define TMY_NO_KEEP_DOMAIN "no_keep_domain "
393++#define TMY_NO_KEEP_DOMAIN_LEN (sizeof(TMY_NO_KEEP_DOMAIN) - 1)
394++#define TMY_PATH_GROUP "path_group "
395++#define TMY_PATH_GROUP_LEN (sizeof(TMY_PATH_GROUP) - 1)
396++#define TMY_SELECT "select "
397++#define TMY_SELECT_LEN (sizeof(TMY_SELECT) - 1)
398++#define TMY_UNDELETE "undelete "
399++#define TMY_UNDELETE_LEN (sizeof(TMY_UNDELETE) - 1)
400++
401++#define TMY_ALLOW_MOUNT "allow_mount "
402++#define TMY_ALLOW_MOUNT_LEN (sizeof(TMY_ALLOW_MOUNT) - 1)
403++#define TMY_DENY_UNMOUNT "deny_unmount "
404++#define TMY_DENY_UNMOUNT_LEN (sizeof(TMY_DENY_UNMOUNT) - 1)
405++#define TMY_ALLOW_PIVOT_ROOT "allow_pivot_root "
406++#define TMY_ALLOW_PIVOT_ROOT_LEN (sizeof(TMY_ALLOW_PIVOT_ROOT) - 1)
407++
408++#define TMY_USE_PROFILE "use_profile "
409++
410++#define TMY_ROOT_NAME "<kernel>"
411++#define TMY_ROOT_NAME_LEN (sizeof(TMY_ROOT_NAME) - 1)
412++
413++#define TMY_ALLOW_ARGV0 "allow_argv0 "
414++#define TMY_ALLOW_ARGV0_LEN (sizeof(TMY_ALLOW_ARGV0) - 1)
415++
416++#define TMY_ADDRESS_GROUP "address_group "
417++#define TMY_ADDRESS_GROUP_LEN (sizeof(TMY_ADDRESS_GROUP) - 1)
418++#define TMY_ALLOW_NETWORK "allow_network "
419++#define TMY_ALLOW_NETWORK_LEN (sizeof(TMY_ALLOW_NETWORK) - 1)
420++
421++#define TMY_ALLOW_SIGNAL "allow_signal "
422++#define TMY_ALLOW_SIGNAL_LEN (sizeof(TMY_ALLOW_SIGNAL) - 1)
423++
424++#define TMY_ALLOW_CAPABILITY "allow_capability "
425++#define TMY_ALLOW_CAPABILITY_LEN (sizeof(TMY_ALLOW_CAPABILITY) - 1)
426++#define TMY_MAC_FOR_CAPABILITY "MAC_FOR_CAPABILITY::"
427++#define TMY_MAC_FOR_CAPABILITY_LEN (sizeof(TMY_MAC_FOR_CAPABILITY) - 1)
428++
429++/******************** Index numbers for Access Controls. ********************/
430++
431++#define TMY_COMMENT 0
432++#define TMY_MAC_FOR_FILE 1
433++#define TMY_MAC_FOR_ARGV0 2
434++#define TMY_MAC_FOR_NETWORK 3
435++#define TMY_MAC_FOR_SIGNAL 4
436++#define TMY_DENY_CONCEAL_MOUNT 5
437++#define TMY_RESTRICT_MOUNT 6
438++#define TMY_RESTRICT_UMOUNT 7
439++#define TMY_RESTRICT_PIVOT_ROOT 8
440++#define TMY_MAX_ACCEPT_ENTRY 9
441++#define TMY_MAX_GRANT_LOG 10
442++#define TMY_MAX_REJECT_LOG 11
443++#define TMY_VERBOSE 12
444++#define TMY_ALLOW_ENFORCE_GRACE 13
445++#define TMY_MAX_CONTROL_INDEX 14
446++
447++#define TMY_NETWORK_ACL_UDP_BIND 0
448++#define TMY_NETWORK_ACL_UDP_CONNECT 1
449++#define TMY_NETWORK_ACL_TCP_BIND 2
450++#define TMY_NETWORK_ACL_TCP_LISTEN 3
451++#define TMY_NETWORK_ACL_TCP_CONNECT 4
452++#define TMY_NETWORK_ACL_TCP_ACCEPT 5
453++#define TMY_NETWORK_ACL_RAW_BIND 6
454++#define TMY_NETWORK_ACL_RAW_CONNECT 7
455++
456++/************* Index numbers for Capability Controls. **********/
457++
458++/* socket(PF_INET or PF_INET6, SOCK_STREAM, *) */
459++#define TMY_INET_STREAM_SOCKET_CREATE 0
460++/* listen() for PF_INET or PF_INET6, SOCK_STREAM */
461++#define TMY_INET_STREAM_SOCKET_LISTEN 1
462++/* connect() for PF_INET or PF_INET6, SOCK_STREAM */
463++#define TMY_INET_STREAM_SOCKET_CONNECT 2
464++/* socket(PF_INET or PF_INET6, SOCK_DGRAM, *) */
465++#define TMY_USE_INET_DGRAM_SOCKET 3
466++/* socket(PF_INET or PF_INET6, SOCK_RAW, *) */
467++#define TMY_USE_INET_RAW_SOCKET 4
468++/* socket(PF_ROUTE, *, *) */
469++#define TMY_USE_ROUTE_SOCKET 5
470++/* socket(PF_PACKET, *, *) */
471++#define TMY_USE_PACKET_SOCKET 6
472++/* sys_mount() */
473++#define TMY_SYS_MOUNT 7
474++/* sys_umount() */
475++#define TMY_SYS_UMOUNT 8
476++/* sys_reboot() */
477++#define TMY_SYS_REBOOT 9
478++/* sys_chroot() */
479++#define TMY_SYS_CHROOT 10
480++/* sys_kill(), sys_tkill(), sys_tgkill() */
481++#define TMY_SYS_KILL 11
482++/* sys_vhangup() */
483++#define TMY_SYS_VHANGUP 12
484++/* do_settimeofday(), sys_adjtimex() */
485++#define TMY_SYS_SETTIME 13
486++/* sys_nice(), sys_setpriority() */
487++#define TMY_SYS_NICE 14
488++/* sys_sethostname(), sys_setdomainname() */
489++#define TMY_SYS_SETHOSTNAME 15
490++/* sys_create_module(), sys_init_module(), sys_delete_module() */
491++#define TMY_USE_KERNEL_MODULE 16
492++/* sys_mknod(S_IFIFO) */
493++#define TMY_CREATE_FIFO 17
494++/* sys_mknod(S_IFBLK) */
495++#define TMY_CREATE_BLOCK_DEV 18
496++/* sys_mknod(S_IFCHR) */
497++#define TMY_CREATE_CHAR_DEV 19
498++/* sys_mknod(S_IFSOCK) */
499++#define TMY_CREATE_UNIX_SOCKET 20
500++/* sys_link() */
501++#define TMY_SYS_LINK 21
502++/* sys_symlink() */
503++#define TMY_SYS_SYMLINK 22
504++/* sys_rename() */
505++#define TMY_SYS_RENAME 23
506++/* sys_unlink() */
507++#define TMY_SYS_UNLINK 24
508++/* sys_chmod(), sys_fchmod() */
509++#define TMY_SYS_CHMOD 25
510++/* sys_chown(), sys_fchown(), sys_lchown() */
511++#define TMY_SYS_CHOWN 26
512++/* sys_ioctl(), compat_sys_ioctl() */
513++#define TMY_SYS_IOCTL 27
514++/* sys_kexec_load() */
515++#define TMY_SYS_KEXEC_LOAD 28
516++/* sys_pivot_root() */
517++#define TMY_SYS_PIVOT_ROOT 29
518++#define TMY_MAX_CAPABILITY_INDEX 30
519++
520++/******************** Index numbers for updates counter. ********************/
521++
522++#define TMY_UPDATE_DOMAINPOLICY 0
523++#define TMY_UPDATE_SYSTEMPOLICY 1
524++#define TMY_UPDATE_EXCEPTIONPOLICY 2
525++#define TMY_UPDATE_PROFILE 3
526++#define TMY_UPDATE_QUERY 4
527++#define TMY_UPDATE_MANAGER 5
528++#define TMY_UPDATE_GRANT_LOG 6
529++#define TMY_UPDATE_REJECT_LOG 7
530++#define TMY_MAX_UPDATES_COUNTER 8
531++
532++/*************** Indexes for /sys/kernel/security interfaces. ***************/
533++
534++#define TMY_DOMAINPOLICY 0
535++#define TMY_SYSTEMPOLICY 1
536++#define TMY_EXCEPTIONPOLICY 2
537++#define TMY_DOMAIN_STATUS 3
538++#define TMY_PROCESS_STATUS 4
539++#define TMY_MEMINFO 5
540++#define TMY_SELFDOMAIN 6
541++#define TMY_PROFILE 7
542++#define TMY_QUERY 8
543++#define TMY_MANAGER 9
544++#define TMY_UPDATESCOUNTER 10
545++#define TMY_GRANT_LOG 11
546++#define TMY_REJECT_LOG 12
547++#define TMY_VERSION 13
548++
549++/*************** The structure for /sys/kernel/security interfaces. *********/
550++
551++struct io_buffer {
552++ int (*read) (struct io_buffer *);
553++ struct mutex read_mutex; /* Lock for reading. */
554++ int (*write) (struct io_buffer *);
555++ struct mutex write_mutex; /* Lock for updating. */
556++ int (*poll) (struct file *file, poll_table *wait);
557++ struct list_head *read_var1; /* The position currently reading from. */
558++ struct list_head *read_var2; /* Extra variables for reading. */
559++ struct domain_info *write_var1; /* The position currently writing to. */
560++ int read_step; /* The step for reading. */
561++ char *read_buf; /* Buffer for reading. */
562++ bool read_eof; /* EOF flag for reading. */
563++ int read_avail; /* Bytes available for reading. */
564++ int readbuf_size; /* Size of read buffer. */
565++ char *write_buf; /* Buffer for writing. */
566++ int write_avail; /* Bytes available for writing. */
567++ int writebuf_size; /* Size of write buffer. */
568++};
569++
570++/************************* PROTOTYPES *************************/
571++
572++char *tmy_find_condition_part(char *data);
573++const struct condition_list *tmy_assign_condition(const char *condition);
574++int tmy_check_condition(const struct condition_list *ptr,
575++ struct obj_info *obj);
576++int tmy_dump_condition(struct io_buffer *head,
577++ const struct condition_list *ptr);
578++const char *tmy_get_exe(void);
579++const char *tmy_getmsg(bool is_enforce);
580++const char *tmy_lastname(const struct domain_info *domain);
581++const char *tmy_acltype2keyword(const unsigned int acl_type);
582++
583++int tmy_mount_perm(char *dev_name,
584++ char *dir_name,
585++ char *type,
586++ unsigned long flags);
587++int tmy_conceal_mount(struct nameidata *nd);
588++int tmy_umount_perm(struct vfsmount *mnt);
589++int tmy_add_mount_policy(char *data, const bool is_delete);
590++int tmy_read_mount_policy(struct io_buffer *head);
591++int tmy_add_no_umount_policy(char *data, const bool is_delete);
592++int tmy_read_no_umount_policy(struct io_buffer *head);
593++int tmy_pivot_root_perm(struct nameidata *old_nd,
594++ struct nameidata *new_nd);
595++int tmy_add_pivot_root_policy(char *data, const bool is_delete);
596++int tmy_read_pivot_root_policy(struct io_buffer *head);
597++
598++int tmy_add_aggregator_policy(char *data, const bool is_delete);
599++int tmy_add_address_group_policy(char *data, const bool is_delete);
600++int tmy_add_alias_policy(char *data, const bool is_delete);
601++int tmy_add_argv0_policy(char *data,
602++ struct domain_info *domain,
603++ const struct condition_list *cond,
604++ const bool is_delete);
605++int tmy_add_acl(struct domain_info *domain, struct acl_info *acl);
606++int tmy_add_capability_policy(char *data,
607++ struct domain_info *domain,
608++ const struct condition_list *cond,
609++ const bool is_delete);
610++int tmy_add_domain_initializer_policy(char *data,
611++ const bool is_not,
612++ const bool is_delete);
613++int tmy_add_domain_keeper_policy(char *data,
614++ const bool is_not,
615++ const bool is_delete);
616++int tmy_file_perm(const char *filename0, const u8 perm, const char *operation);
617++int tmy_add_file_policy(char *data,
618++ struct domain_info *domain,
619++ const struct condition_list *cond,
620++ const bool is_delete);
621++int tmy_add_globally_readable_policy(char *data, const bool is_delete);
622++int tmy_add_group_policy(char *data, const bool is_delete);
623++int tmy_add_network_policy(char *data,
624++ struct domain_info *domain,
625++ const struct condition_list *cond,
626++ const bool is_delete);
627++int tmy_add_no_rewrite_policy(char *pattern, const bool is_delete);
628++int tmy_add_pattern_policy(char *data, const bool is_delete);
629++int tmy_supervisor(const char *fmt, ...)
630++ __attribute__((format(printf, 1, 2)));
631++#ifdef CONFIG_SECURITY_TOMOYO_USE_AUDITD
632++int tmy_audit(const char *fmt, ...)
633++ __attribute__((format(printf, 1, 2)));
634++#else
635++#define tmy_audit printk
636++#endif
637++
638++int tmy_del_acl(struct acl_info *ptr);
639++int tmy_delete_domain(char *data);
640++bool tmy_is_correct_domain(const unsigned char *domainname,
641++ const char *function);
642++bool tmy_correct_path(const char *filename,
643++ const int start_type,
644++ const int pattern_type,
645++ const int end_type,
646++ const char *function);
647++bool tmy_is_domain_def(const unsigned char *buffer);
648++bool tmy_path_match(const struct path_info *pathname0,
649++ const struct path_info *pattern0);
650++int tmy_read_aggregator_policy(struct io_buffer *head);
651++int tmy_read_alias_policy(struct io_buffer *head);
652++int tmy_read_domain_initializer_policy(struct io_buffer *head);
653++int tmy_read_domain_keeper_policy(struct io_buffer *head);
654++int tmy_read_globally_readable_policy(struct io_buffer *head);
655++int tmy_read_path_group_policy(struct io_buffer *head);
656++int tmy_read_no_rewrite_policy(struct io_buffer *head);
657++int tmy_read_pattern_policy(struct io_buffer *head);
658++int tmy_read_address_group_policy(struct io_buffer *head);
659++int tmy_argv0_perm(const struct path_info *filename, const char *argv0);
660++int tmy_capable(const unsigned int capability);
661++int tmy_network_listen_acl(const bool is_ipv6,
662++ const u8 *address,
663++ const u16 port);
664++int tmy_network_connect_acl(const bool is_ipv6,
665++ const int sock_type,
666++ const u8 *address,
667++ const u16 port);
668++int tmy_network_bind_acl(const bool is_ipv6,
669++ const int sock_type,
670++ const u8 *address,
671++ const u16 port);
672++int tmy_network_sendmsg_acl(const bool is_ipv6,
673++ const int sock_type,
674++ const u8 *address,
675++ const u16 port);
676++int tmy_network_accept_acl(const bool is_ipv6,
677++ const u8 *address,
678++ const u16 port);
679++int tmy_network_recvmsg_acl(const bool is_ipv6,
680++ const int sock_type,
681++ const u8 *address,
682++ const u16 port);
683++
684++int tmy_signal_acl(int sig, int pid);
685++int tmy_add_signal_policy(char *data,
686++ struct domain_info *domain,
687++ const struct condition_list *cond,
688++ const bool is_delete);
689++
690++char *tmy_init_audit_log(int *len, const u8 profile, const unsigned int mode);
691++int tmy_write_audit_log(char *log, const bool is_granted);
692++int tmy_acltype2paths(const unsigned int acl_type);
693++int tmy_io_printf(struct io_buffer *head, const char *fmt, ...)
694++ __attribute__((format(printf, 2, 3)));
695++struct domain_info *tmy_find_domain(const char *domainname);
696++struct domain_info *tmy_new_domain(const char *domainname, const u8 profile);
697++struct domain_info *tmy_undelete_domain(const char *domainname0);
698++bool tmy_quota(void);
699++unsigned int tmy_flags(const unsigned int index);
700++bool tmy_audit_grant(void);
701++bool tmy_audit_reject(void);
702++void tmy_update_counter(const unsigned char index);
703++void *tmy_alloc(const size_t size);
704++void tmy_free(const void *p);
705++void tmy_fill_path_info(struct path_info *ptr);
706++const char *tmy_capability2keyword(const unsigned int capability);
707++int tmy_read_capability_profile(struct io_buffer *head);
708++int tmy_set_capability_profile(const char *data, unsigned int value,
709++ const unsigned int profile);
710++
711++int tmy_read_grant_log(struct io_buffer *head);
712++int tmy_poll_grant_log(struct file *file, poll_table *wait);
713++int tmy_read_reject_log(struct io_buffer *head);
714++int tmy_poll_reject_log(struct file *file, poll_table *wait);
715++
716++static inline bool tmy_pathcmp(const struct path_info *a,
717++ const struct path_info *b)
718++{
719++ return a->hash != b->hash || strcmp(a->name, b->name);
720++}
721++
722++extern struct domain_info KERNEL_DOMAIN;
723++extern struct list_head domain_list;
724++void tmy_load_policy(const char *filename);
725++int tmy_find_next_domain(struct linux_binprm *,
726++ struct domain_info **);
727++
728++struct path_info;
729++
730++int tmy_exec_perm(const struct path_info *filename, struct file *filp);
731++/* Check whether the given dentry is allowed to read/write/execute. */
732++int tmy_open_perm(struct dentry *dentry, struct vfsmount *mnt, const int flag);
733++/* Check whether the given dentry is allowed to write. */
734++int tmy_single_write_perm(const unsigned int operation,
735++ struct dentry *dentry,
736++ struct vfsmount *mnt);
737++int tmy_double_write_perm(const unsigned int operation,
738++ struct dentry *dentry1,
739++ struct vfsmount *mnt1,
740++ struct dentry *dentry2,
741++ struct vfsmount *mnt2);
742++int tmy_rewrite_perm(struct file *filp);
743++
744++struct inode;
745++
746++/******************** Index numbers for Access Controls. ********************/
747++
748++#define TMY_TYPE_CREATE_ACL 0
749++#define TMY_TYPE_UNLINK_ACL 1
750++#define TMY_TYPE_MKDIR_ACL 2
751++#define TMY_TYPE_RMDIR_ACL 3
752++#define TMY_TYPE_MKFIFO_ACL 4
753++#define TMY_TYPE_MKSOCK_ACL 5
754++#define TMY_TYPE_MKBLOCK_ACL 6
755++#define TMY_TYPE_MKCHAR_ACL 7
756++#define TMY_TYPE_TRUNCATE_ACL 8
757++#define TMY_TYPE_SYMLINK_ACL 9
758++#define TMY_TYPE_LINK_ACL 10
759++#define TMY_TYPE_RENAME_ACL 11
760++#define TMY_TYPE_REWRITE_ACL 12
761++
762++#define TMY_TYPE_FILE_ACL 100
763++#define TMY_TYPE_ARGV0_ACL 101
764++#define TMY_TYPE_IP_NETWORK_ACL 103
765++#define TMY_TYPE_SIGNAL_ACL 104
766++#define TMY_TYPE_CAPABILITY_ACL 105
767++
768++#define TMY_CHECK_READ_FOR_OPEN_EXEC 1
769++
770++char *tmy_print_ipv6(char *buffer, const int buffer_len, const u16 *ip);
771++const char *tmy_network2keyword(const unsigned int operation);
772++
773++/* to check "if task.parent.pid" condition. */
774++extern asmlinkage long sys_getppid(void);
775++
776++#endif
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-signal.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-signal.diff (revision 755)
@@ -0,0 +1,243 @@
1+Signal control functions for TOMOYO Linux.
2+TOMOYO Linux checks sending signal by signal number and
3+the domain of target process. In order to check signal
4+permission, LSM expansion patch [TOMOYO /] is needed.
5+
6+Each permission can be automatically accumulated into
7+the policy of each domain using 'learning mode'.
8+
9+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
10+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
11+ security/tomoyo/signal.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++
12+ 1 file changed, 227 insertions(+)
13+
14+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
15++++ linux-2.6.23/security/tomoyo/signal.c 2007-11-09 16:51:15.000000000 +0900
16+@@ -0,0 +1,227 @@
17++/*
18++ * security/tomoyo/signal.c
19++ *
20++ * Signal access contol functions for TOMOYO Linux.
21++ */
22++
23++#include "tomoyo.h"
24++#include "realpath.h"
25++
26++/************************* AUDIT FUNCTIONS *************************/
27++
28++static int tmy_audit_signal_log(const int signal,
29++ const struct path_info *dest_domain,
30++ const bool is_granted,
31++ const u8 profile,
32++ const unsigned int mode)
33++{
34++ char *buf;
35++ int len;
36++
37++ if (is_granted) {
38++ if (!tmy_audit_grant())
39++ return 0;
40++ } else {
41++ if (!tmy_audit_reject())
42++ return 0;
43++ }
44++
45++ len = dest_domain->total_len;
46++ buf = tmy_init_audit_log(&len, profile, mode);
47++
48++ if (!buf)
49++ return -ENOMEM;
50++
51++ snprintf(buf + strlen(buf),
52++ len - strlen(buf) - 1,
53++ "%s%d %s\n",
54++ TMY_ALLOW_SIGNAL, signal, dest_domain->name);
55++
56++ return tmy_write_audit_log(buf, is_granted);
57++}
58++
59++/************************* SIGNAL ACL HANDLER *************************/
60++
61++static int tmy_add_signal_entry(const u16 sig, const char *dest_pattern,
62++ struct domain_info *domain,
63++ const struct condition_list *cond,
64++ const bool is_delete)
65++{
66++ struct acl_info *ptr;
67++ struct signal_acl *acl;
68++ const struct path_info *saved_dest_pattern;
69++ int error = -ENOMEM;
70++
71++ if (!domain)
72++ return -EINVAL;
73++ if (!dest_pattern ||
74++ !tmy_is_correct_domain(dest_pattern, __FUNCTION__))
75++ return -EINVAL;
76++
77++ saved_dest_pattern = tmy_save_name(dest_pattern);
78++ if (!saved_dest_pattern)
79++ return -ENOMEM;
80++
81++ mutex_lock(&domain_acl_lock);
82++
83++ if (is_delete)
84++ goto remove;
85++
86++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
87++ acl = (struct signal_acl *) ptr;
88++
89++ if (ptr->type == TMY_TYPE_SIGNAL_ACL && acl->sig == sig
90++ && ptr->cond == cond
91++ && !tmy_pathcmp(acl->domainname, saved_dest_pattern)) {
92++ ptr->is_deleted = 0;
93++ /* Found. Nothing to do. */
94++ error = 0;
95++ goto ok;
96++ }
97++ }
98++ /* Not found. Append it to the tail. */
99++ acl = tmy_alloc_element(sizeof(*acl));
100++ if (!acl)
101++ goto ok;
102++
103++ acl->head.type = TMY_TYPE_SIGNAL_ACL;
104++ acl->head.cond = cond;
105++ acl->sig = sig;
106++ acl->domainname = saved_dest_pattern;
107++ error = tmy_add_acl(domain, (struct acl_info *) acl);
108++ goto ok;
109++remove: ;
110++ error = -ENOENT;
111++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
112++ acl = (struct signal_acl *) ptr;
113++ if (ptr->type != TMY_TYPE_SIGNAL_ACL || ptr->cond != cond ||
114++ ptr->is_deleted || acl->sig != sig ||
115++ tmy_pathcmp(acl->domainname, saved_dest_pattern))
116++ continue;
117++ error = tmy_del_acl(ptr);
118++ break;
119++ }
120++
121++ok: ;
122++ mutex_unlock(&domain_acl_lock);
123++
124++ return error;
125++}
126++
127++/**
128++ * tmy_signal_acl - check permission for kill(2)/tkill(2)/tgkill(2).
129++ * @sig: signal number.
130++ * @pid: pid of destination process.
131++ *
132++ * Returns zero if permission granted.
133++ * Returns nonzero if permission denied.
134++ */
135++int tmy_signal_acl(const int sig, const int pid)
136++{
137++ struct domain_info *domain = TMY_SECURITY->domain;
138++ struct domain_info *dest = NULL;
139++ const char *dest_pattern;
140++ struct acl_info *ptr;
141++ const u16 hash = sig;
142++ const u8 profile = domain->profile;
143++ const unsigned int mode = tmy_flags(TMY_MAC_FOR_SIGNAL);
144++ const bool is_enforce = (mode == 3);
145++ bool found = 0;
146++
147++ if (!mode)
148++ return 0;
149++ if (!sig)
150++ return 0; /* No check for NULL signal. */
151++ if (current->pid == pid) {
152++ tmy_audit_signal_log(sig, domain->domainname, 1, profile, mode);
153++ return 0; /* No check for self. */
154++ }
155++
156++ { /* Simplified checking. */
157++ struct task_struct *p = NULL;
158++ read_lock(&tasklist_lock);
159++ if (pid > 0)
160++ p = find_task_by_pid((pid_t) pid);
161++ else if (pid == 0)
162++ p = current;
163++ else if (pid == -1)
164++ dest = &KERNEL_DOMAIN;
165++ else
166++ p = find_task_by_pid((pid_t) -pid);
167++ if (p)
168++ /* "struct task_struct"->security is not NULL. */
169++ dest = ((struct tmy_security *) p->security)->domain;
170++ read_unlock(&tasklist_lock);
171++ if (!dest)
172++ return 0; /* I can't find destinatioin. */
173++ }
174++
175++ if (domain == dest) {
176++ tmy_audit_signal_log(sig, dest->domainname, 1, profile, mode);
177++ return 0;
178++ }
179++
180++ dest_pattern = dest->domainname->name;
181++ list_for_each_entry(ptr, &domain->acl_info_list, list) {
182++ struct signal_acl *acl = (struct signal_acl *) ptr;
183++
184++ if (ptr->type == TMY_TYPE_SIGNAL_ACL && ptr->is_deleted == 0
185++ && acl->sig == hash &&
186++ tmy_check_condition(ptr->cond, NULL) == 0) {
187++ const int len = acl->domainname->total_len;
188++
189++ if (strncmp(acl->domainname->name,
190++ dest_pattern, len) == 0
191++ && (dest_pattern[len] == ' ' ||
192++ dest_pattern[len] == '\0')) {
193++ found = 1;
194++ break;
195++ }
196++ }
197++ }
198++
199++ tmy_audit_signal_log(sig, dest->domainname, found, profile, mode);
200++
201++ if (found)
202++ return 0;
203++
204++ if (tmy_flags(TMY_VERBOSE))
205++ tmy_audit("TOMOYO-%s: Signal %d to %s denied for %s\n",
206++ tmy_getmsg(is_enforce), sig,
207++ tmy_lastname(dest), tmy_lastname(domain));
208++
209++ if (is_enforce)
210++ return tmy_supervisor("%s\n" TMY_ALLOW_SIGNAL "%d %s\n",
211++ domain->domainname->name,
212++ sig, dest_pattern);
213++ if (mode == 1 && tmy_quota())
214++ tmy_add_signal_entry(sig, dest_pattern, domain, NULL, 0);
215++
216++ return 0;
217++}
218++
219++/**
220++ * tmy_add_signal_policy - add or delete signal policy.
221++ * @data: a line to parse.
222++ * @domain: pointer to "struct domain_info".
223++ * @cond: pointer to "struct condition_list". May be NULL.
224++ * @is_delete: is this delete request?
225++ *
226++ * Returns zero on success.
227++ * Returns nonzero on failure.
228++ */
229++int tmy_add_signal_policy(char *data,
230++ struct domain_info *domain,
231++ const struct condition_list *cond,
232++ const bool is_delete)
233++{
234++ int sig;
235++ char *domainname = strchr(data, ' ');
236++
237++ if (sscanf(data, "%d", &sig) == 1 && domainname &&
238++ tmy_is_domain_def(domainname + 1))
239++ return tmy_add_signal_entry(sig, domainname + 1, domain,
240++ cond, is_delete);
241++
242++ return -EINVAL;
243++}
--- tags/tomoyo-lsm/2.1.1/patches/tomoyo-file.diff (nonexistent)
+++ tags/tomoyo-lsm/2.1.1/patches/tomoyo-file.diff (revision 755)
@@ -0,0 +1,1487 @@
1+File access control functions for TOMOYO Linux.
2+TOMOYO Linux checks permission in
3+open/creat/unlink/truncate/ftruncate/mknod/mkdir/
4+rmdir/symlink/link/rename/uselib/sysctl .
5+
6+Each permission can be automatically accumulated into
7+the policy of each domain using 'learning mode'.
8+
9+Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
10+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
11+ security/tomoyo/file.c | 1471 +++++++++++++++++++++++++++++++++++++++++++++++++
12+ 1 file changed, 1471 insertions(+)
13+
14+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
15++++ linux-2.6.23/security/tomoyo/file.c 2007-11-09 16:39:25.000000000 +0900
16+@@ -0,0 +1,1471 @@
17++/*
18++ * security/tomoyo/file.c
19++ *
20++ * File access control functions for TOMOYO Linux.
21++ */
22++
23++#include "tomoyo.h"
24++#include "realpath.h"
25++
26++#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
27++
28++/************************* VARIABLES *************************/
29++
30++/***** The structure for globally readable files. *****/
31++
32++struct globally_readable_file_entry {
33++ struct list_head list;
34++ const struct path_info *filename;
35++ bool is_deleted;
36++};
37++
38++/***** The structure for filename patterns. *****/
39++
40++struct pattern_entry {
41++ struct list_head list;
42++ const struct path_info *pattern;
43++ bool is_deleted;
44++};
45++
46++/***** The structure for non-rewritable-by-default file patterns. *****/
47++
48++struct no_rewrite_entry {
49++ struct list_head list;
50++ const struct path_info *pattern;
51++ bool is_deleted;
52++};
53++
54++/***** The structure for detailed write operations. *****/
55++
56++static struct {
57++ const char *keyword;
58++ const int paths;
59++} acl_type_array[] = {
60++ { "create", 1 }, /* TMY_TYPE_CREATE_ACL */
61++ { "unlink", 1 }, /* TMY_TYPE_UNLINK_ACL */
62++ { "mkdir", 1 }, /* TMY_TYPE_MKDIR_ACL */
63++ { "rmdir", 1 }, /* TMY_TYPE_RMDIR_ACL */
64++ { "mkfifo", 1 }, /* TMY_TYPE_MKFIFO_ACL */
65++ { "mksock", 1 }, /* TMY_TYPE_MKSOCK_ACL */
66++ { "mkblock", 1 }, /* TMY_TYPE_MKBLOCK_ACL */
67++ { "mkchar", 1 }, /* TMY_TYPE_MKCHAR_ACL */
68++ { "truncate", 1 }, /* TMY_TYPE_TRUNCATE_ACL */
69++ { "symlink", 1 }, /* TMY_TYPE_SYMLINK_ACL */
70++ { "link", 2 }, /* TMY_TYPE_LINK_ACL */
71++ { "rename", 2 }, /* TMY_TYPE_RENAME_ACL */
72++ { "rewrite", 1 }, /* TMY_TYPE_REWRITE_ACL */
73++ { NULL, 0 }
74++};
75++
76++/************************* UTILITY FUNCTIONS *************************/
77++
78++/**
79++ * tmy_acltype2keyword - get keyword from access control index.
80++ * @acl_type: index number.
81++ *
82++ * Returns keyword that corresponds with @acl_type .
83++ */
84++const char *tmy_acltype2keyword(const unsigned int acl_type)
85++{
86++ return (acl_type < ARRAY_SIZE(acl_type_array))
87++ ? acl_type_array[acl_type].keyword : NULL;
88++}
89++
90++/**
91++ * tmy_acltype2paths - get number of arguments from access control index.
92++ * @acl_type: index number.
93++ *
94++ * Returns number of arguments that corresponds with @acl_type .
95++ */
96++int tmy_acltype2paths(const unsigned int acl_type)
97++{
98++ return (acl_type < ARRAY_SIZE(acl_type_array))
99++ ? acl_type_array[acl_type].paths : 0;
100++}
101++
102++static int tmy_strendswith(const char *name, const char *tail)
103++{
104++ int len;