• R/O
  • SSH
  • HTTPS

caitsith: コミット


コミットメタ情報

リビジョン242 (tree)
日時2017-05-15 20:48:47
作者kumaneko

ログメッセージ

caitsith-tools 0.2.2

変更サマリ

差分

--- tags/caitsith-tools/0.2.2/caitsith-tools.spec (nonexistent)
+++ tags/caitsith-tools/0.2.2/caitsith-tools.spec (revision 242)
@@ -0,0 +1,80 @@
1+Summary: Userspace tools for CaitSith 0.2
2+
3+Name: caitsith-tools
4+Version: 0.2
5+Release: 3
6+License: GPL
7+Group: System Environment/Kernel
8+ExclusiveOS: Linux
9+Autoreqprov: no
10+Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
11+##
12+## This spec file is intended to be distribution independent.
13+## I don't enable "BuildRequires:" line because rpmbuild will fail on
14+## environments where packages are managed by (e.g.) apt.
15+##
16+# BuildRequires: ncurses-devel
17+Requires: ncurses
18+Conflicts: caitsith-tools < 0.2-3
19+
20+Source0: http://osdn.dl.osdn.jp/caitsith/66538/caitsith-tools-0.2-20170515.tar.gz
21+
22+%description
23+This package contains userspace tools for administrating CaitSith 0.2.
24+Please see http://caitsith.osdn.jp/ for documentation.
25+
26+%prep
27+
28+%setup -q -n caitsith-tools
29+
30+%build
31+
32+make USRLIBDIR=%_libdir CFLAGS="-Wall $RPM_OPT_FLAGS"
33+
34+%install
35+
36+rm -rf $RPM_BUILD_ROOT
37+make INSTALLDIR=$RPM_BUILD_ROOT USRLIBDIR=%_libdir install
38+
39+%clean
40+
41+rm -rf $RPM_BUILD_ROOT
42+
43+%post
44+ldconfig || true
45+
46+%files
47+%defattr(-,root,root)
48+/sbin/*
49+%_libdir/caitsith/*
50+%_libdir/libcaitsith*
51+/usr/sbin/*
52+
53+%changelog
54+* Mon May 15 2017 0.2-3
55+- Correct errors in kernel_test/ programs.
56+
57+* Sun Oct 16 2016 0.2-2
58+- In order to cancel the effect of MS_REC|MS_SHARED done by systemd,
59+ mark MS_REC|MS_PRIVATE before mounting securityfs.
60+
61+* Wed Oct 05 2016 0.2-1
62+- Use /sys/kernel/security/caitsith/ by default and fall back to
63+ /proc/caitsith/ .
64+
65+* Thu Jul 23 2015 0.1-5
66+- caitsith-queryd: Copy a line to edit buffer correctly.
67+
68+* Sun Jan 05 2014 0.1-4
69+- Let caitsith-queryd use poll() rather than select().
70+
71+* Thu Feb 14 2013 0.1-3
72+- Change Makefile's build flags, as suggested by Simon Ruderich and Hideki
73+ Yamane. (Debian bug 674723)
74+- Change / to /* in rpm's %files section because Fedora 18 complains conflicts.
75+
76+* Sat May 05 2012 0.1-2
77+- caitsith-init: Count number of ACL entries correctly.
78+
79+* Sun Apr 01 2012 0.1-1
80+- First-release.
--- tags/caitsith-tools/0.2.2/kernel_test/caitsith_lsm_test.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/kernel_test/caitsith_lsm_test.c (revision 242)
@@ -0,0 +1,1847 @@
1+/*
2+ * caitsith_lsm_test.c
3+ *
4+ * Copyright (C) 2012-2013 Tetsuo Handa
5+ *
6+ * Version: 0.2 2016/10/05
7+ *
8+ * This program is free software; you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License v2 as published by the
10+ * Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful, but WITHOUT
13+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15+ * more details.
16+ *
17+ * You should have received a copy of the GNU General Public License along with
18+ * this program; if not, write to the Free Software Foundation, Inc.,
19+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20+ */
21+
22+#include <stdio.h>
23+#include <stdlib.h>
24+#include <string.h>
25+#include <unistd.h>
26+#include <sys/types.h>
27+#include <sys/stat.h>
28+#include <sys/socket.h>
29+#include <netinet/in.h>
30+#include <sys/wait.h>
31+#include <linux/ip.h>
32+#include <fcntl.h>
33+#include <errno.h>
34+#include <sys/mount.h>
35+#ifndef MS_REC
36+#define MS_REC 16384
37+#endif
38+#ifndef MS_PRIVATE
39+#define MS_PRIVATE (1 << 18)
40+#endif
41+
42+static FILE *fp = NULL;
43+
44+static void set(const char *str)
45+{
46+ fprintf(fp, "%s\n", str);
47+ fflush(fp);
48+ errno = 0;
49+}
50+
51+static void unset(const char *str)
52+{
53+ fprintf(fp, "delete %s\n", str);
54+ fflush(fp);
55+ errno = 0;
56+}
57+
58+static void unset2(const char *str)
59+{
60+ const char *cp = str;
61+ while (*cp) {
62+ if (*cp++ != '\n')
63+ continue;
64+ fprintf(fp, "delete ");
65+ fwrite(str, cp - str, 1, fp);
66+ str = cp;
67+ }
68+ fprintf(fp, "delete %s\n", str);
69+ fflush(fp);
70+ errno = 0;
71+}
72+
73+static void check(const char *prompt, int result)
74+{
75+ int err = errno;
76+ printf("%s%s\n", prompt, result ? "Success" : "Failed");
77+ if (!result) {
78+ fprintf(stderr, "Err: %s(%d)\n", strerror(err), err);
79+ {
80+ int fd2 = open(POLDIR "/self_domain", O_RDONLY);
81+ char c;
82+ fprintf(stderr, "task.domain=\"");
83+ while (read(fd2, &c, 1) == 1)
84+ fprintf(stderr, "%c", c);
85+ close(fd2);
86+ fprintf(stderr, "\"\n");
87+ }
88+ kill(1, SIGCONT);
89+ exit(1);
90+ }
91+ printf("\n");
92+ fflush(stdout);
93+}
94+
95+static void check_init(const char *prompt, const char *expected)
96+{
97+ int result;
98+ int fd = open(POLDIR "/.process_status", O_RDWR);
99+ char buffer[1024];
100+ char *cp;
101+ memset(buffer, 0, sizeof(buffer));
102+ kill(1, SIGHUP);
103+ sleep(1);
104+ write(fd, "1\n", 2);
105+ read(fd, buffer, sizeof(buffer) - 1);
106+ close(fd);
107+ cp = strchr(buffer, ' ');
108+ if (cp++)
109+ memmove(buffer, cp, strlen(cp) + 1);
110+ result = !strcmp(buffer, expected);
111+ printf("%s%s\n", prompt, result ? "Success" : "Failed");
112+ if (!result) {
113+ fprintf(stderr, "Err: expected='%s' result='%s'\n",
114+ expected, buffer);
115+ kill(1, SIGCONT);
116+ exit(1);
117+ }
118+ printf("\n");
119+ fflush(stdout);
120+}
121+
122+static void test_task_transition(void)
123+{
124+ int fd = open(POLDIR "/self_domain", O_WRONLY);
125+ char *policy;
126+
127+ policy = "100 acl manual_domain_transition\n"
128+ "0 allow domain=\"domain\\$\"\n";
129+ set(policy);
130+ check(policy, write(fd, "domain0", 7) != EOF);
131+ check(policy, write(fd, "domain10", 8) != EOF);
132+ check(policy, write(fd, "domainXYX", 9) == EOF);
133+ check(policy, write(fd, "domain200", 9) != EOF);
134+ unset(policy);
135+
136+ policy = "100 acl auto_domain_transition\n"
137+ "0 allow task.pid=1 transition=\"<init3>\"\n";
138+ set(policy);
139+ check_init(policy, "<init3>");
140+ unset(policy);
141+
142+ policy = "100 acl auto_domain_transition\n"
143+ "0 allow task.pid=1 task.uid!=0 transition=\"<init2>\"\n";
144+ set(policy);
145+ check_init(policy, "<init3>");
146+ unset(policy);
147+
148+ policy = "100 acl auto_domain_transition\n"
149+ "0 allow task.pid=1 transition=\"<init>\"\n";
150+ set(policy);
151+ check_init(policy, "<init>");
152+ unset(policy);
153+
154+ close(fd);
155+}
156+
157+static void test_file_read(void)
158+{
159+ int fd;
160+ char *policy;
161+
162+ policy = "100 acl read\n";
163+ set(policy);
164+ fd = open("/dev/null", O_RDONLY);
165+ check(policy, fd != EOF);
166+ close(fd);
167+ unset(policy);
168+
169+ policy = "100 acl read\n"
170+ "0 allow\n"
171+ "1 deny\n";
172+ set(policy);
173+ fd = open("/dev/null", O_RDONLY);
174+ check(policy, fd != EOF);
175+ close(fd);
176+ unset(policy);
177+
178+ policy = "100 acl read\n"
179+ "0 deny\n"
180+ "1 allow\n";
181+ set(policy);
182+ fd = open("/dev/null", O_RDONLY);
183+ check(policy, fd == EOF);
184+ close(fd);
185+ unset(policy);
186+
187+ policy = "100 acl read path=\"/dev/null\"\n"
188+ "0 allow\n"
189+ "1 deny\n";
190+ set(policy);
191+ fd = open("/dev/null", O_RDONLY);
192+ check(policy, fd != EOF);
193+ close(fd);
194+ unset(policy);
195+
196+ policy = "100 acl read path=\"/dev/null\"\n"
197+ "0 deny\n"
198+ "1 allow\n";
199+ set(policy);
200+ fd = open("/dev/null", O_RDONLY);
201+ check(policy, fd == EOF);
202+ close(fd);
203+ unset(policy);
204+
205+ policy = "100 acl read\n"
206+ "0 allow path=\"/dev/null\"\n"
207+ "1 deny\n";
208+ set(policy);
209+ fd = open("/dev/null", O_RDONLY);
210+ check(policy, fd != EOF);
211+ close(fd);
212+ unset(policy);
213+
214+ policy = "100 acl read\n"
215+ "0 deny path=\"/dev/null\"\n"
216+ "1 allow\n";
217+ set(policy);
218+ fd = open("/dev/null", O_RDONLY);
219+ check(policy, fd == EOF);
220+ close(fd);
221+ unset(policy);
222+
223+ policy = "100 acl read\n"
224+ "0 allow path.type=char path.dev_major=1 path.dev_minor=3\n"
225+ "1 deny\n";
226+ set(policy);
227+ fd = open("/dev/null", O_RDONLY);
228+ check(policy, fd != EOF);
229+ close(fd);
230+ unset(policy);
231+
232+ policy = "100 acl read\n"
233+ "0 deny path.type=char path.dev_major=1 path.dev_minor=3\n"
234+ "1 allow\n";
235+ set(policy);
236+ fd = open("/dev/null", O_RDONLY);
237+ check(policy, fd == EOF);
238+ close(fd);
239+ unset(policy);
240+
241+ policy = "100 acl read\n"
242+ "0 allow path.type=char path.dev_major=1 path.dev_minor!=3\n"
243+ "1 deny\n";
244+ set(policy);
245+ fd = open("/dev/null", O_RDONLY);
246+ check(policy, fd == EOF);
247+ close(fd);
248+ unset(policy);
249+
250+ policy = "100 acl read\n"
251+ "0 deny path.type=char path.dev_major=1 path.dev_minor!=3\n"
252+ "1 allow\n";
253+ set(policy);
254+ fd = open("/dev/null", O_RDONLY);
255+ check(policy, fd != EOF);
256+ close(fd);
257+ unset(policy);
258+
259+ policy = "string_group GROUP1 /dev/null\n"
260+ "100 acl read\n"
261+ "0 allow path=@GROUP1\n"
262+ "1 deny\n";
263+ set(policy);
264+ fd = open("/dev/null", O_RDONLY);
265+ check(policy, fd != EOF);
266+ close(fd);
267+ unset2(policy);
268+
269+ policy = "string_group GROUP1 /dev/null\n"
270+ "100 acl read\n"
271+ "0 deny path=@GROUP1\n"
272+ "1 allow\n";
273+ set(policy);
274+ fd = open("/dev/null", O_RDONLY);
275+ check(policy, fd == EOF);
276+ close(fd);
277+ unset2(policy);
278+
279+ policy = "string_group GROUP1 /dev/null\n"
280+ "100 acl read\n"
281+ "0 allow path!=@GROUP1\n"
282+ "1 deny\n";
283+ set(policy);
284+ fd = open("/dev/null", O_RDONLY);
285+ check(policy, fd == EOF);
286+ close(fd);
287+ unset2(policy);
288+
289+ policy = "string_group GROUP1 /dev/null\n"
290+ "100 acl read\n"
291+ "0 deny path!=@GROUP1\n"
292+ "1 allow\n";
293+ set(policy);
294+ fd = open("/dev/null", O_RDONLY);
295+ check(policy, fd != EOF);
296+ close(fd);
297+ unset2(policy);
298+
299+ policy = "string_group GROUP1 /dev/null\n"
300+ "number_group MAJOR 1\n"
301+ "number_group MINOR 3\n"
302+ "100 acl read\n"
303+ "0 allow path=@GROUP1 path.dev_major=@MAJOR"
304+ " path.dev_minor=@MINOR\n"
305+ "1 deny\n";
306+ set(policy);
307+ fd = open("/dev/null", O_RDONLY);
308+ check(policy, fd != EOF);
309+ close(fd);
310+ unset2(policy);
311+
312+ policy = "string_group GROUP1 /dev/null\n"
313+ "number_group MAJOR 1\n"
314+ "number_group MINOR 3\n"
315+ "100 acl read\n"
316+ "0 deny path=@GROUP1 path.dev_major=@MAJOR"
317+ " path.dev_minor=@MINOR\n"
318+ "1 allow\n";
319+ set(policy);
320+ fd = open("/dev/null", O_RDONLY);
321+ check(policy, fd == EOF);
322+ close(fd);
323+ unset2(policy);
324+
325+ policy = "string_group GROUP1 /dev/zero\n"
326+ "string_group GROUP1 /dev/null\n"
327+ "string_group GROUP1 /dev/urandom\n"
328+ "number_group MAJOR 0\n"
329+ "number_group MAJOR 2-255\n"
330+ "number_group MINOR 00-0x2\n"
331+ "number_group MINOR 255\n"
332+ "100 acl read\n"
333+ "0 allow path=@GROUP1 path.dev_major=@MAJOR"
334+ " path.dev_minor=@MINOR\n"
335+ "1 deny\n";
336+ set(policy);
337+ fd = open("/dev/null", O_RDONLY);
338+ check(policy, fd == EOF);
339+ close(fd);
340+ unset2(policy);
341+
342+ policy = "string_group GROUP1 /dev/zero\n"
343+ "string_group GROUP1 /dev/null\n"
344+ "string_group GROUP1 /dev/urandom\n"
345+ "number_group MAJOR 0\n"
346+ "number_group MAJOR 2-255\n"
347+ "number_group MINOR 00-0x2\n"
348+ "number_group MINOR 255\n"
349+ "100 acl read\n"
350+ "0 allow path=@GROUP1 path.dev_major!=@MAJOR"
351+ " path.dev_minor!=@MINOR\n"
352+ "1 deny\n";
353+ set(policy);
354+ fd = open("/dev/null", O_RDONLY);
355+ check(policy, fd != EOF);
356+ close(fd);
357+ unset2(policy);
358+}
359+
360+static void test_file_write(void)
361+{
362+ int fd;
363+ char *policy;
364+
365+ policy = "100 acl write\n"
366+ "0 allow\n"
367+ "100 acl append\n"
368+ "0 deny\n";
369+ set(policy);
370+ fd = open("/dev/null", O_WRONLY);
371+ check(policy, fd != EOF);
372+ close(fd);
373+ unset2(policy);
374+
375+ policy = "100 acl write\n"
376+ "0 deny\n"
377+ "100 acl append\n"
378+ "0 allow\n";
379+ set(policy);
380+ fd = open("/dev/null", O_WRONLY);
381+ check(policy, fd == EOF);
382+ close(fd);
383+ unset2(policy);
384+
385+ policy = "100 acl write\n"
386+ "0 allow\n"
387+ "100 acl append\n"
388+ "0 deny\n";
389+ set(policy);
390+ fd = open("/dev/null", O_WRONLY | O_APPEND);
391+ check(policy, fd == EOF);
392+ close(fd);
393+ unset2(policy);
394+
395+ policy = "100 acl write\n"
396+ "0 deny\n"
397+ "100 acl append\n"
398+ "0 append\n";
399+ set(policy);
400+ fd = open("/dev/null", O_WRONLY | O_APPEND);
401+ check(policy, fd != EOF);
402+ close(fd);
403+ unset2(policy);
404+
405+ policy = "100 acl write\n"
406+ "0 allow path.type=char path.dev_major=1 path.dev_minor=3\n"
407+ "1 deny\n";
408+ set(policy);
409+ fd = open("/dev/null", O_WRONLY | O_TRUNC);
410+ check(policy, fd != EOF);
411+ close(fd);
412+ unset(policy);
413+
414+ policy = "100 acl write\n"
415+ "0 allow path.type=char path.dev_major=1"
416+ " path.dev_minor=@MINOR\n"
417+ "1 deny\n";
418+ set(policy);
419+ fd = open("/dev/null", O_WRONLY | O_TRUNC);
420+ check(policy, fd == EOF);
421+ close(fd);
422+ unset(policy);
423+
424+ policy = "100 acl write\n"
425+ "0 allow path.parent.uid=0 path.parent.perm=0755\n"
426+ "1 deny\n";
427+ set(policy);
428+ fd = open("/dev/null", O_WRONLY);
429+ check(policy, fd != EOF);
430+ close(fd);
431+ unset(policy);
432+
433+ policy = "100 acl write\n"
434+ "0 allow path.parent.uid=task.uid path.parent.gid=task.gid\n"
435+ "1 deny\n";
436+ set(policy);
437+ fd = open("/dev/null", O_WRONLY);
438+ check(policy, fd != EOF);
439+ close(fd);
440+ unset(policy);
441+
442+ policy = "100 acl write\n"
443+ "0 allow task.uid=path.parent.uid task.gid=path.parent.gid\n"
444+ "1 deny\n";
445+ set(policy);
446+ fd = open("/dev/null", O_WRONLY);
447+ check(policy, fd != EOF);
448+ close(fd);
449+ unset(policy);
450+}
451+
452+static void test_file_create(void)
453+{
454+ int fd;
455+ char *policy;
456+
457+ policy = "100 acl create\n"
458+ "0 allow path.uid=0\n"
459+ "1 deny\n";
460+ set(policy);
461+ unlink("/tmp/file");
462+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
463+ check(policy, fd == EOF);
464+ close(fd);
465+ unset(policy);
466+
467+ policy = "100 acl create\n"
468+ "0 allow path=\"dev(\\$,\\$):/tmp/file\" path.parent.uid=0\n"
469+ "0 allow path=\"/tmp/file\" path.parent.uid=0\n"
470+ "0 allow path=\"dev(\\$,\\$):/file\" path.parent.uid=0\n"
471+ "1 deny\n";
472+ set(policy);
473+ unlink("/tmp/file");
474+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
475+ check(policy, fd != EOF);
476+ close(fd);
477+ unset(policy);
478+
479+ policy = "number_group GROUP1 1-0xFFFFFFFF\n"
480+ "100 acl create\n"
481+ "0 allow path.parent.uid!=@GROUP1 perm=0600\n"
482+ "1 deny\n";
483+ set(policy);
484+ unlink("/tmp/file");
485+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
486+ check(policy, fd != EOF);
487+ close(fd);
488+ unset2(policy);
489+
490+ policy = "number_group GROUP1 1-0xFFFFFFFF\n"
491+ "100 acl create\n"
492+ "0 allow path.parent.uid!=@GROUP1 perm!=0600\n"
493+ "1 deny\n";
494+ set(policy);
495+ unlink("/tmp/file");
496+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
497+ check(policy, fd == EOF);
498+ close(fd);
499+ unset2(policy);
500+
501+ policy = "100 acl create\n"
502+ "0 allow path.parent.uid=task.uid\n"
503+ "1 deny\n";
504+ set(policy);
505+ unlink("/tmp/file");
506+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
507+ check(policy, fd != EOF);
508+ close(fd);
509+ unset(policy);
510+}
511+
512+static void test_file_unlink(void)
513+{
514+ char *policy;
515+
516+ policy = "100 acl unlink\n"
517+ "0 allow path.uid=0 path.uid=path.parent.uid\n"
518+ "1 deny\n";
519+ set(policy);
520+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
521+ check(policy, unlink("/tmp/file") == 0);
522+ unset(policy);
523+
524+ policy = "100 acl unlink\n"
525+ "0 deny path.uid=0 path.uid=path.parent.uid\n"
526+ "1 allow\n";
527+ set(policy);
528+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
529+ check(policy, unlink("/tmp/file") == EOF);
530+ unset(policy);
531+}
532+
533+static void test_file_link(void)
534+{
535+ char *policy;
536+
537+ policy = "100 acl link\n"
538+ "0 allow old_path.uid=0 old_path.uid=old_path.parent.uid"
539+ " old_path.parent.ino=new_path.parent.ino\n"
540+ "1 deny\n";
541+ set(policy);
542+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
543+ unlink("/tmp/file2");
544+ check(policy, link("/tmp/file", "/tmp/file2") == 0);
545+ unset(policy);
546+
547+ policy = "100 acl link\n"
548+ "0 deny old_path.uid=0 old_path.uid=old_path.parent.uid\n"
549+ "1 allow\n";
550+ set(policy);
551+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
552+ unlink("/tmp/file2");
553+ check(policy, link("/tmp/file", "/tmp/file2") == EOF);
554+ unset(policy);
555+}
556+
557+static void test_file_rename(void)
558+{
559+ char *policy;
560+
561+ policy = "100 acl rename\n"
562+ "0 allow old_path.uid=0 old_path.uid=old_path.parent.uid"
563+ " old_path.parent.ino=new_path.parent.ino\n"
564+ "1 deny\n";
565+ set(policy);
566+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
567+ unlink("/tmp/file2");
568+ check(policy, rename("/tmp/file", "/tmp/file2") == 0);
569+ unset(policy);
570+
571+ policy = "100 acl rename\n"
572+ "0 deny old_path.uid=0 old_path.uid=old_path.parent.uid\n"
573+ "1 allow\n";
574+ set(policy);
575+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
576+ unlink("/tmp/file2");
577+ check(policy, rename("/tmp/file", "/tmp/file2") == EOF);
578+ unset(policy);
579+}
580+
581+static void test_network_inet_stream(void)
582+{
583+ struct sockaddr_in addr1 = { };
584+ struct sockaddr_in addr2 = { };
585+ socklen_t size = sizeof(addr1);
586+ int fd1;
587+ int fd2;
588+ int fd3;
589+ char *policy;
590+ char buffer[1024];
591+ memset(buffer, 0, sizeof(buffer));
592+
593+ fd1 = socket(PF_INET, SOCK_STREAM, 0);
594+ fd2 = socket(PF_INET, SOCK_STREAM, 0);
595+ addr1.sin_family = AF_INET;
596+ addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
597+
598+ policy = "100 acl inet_stream_bind\n"
599+ "0 allow ip=127.0.0.1 port!=0\n"
600+ "1 deny\n";
601+ set(policy);
602+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
603+ EOF);
604+ unset(policy);
605+
606+ policy = "100 acl inet_stream_bind\n"
607+ "0 allow ip!=127.0.0.1 port=0\n"
608+ "1 deny\n";
609+ set(policy);
610+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
611+ EOF);
612+ unset(policy);
613+
614+ policy = "100 acl inet_stream_bind\n"
615+ "0 allow ip=127.0.0.1 port=0 path.uid=task.uid\n"
616+ "1 deny\n";
617+ set(policy);
618+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
619+ EOF);
620+ unset(policy);
621+
622+ policy = "100 acl inet_stream_bind\n"
623+ "0 allow ip=127.0.0.1 port=0\n"
624+ "1 deny\n";
625+ set(policy);
626+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
627+ 0);
628+ unset(policy);
629+
630+ getsockname(fd1, (struct sockaddr *) &addr1, &size);
631+
632+ snprintf(buffer, sizeof(buffer) - 1,
633+ "100 acl inet_stream_listen\n"
634+ "0 allow ip=127.0.0.1 port!=%u\n"
635+ "1 deny\n", ntohs(addr1.sin_port));
636+ policy = buffer;
637+ set(policy);
638+ check(policy, listen(fd1, 5) == EOF);
639+ unset(policy);
640+
641+ snprintf(buffer, sizeof(buffer) - 1,
642+ "100 acl inet_stream_listen\n"
643+ "0 allow ip=127.0.0.1 port=%u\n"
644+ "1 deny\n", ntohs(addr1.sin_port));
645+ policy = buffer;
646+ set(policy);
647+ check(policy, listen(fd1, 5) == 0);
648+ unset(policy);
649+
650+ snprintf(buffer, sizeof(buffer) - 1,
651+ "100 acl inet_stream_connect\n"
652+ "0 allow ip=127.0.0.1 port!=%u\n"
653+ "1 deny\n", ntohs(addr1.sin_port));
654+ policy = buffer;
655+ set(policy);
656+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
657+ == EOF);
658+ unset(policy);
659+
660+ snprintf(buffer, sizeof(buffer) - 1,
661+ "100 acl inet_stream_connect\n"
662+ "0 allow ip=127.0.0.1 port=%u\n"
663+ "1 deny\n", ntohs(addr1.sin_port));
664+ policy = buffer;
665+ set(policy);
666+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
667+ == 0);
668+ unset(policy);
669+
670+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
671+
672+ snprintf(buffer, sizeof(buffer) - 1,
673+ "100 acl inet_stream_accept\n"
674+ "0 allow ip=127.0.0.1 port=%u\n"
675+ "1 deny\n", ntohs(addr2.sin_port));
676+ policy = buffer;
677+ set(policy);
678+ fd3 = accept(fd1, NULL, 0);
679+ check(policy, write(fd3, "", 1) == 1);
680+ close(fd3);
681+ unset(policy);
682+
683+ snprintf(buffer, sizeof(buffer) - 1,
684+ "100 acl inet_stream_connect\n"
685+ "0 allow ip=127.0.0.1 port=%u\n"
686+ "1 deny\n", ntohs(addr1.sin_port));
687+ policy = buffer;
688+ set(policy);
689+ close(fd2);
690+ fd2 = socket(PF_INET, SOCK_STREAM, 0);
691+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
692+ == 0);
693+ unset(policy);
694+
695+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
696+
697+ snprintf(buffer, sizeof(buffer) - 1,
698+ "100 acl inet_stream_accept\n"
699+ "0 allow ip=127.0.0.1 port!=%u\n"
700+ "1 deny\n", ntohs(addr2.sin_port));
701+ policy = buffer;
702+ set(policy);
703+ fd3 = accept(fd1, NULL, 0);
704+ check(policy, write(fd3, "", 1) == EOF);
705+ close(fd3);
706+ unset(policy);
707+
708+ close(fd1);
709+ close(fd2);
710+}
711+
712+static void test_network_inet_dgram(void)
713+{
714+ struct sockaddr_in addr1 = { };
715+ struct sockaddr_in addr2 = { };
716+ socklen_t size = sizeof(addr1);
717+ int fd1;
718+ int fd2;
719+ char *policy;
720+ char buffer[1024];
721+ memset(buffer, 0, sizeof(buffer));
722+
723+ fd1 = socket(PF_INET, SOCK_DGRAM, 0);
724+ fd2 = socket(PF_INET, SOCK_DGRAM, 0);
725+ addr1.sin_family = AF_INET;
726+ addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
727+
728+ policy = "100 acl inet_dgram_bind\n"
729+ "0 allow ip=127.0.0.1 port!=0\n"
730+ "1 deny\n";
731+ set(policy);
732+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
733+ EOF);
734+ unset(policy);
735+
736+ policy = "100 acl inet_dgram_bind\n"
737+ "0 allow ip!=127.0.0.1 port=0\n"
738+ "1 deny\n";
739+ set(policy);
740+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
741+ EOF);
742+ unset(policy);
743+
744+ policy = "100 acl inet_dgram_bind\n"
745+ "0 allow ip=127.0.0.1 port=0 path.uid=task.uid\n"
746+ "1 deny\n";
747+ set(policy);
748+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
749+ EOF);
750+ unset(policy);
751+
752+ policy = "100 acl inet_dgram_bind\n"
753+ "0 allow ip=127.0.0.1 port=0\n"
754+ "1 deny\n";
755+ set(policy);
756+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
757+ 0);
758+ unset(policy);
759+
760+ getsockname(fd1, (struct sockaddr *) &addr1, &size);
761+
762+ snprintf(buffer, sizeof(buffer) - 1,
763+ "100 acl inet_dgram_send\n"
764+ "0 allow ip=127.0.0.1 port!=%u\n"
765+ "1 deny\n", ntohs(addr1.sin_port));
766+ policy = buffer;
767+ set(policy);
768+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
769+ == EOF);
770+ unset(policy);
771+
772+ snprintf(buffer, sizeof(buffer) - 1,
773+ "100 acl inet_dgram_send\n"
774+ "0 allow ip=127.0.0.1 port=%u\n"
775+ "1 deny\n", ntohs(addr1.sin_port));
776+ policy = buffer;
777+ set(policy);
778+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
779+ == 0);
780+ unset(policy);
781+
782+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
783+
784+ snprintf(buffer, sizeof(buffer) - 1,
785+ "100 acl inet_dgram_send\n"
786+ "0 allow ip=127.0.0.1 port=%u\n"
787+ "1 deny\n", ntohs(addr1.sin_port));
788+ policy = buffer;
789+ set(policy);
790+ check(policy, send(fd2, "", 1, 0) != EOF);
791+ unset(policy);
792+
793+ snprintf(buffer, sizeof(buffer) - 1,
794+ "100 acl inet_dgram_send\n"
795+ "0 allow ip=127.0.0.1 port=%u\n"
796+ "1 deny\n", ntohs(addr1.sin_port));
797+ policy = buffer;
798+ set(policy);
799+ check(policy, send(fd2, "", 1, 0) != EOF);
800+ unset(policy);
801+
802+ snprintf(buffer, sizeof(buffer) - 1,
803+ "ip_group LOCALHOST 127.0.0.0-127.255.255.255\n"
804+ "100 acl inet_dgram_send\n"
805+ "0 allow ip=@LOCALHOST port=%u\n"
806+ "1 deny\n", ntohs(addr1.sin_port));
807+ policy = buffer;
808+ set(policy);
809+ check(policy, send(fd2, "", 1, 0) != EOF);
810+ unset2(policy);
811+
812+ close(fd1);
813+ close(fd2);
814+}
815+
816+static void test_network_inet_raw(void)
817+{
818+ struct sockaddr_in addr = { };
819+ struct iphdr ip = { };
820+ int fd1;
821+ int fd2;
822+ char *policy;
823+ fd1 = socket(PF_INET, SOCK_RAW, 1);
824+ fd2 = socket(PF_INET, SOCK_RAW, 1);
825+ addr.sin_family = AF_INET;
826+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
827+ ip.version = 4;
828+ ip.ihl = sizeof(struct iphdr) / 4;
829+ ip.protocol = IPPROTO_RAW;
830+ ip.daddr = htonl(INADDR_LOOPBACK);
831+ ip.saddr = ip.daddr;
832+
833+ policy = "100 acl inet_raw_bind\n"
834+ "0 allow ip=127.0.0.1 proto!=1\n"
835+ "1 deny\n";
836+ set(policy);
837+ check(policy, bind(fd1, (struct sockaddr *) &addr, sizeof(addr)) ==
838+ EOF);
839+ unset(policy);
840+
841+ policy = "100 acl inet_raw_bind\n"
842+ "0 allow ip!=127.0.0.1 proto=1\n"
843+ "1 deny\n";
844+ set(policy);
845+ check(policy, bind(fd1, (struct sockaddr *) &addr, sizeof(addr)) ==
846+ EOF);
847+ unset(policy);
848+
849+ policy = "100 acl inet_raw_bind\n"
850+ "0 allow ip=127.0.0.1 proto=1 path.uid=task.uid\n"
851+ "1 deny\n";
852+ set(policy);
853+ check(policy, bind(fd1, (struct sockaddr *) &addr, sizeof(addr)) ==
854+ EOF);
855+ unset(policy);
856+
857+ policy = "100 acl inet_raw_bind\n"
858+ "0 allow ip=127.0.0.1 proto=1\n"
859+ "1 deny\n";
860+ set(policy);
861+ check(policy, bind(fd2, (struct sockaddr *) &addr, sizeof(addr)) ==
862+ 0);
863+ unset(policy);
864+
865+ policy = "100 acl inet_raw_send\n"
866+ "0 allow ip=127.0.0.1 proto!=1\n"
867+ "1 deny\n";
868+ set(policy);
869+ check(policy, connect(fd2, (struct sockaddr *) &addr, sizeof(addr))
870+ == EOF);
871+ unset(policy);
872+
873+ policy = "100 acl inet_raw_send\n"
874+ "0 allow ip=127.0.0.1 proto=1\n"
875+ "1 deny\n";
876+ set(policy);
877+ check(policy, connect(fd2, (struct sockaddr *) &addr, sizeof(addr))
878+ == 0);
879+ unset(policy);
880+
881+ policy = "100 acl inet_raw_send\n"
882+ "0 allow ip=127.0.0.1 proto=1\n"
883+ "1 deny\n";
884+ set(policy);
885+ check(policy, send(fd2, &ip, sizeof(ip), 0) != EOF);
886+ unset(policy);
887+
888+ policy = "100 acl inet_raw_send\n"
889+ "0 allow ip=127.0.0.1 proto=1\n"
890+ "1 deny\n";
891+ set(policy);
892+ check(policy, send(fd2, &ip, sizeof(ip), 0) != EOF);
893+ unset(policy);
894+
895+ policy = "ip_group LOCALHOST 127.0.0.0-127.255.255.255\n"
896+ "100 acl inet_raw_send\n"
897+ "0 allow ip=@LOCALHOST proto=1\n"
898+ "1 deny\n";
899+ set(policy);
900+ check(policy, send(fd2, &ip, sizeof(ip), 0) != EOF);
901+ unset2(policy);
902+
903+ close(fd1);
904+ close(fd2);
905+}
906+
907+static void test_network_inet6_stream(void)
908+{
909+ struct sockaddr_in6 addr1 = { };
910+ struct sockaddr_in6 addr2 = { };
911+ socklen_t size = sizeof(addr1);
912+ int fd1;
913+ int fd2;
914+ int fd3;
915+ char *policy;
916+ char buffer[1024];
917+ memset(buffer, 0, sizeof(buffer));
918+
919+ fd1 = socket(PF_INET6, SOCK_STREAM, 0);
920+ if (fd1 == EOF && errno == EAFNOSUPPORT)
921+ return;
922+ fd2 = socket(PF_INET6, SOCK_STREAM, 0);
923+ addr1.sin6_family = AF_INET6;
924+ addr1.sin6_addr = in6addr_loopback;
925+
926+ policy = "100 acl inet_stream_bind\n"
927+ "0 allow ip=::1 port!=0\n"
928+ "1 deny\n";
929+ set(policy);
930+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
931+ EOF);
932+ unset(policy);
933+
934+ policy = "100 acl inet_stream_bind\n"
935+ "0 allow ip!=::1 port=0\n"
936+ "1 deny\n";
937+ set(policy);
938+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
939+ EOF);
940+ unset(policy);
941+
942+ policy = "100 acl inet_stream_bind\n"
943+ "0 allow ip=::1 port=0 path.uid=task.uid\n"
944+ "1 deny\n";
945+ set(policy);
946+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
947+ EOF);
948+ unset(policy);
949+
950+ policy = "100 acl inet_stream_bind\n"
951+ "0 allow ip=::1 port=0\n"
952+ "1 deny\n";
953+ set(policy);
954+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
955+ 0);
956+ unset(policy);
957+
958+ getsockname(fd1, (struct sockaddr *) &addr1, &size);
959+
960+ snprintf(buffer, sizeof(buffer) - 1,
961+ "100 acl inet_stream_listen\n"
962+ "0 allow ip=::1 port!=%u\n"
963+ "1 deny\n", ntohs(addr1.sin6_port));
964+ policy = buffer;
965+ set(policy);
966+ check(policy, listen(fd1, 5) == EOF);
967+ unset(policy);
968+
969+ snprintf(buffer, sizeof(buffer) - 1,
970+ "100 acl inet_stream_listen\n"
971+ "0 allow ip=::1 port=%u\n"
972+ "1 deny\n", ntohs(addr1.sin6_port));
973+ policy = buffer;
974+ set(policy);
975+ check(policy, listen(fd1, 5) == 0);
976+ unset(policy);
977+
978+ snprintf(buffer, sizeof(buffer) - 1,
979+ "100 acl inet_stream_connect\n"
980+ "0 allow ip=::1 port!=%u\n"
981+ "1 deny\n", ntohs(addr1.sin6_port));
982+ policy = buffer;
983+ set(policy);
984+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
985+ == EOF);
986+ unset(policy);
987+
988+ snprintf(buffer, sizeof(buffer) - 1,
989+ "100 acl inet_stream_connect\n"
990+ "0 allow ip=::1 port=%u\n"
991+ "1 deny\n", ntohs(addr1.sin6_port));
992+ policy = buffer;
993+ set(policy);
994+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
995+ == 0);
996+ unset(policy);
997+
998+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
999+
1000+ snprintf(buffer, sizeof(buffer) - 1,
1001+ "100 acl inet_stream_accept\n"
1002+ "0 allow ip=::1 port=%u\n"
1003+ "1 deny\n", ntohs(addr2.sin6_port));
1004+ policy = buffer;
1005+ set(policy);
1006+ fd3 = accept(fd1, NULL, 0);
1007+ check(policy, write(fd3, "", 1) == 1);
1008+ close(fd3);
1009+ unset(policy);
1010+
1011+ snprintf(buffer, sizeof(buffer) - 1,
1012+ "100 acl inet_stream_connect\n"
1013+ "0 allow ip=::1 port=%u\n"
1014+ "1 deny\n", ntohs(addr1.sin6_port));
1015+ policy = buffer;
1016+ set(policy);
1017+ close(fd2);
1018+ fd2 = socket(PF_INET6, SOCK_STREAM, 0);
1019+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
1020+ == 0);
1021+ unset(policy);
1022+
1023+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
1024+
1025+ snprintf(buffer, sizeof(buffer) - 1,
1026+ "100 acl inet_stream_accept\n"
1027+ "0 allow ip=::1 port!=%u\n"
1028+ "1 deny\n", ntohs(addr2.sin6_port));
1029+ policy = buffer;
1030+ set(policy);
1031+ fd3 = accept(fd1, NULL, 0);
1032+ check(policy, write(fd3, "", 1) == EOF);
1033+ close(fd3);
1034+ unset(policy);
1035+
1036+ close(fd1);
1037+ close(fd2);
1038+}
1039+
1040+static void test_network_inet6_dgram(void)
1041+{
1042+ struct sockaddr_in6 addr1 = { };
1043+ struct sockaddr_in6 addr2 = { };
1044+ socklen_t size = sizeof(addr1);
1045+ int fd1;
1046+ int fd2;
1047+ char *policy;
1048+ char buffer[1024];
1049+ memset(buffer, 0, sizeof(buffer));
1050+
1051+ fd1 = socket(PF_INET6, SOCK_DGRAM, 0);
1052+ if (fd1 == EOF && errno == EAFNOSUPPORT)
1053+ return;
1054+ fd2 = socket(PF_INET6, SOCK_DGRAM, 0);
1055+ addr1.sin6_family = AF_INET6;
1056+ addr1.sin6_addr = in6addr_loopback;
1057+
1058+ policy = "100 acl inet_dgram_bind\n"
1059+ "0 allow ip=::1 port!=0\n"
1060+ "1 deny\n";
1061+ set(policy);
1062+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
1063+ EOF);
1064+ unset(policy);
1065+
1066+ policy = "100 acl inet_dgram_bind\n"
1067+ "0 allow ip!=::1 port=0\n"
1068+ "1 deny\n";
1069+ set(policy);
1070+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
1071+ EOF);
1072+ unset(policy);
1073+
1074+ policy = "100 acl inet_dgram_bind\n"
1075+ "0 allow ip=::1 port=0 path.uid=task.uid\n"
1076+ "1 deny\n";
1077+ set(policy);
1078+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
1079+ EOF);
1080+ unset(policy);
1081+
1082+ policy = "100 acl inet_dgram_bind\n"
1083+ "0 allow ip=::1 port=0\n"
1084+ "1 deny\n";
1085+ set(policy);
1086+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
1087+ 0);
1088+ unset(policy);
1089+
1090+ getsockname(fd1, (struct sockaddr *) &addr1, &size);
1091+
1092+ snprintf(buffer, sizeof(buffer) - 1,
1093+ "100 acl inet_dgram_send\n"
1094+ "0 allow ip=::1 port!=%u\n"
1095+ "1 deny\n", ntohs(addr1.sin6_port));
1096+ policy = buffer;
1097+ set(policy);
1098+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
1099+ == EOF);
1100+ unset(policy);
1101+
1102+ snprintf(buffer, sizeof(buffer) - 1,
1103+ "100 acl inet_dgram_send\n"
1104+ "0 allow ip=::1 port=%u\n"
1105+ "1 deny\n", ntohs(addr1.sin6_port));
1106+ policy = buffer;
1107+ set(policy);
1108+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
1109+ == 0);
1110+ unset(policy);
1111+
1112+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
1113+
1114+ snprintf(buffer, sizeof(buffer) - 1,
1115+ "100 acl inet_dgram_send\n"
1116+ "0 allow ip=::1 port=%u\n"
1117+ "1 deny\n", ntohs(addr1.sin6_port));
1118+ policy = buffer;
1119+ set(policy);
1120+ check(policy, send(fd2, "", 1, 0) != EOF);
1121+ unset(policy);
1122+
1123+ snprintf(buffer, sizeof(buffer) - 1,
1124+ "100 acl inet_dgram_send\n"
1125+ "0 allow ip=::1 port=%u\n"
1126+ "1 deny\n", ntohs(addr1.sin6_port));
1127+ policy = buffer;
1128+ set(policy);
1129+ check(policy, send(fd2, "", 1, 0) != EOF);
1130+ unset(policy);
1131+
1132+ snprintf(buffer, sizeof(buffer) - 1,
1133+ "ip_group LOCALHOST ::-::ffff\n"
1134+ "100 acl inet_dgram_send\n"
1135+ "0 allow ip=@LOCALHOST port=%u\n"
1136+ "1 deny\n", ntohs(addr1.sin6_port));
1137+ policy = buffer;
1138+ set(policy);
1139+ check(policy, send(fd2, "", 1, 0) != EOF);
1140+ unset2(policy);
1141+
1142+ close(fd1);
1143+ close(fd2);
1144+}
1145+
1146+static int fork_exec(char *envp[])
1147+{
1148+ int ret_ignored;
1149+ int pipe_fd[2] = { EOF, EOF };
1150+ int err = 0;
1151+ pid_t pid;
1152+ if (pipe(pipe_fd)) {
1153+ fprintf(stderr, "Err: %s(%d)\n", strerror(err), err);
1154+ exit(1);
1155+ }
1156+ pid = fork();
1157+ if (pid == 0) {
1158+ char *argv[2] = { BINDIR "/true", NULL };
1159+ execve(BINDIR "/true", argv, envp);
1160+ err = errno;
1161+ ret_ignored = write(pipe_fd[1], &err, sizeof(err));
1162+ _exit(0);
1163+ }
1164+ close(pipe_fd[1]);
1165+ ret_ignored = read(pipe_fd[0], &err, sizeof(err));
1166+ close(pipe_fd[0]);
1167+ wait(NULL);
1168+ errno = err;
1169+ return err ? EOF : 0;
1170+}
1171+
1172+static void test_environ(void)
1173+{
1174+ char *policy;
1175+ char *envp[2];
1176+ envp[1] = NULL;
1177+
1178+ policy = "100 acl environ name=\"PATH2\"\n"
1179+ "0 allow value=\"/\"\n"
1180+ "1 deny\n";
1181+ set(policy);
1182+ envp[0] = "PATH2=/";
1183+ check(policy, fork_exec(envp) == 0);
1184+ unset(policy);
1185+
1186+ policy = "100 acl environ name=\"PATH2\"\n"
1187+ "0 allow value!=\"/\"\n"
1188+ "1 deny\n";
1189+ set(policy);
1190+ envp[0] = "PATH2=/";
1191+ check(policy, fork_exec(envp) == EOF);
1192+ unset(policy);
1193+
1194+ policy = "100 acl environ name=\"PATH2\"\n"
1195+ "0 deny value!=\"/\"\n"
1196+ "1 allow\n";
1197+ set(policy);
1198+ envp[0] = "PATH2=/";
1199+ check(policy, fork_exec(envp) == 0);
1200+ unset(policy);
1201+
1202+ policy = "100 acl environ name=\"PATH2\"\n"
1203+ "0 deny value=\"/\"\n"
1204+ "1 allow\n";
1205+ set(policy);
1206+ envp[0] = "PATH2=/";
1207+ check(policy, fork_exec(envp) == EOF);
1208+ unset(policy);
1209+
1210+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1211+ "0 allow envp[\"PATH2\"]=\"/\"\n"
1212+ "1 deny\n";
1213+ set(policy);
1214+ envp[0] = "PATH2=/";
1215+ check(policy, fork_exec(envp) == 0);
1216+ unset(policy);
1217+
1218+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1219+ "0 allow envp[\"PATH2\"]!=\"/\"\n"
1220+ "1 deny\n";
1221+ set(policy);
1222+ envp[0] = "PATH2=/";
1223+ check(policy, fork_exec(envp) == EOF);
1224+ unset(policy);
1225+
1226+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1227+ "0 allow envp[\"PATH2\"]!=NULL\n"
1228+ "1 deny\n";
1229+ set(policy);
1230+ envp[0] = "PATH2";
1231+ check(policy, fork_exec(envp) == 0);
1232+ unset(policy);
1233+
1234+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1235+ "0 allow envp[\"PATH2\"]!=NULL\n"
1236+ "1 deny\n";
1237+ set(policy);
1238+ envp[0] = "PATH2=";
1239+ check(policy, fork_exec(envp) == 0);
1240+ unset(policy);
1241+
1242+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1243+ "0 allow envp[\"PATH2\"]!=NULL\n"
1244+ "1 deny\n";
1245+ set(policy);
1246+ envp[0] = "PATH2=/";
1247+ check(policy, fork_exec(envp) == 0);
1248+ unset(policy);
1249+
1250+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1251+ "0 allow envp[\"PATH2\"]=NULL\n"
1252+ "1 deny\n";
1253+ set(policy);
1254+ envp[0] = "PATH2";
1255+ check(policy, fork_exec(envp) == EOF);
1256+ unset(policy);
1257+
1258+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1259+ "0 allow envp[\"PATH2\"]=NULL\n"
1260+ "1 deny\n";
1261+ set(policy);
1262+ envp[0] = "PATH2=";
1263+ check(policy, fork_exec(envp) == EOF);
1264+ unset(policy);
1265+
1266+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1267+ "0 allow envp[\"PATH2\"]=NULL\n"
1268+ "1 deny\n";
1269+ set(policy);
1270+ envp[0] = "PATH2=/";
1271+ check(policy, fork_exec(envp) == EOF);
1272+ unset(policy);
1273+
1274+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1275+ "0 allow envp[\"\"]=NULL\n"
1276+ "1 deny\n";
1277+ set(policy);
1278+ envp[0] = "";
1279+ check(policy, fork_exec(envp) == EOF);
1280+ unset(policy);
1281+
1282+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1283+ "0 allow envp[\"\"]!=NULL\n"
1284+ "1 deny\n";
1285+ set(policy);
1286+ envp[0] = "";
1287+ check(policy, fork_exec(envp) == 0);
1288+ unset(policy);
1289+
1290+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1291+ "0 allow envp[\"\"]!=NULL\n"
1292+ "1 deny\n";
1293+ set(policy);
1294+ envp[0] = "=";
1295+ check(policy, fork_exec(envp) == 0);
1296+ unset(policy);
1297+
1298+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1299+ "0 allow envp[\"\"]!=NULL\n"
1300+ "1 deny\n";
1301+ set(policy);
1302+ envp[0] = "=/";
1303+ check(policy, fork_exec(envp) == 0);
1304+ unset(policy);
1305+}
1306+
1307+static int fork_exec2(char *argv[], char *envp[])
1308+{
1309+ int ret_ignored;
1310+ int pipe_fd[2] = { EOF, EOF };
1311+ int err = 0;
1312+ pid_t pid;
1313+ if (pipe(pipe_fd)) {
1314+ fprintf(stderr, "Err: %s(%d)\n", strerror(err), err);
1315+ exit(1);
1316+ }
1317+ pid = fork();
1318+ if (pid == 0) {
1319+ execve(BINDIR "/true", argv, envp);
1320+ err = errno;
1321+ ret_ignored = write(pipe_fd[1], &err, sizeof(err));
1322+ _exit(0);
1323+ }
1324+ close(pipe_fd[1]);
1325+ ret_ignored = read(pipe_fd[0], &err, sizeof(err));
1326+ close(pipe_fd[0]);
1327+ wait(NULL);
1328+ errno = err;
1329+ return err ? EOF : 0;
1330+}
1331+
1332+static void test_file_execute(void)
1333+{
1334+ char *policy;
1335+ char *argv[5];
1336+ char *envp[5];
1337+ memset(argv, 0, sizeof(argv));
1338+ memset(envp, 0, sizeof(envp));
1339+
1340+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1341+ "0 allow argc=1\n"
1342+ "1 deny\n";
1343+ set(policy);
1344+ argv[0]="true";
1345+ check(policy, fork_exec2(argv, envp) == 0);
1346+ unset(policy);
1347+
1348+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1349+ "0 allow argc!=1\n"
1350+ "1 deny\n";
1351+ set(policy);
1352+ check(policy, fork_exec2(argv, envp) == EOF);
1353+ unset(policy);
1354+
1355+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1356+ "0 deny argc!=1\n"
1357+ "1 allow\n";
1358+ set(policy);
1359+ check(policy, fork_exec2(argv, envp) == 0);
1360+ unset(policy);
1361+
1362+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1363+ "0 deny argc=1\n"
1364+ "1 allow\n";
1365+ set(policy);
1366+ check(policy, fork_exec2(argv, envp) == EOF);
1367+ unset(policy);
1368+
1369+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1370+ "0 deny argv[0]!=\"true\"\n"
1371+ "1 allow\n";
1372+ set(policy);
1373+ check(policy, fork_exec2(argv, envp) == 0);
1374+ unset(policy);
1375+
1376+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1377+ "0 deny argv[0]=\"true\"\n"
1378+ "1 allow\n";
1379+ set(policy);
1380+ check(policy, fork_exec2(argv, envp) == EOF);
1381+ unset(policy);
1382+
1383+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1384+ "0 allow argv[0]!=\"true\"\n"
1385+ "1 deny\n";
1386+ set(policy);
1387+ check(policy, fork_exec2(argv, envp) == EOF);
1388+ unset(policy);
1389+
1390+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1391+ "0 allow argv[0]=\"true\"\n"
1392+ "1 deny\n";
1393+ set(policy);
1394+ check(policy, fork_exec2(argv, envp) == 0);
1395+ unset(policy);
1396+
1397+ policy = "string_group EXEC_ARGV0 false\n"
1398+ "string_group EXEC_ARGV0 true\n"
1399+ "100 acl execute path=\"" BINDIR "/true\"\n"
1400+ "0 deny argv[0]!=@EXEC_ARGV0\n"
1401+ "1 allow\n";
1402+ set(policy);
1403+ check(policy, fork_exec2(argv, envp) == 0);
1404+ unset2(policy);
1405+
1406+ policy = "string_group EXEC_ARGV0 false\n"
1407+ "string_group EXEC_ARGV0 true\n"
1408+ "100 acl execute path=\"" BINDIR "/true\"\n"
1409+ "0 deny argv[0]=@EXEC_ARGV0\n"
1410+ "1 allow\n";
1411+ set(policy);
1412+ check(policy, fork_exec2(argv, envp) == EOF);
1413+ unset2(policy);
1414+
1415+ policy = "string_group EXEC_ARGV0 false\n"
1416+ "string_group EXEC_ARGV0 true\n"
1417+ "100 acl execute path=\"" BINDIR "/true\"\n"
1418+ "0 allow argv[0]!=@EXEC_ARGV0\n"
1419+ "1 deny\n";
1420+ set(policy);
1421+ check(policy, fork_exec2(argv, envp) == EOF);
1422+ unset2(policy);
1423+
1424+ policy = "string_group EXEC_ARGV0 false\n"
1425+ "string_group EXEC_ARGV0 true\n"
1426+ "100 acl execute path=\"" BINDIR "/true\"\n"
1427+ "0 allow argv[0]=@EXEC_ARGV0\n"
1428+ "1 deny\n";
1429+ set(policy);
1430+ check(policy, fork_exec2(argv, envp) == 0);
1431+ unset2(policy);
1432+
1433+
1434+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1435+ "0 allow envc=1\n"
1436+ "1 deny\n";
1437+ set(policy);
1438+ envp[0]="PATH=/";
1439+ check(policy, fork_exec2(argv, envp) == 0);
1440+ unset(policy);
1441+
1442+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1443+ "0 allow envc!=1\n"
1444+ "1 deny\n";
1445+ set(policy);
1446+ check(policy, fork_exec2(argv, envp) == EOF);
1447+ unset(policy);
1448+
1449+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1450+ "0 deny envc!=1\n"
1451+ "1 allow\n";
1452+ set(policy);
1453+ check(policy, fork_exec2(argv, envp) == 0);
1454+ unset(policy);
1455+
1456+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1457+ "0 deny envc=1\n"
1458+ "1 allow\n";
1459+ set(policy);
1460+ check(policy, fork_exec2(argv, envp) == EOF);
1461+ unset(policy);
1462+
1463+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1464+ "0 deny envp[\"PATH\"]!=\"/\"\n"
1465+ "1 allow\n";
1466+ set(policy);
1467+ check(policy, fork_exec2(argv, envp) == 0);
1468+ unset(policy);
1469+
1470+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1471+ "0 deny envp[\"PATH\"]=\"/\"\n"
1472+ "1 allow\n";
1473+ set(policy);
1474+ check(policy, fork_exec2(argv, envp) == EOF);
1475+ unset(policy);
1476+
1477+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1478+ "0 allow envp[\"PATH\"]!=\"/\"\n"
1479+ "1 deny\n";
1480+ set(policy);
1481+ check(policy, fork_exec2(argv, envp) == EOF);
1482+ unset(policy);
1483+
1484+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1485+ "0 allow envp[\"PATH\"]=\"/\"\n"
1486+ "1 deny\n";
1487+ set(policy);
1488+ check(policy, fork_exec2(argv, envp) == 0);
1489+ unset(policy);
1490+
1491+ policy = "string_group PATH_VALUES " BINDIR "\n"
1492+ "string_group PATH_VALUES /\n"
1493+ "string_group PATH_VALUES /sbin\n"
1494+ "100 acl execute path=\"" BINDIR "/true\"\n"
1495+ "0 deny envp[\"PATH\"]!=@PATH_VALUES\n"
1496+ "1 allow\n";
1497+ set(policy);
1498+ check(policy, fork_exec2(argv, envp) == 0);
1499+ unset2(policy);
1500+
1501+ policy = "string_group PATH_VALUES " BINDIR "\n"
1502+ "string_group PATH_VALUES /\n"
1503+ "string_group PATH_VALUES /sbin\n"
1504+ "100 acl execute path=\"" BINDIR "/true\"\n"
1505+ "0 deny envp[\"PATH\"]=@PATH_VALUES\n"
1506+ "1 allow\n";
1507+ set(policy);
1508+ check(policy, fork_exec2(argv, envp) == EOF);
1509+ unset2(policy);
1510+
1511+ policy = "string_group PATH_VALUES " BINDIR "\n"
1512+ "string_group PATH_VALUES /\n"
1513+ "string_group PATH_VALUES /sbin\n"
1514+ "100 acl execute path=\"" BINDIR "/true\"\n"
1515+ "0 allow envp[\"PATH\"]!=@PATH_VALUES\n"
1516+ "1 deny\n";
1517+ set(policy);
1518+ check(policy, fork_exec2(argv, envp) == EOF);
1519+ unset2(policy);
1520+
1521+ policy = "string_group PATH_VALUES " BINDIR "\n"
1522+ "string_group PATH_VALUES /\n"
1523+ "string_group PATH_VALUES /sbin\n"
1524+ "100 acl execute path=\"" BINDIR "/true\"\n"
1525+ "0 allow envp[\"PATH\"]=@PATH_VALUES\n"
1526+ "1 deny\n";
1527+ set(policy);
1528+ check(policy, fork_exec2(argv, envp) == 0);
1529+ unset2(policy);
1530+
1531+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1532+ "0 deny envp[\"PATH\"]!=NULL\n"
1533+ "1 allow\n";
1534+ set(policy);
1535+ check(policy, fork_exec2(argv, envp) == EOF);
1536+ unset(policy);
1537+
1538+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1539+ "0 deny envp[\"PATH\"]=NULL\n"
1540+ "1 allow\n";
1541+ set(policy);
1542+ check(policy, fork_exec2(argv, envp) == 0);
1543+ unset(policy);
1544+
1545+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1546+ "0 allow envp[\"PATH\"]!=NULL\n"
1547+ "1 deny\n";
1548+ set(policy);
1549+ check(policy, fork_exec2(argv, envp) == 0);
1550+ unset(policy);
1551+
1552+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1553+ "0 allow envp[\"PATH\"]=NULL\n"
1554+ "1 deny\n";
1555+ set(policy);
1556+ check(policy, fork_exec2(argv, envp) == EOF);
1557+ unset(policy);
1558+}
1559+
1560+static void test_file_misc(void)
1561+{
1562+ int fd;
1563+ const pid_t pid = getpid();
1564+ char buffer[1024];
1565+ memset(buffer, 0, sizeof(buffer));
1566+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1567+ "10 allow path!=NULL\n"
1568+ "20 deny\n", pid);
1569+ set(buffer);
1570+ fd = open("/dev/null", O_RDONLY);
1571+ check(buffer, fd != EOF);
1572+ close(fd);
1573+ unset(buffer);
1574+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1575+ "10 allow path=NULL\n"
1576+ "20 deny\n", pid);
1577+ set(buffer);
1578+ fd = open("/dev/null", O_RDONLY);
1579+ check(buffer, fd == EOF);
1580+ close(fd);
1581+ unset(buffer);
1582+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1583+ "10 deny path=NULL\n"
1584+ "20 allow\n", pid);
1585+ set(buffer);
1586+ fd = open("/dev/null", O_RDONLY);
1587+ check(buffer, fd != EOF);
1588+ close(fd);
1589+ unset(buffer);
1590+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1591+ "10 deny path!=NULL\n"
1592+ "20 allow\n", pid);
1593+ set(buffer);
1594+ fd = open("/dev/null", O_RDONLY);
1595+ check(buffer, fd == EOF);
1596+ close(fd);
1597+ unset(buffer);
1598+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1599+ "10 allow path=path\n"
1600+ "20 deny\n", pid);
1601+ set(buffer);
1602+ fd = open("/dev/null", O_RDONLY);
1603+ check(buffer, fd != EOF);
1604+ close(fd);
1605+ unset(buffer);
1606+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1607+ "10 allow path!=path\n"
1608+ "20 deny\n", pid);
1609+ set(buffer);
1610+ fd = open("/dev/null", O_RDONLY);
1611+ check(buffer, fd == EOF);
1612+ close(fd);
1613+ unset(buffer);
1614+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1615+ "10 deny path!=path\n"
1616+ "20 allow\n", pid);
1617+ set(buffer);
1618+ fd = open("/dev/null", O_RDONLY);
1619+ check(buffer, fd != EOF);
1620+ close(fd);
1621+ unset(buffer);
1622+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1623+ "10 deny path=path\n"
1624+ "20 allow\n", pid);
1625+ set(buffer);
1626+ fd = open("/dev/null", O_RDONLY);
1627+ check(buffer, fd == EOF);
1628+ close(fd);
1629+ unset(buffer);
1630+ snprintf(buffer, sizeof(buffer) - 1,
1631+ "string_group STRING_GROUP1 /dev/null\n"
1632+ "100 acl read task.pid=%u\n"
1633+ "10 allow path=@STRING_GROUP1\n"
1634+ "20 deny\n", pid);
1635+ set(buffer);
1636+ fd = open("/dev/null", O_RDONLY);
1637+ check(buffer, fd != EOF);
1638+ close(fd);
1639+ unset2(buffer);
1640+ snprintf(buffer, sizeof(buffer) - 1,
1641+ "string_group STRING_GROUP1 /dev/null\n"
1642+ "100 acl read task.pid=%u\n"
1643+ "10 allow path!=@STRING_GROUP1\n"
1644+ "20 deny\n", pid);
1645+ set(buffer);
1646+ fd = open("/dev/null", O_RDONLY);
1647+ check(buffer, fd == EOF);
1648+ close(fd);
1649+ unset2(buffer);
1650+ snprintf(buffer, sizeof(buffer) - 1,
1651+ "string_group STRING_GROUP1 /dev/null\n"
1652+ "100 acl read task.pid=%u\n"
1653+ "10 deny path!=@STRING_GROUP1\n"
1654+ "20 allow\n", pid);
1655+ set(buffer);
1656+ fd = open("/dev/null", O_RDONLY);
1657+ check(buffer, fd != EOF);
1658+ close(fd);
1659+ unset2(buffer);
1660+ snprintf(buffer, sizeof(buffer) - 1,
1661+ "string_group STRING_GROUP1 /dev/null\n"
1662+ "100 acl read task.pid=%u\n"
1663+ "10 deny path=@STRING_GROUP1\n"
1664+ "20 allow\n", pid);
1665+ set(buffer);
1666+ fd = open("/dev/null", O_RDONLY);
1667+ check(buffer, fd == EOF);
1668+ close(fd);
1669+ unset2(buffer);
1670+ snprintf(buffer, sizeof(buffer) - 1,
1671+ "number_group NUMBER_GROUP1 0666\n"
1672+ "100 acl read task.pid=%u\n"
1673+ "10 deny path.perm!=@NUMBER_GROUP1\n"
1674+ "20 allow\n", pid);
1675+ set(buffer);
1676+ fd = open("/dev/null", O_RDONLY);
1677+ check(buffer, fd != EOF);
1678+ close(fd);
1679+ unset2(buffer);
1680+ snprintf(buffer, sizeof(buffer) - 1,
1681+ "number_group NUMBER_GROUP1 0666\n"
1682+ "100 acl read task.pid=%u\n"
1683+ "10 deny path.perm=@NUMBER_GROUP1\n"
1684+ "20 allow\n", pid);
1685+ set(buffer);
1686+ fd = open("/dev/null", O_RDONLY);
1687+ check(buffer, fd == EOF);
1688+ close(fd);
1689+ unset2(buffer);
1690+ snprintf(buffer, sizeof(buffer) - 1,
1691+ "100 acl read task.pid=%u\n"
1692+ "10 deny path.perm!=owner_read\n"
1693+ "20 allow\n", pid);
1694+ set(buffer);
1695+ fd = open("/dev/null", O_RDONLY);
1696+ check(buffer, fd != EOF);
1697+ close(fd);
1698+ unset2(buffer);
1699+ snprintf(buffer, sizeof(buffer) - 1,
1700+ "100 acl read task.pid=%u\n"
1701+ "10 deny path.perm=owner_read\n"
1702+ "20 allow\n", pid);
1703+ set(buffer);
1704+ fd = open("/dev/null", O_RDONLY);
1705+ check(buffer, fd == EOF);
1706+ close(fd);
1707+ unset2(buffer);
1708+ snprintf(buffer, sizeof(buffer) - 1,
1709+ "100 acl read task.pid=%u\n"
1710+ "10 deny path.perm!=group_write\n"
1711+ "20 allow\n", pid);
1712+ set(buffer);
1713+ fd = open("/dev/null", O_RDONLY);
1714+ check(buffer, fd != EOF);
1715+ close(fd);
1716+ unset2(buffer);
1717+ snprintf(buffer, sizeof(buffer) - 1,
1718+ "100 acl read task.pid=%u\n"
1719+ "10 deny path.perm=group_write\n"
1720+ "20 allow\n", pid);
1721+ set(buffer);
1722+ fd = open("/dev/null", O_RDONLY);
1723+ check(buffer, fd == EOF);
1724+ close(fd);
1725+ unset2(buffer);
1726+ snprintf(buffer, sizeof(buffer) - 1,
1727+ "100 acl read task.pid=%u\n"
1728+ "10 deny path.perm!=others_read\n"
1729+ "20 allow\n", pid);
1730+ set(buffer);
1731+ fd = open("/dev/null", O_RDONLY);
1732+ check(buffer, fd != EOF);
1733+ close(fd);
1734+ unset2(buffer);
1735+ snprintf(buffer, sizeof(buffer) - 1,
1736+ "100 acl read task.pid=%u\n"
1737+ "10 deny path.perm=others_read\n"
1738+ "20 allow\n", pid);
1739+ set(buffer);
1740+ fd = open("/dev/null", O_RDONLY);
1741+ check(buffer, fd == EOF);
1742+ close(fd);
1743+ unset2(buffer);
1744+ snprintf(buffer, sizeof(buffer) - 1,
1745+ "100 acl read task.pid=%u\n"
1746+ "10 deny path.perm=path.parent.perm\n"
1747+ "20 allow\n", pid);
1748+ set(buffer);
1749+ fd = open("/dev/null", O_RDONLY);
1750+ check(buffer, fd != EOF);
1751+ close(fd);
1752+ unset2(buffer);
1753+ snprintf(buffer, sizeof(buffer) - 1,
1754+ "100 acl read task.pid=%u\n"
1755+ "10 deny path.perm!=path.parent.perm\n"
1756+ "20 allow\n", pid);
1757+ set(buffer);
1758+ fd = open("/dev/null", O_RDONLY);
1759+ check(buffer, fd == EOF);
1760+ close(fd);
1761+ unset2(buffer);
1762+ snprintf(buffer, sizeof(buffer) - 1,
1763+ "100 acl execute task.ppid=%u\n"
1764+ "10 allow path=exec\n"
1765+ "20 deny\n", pid);
1766+ set(buffer);
1767+ check(buffer, fork_exec(NULL) == 0);
1768+ unset(buffer);
1769+ snprintf(buffer, sizeof(buffer) - 1,
1770+ "100 acl execute task.ppid=%u\n"
1771+ "10 allow path!=exec\n"
1772+ "20 deny\n", pid);
1773+ set(buffer);
1774+ check(buffer, fork_exec(NULL) == EOF);
1775+ unset(buffer);
1776+ snprintf(buffer, sizeof(buffer) - 1,
1777+ "100 acl execute task.ppid=%u\n"
1778+ "10 deny path=exec\n"
1779+ "20 allow\n", pid);
1780+ set(buffer);
1781+ check(buffer, fork_exec(NULL) == EOF);
1782+ unset(buffer);
1783+ snprintf(buffer, sizeof(buffer) - 1,
1784+ "100 acl execute task.ppid=%u\n"
1785+ "10 deny path!=exec\n"
1786+ "20 allow\n", pid);
1787+ set(buffer);
1788+ check(buffer, fork_exec(NULL) == 0);
1789+ unset(buffer);
1790+}
1791+
1792+static void reset_policy(void)
1793+{
1794+ FILE *fp2 = fopen(POLDIR "/policy", "r");
1795+ FILE *fp1 = fopen(POLDIR "/policy", "w");
1796+ if (!fp1 || !fp2) {
1797+ fprintf(stderr, " Can't open " POLDIR "/policy\n");
1798+ exit(1);
1799+ }
1800+ while (1) {
1801+ const int c = fgetc(fp2);
1802+ if (c == EOF)
1803+ break;
1804+ fputc(c, fp1);
1805+ if (c == '\n')
1806+ fprintf(fp1, "delete ");
1807+ }
1808+ fclose(fp2);
1809+ fclose(fp1);
1810+
1811+ /* Do not leave the init process in stopped state. */
1812+ kill(1, SIGCONT);
1813+
1814+ /* Undo mount("/", MS_REC|MS_SHARED) made by systemd. */
1815+ mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL);
1816+}
1817+
1818+int main(int argc, char *argv[])
1819+{
1820+ reset_policy();
1821+
1822+ fp = fopen(POLDIR "/policy", "w");
1823+ if (!fp) {
1824+ fprintf(stderr, " Can't open " POLDIR "/policy\n");
1825+ return 1;
1826+ }
1827+ fprintf(fp, "quota audit[0]"
1828+ " allowed=1024 unmatched=1024 denied=1024\n");
1829+ fflush(fp);
1830+
1831+ test_task_transition();
1832+ test_file_read();
1833+ test_file_write();
1834+ test_file_create();
1835+ test_file_unlink();
1836+ test_file_link();
1837+ test_file_rename();
1838+ test_network_inet_stream();
1839+ test_network_inet_dgram();
1840+ test_network_inet_raw();
1841+ test_network_inet6_stream();
1842+ test_network_inet6_dgram();
1843+ test_environ();
1844+ test_file_execute();
1845+ test_file_misc();
1846+ return 0;
1847+}
--- tags/caitsith-tools/0.2.2/kernel_test/caitsith_param_test.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/kernel_test/caitsith_param_test.c (revision 242)
@@ -0,0 +1,2044 @@
1+#include <stdio.h>
2+#include <stdlib.h>
3+#include <string.h>
4+#include <unistd.h>
5+#include <sys/types.h>
6+#include <sys/stat.h>
7+#include <sys/socket.h>
8+#include <netinet/in.h>
9+#include <sys/ptrace.h>
10+#include <sys/wait.h>
11+#include <linux/ip.h>
12+#include <fcntl.h>
13+#include <errno.h>
14+#include <sys/mount.h>
15+#ifndef MS_REC
16+#define MS_REC 16384
17+#endif
18+#ifndef MS_PRIVATE
19+#define MS_PRIVATE (1 << 18)
20+#endif
21+
22+static FILE *fp = NULL;
23+
24+static void set(const char *str)
25+{
26+ fprintf(fp, "%s\n", str);
27+ fflush(fp);
28+ errno = 0;
29+}
30+
31+static void unset(const char *str)
32+{
33+ fprintf(fp, "delete %s\n", str);
34+ fflush(fp);
35+ errno = 0;
36+}
37+
38+static void unset2(const char *str)
39+{
40+ const char *cp = str;
41+ while (*cp) {
42+ if (*cp++ != '\n')
43+ continue;
44+ fprintf(fp, "delete ");
45+ fwrite(str, cp - str, 1, fp);
46+ str = cp;
47+ }
48+ fprintf(fp, "delete %s\n", str);
49+ fflush(fp);
50+ errno = 0;
51+}
52+
53+static void check(const char *prompt, int result)
54+{
55+ int err = errno;
56+ printf("%s%s\n", prompt, result ? "Success" : "Failed");
57+ if (!result) {
58+ fprintf(stderr, "Err: %s(%d)\n", strerror(err), err);
59+ {
60+ int fd2 = open(POLDIR "/self_domain", O_RDONLY);
61+ char c;
62+ fprintf(stderr, "task.domain=\"");
63+ while (read(fd2, &c, 1) == 1)
64+ fprintf(stderr, "%c", c);
65+ close(fd2);
66+ fprintf(stderr, "\"\n");
67+ }
68+ kill(1, SIGCONT);
69+ exit(1);
70+ }
71+ printf("\n");
72+ fflush(stdout);
73+}
74+
75+static void check_init(const char *prompt, const char *expected)
76+{
77+ int result;
78+ int fd = open(POLDIR "/.process_status", O_RDWR);
79+ char buffer[1024];
80+ char *cp;
81+ memset(buffer, 0, sizeof(buffer));
82+ kill(1, SIGHUP);
83+ sleep(1);
84+ write(fd, "1\n", 2);
85+ read(fd, buffer, sizeof(buffer) - 1);
86+ close(fd);
87+ cp = strchr(buffer, ' ');
88+ if (cp++)
89+ memmove(buffer, cp, strlen(cp) + 1);
90+ result = !strcmp(buffer, expected);
91+ printf("%s%s\n", prompt, result ? "Success" : "Failed");
92+ if (!result) {
93+ fprintf(stderr, "Err: expected='%s' result='%s'\n",
94+ expected, buffer);
95+ kill(1, SIGCONT);
96+ exit(1);
97+ }
98+ printf("\n");
99+ fflush(stdout);
100+}
101+
102+static void test_task_transition(void)
103+{
104+ int fd = open(POLDIR "/self_domain", O_WRONLY);
105+ char *policy;
106+
107+ policy = "100 acl manual_domain_transition\n"
108+ "0 allow domain=\"domain\\$\"\n";
109+ set(policy);
110+ check(policy, write(fd, "domain0", 7) != EOF);
111+ check(policy, write(fd, "domain10", 8) != EOF);
112+ check(policy, write(fd, "domainXYX", 9) == EOF);
113+ check(policy, write(fd, "domain200", 9) != EOF);
114+ unset(policy);
115+
116+ policy = "100 acl auto_domain_transition\n"
117+ "0 allow task.pid=1 transition=\"<init3>\"\n";
118+ set(policy);
119+ check_init(policy, "<init3>");
120+ unset(policy);
121+
122+ policy = "100 acl auto_domain_transition\n"
123+ "0 allow task.pid=1 task.uid!=0 transition=\"<init2>\"\n";
124+ set(policy);
125+ check_init(policy, "<init3>");
126+ unset(policy);
127+
128+ policy = "100 acl auto_domain_transition\n"
129+ "0 allow task.pid=1 transition=\"<init>\"\n";
130+ set(policy);
131+ check_init(policy, "<init>");
132+ unset(policy);
133+
134+ close(fd);
135+}
136+
137+static void test_file_read(void)
138+{
139+ int fd;
140+ char *policy;
141+
142+ policy = "100 acl read\n";
143+ set(policy);
144+ fd = open("/dev/null", O_RDONLY);
145+ check(policy, fd != EOF);
146+ close(fd);
147+ unset(policy);
148+
149+ policy = "100 acl read\n"
150+ "0 allow\n"
151+ "1 deny\n";
152+ set(policy);
153+ fd = open("/dev/null", O_RDONLY);
154+ check(policy, fd != EOF);
155+ close(fd);
156+ unset(policy);
157+
158+ policy = "100 acl read\n"
159+ "0 deny\n"
160+ "1 allow\n";
161+ set(policy);
162+ fd = open("/dev/null", O_RDONLY);
163+ check(policy, fd == EOF);
164+ close(fd);
165+ unset(policy);
166+
167+ policy = "100 acl read path=\"/dev/null\"\n"
168+ "0 allow\n"
169+ "1 deny\n";
170+ set(policy);
171+ fd = open("/dev/null", O_RDONLY);
172+ check(policy, fd != EOF);
173+ close(fd);
174+ unset(policy);
175+
176+ policy = "100 acl read path=\"/dev/null\"\n"
177+ "0 deny\n"
178+ "1 allow\n";
179+ set(policy);
180+ fd = open("/dev/null", O_RDONLY);
181+ check(policy, fd == EOF);
182+ close(fd);
183+ unset(policy);
184+
185+ policy = "100 acl read\n"
186+ "0 allow path=\"/dev/null\"\n"
187+ "1 deny\n";
188+ set(policy);
189+ fd = open("/dev/null", O_RDONLY);
190+ check(policy, fd != EOF);
191+ close(fd);
192+ unset(policy);
193+
194+ policy = "100 acl read\n"
195+ "0 deny path=\"/dev/null\"\n"
196+ "1 allow\n";
197+ set(policy);
198+ fd = open("/dev/null", O_RDONLY);
199+ check(policy, fd == EOF);
200+ close(fd);
201+ unset(policy);
202+
203+ policy = "100 acl read\n"
204+ "0 allow path.type=char path.dev_major=1 path.dev_minor=3\n"
205+ "1 deny\n";
206+ set(policy);
207+ fd = open("/dev/null", O_RDONLY);
208+ check(policy, fd != EOF);
209+ close(fd);
210+ unset(policy);
211+
212+ policy = "100 acl read\n"
213+ "0 deny path.type=char path.dev_major=1 path.dev_minor=3\n"
214+ "1 allow\n";
215+ set(policy);
216+ fd = open("/dev/null", O_RDONLY);
217+ check(policy, fd == EOF);
218+ close(fd);
219+ unset(policy);
220+
221+ policy = "100 acl read\n"
222+ "0 allow path.type=char path.dev_major=1 path.dev_minor!=3\n"
223+ "1 deny\n";
224+ set(policy);
225+ fd = open("/dev/null", O_RDONLY);
226+ check(policy, fd == EOF);
227+ close(fd);
228+ unset(policy);
229+
230+ policy = "100 acl read\n"
231+ "0 deny path.type=char path.dev_major=1 path.dev_minor!=3\n"
232+ "1 allow\n";
233+ set(policy);
234+ fd = open("/dev/null", O_RDONLY);
235+ check(policy, fd != EOF);
236+ close(fd);
237+ unset(policy);
238+
239+ policy = "string_group GROUP1 /dev/null\n"
240+ "100 acl read\n"
241+ "0 allow path=@GROUP1\n"
242+ "1 deny\n";
243+ set(policy);
244+ fd = open("/dev/null", O_RDONLY);
245+ check(policy, fd != EOF);
246+ close(fd);
247+ unset2(policy);
248+
249+ policy = "string_group GROUP1 /dev/null\n"
250+ "100 acl read\n"
251+ "0 deny path=@GROUP1\n"
252+ "1 allow\n";
253+ set(policy);
254+ fd = open("/dev/null", O_RDONLY);
255+ check(policy, fd == EOF);
256+ close(fd);
257+ unset2(policy);
258+
259+ policy = "string_group GROUP1 /dev/null\n"
260+ "100 acl read\n"
261+ "0 allow path!=@GROUP1\n"
262+ "1 deny\n";
263+ set(policy);
264+ fd = open("/dev/null", O_RDONLY);
265+ check(policy, fd == EOF);
266+ close(fd);
267+ unset2(policy);
268+
269+ policy = "string_group GROUP1 /dev/null\n"
270+ "100 acl read\n"
271+ "0 deny path!=@GROUP1\n"
272+ "1 allow\n";
273+ set(policy);
274+ fd = open("/dev/null", O_RDONLY);
275+ check(policy, fd != EOF);
276+ close(fd);
277+ unset2(policy);
278+
279+ policy = "string_group GROUP1 /dev/null\n"
280+ "number_group MAJOR 1\n"
281+ "number_group MINOR 3\n"
282+ "100 acl read\n"
283+ "0 allow path=@GROUP1 path.dev_major=@MAJOR"
284+ " path.dev_minor=@MINOR\n"
285+ "1 deny\n";
286+ set(policy);
287+ fd = open("/dev/null", O_RDONLY);
288+ check(policy, fd != EOF);
289+ close(fd);
290+ unset2(policy);
291+
292+ policy = "string_group GROUP1 /dev/null\n"
293+ "number_group MAJOR 1\n"
294+ "number_group MINOR 3\n"
295+ "100 acl read\n"
296+ "0 deny path=@GROUP1 path.dev_major=@MAJOR"
297+ " path.dev_minor=@MINOR\n"
298+ "1 allow\n";
299+ set(policy);
300+ fd = open("/dev/null", O_RDONLY);
301+ check(policy, fd == EOF);
302+ close(fd);
303+ unset2(policy);
304+
305+ policy = "string_group GROUP1 /dev/zero\n"
306+ "string_group GROUP1 /dev/null\n"
307+ "string_group GROUP1 /dev/urandom\n"
308+ "number_group MAJOR 0\n"
309+ "number_group MAJOR 2-255\n"
310+ "number_group MINOR 00-0x2\n"
311+ "number_group MINOR 255\n"
312+ "100 acl read\n"
313+ "0 allow path=@GROUP1 path.dev_major=@MAJOR"
314+ " path.dev_minor=@MINOR\n"
315+ "1 deny\n";
316+ set(policy);
317+ fd = open("/dev/null", O_RDONLY);
318+ check(policy, fd == EOF);
319+ close(fd);
320+ unset2(policy);
321+
322+ policy = "string_group GROUP1 /dev/zero\n"
323+ "string_group GROUP1 /dev/null\n"
324+ "string_group GROUP1 /dev/urandom\n"
325+ "number_group MAJOR 0\n"
326+ "number_group MAJOR 2-255\n"
327+ "number_group MINOR 00-0x2\n"
328+ "number_group MINOR 255\n"
329+ "100 acl read\n"
330+ "0 allow path=@GROUP1 path.dev_major!=@MAJOR"
331+ " path.dev_minor!=@MINOR\n"
332+ "1 deny\n";
333+ set(policy);
334+ fd = open("/dev/null", O_RDONLY);
335+ check(policy, fd != EOF);
336+ close(fd);
337+ unset2(policy);
338+}
339+
340+static void test_file_write(void)
341+{
342+ int fd;
343+ char *policy;
344+
345+ policy = "100 acl write\n"
346+ "0 allow\n"
347+ "100 acl append\n"
348+ "0 deny\n";
349+ set(policy);
350+ fd = open("/dev/null", O_WRONLY);
351+ check(policy, fd != EOF);
352+ close(fd);
353+ unset2(policy);
354+
355+ policy = "100 acl write\n"
356+ "0 deny\n"
357+ "100 acl append\n"
358+ "0 allow\n";
359+ set(policy);
360+ fd = open("/dev/null", O_WRONLY);
361+ check(policy, fd == EOF);
362+ close(fd);
363+ unset2(policy);
364+
365+ policy = "100 acl write\n"
366+ "0 allow\n"
367+ "100 acl append\n"
368+ "0 deny\n";
369+ set(policy);
370+ fd = open("/dev/null", O_WRONLY | O_APPEND);
371+ check(policy, fd == EOF);
372+ close(fd);
373+ unset2(policy);
374+
375+ policy = "100 acl write\n"
376+ "0 deny\n"
377+ "100 acl append\n"
378+ "0 append\n";
379+ set(policy);
380+ fd = open("/dev/null", O_WRONLY | O_APPEND);
381+ check(policy, fd != EOF);
382+ close(fd);
383+ unset2(policy);
384+
385+ policy = "100 acl write\n"
386+ "0 allow path.type=char path.dev_major=1 path.dev_minor=3\n"
387+ "1 deny\n";
388+ set(policy);
389+ fd = open("/dev/null", O_WRONLY | O_TRUNC);
390+ check(policy, fd != EOF);
391+ close(fd);
392+ unset(policy);
393+
394+ policy = "100 acl write\n"
395+ "0 allow path.type=char path.dev_major=1"
396+ " path.dev_minor=@MINOR\n"
397+ "1 deny\n";
398+ set(policy);
399+ fd = open("/dev/null", O_WRONLY | O_TRUNC);
400+ check(policy, fd == EOF);
401+ close(fd);
402+ unset(policy);
403+
404+ policy = "100 acl write\n"
405+ "0 allow path.parent.uid=0 path.parent.perm=0755\n"
406+ "1 deny\n";
407+ set(policy);
408+ fd = open("/dev/null", O_WRONLY);
409+ check(policy, fd != EOF);
410+ close(fd);
411+ unset(policy);
412+
413+ policy = "100 acl write\n"
414+ "0 allow path.parent.uid=task.uid path.parent.gid=task.gid\n"
415+ "1 deny\n";
416+ set(policy);
417+ fd = open("/dev/null", O_WRONLY);
418+ check(policy, fd != EOF);
419+ close(fd);
420+ unset(policy);
421+
422+ policy = "100 acl write\n"
423+ "0 allow task.uid=path.parent.uid task.gid=path.parent.gid\n"
424+ "1 deny\n";
425+ set(policy);
426+ fd = open("/dev/null", O_WRONLY);
427+ check(policy, fd != EOF);
428+ close(fd);
429+ unset(policy);
430+}
431+
432+static void test_file_create(void)
433+{
434+ int fd;
435+ char *policy;
436+
437+ policy = "100 acl create\n"
438+ "0 allow path.uid=0\n"
439+ "1 deny\n";
440+ set(policy);
441+ unlink("/tmp/file");
442+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
443+ check(policy, fd == EOF);
444+ close(fd);
445+ unset(policy);
446+
447+ policy = "100 acl create\n"
448+ "0 allow path=\"/tmp/file\" path.parent.uid=0\n"
449+ "1 deny\n";
450+ set(policy);
451+ unlink("/tmp/file");
452+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
453+ check(policy, fd != EOF);
454+ close(fd);
455+ unset(policy);
456+
457+ policy = "number_group GROUP1 1-0xFFFFFFFF\n"
458+ "100 acl create\n"
459+ "0 allow path.parent.uid!=@GROUP1 perm=0600\n"
460+ "1 deny\n";
461+ set(policy);
462+ unlink("/tmp/file");
463+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
464+ check(policy, fd != EOF);
465+ close(fd);
466+ unset2(policy);
467+
468+ policy = "number_group GROUP1 1-0xFFFFFFFF\n"
469+ "100 acl create\n"
470+ "0 allow path.parent.uid!=@GROUP1 perm!=0600\n"
471+ "1 deny\n";
472+ set(policy);
473+ unlink("/tmp/file");
474+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
475+ check(policy, fd == EOF);
476+ close(fd);
477+ unset2(policy);
478+
479+ policy = "100 acl create\n"
480+ "0 allow path.parent.uid=task.uid\n"
481+ "1 deny\n";
482+ set(policy);
483+ unlink("/tmp/file");
484+ fd = open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600);
485+ check(policy, fd != EOF);
486+ close(fd);
487+ unset(policy);
488+}
489+
490+static void test_file_unlink(void)
491+{
492+ char *policy;
493+
494+ policy = "100 acl unlink\n"
495+ "0 allow path.uid=0 path.uid=path.parent.uid\n"
496+ "1 deny\n";
497+ set(policy);
498+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
499+ check(policy, unlink("/tmp/file") == 0);
500+ unset(policy);
501+
502+ policy = "100 acl unlink\n"
503+ "0 deny path.uid=0 path.uid=path.parent.uid\n"
504+ "1 allow\n";
505+ set(policy);
506+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
507+ check(policy, unlink("/tmp/file") == EOF);
508+ unset(policy);
509+}
510+
511+static void test_file_link(void)
512+{
513+ char *policy;
514+
515+ policy = "100 acl link\n"
516+ "0 allow old_path.uid=0 old_path.uid=old_path.parent.uid"
517+ " old_path.parent.ino=new_path.parent.ino\n"
518+ "1 deny\n";
519+ set(policy);
520+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
521+ unlink("/tmp/file2");
522+ check(policy, link("/tmp/file", "/tmp/file2") == 0);
523+ unset(policy);
524+
525+ policy = "100 acl link\n"
526+ "0 deny old_path.uid=0 old_path.uid=old_path.parent.uid\n"
527+ "1 allow\n";
528+ set(policy);
529+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
530+ unlink("/tmp/file2");
531+ check(policy, link("/tmp/file", "/tmp/file2") == EOF);
532+ unset(policy);
533+}
534+
535+static void test_file_rename(void)
536+{
537+ char *policy;
538+
539+ policy = "100 acl rename\n"
540+ "0 allow old_path.uid=0 old_path.uid=old_path.parent.uid"
541+ " old_path.parent.ino=new_path.parent.ino\n"
542+ "1 deny\n";
543+ set(policy);
544+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
545+ unlink("/tmp/file2");
546+ check(policy, rename("/tmp/file", "/tmp/file2") == 0);
547+ unset(policy);
548+
549+ policy = "100 acl rename\n"
550+ "0 deny old_path.uid=0 old_path.uid=old_path.parent.uid\n"
551+ "1 allow\n";
552+ set(policy);
553+ close(open("/tmp/file", O_CREAT | O_WRONLY | O_EXCL, 0600));
554+ unlink("/tmp/file2");
555+ check(policy, rename("/tmp/file", "/tmp/file2") == EOF);
556+ unset(policy);
557+}
558+
559+static void test_network_inet_stream(void)
560+{
561+ struct sockaddr_in addr1 = { };
562+ struct sockaddr_in addr2 = { };
563+ socklen_t size = sizeof(addr1);
564+ int fd1;
565+ int fd2;
566+ int fd3;
567+ char *policy;
568+ char buffer[1024];
569+ memset(buffer, 0, sizeof(buffer));
570+
571+ fd1 = socket(PF_INET, SOCK_STREAM, 0);
572+ fd2 = socket(PF_INET, SOCK_STREAM, 0);
573+ addr1.sin_family = AF_INET;
574+ addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
575+
576+ policy = "100 acl inet_stream_bind\n"
577+ "0 allow ip=127.0.0.1 port!=0\n"
578+ "1 deny\n";
579+ set(policy);
580+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
581+ EOF);
582+ unset(policy);
583+
584+ policy = "100 acl inet_stream_bind\n"
585+ "0 allow ip!=127.0.0.1 port=0\n"
586+ "1 deny\n";
587+ set(policy);
588+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
589+ EOF);
590+ unset(policy);
591+
592+ policy = "100 acl inet_stream_bind\n"
593+ "0 allow ip=127.0.0.1 port=0 path.uid=task.uid\n"
594+ "1 deny\n";
595+ set(policy);
596+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
597+ EOF);
598+ unset(policy);
599+
600+ policy = "100 acl inet_stream_bind\n"
601+ "0 allow ip=127.0.0.1 port=0\n"
602+ "1 deny\n";
603+ set(policy);
604+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
605+ 0);
606+ unset(policy);
607+
608+ getsockname(fd1, (struct sockaddr *) &addr1, &size);
609+
610+ snprintf(buffer, sizeof(buffer) - 1,
611+ "100 acl inet_stream_listen\n"
612+ "0 allow ip=127.0.0.1 port!=%u\n"
613+ "1 deny\n", ntohs(addr1.sin_port));
614+ policy = buffer;
615+ set(policy);
616+ check(policy, listen(fd1, 5) == EOF);
617+ unset(policy);
618+
619+ snprintf(buffer, sizeof(buffer) - 1,
620+ "100 acl inet_stream_listen\n"
621+ "0 allow ip=127.0.0.1 port=%u\n"
622+ "1 deny\n", ntohs(addr1.sin_port));
623+ policy = buffer;
624+ set(policy);
625+ check(policy, listen(fd1, 5) == 0);
626+ unset(policy);
627+
628+ snprintf(buffer, sizeof(buffer) - 1,
629+ "100 acl inet_stream_connect\n"
630+ "0 allow ip=127.0.0.1 port!=%u\n"
631+ "1 deny\n", ntohs(addr1.sin_port));
632+ policy = buffer;
633+ set(policy);
634+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
635+ == EOF);
636+ unset(policy);
637+
638+ snprintf(buffer, sizeof(buffer) - 1,
639+ "100 acl inet_stream_connect\n"
640+ "0 allow ip=127.0.0.1 port=%u\n"
641+ "1 deny\n", ntohs(addr1.sin_port));
642+ policy = buffer;
643+ set(policy);
644+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
645+ == 0);
646+ unset(policy);
647+
648+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
649+
650+ snprintf(buffer, sizeof(buffer) - 1,
651+ "100 acl inet_stream_accept\n"
652+ "0 allow ip=127.0.0.1 port=%u\n"
653+ "1 deny\n", ntohs(addr2.sin_port));
654+ policy = buffer;
655+ set(policy);
656+ fd3 = accept(fd1, NULL, 0);
657+ check(policy, fd3 != EOF);
658+ close(fd3);
659+ unset(policy);
660+
661+ snprintf(buffer, sizeof(buffer) - 1,
662+ "100 acl inet_stream_connect\n"
663+ "0 allow ip=127.0.0.1 port=%u\n"
664+ "1 deny\n", ntohs(addr1.sin_port));
665+ policy = buffer;
666+ set(policy);
667+ close(fd2);
668+ fd2 = socket(PF_INET, SOCK_STREAM, 0);
669+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
670+ == 0);
671+ unset(policy);
672+
673+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
674+
675+ snprintf(buffer, sizeof(buffer) - 1,
676+ "100 acl inet_stream_accept\n"
677+ "0 allow ip=127.0.0.1 port!=%u\n"
678+ "1 deny\n", ntohs(addr2.sin_port));
679+ policy = buffer;
680+ set(policy);
681+ fd3 = accept(fd1, NULL, 0);
682+ check(policy, fd3 == EOF);
683+ close(fd3);
684+ unset(policy);
685+
686+ close(fd1);
687+ close(fd2);
688+}
689+
690+static void test_network_inet_dgram(void)
691+{
692+ struct sockaddr_in addr1 = { };
693+ struct sockaddr_in addr2 = { };
694+ socklen_t size = sizeof(addr1);
695+ int fd1;
696+ int fd2;
697+ char c;
698+ char *policy;
699+ char buffer[1024];
700+ memset(buffer, 0, sizeof(buffer));
701+
702+ fd1 = socket(PF_INET, SOCK_DGRAM, 0);
703+ fd2 = socket(PF_INET, SOCK_DGRAM, 0);
704+ addr1.sin_family = AF_INET;
705+ addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
706+
707+ policy = "100 acl inet_dgram_bind\n"
708+ "0 allow ip=127.0.0.1 port!=0\n"
709+ "1 deny\n";
710+ set(policy);
711+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
712+ EOF);
713+ unset(policy);
714+
715+ policy = "100 acl inet_dgram_bind\n"
716+ "0 allow ip!=127.0.0.1 port=0\n"
717+ "1 deny\n";
718+ set(policy);
719+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
720+ EOF);
721+ unset(policy);
722+
723+ policy = "100 acl inet_dgram_bind\n"
724+ "0 allow ip=127.0.0.1 port=0 path.uid=task.uid\n"
725+ "1 deny\n";
726+ set(policy);
727+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
728+ EOF);
729+ unset(policy);
730+
731+ policy = "100 acl inet_dgram_bind\n"
732+ "0 allow ip=127.0.0.1 port=0\n"
733+ "1 deny\n";
734+ set(policy);
735+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
736+ 0);
737+ unset(policy);
738+
739+ getsockname(fd1, (struct sockaddr *) &addr1, &size);
740+
741+ snprintf(buffer, sizeof(buffer) - 1,
742+ "100 acl inet_dgram_send\n"
743+ "0 allow ip=127.0.0.1 port!=%u\n"
744+ "1 deny\n", ntohs(addr1.sin_port));
745+ policy = buffer;
746+ set(policy);
747+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
748+ == EOF);
749+ unset(policy);
750+
751+ snprintf(buffer, sizeof(buffer) - 1,
752+ "100 acl inet_dgram_send\n"
753+ "0 allow ip=127.0.0.1 port=%u\n"
754+ "1 deny\n", ntohs(addr1.sin_port));
755+ policy = buffer;
756+ set(policy);
757+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
758+ == 0);
759+ unset(policy);
760+
761+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
762+
763+ snprintf(buffer, sizeof(buffer) - 1,
764+ "100 acl inet_dgram_send\n"
765+ "0 allow ip=127.0.0.1 port=%u\n"
766+ "1 deny\n", ntohs(addr1.sin_port));
767+ policy = buffer;
768+ set(policy);
769+ check(policy, send(fd2, "", 1, 0) != EOF);
770+ unset(policy);
771+
772+ snprintf(buffer, sizeof(buffer) - 1,
773+ "100 acl inet_dgram_recv\n"
774+ "0 allow ip=127.0.0.1 port=%u\n"
775+ "1 deny\n", ntohs(addr2.sin_port));
776+ policy = buffer;
777+ set(policy);
778+ check(policy, recv(fd1, &c, 1, 0) != EOF);
779+ unset(policy);
780+
781+ snprintf(buffer, sizeof(buffer) - 1,
782+ "100 acl inet_dgram_send\n"
783+ "0 allow ip=127.0.0.1 port=%u\n"
784+ "1 deny\n", ntohs(addr1.sin_port));
785+ policy = buffer;
786+ set(policy);
787+ check(policy, send(fd2, "", 1, 0) != EOF);
788+ unset(policy);
789+
790+ snprintf(buffer, sizeof(buffer) - 1,
791+ "100 acl inet_dgram_recv\n"
792+ "0 allow ip=127.0.0.1 port!=%u\n"
793+ "1 deny\n", ntohs(addr2.sin_port));
794+ policy = buffer;
795+ set(policy);
796+ check(policy, recv(fd1, &c, 1, 0) == EOF);
797+ unset(policy);
798+
799+ snprintf(buffer, sizeof(buffer) - 1,
800+ "ip_group LOCALHOST 127.0.0.0-127.255.255.255\n"
801+ "100 acl inet_dgram_send\n"
802+ "0 allow ip=@LOCALHOST port=%u\n"
803+ "1 deny\n", ntohs(addr1.sin_port));
804+ policy = buffer;
805+ set(policy);
806+ check(policy, send(fd2, "", 1, 0) != EOF);
807+ unset2(policy);
808+
809+ snprintf(buffer, sizeof(buffer) - 1,
810+ "ip_group LOCALHOST 127.0.0.0-127.255.255.255\n"
811+ "100 acl inet_dgram_recv\n"
812+ "0 allow ip!=@LOCALHOST port=%u\n"
813+ "1 deny\n", ntohs(addr2.sin_port));
814+ policy = buffer;
815+ set(policy);
816+ check(policy, recv(fd1, &c, 1, 0) == EOF);
817+ unset2(policy);
818+
819+ close(fd1);
820+ close(fd2);
821+}
822+
823+static void test_network_inet_raw(void)
824+{
825+ struct sockaddr_in addr = { };
826+ static struct iphdr ip = { };
827+ int fd1;
828+ int fd2;
829+ char *policy;
830+ fd1 = socket(PF_INET, SOCK_RAW, 1);
831+ fd2 = socket(PF_INET, SOCK_RAW, 1);
832+ addr.sin_family = AF_INET;
833+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
834+ ip.version = 4;
835+ ip.ihl = sizeof(struct iphdr) / 4;
836+ ip.protocol = IPPROTO_RAW;
837+ ip.daddr = htonl(INADDR_LOOPBACK);
838+ ip.saddr = ip.daddr;
839+
840+ policy = "100 acl inet_raw_bind\n"
841+ "0 allow ip=127.0.0.1 proto!=1\n"
842+ "1 deny\n";
843+ set(policy);
844+ check(policy, bind(fd1, (struct sockaddr *) &addr, sizeof(addr)) ==
845+ EOF);
846+ unset(policy);
847+
848+ policy = "100 acl inet_raw_bind\n"
849+ "0 allow ip!=127.0.0.1 proto=1\n"
850+ "1 deny\n";
851+ set(policy);
852+ check(policy, bind(fd1, (struct sockaddr *) &addr, sizeof(addr)) ==
853+ EOF);
854+ unset(policy);
855+
856+ policy = "100 acl inet_raw_bind\n"
857+ "0 allow ip=127.0.0.1 proto=1 path.uid=task.uid\n"
858+ "1 deny\n";
859+ set(policy);
860+ check(policy, bind(fd1, (struct sockaddr *) &addr, sizeof(addr)) ==
861+ EOF);
862+ unset(policy);
863+
864+ policy = "100 acl inet_raw_bind\n"
865+ "0 allow ip=127.0.0.1 proto=1\n"
866+ "1 deny\n";
867+ set(policy);
868+ check(policy, bind(fd2, (struct sockaddr *) &addr, sizeof(addr)) ==
869+ 0);
870+ unset(policy);
871+
872+ policy = "100 acl inet_raw_send\n"
873+ "0 allow ip=127.0.0.1 proto!=1\n"
874+ "1 deny\n";
875+ set(policy);
876+ check(policy, connect(fd2, (struct sockaddr *) &addr, sizeof(addr))
877+ == EOF);
878+ unset(policy);
879+
880+ policy = "100 acl inet_raw_send\n"
881+ "0 allow ip=127.0.0.1 proto=1\n"
882+ "1 deny\n";
883+ set(policy);
884+ check(policy, connect(fd2, (struct sockaddr *) &addr, sizeof(addr))
885+ == 0);
886+ unset(policy);
887+
888+ policy = "100 acl inet_raw_send\n"
889+ "0 allow ip=127.0.0.1 proto=1\n"
890+ "1 deny\n";
891+ set(policy);
892+ check(policy, send(fd2, &ip, sizeof(ip), 0) != EOF);
893+ unset(policy);
894+
895+ policy = "100 acl inet_raw_recv\n"
896+ "0 allow ip=127.0.0.1 proto=1\n"
897+ "1 deny\n";
898+ set(policy);
899+ check(policy, recv(fd1, &ip, sizeof(ip), MSG_DONTWAIT) != EOF);
900+ unset(policy);
901+
902+ policy = "100 acl inet_raw_send\n"
903+ "0 allow ip=127.0.0.1 proto=1\n"
904+ "1 deny\n";
905+ set(policy);
906+ check(policy, send(fd2, &ip, sizeof(ip), 0) != EOF);
907+ unset(policy);
908+
909+ policy = "100 acl inet_raw_recv\n"
910+ "0 allow ip=127.0.0.1 proto!=1\n"
911+ "1 deny\n";
912+ set(policy);
913+ check(policy, recv(fd1, &ip, sizeof(ip), MSG_DONTWAIT) == EOF);
914+ unset(policy);
915+
916+ policy = "ip_group LOCALHOST 127.0.0.0-127.255.255.255\n"
917+ "100 acl inet_raw_send\n"
918+ "0 allow ip=@LOCALHOST proto=1\n"
919+ "1 deny\n";
920+ set(policy);
921+ check(policy, send(fd2, &ip, sizeof(ip), 0) != EOF);
922+ unset2(policy);
923+
924+ policy = "ip_group LOCALHOST 127.0.0.0-127.255.255.255\n"
925+ "100 acl inet_raw_recv\n"
926+ "0 allow ip!=@LOCALHOST proto=1\n"
927+ "1 deny\n";
928+ set(policy);
929+ check(policy, recv(fd1, &ip, sizeof(ip), MSG_DONTWAIT) == EOF);
930+ unset2(policy);
931+
932+ close(fd1);
933+ close(fd2);
934+}
935+
936+static void test_network_inet6_stream(void)
937+{
938+ struct sockaddr_in6 addr1 = { };
939+ struct sockaddr_in6 addr2 = { };
940+ socklen_t size = sizeof(addr1);
941+ int fd1;
942+ int fd2;
943+ int fd3;
944+ char *policy;
945+ char buffer[1024];
946+ memset(buffer, 0, sizeof(buffer));
947+
948+ fd1 = socket(PF_INET6, SOCK_STREAM, 0);
949+ if (fd1 == EOF && errno == EAFNOSUPPORT)
950+ return;
951+ fd2 = socket(PF_INET6, SOCK_STREAM, 0);
952+ addr1.sin6_family = AF_INET6;
953+ addr1.sin6_addr = in6addr_loopback;
954+
955+ policy = "100 acl inet_stream_bind\n"
956+ "0 allow ip=::1 port!=0\n"
957+ "1 deny\n";
958+ set(policy);
959+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
960+ EOF);
961+ unset(policy);
962+
963+ policy = "100 acl inet_stream_bind\n"
964+ "0 allow ip!=::1 port=0\n"
965+ "1 deny\n";
966+ set(policy);
967+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
968+ EOF);
969+ unset(policy);
970+
971+ policy = "100 acl inet_stream_bind\n"
972+ "0 allow ip=::1 port=0 path.uid=task.uid\n"
973+ "1 deny\n";
974+ set(policy);
975+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
976+ EOF);
977+ unset(policy);
978+
979+ policy = "100 acl inet_stream_bind\n"
980+ "0 allow ip=::1 port=0\n"
981+ "1 deny\n";
982+ set(policy);
983+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
984+ 0);
985+ unset(policy);
986+
987+ getsockname(fd1, (struct sockaddr *) &addr1, &size);
988+
989+ snprintf(buffer, sizeof(buffer) - 1,
990+ "100 acl inet_stream_listen\n"
991+ "0 allow ip=::1 port!=%u\n"
992+ "1 deny\n", ntohs(addr1.sin6_port));
993+ policy = buffer;
994+ set(policy);
995+ check(policy, listen(fd1, 5) == EOF);
996+ unset(policy);
997+
998+ snprintf(buffer, sizeof(buffer) - 1,
999+ "100 acl inet_stream_listen\n"
1000+ "0 allow ip=::1 port=%u\n"
1001+ "1 deny\n", ntohs(addr1.sin6_port));
1002+ policy = buffer;
1003+ set(policy);
1004+ check(policy, listen(fd1, 5) == 0);
1005+ unset(policy);
1006+
1007+ snprintf(buffer, sizeof(buffer) - 1,
1008+ "100 acl inet_stream_connect\n"
1009+ "0 allow ip=::1 port!=%u\n"
1010+ "1 deny\n", ntohs(addr1.sin6_port));
1011+ policy = buffer;
1012+ set(policy);
1013+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
1014+ == EOF);
1015+ unset(policy);
1016+
1017+ snprintf(buffer, sizeof(buffer) - 1,
1018+ "100 acl inet_stream_connect\n"
1019+ "0 allow ip=::1 port=%u\n"
1020+ "1 deny\n", ntohs(addr1.sin6_port));
1021+ policy = buffer;
1022+ set(policy);
1023+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
1024+ == 0);
1025+ unset(policy);
1026+
1027+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
1028+
1029+ snprintf(buffer, sizeof(buffer) - 1,
1030+ "100 acl inet_stream_accept\n"
1031+ "0 allow ip=::1 port=%u\n"
1032+ "1 deny\n", ntohs(addr2.sin6_port));
1033+ policy = buffer;
1034+ set(policy);
1035+ fd3 = accept(fd1, NULL, 0);
1036+ check(policy, fd3 != EOF);
1037+ close(fd3);
1038+ unset(policy);
1039+
1040+ snprintf(buffer, sizeof(buffer) - 1,
1041+ "100 acl inet_stream_connect\n"
1042+ "0 allow ip=::1 port=%u\n"
1043+ "1 deny\n", ntohs(addr1.sin6_port));
1044+ policy = buffer;
1045+ set(policy);
1046+ close(fd2);
1047+ fd2 = socket(PF_INET6, SOCK_STREAM, 0);
1048+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
1049+ == 0);
1050+ unset(policy);
1051+
1052+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
1053+
1054+ snprintf(buffer, sizeof(buffer) - 1,
1055+ "100 acl inet_stream_accept\n"
1056+ "0 allow ip=::1 port!=%u\n"
1057+ "1 deny\n", ntohs(addr2.sin6_port));
1058+ policy = buffer;
1059+ set(policy);
1060+ fd3 = accept(fd1, NULL, 0);
1061+ check(policy, fd3 == EOF);
1062+ close(fd3);
1063+ unset(policy);
1064+
1065+ close(fd1);
1066+ close(fd2);
1067+}
1068+
1069+static void test_network_inet6_dgram(void)
1070+{
1071+ struct sockaddr_in6 addr1 = { };
1072+ struct sockaddr_in6 addr2 = { };
1073+ socklen_t size = sizeof(addr1);
1074+ int fd1;
1075+ int fd2;
1076+ char c;
1077+ char *policy;
1078+ char buffer[1024];
1079+ memset(buffer, 0, sizeof(buffer));
1080+
1081+ fd1 = socket(PF_INET6, SOCK_DGRAM, 0);
1082+ if (fd1 == EOF && errno == EAFNOSUPPORT)
1083+ return;
1084+ fd2 = socket(PF_INET6, SOCK_DGRAM, 0);
1085+ addr1.sin6_family = AF_INET6;
1086+ addr1.sin6_addr = in6addr_loopback;
1087+
1088+ policy = "100 acl inet_dgram_bind\n"
1089+ "0 allow ip=::1 port!=0\n"
1090+ "1 deny\n";
1091+ set(policy);
1092+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
1093+ EOF);
1094+ unset(policy);
1095+
1096+ policy = "100 acl inet_dgram_bind\n"
1097+ "0 allow ip!=::1 port=0\n"
1098+ "1 deny\n";
1099+ set(policy);
1100+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
1101+ EOF);
1102+ unset(policy);
1103+
1104+ policy = "100 acl inet_dgram_bind\n"
1105+ "0 allow ip=::1 port=0 path.uid=task.uid\n"
1106+ "1 deny\n";
1107+ set(policy);
1108+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
1109+ EOF);
1110+ unset(policy);
1111+
1112+ policy = "100 acl inet_dgram_bind\n"
1113+ "0 allow ip=::1 port=0\n"
1114+ "1 deny\n";
1115+ set(policy);
1116+ check(policy, bind(fd1, (struct sockaddr *) &addr1, sizeof(addr1)) ==
1117+ 0);
1118+ unset(policy);
1119+
1120+ getsockname(fd1, (struct sockaddr *) &addr1, &size);
1121+
1122+ snprintf(buffer, sizeof(buffer) - 1,
1123+ "100 acl inet_dgram_send\n"
1124+ "0 allow ip=::1 port!=%u\n"
1125+ "1 deny\n", ntohs(addr1.sin6_port));
1126+ policy = buffer;
1127+ set(policy);
1128+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
1129+ == EOF);
1130+ unset(policy);
1131+
1132+ snprintf(buffer, sizeof(buffer) - 1,
1133+ "100 acl inet_dgram_send\n"
1134+ "0 allow ip=::1 port=%u\n"
1135+ "1 deny\n", ntohs(addr1.sin6_port));
1136+ policy = buffer;
1137+ set(policy);
1138+ check(policy, connect(fd2, (struct sockaddr *) &addr1, sizeof(addr1))
1139+ == 0);
1140+ unset(policy);
1141+
1142+ getsockname(fd2, (struct sockaddr *) &addr2, &size);
1143+
1144+ snprintf(buffer, sizeof(buffer) - 1,
1145+ "100 acl inet_dgram_send\n"
1146+ "0 allow ip=::1 port=%u\n"
1147+ "1 deny\n", ntohs(addr1.sin6_port));
1148+ policy = buffer;
1149+ set(policy);
1150+ check(policy, send(fd2, "", 1, 0) != EOF);
1151+ unset(policy);
1152+
1153+ snprintf(buffer, sizeof(buffer) - 1,
1154+ "100 acl inet_dgram_recv\n"
1155+ "0 allow ip=::1 port=%u\n"
1156+ "1 deny\n", ntohs(addr2.sin6_port));
1157+ policy = buffer;
1158+ set(policy);
1159+ check(policy, recv(fd1, &c, 1, 0) != EOF);
1160+ unset(policy);
1161+
1162+ snprintf(buffer, sizeof(buffer) - 1,
1163+ "100 acl inet_dgram_send\n"
1164+ "0 allow ip=::1 port=%u\n"
1165+ "1 deny\n", ntohs(addr1.sin6_port));
1166+ policy = buffer;
1167+ set(policy);
1168+ check(policy, send(fd2, "", 1, 0) != EOF);
1169+ unset(policy);
1170+
1171+ snprintf(buffer, sizeof(buffer) - 1,
1172+ "100 acl inet_dgram_recv\n"
1173+ "0 allow ip=::1 port!=%u\n"
1174+ "1 deny\n", ntohs(addr2.sin6_port));
1175+ policy = buffer;
1176+ set(policy);
1177+ check(policy, recv(fd1, &c, 1, 0) == EOF);
1178+ unset(policy);
1179+
1180+ snprintf(buffer, sizeof(buffer) - 1,
1181+ "ip_group LOCALHOST ::-::ffff\n"
1182+ "100 acl inet_dgram_send\n"
1183+ "0 allow ip=@LOCALHOST port=%u\n"
1184+ "1 deny\n", ntohs(addr1.sin6_port));
1185+ policy = buffer;
1186+ set(policy);
1187+ check(policy, send(fd2, "", 1, 0) != EOF);
1188+ unset2(policy);
1189+
1190+ snprintf(buffer, sizeof(buffer) - 1,
1191+ "ip_group LOCALHOST ::-::ffff\n"
1192+ "100 acl inet_dgram_recv\n"
1193+ "0 allow ip!=@LOCALHOST port=%u\n"
1194+ "1 deny\n", ntohs(addr2.sin6_port));
1195+ policy = buffer;
1196+ set(policy);
1197+ check(policy, recv(fd1, &c, 1, 0) == EOF);
1198+ unset2(policy);
1199+
1200+ close(fd1);
1201+ close(fd2);
1202+}
1203+
1204+static void test_capability(void)
1205+{
1206+ char *policy;
1207+
1208+ policy = "100 acl set_priority\n"
1209+ "0 allow task.uid=0\n"
1210+ "1 deny\n";
1211+ set(policy);
1212+ check(policy, nice(0) == 0);
1213+ unset(policy);
1214+
1215+ policy = "100 acl set_priority\n"
1216+ "0 allow task.uid=task.gid task.type!=execute_handler\n"
1217+ "1 deny\n";
1218+ set(policy);
1219+ check(policy, nice(0) == 0);
1220+ unset(policy);
1221+
1222+ policy = "100 acl set_priority\n"
1223+ "0 deny task.uid=0\n"
1224+ "1 allow\n";
1225+ set(policy);
1226+ check(policy, nice(0) == EOF);
1227+ unset(policy);
1228+
1229+ policy = "100 acl set_priority\n"
1230+ "0 allow task.uid=task.gid task.type=execute_handler\n"
1231+ "1 deny\n";
1232+ set(policy);
1233+ check(policy, nice(0) == EOF);
1234+ unset(policy);
1235+}
1236+
1237+static void detach_init(void)
1238+{
1239+ int i;
1240+ for (i = 0; i < 2; i++) {
1241+ ptrace(PTRACE_DETACH, 1, NULL, NULL);
1242+ kill(1, SIGCONT);
1243+ sleep(1);
1244+ }
1245+}
1246+
1247+static void test_ptrace(void)
1248+{
1249+ char *policy;
1250+
1251+ policy = "100 acl ptrace\n"
1252+ "0 allow cmd=1 domain!=\"foo\"\n"
1253+ "0 allow cmd=17\n"
1254+ "1 deny\n";
1255+ set(policy);
1256+ check(policy, ptrace(PTRACE_ATTACH, 1, NULL, NULL) == EOF);
1257+ unset(policy);
1258+ detach_init();
1259+
1260+ policy = "100 acl ptrace\n"
1261+ "0 allow cmd=16 domain=\"foo\"\n"
1262+ "0 allow cmd=17\n"
1263+ "1 deny\n";
1264+ set(policy);
1265+ check(policy, ptrace(PTRACE_ATTACH, 1, NULL, NULL) == EOF);
1266+ unset(policy);
1267+ detach_init();
1268+
1269+ policy = "100 acl ptrace\n"
1270+ "0 allow cmd=16 domain!=\"foo\"\n"
1271+ "0 allow cmd=17\n"
1272+ "1 deny\n";
1273+ set(policy);
1274+ check(policy, ptrace(PTRACE_ATTACH, 1, NULL, NULL) == 0);
1275+ unset(policy);
1276+ detach_init();
1277+
1278+ policy = "string_group DOMAINS <init>\n"
1279+ "100 acl ptrace\n"
1280+ "0 allow cmd=16 domain=@DOMAINS\n"
1281+ "0 allow cmd=17\n"
1282+ "1 deny\n";
1283+ set(policy);
1284+ check(policy, ptrace(PTRACE_ATTACH, 1, NULL, NULL) == 0);
1285+ unset2(policy);
1286+ detach_init();
1287+
1288+ policy = "string_group DOMAINS <init>\n"
1289+ "100 acl ptrace\n"
1290+ "0 allow cmd=16 domain!=@DOMAINS\n"
1291+ "0 allow cmd=17\n"
1292+ "1 deny\n";
1293+ set(policy);
1294+ check(policy, ptrace(PTRACE_ATTACH, 1, NULL, NULL) == EOF);
1295+ unset2(policy);
1296+ detach_init();
1297+}
1298+
1299+static void test_signal(void)
1300+{
1301+ char *policy;
1302+
1303+ policy = "100 acl signal task.domain=\"domain200\"\n"
1304+ "0 allow sig=1 task.uid=0\n"
1305+ "1 deny\n";
1306+ set(policy);
1307+ check(policy, kill(1, 1) == 0);
1308+ unset(policy);
1309+
1310+ policy = "100 acl signal task.domain=\"domain200\"\n"
1311+ "0 allow sig!=1 task.uid=0\n"
1312+ "1 deny\n";
1313+ set(policy);
1314+ check(policy, kill(1, 1) == EOF);
1315+ unset(policy);
1316+
1317+ policy = "100 acl signal\n"
1318+ "0 allow task.domain!=\"domain200\"\n"
1319+ "0 allow sig=1\n"
1320+ "1 deny\n";
1321+ set(policy);
1322+ check(policy, kill(1, 1) == 0);
1323+ unset(policy);
1324+
1325+ policy = "100 acl signal\n"
1326+ "0 deny task.domain=\"domain200\"\n"
1327+ "0 allow\n";
1328+ set(policy);
1329+ check(policy, kill(1, 1) == EOF);
1330+ unset(policy);
1331+
1332+ policy = "100 acl signal\n"
1333+ "0 deny sig=1 task.domain=\"domain200\"\n"
1334+ "0 allow\n";
1335+ set(policy);
1336+ check(policy, kill(1, 1) == EOF);
1337+ unset(policy);
1338+}
1339+
1340+static int fork_exec(char *envp[])
1341+{
1342+ int ret_ignored;
1343+ int pipe_fd[2] = { EOF, EOF };
1344+ int err = 0;
1345+ pid_t pid;
1346+ if (pipe(pipe_fd)) {
1347+ fprintf(stderr, "Err: %s(%d)\n", strerror(err), err);
1348+ exit(1);
1349+ }
1350+ pid = fork();
1351+ if (pid == 0) {
1352+ char *argv[2] = { BINDIR "/true", NULL };
1353+ execve(BINDIR "/true", argv, envp);
1354+ err = errno;
1355+ ret_ignored = write(pipe_fd[1], &err, sizeof(err));
1356+ _exit(0);
1357+ }
1358+ close(pipe_fd[1]);
1359+ ret_ignored = read(pipe_fd[0], &err, sizeof(err));
1360+ close(pipe_fd[0]);
1361+ wait(NULL);
1362+ errno = err;
1363+ return err ? EOF : 0;
1364+}
1365+
1366+static void test_environ(void)
1367+{
1368+ char *policy;
1369+ char *envp[2];
1370+ envp[1] = NULL;
1371+
1372+ policy = "100 acl environ name=\"PATH2\"\n"
1373+ "0 allow value=\"/\"\n"
1374+ "1 deny\n";
1375+ set(policy);
1376+ envp[0] = "PATH2=/";
1377+ check(policy, fork_exec(envp) == 0);
1378+ unset(policy);
1379+
1380+ policy = "100 acl environ name=\"PATH2\"\n"
1381+ "0 allow value!=\"/\"\n"
1382+ "1 deny\n";
1383+ set(policy);
1384+ envp[0] = "PATH2=/";
1385+ check(policy, fork_exec(envp) == EOF);
1386+ unset(policy);
1387+
1388+ policy = "100 acl environ name=\"PATH2\"\n"
1389+ "0 deny value!=\"/\"\n"
1390+ "1 allow\n";
1391+ set(policy);
1392+ envp[0] = "PATH2=/";
1393+ check(policy, fork_exec(envp) == 0);
1394+ unset(policy);
1395+
1396+ policy = "100 acl environ name=\"PATH2\"\n"
1397+ "0 deny value=\"/\"\n"
1398+ "1 allow\n";
1399+ set(policy);
1400+ envp[0] = "PATH2=/";
1401+ check(policy, fork_exec(envp) == EOF);
1402+ unset(policy);
1403+
1404+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1405+ "0 allow envp[\"PATH2\"]=\"/\"\n"
1406+ "1 deny\n";
1407+ set(policy);
1408+ envp[0] = "PATH2=/";
1409+ check(policy, fork_exec(envp) == 0);
1410+ unset(policy);
1411+
1412+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1413+ "0 allow envp[\"PATH2\"]!=\"/\"\n"
1414+ "1 deny\n";
1415+ set(policy);
1416+ envp[0] = "PATH2=/";
1417+ check(policy, fork_exec(envp) == EOF);
1418+ unset(policy);
1419+
1420+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1421+ "0 allow envp[\"PATH2\"]!=NULL\n"
1422+ "1 deny\n";
1423+ set(policy);
1424+ envp[0] = "PATH2";
1425+ check(policy, fork_exec(envp) == 0);
1426+ unset(policy);
1427+
1428+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1429+ "0 allow envp[\"PATH2\"]!=NULL\n"
1430+ "1 deny\n";
1431+ set(policy);
1432+ envp[0] = "PATH2=";
1433+ check(policy, fork_exec(envp) == 0);
1434+ unset(policy);
1435+
1436+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1437+ "0 allow envp[\"PATH2\"]!=NULL\n"
1438+ "1 deny\n";
1439+ set(policy);
1440+ envp[0] = "PATH2=/";
1441+ check(policy, fork_exec(envp) == 0);
1442+ unset(policy);
1443+
1444+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1445+ "0 allow envp[\"PATH2\"]=NULL\n"
1446+ "1 deny\n";
1447+ set(policy);
1448+ envp[0] = "PATH2";
1449+ check(policy, fork_exec(envp) == EOF);
1450+ unset(policy);
1451+
1452+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1453+ "0 allow envp[\"PATH2\"]=NULL\n"
1454+ "1 deny\n";
1455+ set(policy);
1456+ envp[0] = "PATH2=";
1457+ check(policy, fork_exec(envp) == EOF);
1458+ unset(policy);
1459+
1460+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1461+ "0 allow envp[\"PATH2\"]=NULL\n"
1462+ "1 deny\n";
1463+ set(policy);
1464+ envp[0] = "PATH2=/";
1465+ check(policy, fork_exec(envp) == EOF);
1466+ unset(policy);
1467+
1468+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1469+ "0 allow envp[\"\"]=NULL\n"
1470+ "1 deny\n";
1471+ set(policy);
1472+ envp[0] = "";
1473+ check(policy, fork_exec(envp) == EOF);
1474+ unset(policy);
1475+
1476+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1477+ "0 allow envp[\"\"]!=NULL\n"
1478+ "1 deny\n";
1479+ set(policy);
1480+ envp[0] = "";
1481+ check(policy, fork_exec(envp) == 0);
1482+ unset(policy);
1483+
1484+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1485+ "0 allow envp[\"\"]!=NULL\n"
1486+ "1 deny\n";
1487+ set(policy);
1488+ envp[0] = "=";
1489+ check(policy, fork_exec(envp) == 0);
1490+ unset(policy);
1491+
1492+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1493+ "0 allow envp[\"\"]!=NULL\n"
1494+ "1 deny\n";
1495+ set(policy);
1496+ envp[0] = "=/";
1497+ check(policy, fork_exec(envp) == 0);
1498+ unset(policy);
1499+}
1500+
1501+static int fork_exec2(char *argv[], char *envp[])
1502+{
1503+ int ret_ignored;
1504+ int pipe_fd[2] = { EOF, EOF };
1505+ int err = 0;
1506+ pid_t pid;
1507+ if (pipe(pipe_fd)) {
1508+ fprintf(stderr, "Err: %s(%d)\n", strerror(err), err);
1509+ exit(1);
1510+ }
1511+ pid = fork();
1512+ if (pid == 0) {
1513+ execve(BINDIR "/true", argv, envp);
1514+ err = errno;
1515+ ret_ignored = write(pipe_fd[1], &err, sizeof(err));
1516+ _exit(0);
1517+ }
1518+ close(pipe_fd[1]);
1519+ ret_ignored = read(pipe_fd[0], &err, sizeof(err));
1520+ close(pipe_fd[0]);
1521+ wait(NULL);
1522+ errno = err;
1523+ return err ? EOF : 0;
1524+}
1525+
1526+static void test_file_execute(void)
1527+{
1528+ char *policy;
1529+ char *argv[5];
1530+ char *envp[5];
1531+ memset(argv, 0, sizeof(argv));
1532+ memset(envp, 0, sizeof(envp));
1533+
1534+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1535+ "0 allow argc=1\n"
1536+ "1 deny\n";
1537+ set(policy);
1538+ argv[0]="true";
1539+ check(policy, fork_exec2(argv, envp) == 0);
1540+ unset(policy);
1541+
1542+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1543+ "0 allow argc!=1\n"
1544+ "1 deny\n";
1545+ set(policy);
1546+ check(policy, fork_exec2(argv, envp) == EOF);
1547+ unset(policy);
1548+
1549+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1550+ "0 deny argc!=1\n"
1551+ "1 allow\n";
1552+ set(policy);
1553+ check(policy, fork_exec2(argv, envp) == 0);
1554+ unset(policy);
1555+
1556+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1557+ "0 deny argc=1\n"
1558+ "1 allow\n";
1559+ set(policy);
1560+ check(policy, fork_exec2(argv, envp) == EOF);
1561+ unset(policy);
1562+
1563+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1564+ "0 deny argv[0]!=\"true\"\n"
1565+ "1 allow\n";
1566+ set(policy);
1567+ check(policy, fork_exec2(argv, envp) == 0);
1568+ unset(policy);
1569+
1570+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1571+ "0 deny argv[0]=\"true\"\n"
1572+ "1 allow\n";
1573+ set(policy);
1574+ check(policy, fork_exec2(argv, envp) == EOF);
1575+ unset(policy);
1576+
1577+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1578+ "0 allow argv[0]!=\"true\"\n"
1579+ "1 deny\n";
1580+ set(policy);
1581+ check(policy, fork_exec2(argv, envp) == EOF);
1582+ unset(policy);
1583+
1584+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1585+ "0 allow argv[0]=\"true\"\n"
1586+ "1 deny\n";
1587+ set(policy);
1588+ check(policy, fork_exec2(argv, envp) == 0);
1589+ unset(policy);
1590+
1591+ policy = "string_group EXEC_ARGV0 false\n"
1592+ "string_group EXEC_ARGV0 true\n"
1593+ "100 acl execute path=\"" BINDIR "/true\"\n"
1594+ "0 deny argv[0]!=@EXEC_ARGV0\n"
1595+ "1 allow\n";
1596+ set(policy);
1597+ check(policy, fork_exec2(argv, envp) == 0);
1598+ unset2(policy);
1599+
1600+ policy = "string_group EXEC_ARGV0 false\n"
1601+ "string_group EXEC_ARGV0 true\n"
1602+ "100 acl execute path=\"" BINDIR "/true\"\n"
1603+ "0 deny argv[0]=@EXEC_ARGV0\n"
1604+ "1 allow\n";
1605+ set(policy);
1606+ check(policy, fork_exec2(argv, envp) == EOF);
1607+ unset2(policy);
1608+
1609+ policy = "string_group EXEC_ARGV0 false\n"
1610+ "string_group EXEC_ARGV0 true\n"
1611+ "100 acl execute path=\"" BINDIR "/true\"\n"
1612+ "0 allow argv[0]!=@EXEC_ARGV0\n"
1613+ "1 deny\n";
1614+ set(policy);
1615+ check(policy, fork_exec2(argv, envp) == EOF);
1616+ unset2(policy);
1617+
1618+ policy = "string_group EXEC_ARGV0 false\n"
1619+ "string_group EXEC_ARGV0 true\n"
1620+ "100 acl execute path=\"" BINDIR "/true\"\n"
1621+ "0 allow argv[0]=@EXEC_ARGV0\n"
1622+ "1 deny\n";
1623+ set(policy);
1624+ check(policy, fork_exec2(argv, envp) == 0);
1625+ unset2(policy);
1626+
1627+
1628+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1629+ "0 allow envc=1\n"
1630+ "1 deny\n";
1631+ set(policy);
1632+ envp[0]="PATH=/";
1633+ check(policy, fork_exec2(argv, envp) == 0);
1634+ unset(policy);
1635+
1636+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1637+ "0 allow envc!=1\n"
1638+ "1 deny\n";
1639+ set(policy);
1640+ check(policy, fork_exec2(argv, envp) == EOF);
1641+ unset(policy);
1642+
1643+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1644+ "0 deny envc!=1\n"
1645+ "1 allow\n";
1646+ set(policy);
1647+ check(policy, fork_exec2(argv, envp) == 0);
1648+ unset(policy);
1649+
1650+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1651+ "0 deny envc=1\n"
1652+ "1 allow\n";
1653+ set(policy);
1654+ check(policy, fork_exec2(argv, envp) == EOF);
1655+ unset(policy);
1656+
1657+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1658+ "0 deny envp[\"PATH\"]!=\"/\"\n"
1659+ "1 allow\n";
1660+ set(policy);
1661+ check(policy, fork_exec2(argv, envp) == 0);
1662+ unset(policy);
1663+
1664+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1665+ "0 deny envp[\"PATH\"]=\"/\"\n"
1666+ "1 allow\n";
1667+ set(policy);
1668+ check(policy, fork_exec2(argv, envp) == EOF);
1669+ unset(policy);
1670+
1671+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1672+ "0 allow envp[\"PATH\"]!=\"/\"\n"
1673+ "1 deny\n";
1674+ set(policy);
1675+ check(policy, fork_exec2(argv, envp) == EOF);
1676+ unset(policy);
1677+
1678+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1679+ "0 allow envp[\"PATH\"]=\"/\"\n"
1680+ "1 deny\n";
1681+ set(policy);
1682+ check(policy, fork_exec2(argv, envp) == 0);
1683+ unset(policy);
1684+
1685+ policy = "string_group PATH_VALUES " BINDIR "\n"
1686+ "string_group PATH_VALUES /\n"
1687+ "string_group PATH_VALUES /sbin\n"
1688+ "100 acl execute path=\"" BINDIR "/true\"\n"
1689+ "0 deny envp[\"PATH\"]!=@PATH_VALUES\n"
1690+ "1 allow\n";
1691+ set(policy);
1692+ check(policy, fork_exec2(argv, envp) == 0);
1693+ unset2(policy);
1694+
1695+ policy = "string_group PATH_VALUES " BINDIR "\n"
1696+ "string_group PATH_VALUES /\n"
1697+ "string_group PATH_VALUES /sbin\n"
1698+ "100 acl execute path=\"" BINDIR "/true\"\n"
1699+ "0 deny envp[\"PATH\"]=@PATH_VALUES\n"
1700+ "1 allow\n";
1701+ set(policy);
1702+ check(policy, fork_exec2(argv, envp) == EOF);
1703+ unset2(policy);
1704+
1705+ policy = "string_group PATH_VALUES " BINDIR "\n"
1706+ "string_group PATH_VALUES /\n"
1707+ "string_group PATH_VALUES /sbin\n"
1708+ "100 acl execute path=\"" BINDIR "/true\"\n"
1709+ "0 allow envp[\"PATH\"]!=@PATH_VALUES\n"
1710+ "1 deny\n";
1711+ set(policy);
1712+ check(policy, fork_exec2(argv, envp) == EOF);
1713+ unset2(policy);
1714+
1715+ policy = "string_group PATH_VALUES " BINDIR "\n"
1716+ "string_group PATH_VALUES /\n"
1717+ "string_group PATH_VALUES /sbin\n"
1718+ "100 acl execute path=\"" BINDIR "/true\"\n"
1719+ "0 allow envp[\"PATH\"]=@PATH_VALUES\n"
1720+ "1 deny\n";
1721+ set(policy);
1722+ check(policy, fork_exec2(argv, envp) == 0);
1723+ unset2(policy);
1724+
1725+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1726+ "0 deny envp[\"PATH\"]!=NULL\n"
1727+ "1 allow\n";
1728+ set(policy);
1729+ check(policy, fork_exec2(argv, envp) == EOF);
1730+ unset(policy);
1731+
1732+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1733+ "0 deny envp[\"PATH\"]=NULL\n"
1734+ "1 allow\n";
1735+ set(policy);
1736+ check(policy, fork_exec2(argv, envp) == 0);
1737+ unset(policy);
1738+
1739+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1740+ "0 allow envp[\"PATH\"]!=NULL\n"
1741+ "1 deny\n";
1742+ set(policy);
1743+ check(policy, fork_exec2(argv, envp) == 0);
1744+ unset(policy);
1745+
1746+ policy = "100 acl execute path=\"" BINDIR "/true\"\n"
1747+ "0 allow envp[\"PATH\"]=NULL\n"
1748+ "1 deny\n";
1749+ set(policy);
1750+ check(policy, fork_exec2(argv, envp) == EOF);
1751+ unset(policy);
1752+}
1753+
1754+static void test_file_misc(void)
1755+{
1756+ int fd;
1757+ const pid_t pid = getpid();
1758+ char buffer[1024];
1759+ memset(buffer, 0, sizeof(buffer));
1760+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1761+ "10 allow path!=NULL\n"
1762+ "20 deny\n", pid);
1763+ set(buffer);
1764+ fd = open("/dev/null", O_RDONLY);
1765+ check(buffer, fd != EOF);
1766+ close(fd);
1767+ unset(buffer);
1768+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1769+ "10 allow path=NULL\n"
1770+ "20 deny\n", pid);
1771+ set(buffer);
1772+ fd = open("/dev/null", O_RDONLY);
1773+ check(buffer, fd == EOF);
1774+ close(fd);
1775+ unset(buffer);
1776+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1777+ "10 deny path=NULL\n"
1778+ "20 allow\n", pid);
1779+ set(buffer);
1780+ fd = open("/dev/null", O_RDONLY);
1781+ check(buffer, fd != EOF);
1782+ close(fd);
1783+ unset(buffer);
1784+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1785+ "10 deny path!=NULL\n"
1786+ "20 allow\n", pid);
1787+ set(buffer);
1788+ fd = open("/dev/null", O_RDONLY);
1789+ check(buffer, fd == EOF);
1790+ close(fd);
1791+ unset(buffer);
1792+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1793+ "10 allow path=path\n"
1794+ "20 deny\n", pid);
1795+ set(buffer);
1796+ fd = open("/dev/null", O_RDONLY);
1797+ check(buffer, fd != EOF);
1798+ close(fd);
1799+ unset(buffer);
1800+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1801+ "10 allow path!=path\n"
1802+ "20 deny\n", pid);
1803+ set(buffer);
1804+ fd = open("/dev/null", O_RDONLY);
1805+ check(buffer, fd == EOF);
1806+ close(fd);
1807+ unset(buffer);
1808+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1809+ "10 deny path!=path\n"
1810+ "20 allow\n", pid);
1811+ set(buffer);
1812+ fd = open("/dev/null", O_RDONLY);
1813+ check(buffer, fd != EOF);
1814+ close(fd);
1815+ unset(buffer);
1816+ snprintf(buffer, sizeof(buffer) - 1, "100 acl read task.pid=%u\n"
1817+ "10 deny path=path\n"
1818+ "20 allow\n", pid);
1819+ set(buffer);
1820+ fd = open("/dev/null", O_RDONLY);
1821+ check(buffer, fd == EOF);
1822+ close(fd);
1823+ unset(buffer);
1824+ snprintf(buffer, sizeof(buffer) - 1,
1825+ "string_group STRING_GROUP1 /dev/null\n"
1826+ "100 acl read task.pid=%u\n"
1827+ "10 allow path=@STRING_GROUP1\n"
1828+ "20 deny\n", pid);
1829+ set(buffer);
1830+ fd = open("/dev/null", O_RDONLY);
1831+ check(buffer, fd != EOF);
1832+ close(fd);
1833+ unset2(buffer);
1834+ snprintf(buffer, sizeof(buffer) - 1,
1835+ "string_group STRING_GROUP1 /dev/null\n"
1836+ "100 acl read task.pid=%u\n"
1837+ "10 allow path!=@STRING_GROUP1\n"
1838+ "20 deny\n", pid);
1839+ set(buffer);
1840+ fd = open("/dev/null", O_RDONLY);
1841+ check(buffer, fd == EOF);
1842+ close(fd);
1843+ unset2(buffer);
1844+ snprintf(buffer, sizeof(buffer) - 1,
1845+ "string_group STRING_GROUP1 /dev/null\n"
1846+ "100 acl read task.pid=%u\n"
1847+ "10 deny path!=@STRING_GROUP1\n"
1848+ "20 allow\n", pid);
1849+ set(buffer);
1850+ fd = open("/dev/null", O_RDONLY);
1851+ check(buffer, fd != EOF);
1852+ close(fd);
1853+ unset2(buffer);
1854+ snprintf(buffer, sizeof(buffer) - 1,
1855+ "string_group STRING_GROUP1 /dev/null\n"
1856+ "100 acl read task.pid=%u\n"
1857+ "10 deny path=@STRING_GROUP1\n"
1858+ "20 allow\n", pid);
1859+ set(buffer);
1860+ fd = open("/dev/null", O_RDONLY);
1861+ check(buffer, fd == EOF);
1862+ close(fd);
1863+ unset2(buffer);
1864+ snprintf(buffer, sizeof(buffer) - 1,
1865+ "number_group NUMBER_GROUP1 0666\n"
1866+ "100 acl read task.pid=%u\n"
1867+ "10 deny path.perm!=@NUMBER_GROUP1\n"
1868+ "20 allow\n", pid);
1869+ set(buffer);
1870+ fd = open("/dev/null", O_RDONLY);
1871+ check(buffer, fd != EOF);
1872+ close(fd);
1873+ unset2(buffer);
1874+ snprintf(buffer, sizeof(buffer) - 1,
1875+ "number_group NUMBER_GROUP1 0666\n"
1876+ "100 acl read task.pid=%u\n"
1877+ "10 deny path.perm=@NUMBER_GROUP1\n"
1878+ "20 allow\n", pid);
1879+ set(buffer);
1880+ fd = open("/dev/null", O_RDONLY);
1881+ check(buffer, fd == EOF);
1882+ close(fd);
1883+ unset2(buffer);
1884+ snprintf(buffer, sizeof(buffer) - 1,
1885+ "100 acl read task.pid=%u\n"
1886+ "10 deny path.perm!=owner_read\n"
1887+ "20 allow\n", pid);
1888+ set(buffer);
1889+ fd = open("/dev/null", O_RDONLY);
1890+ check(buffer, fd != EOF);
1891+ close(fd);
1892+ unset2(buffer);
1893+ snprintf(buffer, sizeof(buffer) - 1,
1894+ "100 acl read task.pid=%u\n"
1895+ "10 deny path.perm=owner_read\n"
1896+ "20 allow\n", pid);
1897+ set(buffer);
1898+ fd = open("/dev/null", O_RDONLY);
1899+ check(buffer, fd == EOF);
1900+ close(fd);
1901+ unset2(buffer);
1902+ snprintf(buffer, sizeof(buffer) - 1,
1903+ "100 acl read task.pid=%u\n"
1904+ "10 deny path.perm!=group_write\n"
1905+ "20 allow\n", pid);
1906+ set(buffer);
1907+ fd = open("/dev/null", O_RDONLY);
1908+ check(buffer, fd != EOF);
1909+ close(fd);
1910+ unset2(buffer);
1911+ snprintf(buffer, sizeof(buffer) - 1,
1912+ "100 acl read task.pid=%u\n"
1913+ "10 deny path.perm=group_write\n"
1914+ "20 allow\n", pid);
1915+ set(buffer);
1916+ fd = open("/dev/null", O_RDONLY);
1917+ check(buffer, fd == EOF);
1918+ close(fd);
1919+ unset2(buffer);
1920+ snprintf(buffer, sizeof(buffer) - 1,
1921+ "100 acl read task.pid=%u\n"
1922+ "10 deny path.perm!=others_read\n"
1923+ "20 allow\n", pid);
1924+ set(buffer);
1925+ fd = open("/dev/null", O_RDONLY);
1926+ check(buffer, fd != EOF);
1927+ close(fd);
1928+ unset2(buffer);
1929+ snprintf(buffer, sizeof(buffer) - 1,
1930+ "100 acl read task.pid=%u\n"
1931+ "10 deny path.perm=others_read\n"
1932+ "20 allow\n", pid);
1933+ set(buffer);
1934+ fd = open("/dev/null", O_RDONLY);
1935+ check(buffer, fd == EOF);
1936+ close(fd);
1937+ unset2(buffer);
1938+ snprintf(buffer, sizeof(buffer) - 1,
1939+ "100 acl read task.pid=%u\n"
1940+ "10 deny path.perm=path.parent.perm\n"
1941+ "20 allow\n", pid);
1942+ set(buffer);
1943+ fd = open("/dev/null", O_RDONLY);
1944+ check(buffer, fd != EOF);
1945+ close(fd);
1946+ unset2(buffer);
1947+ snprintf(buffer, sizeof(buffer) - 1,
1948+ "100 acl read task.pid=%u\n"
1949+ "10 deny path.perm!=path.parent.perm\n"
1950+ "20 allow\n", pid);
1951+ set(buffer);
1952+ fd = open("/dev/null", O_RDONLY);
1953+ check(buffer, fd == EOF);
1954+ close(fd);
1955+ unset2(buffer);
1956+ snprintf(buffer, sizeof(buffer) - 1,
1957+ "100 acl execute task.ppid=%u\n"
1958+ "10 allow path=exec\n"
1959+ "20 deny\n", pid);
1960+ set(buffer);
1961+ check(buffer, fork_exec(NULL) == 0);
1962+ unset(buffer);
1963+ snprintf(buffer, sizeof(buffer) - 1,
1964+ "100 acl execute task.ppid=%u\n"
1965+ "10 allow path!=exec\n"
1966+ "20 deny\n", pid);
1967+ set(buffer);
1968+ check(buffer, fork_exec(NULL) == EOF);
1969+ unset(buffer);
1970+ snprintf(buffer, sizeof(buffer) - 1,
1971+ "100 acl execute task.ppid=%u\n"
1972+ "10 deny path=exec\n"
1973+ "20 allow\n", pid);
1974+ set(buffer);
1975+ check(buffer, fork_exec(NULL) == EOF);
1976+ unset(buffer);
1977+ snprintf(buffer, sizeof(buffer) - 1,
1978+ "100 acl execute task.ppid=%u\n"
1979+ "10 deny path!=exec\n"
1980+ "20 allow\n", pid);
1981+ set(buffer);
1982+ check(buffer, fork_exec(NULL) == 0);
1983+ unset(buffer);
1984+}
1985+
1986+static void reset_policy(void)
1987+{
1988+ FILE *fp2 = fopen(POLDIR "/policy", "r");
1989+ FILE *fp1 = fopen(POLDIR "/policy", "w");
1990+ if (!fp1 || !fp2) {
1991+ fprintf(stderr, " Can't open " POLDIR "/policy\n");
1992+ exit(1);
1993+ }
1994+ while (1) {
1995+ const int c = fgetc(fp2);
1996+ if (c == EOF)
1997+ break;
1998+ fputc(c, fp1);
1999+ if (c == '\n')
2000+ fprintf(fp1, "delete ");
2001+ }
2002+ fclose(fp2);
2003+ fclose(fp1);
2004+
2005+ /* Do not leave the init process in stopped state. */
2006+ kill(1, SIGCONT);
2007+
2008+ /* Undo mount("/", MS_REC|MS_SHARED) made by systemd. */
2009+ mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL);
2010+}
2011+
2012+int main(int argc, char *argv[])
2013+{
2014+ reset_policy();
2015+
2016+ fp = fopen(POLDIR "/policy", "w");
2017+ if (!fp) {
2018+ fprintf(stderr, " Can't open " POLDIR "/policy\n");
2019+ return 1;
2020+ }
2021+ fprintf(fp, "quota audit[0]"
2022+ " allowed=1024 unmatched=1024 denied=1024\n");
2023+ fflush(fp);
2024+
2025+ test_task_transition();
2026+ test_file_read();
2027+ test_file_write();
2028+ test_file_create();
2029+ test_file_unlink();
2030+ test_file_link();
2031+ test_file_rename();
2032+ test_network_inet_stream();
2033+ test_network_inet_dgram();
2034+ test_network_inet_raw();
2035+ test_network_inet6_stream();
2036+ test_network_inet6_dgram();
2037+ test_capability();
2038+ test_ptrace();
2039+ test_signal();
2040+ test_environ();
2041+ test_file_execute();
2042+ test_file_misc();
2043+ return 0;
2044+}
--- tags/caitsith-tools/0.2.2/kernel_test/caitsith_audit2cond_test.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/kernel_test/caitsith_audit2cond_test.c (revision 242)
@@ -0,0 +1,1339 @@
1+/*
2+ * caitsith_audit2cond_test.c
3+ *
4+ * Copyright (C) 2012-2013 Tetsuo Handa
5+ *
6+ * Version: 0.2 2016/10/05
7+ *
8+ * This program is free software; you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License v2 as published by the
10+ * Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful, but WITHOUT
13+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15+ * more details.
16+ *
17+ * You should have received a copy of the GNU General Public License along with
18+ * this program; if not, write to the Free Software Foundation, Inc.,
19+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20+ */
21+
22+#include <errno.h>
23+#include <fcntl.h>
24+#include <linux/ip.h>
25+#include <linux/kdev_t.h>
26+#include <linux/reboot.h>
27+#include <netinet/in.h>
28+#include <poll.h>
29+#include <pty.h>
30+#include <sched.h>
31+#include <stdio.h>
32+#include <stdlib.h>
33+#include <string.h>
34+#include <signal.h>
35+#include <sys/mount.h>
36+#include <sys/ptrace.h>
37+#include <sys/socket.h>
38+#include <sys/stat.h>
39+#include <sys/syscall.h>
40+#include <sys/timex.h>
41+#include <sys/types.h>
42+#include <sys/un.h>
43+#include <sys/wait.h>
44+#include <time.h>
45+#include <unistd.h>
46+#ifndef CLONE_NEWNS
47+#include <linux/sched.h>
48+#endif
49+#ifndef PRIO_PROCESS
50+#include <sys/resource.h>
51+#endif
52+#ifndef MS_REC
53+#define MS_REC 16384
54+#endif
55+#ifndef MS_PRIVATE
56+#define MS_PRIVATE (1 << 18)
57+#endif
58+int unshare(int flags);
59+int reboot(int cmd);
60+struct module;
61+int init_module(const char *name, struct module *image);
62+int delete_module(const char *name);
63+int pivot_root(const char *new_root, const char *put_old);
64+struct kexec_segment;
65+static inline long sys_kexec_load(unsigned long entry,
66+ unsigned long nr_segments,
67+ struct kexec_segment *segments,
68+ unsigned long flags)
69+{
70+ return (long) syscall(__NR_kexec_load, entry, nr_segments,
71+ segments, flags);
72+}
73+
74+static char *args[512];
75+static int audit_fd = EOF;
76+static int policy_fd = EOF;
77+static int one = 1;
78+
79+static const char *make_variable(const char *name, const unsigned int type)
80+{
81+ const char *cp = name + strlen(name) + 1;
82+ if (type == 0)
83+ return cp;
84+ if (*cp == '"') {
85+ /* Name variables. */
86+ if (type == 1)
87+ return "NULL";
88+ if (type == 2)
89+ return "!@EMPTY_NAME_GROUP";
90+ //if (type == 3)
91+ // return "task.exe"; // How can this match?
92+ } else if (!strcmp(name, "ip")) {
93+ /* IP address variables */
94+ if (type == 1)
95+ return "!@EMPTY_IP_GROUP";
96+ } else if (strstr(name, ".type")) {
97+ /* task.type or path.type */
98+ /* No variables supported. */
99+ } else {
100+ /* Numeric variables */
101+ const int zero = !strcmp(cp, "0") || !strcmp(cp, "00") ||
102+ !strcmp(cp, "0x0");
103+ if (type == 1)
104+ return "!@EMPTY_NUMBER_GROUP";
105+ if (type == 2)
106+ return "!@ZERO" + zero;
107+ if (type == 3)
108+ return "!task.uid" + zero;
109+ if (strstr(name, ".perm")) {
110+ unsigned int perm = 0;
111+ sscanf(cp, "%o", &perm);
112+ if (type == 4)
113+ return "!setuid" + ((perm & 04000) != 0);
114+ if (type == 5)
115+ return "!setgid" + ((perm & 02000) != 0);
116+ if (type == 6)
117+ return "!sticky" + ((perm & 01000) != 0);
118+ if (type == 7)
119+ return "!owner_read" + ((perm & 0400) != 0);
120+ if (type == 8)
121+ return "!owner_write" + ((perm & 0200) != 0);
122+ if (type == 9)
123+ return "!owner_execute" + ((perm & 0100) != 0);
124+ if (type == 10)
125+ return "!group_read" + ((perm & 040) != 0);
126+ if (type == 11)
127+ return "!group_write" + ((perm & 020) != 0);
128+ if (type == 12)
129+ return "!group_execute" + ((perm & 010) != 0);
130+ if (type == 13)
131+ return "!others_read" + ((perm & 04) != 0);
132+ if (type == 14)
133+ return "!others_write" + ((perm & 02) != 0);
134+ if (type == 15)
135+ return "!others_execute" + ((perm & 01) != 0);
136+ }
137+ }
138+ return NULL;
139+}
140+
141+static int make_policy(const char *action, const unsigned int loop,
142+ const int check, const int max)
143+{
144+ static char buffer[1048576];
145+ int pos;
146+ int i;
147+ const char *var = "";
148+ int not_equals = (loop & 1);
149+ if (max) {
150+ /* Nothing more to test if there is no more variables. */
151+ var = make_variable(args[check], loop >> 1);
152+ if (!var)
153+ return 0;
154+ /* NULL has inverse semantics. */
155+ if (!strcmp(var, "NULL"))
156+ not_equals = !not_equals;
157+ /* Handle other inversed conditions. */
158+ else if (*var == '!') {
159+ var++;
160+ not_equals = !not_equals;
161+ }
162+ }
163+ memset(buffer, 0, sizeof(buffer));
164+ pos = snprintf(buffer, sizeof(buffer) - 1, "0 acl %s task.ppid=%u\n"
165+ "\t0 allow", action, getpid());
166+ for (i = 0; i < max; i++) {
167+ /* Change only one argument at a time. */
168+ if (i != check)
169+ pos += snprintf(buffer + pos, sizeof(buffer) - 1 - pos,
170+ " %s=%s", args[i],
171+ args[i] + strlen(args[i]) + 1);
172+ else
173+ pos += snprintf(buffer + pos, sizeof(buffer) - 1 - pos,
174+ " %s%s=%s", args[i],
175+ not_equals ? "!" : "", var);
176+ }
177+ pos += snprintf(buffer + pos, sizeof(buffer) - 1 - pos, "\n"
178+ "\t1 deny\n");
179+ write(policy_fd, buffer, strlen(buffer));
180+ printf("Expecting %s: %s", (loop & 1) ? "denied" : "allowed",
181+ buffer);
182+ return 1;
183+}
184+
185+static int do_test(int (*func) (void))
186+{
187+ int error = 0;
188+ const pid_t pid = fork();
189+ switch (pid) {
190+ case 0:
191+ if (unshare(CLONE_NEWNS)) {
192+ fprintf(stderr, "***** Can't unshare.\n");
193+ _exit(1);
194+ }
195+ errno = 0;
196+ _exit(func());
197+ case -1:
198+ fprintf(stderr, "***** Can't fork.\n");
199+ return 1;
200+ }
201+ while (waitpid(pid, &error, 0) == EOF && errno == EINTR);
202+ return WIFEXITED(error) ? WEXITSTATUS(error) : -1;
203+}
204+
205+static int check_result(const char *action, int (*func) (void),
206+ const unsigned int loop)
207+{
208+ static char buffer[1048576];
209+ char *cp1;
210+ char *cp2;
211+ int retries = 0;
212+retry:
213+ do_test(func);
214+ memset(buffer, 0, sizeof(buffer));
215+ read(audit_fd, buffer, sizeof(buffer) - 1);
216+ cp1 = strchr(buffer, '\n');
217+ if (!cp1) {
218+ if (retries++ < 100)
219+ goto retry;
220+ fprintf(stderr, "***** Missing audit log for '%s': %s\n",
221+ action, buffer);
222+ return 1;
223+ }
224+ *cp1 = '\0';
225+ cp1 = strstr(buffer, " / ");
226+ if (!cp1) {
227+ fprintf(stderr, "***** Corrupted audit log for '%s': %s\n",
228+ action, buffer);
229+ return 1;
230+ }
231+ cp1 += 3;
232+ cp2 = strchr(cp1, ' ');
233+ if (!cp2) {
234+ fprintf(stderr, "***** Corrupted audit log for '%s': %s\n",
235+ action, buffer);
236+ return 1;
237+ }
238+ *cp2 = '\0';
239+ if (strcmp(cp1, action)) {
240+ if (retries++ < 100)
241+ goto retry;
242+ *cp2 = ' ';
243+ fprintf(stderr, "***** Unexpected audit log for '%s': %s\n",
244+ action, buffer);
245+ return 1;
246+ }
247+ *cp2 = ' ';
248+ if (!(loop & 1)) {
249+ if (!strstr(buffer, " result=allowed ")) {
250+ fprintf(stderr, "***** result=allowed expected: %s\n",
251+ buffer);
252+ exit(1);
253+ return 1;
254+ }
255+ } else {
256+ if (!strstr(buffer, " result=denied ")) {
257+ fprintf(stderr, "***** result=denied expected: %s\n",
258+ buffer);
259+ exit(1);
260+ return 1;
261+ }
262+ }
263+ snprintf(buffer, sizeof(buffer) - 1, "delete 0 acl %s task.ppid=%u\n",
264+ action, getpid());
265+ write(policy_fd, buffer, strlen(buffer));
266+ while (read(audit_fd, buffer, sizeof(buffer) - 1) > 0);
267+ return 0;
268+}
269+
270+static void test_action(const char *action, int (*func) (void))
271+{
272+ static char buffer[1048576];
273+ int pos;
274+ int i;
275+ char *cp1;
276+ char *cp2;
277+ int retries = 0;
278+ memset(args, 0, sizeof(args));
279+ make_policy(action, 0, 0, 0);
280+retry:
281+ do_test(func);
282+ memset(buffer, 0, sizeof(buffer));
283+ read(audit_fd, buffer, sizeof(buffer) - 1);
284+ cp1 = strchr(buffer, '\n');
285+ if (!cp1) {
286+ if (retries++ < 100)
287+ goto retry;
288+ fprintf(stderr, "+++++ Missing audit log for '%s': %s\n",
289+ action, buffer);
290+ return;
291+ }
292+ *cp1 = '\0';
293+ cp1 = strstr(buffer, " / ");
294+ if (!cp1) {
295+ fprintf(stderr, "+++++ Corrupted audit log for '%s': %s\n",
296+ action, buffer);
297+ return;
298+ }
299+ cp1 += 3;
300+ cp2 = strchr(cp1, ' ');
301+ if (!cp2) {
302+ fprintf(stderr, "+++++ Corrupted audit log for '%s': %s\n",
303+ action, buffer);
304+ return;
305+ }
306+ *cp2++ = '\0';
307+ if (strcmp(cp1, action)) {
308+ if (retries++ < 100)
309+ goto retry;
310+ fprintf(stderr, "+++++ Unexpected audit log for '%s': %s\n",
311+ action, cp1);
312+ return;
313+ }
314+ cp1 = cp2;
315+ pos = 0;
316+ while (pos < (sizeof(args) / sizeof(args[0]))) {
317+ char *cp3;
318+ args[pos++] = cp1;
319+ cp2 = strchr(cp1, ' ');
320+ if (cp2)
321+ *cp2++ = '\0';
322+ cp3 = strchr(cp1, '=');
323+ if (!cp3 || !*(cp3 + 1)) {
324+ fprintf(stderr, "+++++ Corrupted audit log.\n");
325+ return;
326+ }
327+ *cp3 = '\0';
328+ /*
329+ * Ignore task.pid which cannot be matched due to tesing under
330+ * fork()ed process.
331+ */
332+ if (!strcmp(cp1, "task.pid"))
333+ pos--;
334+ /*
335+ * Ignore .ino which might change for each test.
336+ */
337+ else if (strstr(cp1, ".ino"))
338+ pos--;
339+ /*
340+ * Ignore .minor which might change for each test.
341+ */
342+ else if (strstr(cp1, ".minor"))
343+ pos--;
344+ cp1 = cp2;
345+ if (!cp1)
346+ break;
347+ }
348+ if (pos == (sizeof(args) / sizeof(args[0]))) {
349+ fprintf(stderr, "+++++ Line too long.\n");
350+ return;
351+ }
352+ {
353+ static char buffer2[1024];
354+ while (read(audit_fd, buffer2, sizeof(buffer2)) > 0);
355+ }
356+ for (i = 0; i < pos; i++) {
357+ unsigned int loop;
358+ for (loop = 0; make_policy(action, loop, i, pos); loop++)
359+ check_result(action, func, loop);
360+ }
361+ return;
362+}
363+
364+static void startup(void)
365+{
366+ int pipe_fd[2] = { EOF, EOF };
367+ static char buffer[1048576];
368+ FILE *fp = fopen(POLDIR "/policy", "r");
369+ policy_fd = open(POLDIR "/policy", O_WRONLY);
370+ audit_fd = open(POLDIR "/audit", O_RDONLY);
371+ if (!fp || policy_fd == EOF || audit_fd == EOF) {
372+ fprintf(stderr,
373+ "***** Can't open " POLDIR "/ interface.\n");
374+ exit(1);
375+ }
376+ if (pipe(pipe_fd)) {
377+ fprintf(stderr, "***** Can't pipe.\n");
378+ exit(1);
379+ }
380+ mkdir("/tmp/caitsith.tmp", 0700);
381+ if (chown("/tmp/caitsith.tmp", 0, 0) ||
382+ chmod("/tmp/caitsith.tmp", 0700)) {
383+ fprintf(stderr, "***** Can't chown/chmod.\n");
384+ exit(1);
385+ }
386+ while (memset(buffer, 0, sizeof(buffer)),
387+ fgets(buffer, sizeof(buffer) - 1, fp)) {
388+ if (!strchr(buffer, '\n')) {
389+ fprintf(stderr, "***** Line too long.\n");
390+ exit(1);
391+ }
392+ write(policy_fd, "delete ", 7);
393+ write(policy_fd, buffer, strlen(buffer));
394+ }
395+ fclose(fp);
396+ {
397+ const char *config = "quota Memory used by audit: 1048576\n"
398+ "quota audit[0] allowed=1024 denied=1024 "
399+ "unmatched=1024\n" "number_group ZERO 0\n";
400+ write(policy_fd, config, strlen(config));
401+ }
402+ while (read(audit_fd, buffer, sizeof(buffer)) > 0);
403+ switch (fork()) {
404+ int fd;
405+ case 0:
406+ close(policy_fd);
407+ close(audit_fd);
408+ close(pipe_fd[1]);
409+ fd = open(POLDIR "/query", O_RDWR);
410+ while (1) {
411+ unsigned int serial;
412+ unsigned int retry;
413+ struct pollfd pfd[2] = {
414+ { fd, POLLIN, 0 },
415+ { pipe_fd[0], POLLIN, 0 }
416+ };
417+ poll(pfd, 2, -1);
418+ if (pfd[0].revents & POLLIN)
419+ break;
420+ if (read(fd, buffer, sizeof(buffer) - 1) <= 0)
421+ continue;
422+ if (sscanf(buffer, "Q%u-%u", &serial, &retry) != 2) {
423+ fprintf(stderr, "***** Corrupted query: %s\n",
424+ buffer);
425+ break;
426+ }
427+ snprintf(buffer, sizeof(buffer) - 1, "A%u=%u\n",
428+ serial,
429+ retry < 5 ? 3 /* Retry */ : 2 /* No */);
430+ write(fd, buffer, strlen(buffer));
431+ }
432+ _exit(0);
433+ case -1:
434+ fprintf(stderr, "***** Can't fork.\n");
435+ exit(1);
436+ }
437+ close(pipe_fd[0]);
438+}
439+
440+static int test_execute(void)
441+{
442+ execlp(BINDIR "/true", "true", NULL);
443+ return errno;
444+}
445+
446+static int test_read(void)
447+{
448+ open("/dev/null", O_RDONLY);
449+ return errno;
450+}
451+
452+static int test_write(void)
453+{
454+ open("/dev/null", O_WRONLY);
455+ return errno;
456+}
457+
458+static int test_create_no_append(void)
459+{
460+ int err;
461+ open("/tmp/caitsith.tmp/file", O_CREAT | O_RDWR | O_TRUNC, 0600);
462+ err = errno;
463+ unlink("/tmp/caitsith.tmp/file");
464+ return err;
465+}
466+
467+static int test_create_append(void)
468+{
469+ int err;
470+ open("/tmp/caitsith.tmp/file", O_CREAT | O_RDWR | O_TRUNC | O_APPEND,
471+ 0600);
472+ err = errno;
473+ unlink("/tmp/caitsith.tmp/file");
474+ return err;
475+}
476+
477+static int test_fcntl_clear_append(void)
478+{
479+ const int fd = open("/dev/null", O_WRONLY | O_APPEND);
480+ const int flags = fcntl(fd, F_GETFL);
481+ errno = 0;
482+ fcntl(fd, F_SETFL, flags & ~O_APPEND);
483+ return errno;
484+}
485+
486+static int test_fcntl_set_append(void)
487+{
488+ const int fd = open("/dev/null", O_WRONLY);
489+ const int flags = fcntl(fd, F_GETFL);
490+ errno = 0;
491+ fcntl(fd, F_SETFL, flags | O_APPEND);
492+ return errno;
493+}
494+
495+static int test_unlink(void)
496+{
497+ mknod("/tmp/caitsith.tmp/file", S_IFREG | 0600, 0);
498+ errno = 0;
499+ unlink("/tmp/caitsith.tmp/file");
500+ return errno;
501+}
502+
503+static int test_getattr(void)
504+{
505+ struct stat buf;
506+ stat("/dev/null", &buf);
507+ return errno;
508+}
509+
510+static int test_mkdir(void)
511+{
512+ int err;
513+ mkdir("/tmp/caitsith.tmp/dir", 0755);
514+ err = errno;
515+ rmdir("/tmp/caitsith.tmp/dir");
516+ return err;
517+}
518+
519+static int test_rmdir(void)
520+{
521+ mkdir("/tmp/caitsith.tmp/dir", 0755);
522+ errno = 0;
523+ rmdir("/tmp/caitsith.tmp/dir");
524+ return errno;
525+}
526+
527+static int test_mkfifo(void)
528+{
529+ int err;
530+ mknod("/tmp/caitsith.tmp/fifo", S_IFIFO | 0600, 0);
531+ err = errno;
532+ unlink("/tmp/caitsith.tmp/fifo");
533+ return err;
534+}
535+
536+static int test_mksock_by_mknod(void)
537+{
538+ int err;
539+ mknod("/tmp/caitsith.tmp/sock", S_IFSOCK | 0600, 0);
540+ err = errno;
541+ unlink("/tmp/caitsith.tmp/sock");
542+ return err;
543+}
544+
545+static int test_mksock_by_bind(void)
546+{
547+ struct sockaddr_un addr;
548+ int err;
549+ int fd = socket(PF_UNIX, SOCK_STREAM, 0);
550+ memset(&addr, 0, sizeof(addr));
551+ addr.sun_family = AF_UNIX;
552+ snprintf(addr.sun_path, sizeof(addr.sun_path) - 1,
553+ "/tmp/caitsith.tmp/sock");
554+ errno = 0;
555+ bind(fd, (struct sockaddr *) &addr, sizeof(addr));
556+ err = errno;
557+ unlink(addr.sun_path);
558+ return err;
559+}
560+
561+static int test_truncate(void)
562+{
563+ mknod("/tmp/caitsith.tmp/truncate", S_IFREG | 0600, 0);
564+ errno = 0;
565+ truncate("/tmp/caitsith.tmp/truncate", 0);
566+ return errno;
567+}
568+
569+static int test_symlink(void)
570+{
571+ int err;
572+ symlink(".", "/tmp/caitsith.tmp/symlink");
573+ err = errno;
574+ unlink("/tmp/caitsith.tmp/symlink");
575+ return err;
576+}
577+
578+static int test_mkchar(void)
579+{
580+ int err;
581+ mknod("/tmp/caitsith.tmp/char", S_IFCHR | 0600, MKDEV(1, 3));
582+ err = errno;
583+ unlink("/tmp/caitsith.tmp/char");
584+ return err;
585+}
586+
587+static int test_mkblock(void)
588+{
589+ int err;
590+ mknod("/tmp/caitsith.tmp/block", S_IFBLK | 0600, MKDEV(1, 0));
591+ err = errno;
592+ unlink("/tmp/caitsith.tmp/block");
593+ return err;
594+}
595+
596+static int test_link(void)
597+{
598+ int err;
599+ mknod("/tmp/caitsith.tmp/old_path", S_IFREG | 0600, 0);
600+ errno = 0;
601+ link("/tmp/caitsith.tmp/old_path", "/tmp/caitsith.tmp/new_path");
602+ err = errno;
603+ unlink("/tmp/caitsith.tmp/old_path");
604+ unlink("/tmp/caitsith.tmp/new_path");
605+ return err;
606+}
607+
608+static int test_rename(void)
609+{
610+ int err;
611+ mknod("/tmp/caitsith.tmp/old_path", S_IFREG | 0600, 0);
612+ errno = 0;
613+ rename("/tmp/caitsith.tmp/old_path", "/tmp/caitsith.tmp/new_path");
614+ err = errno;
615+ unlink("/tmp/caitsith.tmp/old_path");
616+ unlink("/tmp/caitsith.tmp/new_path");
617+ return err;
618+}
619+
620+static int test_chmod(void)
621+{
622+ chmod("/dev/null", 0666);
623+ return errno;
624+}
625+
626+static int test_chown(void)
627+{
628+ chown("/dev/null", 0, -1);
629+ return errno;
630+}
631+
632+static int test_chgrp(void)
633+{
634+ chown("/dev/null", -1, 0);
635+ return errno;
636+}
637+
638+static int test_ioctl(void)
639+{
640+ const int fd = open("/dev/null", O_WRONLY);
641+ errno = 0;
642+ ioctl(fd, 0, 0);
643+ return errno;
644+}
645+
646+static int test_chroot(void)
647+{
648+ chroot("/tmp/caitsith.tmp");
649+ return errno;
650+}
651+
652+static int test_mount(void)
653+{
654+ mount(NULL, "/tmp/caitsith.tmp", "tmpfs", 0, NULL);
655+ return errno;
656+}
657+
658+static int test_unmount(void)
659+{
660+ mount(NULL, "/tmp/caitsith.tmp", "tmpfs", 0, NULL);
661+ errno = 0;
662+ umount("/tmp/caitsith.tmp");
663+ return errno;
664+}
665+
666+static int test_pivot_root(void)
667+{
668+ errno = 0;
669+ pivot_root("/sys/kernel/security/", "/sys/kernel/security/caitsith/");
670+ if (errno == ENOENT) {
671+ errno = 0;
672+ pivot_root("/proc/", "/proc/caitsith/");
673+ }
674+ return errno;
675+}
676+
677+static void inet_bind(const int fd, const unsigned short int port)
678+{
679+ struct sockaddr_in addr = { };
680+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
681+ addr.sin_family = AF_INET;
682+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
683+ addr.sin_port = htons(port);
684+ bind(fd, (struct sockaddr *) &addr, sizeof(addr));
685+}
686+
687+static int test_inet_stream_bind(void)
688+{
689+ int fd = socket(PF_INET, SOCK_STREAM, 0);
690+ struct sockaddr_in addr = { };
691+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
692+ addr.sin_family = AF_INET;
693+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
694+ addr.sin_port = htons(10000);
695+ errno = 0;
696+ bind(fd, (struct sockaddr *) &addr, sizeof(addr));
697+ return errno;
698+}
699+
700+static int test_inet_stream_listen(void)
701+{
702+ int fd = socket(PF_INET, SOCK_STREAM, 0);
703+ inet_bind(fd, 10000);
704+ errno = 0;
705+ listen(fd, 5);
706+ return errno;
707+}
708+
709+static int test_inet_stream_connect(void)
710+{
711+ int fd1 = socket(PF_INET, SOCK_STREAM, 0);
712+ int fd2 = socket(PF_INET, SOCK_STREAM, 0);
713+ struct sockaddr_in addr = { };
714+ socklen_t size = sizeof(addr);
715+ inet_bind(fd1, 10000);
716+ listen(fd1, 0);
717+ inet_bind(fd2, 10001);
718+ getsockname(fd1, (struct sockaddr *) &addr, &size);
719+ errno = 0;
720+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
721+ return errno;
722+}
723+
724+static int test_inet_stream_accept(void)
725+{
726+ int fd1 = socket(PF_INET, SOCK_STREAM, 0);
727+ int fd2 = socket(PF_INET, SOCK_STREAM, 0);
728+ struct sockaddr_in addr = { };
729+ socklen_t size = sizeof(addr);
730+ inet_bind(fd1, 10000);
731+ listen(fd1, 0);
732+ inet_bind(fd2, 10001);
733+ getsockname(fd1, (struct sockaddr *) &addr, &size);
734+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
735+ errno = 0;
736+ accept(fd1, (struct sockaddr *) &addr, &size);
737+ return errno;
738+}
739+
740+static int test_inet_dgram_bind(void)
741+{
742+ int fd = socket(PF_INET, SOCK_DGRAM, 0);
743+ struct sockaddr_in addr = { };
744+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
745+ addr.sin_family = AF_INET;
746+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
747+ addr.sin_port = htons(10000);
748+ errno = 0;
749+ bind(fd, (struct sockaddr *) &addr, sizeof(addr));
750+ return errno;
751+}
752+
753+static int test_inet_dgram_connect(void)
754+{
755+ int fd1 = socket(PF_INET, SOCK_DGRAM, 0);
756+ int fd2 = socket(PF_INET, SOCK_DGRAM, 0);
757+ struct sockaddr_in addr = { };
758+ socklen_t size = sizeof(addr);
759+ inet_bind(fd1, 10000);
760+ inet_bind(fd2, 10001);
761+ getsockname(fd1, (struct sockaddr *) &addr, &size);
762+ errno = 0;
763+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
764+ return errno;
765+}
766+
767+static int test_inet_dgram_send(void)
768+{
769+ int fd1 = socket(PF_INET, SOCK_DGRAM, 0);
770+ int fd2 = socket(PF_INET, SOCK_DGRAM, 0);
771+ struct sockaddr_in addr = { };
772+ socklen_t size = sizeof(addr);
773+ inet_bind(fd1, 10000);
774+ inet_bind(fd2, 10001);
775+ getsockname(fd1, (struct sockaddr *) &addr, &size);
776+ errno = 0;
777+ sendto(fd2, "", 1, 0, (struct sockaddr *) &addr, sizeof(addr));
778+ return errno;
779+}
780+
781+static int test_inet_dgram_recv(void)
782+{
783+ int fd1 = socket(PF_INET, SOCK_DGRAM, 0);
784+ int fd2 = socket(PF_INET, SOCK_DGRAM, 0);
785+ char c;
786+ struct sockaddr_in addr = { };
787+ socklen_t size = sizeof(addr);
788+ inet_bind(fd1, 10000);
789+ inet_bind(fd2, 10001);
790+ getsockname(fd1, (struct sockaddr *) &addr, &size);
791+ sendto(fd2, "", 1, 0, (struct sockaddr *) &addr, sizeof(addr));
792+ errno = 0;
793+ recvfrom(fd1, &c, 1, MSG_DONTWAIT, (struct sockaddr *) &addr, &size);
794+ return errno;
795+}
796+
797+static int test_inet_raw_bind(void)
798+{
799+ int fd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
800+ struct sockaddr_in addr = { };
801+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
802+ addr.sin_family = AF_INET;
803+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
804+ addr.sin_port = htons(10000);
805+ errno = 0;
806+ bind(fd, (struct sockaddr *) &addr, sizeof(addr));
807+ return errno;
808+}
809+
810+static int test_inet_raw_connect(void)
811+{
812+ int fd1 = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
813+ int fd2 = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
814+ struct sockaddr_in addr = { };
815+ socklen_t size = sizeof(addr);
816+ inet_bind(fd1, 10000);
817+ inet_bind(fd2, 10001);
818+ getsockname(fd1, (struct sockaddr *) &addr, &size);
819+ errno = 0;
820+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
821+ return errno;
822+}
823+
824+static int test_inet_raw_send(void)
825+{
826+ int fd1 = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
827+ int fd2 = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
828+ struct sockaddr_in addr = { };
829+ socklen_t size = sizeof(addr);
830+ static struct iphdr ip = { };
831+ inet_bind(fd1, 10000);
832+ inet_bind(fd2, 10001);
833+ getsockname(fd1, (struct sockaddr *) &addr, &size);
834+ ip.version = 4;
835+ ip.ihl = sizeof(struct iphdr) / 4;
836+ ip.protocol = IPPROTO_RAW;
837+ ip.daddr = htonl(INADDR_LOOPBACK);
838+ ip.saddr = ip.daddr;
839+ errno = 0;
840+ sendto(fd2, &ip, sizeof(ip), 0, (struct sockaddr *) &addr,
841+ sizeof(addr));
842+ return errno;
843+}
844+
845+static int test_inet_raw_recv(void)
846+{
847+ int fd1 = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
848+ int fd2 = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
849+ struct sockaddr_in addr = { };
850+ socklen_t size = sizeof(addr);
851+ static struct iphdr ip = { };
852+ inet_bind(fd1, 10000);
853+ inet_bind(fd2, 10000);
854+ getsockname(fd1, (struct sockaddr *) &addr, &size);
855+ ip.version = 4;
856+ ip.ihl = sizeof(struct iphdr) / 4;
857+ ip.protocol = IPPROTO_RAW;
858+ ip.daddr = htonl(INADDR_LOOPBACK);
859+ ip.saddr = ip.daddr;
860+ sendto(fd2, &ip, sizeof(ip), 0, (struct sockaddr *) &addr,
861+ sizeof(addr));
862+ errno = 0;
863+ recvfrom(fd1, &ip, sizeof(ip), MSG_DONTWAIT, (struct sockaddr *) &addr,
864+ &size);
865+ return errno;
866+}
867+
868+static void unix_bind(const int fd, const _Bool listener)
869+{
870+ struct sockaddr_un addr = { };
871+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
872+ addr.sun_family = AF_UNIX;
873+ snprintf(addr.sun_path, sizeof(addr.sun_path) - 1,
874+ "/tmp/caitsith.tmp/%s", listener ? "server" : "client");
875+ unlink(addr.sun_path);
876+ bind(fd, (struct sockaddr *) &addr, sizeof(addr));
877+}
878+
879+static int test_unix_stream_bind(void)
880+{
881+ int fd = socket(PF_UNIX, SOCK_STREAM, 0);
882+ struct sockaddr_un addr = { };
883+ addr.sun_family = AF_UNIX;
884+ errno = 0;
885+ bind(fd, (struct sockaddr *) &addr, sizeof(addr.sun_family));
886+ return errno;
887+}
888+
889+static int test_unix_stream_listen(void)
890+{
891+ int fd = socket(PF_UNIX, SOCK_STREAM, 0);
892+ unix_bind(fd, 1);
893+ errno = 0;
894+ listen(fd, 5);
895+ return errno;
896+}
897+
898+static int test_unix_stream_connect(void)
899+{
900+ int fd1 = socket(PF_UNIX, SOCK_STREAM, 0);
901+ int fd2 = socket(PF_UNIX, SOCK_STREAM, 0);
902+ struct sockaddr_un addr = { };
903+ socklen_t size = sizeof(addr);
904+ unix_bind(fd1, 1);
905+ unix_bind(fd2, 0);
906+ listen(fd1, 0);
907+ getsockname(fd1, (struct sockaddr *) &addr, &size);
908+ errno = 0;
909+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
910+ return errno;
911+}
912+
913+static int test_unix_stream_accept(void)
914+{
915+ int fd1 = socket(PF_UNIX, SOCK_STREAM, 0);
916+ int fd2 = socket(PF_UNIX, SOCK_STREAM, 0);
917+ struct sockaddr_un addr = { };
918+ socklen_t size = sizeof(addr);
919+ unix_bind(fd1, 1);
920+ unix_bind(fd2, 0);
921+ listen(fd1, 0);
922+ getsockname(fd1, (struct sockaddr *) &addr, &size);
923+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
924+ errno = 0;
925+ accept(fd1, (struct sockaddr *) &addr, &size);
926+ return errno;
927+}
928+
929+static int test_unix_dgram_bind(void)
930+{
931+ int fd = socket(PF_UNIX, SOCK_DGRAM, 0);
932+ int err;
933+ struct sockaddr_un addr = { };
934+ addr.sun_family = AF_UNIX;
935+ errno = 0;
936+ bind(fd, (struct sockaddr *) &addr, sizeof(addr));
937+ err = errno;
938+ close(fd);
939+ return err;
940+}
941+
942+static int test_unix_dgram_connect(void)
943+{
944+ int fd1 = socket(PF_UNIX, SOCK_DGRAM, 0);
945+ int fd2 = socket(PF_UNIX, SOCK_DGRAM, 0);
946+ int err;
947+ struct sockaddr_un addr = { };
948+ socklen_t size = sizeof(addr);
949+ unix_bind(fd1, 1);
950+ unix_bind(fd2, 0);
951+ getsockname(fd1, (struct sockaddr *) &addr, &size);
952+ errno = 0;
953+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
954+ err = errno;
955+ close(fd1);
956+ close(fd2);
957+ return err;
958+}
959+
960+static int test_unix_dgram_send(void)
961+{
962+ int fd1 = socket(PF_UNIX, SOCK_DGRAM, 0);
963+ int fd2 = socket(PF_UNIX, SOCK_DGRAM, 0);
964+ int err;
965+ struct sockaddr_un addr = { };
966+ socklen_t size = sizeof(addr);
967+ unix_bind(fd1, 1);
968+ unix_bind(fd2, 0);
969+ getsockname(fd1, (struct sockaddr *) &addr, &size);
970+ errno = 0;
971+ sendto(fd2, "", 1, 0, (struct sockaddr *) &addr, sizeof(addr));
972+ err = errno;
973+ close(fd1);
974+ close(fd2);
975+ return err;
976+}
977+
978+static int test_unix_dgram_recv(void)
979+{
980+ int fd1 = socket(PF_UNIX, SOCK_DGRAM, 0);
981+ int fd2 = socket(PF_UNIX, SOCK_DGRAM, 0);
982+ int err;
983+ char c;
984+ struct sockaddr_un addr = { };
985+ socklen_t size = sizeof(addr);
986+ unix_bind(fd1, 1);
987+ unix_bind(fd2, 0);
988+ getsockname(fd1, (struct sockaddr *) &addr, &size);
989+ sendto(fd2, "", 1, 0, (struct sockaddr *) &addr, sizeof(addr));
990+ errno = 0;
991+ recvfrom(fd1, &c, 1, MSG_DONTWAIT, (struct sockaddr *) &addr, &size);
992+ err = errno;
993+ close(fd1);
994+ close(fd2);
995+ return err;
996+}
997+
998+static int test_unix_seqpacket_bind(void)
999+{
1000+ int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1001+ int err;
1002+ struct sockaddr_un addr = { };
1003+ addr.sun_family = AF_UNIX;
1004+ errno = 0;
1005+ bind(fd, (struct sockaddr *) &addr, sizeof(addr.sun_family));
1006+ err = errno;
1007+ close(fd);
1008+ return err;
1009+}
1010+
1011+static int test_unix_seqpacket_listen(void)
1012+{
1013+ int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1014+ int err;
1015+ unix_bind(fd, 1);
1016+ errno = 0;
1017+ listen(fd, 5);
1018+ err = errno;
1019+ close(fd);
1020+ return err;
1021+}
1022+
1023+static int test_unix_seqpacket_connect(void)
1024+{
1025+ int fd1 = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1026+ int fd2 = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1027+ int err;
1028+ struct sockaddr_un addr = { };
1029+ socklen_t size = sizeof(addr);
1030+ unix_bind(fd1, 1);
1031+ unix_bind(fd2, 0);
1032+ listen(fd1, 0);
1033+ getsockname(fd1, (struct sockaddr *) &addr, &size);
1034+ errno = 0;
1035+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
1036+ err = errno;
1037+ close(fd1);
1038+ close(fd2);
1039+ return err;
1040+}
1041+
1042+static int test_unix_seqpacket_accept(void)
1043+{
1044+ int fd1 = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1045+ int fd2 = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1046+ struct sockaddr_un addr = { };
1047+ socklen_t size = sizeof(addr);
1048+ unix_bind(fd1, 1);
1049+ unix_bind(fd2, 0);
1050+ listen(fd1, 0);
1051+ getsockname(fd1, (struct sockaddr *) &addr, &size);
1052+ connect(fd2, (struct sockaddr *) &addr, sizeof(addr));
1053+ errno = 0;
1054+ accept(fd1, (struct sockaddr *) &addr, &size);
1055+ return errno;
1056+}
1057+
1058+static int test_environ(void)
1059+{
1060+ char * const argv[2] = { "true", NULL };
1061+ char * const envp[2] = { "HOME=/", NULL };
1062+ execve(BINDIR "/true", argv, envp);
1063+ return errno;
1064+}
1065+
1066+static int test_ptrace(void)
1067+{
1068+ ptrace(PTRACE_ATTACH, 1, NULL, NULL);
1069+ return errno;
1070+}
1071+
1072+static int test_signal(void)
1073+{
1074+ kill(1, 1);
1075+ return errno;
1076+}
1077+
1078+static int test_modify_policy(void)
1079+{
1080+ const char *policy = "1 acl modify_policy\n";
1081+ /*
1082+ * Try to execute a non-executable in order to clear cached policy
1083+ * manager attribute.
1084+ */
1085+ const int fd = open("/tmp/caitsith.tmp/exec",
1086+ O_CREAT | O_TRUNC | O_WRONLY, 0600);
1087+ fchmod(fd, 0700);
1088+ close(fd);
1089+ execl("/tmp/caitsith.tmp/exec", "exec", NULL);
1090+ /* Now policy manager attribute was cleared. */
1091+ errno = 0;
1092+ write(policy_fd, policy, strlen(policy));
1093+ return errno;
1094+}
1095+
1096+static int test_use_netlink_socket(void)
1097+{
1098+ const int fd = socket(AF_ROUTE, SOCK_RAW, 0);
1099+ const int err = errno;
1100+ close(fd);
1101+ return err;
1102+}
1103+
1104+static int test_use_packet_socket(void)
1105+{
1106+ const int fd = socket(AF_PACKET, SOCK_RAW, 0);
1107+ const int err = errno;
1108+ close(fd);
1109+ return err;
1110+}
1111+
1112+static int test_use_reboot(void)
1113+{
1114+ FILE *fp = fopen("/proc/sys/kernel/ctrl-alt-del", "a+");
1115+ unsigned int c;
1116+ int err;
1117+ if (fp && fscanf(fp, "%u", &c) == 1) {
1118+ errno = 0;
1119+ reboot(LINUX_REBOOT_CMD_CAD_ON);
1120+ err = errno;
1121+ rewind(fp);
1122+ fprintf(fp, "%u\n", c);
1123+ } else {
1124+ errno = 0;
1125+ /* Use invalid value */
1126+ reboot(0x0000C0DE);
1127+ err = errno;
1128+ }
1129+ if (fp)
1130+ fclose(fp);
1131+ return err;
1132+}
1133+
1134+static int test_use_vhangup(void)
1135+{
1136+ setsid();
1137+ errno = 0;
1138+ vhangup();
1139+ return errno;
1140+}
1141+
1142+static int test_set_time_by_stime(void)
1143+{
1144+ const time_t now = time(NULL);
1145+ errno = 0;
1146+ stime(&now);
1147+ return errno;
1148+}
1149+
1150+static int test_set_time_by_settimeofday(void)
1151+{
1152+ struct timeval tv;
1153+ struct timezone tz;
1154+ gettimeofday(&tv, &tz);
1155+ errno = 0;
1156+ settimeofday(&tv, &tz);
1157+ return errno;
1158+}
1159+
1160+static int test_set_time_by_adjtimex(void)
1161+{
1162+ struct timex buf = { };
1163+ buf.modes = 0x100; /* Use invalid value so that the clock
1164+ won't change. */
1165+ adjtimex(&buf);
1166+ return errno;
1167+}
1168+
1169+static int test_set_priority_by_nice(void)
1170+{
1171+ nice(0);
1172+ return errno;
1173+}
1174+
1175+static int test_set_priority_by_setpriority(void)
1176+{
1177+ const int priority = getpriority(PRIO_PROCESS, getpid());
1178+ errno = 0;
1179+ setpriority(PRIO_PROCESS, getpid(), priority);
1180+ return errno;
1181+}
1182+
1183+static int test_set_hostname_by_sethostname(void)
1184+{
1185+ char buffer[4096] = { };
1186+ gethostname(buffer, sizeof(buffer) - 1);
1187+ errno = 0;
1188+ sethostname(buffer, strlen(buffer));
1189+ return errno;
1190+}
1191+
1192+static int test_set_hostname_by_setdomainname(void)
1193+{
1194+ char buffer[4096] = { };
1195+ getdomainname(buffer, sizeof(buffer) - 1);
1196+ errno = 0;
1197+ setdomainname(buffer, strlen(buffer));
1198+ return errno;
1199+}
1200+
1201+static int test_use_kernel_module_by_init_module(void)
1202+{
1203+ init_module("", NULL);
1204+ return errno;
1205+}
1206+
1207+static int test_use_kernel_module_by_delete_module(void)
1208+{
1209+ delete_module("");
1210+ return errno;
1211+}
1212+
1213+static int test_use_new_kernel(void)
1214+{
1215+ sys_kexec_load(0, 0, NULL, 0);
1216+ return errno;
1217+}
1218+
1219+static void reset_policy(void)
1220+{
1221+ FILE *fp2 = fopen(POLDIR "/policy", "r");
1222+ FILE *fp1 = fopen(POLDIR "/policy", "w");
1223+ if (!fp1 || !fp2) {
1224+ fprintf(stderr, " Can't open " POLDIR "/policy\n");
1225+ exit(1);
1226+ }
1227+ while (1) {
1228+ const int c = fgetc(fp2);
1229+ if (c == EOF)
1230+ break;
1231+ fputc(c, fp1);
1232+ if (c == '\n')
1233+ fprintf(fp1, "delete ");
1234+ }
1235+ fclose(fp2);
1236+ fclose(fp1);
1237+
1238+ /* Do not leave the init process in stopped state. */
1239+ kill(1, SIGCONT);
1240+
1241+ /* Undo mount("/", MS_REC|MS_SHARED) made by systemd. */
1242+ mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL);
1243+}
1244+
1245+int main(int argc, char *argv[])
1246+{
1247+ int i;
1248+ static const struct {
1249+ const char *action;
1250+ int (*func) (void);
1251+ } testcases[] = {
1252+ { "execute", test_execute },
1253+ { "read", test_read },
1254+ { "write", test_write },
1255+ { "create", test_create_no_append },
1256+ { "read", test_create_no_append },
1257+ { "write", test_create_no_append },
1258+ /* { "truncate", test_create_no_append }, */
1259+ { "create", test_create_append },
1260+ { "read", test_create_append },
1261+ { "append", test_create_append },
1262+ /* { "truncate", test_create_append }, */
1263+ { "write", test_fcntl_clear_append },
1264+ { "append", test_fcntl_set_append },
1265+ { "unlink", test_unlink },
1266+ { "getattr", test_getattr },
1267+ { "mkdir", test_mkdir },
1268+ { "rmdir", test_rmdir },
1269+ { "mkfifo", test_mkfifo },
1270+ { "mksock", test_mksock_by_mknod },
1271+ { "mksock", test_mksock_by_bind },
1272+ { "truncate", test_truncate },
1273+ { "symlink", test_symlink },
1274+ { "mkchar", test_mkchar },
1275+ { "mkblock", test_mkblock },
1276+ { "link", test_link },
1277+ { "rename", test_rename },
1278+ { "chmod", test_chmod },
1279+ { "chown", test_chown },
1280+ { "chgrp", test_chgrp },
1281+ { "ioctl", test_ioctl },
1282+ { "chroot", test_chroot },
1283+ { "mount", test_mount },
1284+ { "unmount", test_unmount },
1285+ { "pivot_root", test_pivot_root },
1286+ { "inet_stream_bind", test_inet_stream_bind },
1287+ { "inet_stream_listen", test_inet_stream_listen },
1288+ { "inet_stream_connect", test_inet_stream_connect },
1289+ { "inet_stream_accept", test_inet_stream_accept },
1290+ { "inet_dgram_bind", test_inet_dgram_bind },
1291+ { "inet_dgram_send", test_inet_dgram_connect },
1292+ { "inet_dgram_send", test_inet_dgram_send },
1293+ { "inet_dgram_recv", test_inet_dgram_recv },
1294+ { "inet_raw_bind", test_inet_raw_bind },
1295+ { "inet_raw_send", test_inet_raw_connect },
1296+ { "inet_raw_send", test_inet_raw_send },
1297+ { "inet_raw_recv", test_inet_raw_recv },
1298+ { "unix_stream_bind", test_unix_stream_bind },
1299+ { "unix_stream_listen", test_unix_stream_listen },
1300+ { "unix_stream_connect", test_unix_stream_connect },
1301+ { "unix_stream_accept", test_unix_stream_accept },
1302+ { "unix_dgram_bind", test_unix_dgram_bind },
1303+ { "unix_dgram_send", test_unix_dgram_connect },
1304+ { "unix_dgram_send", test_unix_dgram_send },
1305+ { "unix_dgram_recv", test_unix_dgram_recv },
1306+ { "unix_seqpacket_bind", test_unix_seqpacket_bind },
1307+ { "unix_seqpacket_listen", test_unix_seqpacket_listen },
1308+ { "unix_seqpacket_connect", test_unix_seqpacket_connect },
1309+ { "unix_seqpacket_accept", test_unix_seqpacket_accept },
1310+ { "environ", test_environ },
1311+ { "ptrace", test_ptrace },
1312+ { "signal", test_signal },
1313+ { "modify_policy", test_modify_policy },
1314+ { "use_netlink_socket", test_use_netlink_socket },
1315+ { "use_packet_socket", test_use_packet_socket },
1316+ { "use_reboot", test_use_reboot },
1317+ { "use_vhangup", test_use_vhangup },
1318+ { "set_time", test_set_time_by_stime },
1319+ { "set_time", test_set_time_by_settimeofday },
1320+ { "set_time", test_set_time_by_adjtimex },
1321+ { "set_priority", test_set_priority_by_nice },
1322+ { "set_priority", test_set_priority_by_setpriority },
1323+ { "set_hostname", test_set_hostname_by_sethostname },
1324+ { "set_hostname", test_set_hostname_by_setdomainname },
1325+ { "use_kernel_module", test_use_kernel_module_by_init_module },
1326+ { "use_kernel_module",
1327+ test_use_kernel_module_by_delete_module },
1328+ { "use_new_kernel", test_use_new_kernel },
1329+ { NULL, NULL }
1330+ };
1331+
1332+ reset_policy();
1333+
1334+ startup();
1335+ for (i = 0; testcases[i].action; i++)
1336+ test_action(testcases[i].action, testcases[i].func);
1337+ fprintf(stderr, "Done.\n");
1338+ return 0;
1339+}
--- tags/caitsith-tools/0.2.2/kernel_test/caitsith_parser_test.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/kernel_test/caitsith_parser_test.c (revision 242)
@@ -0,0 +1,953 @@
1+/*
2+ * caitsith-parser-test.c
3+ *
4+ * Copyright (C) 2012-2013 Tetsuo Handa
5+ *
6+ * Version: 0.2 2016/10/05
7+ *
8+ * This program is free software; you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License v2 as published by the
10+ * Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful, but WITHOUT
13+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15+ * more details.
16+ *
17+ * You should have received a copy of the GNU General Public License along with
18+ * this program; if not, write to the Free Software Foundation, Inc.,
19+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20+ */
21+
22+#include <stdio.h>
23+#include <string.h>
24+#include <stdlib.h>
25+#include <sys/types.h>
26+#include <sys/stat.h>
27+#include <fcntl.h>
28+#include <unistd.h>
29+#include <time.h>
30+#include <signal.h>
31+#include <sys/mount.h>
32+#ifndef MS_REC
33+#define MS_REC 16384
34+#endif
35+#ifndef MS_PRIVATE
36+#define MS_PRIVATE (1 << 18)
37+#endif
38+
39+enum ccs_mac_index {
40+ CCS_MAC_EXECUTE,
41+ CCS_MAC_READ,
42+ CCS_MAC_WRITE,
43+ CCS_MAC_APPEND,
44+ CCS_MAC_CREATE,
45+ CCS_MAC_UNLINK,
46+ CCS_MAC_GETATTR,
47+ CCS_MAC_MKDIR,
48+ CCS_MAC_RMDIR,
49+ CCS_MAC_MKFIFO,
50+ CCS_MAC_MKSOCK,
51+ CCS_MAC_TRUNCATE,
52+ CCS_MAC_SYMLINK,
53+ CCS_MAC_MKBLOCK,
54+ CCS_MAC_MKCHAR,
55+ CCS_MAC_LINK,
56+ CCS_MAC_RENAME,
57+ CCS_MAC_CHMOD,
58+ CCS_MAC_CHOWN,
59+ CCS_MAC_CHGRP,
60+ CCS_MAC_IOCTL,
61+ CCS_MAC_CHROOT,
62+ CCS_MAC_MOUNT,
63+ CCS_MAC_UMOUNT,
64+ CCS_MAC_PIVOT_ROOT,
65+ CCS_MAC_INET_STREAM_BIND,
66+ CCS_MAC_INET_STREAM_LISTEN,
67+ CCS_MAC_INET_STREAM_CONNECT,
68+ CCS_MAC_INET_STREAM_ACCEPT,
69+ CCS_MAC_INET_DGRAM_BIND,
70+ CCS_MAC_INET_DGRAM_SEND,
71+ CCS_MAC_INET_DGRAM_RECV,
72+ CCS_MAC_INET_RAW_BIND,
73+ CCS_MAC_INET_RAW_SEND,
74+ CCS_MAC_INET_RAW_RECV,
75+ CCS_MAC_UNIX_STREAM_BIND,
76+ CCS_MAC_UNIX_STREAM_LISTEN,
77+ CCS_MAC_UNIX_STREAM_CONNECT,
78+ CCS_MAC_UNIX_STREAM_ACCEPT,
79+ CCS_MAC_UNIX_DGRAM_BIND,
80+ CCS_MAC_UNIX_DGRAM_SEND,
81+ CCS_MAC_UNIX_DGRAM_RECV,
82+ CCS_MAC_UNIX_SEQPACKET_BIND,
83+ CCS_MAC_UNIX_SEQPACKET_LISTEN,
84+ CCS_MAC_UNIX_SEQPACKET_CONNECT,
85+ CCS_MAC_UNIX_SEQPACKET_ACCEPT,
86+ CCS_MAC_ENVIRON,
87+ CCS_MAC_PTRACE,
88+ CCS_MAC_SIGNAL,
89+ CCS_MAC_MODIFY_POLICY,
90+ CCS_MAC_USE_NETLINK_SOCKET,
91+ CCS_MAC_USE_PACKET_SOCKET,
92+ CCS_MAC_USE_REBOOT,
93+ CCS_MAC_USE_VHANGUP,
94+ CCS_MAC_SET_TIME,
95+ CCS_MAC_SET_PRIORITY,
96+ CCS_MAC_SET_HOSTNAME,
97+ CCS_MAC_USE_KERNEL_MODULE,
98+ CCS_MAC_USE_NEW_KERNEL,
99+ CCS_MAC_AUTO_DOMAIN_TRANSITION,
100+ CCS_MAC_MANUAL_DOMAIN_TRANSITION,
101+ CCS_MAX_MAC_INDEX
102+};
103+
104+static const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX] = {
105+ [CCS_MAC_EXECUTE] = "execute",
106+ [CCS_MAC_READ] = "read",
107+ [CCS_MAC_WRITE] = "write",
108+ [CCS_MAC_APPEND] = "append",
109+ [CCS_MAC_CREATE] = "create",
110+ [CCS_MAC_UNLINK] = "unlink",
111+ [CCS_MAC_GETATTR] = "getattr",
112+ [CCS_MAC_MKDIR] = "mkdir",
113+ [CCS_MAC_RMDIR] = "rmdir",
114+ [CCS_MAC_MKFIFO] = "mkfifo",
115+ [CCS_MAC_MKSOCK] = "mksock",
116+ [CCS_MAC_TRUNCATE] = "truncate",
117+ [CCS_MAC_SYMLINK] = "symlink",
118+ [CCS_MAC_MKBLOCK] = "mkblock",
119+ [CCS_MAC_MKCHAR] = "mkchar",
120+ [CCS_MAC_LINK] = "link",
121+ [CCS_MAC_RENAME] = "rename",
122+ [CCS_MAC_CHMOD] = "chmod",
123+ [CCS_MAC_CHOWN] = "chown",
124+ [CCS_MAC_CHGRP] = "chgrp",
125+ [CCS_MAC_IOCTL] = "ioctl",
126+ [CCS_MAC_CHROOT] = "chroot",
127+ [CCS_MAC_MOUNT] = "mount",
128+ [CCS_MAC_UMOUNT] = "unmount",
129+ [CCS_MAC_PIVOT_ROOT] = "pivot_root",
130+ [CCS_MAC_INET_STREAM_BIND] = "inet_stream_bind",
131+ [CCS_MAC_INET_STREAM_LISTEN] = "inet_stream_listen",
132+ [CCS_MAC_INET_STREAM_CONNECT] = "inet_stream_connect",
133+ [CCS_MAC_INET_STREAM_ACCEPT] = "inet_stream_accept",
134+ [CCS_MAC_INET_DGRAM_BIND] = "inet_dgram_bind",
135+ [CCS_MAC_INET_DGRAM_SEND] = "inet_dgram_send",
136+ [CCS_MAC_INET_DGRAM_RECV] = "inet_dgram_recv",
137+ [CCS_MAC_INET_RAW_BIND] = "inet_raw_bind",
138+ [CCS_MAC_INET_RAW_SEND] = "inet_raw_send",
139+ [CCS_MAC_INET_RAW_RECV] = "inet_raw_recv",
140+ [CCS_MAC_UNIX_STREAM_BIND] = "unix_stream_bind",
141+ [CCS_MAC_UNIX_STREAM_LISTEN] = "unix_stream_listen",
142+ [CCS_MAC_UNIX_STREAM_CONNECT] = "unix_stream_connect",
143+ [CCS_MAC_UNIX_STREAM_ACCEPT] = "unix_stream_accept",
144+ [CCS_MAC_UNIX_DGRAM_BIND] = "unix_dgram_bind",
145+ [CCS_MAC_UNIX_DGRAM_SEND] = "unix_dgram_send",
146+ [CCS_MAC_UNIX_DGRAM_RECV] = "unix_dgram_recv",
147+ [CCS_MAC_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind",
148+ [CCS_MAC_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen",
149+ [CCS_MAC_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",
150+ [CCS_MAC_UNIX_SEQPACKET_ACCEPT] = "unix_seqpacket_accept",
151+ [CCS_MAC_ENVIRON] = "environ",
152+ [CCS_MAC_PTRACE] = "ptrace",
153+ [CCS_MAC_SIGNAL] = "signal",
154+ [CCS_MAC_MODIFY_POLICY] = "modify_policy",
155+ [CCS_MAC_USE_NETLINK_SOCKET] = "use_netlink_socket",
156+ [CCS_MAC_USE_PACKET_SOCKET] = "use_packet_socket",
157+ [CCS_MAC_USE_REBOOT] = "use_reboot",
158+ [CCS_MAC_USE_VHANGUP] = "use_vhangup",
159+ [CCS_MAC_SET_TIME] = "set_time",
160+ [CCS_MAC_SET_PRIORITY] = "set_priority",
161+ [CCS_MAC_SET_HOSTNAME] = "set_hostname",
162+ [CCS_MAC_USE_KERNEL_MODULE] = "use_kernel_module",
163+ [CCS_MAC_USE_NEW_KERNEL] = "use_new_kernel",
164+ [CCS_MAC_AUTO_DOMAIN_TRANSITION] = "auto_domain_transition",
165+ [CCS_MAC_MANUAL_DOMAIN_TRANSITION] = "manual_domain_transition",
166+};
167+
168+#define F(bit) (1ULL << bit)
169+
170+#define CCS_ALL_OK \
171+ (F(CCS_MAC_EXECUTE) | \
172+ F(CCS_MAC_READ) | \
173+ F(CCS_MAC_WRITE) | \
174+ F(CCS_MAC_APPEND) | \
175+ F(CCS_MAC_CREATE) | \
176+ F(CCS_MAC_UNLINK) | \
177+ F(CCS_MAC_GETATTR) | \
178+ F(CCS_MAC_MKDIR) | \
179+ F(CCS_MAC_RMDIR) | \
180+ F(CCS_MAC_MKFIFO) | \
181+ F(CCS_MAC_MKSOCK) | \
182+ F(CCS_MAC_TRUNCATE) | \
183+ F(CCS_MAC_SYMLINK) | \
184+ F(CCS_MAC_MKBLOCK) | \
185+ F(CCS_MAC_MKCHAR) | \
186+ F(CCS_MAC_LINK) | \
187+ F(CCS_MAC_RENAME) | \
188+ F(CCS_MAC_CHMOD) | \
189+ F(CCS_MAC_CHOWN) | \
190+ F(CCS_MAC_CHGRP) | \
191+ F(CCS_MAC_IOCTL) | \
192+ F(CCS_MAC_CHROOT) | \
193+ F(CCS_MAC_MOUNT) | \
194+ F(CCS_MAC_UMOUNT) | \
195+ F(CCS_MAC_PIVOT_ROOT) | \
196+ F(CCS_MAC_INET_STREAM_BIND) | \
197+ F(CCS_MAC_INET_STREAM_LISTEN) | \
198+ F(CCS_MAC_INET_STREAM_CONNECT) | \
199+ F(CCS_MAC_INET_STREAM_ACCEPT) | \
200+ F(CCS_MAC_INET_DGRAM_BIND) | \
201+ F(CCS_MAC_INET_DGRAM_SEND) | \
202+ F(CCS_MAC_INET_DGRAM_RECV) | \
203+ F(CCS_MAC_INET_RAW_BIND) | \
204+ F(CCS_MAC_INET_RAW_SEND) | \
205+ F(CCS_MAC_INET_RAW_RECV) | \
206+ F(CCS_MAC_UNIX_STREAM_BIND) | \
207+ F(CCS_MAC_UNIX_STREAM_LISTEN) | \
208+ F(CCS_MAC_UNIX_STREAM_CONNECT) | \
209+ F(CCS_MAC_UNIX_STREAM_ACCEPT) | \
210+ F(CCS_MAC_UNIX_DGRAM_BIND) | \
211+ F(CCS_MAC_UNIX_DGRAM_SEND) | \
212+ F(CCS_MAC_UNIX_DGRAM_RECV) | \
213+ F(CCS_MAC_UNIX_SEQPACKET_BIND) | \
214+ F(CCS_MAC_UNIX_SEQPACKET_LISTEN) | \
215+ F(CCS_MAC_UNIX_SEQPACKET_CONNECT) | \
216+ F(CCS_MAC_UNIX_SEQPACKET_ACCEPT) | \
217+ F(CCS_MAC_ENVIRON) | \
218+ F(CCS_MAC_PTRACE) | \
219+ F(CCS_MAC_SIGNAL) | \
220+ F(CCS_MAC_MODIFY_POLICY) | \
221+ F(CCS_MAC_USE_NETLINK_SOCKET) | \
222+ F(CCS_MAC_USE_PACKET_SOCKET) | \
223+ F(CCS_MAC_USE_REBOOT) | \
224+ F(CCS_MAC_USE_VHANGUP) | \
225+ F(CCS_MAC_SET_TIME) | \
226+ F(CCS_MAC_SET_PRIORITY) | \
227+ F(CCS_MAC_SET_HOSTNAME) | \
228+ F(CCS_MAC_USE_KERNEL_MODULE) | \
229+ F(CCS_MAC_USE_NEW_KERNEL) | \
230+ F(CCS_MAC_AUTO_DOMAIN_TRANSITION) | \
231+ F(CCS_MAC_MANUAL_DOMAIN_TRANSITION))
232+
233+#define CCS_PATH_SELF_OK \
234+ (F(CCS_MAC_EXECUTE) | \
235+ F(CCS_MAC_ENVIRON) | \
236+ F(CCS_MAC_READ) | \
237+ F(CCS_MAC_WRITE) | \
238+ F(CCS_MAC_APPEND) | \
239+ F(CCS_MAC_UNLINK) | \
240+ F(CCS_MAC_GETATTR) | \
241+ F(CCS_MAC_RMDIR) | \
242+ F(CCS_MAC_TRUNCATE) | \
243+ F(CCS_MAC_CHMOD) | \
244+ F(CCS_MAC_CHOWN) | \
245+ F(CCS_MAC_CHGRP) | \
246+ F(CCS_MAC_IOCTL) | \
247+ F(CCS_MAC_CHROOT) | \
248+ F(CCS_MAC_UMOUNT))
249+
250+#define CCS_PATH_PARENT_OK \
251+ (F(CCS_MAC_CREATE) | \
252+ F(CCS_MAC_MKDIR) | \
253+ F(CCS_MAC_MKFIFO) | \
254+ F(CCS_MAC_MKSOCK) | \
255+ F(CCS_MAC_SYMLINK) | \
256+ F(CCS_MAC_MKBLOCK) | \
257+ F(CCS_MAC_MKCHAR))
258+
259+#define CCS_PATH_OK (CCS_PATH_SELF_OK | CCS_PATH_PARENT_OK)
260+
261+#define CCS_RENAME_OR_LINK_OK (F(CCS_MAC_LINK) | F(CCS_MAC_RENAME))
262+
263+#define CCS_EXECUTE_OR_ENVIRON_OK (F(CCS_MAC_EXECUTE) | F(CCS_MAC_ENVIRON))
264+
265+#define CCS_MKDEV_OK (F(CCS_MAC_MKBLOCK) | F(CCS_MAC_MKCHAR))
266+
267+#define CCS_PATH_PERM_OK \
268+ (F(CCS_MAC_MKDIR) | \
269+ F(CCS_MAC_MKBLOCK) | \
270+ F(CCS_MAC_MKCHAR) | \
271+ F(CCS_MAC_MKFIFO) | \
272+ F(CCS_MAC_MKSOCK) | \
273+ F(CCS_MAC_CREATE) | \
274+ F(CCS_MAC_CHMOD))
275+
276+#define CCS_IP_SOCKET_OK \
277+ (F(CCS_MAC_INET_STREAM_BIND) | \
278+ F(CCS_MAC_INET_STREAM_LISTEN) | \
279+ F(CCS_MAC_INET_STREAM_CONNECT) | \
280+ F(CCS_MAC_INET_STREAM_ACCEPT) | \
281+ F(CCS_MAC_INET_DGRAM_BIND) | \
282+ F(CCS_MAC_INET_DGRAM_SEND) | \
283+ F(CCS_MAC_INET_DGRAM_RECV))
284+
285+#define CCS_RAW_SOCKET_OK \
286+ (F(CCS_MAC_INET_RAW_BIND) | \
287+ F(CCS_MAC_INET_RAW_SEND) | \
288+ F(CCS_MAC_INET_RAW_RECV))
289+
290+#define CCS_INET_SOCKET_OK (CCS_IP_SOCKET_OK | CCS_RAW_SOCKET_OK)
291+
292+#define CCS_UNIX_SOCKET_OK \
293+ (F(CCS_MAC_UNIX_STREAM_BIND) | \
294+ F(CCS_MAC_UNIX_STREAM_LISTEN) | \
295+ F(CCS_MAC_UNIX_STREAM_CONNECT) | \
296+ F(CCS_MAC_UNIX_STREAM_ACCEPT) | \
297+ F(CCS_MAC_UNIX_DGRAM_BIND) | \
298+ F(CCS_MAC_UNIX_DGRAM_SEND) | \
299+ F(CCS_MAC_UNIX_DGRAM_RECV) | \
300+ F(CCS_MAC_UNIX_SEQPACKET_BIND) | \
301+ F(CCS_MAC_UNIX_SEQPACKET_LISTEN) | \
302+ F(CCS_MAC_UNIX_SEQPACKET_CONNECT) | \
303+ F(CCS_MAC_UNIX_SEQPACKET_ACCEPT))
304+
305+enum ccs_var_type {
306+ CCS_TYPE_INVALID,
307+ CCS_TYPE_NUMBER,
308+ CCS_TYPE_STRING,
309+ CCS_TYPE_IPADDR,
310+ CCS_TYPE_FILEPERM,
311+ CCS_TYPE_FILETYPE,
312+ CCS_TYPE_TASKTYPE,
313+ CCS_TYPE_ASSIGN,
314+};
315+
316+static const struct {
317+ const char * const keyword;
318+ const enum ccs_var_type left_type;
319+ const enum ccs_var_type right_type;
320+ const unsigned long long available;
321+} ccs_conditions[] = {
322+ { "addr", CCS_TYPE_STRING, CCS_TYPE_STRING,
323+ CCS_UNIX_SOCKET_OK },
324+ { "argc", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
325+ CCS_EXECUTE_OR_ENVIRON_OK },
326+ { "block", CCS_TYPE_INVALID, CCS_TYPE_FILETYPE,
327+ CCS_ALL_OK },
328+ { "char", CCS_TYPE_INVALID, CCS_TYPE_FILETYPE,
329+ CCS_ALL_OK },
330+ { "cmd", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
331+ F(CCS_MAC_IOCTL) | F(CCS_MAC_PTRACE) },
332+ { "data", CCS_TYPE_STRING, CCS_TYPE_STRING,
333+ F(CCS_MAC_MOUNT) },
334+ { "dev_major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
335+ CCS_MKDEV_OK },
336+ { "dev_minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
337+ CCS_MKDEV_OK },
338+ { "directory", CCS_TYPE_INVALID, CCS_TYPE_FILETYPE,
339+ CCS_ALL_OK },
340+ { "domain", CCS_TYPE_STRING, CCS_TYPE_STRING,
341+ F(CCS_MAC_PTRACE) | F(CCS_MAC_MANUAL_DOMAIN_TRANSITION) },
342+ { "envc", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
343+ CCS_EXECUTE_OR_ENVIRON_OK },
344+ { "exec", CCS_TYPE_STRING, CCS_TYPE_STRING,
345+ CCS_EXECUTE_OR_ENVIRON_OK },
346+ { "exec.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
347+ CCS_EXECUTE_OR_ENVIRON_OK },
348+ { "exec.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
349+ CCS_EXECUTE_OR_ENVIRON_OK },
350+ { "exec.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
351+ CCS_EXECUTE_OR_ENVIRON_OK },
352+ { "exec.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
353+ CCS_EXECUTE_OR_ENVIRON_OK },
354+ { "exec.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
355+ CCS_EXECUTE_OR_ENVIRON_OK },
356+ { "exec.parent.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
357+ CCS_EXECUTE_OR_ENVIRON_OK },
358+ { "exec.parent.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
359+ CCS_EXECUTE_OR_ENVIRON_OK },
360+ { "exec.parent.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
361+ CCS_EXECUTE_OR_ENVIRON_OK },
362+ { "exec.parent.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
363+ CCS_EXECUTE_OR_ENVIRON_OK },
364+ { "exec.parent.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
365+ CCS_EXECUTE_OR_ENVIRON_OK },
366+ { "exec.parent.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
367+ CCS_EXECUTE_OR_ENVIRON_OK },
368+ { "exec.parent.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
369+ CCS_EXECUTE_OR_ENVIRON_OK },
370+ { "exec.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
371+ CCS_EXECUTE_OR_ENVIRON_OK },
372+ { "exec.type", CCS_TYPE_FILETYPE, CCS_TYPE_FILETYPE,
373+ CCS_EXECUTE_OR_ENVIRON_OK },
374+ { "exec.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
375+ CCS_EXECUTE_OR_ENVIRON_OK },
376+ { "execute_handler", CCS_TYPE_INVALID, CCS_TYPE_TASKTYPE,
377+ CCS_ALL_OK },
378+ { "fifo", CCS_TYPE_INVALID, CCS_TYPE_FILETYPE,
379+ CCS_ALL_OK },
380+ { "file", CCS_TYPE_INVALID, CCS_TYPE_FILETYPE,
381+ CCS_ALL_OK },
382+ { "flags", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
383+ F(CCS_MAC_MOUNT) | F(CCS_MAC_UMOUNT) },
384+ { "fstype", CCS_TYPE_STRING, CCS_TYPE_STRING,
385+ F(CCS_MAC_MOUNT) },
386+ { "gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
387+ F(CCS_MAC_CHGRP) },
388+ { "group_execute", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
389+ CCS_ALL_OK },
390+ { "group_read", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
391+ CCS_ALL_OK },
392+ { "group_write", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
393+ CCS_ALL_OK },
394+ { "handler", CCS_TYPE_ASSIGN, CCS_TYPE_INVALID,
395+ F(CCS_MAC_EXECUTE) },
396+ { "ip", CCS_TYPE_IPADDR, CCS_TYPE_INVALID,
397+ CCS_INET_SOCKET_OK },
398+ { "name", CCS_TYPE_STRING, CCS_TYPE_STRING,
399+ F(CCS_MAC_ENVIRON) },
400+ { "new_path", CCS_TYPE_STRING, CCS_TYPE_STRING,
401+ CCS_RENAME_OR_LINK_OK },
402+ { "new_path.dev_major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
403+ F(CCS_MAC_RENAME) },
404+ { "new_path.dev_minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
405+ F(CCS_MAC_RENAME) },
406+ { "new_path.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
407+ F(CCS_MAC_RENAME) },
408+ { "new_path.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
409+ F(CCS_MAC_RENAME) },
410+ { "new_path.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
411+ F(CCS_MAC_RENAME) },
412+ { "new_path.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
413+ F(CCS_MAC_RENAME) },
414+ { "new_path.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
415+ F(CCS_MAC_RENAME) },
416+ { "new_path.parent.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
417+ CCS_RENAME_OR_LINK_OK },
418+ { "new_path.parent.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
419+ CCS_RENAME_OR_LINK_OK },
420+ { "new_path.parent.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
421+ CCS_RENAME_OR_LINK_OK },
422+ { "new_path.parent.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
423+ CCS_RENAME_OR_LINK_OK },
424+ { "new_path.parent.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
425+ CCS_RENAME_OR_LINK_OK },
426+ { "new_path.parent.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
427+ CCS_RENAME_OR_LINK_OK },
428+ { "new_path.parent.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
429+ CCS_RENAME_OR_LINK_OK },
430+ { "new_path.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
431+ F(CCS_MAC_RENAME) },
432+ { "new_path.type", CCS_TYPE_FILETYPE, CCS_TYPE_FILETYPE,
433+ F(CCS_MAC_RENAME) },
434+ { "new_path.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
435+ F(CCS_MAC_RENAME) },
436+ { "new_root", CCS_TYPE_STRING, CCS_TYPE_STRING,
437+ F(CCS_MAC_PIVOT_ROOT) },
438+ { "new_root.dev_major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
439+ F(CCS_MAC_PIVOT_ROOT) },
440+ { "new_root.dev_minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
441+ F(CCS_MAC_PIVOT_ROOT) },
442+ { "new_root.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
443+ F(CCS_MAC_PIVOT_ROOT) },
444+ { "new_root.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
445+ F(CCS_MAC_PIVOT_ROOT) },
446+ { "new_root.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
447+ F(CCS_MAC_PIVOT_ROOT) },
448+ { "new_root.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
449+ F(CCS_MAC_PIVOT_ROOT) },
450+ { "new_root.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
451+ F(CCS_MAC_PIVOT_ROOT) },
452+ { "new_root.parent.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
453+ F(CCS_MAC_PIVOT_ROOT) },
454+ { "new_root.parent.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
455+ F(CCS_MAC_PIVOT_ROOT) },
456+ { "new_root.parent.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
457+ F(CCS_MAC_PIVOT_ROOT) },
458+ { "new_root.parent.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
459+ F(CCS_MAC_PIVOT_ROOT) },
460+ { "new_root.parent.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
461+ F(CCS_MAC_PIVOT_ROOT) },
462+ { "new_root.parent.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
463+ F(CCS_MAC_PIVOT_ROOT) },
464+ { "new_root.parent.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
465+ F(CCS_MAC_PIVOT_ROOT) },
466+ { "new_root.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
467+ F(CCS_MAC_PIVOT_ROOT) },
468+ { "new_root.type", CCS_TYPE_FILETYPE, CCS_TYPE_FILETYPE,
469+ F(CCS_MAC_PIVOT_ROOT) },
470+ { "new_root.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
471+ F(CCS_MAC_PIVOT_ROOT) },
472+ { "old_path", CCS_TYPE_STRING, CCS_TYPE_STRING,
473+ CCS_RENAME_OR_LINK_OK },
474+ { "old_path.dev_major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
475+ CCS_RENAME_OR_LINK_OK },
476+ { "old_path.dev_minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
477+ CCS_RENAME_OR_LINK_OK },
478+ { "old_path.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
479+ CCS_RENAME_OR_LINK_OK },
480+ { "old_path.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
481+ CCS_RENAME_OR_LINK_OK },
482+ { "old_path.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
483+ CCS_RENAME_OR_LINK_OK },
484+ { "old_path.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
485+ CCS_RENAME_OR_LINK_OK },
486+ { "old_path.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
487+ CCS_RENAME_OR_LINK_OK },
488+ { "old_path.parent.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
489+ CCS_RENAME_OR_LINK_OK },
490+ { "old_path.parent.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
491+ CCS_RENAME_OR_LINK_OK },
492+ { "old_path.parent.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
493+ CCS_RENAME_OR_LINK_OK },
494+ { "old_path.parent.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
495+ CCS_RENAME_OR_LINK_OK },
496+ { "old_path.parent.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
497+ CCS_RENAME_OR_LINK_OK },
498+ { "old_path.parent.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
499+ CCS_RENAME_OR_LINK_OK },
500+ { "old_path.parent.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
501+ CCS_RENAME_OR_LINK_OK },
502+ { "old_path.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
503+ CCS_RENAME_OR_LINK_OK },
504+ { "old_path.type", CCS_TYPE_FILETYPE, CCS_TYPE_FILETYPE,
505+ CCS_RENAME_OR_LINK_OK },
506+ { "old_path.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
507+ CCS_RENAME_OR_LINK_OK },
508+ { "others_execute", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
509+ CCS_ALL_OK },
510+ { "others_read", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
511+ CCS_ALL_OK },
512+ { "others_write", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
513+ CCS_ALL_OK },
514+ { "owner_execute", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
515+ CCS_ALL_OK },
516+ { "owner_read", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
517+ CCS_ALL_OK },
518+ { "owner_write", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
519+ CCS_ALL_OK },
520+ { "path", CCS_TYPE_STRING, CCS_TYPE_STRING,
521+ CCS_PATH_OK },
522+ { "path.dev_major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
523+ CCS_PATH_SELF_OK },
524+ { "path.dev_minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
525+ CCS_PATH_SELF_OK },
526+ { "path.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
527+ CCS_PATH_SELF_OK },
528+ { "path.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
529+ CCS_PATH_SELF_OK },
530+ { "path.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
531+ CCS_PATH_SELF_OK },
532+ { "path.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
533+ CCS_PATH_SELF_OK },
534+ { "path.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
535+ CCS_PATH_SELF_OK },
536+ { "path.parent.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
537+ CCS_PATH_OK },
538+ { "path.parent.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
539+ CCS_PATH_OK },
540+ { "path.parent.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
541+ CCS_PATH_OK },
542+ { "path.parent.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
543+ CCS_PATH_OK },
544+ { "path.parent.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
545+ CCS_PATH_OK },
546+ { "path.parent.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
547+ CCS_PATH_OK },
548+ { "path.parent.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
549+ CCS_PATH_OK },
550+ { "path.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
551+ CCS_PATH_SELF_OK },
552+ { "path.type", CCS_TYPE_FILETYPE, CCS_TYPE_FILETYPE,
553+ CCS_PATH_SELF_OK },
554+ { "path.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
555+ CCS_PATH_SELF_OK },
556+ { "perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
557+ CCS_PATH_PERM_OK },
558+ { "port", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
559+ CCS_IP_SOCKET_OK },
560+ { "proto", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
561+ CCS_RAW_SOCKET_OK },
562+ { "put_old", CCS_TYPE_STRING, CCS_TYPE_STRING,
563+ F(CCS_MAC_PIVOT_ROOT) },
564+ { "put_old.dev_major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
565+ F(CCS_MAC_PIVOT_ROOT) },
566+ { "put_old.dev_minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
567+ F(CCS_MAC_PIVOT_ROOT) },
568+ { "put_old.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
569+ F(CCS_MAC_PIVOT_ROOT) },
570+ { "put_old.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
571+ F(CCS_MAC_PIVOT_ROOT) },
572+ { "put_old.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
573+ F(CCS_MAC_PIVOT_ROOT) },
574+ { "put_old.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
575+ F(CCS_MAC_PIVOT_ROOT) },
576+ { "put_old.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
577+ F(CCS_MAC_PIVOT_ROOT) },
578+ { "put_old.parent.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
579+ F(CCS_MAC_PIVOT_ROOT) },
580+ { "put_old.parent.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
581+ F(CCS_MAC_PIVOT_ROOT) },
582+ { "put_old.parent.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
583+ F(CCS_MAC_PIVOT_ROOT) },
584+ { "put_old.parent.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
585+ F(CCS_MAC_PIVOT_ROOT) },
586+ { "put_old.parent.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
587+ F(CCS_MAC_PIVOT_ROOT) },
588+ { "put_old.parent.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
589+ F(CCS_MAC_PIVOT_ROOT) },
590+ { "put_old.parent.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
591+ F(CCS_MAC_PIVOT_ROOT) },
592+ { "put_old.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
593+ F(CCS_MAC_PIVOT_ROOT) },
594+ { "put_old.type", CCS_TYPE_FILETYPE, CCS_TYPE_FILETYPE,
595+ F(CCS_MAC_PIVOT_ROOT) },
596+ { "put_old.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
597+ F(CCS_MAC_PIVOT_ROOT) },
598+ { "setgid", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
599+ CCS_ALL_OK },
600+ { "setuid", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
601+ CCS_ALL_OK },
602+ { "sig", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
603+ F(CCS_MAC_SIGNAL) },
604+ { "socket", CCS_TYPE_INVALID, CCS_TYPE_FILETYPE,
605+ CCS_ALL_OK },
606+ { "source", CCS_TYPE_STRING, CCS_TYPE_STRING,
607+ F(CCS_MAC_MOUNT) },
608+ { "source.dev_major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
609+ F(CCS_MAC_MOUNT) },
610+ { "source.dev_minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
611+ F(CCS_MAC_MOUNT) },
612+ { "source.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
613+ F(CCS_MAC_MOUNT) },
614+ { "source.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
615+ F(CCS_MAC_MOUNT) },
616+ { "source.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
617+ F(CCS_MAC_MOUNT) },
618+ { "source.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
619+ F(CCS_MAC_MOUNT) },
620+ { "source.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
621+ F(CCS_MAC_MOUNT) },
622+ { "source.parent.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
623+ F(CCS_MAC_MOUNT) },
624+ { "source.parent.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
625+ F(CCS_MAC_MOUNT) },
626+ { "source.parent.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
627+ F(CCS_MAC_MOUNT) },
628+ { "source.parent.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
629+ F(CCS_MAC_MOUNT) },
630+ { "source.parent.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
631+ F(CCS_MAC_MOUNT) },
632+ { "source.parent.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
633+ F(CCS_MAC_MOUNT) },
634+ { "source.parent.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
635+ F(CCS_MAC_MOUNT) },
636+ { "source.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
637+ F(CCS_MAC_MOUNT) },
638+ { "source.type", CCS_TYPE_FILETYPE, CCS_TYPE_FILETYPE,
639+ F(CCS_MAC_MOUNT) },
640+ { "source.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
641+ F(CCS_MAC_MOUNT) },
642+ { "sticky", CCS_TYPE_INVALID, CCS_TYPE_FILEPERM,
643+ CCS_ALL_OK },
644+ { "symlink", CCS_TYPE_INVALID, CCS_TYPE_FILETYPE,
645+ CCS_ALL_OK },
646+ { "target", CCS_TYPE_STRING, CCS_TYPE_STRING,
647+ F(CCS_MAC_MOUNT) | F(CCS_MAC_SYMLINK) },
648+ { "target.dev_major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
649+ F(CCS_MAC_MOUNT) },
650+ { "target.dev_minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
651+ F(CCS_MAC_MOUNT) },
652+ { "target.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
653+ F(CCS_MAC_MOUNT) },
654+ { "target.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
655+ F(CCS_MAC_MOUNT) },
656+ { "target.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
657+ F(CCS_MAC_MOUNT) },
658+ { "target.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
659+ F(CCS_MAC_MOUNT) },
660+ { "target.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
661+ F(CCS_MAC_MOUNT) },
662+ { "target.parent.fsmagic", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
663+ F(CCS_MAC_MOUNT) },
664+ { "target.parent.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
665+ F(CCS_MAC_MOUNT) },
666+ { "target.parent.ino", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
667+ F(CCS_MAC_MOUNT) },
668+ { "target.parent.major", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
669+ F(CCS_MAC_MOUNT) },
670+ { "target.parent.minor", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
671+ F(CCS_MAC_MOUNT) },
672+ { "target.parent.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
673+ F(CCS_MAC_MOUNT) },
674+ { "target.parent.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
675+ F(CCS_MAC_MOUNT) },
676+ { "target.perm", CCS_TYPE_FILEPERM, CCS_TYPE_FILEPERM,
677+ F(CCS_MAC_MOUNT) },
678+ { "target.type", CCS_TYPE_FILETYPE, CCS_TYPE_FILETYPE,
679+ F(CCS_MAC_MOUNT) },
680+ { "target.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
681+ F(CCS_MAC_MOUNT) },
682+ { "task.domain", CCS_TYPE_STRING, CCS_TYPE_STRING,
683+ CCS_ALL_OK },
684+ { "task.egid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
685+ CCS_ALL_OK },
686+ { "task.euid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
687+ CCS_ALL_OK },
688+ { "task.exe", CCS_TYPE_STRING, CCS_TYPE_STRING,
689+ CCS_ALL_OK },
690+ { "task.fsgid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
691+ CCS_ALL_OK },
692+ { "task.fsuid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
693+ CCS_ALL_OK },
694+ { "task.gid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
695+ CCS_ALL_OK },
696+ { "task.pid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
697+ CCS_ALL_OK },
698+ { "task.ppid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
699+ CCS_ALL_OK },
700+ { "task.sgid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
701+ CCS_ALL_OK },
702+ { "task.suid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
703+ CCS_ALL_OK },
704+ { "task.type", CCS_TYPE_TASKTYPE, CCS_TYPE_INVALID,
705+ CCS_ALL_OK },
706+ { "task.uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
707+ CCS_ALL_OK },
708+ { "transition", CCS_TYPE_ASSIGN, CCS_TYPE_INVALID,
709+ F(CCS_MAC_EXECUTE) | F(CCS_MAC_AUTO_DOMAIN_TRANSITION) },
710+ { "uid", CCS_TYPE_NUMBER, CCS_TYPE_NUMBER,
711+ F(CCS_MAC_CHOWN) },
712+ { "value", CCS_TYPE_STRING, CCS_TYPE_STRING,
713+ F(CCS_MAC_ENVIRON) },
714+ { "argv[0]", CCS_TYPE_STRING, CCS_TYPE_INVALID,
715+ CCS_EXECUTE_OR_ENVIRON_OK },
716+ { "argv[4294967295]", CCS_TYPE_STRING, CCS_TYPE_INVALID,
717+ CCS_EXECUTE_OR_ENVIRON_OK },
718+ { "envp[\"PATH\"]", CCS_TYPE_STRING, CCS_TYPE_INVALID,
719+ CCS_EXECUTE_OR_ENVIRON_OK },
720+ { "envp[\"\\*\"]", CCS_TYPE_STRING, CCS_TYPE_INVALID,
721+ CCS_EXECUTE_OR_ENVIRON_OK },
722+ { "NULL", CCS_TYPE_INVALID, CCS_TYPE_STRING,
723+ CCS_ALL_OK },
724+ { "\"word\"", CCS_TYPE_INVALID, CCS_TYPE_ASSIGN,
725+ CCS_ALL_OK },
726+ { "\"/\"", CCS_TYPE_INVALID, CCS_TYPE_STRING,
727+ CCS_ALL_OK },
728+ { "\"/\\*\"", CCS_TYPE_INVALID, CCS_TYPE_STRING,
729+ CCS_ALL_OK },
730+ { "@STRING_GROUP", CCS_TYPE_INVALID, CCS_TYPE_STRING,
731+ CCS_ALL_OK },
732+ { "0", CCS_TYPE_INVALID, CCS_TYPE_NUMBER,
733+ CCS_ALL_OK },
734+ { "0-4294967295", CCS_TYPE_INVALID, CCS_TYPE_NUMBER,
735+ CCS_ALL_OK },
736+ { "@NUMBER_GROUP", CCS_TYPE_INVALID, CCS_TYPE_NUMBER,
737+ CCS_ALL_OK },
738+ { "127.0.0.1", CCS_TYPE_INVALID, CCS_TYPE_IPADDR,
739+ CCS_ALL_OK },
740+ { "0.0.0.0-0.0.0.1", CCS_TYPE_INVALID, CCS_TYPE_IPADDR,
741+ CCS_ALL_OK },
742+ { "::1", CCS_TYPE_INVALID, CCS_TYPE_IPADDR,
743+ CCS_ALL_OK },
744+ { "::-::1", CCS_TYPE_INVALID, CCS_TYPE_IPADDR,
745+ CCS_ALL_OK },
746+ { "@IP_GROUP", CCS_TYPE_INVALID, CCS_TYPE_IPADDR,
747+ CCS_ALL_OK },
748+};
749+
750+static char *policy = NULL;
751+static int policy_len = 0;
752+
753+static inline void truncate_policy(void)
754+{
755+ policy_len = 0;
756+}
757+
758+static void add_policy(const char *data)
759+{
760+ const int len = strlen(data);
761+ char *tmp = realloc(policy, policy_len + len + 1);
762+ if (!tmp) {
763+ fprintf(stderr, "Out of memory\n");
764+ exit(1);
765+ }
766+ policy = tmp;
767+ memmove(policy + policy_len, data, len + 1);
768+ policy_len += len;
769+}
770+
771+static unsigned int tests_now = 0;
772+
773+static void check_policy_written(const _Bool valid)
774+{
775+ int fd1 = open(POLDIR "/policy", O_RDWR);
776+ int fd2 = open(POLDIR "/policy", O_RDWR);
777+ int len = strlen(policy);
778+ int ret;
779+ char *buffer;
780+ if (fd1 == EOF || fd2 == EOF) {
781+ printf("%s", policy);
782+ return;
783+ }
784+ ret = write(fd1, policy, len);
785+ if (ret != len) {
786+ fprintf(stderr, "Write error (%d, %d)\n", ret, len);
787+ exit(1);
788+ }
789+ buffer = calloc(len + 4096, 1);
790+ if (!buffer) {
791+ fprintf(stderr, "Out of memory\n");
792+ exit(1);
793+ }
794+ ret = read(fd1, buffer, len + 4095);
795+ if (!strstr(buffer, policy) != !valid) {
796+ fprintf(stderr, "Test %u: FAILED(add) '%s' : '%s' valid=%u\n",
797+ tests_now - 1, buffer, policy, valid);
798+ exit(1);
799+ }
800+ printf("Test %u: OK '%s' : '%s'\n", tests_now - 1, buffer, policy);
801+ if (write(fd2, "delete ", 7) != 7 || write(fd2, policy, len) != len) {
802+ fprintf(stderr, "Write error\n");
803+ exit(1);
804+ }
805+ memset(buffer, 0, len + 1024);
806+ ret = read(fd2, buffer, len + 1023);
807+ if (strstr(buffer, policy)) {
808+ fprintf(stderr, "Test %u: FAILED(remove) '%s' : '%s'\n",
809+ tests_now - 1, buffer, policy);
810+ exit(1);
811+ }
812+ printf("Test %u: OK '%s' : '%s'\n", tests_now - 1, buffer, policy);
813+ free(buffer);
814+ close(fd1);
815+ close(fd2);
816+}
817+
818+static inline void add_policy2(const char *data1, const char *data2)
819+{
820+ add_policy(data1);
821+ add_policy(data2);
822+}
823+
824+static inline void add_policy3(const char *data1, const char *data2,
825+ const char *data3)
826+{
827+ add_policy(data1);
828+ add_policy(data2);
829+ add_policy(data3);
830+}
831+
832+static _Bool adjust_exception(const int mac, const int p1, const int p2)
833+{
834+ if (ccs_conditions[p1].left_type == CCS_TYPE_ASSIGN)
835+ return !strcmp(ccs_conditions[p2].keyword, "NULL") ||
836+ !strcmp(ccs_conditions[p2].keyword,"\"/\"");
837+ if (ccs_conditions[p2].keyword[0] == '@')
838+ return ccs_conditions[p1].left_type == CCS_TYPE_STRING ||
839+ ccs_conditions[p1].left_type == CCS_TYPE_NUMBER ||
840+ ccs_conditions[p1].left_type == CCS_TYPE_IPADDR ||
841+ ccs_conditions[p1].left_type == CCS_TYPE_FILEPERM;
842+ if (ccs_conditions[p1].left_type == CCS_TYPE_STRING)
843+ return !strcmp(ccs_conditions[p2].keyword, "\"word\"");
844+ if (ccs_conditions[p1].left_type == CCS_TYPE_FILEPERM &&
845+ ccs_conditions[p2].right_type == CCS_TYPE_NUMBER)
846+ return 1;
847+ return 0;
848+}
849+
850+static unsigned int tests_start = 0;
851+
852+static void check_righthand(const int mac, const int p1, const _Bool org_valid)
853+{
854+ int p2;
855+ const enum ccs_var_type type = ccs_conditions[p1].left_type;
856+ for (p2 = 0; p2 < sizeof(ccs_conditions) / sizeof(ccs_conditions[0]);
857+ p2++) {
858+ _Bool valid = org_valid;
859+ if (tests_now++ < tests_start)
860+ continue;
861+ if (valid) {
862+ if (!(ccs_conditions[p2].available & F(mac)))
863+ valid = 0;
864+ else if (ccs_conditions[p2].right_type != type)
865+ valid = adjust_exception(mac, p1, p2);
866+ }
867+ truncate_policy();
868+ add_policy3("0 acl ", ccs_mac_keywords[mac], "\n"
869+ " audit 0\n 0 allow");
870+ add_policy2(" ", ccs_conditions[p1].keyword);
871+ add_policy2("=", ccs_conditions[p2].keyword);
872+ if (mac == CCS_MAC_AUTO_DOMAIN_TRANSITION &&
873+ strcmp(ccs_conditions[p1].keyword, "transition"))
874+ add_policy(" transition=\"word\"");
875+ add_policy("\n");
876+ check_policy_written(valid);
877+ if (type == CCS_TYPE_ASSIGN)
878+ valid = 0;
879+ truncate_policy();
880+ add_policy3("0 acl ", ccs_mac_keywords[mac], "\n"
881+ " audit 0\n 0 allow");
882+ add_policy2(" ", ccs_conditions[p1].keyword);
883+ add_policy2("!=", ccs_conditions[p2].keyword);
884+ if (mac == CCS_MAC_AUTO_DOMAIN_TRANSITION &&
885+ strcmp(ccs_conditions[p1].keyword, "transition"))
886+ add_policy(" transition=\"word\"");
887+ add_policy("\n");
888+ check_policy_written(valid);
889+ {
890+ static time_t last = 0;
891+ time_t now = time(NULL);
892+ if (now - last >= (time_t) 10) {
893+ last = now;
894+ fprintf(stderr, "Test %u passed\n",
895+ tests_now - 1);
896+ }
897+ }
898+ }
899+}
900+
901+static void reset_policy(void)
902+{
903+ FILE *fp2 = fopen(POLDIR "/policy", "r");
904+ FILE *fp1 = fopen(POLDIR "/policy", "w");
905+ if (!fp1 || !fp2) {
906+ fprintf(stderr, " Can't open " POLDIR "/policy\n");
907+ exit(1);
908+ }
909+ while (1) {
910+ const int c = fgetc(fp2);
911+ if (c == EOF)
912+ break;
913+ fputc(c, fp1);
914+ if (c == '\n')
915+ fprintf(fp1, "delete ");
916+ }
917+ fclose(fp2);
918+ fclose(fp1);
919+
920+ /* Do not leave the init process in stopped state. */
921+ kill(1, SIGCONT);
922+
923+ /* Undo mount("/", MS_REC|MS_SHARED) made by systemd. */
924+ mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL);
925+}
926+
927+int main(int argc, char *argv[]) {
928+ int mac;
929+
930+ reset_policy();
931+ if (argc > 1)
932+ tests_start = atoi(argv[1]);
933+ for (mac = 0; mac < CCS_MAX_MAC_INDEX; mac++) {
934+ truncate_policy();
935+ add_policy3("0 acl ", ccs_mac_keywords[mac], "\n"
936+ " audit 0\n");
937+ check_policy_written(1);
938+ }
939+ for (mac = 0; mac < CCS_MAX_MAC_INDEX; mac++) {
940+ int p1;
941+ for (p1 = 0;
942+ p1 < sizeof(ccs_conditions) / sizeof(ccs_conditions[0]);
943+ p1++) {
944+ _Bool valid = 1;
945+ if (ccs_conditions[p1].left_type == CCS_TYPE_INVALID ||
946+ !(ccs_conditions[p1].available & F(mac)))
947+ valid = 0;
948+ check_righthand(mac, p1, valid);
949+ }
950+ }
951+ fprintf(stderr, "Test %u passed\n", tests_now - 1);
952+ return 0;
953+}
--- tags/caitsith-tools/0.2.2/kernel_test/Makefile (nonexistent)
+++ tags/caitsith-tools/0.2.2/kernel_test/Makefile (revision 242)
@@ -0,0 +1,23 @@
1+include ../Include.make
2+
3+ALL_FILES = caitsith_param_test caitsith_log_test caitsith_parser_test caitsith_audit2cond_test caitsith_lsm_test caitsith_wildcard_test
4+
5+all: $(ALL_FILES)
6+
7+#
8+# Tools for kernel testing.
9+#
10+
11+BINDIR = '"'$(shell readlink -f /bin)'"'
12+POLDIR = '"/sys/kernel/security/caitsith"'
13+#POLDIR = '"/proc/caitsith"'
14+
15+.c:
16+ $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DBINDIR=$(BINDIR) -DPOLDIR=$(POLDIR) -o $@ $<
17+
18+#
19+# Delete all test programs.
20+#
21+
22+clean:
23+ rm -f $(ALL_FILES)
--- tags/caitsith-tools/0.2.2/kernel_test/caitsith_log_test.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/kernel_test/caitsith_log_test.c (revision 242)
@@ -0,0 +1,440 @@
1+#include <stdio.h>
2+#include <string.h>
3+#include <stdlib.h>
4+#include <sys/types.h>
5+#include <sys/stat.h>
6+#include <fcntl.h>
7+#include <unistd.h>
8+#include <linux/kdev_t.h>
9+#include <signal.h>
10+#include <sys/mount.h>
11+#include <sys/ioctl.h>
12+
13+#ifndef MS_MOVE
14+#define MS_MOVE 8192
15+#endif
16+#ifndef MS_REC
17+#define MS_REC 16384
18+#endif
19+#ifndef MS_UNBINDABLE
20+#define MS_UNBINDABLE (1<<17)
21+#endif
22+#ifndef MS_PRIVATE
23+#define MS_PRIVATE (1<<18)
24+#endif
25+#ifndef MS_SLAVE
26+#define MS_SLAVE (1<<19)
27+#endif
28+#ifndef MS_SHARED
29+#define MS_SHARED (1<<20)
30+#endif
31+
32+#include <asm/unistd.h>
33+static inline int pivot_root(const char *new_root, const char *put_old)
34+{
35+ return syscall(__NR_pivot_root, new_root, put_old);
36+}
37+
38+static _Bool debug = 0;
39+
40+static char *read_log(const char *expected_result, const char *expected_action)
41+{
42+ static int fd = EOF;
43+ static char buffer[16384];
44+ if (fd == EOF)
45+ fd = open(POLDIR "/audit", O_RDONLY);
46+ memset(buffer, 0, sizeof(buffer));
47+ while (buffer[0] = '\0', read(fd, buffer, sizeof(buffer) - 1) > 0) {
48+ char *cp1;
49+ char *cp2;
50+ if (debug)
51+ printf("Got '%s'\n", buffer);
52+ cp1 = strstr(buffer, " / ");
53+ if (buffer[0] != '#' || !cp1 || !strchr(buffer, '\n')) {
54+ fprintf(stderr,
55+ "Expected complete audit log, got '%s'\n",
56+ buffer);
57+ return NULL;
58+ }
59+ *cp1 = '\0';
60+ if (!strstr(buffer, expected_result))
61+ continue;
62+ cp1 += 3;
63+ cp2 = strchr(cp1, ' ');
64+ if (!cp2) {
65+ fprintf(stderr,
66+ "Expected complete audit log, got '%s'\n",
67+ cp1);
68+ return NULL;
69+ }
70+ *cp2++ = '\0';
71+ if (strcmp(expected_action, cp1))
72+ continue;
73+ return cp2;
74+ }
75+ fprintf(stderr, "Expected '%s' '%s', found none\n",
76+ expected_result, expected_action);
77+ return NULL;
78+}
79+
80+static void create_dummy(const char *path)
81+{
82+ close(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600));
83+}
84+
85+static void test_execute(void)
86+{
87+ char *args[3] = { "null", "--help", NULL };
88+ char *envs[3] = { "PATH=/", "HOME=/", NULL };
89+ create_dummy("/tmp/null");
90+ chmod("/tmp/null", 0700);
91+ execve("/tmp/null", args, envs);
92+}
93+
94+static void test_read(void)
95+{
96+ close(open("/dev/null", O_RDONLY));
97+}
98+
99+static void test_write(void)
100+{
101+ close(open("/dev/null", O_WRONLY));
102+}
103+
104+static void test_append(void)
105+{
106+ close(open("/dev/null", O_WRONLY | O_APPEND));
107+}
108+
109+static void test_create(void)
110+{
111+ unlink("/tmp/null");
112+ create_dummy("/tmp/null");
113+}
114+
115+static void test_unlink(void)
116+{
117+ create_dummy("/tmp/null");
118+ unlink("/tmp/null");
119+}
120+
121+static void test_getattr(void)
122+{
123+ struct stat buf;
124+ create_dummy("/tmp/null");
125+ stat("/tmp/null", &buf);
126+}
127+
128+static void test_mkdir(void)
129+{
130+ rmdir("/tmp/nulldir");
131+ mkdir("/tmp/nulldir", 0755);
132+}
133+
134+static void test_rmdir(void)
135+{
136+ mkdir("/tmp/nulldir", 0755);
137+ rmdir("/tmp/nulldir");
138+}
139+
140+static void test_mkfifo(void)
141+{
142+ unlink("/tmp/null");
143+ mknod("/tmp/null", S_IFIFO, 0);
144+}
145+
146+static void test_mksock(void)
147+{
148+ unlink("/tmp/null");
149+ mknod("/tmp/null", S_IFSOCK, 0);
150+}
151+
152+static void test_truncate(void)
153+{
154+ create_dummy("/tmp/null");
155+ truncate("/tmp/null", 0);
156+}
157+
158+static void test_symlink(void)
159+{
160+ unlink("/tmp/null");
161+ symlink("symlink'starget", "/tmp/null");
162+}
163+
164+static void test_mkblock(void)
165+{
166+ unlink("/tmp/null");
167+ mknod("/tmp/null", S_IFBLK, MKDEV(1, 0));
168+}
169+
170+static void test_mkchar(void)
171+{
172+ unlink("/tmp/null");
173+ mknod("/tmp/null", S_IFCHR, MKDEV(1, 3));
174+}
175+
176+static void test_link(void)
177+{
178+ create_dummy("/tmp/link");
179+ unlink("/tmp/newlink");
180+ link("/tmp/link", "/tmp/newlink");
181+}
182+
183+static void test_rename(void)
184+{
185+ link("/dev/null", "/dev/null0");
186+ rename("/dev/null0", "/dev/null1");
187+ unlink("/dev/null1");
188+}
189+
190+static void test_chmod(void)
191+{
192+ chmod("/dev/null", 0666);
193+}
194+
195+static void test_chown(void)
196+{
197+ chown("/dev/null", 0, -1);
198+}
199+
200+static void test_chgrp(void)
201+{
202+ chown("/dev/null", -1, 0);
203+}
204+
205+static void test_ioctl(void)
206+{
207+ int fd = open("/dev/null", 3);
208+ ioctl(fd, 0);
209+ close(fd);
210+}
211+
212+static void test_chroot(void)
213+{
214+ chroot("/");
215+}
216+
217+static void test_mount1(void)
218+{
219+ mount(NULL, "/tmp", "tmpfs", 0, "size=10%,uid=0,gid=0");
220+ umount("/tmp");
221+}
222+
223+static void test_mount2(void)
224+{
225+ mount("/", "/", NULL, MS_BIND, NULL);
226+}
227+
228+static void test_mount3(void)
229+{
230+ mount("/", "/", NULL, MS_MOVE, NULL);
231+}
232+
233+static void test_mount4(void)
234+{
235+ mount(NULL, "/", NULL, MS_REMOUNT | MS_NOATIME, NULL);
236+}
237+
238+static void test_unmount(void)
239+{
240+ umount2("/", 1);
241+}
242+
243+static void test_pivot_root(void)
244+{
245+ pivot_root("/", "/");
246+}
247+
248+static _Bool check_policy(const char *policy, const char *decision,
249+ const char *condition)
250+{
251+ static char buffer[16384];
252+ FILE *fp = fopen(POLDIR "/policy", "r");
253+ _Bool found = 0;
254+ if (!fp) {
255+ fprintf(stderr, "Can't read " POLDIR "/policy interface.\n");
256+ return 0;
257+ }
258+ memset(buffer, 0, sizeof(buffer));
259+ while (fgets(buffer, sizeof(buffer) - 1, fp)) {
260+ if (strstr(buffer, decision) && strstr(buffer, condition)) {
261+ found = 1;
262+ break;
263+ }
264+ }
265+ fclose(fp);
266+ if (found) {
267+ printf("%s %s%s\n", policy, decision, condition);
268+ return 1;
269+ }
270+ fprintf(stderr, "Can't find %s %s%s\n",
271+ policy, decision, condition);
272+ return 0;
273+}
274+
275+static void reset_policy(void)
276+{
277+ FILE *fp2 = fopen(POLDIR "/policy", "r");
278+ FILE *fp1 = fopen(POLDIR "/policy", "w");
279+ if (!fp1 || !fp2) {
280+ fprintf(stderr, " Can't open " POLDIR "/policy\n");
281+ exit(1);
282+ }
283+ while (1) {
284+ const int c = fgetc(fp2);
285+ if (c == EOF)
286+ break;
287+ fputc(c, fp1);
288+ if (c == '\n')
289+ fprintf(fp1, "delete ");
290+ }
291+ fclose(fp2);
292+ fclose(fp1);
293+
294+ /* Do not leave the init process in stopped state. */
295+ kill(1, SIGCONT);
296+
297+ /* Undo mount("/", MS_REC|MS_SHARED) made by systemd. */
298+ mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL);
299+}
300+
301+int main(int argc, char *argv[])
302+{
303+ unsigned int i;
304+ char buffer[16384];
305+ struct {
306+ const char *action;
307+ void (*func) (void);
308+ } testcases[] = {
309+ { "execute", test_execute },
310+ { "read", test_read },
311+ { "write", test_write },
312+ { "append", test_append },
313+ { "create", test_create },
314+ { "unlink", test_unlink },
315+ { "getattr", test_getattr },
316+ { "mkdir", test_mkdir },
317+ { "rmdir", test_rmdir },
318+ { "mkfifo", test_mkfifo },
319+ { "mksock", test_mksock },
320+ { "truncate", test_truncate },
321+ { "symlink", test_symlink },
322+ { "mkblock", test_mkblock },
323+ { "mkchar", test_mkchar },
324+ { "link", test_link },
325+ { "rename", test_rename },
326+ { "chmod", test_chmod },
327+ { "chown", test_chown },
328+ { "chgrp", test_chgrp },
329+ { "ioctl", test_ioctl },
330+ { "chroot", test_chroot },
331+ { "mount", test_mount1 },
332+ { "mount", test_mount2 },
333+ { "mount", test_mount3 },
334+ { "mount", test_mount4 },
335+ { "unmount", test_unmount },
336+ { "pivot_root", test_pivot_root },
337+ /*
338+ acl inet_stream_bind
339+ acl inet_stream_listen
340+ acl inet_stream_connect
341+ acl inet_stream_accept
342+ acl inet_dgram_bind
343+ acl inet_dgram_send
344+ acl inet_dgram_recv
345+ acl inet_raw_bind
346+ acl inet_raw_send
347+ acl inet_raw_recv
348+ acl unix_stream_bind
349+ acl unix_stream_listen
350+ # acl unix_stream_connect
351+ acl unix_stream_accept
352+ acl unix_dgram_bind
353+ acl unix_dgram_send
354+ acl unix_dgram_recv
355+ acl unix_seqpacket_bind
356+ acl unix_seqpacket_listen
357+ acl unix_seqpacket_connect
358+ acl unix_seqpacket_accept
359+ # acl environ
360+ acl ptrace
361+ acl signal
362+ acl modify_policy
363+ # acl use_netlink_socket
364+ acl use_packet_socket
365+ acl use_reboot
366+ acl use_vhangup
367+ acl set_time
368+ acl set_priority
369+ acl set_hostname
370+ acl use_kernel_module
371+ acl use_new_kernel
372+ # acl auto_domain_transition
373+ acl manual_domain_transition
374+ */
375+ { NULL, NULL },
376+ };
377+ int fd_out = open(POLDIR "/policy", O_WRONLY);
378+ char *cp1;
379+ char *cp2;
380+
381+ reset_policy();
382+
383+ memset(buffer, 0, sizeof(buffer));
384+ if (fd_out == EOF) {
385+ fprintf(stderr, "Can't write " POLDIR "/policy interface.\n");
386+ goto out;
387+ }
388+ {
389+ int fd = open(POLDIR "/audit", O_RDONLY);
390+ char buffer[4096];
391+ while (read(fd, buffer, sizeof(buffer)) > 0);
392+ close(fd);
393+ }
394+ cp1 = "POLICY_VERSION=20120401\n"
395+ "quota memory audit 16777216\n"
396+ "quota memory query 1048576\n"
397+ "quota audit[1] allowed=1024 denied=1024 unmatched=1024\n";
398+ i = strlen(cp1);
399+ if (write(fd_out, cp1, i) != i) {
400+ fprintf(stderr, "Can't write " POLDIR "/policy interface.\n");
401+ goto out;
402+ }
403+ for (i = 0; testcases[i].action; i++) {
404+ int fd_in = open(POLDIR "/policy", O_RDONLY);
405+ if (fd_in == EOF) {
406+ fprintf(stderr,
407+ "Can't read " POLDIR "/policy interface.\n");
408+ goto out;
409+ }
410+ snprintf(buffer, sizeof(buffer) - 1, "0 acl %s task.pid=%u\n"
411+ " audit 1\n", testcases[i].action, getpid());
412+ write(fd_out, buffer, strlen(buffer));
413+ testcases[i].func();
414+ cp2 = read_log("result=unmatched", testcases[i].action);
415+ if (!cp2)
416+ goto out;
417+ cp1 = "0 deny ";
418+ write(fd_out, cp1, strlen(cp1));
419+ if (!strcmp(testcases[i].action, "rmdir")) {
420+ char *cp3 = strstr(cp2, " path.ino=");
421+ char *cp4 = cp3 ? strchr(cp3 + 1, ' ') : NULL;
422+ if (cp4)
423+ memmove(cp3, cp4, strlen(cp4) + 1);
424+ }
425+ write(fd_out, cp2, strlen(cp2));
426+ if (!check_policy(buffer, cp1, cp2))
427+ goto out;
428+ testcases[i].func();
429+ cp2 = read_log("result=denied", testcases[i].action);
430+ if (!cp2)
431+ goto out;
432+ snprintf(buffer, sizeof(buffer) - 1,
433+ "delete 0 acl %s task.pid=%u\n",
434+ testcases[i].action, getpid());
435+ write(fd_out, buffer, strlen(buffer));
436+ }
437+ return 0;
438+out:
439+ return 1;
440+}
--- tags/caitsith-tools/0.2.2/kernel_test/caitsith_wildcard_test.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/kernel_test/caitsith_wildcard_test.c (revision 242)
@@ -0,0 +1,692 @@
1+#include <stdio.h>
2+#include <string.h>
3+#include <stdlib.h>
4+
5+#define bool _Bool
6+#define true 1
7+#define false 0
8+#define u32 unsigned int
9+#define u8 unsigned char
10+
11+struct cs_path_info {
12+ const char *name;
13+ u32 hash; /* = full_name_hash(name, strlen(name)) */
14+ u32 total_len; /* = strlen(name) */
15+ u32 const_len; /* = cs_const_part_length(name) */
16+};
17+
18+static void out_of_memory(void)
19+{
20+ fprintf(stderr, "Out of memory\n");
21+ exit(1);
22+}
23+
24+/* Copied from Linux kernel source code. */
25+static unsigned int full_name_hash(const unsigned char *name, unsigned int len)
26+{
27+ unsigned long hash = 0;
28+ while (len--) {
29+ unsigned long c = *name++;
30+ hash = (hash + (c << 4) + (c >> 4)) * 11;
31+ }
32+ return (unsigned int) hash;
33+}
34+
35+/**
36+ * cs_pathcmp - strcmp() for "struct cs_path_info" structure.
37+ *
38+ * @a: Pointer to "struct cs_path_info".
39+ * @b: Pointer to "struct cs_path_info".
40+ *
41+ * Returns true if @a != @b, false otherwise.
42+ */
43+static inline bool cs_pathcmp(const struct cs_path_info *a,
44+ const struct cs_path_info *b)
45+{
46+ return a->hash != b->hash || strcmp(a->name, b->name);
47+}
48+
49+/**
50+ * cs_const_part_length - Evaluate the initial length without a pattern in a token.
51+ *
52+ * @filename: The string to evaluate. Maybe NULL.
53+ *
54+ * Returns the initial length without a pattern in @filename.
55+ */
56+static int cs_const_part_length(const char *filename)
57+{
58+ char c;
59+ int len = 0;
60+ if (!filename)
61+ return 0;
62+ while (1) {
63+ c = *filename++;
64+ if (!c)
65+ break;
66+ if (c != '\\') {
67+ len++;
68+ continue;
69+ }
70+ c = *filename++;
71+ switch (c) {
72+ case '0': /* "\ooo" */
73+ case '1':
74+ case '2':
75+ case '3':
76+ c = *filename++;
77+ if (c < '0' || c > '7')
78+ break;
79+ c = *filename++;
80+ if (c < '0' || c > '7')
81+ break;
82+ len += 4;
83+ continue;
84+ }
85+ break;
86+ }
87+ return len;
88+}
89+
90+/**
91+ * cs_fill_path_info - Fill in "struct cs_path_info" members.
92+ *
93+ * @ptr: Pointer to "struct cs_path_info" to fill in.
94+ *
95+ * Returns nothing.
96+ *
97+ * The caller sets "struct cs_path_info"->name.
98+ */
99+static void cs_fill_path_info(struct cs_path_info *ptr)
100+{
101+ const char *name = ptr->name;
102+ const int len = strlen(name);
103+ ptr->total_len = len;
104+ ptr->const_len = cs_const_part_length(name);
105+ ptr->hash = full_name_hash((const unsigned char *) name, len);
106+}
107+
108+/**
109+ * cs_byte_range - Check whether the string is a \ooo style octal value.
110+ *
111+ * @str: Pointer to the string.
112+ *
113+ * Returns true if @str is a \ooo style octal value, false otherwise.
114+ */
115+static bool cs_byte_range(const char *str)
116+{
117+ return *str >= '0' && *str++ <= '3' &&
118+ *str >= '0' && *str++ <= '7' &&
119+ *str >= '0' && *str <= '7';
120+}
121+
122+/**
123+ * cs_decimal - Check whether the character is a decimal character.
124+ *
125+ * @c: The character to check.
126+ *
127+ * Returns true if @c is a decimal character, false otherwise.
128+ */
129+static bool cs_decimal(const char c)
130+{
131+ return c >= '0' && c <= '9';
132+}
133+
134+/**
135+ * cs_hexadecimal - Check whether the character is a hexadecimal character.
136+ *
137+ * @c: The character to check.
138+ *
139+ * Returns true if @c is a hexadecimal character, false otherwise.
140+ */
141+static bool cs_hexadecimal(const char c)
142+{
143+ return (c >= '0' && c <= '9') ||
144+ (c >= 'A' && c <= 'F') ||
145+ (c >= 'a' && c <= 'f');
146+}
147+
148+/**
149+ * cs_alphabet_char - Check whether the character is an alphabet.
150+ *
151+ * @c: The character to check.
152+ *
153+ * Returns true if @c is an alphabet character, false otherwise.
154+ */
155+static bool cs_alphabet_char(const char c)
156+{
157+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
158+}
159+
160+/**
161+ * cs_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
162+ *
163+ * @filename: The start of string to check.
164+ * @filename_end: The end of string to check.
165+ * @pattern: The start of pattern to compare.
166+ * @pattern_end: The end of pattern to compare.
167+ *
168+ * Returns true if @filename matches @pattern, false otherwise.
169+ */
170+static bool cs_file_matches_pattern2(const char *filename,
171+ const char *filename_end,
172+ const char *pattern,
173+ const char *pattern_end)
174+{
175+ while (filename < filename_end && pattern < pattern_end) {
176+ char c;
177+ if (*pattern != '\\') {
178+ if (*filename++ != *pattern++)
179+ return false;
180+ continue;
181+ }
182+ c = *filename;
183+ pattern++;
184+ switch (*pattern) {
185+ int i;
186+ int j;
187+ case '?':
188+ if (c == '/') {
189+ return false;
190+ } else if (c == '\\') {
191+ if (cs_byte_range(filename + 1))
192+ filename += 3;
193+ else
194+ return false;
195+ }
196+ break;
197+ case '+':
198+ if (!cs_decimal(c))
199+ return false;
200+ break;
201+ case 'x':
202+ if (!cs_hexadecimal(c))
203+ return false;
204+ break;
205+ case 'a':
206+ if (!cs_alphabet_char(c))
207+ return false;
208+ break;
209+ case '0':
210+ case '1':
211+ case '2':
212+ case '3':
213+ if (c == '\\' && cs_byte_range(filename + 1)
214+ && !strncmp(filename + 1, pattern, 3)) {
215+ filename += 3;
216+ pattern += 2;
217+ break;
218+ }
219+ return false; /* Not matched. */
220+ case '*':
221+ case '@':
222+ for (i = 0; i <= filename_end - filename; i++) {
223+ if (cs_file_matches_pattern2(filename + i,
224+ filename_end,
225+ pattern + 1,
226+ pattern_end))
227+ return true;
228+ c = filename[i];
229+ if (c == '.' && *pattern == '@')
230+ break;
231+ if (c != '\\')
232+ continue;
233+ if (cs_byte_range(filename + i + 1))
234+ i += 3;
235+ else
236+ break; /* Bad pattern. */
237+ }
238+ return false; /* Not matched. */
239+ default:
240+ j = 0;
241+ c = *pattern;
242+ if (c == '$') {
243+ while (cs_decimal(filename[j]))
244+ j++;
245+ } else if (c == 'X') {
246+ while (cs_hexadecimal(filename[j]))
247+ j++;
248+ } else if (c == 'A') {
249+ while (cs_alphabet_char(filename[j]))
250+ j++;
251+ }
252+ for (i = 1; i <= j; i++) {
253+ if (cs_file_matches_pattern2(filename + i,
254+ filename_end,
255+ pattern + 1,
256+ pattern_end))
257+ return true;
258+ }
259+ return false; /* Not matched or bad pattern. */
260+ }
261+ filename++;
262+ pattern++;
263+ }
264+ /* Ignore trailing "\*" and "\@" in @pattern. */
265+ while (*pattern == '\\' &&
266+ (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
267+ pattern += 2;
268+ return filename == filename_end && pattern == pattern_end;
269+}
270+
271+/**
272+ * cs_file_matches_pattern - Pattern matching without '/' character.
273+ *
274+ * @filename: The start of string to check.
275+ * @filename_end: The end of string to check.
276+ * @pattern: The start of pattern to compare.
277+ * @pattern_end: The end of pattern to compare.
278+ *
279+ * Returns true if @filename matches @pattern, false otherwise.
280+ */
281+static bool cs_file_matches_pattern(const char *filename,
282+ const char *filename_end,
283+ const char *pattern,
284+ const char *pattern_end)
285+{
286+ const char *pattern_start = pattern;
287+ bool first = true;
288+ bool result;
289+ if (filename_end > filename && memchr(filename, '/', filename_end - filename)) {
290+ printf("'");
291+ fwrite(filename, 1, filename_end - filename, stdout);
292+ printf("', '");
293+ fwrite(pattern, 1, pattern_end - pattern, stdout);
294+ printf("'\n");
295+ }
296+ if (pattern_end > pattern && memchr(pattern, '/', pattern_end - pattern)) {
297+ printf("'");
298+ fwrite(filename, 1, filename_end - filename, stdout);
299+ printf("', '");
300+ fwrite(pattern, 1, pattern_end - pattern, stdout);
301+ printf("'\n");
302+ }
303+ while (pattern < pattern_end - 1) {
304+ /* Split at "\-" pattern. */
305+ if (*pattern++ != '\\' || *pattern++ != '-')
306+ continue;
307+ result = cs_file_matches_pattern2(filename, filename_end,
308+ pattern_start, pattern - 2);
309+ if (first)
310+ result = !result;
311+ if (result)
312+ return false;
313+ first = false;
314+ pattern_start = pattern;
315+ }
316+ result = cs_file_matches_pattern2(filename, filename_end,
317+ pattern_start, pattern_end);
318+ return first ? result : !result;
319+}
320+
321+/**
322+ * cs_path_matches_pattern2 - Do pathname pattern matching.
323+ *
324+ * @f: The start of string to check.
325+ * @p: The start of pattern to compare.
326+ *
327+ * Returns true if @f matches @p, false otherwise.
328+ */
329+static bool cs_path_matches_pattern2(const char *f, const char *p)
330+{
331+ const char *f_delimiter;
332+ const char *p_delimiter;
333+ while (*f && *p) {
334+ f_delimiter = strchr(f + 1, '/');
335+ if (!f_delimiter)
336+ f_delimiter = f + strlen(f);
337+ p_delimiter = strchr(p + 1, '/');
338+ if (!p_delimiter)
339+ p_delimiter = p + strlen(p);
340+ if (*p == '/' && *(p + 1) == '\\') {
341+ if (*(p + 2) == '(') {
342+ /* Check zero repetition. */
343+ if (cs_path_matches_pattern2(f, p_delimiter))
344+ return true;
345+ /* Check one or more repetition. */
346+ goto repetition;
347+ }
348+ if (*(p + 2) == '{')
349+ goto repetition;
350+ }
351+ if ((*f == '/' || *p == '/') && *f++ != *p++)
352+ return false;
353+ if (!cs_file_matches_pattern(f, f_delimiter, p, p_delimiter))
354+ return false;
355+ f = f_delimiter;
356+ p = p_delimiter;
357+ }
358+ /* Ignore trailing "\*" and "\@" in @pattern. */
359+ while (*p == '\\' && (*(p + 1) == '*' || *(p + 1) == '@'))
360+ p += 2;
361+ return !*f && !*p;
362+repetition:
363+ do {
364+ /* Compare current component with pattern. */
365+ if (!cs_file_matches_pattern(f + 1, f_delimiter,
366+ p + 3, p_delimiter - 2))
367+ break;
368+ /* Proceed to next component. */
369+ f = f_delimiter;
370+ if (!*f)
371+ break;
372+ /* Continue comparison. */
373+ if (cs_path_matches_pattern2(f, p_delimiter))
374+ return true;
375+ f_delimiter = strchr(f + 1, '/');
376+ } while (f_delimiter);
377+ return false; /* Not matched. */
378+}
379+
380+/**
381+ * cs_path_matches_pattern - Check whether the given filename matches the given pattern.
382+ *
383+ * @filename: The filename to check.
384+ * @pattern: The pattern to compare.
385+ *
386+ * Returns true if matches, false otherwise.
387+ *
388+ * The following patterns are available.
389+ * \ooo Octal representation of a byte.
390+ * \* Zero or more repetitions of characters other than '/'.
391+ * \@ Zero or more repetitions of characters other than '/' or '.'.
392+ * \? 1 byte character other than '/'.
393+ * \$ One or more repetitions of decimal digits.
394+ * \+ 1 decimal digit.
395+ * \X One or more repetitions of hexadecimal digits.
396+ * \x 1 hexadecimal digit.
397+ * \A One or more repetitions of alphabet characters.
398+ * \a 1 alphabet character.
399+ *
400+ * \- Subtraction operator.
401+ *
402+ * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
403+ * /dir/dir/dir/ ).
404+ *
405+ * /\(dir\)/ '/' + 'Zero or more repetitions of dir/' (e.g. / /dir/
406+ * /dir/dir/ ).
407+ */
408+static bool cs_path_matches_pattern(const struct cs_path_info *filename,
409+ const struct cs_path_info *pattern)
410+{
411+ const char *f = filename->name;
412+ const char *p = pattern->name;
413+ const int len = pattern->const_len;
414+ /* If @pattern doesn't contain pattern, I can use strcmp(). */
415+ if (len == pattern->total_len)
416+ return !cs_pathcmp(filename, pattern);
417+ /* Compare the initial length without patterns. */
418+ if (len) {
419+ if (strncmp(f, p, len))
420+ return false;
421+ f += len - 1;
422+ p += len - 1;
423+ }
424+ return cs_path_matches_pattern2(f, p);
425+}
426+
427+/**
428+ * cs_correct_word - Check whether the given string follows the naming rules.
429+ *
430+ * @string: The string to check.
431+ * @allow_pattern: True if allow use of patterns, false otherwise.
432+ *
433+ * Returns true if @string follows the naming rules, false otherwise.
434+ */
435+static bool cs_correct_word(const char *string, bool allow_pattern)
436+{
437+ u8 recursion = 20;
438+ const char *const start = string;
439+ u8 in_repetition = 0;
440+ if (!*string)
441+ goto out;
442+ while (*string) {
443+ unsigned char c = *string++;
444+ if (in_repetition && c == '/')
445+ goto out;
446+ if (c <= ' ' || c >= 127)
447+ goto out;
448+ if (c != '\\')
449+ continue;
450+ c = *string++;
451+ if (c >= '0' && c <= '3') {
452+ unsigned char d;
453+ unsigned char e;
454+ d = *string++;
455+ if (d < '0' || d > '7')
456+ goto out;
457+ e = *string++;
458+ if (e < '0' || e > '7')
459+ goto out;
460+ c = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
461+ if (c <= ' ' || c >= 127 || c == '\\')
462+ continue;
463+ goto out;
464+ }
465+ if (!allow_pattern)
466+ goto out;
467+ switch (c) {
468+ case '+': /* "\+" */
469+ case '?': /* "\?" */
470+ case 'x': /* "\x" */
471+ case 'a': /* "\a" */
472+ case '-': /* "\-" */
473+ continue;
474+ }
475+ /* Reject too deep wildcard that consumes too much stack. */
476+ if (!recursion--)
477+ goto out;
478+ switch (c) {
479+ case '*': /* "\*" */
480+ case '@': /* "\@" */
481+ case '$': /* "\$" */
482+ case 'X': /* "\X" */
483+ case 'A': /* "\A" */
484+ continue;
485+ case '{': /* "/\{" */
486+ if (string - 3 < start || *(string - 3) != '/')
487+ goto out;
488+ in_repetition = 1;
489+ continue;
490+ case '}': /* "\}/" */
491+ if (in_repetition != 1 || *string++ != '/')
492+ goto out;
493+ in_repetition = 0;
494+ continue;
495+ case '(': /* "/\(" */
496+ if (string - 3 < start || *(string - 3) != '/')
497+ goto out;
498+ in_repetition = 2;
499+ continue;
500+ case ')': /* "\)/" */
501+ if (in_repetition != 2 || *string++ != '/')
502+ goto out;
503+ in_repetition = 0;
504+ continue;
505+ }
506+ goto out;
507+ }
508+ if (in_repetition)
509+ goto out;
510+ return true;
511+out:
512+ return false;
513+}
514+
515+/**
516+ * cs_get_name - Allocate memory for string data.
517+ *
518+ * @name: The string to save.
519+ *
520+ * Returns pointer to "struct cs_path_info" on success, NULL otherwise.
521+ */
522+static struct cs_path_info *cs_get_name(const char *name)
523+{
524+ struct cs_path_info *ptr =
525+ (struct cs_path_info *) malloc(sizeof(struct cs_path_info));
526+ if (!ptr)
527+ out_of_memory();
528+ ptr->name = strdup(name);
529+ if (!ptr->name)
530+ out_of_memory();
531+ cs_fill_path_info(ptr);
532+ return ptr;
533+}
534+
535+/**
536+ * cs_put_name - Free memory for string data.
537+ *
538+ * @name: Pointer to "struct cs_path_info". Maybe NULL.
539+ *
540+ * Returns nothing.
541+ */
542+static void cs_put_name(struct cs_path_info *name)
543+{
544+ if (name) {
545+ free((void *) name->name);
546+ free(name);
547+ }
548+}
549+
550+/**
551+ * cs_normalize_line - Format string.
552+ *
553+ * @buffer: The line to normalize.
554+ *
555+ * Returns nothing.
556+ *
557+ * Leading and trailing whitespaces are removed.
558+ * Multiple whitespaces are packed into single space.
559+ */
560+static void cs_normalize_line(char *buffer)
561+{
562+ unsigned char *sp = (unsigned char *) buffer;
563+ unsigned char *dp = (unsigned char *) buffer;
564+ bool first = true;
565+ while (*sp && (*sp <= ' ' || *sp >= 127))
566+ sp++;
567+ while (*sp) {
568+ if (!first)
569+ *dp++ = ' ';
570+ first = false;
571+ while (*sp > ' ' && *sp < 127)
572+ *dp++ = *sp++;
573+ while (*sp && (*sp <= ' ' || *sp >= 127))
574+ sp++;
575+ }
576+ *dp = '\0';
577+}
578+
579+static struct testcase {
580+ const char *pathname;
581+ const char *pattern;
582+ _Bool match;
583+} testcases[] = {
584+ { "/tmp/000", "/tmp/\\*", 1 },
585+ { "/tmp/000", "/tmp/\\@", 1 },
586+ { "/tmp/000", "/tmp/\\?\\?\\?", 1 },
587+ { "/tmp/000", "/tmp/\\*\\$\\@\\$", 1 },
588+ { "/tmp/000\\040111", "/tmp/\\*", 1 },
589+ { "/tmp/000\\040111", "/tmp/\\X", 0 },
590+ { "/tmp/000\\040111", "/tmp/\\$\\?\\$", 1 },
591+ { "/tmp/000111", "/tmp/\\(\\*\\)/\\*", 1 },
592+ { "/tmp/000/111", "/tmp/\\(\\*\\)/\\*", 1 },
593+ { "/tmp/0/0/0/1/1/1", "/tmp/\\(\\*\\)/\\*", 1 },
594+ { "/tmp/0/0/0/1/1/1", "/tmp/\\{\\$\\}/\\$", 1 },
595+ { "/tmp/0/0/0/1/1/1", "/tmp/\\{\\a\\}/\\$", 0 },
596+ { "/tmp/0/0/0/1/1/1", "/tmp/\\{\\$\\-\\a\\}/\\$", 1 },
597+ { "/tmp/0/0/0/1/1/1", "/tmp/\\{\\x\\-\\a\\}/\\$", 1 },
598+ { "/tmp/\\001/\\002/\\040/^/$", "/tmp/\\{\\*\\-\\a\\}/\\?", 1 },
599+ { "/tmp/\\001/\\002/\\040/^/$", "/tmp/\\{\\*\\-\\a\\-\\x\\}/\\?", 1 },
600+ { "/tmp/$", "/tmp/\\*\\-\\a\\-\\x", 1 },
601+ { "/bin/true", "/bin/\\*", 1 },
602+ { "/bin/true", "/bin\\@\\*/\\*", 1 },
603+ { "/usr/local/", "/usr/\\*/", 1 },
604+ { "/usr/local/", "/usr/\\*\\*\\@\\*/", 1 },
605+ { "pipe:[12345]", "pipe:[\\$]", 1 },
606+ { "socket:[family=1:type=2:protocol=3]", "socket:[family=1:type=2:protocol=\\$]", 1 },
607+ { "http://tomoyo.osdn.jp/", "\\*/\\*/\\*/", 1 },
608+ { "http://tomoyo.osdn.jp/index.html", "\\*/\\*/\\*/\\*", 1 },
609+ { "http://tomoyo.osdn.jp/index.html", "\\*/\\*/\\*/\\*\\*\\@\\*\\@", 1 },
610+ { "http://tomoyo.osdn.jp/index.html", "\\*/\\@\\*/\\*\\@/\\*\\@\\*\\@\\*", 1 },
611+ { "http://tomoyo.osdn.jp/1.8/index.html", "http://\\{\\*\\}/\\@.html", 1 },
612+ { "http://tomoyo.osdn.jp/index.html", "\\*://\\@.osdn.jp/\\*", 1 },
613+ { "http://tomoyo.osdn.jp/index.html", "\\*://\\@.osdn.jp/\\*", 1 },
614+ { "http://osdn.jp/projects/tomoyo/svn/view/trunk/1.8.x/ccs-patch/security/ccsecurity/?root=tomoyo", "\\*://\\@osdn.jp/\\{\\*\\}/?root=tomoyo", 1 },
615+ { "http://osdn.jp/projects/tomoyo/svn/view/trunk/1.8.x/ccs-patch/security/?root=tomoyo", "\\*://\\@osdn.jp/\\{\\*\\}/?root=tomoyo", 1 },
616+ { "http://osdn.jp/projects/tomoyo/svn/view/trunk/1.8.x/ccs-patch/?root=tomoyo", "\\*://\\@osdn.jp/\\{\\*\\}/?root=tomoyo", 1 },
617+ { "http://osdn.jp/projects/tomoyo/svn/view/trunk/1.8.x//ccs-patch///security//ccsecurity///?root=tomoyo", "\\*://\\@osdn.jp/\\{\\*\\-.\\-..\\-\\*%\\*\\}/?root=tomoyo\\*\\*", 1 },
618+ { "/var/www/html/test/test/test/index.html", "/var/www/html/\\{test\\}/\\*.html", 1 },
619+ { "/etc/skel/", "/etc/\\{\\*\\}/\\*/", 0 },
620+ { "/etc/passwd", "/etc/\\{\\*\\}/\\*", 0 },
621+ { "/bin/true", "/bin/\\*/", 0 },
622+ { "/bin/", "/bin/\\*", 1 },
623+ { "/bin/", "/bin/\\@", 1 },
624+ { "/bin/", "/bin/\\@\\@", 1 },
625+ { "http://tomoyo.osdn.jp/", "\\*/\\*/\\*/\\?", 0 },
626+ { "http://tomoyo.osdn.jp/index.html", "\\*/\\*/\\*/\\@", 0 },
627+ { "http://tomoyo.osdn.jp/index.html", "http://\\*/\\@", 0 },
628+ { "socket:[family=1:type=2:protocol=3]", "/\\{\\*\\}/socket:[\\*]", 0 },
629+ { "/", "/\\(\\*\\)/\\*", 1 },
630+ { "/", "/\\{\\*\\}/\\*", 0 },
631+ { "/foo/", "/foo/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\*", 1 },
632+ { "/foo/", "/foo/\\{\\*\\}/\\*", 0 },
633+ { "/foo/bar/", "/foo/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\*", 1 },
634+ { "/foo/bar/", "/foo/\\{\\*\\}/\\*", 1 },
635+ { "/foo/bar", "/foo/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/bar", 1 },
636+ { "/foo/bar", "/foo/\\{\\*\\}/bar", 0 },
637+ { "/foo/bar", "/foo/\\*/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\(\\*\\)/\\*", 0 },
638+ { "/foo/bar/", "/foo/\\(\\*\\)/", 1 },
639+ { "/foo/bar/", "/foo/\\*/\\(\\*\\)/", 1 },
640+ { "/foo/bar/", "/foo/\\*/\\*/\\(\\*\\)/", 0 },
641+ { "/foo/bar/", "/foo/\\*/\\(\\*\\)/\\*/", 0 },
642+ { "/foo/", "/foo/\\(\\*\\)/", 1 },
643+ { "abc", "abc", 1 },
644+ { "abc", "\\A\\A\\A", 1 },
645+ { "abc", "\\X\\X\\X", 1 },
646+ { "abc", "\\*\\*\\*", 1 },
647+ { "abc", "\\@\\@\\@", 1 },
648+ { "abc", "\\a\\@\\x", 1 },
649+ { "abc", "\\?\\?\\?", 1 },
650+ { "abc", "\\?\\@\\?\\*", 1 },
651+ { "abc", "\\?\\@\\?\\*\\?", 1 },
652+ { "abc", "def", 0 },
653+ { "abc/def", "\\*/\\(\\X\\)/\\X", 1 },
654+ { "abc/def", "\\*/\\{\\X\\}/\\X", 0 },
655+ { "abc/def/012", "\\*/\\(\\X\\)/\\X", 1 },
656+ { "abc/def/012", "\\*/\\{\\X\\}/\\X", 1 },
657+ { "abc/def/012/345/6789", "\\*/\\(\\X\\)/\\X", 1 },
658+ { "abc/def/012/345/6789", "\\*/\\{\\X\\}/\\X", 1 },
659+ { "abc/345/012/def/6789", "\\*/\\(\\$\\)/\\X", 0 },
660+ { "abc/345/012/def/6789", "\\*/\\(\\*\\)/\\*/", 0 },
661+ { "abc/345/012/def/6789/////1//23///", "\\*/\\(\\*\\)/\\*/", 1 },
662+ { "abc/345/012/def/6789/////1//23//./", "\\*/\\(\\*\\)/\\?/", 1 },
663+ { "abc/345/012/def/6789//1//23//.", "\\*/\\(\\*\\)/\\?/", 0 },
664+ { "abc/345/012/def/6789//1//23//", "\\*/\\(\\*\\)/\\?", 0 },
665+ { "abc", "abc/\\*", 0 },
666+ { "abc/", "abc/\\*", 1 },
667+ { NULL, NULL, 0 },
668+};
669+
670+int main(int argc, char *argv[])
671+{
672+ struct testcase *ptr;
673+ struct cs_path_info *path;
674+ struct cs_path_info *pattern;
675+ for (ptr = testcases; ptr->pathname; ptr++) {
676+ if (!cs_correct_word(ptr->pathname, 0)) {
677+ printf("Bad path: %s\n", ptr->pathname);
678+ continue;
679+ } else if (!cs_correct_word(ptr->pattern, 1)) {
680+ printf("Bad pattern: %s\n", ptr->pattern);
681+ continue;
682+ }
683+ path = cs_get_name(ptr->pathname);
684+ pattern = cs_get_name(ptr->pattern);
685+ if (cs_path_matches_pattern(path, pattern) != ptr->match)
686+ printf("Failed (\"%s\", \"%s\") == %d\n",
687+ ptr->pathname, ptr->pattern, ptr->match);
688+ cs_put_name(path);
689+ cs_put_name(pattern);
690+ }
691+ return 0;
692+}
--- tags/caitsith-tools/0.2.2/usr_sbin/caitsithtools.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/usr_sbin/caitsithtools.c (revision 242)
@@ -0,0 +1,409 @@
1+/*
2+ * caitsithtools.c
3+ *
4+ * CaitSith's utilities.
5+ *
6+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
7+ *
8+ * Version: 0.2 2016/10/16
9+ *
10+ * This program is free software; you can redistribute it and/or modify it
11+ * under the terms of the GNU General Public License v2 as published by the
12+ * Free Software Foundation.
13+ *
14+ * This program is distributed in the hope that it will be useful, but WITHOUT
15+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17+ * more details.
18+ *
19+ * You should have received a copy of the GNU General Public License along with
20+ * this program; if not, write to the Free Software Foundation, Inc.,
21+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22+ */
23+#include "caitsithtools.h"
24+#include <unistd.h>
25+#include <sys/mount.h>
26+#include <sched.h>
27+
28+/* Use caitsith-agent process? */
29+_Bool ccs_network_mode = false;
30+/* The IPv4 address of the remote host running the caitsith-agent . */
31+u32 ccs_network_ip = INADDR_NONE;
32+/* The port number of the remote host running the caitsith-agent . */
33+u16 ccs_network_port = 0;
34+
35+const char *CCS_PROC_POLICY_DIR = "/sys/kernel/security/caitsith";
36+const char *CCS_PROC_POLICY_POLICY = "/sys/kernel/security/caitsith/policy";
37+
38+/* Prototypes */
39+
40+/* Utility functions */
41+
42+/**
43+ * ccs_out_of_memory - Print error message and abort.
44+ *
45+ * This function does not return.
46+ */
47+static void ccs_out_of_memory(void)
48+{
49+ fprintf(stderr, "Out of memory. Aborted.\n");
50+ exit(1);
51+}
52+
53+/**
54+ * ccs_strdup - strdup() with abort on error.
55+ *
56+ * @string: String to duplicate.
57+ *
58+ * Returns copy of @string on success, abort otherwise.
59+ */
60+char *ccs_strdup(const char *string)
61+{
62+ char *cp = strdup(string);
63+ if (!cp)
64+ ccs_out_of_memory();
65+ return cp;
66+}
67+
68+/**
69+ * ccs_realloc - realloc() with abort on error.
70+ *
71+ * @ptr: Pointer to void.
72+ * @size: New size.
73+ *
74+ * Returns return value of realloc() on success, abort otherwise.
75+ */
76+void *ccs_realloc(void *ptr, const size_t size)
77+{
78+ void *vp = realloc(ptr, size);
79+ if (!vp)
80+ ccs_out_of_memory();
81+ return vp;
82+}
83+
84+/**
85+ * ccs_malloc - malloc() with abort on error.
86+ *
87+ * @size: Size to allocate.
88+ *
89+ * Returns return value of malloc() on success, abort otherwise.
90+ *
91+ * Allocated memory is cleared with 0.
92+ */
93+void *ccs_malloc(const size_t size)
94+{
95+ void *vp = malloc(size);
96+ if (!vp)
97+ ccs_out_of_memory();
98+ memset(vp, 0, size);
99+ return vp;
100+}
101+
102+/**
103+ * ccs_str_starts - Check whether the given string starts with the given keyword.
104+ *
105+ * @str: Pointer to "char *".
106+ * @begin: Pointer to "const char *".
107+ *
108+ * Returns true if @str starts with @begin, false otherwise.
109+ *
110+ * Note that @begin will be removed from @str before returning true. Therefore,
111+ * @str must not be "const char *".
112+ *
113+ * Note that this function in kernel source has different arguments and behaves
114+ * differently.
115+ */
116+_Bool ccs_str_starts(char *str, const char *begin)
117+{
118+ const int len = strlen(begin);
119+ if (strncmp(str, begin, len))
120+ return false;
121+ memmove(str, str + len, strlen(str + len) + 1);
122+ return true;
123+}
124+
125+/**
126+ * ccs_normalize_line - Format string.
127+ *
128+ * @buffer: The line to normalize.
129+ *
130+ * Returns nothing.
131+ *
132+ * Leading and trailing whitespaces are removed.
133+ * Multiple whitespaces are packed into single space.
134+ */
135+void ccs_normalize_line(char *buffer)
136+{
137+ unsigned char *sp = (unsigned char *) buffer;
138+ unsigned char *dp = (unsigned char *) buffer;
139+ _Bool first = true;
140+ while (*sp && (*sp <= ' ' || 127 <= *sp))
141+ sp++;
142+ while (*sp) {
143+ if (!first)
144+ *dp++ = ' ';
145+ first = false;
146+ while (' ' < *sp && *sp < 127)
147+ *dp++ = *sp++;
148+ while (*sp && (*sp <= ' ' || 127 <= *sp))
149+ sp++;
150+ }
151+ *dp = '\0';
152+}
153+
154+/**
155+ * ccs_decode - Decode a string in CaitSith's rule to a string in C.
156+ *
157+ * @ascii: Pointer to "const char".
158+ * @bin: Pointer to "char". Must not contain wildcards nor '\000'.
159+ *
160+ * Returns true if @ascii was successfully decoded, false otherwise.
161+ *
162+ * Note that it is legal to pass @ascii == @bin if the caller want to decode
163+ * a string in a temporary buffer.
164+ */
165+_Bool ccs_decode(const char *ascii, char *bin)
166+{
167+ while (true) {
168+ char c = *ascii++;
169+ *bin++ = c;
170+ if (!c)
171+ break;
172+ if (c == '\\') {
173+ char d;
174+ char e;
175+ u8 f;
176+ c = *ascii++;
177+ switch (c) {
178+ case '0': /* "\ooo" */
179+ case '1':
180+ case '2':
181+ case '3':
182+ d = *ascii++;
183+ if (d < '0' || d > '7')
184+ break;
185+ e = *ascii++;
186+ if (e < '0' || e > '7')
187+ break;
188+ f = (u8) ((c - '0') << 6) +
189+ (((u8) (d - '0')) << 3) +
190+ (((u8) (e - '0')));
191+ if (f <= ' ' || f >= 127 || f == '\\') {
192+ *(bin - 1) = f;
193+ continue;
194+ }
195+ }
196+ return false;
197+ } else if (c <= ' ' || c >= 127) {
198+ return false;
199+ }
200+ }
201+ return true;
202+}
203+
204+/**
205+ * ccs_open_read - Open a file for reading.
206+ *
207+ * @filename: String to send to remote caitsith-agent program if using
208+ * network mode, file to open for reading otherwise.
209+ *
210+ * Returns pointer to "FILE" on success, NULL otherwise.
211+ */
212+FILE *ccs_open_read(const char *filename)
213+{
214+ if (ccs_network_mode) {
215+ FILE *fp = ccs_open_write(filename);
216+ if (fp) {
217+ fputc(0, fp);
218+ fflush(fp);
219+ }
220+ return fp;
221+ } else {
222+ return fopen(filename, "r");
223+ }
224+}
225+
226+/**
227+ * ccs_open_stream - Establish IP connection.
228+ *
229+ * @filename: String to send to remote caitsith-agent program.
230+ *
231+ * Retruns file descriptor on success, EOF otherwise.
232+ */
233+int ccs_open_stream(const char *filename)
234+{
235+ const int fd = socket(AF_INET, SOCK_STREAM, 0);
236+ struct sockaddr_in addr;
237+ char c;
238+ int len = strlen(filename) + 1;
239+ memset(&addr, 0, sizeof(addr));
240+ addr.sin_family = AF_INET;
241+ addr.sin_addr.s_addr = ccs_network_ip;
242+ addr.sin_port = ccs_network_port;
243+ if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) ||
244+ write(fd, filename, len) != len || read(fd, &c, 1) != 1 || c) {
245+ close(fd);
246+ return EOF;
247+ }
248+ return fd;
249+}
250+
251+/**
252+ * ccs_open_write - Open a file for writing.
253+ *
254+ * @filename: String to send to remote caitsith-agent program if using
255+ * network mode, file to open for writing otherwise.
256+ *
257+ * Returns pointer to "FILE" on success, NULL otherwise.
258+ */
259+FILE *ccs_open_write(const char *filename)
260+{
261+ if (ccs_network_mode) {
262+ const int fd = socket(AF_INET, SOCK_STREAM, 0);
263+ struct sockaddr_in addr;
264+ FILE *fp;
265+ memset(&addr, 0, sizeof(addr));
266+ addr.sin_family = AF_INET;
267+ addr.sin_addr.s_addr = ccs_network_ip;
268+ addr.sin_port = ccs_network_port;
269+ if (connect(fd, (struct sockaddr *) &addr, sizeof(addr))) {
270+ close(fd);
271+ return NULL;
272+ }
273+ fp = fdopen(fd, "r+");
274+ /* setbuf(fp, NULL); */
275+ fprintf(fp, "%s", filename);
276+ fputc(0, fp);
277+ fflush(fp);
278+ if (fgetc(fp) != 0) {
279+ fclose(fp);
280+ return NULL;
281+ }
282+ return fp;
283+ } else {
284+ return fdopen(open(filename, O_WRONLY), "w");
285+ }
286+}
287+
288+/* Is the shared buffer for ccs_freadline() owned? */
289+static _Bool ccs_buffer_locked = false;
290+
291+/**
292+ * ccs_get - Mark the shared buffer for ccs_freadline() owned.
293+ *
294+ * Returns nothing.
295+ *
296+ * This is for avoiding accidental overwriting.
297+ * ccs_freadline() have their own memory buffer.
298+ */
299+void ccs_get(void)
300+{
301+ if (ccs_buffer_locked)
302+ ccs_out_of_memory();
303+ ccs_buffer_locked = true;
304+}
305+
306+/**
307+ * ccs_put - Mark the shared buffer for ccs_freadline() no longer owned.
308+ *
309+ * Returns nothing.
310+ *
311+ * This is for avoiding accidental overwriting.
312+ * ccs_freadline() have their own memory buffer.
313+ */
314+void ccs_put(void)
315+{
316+ if (!ccs_buffer_locked)
317+ ccs_out_of_memory();
318+ ccs_buffer_locked = false;
319+}
320+
321+/**
322+ * ccs_freadline - Read a line from file to dynamically allocated buffer.
323+ *
324+ * @fp: Pointer to "FILE".
325+ *
326+ * Returns pointer to dynamically allocated buffer on success, NULL otherwise.
327+ *
328+ * The caller must not free() the returned pointer.
329+ */
330+char *ccs_freadline(FILE *fp)
331+{
332+ static char *policy = NULL;
333+ int pos = 0;
334+ while (true) {
335+ static int max_policy_len = 0;
336+ const int c = fgetc(fp);
337+ if (c == EOF)
338+ return NULL;
339+ if (ccs_network_mode && !c)
340+ return NULL;
341+ if (pos == max_policy_len) {
342+ max_policy_len += 4096;
343+ policy = ccs_realloc(policy, max_policy_len);
344+ }
345+ policy[pos++] = (char) c;
346+ if (c == '\n') {
347+ policy[--pos] = '\0';
348+ break;
349+ }
350+ }
351+ ccs_normalize_line(policy);
352+ return policy;
353+}
354+
355+/**
356+ * ccs_check_remote_host - Check whether the remote host is running with the CaitSith kernel or not.
357+ *
358+ * Returns true if running with CaitSith kernel, false otherwise.
359+ */
360+_Bool ccs_check_remote_host(_Bool exit_on_failue)
361+{
362+ int major = 0;
363+ int minor = 0;
364+ FILE *fp = ccs_open_read("version");
365+ if (!fp || (fscanf(fp, "%u.%u", &major, &minor) < 2 && major < 2016)) {
366+ const u32 ip = ntohl(ccs_network_ip);
367+ fprintf(stderr, "Can't connect to %u.%u.%u.%u:%u\n",
368+ (u8) (ip >> 24), (u8) (ip >> 16),
369+ (u8) (ip >> 8), (u8) ip, ntohs(ccs_network_port));
370+ if (fp)
371+ fclose(fp);
372+ if (exit_on_failue)
373+ exit(1);
374+ return false;
375+ } else if (major == 0 && minor == 1) {
376+ CCS_PROC_POLICY_DIR = "/proc/caitsith";
377+ CCS_PROC_POLICY_POLICY = "/proc/caitsith/policy";
378+ }
379+ fclose(fp);
380+ return true;
381+}
382+
383+_Bool ccs_check_policy_dir(_Bool exit_on_failue)
384+{
385+ if (access("/proc/caitsith/", X_OK) == 0) {
386+ CCS_PROC_POLICY_DIR = "/proc/caitsith";
387+ CCS_PROC_POLICY_POLICY = "/proc/caitsith/policy";
388+ } else if (access("/sys/kernel/security/caitsith/", X_OK) &&
389+ (unshare(CLONE_NEWNS) ||
390+ mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) ||
391+ mount("none", "/sys/kernel/security/", "securityfs", 0,
392+ NULL))) {
393+ if (errno != EBUSY) {
394+ fprintf(stderr, "Please mount securityfs on "
395+ "/sys/kernel/security/ .\n");
396+ if (exit_on_failue)
397+ exit(1);
398+ return false;
399+ }
400+ }
401+ if (chdir(CCS_PROC_POLICY_DIR)) {
402+ fprintf(stderr,
403+ "You can't run this program for this kernel.\n");
404+ if (exit_on_failue)
405+ exit(1);
406+ return false;
407+ }
408+ return true;
409+}
--- tags/caitsith-tools/0.2.2/usr_sbin/caitsith-auditd.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/usr_sbin/caitsith-auditd.c (revision 242)
@@ -0,0 +1,460 @@
1+/*
2+ * caitsith-auditd.c
3+ *
4+ * CaitSith's utilities.
5+ *
6+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
7+ *
8+ * Version: 0.2 2016/10/05
9+ *
10+ * This program is free software; you can redistribute it and/or modify it
11+ * under the terms of the GNU General Public License v2 as published by the
12+ * Free Software Foundation.
13+ *
14+ * This program is distributed in the hope that it will be useful, but WITHOUT
15+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17+ * more details.
18+ *
19+ * You should have received a copy of the GNU General Public License along with
20+ * this program; if not, write to the Free Software Foundation, Inc.,
21+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22+ */
23+#include "caitsithtools.h"
24+#include <signal.h>
25+#include <syslog.h>
26+#include <poll.h>
27+
28+#define CCS_AUDITD_CONF "/etc/caitsith/tools/auditd.conf"
29+
30+struct ccs_destination {
31+ const char *pathname;
32+ int fd;
33+};
34+
35+static struct ccs_destination *destination_list = NULL;
36+static unsigned int destination_list_len = 0;
37+
38+enum ccs_rule_types {
39+ CCS_SORT_RULE_HEADER,
40+ CCS_SORT_RULE_ACL,
41+ CCS_SORT_RULE_DESTINATION,
42+};
43+
44+enum ccs_operator_types {
45+ CCS_SORT_OPERATOR_CONTAINS,
46+ CCS_SORT_OPERATOR_EQUALS,
47+ CCS_SORT_OPERATOR_STARTS,
48+};
49+
50+struct ccs_sort_rules {
51+ enum ccs_rule_types type;
52+ enum ccs_operator_types operation;
53+ unsigned int index;
54+ const char *string;
55+ unsigned int string_len; /* strlen(string). */
56+};
57+
58+static struct ccs_sort_rules *rules = NULL;
59+static unsigned int rules_len = 0;
60+
61+static void ccs_auditd_init_rules(const char *filename)
62+{
63+ static _Bool first = 1;
64+ FILE *fp = fopen(filename, "r");
65+ unsigned int line_no = 0;
66+ unsigned int i;
67+ if (!first) {
68+ for (i = 0; i < rules_len; i++)
69+ free((void *) rules[i].string);
70+ rules_len = 0;
71+ for (i = 0; i < destination_list_len; i++) {
72+ free((void *) destination_list[i].pathname);
73+ close(destination_list[i].fd);
74+ }
75+ destination_list_len = 0;
76+ }
77+ if (!fp) {
78+ if (first)
79+ fprintf(stderr, "Can't open %s for reading.\n",
80+ filename);
81+ else
82+ syslog(LOG_WARNING, "Can't open %s for reading.\n",
83+ filename);
84+ exit(1);
85+ }
86+ ccs_get();
87+ while (true) {
88+ char *line = ccs_freadline(fp);
89+ struct ccs_sort_rules *ptr;
90+ unsigned char c;
91+ if (!line)
92+ break;
93+ line_no++;
94+ ccs_normalize_line(line);
95+ if (*line == '#' || !*line)
96+ continue;
97+ rules = ccs_realloc(rules, sizeof(struct ccs_sort_rules) *
98+ (rules_len + 1));
99+ ptr = &rules[rules_len++];
100+ memset(ptr, 0, sizeof(*ptr));
101+ if (ccs_str_starts(line, "destination ")) {
102+ if (*line != '/')
103+ goto invalid_rule;
104+ for (i = 0; i < destination_list_len; i++)
105+ if (!strcmp(destination_list[i].pathname,
106+ line))
107+ break;
108+ if (i < destination_list_len)
109+ goto store_destination;
110+ destination_list =
111+ ccs_realloc(destination_list,
112+ ++destination_list_len *
113+ sizeof(struct ccs_destination));
114+ if (!ccs_decode(line, line))
115+ goto invalid_rule;
116+ destination_list[i].pathname = ccs_strdup(line);
117+ destination_list[i].fd = EOF;
118+store_destination:
119+ ptr->type = CCS_SORT_RULE_DESTINATION;
120+ ptr->index = i;
121+ continue;
122+ }
123+ if (ccs_str_starts(line, "header"))
124+ ptr->type = CCS_SORT_RULE_HEADER;
125+ else if (ccs_str_starts(line, "acl"))
126+ ptr->type = CCS_SORT_RULE_ACL;
127+ else
128+ goto invalid_rule;
129+ switch (sscanf(line, "[%u%c", &ptr->index, &c)) {
130+ case 0:
131+ break;
132+ case 2:
133+ if (c == ']') {
134+ char *cp = strchr(line, ']') + 1;
135+ memmove(line, cp, strlen(cp) + 1);
136+ break;
137+ }
138+ default:
139+ goto invalid_rule;
140+ }
141+ if (ccs_str_starts(line, ".contains "))
142+ ptr->operation = CCS_SORT_OPERATOR_CONTAINS;
143+ else if (ccs_str_starts(line, ".equals "))
144+ ptr->operation = CCS_SORT_OPERATOR_EQUALS;
145+ else if (ccs_str_starts(line, ".starts "))
146+ ptr->operation = CCS_SORT_OPERATOR_STARTS;
147+ else
148+ goto invalid_rule;
149+ if (!*line)
150+ goto invalid_rule;
151+ line = ccs_strdup(line);
152+ ptr->string = line;
153+ ptr->string_len = strlen(line);
154+ }
155+ ccs_put();
156+ fclose(fp);
157+ if (!rules_len) {
158+ if (first)
159+ fprintf(stderr, "No rules defined in %s .\n",
160+ filename);
161+ else
162+ syslog(LOG_WARNING, "No rules defined in %s .\n",
163+ filename);
164+ exit(1);
165+ }
166+ for (i = 0; i < destination_list_len; i++) {
167+ struct ccs_destination *ptr = &destination_list[i];
168+ const char *path = ptr->pathname;
169+ /* This is OK because path is a strdup()ed string. */
170+ char *pos = (char *) path;
171+ while (*pos) {
172+ int ret_ignored;
173+ if (*pos++ != '/')
174+ continue;
175+ *(pos - 1) = '\0';
176+ ret_ignored = mkdir(path, 0700);
177+ *(pos - 1) = '/';
178+ }
179+ do {
180+ ptr->fd = open(path, O_WRONLY | O_APPEND | O_CREAT,
181+ 0600);
182+ } while (ptr->fd == EOF && errno == EINTR);
183+ if (ptr->fd == EOF) {
184+ if (first)
185+ fprintf(stderr, "Can't open %s for writing.\n",
186+ path);
187+ else
188+ syslog(LOG_WARNING,
189+ "Can't open %s for writing.\n", path);
190+ exit(1);
191+ }
192+ }
193+ first = 0;
194+ return;
195+invalid_rule:
196+ if (first)
197+ fprintf(stderr, "Invalid rule at line %u in %s .\n", line_no,
198+ filename);
199+ else
200+ syslog(LOG_WARNING, "Invalid rule at line %u in %s .\n",
201+ line_no, filename);
202+ exit(1);
203+}
204+
205+static int ccs_check_rules(char *header, char *acl)
206+{
207+ unsigned int i;
208+ _Bool matched = true;
209+ for (i = 0; i < rules_len; i++) {
210+ const struct ccs_sort_rules *ptr = &rules[i];
211+ char *line;
212+ unsigned int index = ptr->index;
213+ const char *find = ptr->string;
214+ unsigned int find_len = ptr->string_len;
215+ switch (ptr->type) {
216+ case CCS_SORT_RULE_HEADER:
217+ line = header;
218+ break;
219+ case CCS_SORT_RULE_ACL:
220+ line = acl;
221+ break;
222+ default: /* CCS_SORT_RULE_DESTINATION */
223+ if (matched)
224+ return ptr->index;
225+ matched = true;
226+ continue;
227+ }
228+ if (!matched)
229+ continue;
230+ if (!index) {
231+ switch (ptr->operation) {
232+ case CCS_SORT_OPERATOR_CONTAINS:
233+ while (1) {
234+ char *cp = strstr(line, find);
235+ if (!cp) {
236+ matched = false;
237+ break;
238+ }
239+ if ((cp == line || *(cp - 1) == ' ') &&
240+ (!cp[find_len] ||
241+ cp[find_len] == ' '))
242+ break;
243+ line = cp + 1;
244+ }
245+ break;
246+ case CCS_SORT_OPERATOR_EQUALS:
247+ matched = !strcmp(line, find);
248+ break;
249+ default: /* CCS_SORT_OPERATOR_STARTS */
250+ matched = !strncmp(line, find, find_len) &&
251+ (!line[find_len] ||
252+ line[find_len] == ' ');
253+ }
254+ } else {
255+ char *word = line;
256+ char *word_end;
257+ while (--index) {
258+ char *cp = strchr(word, ' ');
259+ if (!cp) {
260+ matched = false;
261+ break;
262+ }
263+ word = cp + 1;
264+ }
265+ if (!matched)
266+ continue;
267+ word_end = strchr(word, ' ');
268+ if (word_end)
269+ *word_end = '\0';
270+ switch (ptr->operation) {
271+ case CCS_SORT_OPERATOR_CONTAINS:
272+ matched = strstr(word, find) != NULL;
273+ break;
274+ case CCS_SORT_OPERATOR_EQUALS:
275+ matched = !strcmp(word, find);
276+ break;
277+ default: /* CCS_SORT_OPERATOR_STARTS */
278+ matched = !strncmp(word, find, find_len);
279+ break;
280+ }
281+ if (word_end)
282+ *word_end = ' ';
283+ }
284+ }
285+ return EOF;
286+}
287+
288+static _Bool ccs_write_log(const int i, char *buffer)
289+{
290+ int len = strlen(buffer);
291+ int ret;
292+ struct ccs_destination *ptr = &destination_list[i];
293+ /* Create destination file if needed. */
294+ if (access(ptr->pathname, F_OK)) {
295+ close(ptr->fd);
296+ do {
297+ ptr->fd = open(ptr->pathname,
298+ O_WRONLY | O_APPEND | O_CREAT, 0600);
299+ } while (ptr->fd == EOF && errno == EINTR);
300+ if (ptr->fd == EOF) {
301+ syslog(LOG_WARNING, "Can't open %s for writing.\n",
302+ ptr->pathname);
303+ return 0;
304+ }
305+ }
306+ do {
307+ ret = write(ptr->fd, buffer, len);
308+ if (ret == len)
309+ return 1;
310+ } while (ret == EOF && errno == EINTR);
311+ syslog(LOG_WARNING, "Can't write to %s .\n", ptr->pathname);
312+ return 0;
313+}
314+
315+static void block_sighup(const _Bool block)
316+{
317+ sigset_t sigset;
318+ sigemptyset(&sigset);
319+ sigaddset(&sigset, SIGHUP);
320+ sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigset, NULL);
321+}
322+
323+static void ccs_reload_config(int sig)
324+{
325+ block_sighup(1);
326+ syslog(LOG_WARNING, "Reloading configuration file.\n");
327+ ccs_auditd_init_rules(CCS_AUDITD_CONF);
328+ block_sighup(0);
329+}
330+
331+int main(int argc, char *argv[])
332+{
333+ unsigned int i;
334+ int fd_in;
335+ for (i = 1; i < argc; i++) {
336+ char *ptr = argv[i];
337+ char *cp = strchr(ptr, ':');
338+ if (!cp)
339+ goto usage;
340+ *cp++ = '\0';
341+ if (ccs_network_mode)
342+ goto usage;
343+ ccs_network_ip = inet_addr(ptr);
344+ ccs_network_port = htons(atoi(cp));
345+ ccs_network_mode = true;
346+ }
347+ ccs_auditd_init_rules(CCS_AUDITD_CONF);
348+ if (!ccs_network_mode) {
349+ /* Get exclusive lock. */
350+ int fd = open("/proc/self/exe", O_RDONLY);
351+ if (flock(fd, LOCK_EX | LOCK_NB) == EOF)
352+ return 0;
353+ }
354+ if (ccs_network_mode) {
355+ ccs_check_remote_host(true);
356+ fd_in = ccs_open_stream("proc:audit");
357+ } else {
358+ ccs_check_policy_dir(true);
359+ fd_in = open("audit", O_RDONLY);
360+ }
361+ if (fd_in == EOF) {
362+ fprintf(stderr, "Can't open %s/audit for reading.\n",
363+ CCS_PROC_POLICY_DIR);
364+ return 1;
365+ }
366+ switch (fork()) {
367+ case 0:
368+ break;
369+ case -1:
370+ fprintf(stderr, "Can't fork()\n");
371+ return 1;
372+ default:
373+ return 0;
374+ }
375+ if (setsid() == EOF) {
376+ fprintf(stderr, "Can't setsid()\n");
377+ return 1;
378+ }
379+ switch (fork()) {
380+ case 0:
381+ break;
382+ case -1:
383+ fprintf(stderr, "Can't fork()\n");
384+ return 1;
385+ default:
386+ return 0;
387+ }
388+ if (chdir("/")) {
389+ fprintf(stderr, "Can't chdir()\n");
390+ return 1;
391+ }
392+ close(0);
393+ close(1);
394+ close(2);
395+ openlog("caitsith-auditd", 0, LOG_USER);
396+ syslog(LOG_WARNING, "Started.\n");
397+ signal(SIGHUP, ccs_reload_config);
398+ while (true) {
399+ static char buffer[32768];
400+ char *acl;
401+ char *tail;
402+ int ret;
403+ memset(buffer, 0, sizeof(buffer));
404+ if (ccs_network_mode) {
405+ int j;
406+ for (j = 0; j < sizeof(buffer) - 1; j++) {
407+ do {
408+ ret = read(fd_in, buffer + j, 1);
409+ } while (ret == EOF && errno == EINTR);
410+ if (ret != 1)
411+ goto out;
412+ if (!buffer[j])
413+ break;
414+ }
415+ if (j == sizeof(buffer) - 1)
416+ goto out;
417+ } else {
418+ while (read(fd_in, buffer, sizeof(buffer) - 1) <= 0) {
419+ /* Wait for data. */
420+ struct pollfd pfd = {
421+ .fd = fd_in,
422+ .events = POLLIN,
423+ };
424+ if (poll(&pfd, 1, -1) == EOF && errno != EINTR)
425+ goto out;
426+ }
427+ }
428+ /* Split into two parts. */
429+ acl = strstr(buffer, " / ");
430+ if (!acl)
431+ continue;
432+ *acl = '\0';
433+ acl += 3;
434+ tail = strchr(acl, '\n');
435+ if (!tail)
436+ continue;
437+ *tail = '\0';
438+ block_sighup(1);
439+ /* Check for filtering rules. */
440+ i = ccs_check_rules(buffer, acl);
441+ if (i != EOF) {
442+ *tail = '\n';
443+ *(acl - 3) = ' ';
444+ /* Write the audit log. */
445+ if (!ccs_write_log(i, buffer))
446+ break;
447+ }
448+ block_sighup(0);
449+ }
450+out:
451+ syslog(LOG_WARNING, "Terminated.\n");
452+ closelog();
453+ return 1;
454+usage:
455+ printf("Usage: %s [remote_ip:remote_port]\n\n"
456+ "remote_ip:remote_port : Read from caitsith-agent listening "
457+ "at remote_ip:remote_port .\n\n"
458+ "See %s for configuration.\n", argv[0], CCS_AUDITD_CONF);
459+ return 1;
460+}
--- tags/caitsith-tools/0.2.2/usr_sbin/caitsith-loadpolicy.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/usr_sbin/caitsith-loadpolicy.c (revision 242)
@@ -0,0 +1,100 @@
1+/*
2+ * caitsith-loadpolicy.c
3+ *
4+ * CaitSith's utilities.
5+ *
6+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
7+ *
8+ * Version: 0.2 2016/10/05
9+ *
10+ * This program is free software; you can redistribute it and/or modify it
11+ * under the terms of the GNU General Public License v2 as published by the
12+ * Free Software Foundation.
13+ *
14+ * This program is distributed in the hope that it will be useful, but WITHOUT
15+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17+ * more details.
18+ *
19+ * You should have received a copy of the GNU General Public License along with
20+ * this program; if not, write to the Free Software Foundation, Inc.,
21+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22+ */
23+#include "caitsithtools.h"
24+
25+/**
26+ * ccs_close_write - Close stream opened by ccs_open_write().
27+ *
28+ * @fp: Pointer to "FILE".
29+ *
30+ * Returns true on success, false otherwise.
31+ */
32+static _Bool ccs_close_write(FILE *fp)
33+{
34+ _Bool result = true;
35+ if (ccs_network_mode) {
36+ if (fputc(0, fp) == EOF)
37+ result = false;
38+ if (fflush(fp) == EOF)
39+ result = false;
40+ if (fgetc(fp) == EOF)
41+ result = false;
42+ }
43+ if (fclose(fp) == EOF)
44+ result = false;
45+ return result;
46+}
47+
48+static _Bool ccs_move_file_to_proc(const char *dest)
49+{
50+ FILE *proc_fp = ccs_open_write(dest);
51+ _Bool result = true;
52+ if (!proc_fp) {
53+ fprintf(stderr, "Can't open %s for writing.\n", dest);
54+ return false;
55+ }
56+ ccs_get();
57+ while (true) {
58+ char *line = ccs_freadline(stdin);
59+ if (!line)
60+ break;
61+ if (line[0])
62+ if (fprintf(proc_fp, "%s\n", line) < 0)
63+ result = false;
64+ }
65+ ccs_put();
66+ if (!ccs_close_write(proc_fp))
67+ result = false;
68+ return result;
69+}
70+
71+int main(int argc, char *argv[])
72+{
73+ int i;
74+ for (i = 1; i < argc; i++) {
75+ char *ptr = argv[i];
76+ char *cp = strchr(ptr, ':');
77+ if (!cp)
78+ goto usage;
79+ *cp++ = '\0';
80+ ccs_network_ip = inet_addr(ptr);
81+ ccs_network_port = htons(atoi(cp));
82+ if (ccs_network_mode) {
83+ fprintf(stderr, "You cannot specify multiple "
84+ "%s at the same time.\n\n",
85+ "remote agents");
86+ goto usage;
87+ }
88+ ccs_network_mode = true;
89+ }
90+ if (ccs_network_mode)
91+ ccs_check_remote_host(true);
92+ else
93+ ccs_check_policy_dir(true);
94+ return !ccs_move_file_to_proc(CCS_PROC_POLICY_POLICY);
95+usage:
96+ printf("Usage: %s [remote_ip:remote_port]\n\n"
97+ "remote_ip:remote_port : Write to caitsith-agent listening at "
98+ "remote_ip:remote_port .\n", argv[0]);
99+ return 1;
100+}
--- tags/caitsith-tools/0.2.2/usr_sbin/caitsith-notifyd.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/usr_sbin/caitsith-notifyd.c (revision 242)
@@ -0,0 +1,252 @@
1+/*
2+ * caitsith-notifyd.c
3+ *
4+ * CaitSith's utilities.
5+ *
6+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
7+ *
8+ * Version: 0.2 2016/10/05
9+ *
10+ * This program is free software; you can redistribute it and/or modify it
11+ * under the terms of the GNU General Public License v2 as published by the
12+ * Free Software Foundation.
13+ *
14+ * This program is distributed in the hope that it will be useful, but WITHOUT
15+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17+ * more details.
18+ *
19+ * You should have received a copy of the GNU General Public License along with
20+ * this program; if not, write to the Free Software Foundation, Inc.,
21+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22+ */
23+#include "caitsithtools.h"
24+#include <sys/wait.h>
25+#include <signal.h>
26+#include <syslog.h>
27+#include <poll.h>
28+
29+#define CCS_NOTIFYD_CONF "/etc/caitsith/tools/notifyd.conf"
30+
31+static int query_fd = EOF;
32+static int time_to_wait = 0;
33+static char **action_to_take = NULL;
34+static int minimal_interval = 0;
35+
36+static void ccs_notifyd_init_rules(const char *filename)
37+{
38+ static _Bool first = 1;
39+ FILE *fp = fopen(filename, "r");
40+ unsigned int line_no = 0;
41+ char *action = NULL;
42+ if (!first) {
43+ free(action_to_take);
44+ action_to_take = NULL;
45+ time_to_wait = 0;
46+ minimal_interval = 0;
47+ }
48+ if (!fp) {
49+ if (first)
50+ fprintf(stderr, "Can't open %s for reading.\n",
51+ filename);
52+ else
53+ syslog(LOG_WARNING, "Can't open %s for reading.\n",
54+ filename);
55+ exit(1);
56+ }
57+ ccs_get();
58+ while (true) {
59+ char *line = ccs_freadline(fp);
60+ if (!line)
61+ break;
62+ line_no++;
63+ ccs_normalize_line(line);
64+ if (*line == '#' || !*line)
65+ continue;
66+ if (sscanf(line, "time_to_wait %u", &time_to_wait) == 1 ||
67+ sscanf(line, "minimal_interval %u", &minimal_interval)
68+ == 1)
69+ continue;
70+ if (!ccs_str_starts(line, "action_to_take "))
71+ continue;
72+ if (!*line)
73+ goto invalid_rule;
74+ if (action)
75+ goto invalid_rule;
76+ action = ccs_strdup(line);
77+ }
78+ ccs_put();
79+ fclose(fp);
80+ if (!action) {
81+ if (first)
82+ fprintf(stderr, "No actions defined in %s .\n",
83+ filename);
84+ else
85+ syslog(LOG_WARNING, "No actions defined in %s .\n",
86+ filename);
87+ exit(1);
88+ }
89+ {
90+ int count = 0;
91+ char *sp = action;
92+ while (true) {
93+ char *cp = strsep(&sp, " ");
94+ action_to_take = ccs_realloc(action_to_take,
95+ sizeof(char *) * ++count);
96+ action_to_take[count - 1] = cp;
97+ if (!cp)
98+ break;
99+ if (!ccs_decode(cp, cp))
100+ goto invalid_rule;
101+ }
102+ }
103+ first = 0;
104+ return;
105+invalid_rule:
106+ if (first)
107+ fprintf(stderr, "Invalid rule at line %u in %s .\n", line_no,
108+ filename);
109+ else
110+ syslog(LOG_WARNING, "Invalid rule at line %u in %s .\n",
111+ line_no, filename);
112+ exit(1);
113+}
114+
115+static void block_sighup(const _Bool block)
116+{
117+ sigset_t sigset;
118+ sigemptyset(&sigset);
119+ sigaddset(&sigset, SIGHUP);
120+ sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigset, NULL);
121+}
122+
123+static void main_loop(void)
124+{
125+ static char buffer[32768];
126+ while (query_fd != EOF) {
127+ int pipe_fd[2];
128+ pid_t pid;
129+ memset(buffer, 0, sizeof(buffer));
130+ while (read(query_fd, buffer, sizeof(buffer) - 1) <= 0) {
131+ /* Wait for data. */
132+ struct pollfd pfd = {
133+ .fd = query_fd,
134+ .events = POLLIN,
135+ };
136+ if (poll(&pfd, 1, -1) == EOF && errno != EINTR)
137+ return;
138+ }
139+ if (pipe(pipe_fd) == EOF) {
140+ syslog(LOG_WARNING, "Can't create pipe.\n");
141+ return;
142+ }
143+ block_sighup(1);
144+ pid = fork();
145+ if (pid == -1) {
146+ syslog(LOG_WARNING, "Can't fork().\n");
147+ return;
148+ }
149+ if (!pid) {
150+ int ret_ignored;
151+ ret_ignored = close(query_fd);
152+ ret_ignored = close(pipe_fd[1]);
153+ ret_ignored = close(0);
154+ ret_ignored = dup2(pipe_fd[0], 0);
155+ ret_ignored = close(pipe_fd[0]);
156+ execvp(action_to_take[0], action_to_take);
157+ syslog(LOG_WARNING, "Can't execute %s\n",
158+ action_to_take[0]);
159+ closelog();
160+ _exit(1);
161+ } else {
162+ int ret_ignored;
163+ int len = strlen(buffer);
164+ close(pipe_fd[0]);
165+ /* This is OK because read() < sizeof(buffer). */
166+ buffer[len++] = '\n';
167+ ret_ignored = write(pipe_fd[1], buffer, len);
168+ close(pipe_fd[1]);
169+ }
170+ block_sighup(0);
171+ while (time_to_wait-- > 0) {
172+ int ret_ignored;
173+ sleep(1);
174+ ret_ignored = write(query_fd, "\n", 1);
175+ }
176+ close(query_fd);
177+ while (waitpid(pid, NULL, __WALL) == EOF && errno == EINTR);
178+ sleep(minimal_interval);
179+ do {
180+ query_fd = open("query", O_RDWR);
181+ } while (query_fd == EOF && errno == EINTR);
182+ }
183+}
184+
185+static void ccs_reload_config(int sig)
186+{
187+ block_sighup(1);
188+ syslog(LOG_WARNING, "Reloading configuration file.\n");
189+ ccs_notifyd_init_rules(CCS_NOTIFYD_CONF);
190+ block_sighup(0);
191+}
192+
193+int main(int argc, char *argv[])
194+{
195+ unsetenv("SHELLOPTS"); /* Make sure popen() executes commands. */
196+ if (argc != 1)
197+ goto usage;
198+ ccs_notifyd_init_rules(CCS_NOTIFYD_CONF);
199+ ccs_check_policy_dir(true);
200+ query_fd = open("query", O_RDWR);
201+ if (query_fd == EOF) {
202+ fprintf(stderr, "You can't run this daemon for this kernel."
203+ "\n");
204+ return 1;
205+ } else if (time_to_wait && write(query_fd, "", 0) != 0) {
206+ fprintf(stderr, "You need to give this program permission to "
207+ "modify policy.\n");
208+ return 1;
209+ }
210+ umask(0);
211+ switch (fork()) {
212+ case 0:
213+ break;
214+ case -1:
215+ fprintf(stderr, "Can't fork()\n");
216+ return 1;
217+ default:
218+ return 0;
219+ }
220+ if (setsid() == EOF) {
221+ fprintf(stderr, "Can't setsid()\n");
222+ return 1;
223+ }
224+ switch (fork()) {
225+ case 0:
226+ break;
227+ case -1:
228+ fprintf(stderr, "Can't fork()\n");
229+ return 1;
230+ default:
231+ return 0;
232+ }
233+ { /* Get exclusive lock. */
234+ int fd = open("/proc/self/exe", O_RDONLY);
235+ if (flock(fd, LOCK_EX | LOCK_NB) == EOF)
236+ return 0;
237+ }
238+ close(0);
239+ close(1);
240+ close(2);
241+ openlog("caitsith-notifyd", 0, LOG_USER);
242+ syslog(LOG_WARNING, "Started.\n");
243+ signal(SIGHUP, ccs_reload_config);
244+ main_loop();
245+ syslog(LOG_WARNING, "Terminated.\n");
246+ closelog();
247+ return 1;
248+usage:
249+ printf("Usage: %s\n\nSee %s for configuration.\n", argv[0],
250+ CCS_NOTIFYD_CONF);
251+ return 1;
252+}
--- tags/caitsith-tools/0.2.2/usr_sbin/caitsith-pstree.c (nonexistent)
+++ tags/caitsith-tools/0.2.2/usr_sbin/caitsith-pstree.c (revision 242)
@@ -0,0 +1,387 @@
1+/*
2+ * caitsith-pstree.c
3+ *
4+ * CaitSith's utilities.
5+ *
6+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
7+ *
8+ * Version: 0.2 2016/10/05
9+ *
10+ * This program is free software; you can redistribute it and/or modify it
11+ * under the terms of the GNU General Public License v2 as published by the
12+ * Free Software Foundation.
13+ *
14+ * This program is distributed in the hope that it will be useful, but WITHOUT
15+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17+ * more details.
18+ *
19+ * You should have received a copy of the GNU General Public License along with
20+ * this program; if not, write to the Free Software Foundation, Inc.,
21+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22+ */
23+#include "caitsithtools.h"
24+
25+struct ccs_task_entry {
26+ pid_t pid;
27+ pid_t ppid;
28+ char *name;
29+ char *domain;
30+ _Bool selected;
31+ int index;
32+ int depth;
33+};
34+
35+/* The list of processes currently running. */
36+static struct ccs_task_entry *ccs_task_list = NULL;
37+/* The length of ccs_task_list . */
38+static int ccs_task_list_len = 0;
39+
40+/* Serial number for sorting ccs_task_list . */
41+static int ccs_dump_index = 0;
42+
43+/**
44+ * ccs_sort_process_entry - Sort ccs_tasklist list.
45+ *
46+ * @pid: Pid to search.
47+ * @depth: Depth of the process for printing like pstree command.
48+ *
49+ * Returns nothing.
50+ */
51+static void ccs_sort_process_entry(const pid_t pid, const int depth)
52+{
53+ int i;
54+ for (i = 0; i < ccs_task_list_len; i++) {
55+ if (pid != ccs_task_list[i].pid)
56+ continue;
57+ ccs_task_list[i].index = ccs_dump_index++;
58+ ccs_task_list[i].depth = depth;
59+ ccs_task_list[i].selected = true;
60+ }
61+ for (i = 0; i < ccs_task_list_len; i++) {
62+ if (pid != ccs_task_list[i].ppid)
63+ continue;
64+ ccs_sort_process_entry(ccs_task_list[i].pid, depth + 1);
65+ }
66+}
67+
68+/**
69+ * ccs_task_entry_compare - Compare routine for qsort() callback.
70+ *
71+ * @a: Pointer to "void".
72+ * @b: Pointer to "void".
73+ *
74+ * Returns index diff value.
75+ */
76+static int ccs_task_entry_compare(const void *a, const void *b)
77+{
78+ const struct ccs_task_entry *a0 = (struct ccs_task_entry *) a;
79+ const struct ccs_task_entry *b0 = (struct ccs_task_entry *) b;
80+ return a0->index - b0->index;
81+}
82+
83+/**
84+ * ccs_add_process_entry - Add entry for running processes.
85+ *
86+ * @line: A line containing PID and domainname.
87+ * @ppid: Parent PID.
88+ * @name: Comm name (allocated by strdup()).
89+ *
90+ * Returns nothing.
91+ *
92+ * @name is free()d on failure.
93+ */
94+static void ccs_add_process_entry(const char *line, const pid_t ppid,
95+ char *name)
96+{
97+ int index;
98+ unsigned int pid = 0;
99+ char *domain;
100+ if (!line || sscanf(line, "%u", &pid) != 1) {