aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--COPYING280
-rw-r--r--Makefile.in156
-rw-r--r--README28
-rw-r--r--RELNOTES215
-rwxr-xr-xconfigure4723
-rw-r--r--configure.ac52
-rw-r--r--etc/audacious.profile8
-rw-r--r--etc/chromium-browser.profile3
-rw-r--r--etc/chromium.profile7
-rw-r--r--etc/clementine.profile7
-rw-r--r--etc/deadbeef.profile8
-rw-r--r--etc/deluge.profile9
-rw-r--r--etc/disable-common.inc10
-rw-r--r--etc/disable-mgmt.inc12
-rw-r--r--etc/disable-secret.inc9
-rw-r--r--etc/dropbox.profile7
-rw-r--r--etc/empathy.profile6
-rw-r--r--etc/evince.profile8
-rw-r--r--etc/filezilla.profile10
-rw-r--r--etc/firefox.profile9
-rw-r--r--etc/firejail.bash_completion86
-rw-r--r--etc/firemon.bash_completion39
-rw-r--r--etc/generic.profile41
-rw-r--r--etc/gnome-mplayer.profile7
-rw-r--r--etc/icecat.profile2
-rw-r--r--etc/icedove.profile3
-rw-r--r--etc/iceweasel.profile2
-rw-r--r--etc/login.users14
-rw-r--r--etc/midori.profile9
-rw-r--r--etc/opera.profile8
-rw-r--r--etc/pidgin.profile7
-rw-r--r--etc/qbittorrent.profile9
-rw-r--r--etc/quassel.profile7
-rw-r--r--etc/rhythmbox.profile7
-rw-r--r--etc/server.profile6
-rw-r--r--etc/thunderbird.profile9
-rw-r--r--etc/totem.profile7
-rw-r--r--etc/transmission-gtk.profile9
-rw-r--r--etc/transmission-qt.profile9
-rw-r--r--etc/vlc.profile7
-rw-r--r--etc/xchat.profile7
-rwxr-xr-xinstall.sh2
-rwxr-xr-xmkdeb.sh96
-rwxr-xr-xmkman.sh7
-rw-r--r--platform/debian/conffiles33
-rw-r--r--platform/debian/control20
-rw-r--r--platform/debian/copyright30
-rwxr-xr-xplatform/rpm/mkrpm.sh256
-rw-r--r--src/firejail/Makefile.in28
-rw-r--r--src/firejail/arg-checking.txt85
-rw-r--r--src/firejail/arp.c474
-rw-r--r--src/firejail/bandwidth.c483
-rw-r--r--src/firejail/caps.c453
-rw-r--r--src/firejail/cgroup.c118
-rw-r--r--src/firejail/cpu.c141
-rw-r--r--src/firejail/firejail.h354
-rw-r--r--src/firejail/fs.c825
-rw-r--r--src/firejail/fs_dev.c163
-rw-r--r--src/firejail/fs_home.c494
-rw-r--r--src/firejail/fs_hostname.c157
-rw-r--r--src/firejail/fs_trace.c76
-rw-r--r--src/firejail/fs_var.c388
-rw-r--r--src/firejail/join.c364
-rw-r--r--src/firejail/list.c65
-rw-r--r--src/firejail/main.c1168
-rw-r--r--src/firejail/netfilter.c164
-rw-r--r--src/firejail/network.c362
-rw-r--r--src/firejail/network.txt95
-rw-r--r--src/firejail/network_main.c268
-rw-r--r--src/firejail/output.c84
-rw-r--r--src/firejail/profile.c444
-rw-r--r--src/firejail/restricted_shell.c96
-rw-r--r--src/firejail/rlimit.c62
-rw-r--r--src/firejail/sandbox.c490
-rw-r--r--src/firejail/seccomp.c658
-rw-r--r--src/firejail/shutdown.c98
-rw-r--r--src/firejail/syscall.c4942
-rw-r--r--src/firejail/usage.c312
-rw-r--r--src/firejail/util.c480
-rw-r--r--src/firejail/veth.c191
-rw-r--r--src/firemon/Makefile.in24
-rw-r--r--src/firemon/arp.c99
-rw-r--r--src/firemon/caps.c69
-rw-r--r--src/firemon/cgroup.c64
-rw-r--r--src/firemon/cpu.c68
-rw-r--r--src/firemon/firemon.c222
-rw-r--r--src/firemon/firemon.h84
-rw-r--r--src/firemon/interface.c176
-rw-r--r--src/firemon/list.c35
-rw-r--r--src/firemon/netstats.c214
-rw-r--r--src/firemon/procevent.c377
-rw-r--r--src/firemon/route.c213
-rw-r--r--src/firemon/seccomp.c69
-rw-r--r--src/firemon/top.c297
-rw-r--r--src/firemon/tree.c36
-rw-r--r--src/firemon/usage.c77
-rwxr-xr-xsrc/fshaper/fshaper.sh69
-rw-r--r--src/ftee/Makefile.in24
-rw-r--r--src/ftee/ftee.h24
-rw-r--r--src/ftee/main.c228
-rw-r--r--src/include/common.h115
-rw-r--r--src/include/libnetlink.h163
-rw-r--r--src/include/pid.h58
-rw-r--r--src/lib/Makefile.in20
-rw-r--r--src/lib/common.c192
-rw-r--r--src/lib/libnetlink.c803
-rw-r--r--src/lib/pid.c392
-rw-r--r--src/libtrace/Makefile.in25
-rw-r--r--src/libtrace/libtrace.c609
-rw-r--r--src/man/firejail-login.txt36
-rw-r--r--src/man/firejail-profile.txt181
-rw-r--r--src/man/firejail.txt1196
-rw-r--r--src/man/firemon.txt107
-rwxr-xr-xsrc/tools/check-caps.sh46
-rw-r--r--src/tools/extract_caps.c83
-rw-r--r--src/tools/extract_syscalls.c91
-rwxr-xr-xsrc/tools/mkcoverit.sh45
-rw-r--r--src/tools/rvtest.c144
-rw-r--r--src/tools/ttytest.c36
-rwxr-xr-xtest/4bridges_arp.exp175
-rwxr-xr-xtest/4bridges_ip.exp175
-rwxr-xr-xtest/auto/autotest.sh202
-rw-r--r--test/caps1.profile1
-rw-r--r--test/caps2.profile1
-rwxr-xr-xtest/chk_config.exp86
-rwxr-xr-xtest/chromium.exp72
-rwxr-xr-xtest/configure42
-rwxr-xr-xtest/dns.exp69
-rwxr-xr-xtest/doubledash.exp60
-rwxr-xr-xtest/evince.exp72
-rwxr-xr-xtest/extract_command.exp23
-rwxr-xr-xtest/firefox.exp74
-rwxr-xr-xtest/firejail-in-firejail.exp37
-rwxr-xr-xtest/firemon-arp.exp34
-rwxr-xr-xtest/firemon-caps.exp135
-rwxr-xr-xtest/firemon-cgroup.exp40
-rwxr-xr-xtest/firemon-interface.exp34
-rwxr-xr-xtest/firemon-route.exp32
-rwxr-xr-xtest/firemon-seccomp.exp45
-rwxr-xr-xtest/fs_chroot.exp54
-rwxr-xr-xtest/fs_dev_shm.exp87
-rwxr-xr-xtest/fs_home_sanitize.exp33
-rwxr-xr-xtest/fs_overlay.exp64
-rwxr-xr-xtest/fs_sys.exp34
-rwxr-xr-xtest/fs_var_lock.exp87
-rwxr-xr-xtest/fs_var_tmp.exp87
-rwxr-xr-xtest/fscheck-bindnoroot.exp14
-rwxr-xr-xtest/fscheck-blacklist.exp14
-rwxr-xr-xtest/fscheck-chroot.exp77
-rwxr-xr-xtest/fscheck-netfilter.exp69
-rwxr-xr-xtest/fscheck-output.exp104
-rwxr-xr-xtest/fscheck-private.exp77
-rwxr-xr-xtest/fscheck-privatekeep.exp93
-rwxr-xr-xtest/fscheck-profile.exp69
-rwxr-xr-xtest/fscheck-readonly.exp14
-rwxr-xr-xtest/fscheck-shell.exp69
-rwxr-xr-xtest/fscheck-tmpfs.exp14
-rwxr-xr-xtest/fscheck.sh39
-rwxr-xr-xtest/login_ssh.exp59
-rwxr-xr-xtest/midori.exp73
-rwxr-xr-xtest/name.exp25
-rwxr-xr-xtest/net_arp.exp71
-rwxr-xr-xtest/net_badip.exp16
-rwxr-xr-xtest/net_defaultgw.exp65
-rwxr-xr-xtest/net_defaultgw2.exp65
-rwxr-xr-xtest/net_defaultgw3.exp17
-rwxr-xr-xtest/net_ip.exp91
-rwxr-xr-xtest/net_local.exp49
-rwxr-xr-xtest/net_mac.exp36
-rwxr-xr-xtest/net_macvlan.exp88
-rwxr-xr-xtest/net_netfilter.exp88
-rwxr-xr-xtest/net_noip.exp41
-rwxr-xr-xtest/net_noip2.exp41
-rwxr-xr-xtest/net_none.exp36
-rw-r--r--test/netfilter.filter6
-rw-r--r--test/netfilter.profile1
-rwxr-xr-xtest/noroot.exp124
-rwxr-xr-xtest/opera.exp72
-rwxr-xr-xtest/option-join.exp43
-rwxr-xr-xtest/option-shutdown.exp30
-rwxr-xr-xtest/option-trace.exp31
-rwxr-xr-xtest/option_bind_directory.exp26
-rwxr-xr-xtest/option_bind_file.exp26
-rwxr-xr-xtest/option_bind_user.exp15
-rwxr-xr-xtest/option_blacklist.exp35
-rwxr-xr-xtest/option_blacklist_file.exp26
-rwxr-xr-xtest/option_chroot_overlay.exp21
-rwxr-xr-xtest/option_help.exp22
-rwxr-xr-xtest/option_list.exp48
-rwxr-xr-xtest/option_man.exp17
-rwxr-xr-xtest/option_readonly.exp26
-rwxr-xr-xtest/option_rlimit.exp36
-rwxr-xr-xtest/option_tmpfs.exp26
-rwxr-xr-xtest/option_tree.exp60
-rwxr-xr-xtest/option_version.exp15
-rwxr-xr-xtest/output.exp66
-rwxr-xr-xtest/output.sh9
-rwxr-xr-xtest/pid.exp48
-rwxr-xr-xtest/private-keep.exp66
-rw-r--r--test/private-keep.profile1
-rwxr-xr-xtest/private.exp95
-rw-r--r--test/private.profile1
-rwxr-xr-xtest/private_dir.exp53
-rwxr-xr-xtest/private_dir_profile.exp54
-rwxr-xr-xtest/profile_apps.exp48
-rwxr-xr-xtest/profile_followlnk.exp68
-rwxr-xr-xtest/profile_noperm.exp13
-rwxr-xr-xtest/profile_readonly.exp64
-rwxr-xr-xtest/profile_rlimit.exp36
-rwxr-xr-xtest/profile_syntax.exp69
-rwxr-xr-xtest/profile_syntax2.exp47
-rwxr-xr-xtest/profile_tmpfs.exp37
-rw-r--r--test/readonly-lnk.profile2
-rw-r--r--test/readonly.profile2
-rw-r--r--test/rlimit.profile4
-rwxr-xr-xtest/seccomp-bad-empty.exp38
-rw-r--r--test/seccomp-bad-empty.profile1
-rw-r--r--test/seccomp-bad-empty2.profile1
-rwxr-xr-xtest/seccomp-chmod-profile.exp46
-rwxr-xr-xtest/seccomp-chmod.exp46
-rwxr-xr-xtest/seccomp-chown.exp46
-rwxr-xr-xtest/seccomp-debug.exp32
-rwxr-xr-xtest/seccomp-empty.exp145
-rw-r--r--test/seccomp-empty.profile1
-rwxr-xr-xtest/seccomp-ptrace.exp23
-rwxr-xr-xtest/seccomp-su.exp34
-rwxr-xr-xtest/seccomp-umount.exp28
-rw-r--r--test/seccomp.profile1
-rwxr-xr-xtest/servers.exp40
-rwxr-xr-xtest/servers2.exp31
-rwxr-xr-xtest/servers3.exp31
-rwxr-xr-xtest/servers4.exp32
-rwxr-xr-xtest/shell_csh.exp40
-rwxr-xr-xtest/shell_dash.exp41
-rwxr-xr-xtest/shell_zsh.exp40
-rwxr-xr-xtest/sysrq-trigger.exp21
-rwxr-xr-xtest/test-nonet.sh44
-rwxr-xr-xtest/test-root.sh56
-rw-r--r--test/test.profile6
-rw-r--r--test/test.rv49
-rwxr-xr-xtest/test.sh329
-rw-r--r--test/test2.profile4
-rw-r--r--test/tmpfs.profile1
-rwxr-xr-xtest/trace.exp95
-rwxr-xr-xtest/transmission-gtk.exp68
-rwxr-xr-xtest/transmission-qt.exp72
246 files changed, 33999 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 000000000..b6e1c33e0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,280 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Library General Public License instead.) You can apply it to
19your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40(2) offer you this license which gives you legal permission to copy,
41distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 000000000..6b9739524
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,156 @@
1all: apps firejail.1 firemon.1 firejail-profile.5 firejail-login.5
2MYLIBS = src/lib
3APPS = src/firejail src/firemon src/libtrace src/ftee
4
5datarootdir=@datarootdir@
6PREFIX=@prefix@
7prefix=@prefix@
8VERSION=@PACKAGE_VERSION@
9NAME=@PACKAGE_NAME@
10PACKAGE_TARNAME=@PACKAGE_TARNAME@
11DOCDIR=@docdir@
12
13
14.PHONY: mylibs $(MYLIBS)
15mylibs: $(MYLIBS)
16$(MYLIBS):
17 $(MAKE) -C $@
18
19.PHONY: apps $(APPS)
20apps: $(APPS)
21$(APPS): $(MYLIBS)
22 $(MAKE) -C $@
23
24firemon.1: src/man/firemon.txt
25 ./mkman.sh $(VERSION) src/man/firemon.txt firemon.1
26firejail.1: src/man/firejail.txt
27 ./mkman.sh $(VERSION) src/man/firejail.txt firejail.1
28firejail-profile.5: src/man/firejail-profile.txt
29 ./mkman.sh $(VERSION) src/man/firejail-profile.txt firejail-profile.5
30firejail-login.5: src/man/firejail-login.txt
31 ./mkman.sh $(VERSION) src/man/firejail-login.txt firejail-login.5
32
33clean:;
34 for dir in $(APPS); do \
35 $(MAKE) -C $$dir clean; \
36 done
37 for dir in $(MYLIBS); do \
38 $(MAKE) -C $$dir clean; \
39 done
40 rm -f firejail.1 firejail.1.gz firemon.1 firemon.1.gz firejail-profile.5 firejail-profile.5.gz firejail-login.5 firejail-login.5.gz
41
42distclean: clean
43 for dir in $(APPS); do \
44 $(MAKE) -C $$dir distclean; \
45 done
46 for dir in $(MYLIBS); do \
47 $(MAKE) -C $$dir distclean; \
48 done
49 rm -fr Makefile autom4te.cache config.log config.status config.h
50
51install: all
52 # firejail executable
53 strip src/firejail/firejail
54 mkdir -p $(DESTDIR)/$(PREFIX)/bin
55 install -c -m 0755 src/firejail/firejail $(DESTDIR)/$(PREFIX)/bin/.
56 chmod u+s $(DESTDIR)/$(PREFIX)/bin/firejail
57 # firemon executable
58 strip src/firemon/firemon
59 install -c -m 0755 src/firemon/firemon $(DESTDIR)/$(PREFIX)/bin/.
60 # libraries and plugins
61 strip src/libtrace/libtrace.so
62 mkdir -p $(DESTDIR)/$(PREFIX)/lib/firejail
63 install -c -m 0644 src/libtrace/libtrace.so $(DESTDIR)/$(PREFIX)/lib/firejail/.
64 strip src/ftee/ftee
65 install -c -m 0755 src/ftee/ftee $(DESTDIR)/$(PREFIX)/lib/firejail/.
66 install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(PREFIX)/lib/firejail/.
67 # documents
68 mkdir -p $(DESTDIR)/$(DOCDIR)
69 install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/.
70 install -c -m 0644 README $(DESTDIR)/$(DOCDIR)/.
71 install -c -m 0644 RELNOTES $(DESTDIR)/$(DOCDIR)/.
72 # etc files
73 mkdir -p $(DESTDIR)/etc/firejail
74 install -c -m 0644 etc/audacious.profile $(DESTDIR)/etc/firejail/.
75 install -c -m 0644 etc/clementine.profile $(DESTDIR)/etc/firejail/.
76 install -c -m 0644 etc/gnome-mplayer.profile $(DESTDIR)/etc/firejail/.
77 install -c -m 0644 etc/rhythmbox.profile $(DESTDIR)/etc/firejail/.
78 install -c -m 0644 etc/totem.profile $(DESTDIR)/etc/firejail/.
79 install -c -m 0644 etc/firefox.profile $(DESTDIR)/etc/firejail/.
80 install -c -m 0644 etc/icedove.profile $(DESTDIR)/etc/firejail/.
81 install -c -m 0644 etc/iceweasel.profile $(DESTDIR)/etc/firejail/.
82 install -c -m 0644 etc/midori.profile $(DESTDIR)/etc/firejail/.
83 install -c -m 0644 etc/evince.profile $(DESTDIR)/etc/firejail/.
84 install -c -m 0644 etc/chromium-browser.profile $(DESTDIR)/etc/firejail/.
85 install -c -m 0644 etc/chromium.profile $(DESTDIR)/etc/firejail/.
86 install -c -m 0644 etc/disable-mgmt.inc $(DESTDIR)/etc/firejail/.
87 install -c -m 0644 etc/disable-secret.inc $(DESTDIR)/etc/firejail/.
88 install -c -m 0644 etc/disable-common.inc $(DESTDIR)/etc/firejail/.
89 install -c -m 0644 etc/dropbox.profile $(DESTDIR)/etc/firejail/.
90 install -c -m 0644 etc/opera.profile $(DESTDIR)/etc/firejail/.
91 install -c -m 0644 etc/thunderbird.profile $(DESTDIR)/etc/firejail/.
92 install -c -m 0644 etc/transmission-gtk.profile $(DESTDIR)/etc/firejail/.
93 install -c -m 0644 etc/transmission-qt.profile $(DESTDIR)/etc/firejail/.
94 install -c -m 0644 etc/vlc.profile $(DESTDIR)/etc/firejail/.
95 install -c -m 0644 etc/deluge.profile $(DESTDIR)/etc/firejail/.
96 install -c -m 0644 etc/qbittorrent.profile $(DESTDIR)/etc/firejail/.
97 install -c -m 0644 etc/generic.profile $(DESTDIR)/etc/firejail/.
98 install -c -m 0644 etc/pidgin.profile $(DESTDIR)/etc/firejail/.
99 install -c -m 0644 etc/xchat.profile $(DESTDIR)/etc/firejail/.
100 install -c -m 0644 etc/empathy.profile $(DESTDIR)/etc/firejail/.
101 install -c -m 0644 etc/server.profile $(DESTDIR)/etc/firejail/.
102 install -c -m 0644 etc/icecat.profile $(DESTDIR)/etc/firejail/.
103 install -c -m 0644 etc/quassel.profile $(DESTDIR)/etc/firejail/.
104 install -c -m 0644 etc/deadbeef.profile $(DESTDIR)/etc/firejail/.
105 install -c -m 0644 etc/filezilla.profile $(DESTDIR)/etc/firejail/.
106 bash -c "if [ ! -f /etc/firejail/login.users ]; then install -c -m 0644 etc/login.users $(DESTDIR)/etc/firejail/.; fi;"
107 # man pages
108 rm -f firejail.1.gz
109 gzip -9n firejail.1
110 rm -f firemon.1.gz
111 gzip -9n firemon.1
112 rm -f firejail-profile.5.gz
113 gzip -9n firejail-profile.5
114 rm -f firejail-login.5.gz
115 gzip -9n firejail-login.5
116 mkdir -p $(DESTDIR)/$(PREFIX)/share/man/man1
117 install -c -m 0644 firejail.1.gz $(DESTDIR)/$(PREFIX)/share/man/man1/.
118 install -c -m 0644 firemon.1.gz $(DESTDIR)/$(PREFIX)/share/man/man1/.
119 mkdir -p $(DESTDIR)/$(PREFIX)/share/man/man5
120 install -c -m 0644 firejail-profile.5.gz $(DESTDIR)/$(PREFIX)/share/man/man5/.
121 install -c -m 0644 firejail-login.5.gz $(DESTDIR)/$(PREFIX)/share/man/man5/.
122 rm -f firejail.1.gz firemon.1.gz firejail-profile.5.gz firejail-login.5.gz
123 # bash completion
124 mkdir -p $(DESTDIR)/$(PREFIX)/share/bash-completion/completions
125 install -c -m 0644 etc/firejail.bash_completion $(DESTDIR)/$(PREFIX)/share/bash-completion/completions/firejail
126 install -c -m 0644 etc/firemon.bash_completion $(DESTDIR)/$(PREFIX)/share/bash-completion/completions/firemon
127
128uninstall:;
129 rm -f $(DESTDIR)/$(PREFIX)/bin/firejail
130 rm -f $(DESTDIR)/$(PREFIX)/bin/firemon
131 rm -fr $(DESTDIR)/$(PREFIX)/lib/firejail
132 rm -fr $(DESTDIR)/$(PREFIX)/share/doc/firejail
133 rm -f $(DESTDIR)/$(PREFIX)/share/man/man1/firejail.1*
134 rm -f $(DESTDIR)/$(PREFIX)/share/man/man1/firemon.1*
135 rm -f $(DESTDIR)/$(PREFIX)/share/man/man5/firejail-profile.5*
136 rm -f $(DESTDIR)/$(PREFIX)/share/man/man5/firejail-login.5*
137 rm -f $(DESTDIR)/$(PREFIX)/share/bash-completion/completions/firejail
138 rm -f $(DESTDIR)/$(PREFIX)/share/bash-completion/completions/firemon
139
140dist:
141 make distclean
142 rm -fr $(NAME)-$(VERSION) $(NAME)-$(VERSION).tar.bz2
143 mkdir $(NAME)-$(VERSION)
144 cd $(NAME)-$(VERSION); cp -a ../src .; cp -a ../etc .; cp -a ../platform .; cp -a ../test .; rm -f src/tools/rvtest; rm -fr src/art; cd ..
145 cd $(NAME)-$(VERSION); cp -a ../configure .; cp -a ../configure.ac .; cp -a ../Makefile.in .; cp -a ../install.sh .; cp -a ../mkman.sh .; cp -a ../mkdeb.sh .;cd ..
146 cd $(NAME)-$(VERSION); cp -a ../COPYING .; cp -a ../README .; cp -a ../RELNOTES .; cd ..
147 cd $(NAME)-$(VERSION); rm -fr `find . -name .svn`; rm -fr $(NAME)-$(VERSION); cd ..
148 tar -cjvf $(NAME)-$(VERSION).tar.bz2 $(NAME)-$(VERSION)
149 rm -fr $(NAME)-$(VERSION)
150
151deb: dist
152 ./mkdeb.sh $(NAME) $(VERSION)
153
154extras: all
155 $(MAKE) -C extras/firetools
156 \ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 000000000..dde1bfcbb
--- /dev/null
+++ b/README
@@ -0,0 +1,28 @@
1Firejail is a SUID sandbox program that reduces the risk of security
2breaches by restricting the running environment of untrusted applications
3using Linux namespaces and seccomp-bpf. It includes sandbox profiles for
4Iceweasel/Mozilla Firefox, Chromium, Midori, Opera, Evince, Transmission,
5VLC, Audoacious, Clementine, Rhythmbox, Totem, Deluge and qBittorrent.
6
7Firejail also expands the restricted shell facility found in bash by adding
8Linux namespace support. It supports sandboxing specific users upon login.
9
10Download: http://sourceforge.net/projects/firejail/files/
11Build and install: ./configure && make && sudo make install
12Documentation and support: http://firejail.sourceforge.net
13License: GPL v2
14
15Firejail Authors:
16
17netblue30 (netblue30@yahoo.com)
18Patrick Toomey (http://sourceforge.net/u/ptoomey/profile/)
19 - user namespace implementation, ticket 10
20Reiner Herrmann - a number of build patches, man page fixes (tickets 11, 12, 13, 19)
21sshirokov (http://sourceforge.net/u/yshirokov/profile/)
22 - Patch to output "Reading profile" to stderr instead of stdout (ticket 15)
23Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
24 - src/lib/libnetlink.c extracted from iproute2 software package
25G4JC (http://sourceforge.net/u/gaming4jc/profile/)
26 - ARM support (ticket 17)
27
28Copyright (C) 2014, 2015 Firejail Authors
diff --git a/RELNOTES b/RELNOTES
new file mode 100644
index 000000000..379c8f1c3
--- /dev/null
+++ b/RELNOTES
@@ -0,0 +1,215 @@
1firejail (0.9.28) baseline; urgency=low
2 * network scanning, --scan option
3 * interface MAC address support, --mac option
4 * IP address range, --iprange option
5 * traffic shaping, --bandwidth option
6 * reworked printing of network status at startup
7 * man pages rework
8 * added firejail-login man page
9 * added GNU Icecat, FileZilla, Pidgin, XChat, Empathy, DeaDBeeF default
10 profiles
11 * added an /etc/firejail/disable-common.inc file to hold common directory
12 blacklists
13 * blacklist Opera and Chrome/Chromium config directories in profile files
14 * support noroot option for profile files
15 * enabled noroot in default profile files
16 * bugfixes
17 -- netblue30 <netblue30@yahoo.com> Sat, 1 Aug 2015 08:00:00 -0500
18
19firejail (0.9.26) baseline; urgency=low
20 * private dev directory
21 * private.keep option for whitelisting home files in a new private directory
22 * user namespaces support, noroot option
23 * added Deluge and qBittorent profiles
24 * bugfixes
25 -- netblue30 <netblue30@yahoo.com> Thu, 30 Apr 2015 08:00:00 -0500
26
27
28firejail (0.9.24) baseline; urgency=low
29 * whitelist and blacklist seccomp filters
30 * doubledash option
31 * --shell=none support
32 * netfilter file support in profile files
33 * dns server support in profile files
34 * added --dns.print option
35 * added default profiles for Audacious, Clementine, Gnome-MPlayer, Rhythmbox and Totem.
36 * added --caps.drop=all in default profiles
37 * new syscalls in default seccomp filter: sysfs, sysctl, adjtimex, kcmp
38 * clock_adjtime, lookup_dcookie, perf_event_open, fanotify_init
39 * Bugfix: using /proc/sys/kernel/pid_max for the max number of pids
40 * two build patches from Reiner Herman (tickets 11, 12)
41 * man page patch from Reiner Herman (ticket 13)
42 * output patch (ticket 15) from sshirokov
43
44 -- netblue30 <netblue30@yahoo.com> Sun, 5 Apr 2015 08:00:00 -0500
45
46firejail (0.9.22) baseline; urgency=low
47 * Replaced --noip option with --ip=none
48 * Container stdout logging and log rotation
49 * Added process_vm_readv, process_vm_writev and mknod to
50 * default seccomp blacklist
51 * Added CAP_MKNOD to default caps blacklist
52 * Blacklist and whitelist custom Linux capabilities filters
53 * macvlan device driver support for --net option
54 * DNS server support, --dns option
55 * Netfilter support
56 * Monitor network statistics, --netstats option
57 * Added profile for Mozilla Thunderbird/Icedove
58 * - --overlay support for Linux kernels 3.18+
59 * Bugfix: preserve .Xauthority file in private mode (test with ssh -X)
60 * Bugfix: check uid/gid for cgroup
61
62 -- netblue30 <netblue30@yahoo.com> Mon, 9 Mar 2015 09:00:00 -0500
63
64firejail (0.9.20) baseline; urgency=low
65 * utmp, btmp and wtmp enhancements
66 * create empty /var/log/wtmp and /var/log/btmp files in sandbox
67 * generate a new /var/run/utmp file in sandbox
68 * CPU affinity, --cpu option
69 * Linux control groups support, --cgroup option
70 * Opera web browser support
71 * VLC support
72 * Added "empty" attribute to seccomp command to remove the default
73 * syscall list form seccomp blacklist
74 * Added --nogroups option to disable supplementary groups for regular
75 * users. root user always runs without supplementary groups.
76 * firemon enhancements
77 * display the command that started the sandbox
78 * added --caps option to display capabilities for all sandboxes
79 * added --cgroup option to display the control groups for all sandboxes
80 * added --cpu option to display CPU affinity for all sandboxes
81 * added --seccomp option to display seccomp setting for all sandboxes
82 * New compile time options: --disable-chroot, --disable-bind
83 * bugfixes
84
85 -- netblue30 <netblue30@yahoo.com> Mon, 02 Feb 2015 08:00:00 -0500
86
87firejail (0.9.18) baseline; urgency=low
88 * Support for tracing system, setuid, setgid, setfsuid, setfsgid syscalls
89 * Support for tracing setreuid, setregid, setresuid, setresguid syscalls
90 * Added profiles for transmission-gtk and transmission-qt
91 * bugfixes
92
93 -- netblue30 <netblue30@yahoo.com> Fri, 25 Dec 2014 10:00:00 -0500
94
95firejail (0.9.16) baseline; urgency=low
96 * Configurable private home directory
97 * Configurable default user shell
98 * Software configuration support for --docdir and DESTDIR
99 * Profile file support for include, caps, seccomp and private keywords
100 * Dropbox profile file
101 * Linux capabilities and seccomp filters enabled by default for Firefox,
102 Midori, Evince and Dropbox
103 * bugfixes
104
105 -- netblue30 <netblue30@yahoo.com> Tue, 4 Nov 2014 10:00:00 -0500
106
107firejail (0.9.14) baseline; urgency=low
108 * Linux capabilities and seccomp filters are automatically enabled in
109 chroot mode (--chroot option) if the sandbox is started as regular user
110 * Added support for user defined seccomp blacklists
111 * Added syscall trace support
112 * Added --tmpfs option
113 * Added --balcklist option
114 * Added --read-only option
115 * Added --bind option
116 * Logging enhancements
117 * --overlay option was reactivated
118 * Added firemon support to print the ARP table for each sandbox
119 * Added firemon support to print the route table for each sandbox
120 * Added firemon support to print interface information for each sandbox
121 * bugfixes
122
123 -- netblue30 <netblue30@yahoo.com> Tue, 15 Oct 2014 10:00:00 -0500
124
125firejail (0.9.12.2) baseline; urgency=low
126 * Fix for pulseaudio problems
127 * --overlay option was temporarily disabled in this build
128
129 -- netblue30 <netblue30@yahoo.com> Mon, 29 Sept 2014 07:00:00 -0500
130
131firejail (0.9.12.1) baseline; urgency=low
132 * Fix for pulseaudio problems
133 * --overlay option was temporarily disabled in this build
134
135 -- netblue30 <netblue30@yahoo.com> Mon, 22 Sept 2014 09:00:00 -0500
136
137firejail (0.9.12) baseline; urgency=low
138 * Added capabilities support
139 * Added support for CentOS 7
140 * bugfixes
141
142 -- netblue30 <netblue30@yahoo.com> Mon, 15 Sept 2014 10:00:00 -0500
143
144firejail (0.9.10) baseline; urgency=low
145 * Disable /proc/kcore, /proc/kallsyms, /dev/port, /boot
146 * Fixed --top option CPU utilization calculation
147 * Implemented --tree option in firejail and firemon
148 * Implemented --join=name option
149 * Implemented --shutdown option
150 * Preserve the current working directory if possible
151 * Cppcheck and clang errors cleanup
152 * Added a Chromium web browser profile
153
154 -- netblue30 <netblue30@yahoo.com> Thu, 28 Aug 2014 07:00:00 -0500
155
156firejail (0.9.8.1) baseline; urgency=low
157 * FIxed a number of bugs introduced in 0.9.8
158
159 -- netblue30 <netblue30@yahoo.com> Fri, 25 Jul 2014 07:25:00 -0500
160
161firejail (0.9.8) baseline; urgency=low
162 * Implemented nowrap mode for firejail --list command option
163 * Added --top option in both firejail and firemon
164 * seccomp filter support
165 * Added pid support for firemon
166 * bugfixes
167
168 -- netblue30 <netblue30@yahoo.com> Tue, 24 Jul 2014 08:51:00 -0500
169
170firejail (0.9.6) baseline; urgency=low
171
172 * Mounting tmpfs on top of /var/log, required by several server programs
173 * Server fixes for /var/lib and /var/cache
174 * Private mode fixes
175 * csh and zsh default shell support
176 * Chroot mode fixes
177 * Added support for lighttpd, isc-dhcp-server, apache2, nginx, snmpd,
178
179 -- netblue30 <netblue30@yahoo.com> Sat, 7 Jun 2014 09:00:00 -0500
180
181firejail (0.9.4) baseline; urgency=low
182
183 * Fixed resolv.conf on Ubuntu systems using DHCP
184 * Fixed resolv.conf on Debian systems using resolvconf package
185 * Fixed /var/lock directory
186 * Fixed /var/tmp directory
187 * Fixed symbolic links in profile files
188 * Added profiles for evince, midori
189
190 -- netblue30 <netblue30@yahoo.com> Sun, 4 May 2014 08:00:00 -0500
191
192firejail (0.9.2) baseline; urgency=low
193
194 * Checking IP address passed with --ip option using ARP; exit if the address
195 is already present
196 * Using a lock file during ARP address assignment in order to removed a race
197 condition.
198 * Several fixes to --private option; it also mounts a tmpfs filesystem on top
199 of /tmp
200 * Added user access check for profile file
201 * Added --defaultgw option
202 * Added support of --noip option; it is necessary for DHCP setups
203 * Added syslog support
204 * Added support for "tmpfs" and "read-only" profile commands
205 * Added an expect-based testing framework for the project
206 * Added bash completion support
207 * Added support for multiple networks
208
209 -- netblue30 <netblue30@yahoo.com> Fri, 25 Apr 2014 08:00:00 -0500
210
211firejail (0.9) baseline; urgency=low
212
213 * First beta version
214
215 -- netblue30 <netblue30@yahoo.com> Sat, 12 Apr 2014 09:00:00 -0500
diff --git a/configure b/configure
new file mode 100755
index 000000000..50abe97c2
--- /dev/null
+++ b/configure
@@ -0,0 +1,4723 @@
1#! /bin/sh
2# Guess values for system-dependent variables and create Makefiles.
3# Generated by GNU Autoconf 2.69 for firejail 0.9.28.
4#
5# Report bugs to <netblue30@yahoo.com>.
6#
7#
8# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
9#
10#
11# This configure script is free software; the Free Software Foundation
12# gives unlimited permission to copy, distribute and modify it.
13## -------------------- ##
14## M4sh Initialization. ##
15## -------------------- ##
16
17# Be more Bourne compatible
18DUALCASE=1; export DUALCASE # for MKS sh
19if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
20 emulate sh
21 NULLCMD=:
22 # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
23 # is contrary to our usage. Disable this feature.
24 alias -g '${1+"$@"}'='"$@"'
25 setopt NO_GLOB_SUBST
26else
27 case `(set -o) 2>/dev/null` in #(
28 *posix*) :
29 set -o posix ;; #(
30 *) :
31 ;;
32esac
33fi
34
35
36as_nl='
37'
38export as_nl
39# Printing a long string crashes Solaris 7 /usr/bin/printf.
40as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
41as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
42as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
43# Prefer a ksh shell builtin over an external printf program on Solaris,
44# but without wasting forks for bash or zsh.
45if test -z "$BASH_VERSION$ZSH_VERSION" \
46 && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
47 as_echo='print -r --'
48 as_echo_n='print -rn --'
49elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
50 as_echo='printf %s\n'
51 as_echo_n='printf %s'
52else
53 if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
54 as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
55 as_echo_n='/usr/ucb/echo -n'
56 else
57 as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
58 as_echo_n_body='eval
59 arg=$1;
60 case $arg in #(
61 *"$as_nl"*)
62 expr "X$arg" : "X\\(.*\\)$as_nl";
63 arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
64 esac;
65 expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
66 '
67 export as_echo_n_body
68 as_echo_n='sh -c $as_echo_n_body as_echo'
69 fi
70 export as_echo_body
71 as_echo='sh -c $as_echo_body as_echo'
72fi
73
74# The user is always right.
75if test "${PATH_SEPARATOR+set}" != set; then
76 PATH_SEPARATOR=:
77 (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
78 (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
79 PATH_SEPARATOR=';'
80 }
81fi
82
83
84# IFS
85# We need space, tab and new line, in precisely that order. Quoting is
86# there to prevent editors from complaining about space-tab.
87# (If _AS_PATH_WALK were called with IFS unset, it would disable word
88# splitting by setting IFS to empty value.)
89IFS=" "" $as_nl"
90
91# Find who we are. Look in the path if we contain no directory separator.
92as_myself=
93case $0 in #((
94 *[\\/]* ) as_myself=$0 ;;
95 *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
96for as_dir in $PATH
97do
98 IFS=$as_save_IFS
99 test -z "$as_dir" && as_dir=.
100 test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
101 done
102IFS=$as_save_IFS
103
104 ;;
105esac
106# We did not find ourselves, most probably we were run as `sh COMMAND'
107# in which case we are not to be found in the path.
108if test "x$as_myself" = x; then
109 as_myself=$0
110fi
111if test ! -f "$as_myself"; then
112 $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
113 exit 1
114fi
115
116# Unset variables that we do not need and which cause bugs (e.g. in
117# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
118# suppresses any "Segmentation fault" message there. '((' could
119# trigger a bug in pdksh 5.2.14.
120for as_var in BASH_ENV ENV MAIL MAILPATH
121do eval test x\${$as_var+set} = xset \
122 && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
123done
124PS1='$ '
125PS2='> '
126PS4='+ '
127
128# NLS nuisances.
129LC_ALL=C
130export LC_ALL
131LANGUAGE=C
132export LANGUAGE
133
134# CDPATH.
135(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
136
137# Use a proper internal environment variable to ensure we don't fall
138 # into an infinite loop, continuously re-executing ourselves.
139 if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
140 _as_can_reexec=no; export _as_can_reexec;
141 # We cannot yet assume a decent shell, so we have to provide a
142# neutralization value for shells without unset; and this also
143# works around shells that cannot unset nonexistent variables.
144# Preserve -v and -x to the replacement shell.
145BASH_ENV=/dev/null
146ENV=/dev/null
147(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
148case $- in # ((((
149 *v*x* | *x*v* ) as_opts=-vx ;;
150 *v* ) as_opts=-v ;;
151 *x* ) as_opts=-x ;;
152 * ) as_opts= ;;
153esac
154exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
155# Admittedly, this is quite paranoid, since all the known shells bail
156# out after a failed `exec'.
157$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
158as_fn_exit 255
159 fi
160 # We don't want this to propagate to other subprocesses.
161 { _as_can_reexec=; unset _as_can_reexec;}
162if test "x$CONFIG_SHELL" = x; then
163 as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
164 emulate sh
165 NULLCMD=:
166 # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
167 # is contrary to our usage. Disable this feature.
168 alias -g '\${1+\"\$@\"}'='\"\$@\"'
169 setopt NO_GLOB_SUBST
170else
171 case \`(set -o) 2>/dev/null\` in #(
172 *posix*) :
173 set -o posix ;; #(
174 *) :
175 ;;
176esac
177fi
178"
179 as_required="as_fn_return () { (exit \$1); }
180as_fn_success () { as_fn_return 0; }
181as_fn_failure () { as_fn_return 1; }
182as_fn_ret_success () { return 0; }
183as_fn_ret_failure () { return 1; }
184
185exitcode=0
186as_fn_success || { exitcode=1; echo as_fn_success failed.; }
187as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
188as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
189as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
190if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
191
192else
193 exitcode=1; echo positional parameters were not saved.
194fi
195test x\$exitcode = x0 || exit 1
196test -x / || exit 1"
197 as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
198 as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
199 eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
200 test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
201test \$(( 1 + 1 )) = 2 || exit 1"
202 if (eval "$as_required") 2>/dev/null; then :
203 as_have_required=yes
204else
205 as_have_required=no
206fi
207 if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
208
209else
210 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
211as_found=false
212for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
213do
214 IFS=$as_save_IFS
215 test -z "$as_dir" && as_dir=.
216 as_found=:
217 case $as_dir in #(
218 /*)
219 for as_base in sh bash ksh sh5; do
220 # Try only shells that exist, to save several forks.
221 as_shell=$as_dir/$as_base
222 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
223 { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
224 CONFIG_SHELL=$as_shell as_have_required=yes
225 if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
226 break 2
227fi
228fi
229 done;;
230 esac
231 as_found=false
232done
233$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
234 { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
235 CONFIG_SHELL=$SHELL as_have_required=yes
236fi; }
237IFS=$as_save_IFS
238
239
240 if test "x$CONFIG_SHELL" != x; then :
241 export CONFIG_SHELL
242 # We cannot yet assume a decent shell, so we have to provide a
243# neutralization value for shells without unset; and this also
244# works around shells that cannot unset nonexistent variables.
245# Preserve -v and -x to the replacement shell.
246BASH_ENV=/dev/null
247ENV=/dev/null
248(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
249case $- in # ((((
250 *v*x* | *x*v* ) as_opts=-vx ;;
251 *v* ) as_opts=-v ;;
252 *x* ) as_opts=-x ;;
253 * ) as_opts= ;;
254esac
255exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
256# Admittedly, this is quite paranoid, since all the known shells bail
257# out after a failed `exec'.
258$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
259exit 255
260fi
261
262 if test x$as_have_required = xno; then :
263 $as_echo "$0: This script requires a shell more modern than all"
264 $as_echo "$0: the shells that I found on your system."
265 if test x${ZSH_VERSION+set} = xset ; then
266 $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
267 $as_echo "$0: be upgraded to zsh 4.3.4 or later."
268 else
269 $as_echo "$0: Please tell bug-autoconf@gnu.org and
270$0: netblue30@yahoo.com about your system, including any
271$0: error possibly output before this message. Then install
272$0: a modern shell, or manually run the script under such a
273$0: shell if you do have one."
274 fi
275 exit 1
276fi
277fi
278fi
279SHELL=${CONFIG_SHELL-/bin/sh}
280export SHELL
281# Unset more variables known to interfere with behavior of common tools.
282CLICOLOR_FORCE= GREP_OPTIONS=
283unset CLICOLOR_FORCE GREP_OPTIONS
284
285## --------------------- ##
286## M4sh Shell Functions. ##
287## --------------------- ##
288# as_fn_unset VAR
289# ---------------
290# Portably unset VAR.
291as_fn_unset ()
292{
293 { eval $1=; unset $1;}
294}
295as_unset=as_fn_unset
296
297# as_fn_set_status STATUS
298# -----------------------
299# Set $? to STATUS, without forking.
300as_fn_set_status ()
301{
302 return $1
303} # as_fn_set_status
304
305# as_fn_exit STATUS
306# -----------------
307# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
308as_fn_exit ()
309{
310 set +e
311 as_fn_set_status $1
312 exit $1
313} # as_fn_exit
314
315# as_fn_mkdir_p
316# -------------
317# Create "$as_dir" as a directory, including parents if necessary.
318as_fn_mkdir_p ()
319{
320
321 case $as_dir in #(
322 -*) as_dir=./$as_dir;;
323 esac
324 test -d "$as_dir" || eval $as_mkdir_p || {
325 as_dirs=
326 while :; do
327 case $as_dir in #(
328 *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
329 *) as_qdir=$as_dir;;
330 esac
331 as_dirs="'$as_qdir' $as_dirs"
332 as_dir=`$as_dirname -- "$as_dir" ||
333$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
334 X"$as_dir" : 'X\(//\)[^/]' \| \
335 X"$as_dir" : 'X\(//\)$' \| \
336 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
337$as_echo X"$as_dir" |
338 sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
339 s//\1/
340 q
341 }
342 /^X\(\/\/\)[^/].*/{
343 s//\1/
344 q
345 }
346 /^X\(\/\/\)$/{
347 s//\1/
348 q
349 }
350 /^X\(\/\).*/{
351 s//\1/
352 q
353 }
354 s/.*/./; q'`
355 test -d "$as_dir" && break
356 done
357 test -z "$as_dirs" || eval "mkdir $as_dirs"
358 } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
359
360
361} # as_fn_mkdir_p
362
363# as_fn_executable_p FILE
364# -----------------------
365# Test if FILE is an executable regular file.
366as_fn_executable_p ()
367{
368 test -f "$1" && test -x "$1"
369} # as_fn_executable_p
370# as_fn_append VAR VALUE
371# ----------------------
372# Append the text in VALUE to the end of the definition contained in VAR. Take
373# advantage of any shell optimizations that allow amortized linear growth over
374# repeated appends, instead of the typical quadratic growth present in naive
375# implementations.
376if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
377 eval 'as_fn_append ()
378 {
379 eval $1+=\$2
380 }'
381else
382 as_fn_append ()
383 {
384 eval $1=\$$1\$2
385 }
386fi # as_fn_append
387
388# as_fn_arith ARG...
389# ------------------
390# Perform arithmetic evaluation on the ARGs, and store the result in the
391# global $as_val. Take advantage of shells that can avoid forks. The arguments
392# must be portable across $(()) and expr.
393if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
394 eval 'as_fn_arith ()
395 {
396 as_val=$(( $* ))
397 }'
398else
399 as_fn_arith ()
400 {
401 as_val=`expr "$@" || test $? -eq 1`
402 }
403fi # as_fn_arith
404
405
406# as_fn_error STATUS ERROR [LINENO LOG_FD]
407# ----------------------------------------
408# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
409# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
410# script with STATUS, using 1 if that was 0.
411as_fn_error ()
412{
413 as_status=$1; test $as_status -eq 0 && as_status=1
414 if test "$4"; then
415 as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
416 $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
417 fi
418 $as_echo "$as_me: error: $2" >&2
419 as_fn_exit $as_status
420} # as_fn_error
421
422if expr a : '\(a\)' >/dev/null 2>&1 &&
423 test "X`expr 00001 : '.*\(...\)'`" = X001; then
424 as_expr=expr
425else
426 as_expr=false
427fi
428
429if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
430 as_basename=basename
431else
432 as_basename=false
433fi
434
435if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
436 as_dirname=dirname
437else
438 as_dirname=false
439fi
440
441as_me=`$as_basename -- "$0" ||
442$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
443 X"$0" : 'X\(//\)$' \| \
444 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
445$as_echo X/"$0" |
446 sed '/^.*\/\([^/][^/]*\)\/*$/{
447 s//\1/
448 q
449 }
450 /^X\/\(\/\/\)$/{
451 s//\1/
452 q
453 }
454 /^X\/\(\/\).*/{
455 s//\1/
456 q
457 }
458 s/.*/./; q'`
459
460# Avoid depending upon Character Ranges.
461as_cr_letters='abcdefghijklmnopqrstuvwxyz'
462as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
463as_cr_Letters=$as_cr_letters$as_cr_LETTERS
464as_cr_digits='0123456789'
465as_cr_alnum=$as_cr_Letters$as_cr_digits
466
467
468 as_lineno_1=$LINENO as_lineno_1a=$LINENO
469 as_lineno_2=$LINENO as_lineno_2a=$LINENO
470 eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
471 test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
472 # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
473 sed -n '
474 p
475 /[$]LINENO/=
476 ' <$as_myself |
477 sed '
478 s/[$]LINENO.*/&-/
479 t lineno
480 b
481 :lineno
482 N
483 :loop
484 s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
485 t loop
486 s/-\n.*//
487 ' >$as_me.lineno &&
488 chmod +x "$as_me.lineno" ||
489 { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
490
491 # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
492 # already done that, so ensure we don't try to do so again and fall
493 # in an infinite loop. This has already happened in practice.
494 _as_can_reexec=no; export _as_can_reexec
495 # Don't try to exec as it changes $[0], causing all sort of problems
496 # (the dirname of $[0] is not the place where we might find the
497 # original and so on. Autoconf is especially sensitive to this).
498 . "./$as_me.lineno"
499 # Exit status is that of the last command.
500 exit
501}
502
503ECHO_C= ECHO_N= ECHO_T=
504case `echo -n x` in #(((((
505-n*)
506 case `echo 'xy\c'` in
507 *c*) ECHO_T=' ';; # ECHO_T is single tab character.
508 xy) ECHO_C='\c';;
509 *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
510 ECHO_T=' ';;
511 esac;;
512*)
513 ECHO_N='-n';;
514esac
515
516rm -f conf$$ conf$$.exe conf$$.file
517if test -d conf$$.dir; then
518 rm -f conf$$.dir/conf$$.file
519else
520 rm -f conf$$.dir
521 mkdir conf$$.dir 2>/dev/null
522fi
523if (echo >conf$$.file) 2>/dev/null; then
524 if ln -s conf$$.file conf$$ 2>/dev/null; then
525 as_ln_s='ln -s'
526 # ... but there are two gotchas:
527 # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
528 # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
529 # In both cases, we have to default to `cp -pR'.
530 ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
531 as_ln_s='cp -pR'
532 elif ln conf$$.file conf$$ 2>/dev/null; then
533 as_ln_s=ln
534 else
535 as_ln_s='cp -pR'
536 fi
537else
538 as_ln_s='cp -pR'
539fi
540rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
541rmdir conf$$.dir 2>/dev/null
542
543if mkdir -p . 2>/dev/null; then
544 as_mkdir_p='mkdir -p "$as_dir"'
545else
546 test -d ./-p && rmdir ./-p
547 as_mkdir_p=false
548fi
549
550as_test_x='test -x'
551as_executable_p=as_fn_executable_p
552
553# Sed expression to map a string onto a valid CPP name.
554as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
555
556# Sed expression to map a string onto a valid variable name.
557as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
558
559
560test -n "$DJDIR" || exec 7<&0 </dev/null
561exec 6>&1
562
563# Name of the host.
564# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
565# so uname gets run too.
566ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
567
568#
569# Initializations.
570#
571ac_default_prefix=/usr/local
572ac_clean_files=
573ac_config_libobj_dir=.
574LIBOBJS=
575cross_compiling=no
576subdirs=
577MFLAGS=
578MAKEFLAGS=
579
580# Identity of this package.
581PACKAGE_NAME='firejail'
582PACKAGE_TARNAME='firejail'
583PACKAGE_VERSION='0.9.28'
584PACKAGE_STRING='firejail 0.9.28'
585PACKAGE_BUGREPORT='netblue30@yahoo.com'
586PACKAGE_URL='http://firejail.sourceforge.net'
587
588ac_unique_file="src/firejail/main.c"
589# Factoring default headers for most tests.
590ac_includes_default="\
591#include <stdio.h>
592#ifdef HAVE_SYS_TYPES_H
593# include <sys/types.h>
594#endif
595#ifdef HAVE_SYS_STAT_H
596# include <sys/stat.h>
597#endif
598#ifdef STDC_HEADERS
599# include <stdlib.h>
600# include <stddef.h>
601#else
602# ifdef HAVE_STDLIB_H
603# include <stdlib.h>
604# endif
605#endif
606#ifdef HAVE_STRING_H
607# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
608# include <memory.h>
609# endif
610# include <string.h>
611#endif
612#ifdef HAVE_STRINGS_H
613# include <strings.h>
614#endif
615#ifdef HAVE_INTTYPES_H
616# include <inttypes.h>
617#endif
618#ifdef HAVE_STDINT_H
619# include <stdint.h>
620#endif
621#ifdef HAVE_UNISTD_H
622# include <unistd.h>
623#endif"
624
625ac_subst_vars='LTLIBOBJS
626LIBOBJS
627HAVE_SECCOMP_H
628EGREP
629GREP
630CPP
631HAVE_BIND
632HAVE_CHROOT
633HAVE_SECCOMP
634RANLIB
635INSTALL_DATA
636INSTALL_SCRIPT
637INSTALL_PROGRAM
638OBJEXT
639EXEEXT
640ac_ct_CC
641CPPFLAGS
642LDFLAGS
643CFLAGS
644CC
645target_alias
646host_alias
647build_alias
648LIBS
649ECHO_T
650ECHO_N
651ECHO_C
652DEFS
653mandir
654localedir
655libdir
656psdir
657pdfdir
658dvidir
659htmldir
660infodir
661docdir
662oldincludedir
663includedir
664localstatedir
665sharedstatedir
666sysconfdir
667datadir
668datarootdir
669libexecdir
670sbindir
671bindir
672program_transform_name
673prefix
674exec_prefix
675PACKAGE_URL
676PACKAGE_BUGREPORT
677PACKAGE_STRING
678PACKAGE_VERSION
679PACKAGE_TARNAME
680PACKAGE_NAME
681PATH_SEPARATOR
682SHELL'
683ac_subst_files=''
684ac_user_opts='
685enable_option_checking
686enable_seccomp
687enable_chroot
688enable_bind
689'
690 ac_precious_vars='build_alias
691host_alias
692target_alias
693CC
694CFLAGS
695LDFLAGS
696LIBS
697CPPFLAGS
698CPP'
699
700
701# Initialize some variables set by options.
702ac_init_help=
703ac_init_version=false
704ac_unrecognized_opts=
705ac_unrecognized_sep=
706# The variables have the same names as the options, with
707# dashes changed to underlines.
708cache_file=/dev/null
709exec_prefix=NONE
710no_create=
711no_recursion=
712prefix=NONE
713program_prefix=NONE
714program_suffix=NONE
715program_transform_name=s,x,x,
716silent=
717site=
718srcdir=
719verbose=
720x_includes=NONE
721x_libraries=NONE
722
723# Installation directory options.
724# These are left unexpanded so users can "make install exec_prefix=/foo"
725# and all the variables that are supposed to be based on exec_prefix
726# by default will actually change.
727# Use braces instead of parens because sh, perl, etc. also accept them.
728# (The list follows the same order as the GNU Coding Standards.)
729bindir='${exec_prefix}/bin'
730sbindir='${exec_prefix}/sbin'
731libexecdir='${exec_prefix}/libexec'
732datarootdir='${prefix}/share'
733datadir='${datarootdir}'
734sysconfdir='${prefix}/etc'
735sharedstatedir='${prefix}/com'
736localstatedir='${prefix}/var'
737includedir='${prefix}/include'
738oldincludedir='/usr/include'
739docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
740infodir='${datarootdir}/info'
741htmldir='${docdir}'
742dvidir='${docdir}'
743pdfdir='${docdir}'
744psdir='${docdir}'
745libdir='${exec_prefix}/lib'
746localedir='${datarootdir}/locale'
747mandir='${datarootdir}/man'
748
749ac_prev=
750ac_dashdash=
751for ac_option
752do
753 # If the previous option needs an argument, assign it.
754 if test -n "$ac_prev"; then
755 eval $ac_prev=\$ac_option
756 ac_prev=
757 continue
758 fi
759
760 case $ac_option in
761 *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
762 *=) ac_optarg= ;;
763 *) ac_optarg=yes ;;
764 esac
765
766 # Accept the important Cygnus configure options, so we can diagnose typos.
767
768 case $ac_dashdash$ac_option in
769 --)
770 ac_dashdash=yes ;;
771
772 -bindir | --bindir | --bindi | --bind | --bin | --bi)
773 ac_prev=bindir ;;
774 -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
775 bindir=$ac_optarg ;;
776
777 -build | --build | --buil | --bui | --bu)
778 ac_prev=build_alias ;;
779 -build=* | --build=* | --buil=* | --bui=* | --bu=*)
780 build_alias=$ac_optarg ;;
781
782 -cache-file | --cache-file | --cache-fil | --cache-fi \
783 | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
784 ac_prev=cache_file ;;
785 -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
786 | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
787 cache_file=$ac_optarg ;;
788
789 --config-cache | -C)
790 cache_file=config.cache ;;
791
792 -datadir | --datadir | --datadi | --datad)
793 ac_prev=datadir ;;
794 -datadir=* | --datadir=* | --datadi=* | --datad=*)
795 datadir=$ac_optarg ;;
796
797 -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
798 | --dataroo | --dataro | --datar)
799 ac_prev=datarootdir ;;
800 -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
801 | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
802 datarootdir=$ac_optarg ;;
803
804 -disable-* | --disable-*)
805 ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
806 # Reject names that are not valid shell variable names.
807 expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
808 as_fn_error $? "invalid feature name: $ac_useropt"
809 ac_useropt_orig=$ac_useropt
810 ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
811 case $ac_user_opts in
812 *"
813"enable_$ac_useropt"
814"*) ;;
815 *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
816 ac_unrecognized_sep=', ';;
817 esac
818 eval enable_$ac_useropt=no ;;
819
820 -docdir | --docdir | --docdi | --doc | --do)
821 ac_prev=docdir ;;
822 -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
823 docdir=$ac_optarg ;;
824
825 -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
826 ac_prev=dvidir ;;
827 -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
828 dvidir=$ac_optarg ;;
829
830 -enable-* | --enable-*)
831 ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
832 # Reject names that are not valid shell variable names.
833 expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
834 as_fn_error $? "invalid feature name: $ac_useropt"
835 ac_useropt_orig=$ac_useropt
836 ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
837 case $ac_user_opts in
838 *"
839"enable_$ac_useropt"
840"*) ;;
841 *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
842 ac_unrecognized_sep=', ';;
843 esac
844 eval enable_$ac_useropt=\$ac_optarg ;;
845
846 -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
847 | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
848 | --exec | --exe | --ex)
849 ac_prev=exec_prefix ;;
850 -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
851 | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
852 | --exec=* | --exe=* | --ex=*)
853 exec_prefix=$ac_optarg ;;
854
855 -gas | --gas | --ga | --g)
856 # Obsolete; use --with-gas.
857 with_gas=yes ;;
858
859 -help | --help | --hel | --he | -h)
860 ac_init_help=long ;;
861 -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
862 ac_init_help=recursive ;;
863 -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
864 ac_init_help=short ;;
865
866 -host | --host | --hos | --ho)
867 ac_prev=host_alias ;;
868 -host=* | --host=* | --hos=* | --ho=*)
869 host_alias=$ac_optarg ;;
870
871 -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
872 ac_prev=htmldir ;;
873 -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
874 | --ht=*)
875 htmldir=$ac_optarg ;;
876
877 -includedir | --includedir | --includedi | --included | --include \
878 | --includ | --inclu | --incl | --inc)
879 ac_prev=includedir ;;
880 -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
881 | --includ=* | --inclu=* | --incl=* | --inc=*)
882 includedir=$ac_optarg ;;
883
884 -infodir | --infodir | --infodi | --infod | --info | --inf)
885 ac_prev=infodir ;;
886 -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
887 infodir=$ac_optarg ;;
888
889 -libdir | --libdir | --libdi | --libd)
890 ac_prev=libdir ;;
891 -libdir=* | --libdir=* | --libdi=* | --libd=*)
892 libdir=$ac_optarg ;;
893
894 -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
895 | --libexe | --libex | --libe)
896 ac_prev=libexecdir ;;
897 -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
898 | --libexe=* | --libex=* | --libe=*)
899 libexecdir=$ac_optarg ;;
900
901 -localedir | --localedir | --localedi | --localed | --locale)
902 ac_prev=localedir ;;
903 -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
904 localedir=$ac_optarg ;;
905
906 -localstatedir | --localstatedir | --localstatedi | --localstated \
907 | --localstate | --localstat | --localsta | --localst | --locals)
908 ac_prev=localstatedir ;;
909 -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
910 | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
911 localstatedir=$ac_optarg ;;
912
913 -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
914 ac_prev=mandir ;;
915 -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
916 mandir=$ac_optarg ;;
917
918 -nfp | --nfp | --nf)
919 # Obsolete; use --without-fp.
920 with_fp=no ;;
921
922 -no-create | --no-create | --no-creat | --no-crea | --no-cre \
923 | --no-cr | --no-c | -n)
924 no_create=yes ;;
925
926 -no-recursion | --no-recursion | --no-recursio | --no-recursi \
927 | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
928 no_recursion=yes ;;
929
930 -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
931 | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
932 | --oldin | --oldi | --old | --ol | --o)
933 ac_prev=oldincludedir ;;
934 -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
935 | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
936 | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
937 oldincludedir=$ac_optarg ;;
938
939 -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
940 ac_prev=prefix ;;
941 -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
942 prefix=$ac_optarg ;;
943
944 -program-prefix | --program-prefix | --program-prefi | --program-pref \
945 | --program-pre | --program-pr | --program-p)
946 ac_prev=program_prefix ;;
947 -program-prefix=* | --program-prefix=* | --program-prefi=* \
948 | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
949 program_prefix=$ac_optarg ;;
950
951 -program-suffix | --program-suffix | --program-suffi | --program-suff \
952 | --program-suf | --program-su | --program-s)
953 ac_prev=program_suffix ;;
954 -program-suffix=* | --program-suffix=* | --program-suffi=* \
955 | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
956 program_suffix=$ac_optarg ;;
957
958 -program-transform-name | --program-transform-name \
959 | --program-transform-nam | --program-transform-na \
960 | --program-transform-n | --program-transform- \
961 | --program-transform | --program-transfor \
962 | --program-transfo | --program-transf \
963 | --program-trans | --program-tran \
964 | --progr-tra | --program-tr | --program-t)
965 ac_prev=program_transform_name ;;
966 -program-transform-name=* | --program-transform-name=* \
967 | --program-transform-nam=* | --program-transform-na=* \
968 | --program-transform-n=* | --program-transform-=* \
969 | --program-transform=* | --program-transfor=* \
970 | --program-transfo=* | --program-transf=* \
971 | --program-trans=* | --program-tran=* \
972 | --progr-tra=* | --program-tr=* | --program-t=*)
973 program_transform_name=$ac_optarg ;;
974
975 -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
976 ac_prev=pdfdir ;;
977 -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
978 pdfdir=$ac_optarg ;;
979
980 -psdir | --psdir | --psdi | --psd | --ps)
981 ac_prev=psdir ;;
982 -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
983 psdir=$ac_optarg ;;
984
985 -q | -quiet | --quiet | --quie | --qui | --qu | --q \
986 | -silent | --silent | --silen | --sile | --sil)
987 silent=yes ;;
988
989 -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
990 ac_prev=sbindir ;;
991 -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
992 | --sbi=* | --sb=*)
993 sbindir=$ac_optarg ;;
994
995 -sharedstatedir | --sharedstatedir | --sharedstatedi \
996 | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
997 | --sharedst | --shareds | --shared | --share | --shar \
998 | --sha | --sh)
999 ac_prev=sharedstatedir ;;
1000 -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
1001 | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
1002 | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
1003 | --sha=* | --sh=*)
1004 sharedstatedir=$ac_optarg ;;
1005
1006 -site | --site | --sit)
1007 ac_prev=site ;;
1008 -site=* | --site=* | --sit=*)
1009 site=$ac_optarg ;;
1010
1011 -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
1012 ac_prev=srcdir ;;
1013 -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
1014 srcdir=$ac_optarg ;;
1015
1016 -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
1017 | --syscon | --sysco | --sysc | --sys | --sy)
1018 ac_prev=sysconfdir ;;
1019 -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
1020 | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
1021 sysconfdir=$ac_optarg ;;
1022
1023 -target | --target | --targe | --targ | --tar | --ta | --t)
1024 ac_prev=target_alias ;;
1025 -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
1026 target_alias=$ac_optarg ;;
1027
1028 -v | -verbose | --verbose | --verbos | --verbo | --verb)
1029 verbose=yes ;;
1030
1031 -version | --version | --versio | --versi | --vers | -V)
1032 ac_init_version=: ;;
1033
1034 -with-* | --with-*)
1035 ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
1036 # Reject names that are not valid shell variable names.
1037 expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
1038 as_fn_error $? "invalid package name: $ac_useropt"
1039 ac_useropt_orig=$ac_useropt
1040 ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
1041 case $ac_user_opts in
1042 *"
1043"with_$ac_useropt"
1044"*) ;;
1045 *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
1046 ac_unrecognized_sep=', ';;
1047 esac
1048 eval with_$ac_useropt=\$ac_optarg ;;
1049
1050 -without-* | --without-*)
1051 ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
1052 # Reject names that are not valid shell variable names.
1053 expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
1054 as_fn_error $? "invalid package name: $ac_useropt"
1055 ac_useropt_orig=$ac_useropt
1056 ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
1057 case $ac_user_opts in
1058 *"
1059"with_$ac_useropt"
1060"*) ;;
1061 *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
1062 ac_unrecognized_sep=', ';;
1063 esac
1064 eval with_$ac_useropt=no ;;
1065
1066 --x)
1067 # Obsolete; use --with-x.
1068 with_x=yes ;;
1069
1070 -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
1071 | --x-incl | --x-inc | --x-in | --x-i)
1072 ac_prev=x_includes ;;
1073 -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
1074 | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
1075 x_includes=$ac_optarg ;;
1076
1077 -x-libraries | --x-libraries | --x-librarie | --x-librari \
1078 | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
1079 ac_prev=x_libraries ;;
1080 -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
1081 | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
1082 x_libraries=$ac_optarg ;;
1083
1084 -*) as_fn_error $? "unrecognized option: \`$ac_option'
1085Try \`$0 --help' for more information"
1086 ;;
1087
1088 *=*)
1089 ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
1090 # Reject names that are not valid shell variable names.
1091 case $ac_envvar in #(
1092 '' | [0-9]* | *[!_$as_cr_alnum]* )
1093 as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
1094 esac
1095 eval $ac_envvar=\$ac_optarg
1096 export $ac_envvar ;;
1097
1098 *)
1099 # FIXME: should be removed in autoconf 3.0.
1100 $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
1101 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
1102 $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
1103 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
1104 ;;
1105
1106 esac
1107done
1108
1109if test -n "$ac_prev"; then
1110 ac_option=--`echo $ac_prev | sed 's/_/-/g'`
1111 as_fn_error $? "missing argument to $ac_option"
1112fi
1113
1114if test -n "$ac_unrecognized_opts"; then
1115 case $enable_option_checking in
1116 no) ;;
1117 fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
1118 *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
1119 esac
1120fi
1121
1122# Check all directory arguments for consistency.
1123for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
1124 datadir sysconfdir sharedstatedir localstatedir includedir \
1125 oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
1126 libdir localedir mandir
1127do
1128 eval ac_val=\$$ac_var
1129 # Remove trailing slashes.
1130 case $ac_val in
1131 */ )
1132 ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
1133 eval $ac_var=\$ac_val;;
1134 esac
1135 # Be sure to have absolute directory names.
1136 case $ac_val in
1137 [\\/$]* | ?:[\\/]* ) continue;;
1138 NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
1139 esac
1140 as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
1141done
1142
1143# There might be people who depend on the old broken behavior: `$host'
1144# used to hold the argument of --host etc.
1145# FIXME: To remove some day.
1146build=$build_alias
1147host=$host_alias
1148target=$target_alias
1149
1150# FIXME: To remove some day.
1151if test "x$host_alias" != x; then
1152 if test "x$build_alias" = x; then
1153 cross_compiling=maybe
1154 elif test "x$build_alias" != "x$host_alias"; then
1155 cross_compiling=yes
1156 fi
1157fi
1158
1159ac_tool_prefix=
1160test -n "$host_alias" && ac_tool_prefix=$host_alias-
1161
1162test "$silent" = yes && exec 6>/dev/null
1163
1164
1165ac_pwd=`pwd` && test -n "$ac_pwd" &&
1166ac_ls_di=`ls -di .` &&
1167ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
1168 as_fn_error $? "working directory cannot be determined"
1169test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
1170 as_fn_error $? "pwd does not report name of working directory"
1171
1172
1173# Find the source files, if location was not specified.
1174if test -z "$srcdir"; then
1175 ac_srcdir_defaulted=yes
1176 # Try the directory containing this script, then the parent directory.
1177 ac_confdir=`$as_dirname -- "$as_myself" ||
1178$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
1179 X"$as_myself" : 'X\(//\)[^/]' \| \
1180 X"$as_myself" : 'X\(//\)$' \| \
1181 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
1182$as_echo X"$as_myself" |
1183 sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
1184 s//\1/
1185 q
1186 }
1187 /^X\(\/\/\)[^/].*/{
1188 s//\1/
1189 q
1190 }
1191 /^X\(\/\/\)$/{
1192 s//\1/
1193 q
1194 }
1195 /^X\(\/\).*/{
1196 s//\1/
1197 q
1198 }
1199 s/.*/./; q'`
1200 srcdir=$ac_confdir
1201 if test ! -r "$srcdir/$ac_unique_file"; then
1202 srcdir=..
1203 fi
1204else
1205 ac_srcdir_defaulted=no
1206fi
1207if test ! -r "$srcdir/$ac_unique_file"; then
1208 test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
1209 as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
1210fi
1211ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
1212ac_abs_confdir=`(
1213 cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
1214 pwd)`
1215# When building in place, set srcdir=.
1216if test "$ac_abs_confdir" = "$ac_pwd"; then
1217 srcdir=.
1218fi
1219# Remove unnecessary trailing slashes from srcdir.
1220# Double slashes in file names in object file debugging info
1221# mess up M-x gdb in Emacs.
1222case $srcdir in
1223*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
1224esac
1225for ac_var in $ac_precious_vars; do
1226 eval ac_env_${ac_var}_set=\${${ac_var}+set}
1227 eval ac_env_${ac_var}_value=\$${ac_var}
1228 eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
1229 eval ac_cv_env_${ac_var}_value=\$${ac_var}
1230done
1231
1232#
1233# Report the --help message.
1234#
1235if test "$ac_init_help" = "long"; then
1236 # Omit some internal or obsolete options to make the list less imposing.
1237 # This message is too long to be a string in the A/UX 3.1 sh.
1238 cat <<_ACEOF
1239\`configure' configures firejail 0.9.28 to adapt to many kinds of systems.
1240
1241Usage: $0 [OPTION]... [VAR=VALUE]...
1242
1243To assign environment variables (e.g., CC, CFLAGS...), specify them as
1244VAR=VALUE. See below for descriptions of some of the useful variables.
1245
1246Defaults for the options are specified in brackets.
1247
1248Configuration:
1249 -h, --help display this help and exit
1250 --help=short display options specific to this package
1251 --help=recursive display the short help of all the included packages
1252 -V, --version display version information and exit
1253 -q, --quiet, --silent do not print \`checking ...' messages
1254 --cache-file=FILE cache test results in FILE [disabled]
1255 -C, --config-cache alias for \`--cache-file=config.cache'
1256 -n, --no-create do not create output files
1257 --srcdir=DIR find the sources in DIR [configure dir or \`..']
1258
1259Installation directories:
1260 --prefix=PREFIX install architecture-independent files in PREFIX
1261 [$ac_default_prefix]
1262 --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
1263 [PREFIX]
1264
1265By default, \`make install' will install all the files in
1266\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
1267an installation prefix other than \`$ac_default_prefix' using \`--prefix',
1268for instance \`--prefix=\$HOME'.
1269
1270For better control, use the options below.
1271
1272Fine tuning of the installation directories:
1273 --bindir=DIR user executables [EPREFIX/bin]
1274 --sbindir=DIR system admin executables [EPREFIX/sbin]
1275 --libexecdir=DIR program executables [EPREFIX/libexec]
1276 --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
1277 --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
1278 --localstatedir=DIR modifiable single-machine data [PREFIX/var]
1279 --libdir=DIR object code libraries [EPREFIX/lib]
1280 --includedir=DIR C header files [PREFIX/include]
1281 --oldincludedir=DIR C header files for non-gcc [/usr/include]
1282 --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
1283 --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
1284 --infodir=DIR info documentation [DATAROOTDIR/info]
1285 --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
1286 --mandir=DIR man documentation [DATAROOTDIR/man]
1287 --docdir=DIR documentation root [DATAROOTDIR/doc/firejail]
1288 --htmldir=DIR html documentation [DOCDIR]
1289 --dvidir=DIR dvi documentation [DOCDIR]
1290 --pdfdir=DIR pdf documentation [DOCDIR]
1291 --psdir=DIR ps documentation [DOCDIR]
1292_ACEOF
1293
1294 cat <<\_ACEOF
1295_ACEOF
1296fi
1297
1298if test -n "$ac_init_help"; then
1299 case $ac_init_help in
1300 short | recursive ) echo "Configuration of firejail 0.9.28:";;
1301 esac
1302 cat <<\_ACEOF
1303
1304Optional Features:
1305 --disable-option-checking ignore unrecognized --enable/--with options
1306 --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
1307 --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
1308 --disable-seccomp Disable seccomp
1309 --disable-chroot Disable chroot
1310 --disable-bind Disable bind
1311
1312Some influential environment variables:
1313 CC C compiler command
1314 CFLAGS C compiler flags
1315 LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
1316 nonstandard directory <lib dir>
1317 LIBS libraries to pass to the linker, e.g. -l<library>
1318 CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
1319 you have headers in a nonstandard directory <include dir>
1320 CPP C preprocessor
1321
1322Use these variables to override the choices made by `configure' or to help
1323it to find libraries and programs with nonstandard names/locations.
1324
1325Report bugs to <netblue30@yahoo.com>.
1326firejail home page: <http://firejail.sourceforge.net>.
1327_ACEOF
1328ac_status=$?
1329fi
1330
1331if test "$ac_init_help" = "recursive"; then
1332 # If there are subdirs, report their specific --help.
1333 for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
1334 test -d "$ac_dir" ||
1335 { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
1336 continue
1337 ac_builddir=.
1338
1339case "$ac_dir" in
1340.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
1341*)
1342 ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
1343 # A ".." for each directory in $ac_dir_suffix.
1344 ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
1345 case $ac_top_builddir_sub in
1346 "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
1347 *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
1348 esac ;;
1349esac
1350ac_abs_top_builddir=$ac_pwd
1351ac_abs_builddir=$ac_pwd$ac_dir_suffix
1352# for backward compatibility:
1353ac_top_builddir=$ac_top_build_prefix
1354
1355case $srcdir in
1356 .) # We are building in place.
1357 ac_srcdir=.
1358 ac_top_srcdir=$ac_top_builddir_sub
1359 ac_abs_top_srcdir=$ac_pwd ;;
1360 [\\/]* | ?:[\\/]* ) # Absolute name.
1361 ac_srcdir=$srcdir$ac_dir_suffix;
1362 ac_top_srcdir=$srcdir
1363 ac_abs_top_srcdir=$srcdir ;;
1364 *) # Relative name.
1365 ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
1366 ac_top_srcdir=$ac_top_build_prefix$srcdir
1367 ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
1368esac
1369ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
1370
1371 cd "$ac_dir" || { ac_status=$?; continue; }
1372 # Check for guested configure.
1373 if test -f "$ac_srcdir/configure.gnu"; then
1374 echo &&
1375 $SHELL "$ac_srcdir/configure.gnu" --help=recursive
1376 elif test -f "$ac_srcdir/configure"; then
1377 echo &&
1378 $SHELL "$ac_srcdir/configure" --help=recursive
1379 else
1380 $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
1381 fi || ac_status=$?
1382 cd "$ac_pwd" || { ac_status=$?; break; }
1383 done
1384fi
1385
1386test -n "$ac_init_help" && exit $ac_status
1387if $ac_init_version; then
1388 cat <<\_ACEOF
1389firejail configure 0.9.28
1390generated by GNU Autoconf 2.69
1391
1392Copyright (C) 2012 Free Software Foundation, Inc.
1393This configure script is free software; the Free Software Foundation
1394gives unlimited permission to copy, distribute and modify it.
1395_ACEOF
1396 exit
1397fi
1398
1399## ------------------------ ##
1400## Autoconf initialization. ##
1401## ------------------------ ##
1402
1403# ac_fn_c_try_compile LINENO
1404# --------------------------
1405# Try to compile conftest.$ac_ext, and return whether this succeeded.
1406ac_fn_c_try_compile ()
1407{
1408 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1409 rm -f conftest.$ac_objext
1410 if { { ac_try="$ac_compile"
1411case "(($ac_try" in
1412 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1413 *) ac_try_echo=$ac_try;;
1414esac
1415eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1416$as_echo "$ac_try_echo"; } >&5
1417 (eval "$ac_compile") 2>conftest.err
1418 ac_status=$?
1419 if test -s conftest.err; then
1420 grep -v '^ *+' conftest.err >conftest.er1
1421 cat conftest.er1 >&5
1422 mv -f conftest.er1 conftest.err
1423 fi
1424 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1425 test $ac_status = 0; } && {
1426 test -z "$ac_c_werror_flag" ||
1427 test ! -s conftest.err
1428 } && test -s conftest.$ac_objext; then :
1429 ac_retval=0
1430else
1431 $as_echo "$as_me: failed program was:" >&5
1432sed 's/^/| /' conftest.$ac_ext >&5
1433
1434 ac_retval=1
1435fi
1436 eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1437 as_fn_set_status $ac_retval
1438
1439} # ac_fn_c_try_compile
1440
1441# ac_fn_c_try_link LINENO
1442# -----------------------
1443# Try to link conftest.$ac_ext, and return whether this succeeded.
1444ac_fn_c_try_link ()
1445{
1446 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1447 rm -f conftest.$ac_objext conftest$ac_exeext
1448 if { { ac_try="$ac_link"
1449case "(($ac_try" in
1450 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1451 *) ac_try_echo=$ac_try;;
1452esac
1453eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1454$as_echo "$ac_try_echo"; } >&5
1455 (eval "$ac_link") 2>conftest.err
1456 ac_status=$?
1457 if test -s conftest.err; then
1458 grep -v '^ *+' conftest.err >conftest.er1
1459 cat conftest.er1 >&5
1460 mv -f conftest.er1 conftest.err
1461 fi
1462 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1463 test $ac_status = 0; } && {
1464 test -z "$ac_c_werror_flag" ||
1465 test ! -s conftest.err
1466 } && test -s conftest$ac_exeext && {
1467 test "$cross_compiling" = yes ||
1468 test -x conftest$ac_exeext
1469 }; then :
1470 ac_retval=0
1471else
1472 $as_echo "$as_me: failed program was:" >&5
1473sed 's/^/| /' conftest.$ac_ext >&5
1474
1475 ac_retval=1
1476fi
1477 # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
1478 # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
1479 # interfere with the next link command; also delete a directory that is
1480 # left behind by Apple's compiler. We do this before executing the actions.
1481 rm -rf conftest.dSYM conftest_ipa8_conftest.oo
1482 eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1483 as_fn_set_status $ac_retval
1484
1485} # ac_fn_c_try_link
1486
1487# ac_fn_c_try_cpp LINENO
1488# ----------------------
1489# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
1490ac_fn_c_try_cpp ()
1491{
1492 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1493 if { { ac_try="$ac_cpp conftest.$ac_ext"
1494case "(($ac_try" in
1495 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1496 *) ac_try_echo=$ac_try;;
1497esac
1498eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1499$as_echo "$ac_try_echo"; } >&5
1500 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
1501 ac_status=$?
1502 if test -s conftest.err; then
1503 grep -v '^ *+' conftest.err >conftest.er1
1504 cat conftest.er1 >&5
1505 mv -f conftest.er1 conftest.err
1506 fi
1507 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1508 test $ac_status = 0; } > conftest.i && {
1509 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
1510 test ! -s conftest.err
1511 }; then :
1512 ac_retval=0
1513else
1514 $as_echo "$as_me: failed program was:" >&5
1515sed 's/^/| /' conftest.$ac_ext >&5
1516
1517 ac_retval=1
1518fi
1519 eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1520 as_fn_set_status $ac_retval
1521
1522} # ac_fn_c_try_cpp
1523
1524# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
1525# -------------------------------------------------------
1526# Tests whether HEADER exists, giving a warning if it cannot be compiled using
1527# the include files in INCLUDES and setting the cache variable VAR
1528# accordingly.
1529ac_fn_c_check_header_mongrel ()
1530{
1531 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1532 if eval \${$3+:} false; then :
1533 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
1534$as_echo_n "checking for $2... " >&6; }
1535if eval \${$3+:} false; then :
1536 $as_echo_n "(cached) " >&6
1537fi
1538eval ac_res=\$$3
1539 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
1540$as_echo "$ac_res" >&6; }
1541else
1542 # Is the header compilable?
1543{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
1544$as_echo_n "checking $2 usability... " >&6; }
1545cat confdefs.h - <<_ACEOF >conftest.$ac_ext
1546/* end confdefs.h. */
1547$4
1548#include <$2>
1549_ACEOF
1550if ac_fn_c_try_compile "$LINENO"; then :
1551 ac_header_compiler=yes
1552else
1553 ac_header_compiler=no
1554fi
1555rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
1556{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
1557$as_echo "$ac_header_compiler" >&6; }
1558
1559# Is the header present?
1560{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
1561$as_echo_n "checking $2 presence... " >&6; }
1562cat confdefs.h - <<_ACEOF >conftest.$ac_ext
1563/* end confdefs.h. */
1564#include <$2>
1565_ACEOF
1566if ac_fn_c_try_cpp "$LINENO"; then :
1567 ac_header_preproc=yes
1568else
1569 ac_header_preproc=no
1570fi
1571rm -f conftest.err conftest.i conftest.$ac_ext
1572{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
1573$as_echo "$ac_header_preproc" >&6; }
1574
1575# So? What about this header?
1576case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
1577 yes:no: )
1578 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
1579$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
1580 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
1581$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
1582 ;;
1583 no:yes:* )
1584 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
1585$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
1586 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
1587$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
1588 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
1589$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
1590 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
1591$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
1592 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
1593$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
1594( $as_echo "## ---------------------------------- ##
1595## Report this to netblue30@yahoo.com ##
1596## ---------------------------------- ##"
1597 ) | sed "s/^/$as_me: WARNING: /" >&2
1598 ;;
1599esac
1600 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
1601$as_echo_n "checking for $2... " >&6; }
1602if eval \${$3+:} false; then :
1603 $as_echo_n "(cached) " >&6
1604else
1605 eval "$3=\$ac_header_compiler"
1606fi
1607eval ac_res=\$$3
1608 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
1609$as_echo "$ac_res" >&6; }
1610fi
1611 eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1612
1613} # ac_fn_c_check_header_mongrel
1614
1615# ac_fn_c_try_run LINENO
1616# ----------------------
1617# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
1618# that executables *can* be run.
1619ac_fn_c_try_run ()
1620{
1621 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1622 if { { ac_try="$ac_link"
1623case "(($ac_try" in
1624 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1625 *) ac_try_echo=$ac_try;;
1626esac
1627eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1628$as_echo "$ac_try_echo"; } >&5
1629 (eval "$ac_link") 2>&5
1630 ac_status=$?
1631 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1632 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
1633 { { case "(($ac_try" in
1634 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1635 *) ac_try_echo=$ac_try;;
1636esac
1637eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1638$as_echo "$ac_try_echo"; } >&5
1639 (eval "$ac_try") 2>&5
1640 ac_status=$?
1641 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1642 test $ac_status = 0; }; }; then :
1643 ac_retval=0
1644else
1645 $as_echo "$as_me: program exited with status $ac_status" >&5
1646 $as_echo "$as_me: failed program was:" >&5
1647sed 's/^/| /' conftest.$ac_ext >&5
1648
1649 ac_retval=$ac_status
1650fi
1651 rm -rf conftest.dSYM conftest_ipa8_conftest.oo
1652 eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1653 as_fn_set_status $ac_retval
1654
1655} # ac_fn_c_try_run
1656
1657# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
1658# -------------------------------------------------------
1659# Tests whether HEADER exists and can be compiled using the include files in
1660# INCLUDES, setting the cache variable VAR accordingly.
1661ac_fn_c_check_header_compile ()
1662{
1663 as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1664 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
1665$as_echo_n "checking for $2... " >&6; }
1666if eval \${$3+:} false; then :
1667 $as_echo_n "(cached) " >&6
1668else
1669 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
1670/* end confdefs.h. */
1671$4
1672#include <$2>
1673_ACEOF
1674if ac_fn_c_try_compile "$LINENO"; then :
1675 eval "$3=yes"
1676else
1677 eval "$3=no"
1678fi
1679rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
1680fi
1681eval ac_res=\$$3
1682 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
1683$as_echo "$ac_res" >&6; }
1684 eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1685
1686} # ac_fn_c_check_header_compile
1687cat >config.log <<_ACEOF
1688This file contains any messages produced by compilers while
1689running configure, to aid debugging if configure makes a mistake.
1690
1691It was created by firejail $as_me 0.9.28, which was
1692generated by GNU Autoconf 2.69. Invocation command line was
1693
1694 $ $0 $@
1695
1696_ACEOF
1697exec 5>>config.log
1698{
1699cat <<_ASUNAME
1700## --------- ##
1701## Platform. ##
1702## --------- ##
1703
1704hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
1705uname -m = `(uname -m) 2>/dev/null || echo unknown`
1706uname -r = `(uname -r) 2>/dev/null || echo unknown`
1707uname -s = `(uname -s) 2>/dev/null || echo unknown`
1708uname -v = `(uname -v) 2>/dev/null || echo unknown`
1709
1710/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
1711/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
1712
1713/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
1714/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
1715/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
1716/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
1717/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
1718/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
1719/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
1720
1721_ASUNAME
1722
1723as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
1724for as_dir in $PATH
1725do
1726 IFS=$as_save_IFS
1727 test -z "$as_dir" && as_dir=.
1728 $as_echo "PATH: $as_dir"
1729 done
1730IFS=$as_save_IFS
1731
1732} >&5
1733
1734cat >&5 <<_ACEOF
1735
1736
1737## ----------- ##
1738## Core tests. ##
1739## ----------- ##
1740
1741_ACEOF
1742
1743
1744# Keep a trace of the command line.
1745# Strip out --no-create and --no-recursion so they do not pile up.
1746# Strip out --silent because we don't want to record it for future runs.
1747# Also quote any args containing shell meta-characters.
1748# Make two passes to allow for proper duplicate-argument suppression.
1749ac_configure_args=
1750ac_configure_args0=
1751ac_configure_args1=
1752ac_must_keep_next=false
1753for ac_pass in 1 2
1754do
1755 for ac_arg
1756 do
1757 case $ac_arg in
1758 -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
1759 -q | -quiet | --quiet | --quie | --qui | --qu | --q \
1760 | -silent | --silent | --silen | --sile | --sil)
1761 continue ;;
1762 *\'*)
1763 ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
1764 esac
1765 case $ac_pass in
1766 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
1767 2)
1768 as_fn_append ac_configure_args1 " '$ac_arg'"
1769 if test $ac_must_keep_next = true; then
1770 ac_must_keep_next=false # Got value, back to normal.
1771 else
1772 case $ac_arg in
1773 *=* | --config-cache | -C | -disable-* | --disable-* \
1774 | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
1775 | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
1776 | -with-* | --with-* | -without-* | --without-* | --x)
1777 case "$ac_configure_args0 " in
1778 "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
1779 esac
1780 ;;
1781 -* ) ac_must_keep_next=true ;;
1782 esac
1783 fi
1784 as_fn_append ac_configure_args " '$ac_arg'"
1785 ;;
1786 esac
1787 done
1788done
1789{ ac_configure_args0=; unset ac_configure_args0;}
1790{ ac_configure_args1=; unset ac_configure_args1;}
1791
1792# When interrupted or exit'd, cleanup temporary files, and complete
1793# config.log. We remove comments because anyway the quotes in there
1794# would cause problems or look ugly.
1795# WARNING: Use '\'' to represent an apostrophe within the trap.
1796# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
1797trap 'exit_status=$?
1798 # Save into config.log some information that might help in debugging.
1799 {
1800 echo
1801
1802 $as_echo "## ---------------- ##
1803## Cache variables. ##
1804## ---------------- ##"
1805 echo
1806 # The following way of writing the cache mishandles newlines in values,
1807(
1808 for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
1809 eval ac_val=\$$ac_var
1810 case $ac_val in #(
1811 *${as_nl}*)
1812 case $ac_var in #(
1813 *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
1814$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
1815 esac
1816 case $ac_var in #(
1817 _ | IFS | as_nl) ;; #(
1818 BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
1819 *) { eval $ac_var=; unset $ac_var;} ;;
1820 esac ;;
1821 esac
1822 done
1823 (set) 2>&1 |
1824 case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
1825 *${as_nl}ac_space=\ *)
1826 sed -n \
1827 "s/'\''/'\''\\\\'\'''\''/g;
1828 s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
1829 ;; #(
1830 *)
1831 sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
1832 ;;
1833 esac |
1834 sort
1835)
1836 echo
1837
1838 $as_echo "## ----------------- ##
1839## Output variables. ##
1840## ----------------- ##"
1841 echo
1842 for ac_var in $ac_subst_vars
1843 do
1844 eval ac_val=\$$ac_var
1845 case $ac_val in
1846 *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
1847 esac
1848 $as_echo "$ac_var='\''$ac_val'\''"
1849 done | sort
1850 echo
1851
1852 if test -n "$ac_subst_files"; then
1853 $as_echo "## ------------------- ##
1854## File substitutions. ##
1855## ------------------- ##"
1856 echo
1857 for ac_var in $ac_subst_files
1858 do
1859 eval ac_val=\$$ac_var
1860 case $ac_val in
1861 *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
1862 esac
1863 $as_echo "$ac_var='\''$ac_val'\''"
1864 done | sort
1865 echo
1866 fi
1867
1868 if test -s confdefs.h; then
1869 $as_echo "## ----------- ##
1870## confdefs.h. ##
1871## ----------- ##"
1872 echo
1873 cat confdefs.h
1874 echo
1875 fi
1876 test "$ac_signal" != 0 &&
1877 $as_echo "$as_me: caught signal $ac_signal"
1878 $as_echo "$as_me: exit $exit_status"
1879 } >&5
1880 rm -f core *.core core.conftest.* &&
1881 rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
1882 exit $exit_status
1883' 0
1884for ac_signal in 1 2 13 15; do
1885 trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
1886done
1887ac_signal=0
1888
1889# confdefs.h avoids OS command line length limits that DEFS can exceed.
1890rm -f -r conftest* confdefs.h
1891
1892$as_echo "/* confdefs.h */" > confdefs.h
1893
1894# Predefined preprocessor variables.
1895
1896cat >>confdefs.h <<_ACEOF
1897#define PACKAGE_NAME "$PACKAGE_NAME"
1898_ACEOF
1899
1900cat >>confdefs.h <<_ACEOF
1901#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
1902_ACEOF
1903
1904cat >>confdefs.h <<_ACEOF
1905#define PACKAGE_VERSION "$PACKAGE_VERSION"
1906_ACEOF
1907
1908cat >>confdefs.h <<_ACEOF
1909#define PACKAGE_STRING "$PACKAGE_STRING"
1910_ACEOF
1911
1912cat >>confdefs.h <<_ACEOF
1913#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
1914_ACEOF
1915
1916cat >>confdefs.h <<_ACEOF
1917#define PACKAGE_URL "$PACKAGE_URL"
1918_ACEOF
1919
1920
1921# Let the site file select an alternate cache file if it wants to.
1922# Prefer an explicitly selected file to automatically selected ones.
1923ac_site_file1=NONE
1924ac_site_file2=NONE
1925if test -n "$CONFIG_SITE"; then
1926 # We do not want a PATH search for config.site.
1927 case $CONFIG_SITE in #((
1928 -*) ac_site_file1=./$CONFIG_SITE;;
1929 */*) ac_site_file1=$CONFIG_SITE;;
1930 *) ac_site_file1=./$CONFIG_SITE;;
1931 esac
1932elif test "x$prefix" != xNONE; then
1933 ac_site_file1=$prefix/share/config.site
1934 ac_site_file2=$prefix/etc/config.site
1935else
1936 ac_site_file1=$ac_default_prefix/share/config.site
1937 ac_site_file2=$ac_default_prefix/etc/config.site
1938fi
1939for ac_site_file in "$ac_site_file1" "$ac_site_file2"
1940do
1941 test "x$ac_site_file" = xNONE && continue
1942 if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
1943 { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
1944$as_echo "$as_me: loading site script $ac_site_file" >&6;}
1945 sed 's/^/| /' "$ac_site_file" >&5
1946 . "$ac_site_file" \
1947 || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
1948$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
1949as_fn_error $? "failed to load site script $ac_site_file
1950See \`config.log' for more details" "$LINENO" 5; }
1951 fi
1952done
1953
1954if test -r "$cache_file"; then
1955 # Some versions of bash will fail to source /dev/null (special files
1956 # actually), so we avoid doing that. DJGPP emulates it as a regular file.
1957 if test /dev/null != "$cache_file" && test -f "$cache_file"; then
1958 { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
1959$as_echo "$as_me: loading cache $cache_file" >&6;}
1960 case $cache_file in
1961 [\\/]* | ?:[\\/]* ) . "$cache_file";;
1962 *) . "./$cache_file";;
1963 esac
1964 fi
1965else
1966 { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
1967$as_echo "$as_me: creating cache $cache_file" >&6;}
1968 >$cache_file
1969fi
1970
1971# Check that the precious variables saved in the cache have kept the same
1972# value.
1973ac_cache_corrupted=false
1974for ac_var in $ac_precious_vars; do
1975 eval ac_old_set=\$ac_cv_env_${ac_var}_set
1976 eval ac_new_set=\$ac_env_${ac_var}_set
1977 eval ac_old_val=\$ac_cv_env_${ac_var}_value
1978 eval ac_new_val=\$ac_env_${ac_var}_value
1979 case $ac_old_set,$ac_new_set in
1980 set,)
1981 { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
1982$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
1983 ac_cache_corrupted=: ;;
1984 ,set)
1985 { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
1986$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
1987 ac_cache_corrupted=: ;;
1988 ,);;
1989 *)
1990 if test "x$ac_old_val" != "x$ac_new_val"; then
1991 # differences in whitespace do not lead to failure.
1992 ac_old_val_w=`echo x $ac_old_val`
1993 ac_new_val_w=`echo x $ac_new_val`
1994 if test "$ac_old_val_w" != "$ac_new_val_w"; then
1995 { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
1996$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
1997 ac_cache_corrupted=:
1998 else
1999 { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
2000$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
2001 eval $ac_var=\$ac_old_val
2002 fi
2003 { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
2004$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
2005 { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
2006$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
2007 fi;;
2008 esac
2009 # Pass precious variables to config.status.
2010 if test "$ac_new_set" = set; then
2011 case $ac_new_val in
2012 *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
2013 *) ac_arg=$ac_var=$ac_new_val ;;
2014 esac
2015 case " $ac_configure_args " in
2016 *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
2017 *) as_fn_append ac_configure_args " '$ac_arg'" ;;
2018 esac
2019 fi
2020done
2021if $ac_cache_corrupted; then
2022 { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
2023$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
2024 { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
2025$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
2026 as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
2027fi
2028## -------------------- ##
2029## Main body of script. ##
2030## -------------------- ##
2031
2032ac_ext=c
2033ac_cpp='$CPP $CPPFLAGS'
2034ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
2035ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
2036ac_compiler_gnu=$ac_cv_c_compiler_gnu
2037
2038
2039
2040#AC_CONFIG_HEADERS([config.h])
2041
2042
2043ac_ext=c
2044ac_cpp='$CPP $CPPFLAGS'
2045ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
2046ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
2047ac_compiler_gnu=$ac_cv_c_compiler_gnu
2048if test -n "$ac_tool_prefix"; then
2049 # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
2050set dummy ${ac_tool_prefix}gcc; ac_word=$2
2051{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
2052$as_echo_n "checking for $ac_word... " >&6; }
2053if ${ac_cv_prog_CC+:} false; then :
2054 $as_echo_n "(cached) " >&6
2055else
2056 if test -n "$CC"; then
2057 ac_cv_prog_CC="$CC" # Let the user override the test.
2058else
2059as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2060for as_dir in $PATH
2061do
2062 IFS=$as_save_IFS
2063 test -z "$as_dir" && as_dir=.
2064 for ac_exec_ext in '' $ac_executable_extensions; do
2065 if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
2066 ac_cv_prog_CC="${ac_tool_prefix}gcc"
2067 $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
2068 break 2
2069 fi
2070done
2071 done
2072IFS=$as_save_IFS
2073
2074fi
2075fi
2076CC=$ac_cv_prog_CC
2077if test -n "$CC"; then
2078 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
2079$as_echo "$CC" >&6; }
2080else
2081 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
2082$as_echo "no" >&6; }
2083fi
2084
2085
2086fi
2087if test -z "$ac_cv_prog_CC"; then
2088 ac_ct_CC=$CC
2089 # Extract the first word of "gcc", so it can be a program name with args.
2090set dummy gcc; ac_word=$2
2091{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
2092$as_echo_n "checking for $ac_word... " >&6; }
2093if ${ac_cv_prog_ac_ct_CC+:} false; then :
2094 $as_echo_n "(cached) " >&6
2095else
2096 if test -n "$ac_ct_CC"; then
2097 ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
2098else
2099as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2100for as_dir in $PATH
2101do
2102 IFS=$as_save_IFS
2103 test -z "$as_dir" && as_dir=.
2104 for ac_exec_ext in '' $ac_executable_extensions; do
2105 if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
2106 ac_cv_prog_ac_ct_CC="gcc"
2107 $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
2108 break 2
2109 fi
2110done
2111 done
2112IFS=$as_save_IFS
2113
2114fi
2115fi
2116ac_ct_CC=$ac_cv_prog_ac_ct_CC
2117if test -n "$ac_ct_CC"; then
2118 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
2119$as_echo "$ac_ct_CC" >&6; }
2120else
2121 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
2122$as_echo "no" >&6; }
2123fi
2124
2125 if test "x$ac_ct_CC" = x; then
2126 CC=""
2127 else
2128 case $cross_compiling:$ac_tool_warned in
2129yes:)
2130{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
2131$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
2132ac_tool_warned=yes ;;
2133esac
2134 CC=$ac_ct_CC
2135 fi
2136else
2137 CC="$ac_cv_prog_CC"
2138fi
2139
2140if test -z "$CC"; then
2141 if test -n "$ac_tool_prefix"; then
2142 # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
2143set dummy ${ac_tool_prefix}cc; ac_word=$2
2144{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
2145$as_echo_n "checking for $ac_word... " >&6; }
2146if ${ac_cv_prog_CC+:} false; then :
2147 $as_echo_n "(cached) " >&6
2148else
2149 if test -n "$CC"; then
2150 ac_cv_prog_CC="$CC" # Let the user override the test.
2151else
2152as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2153for as_dir in $PATH
2154do
2155 IFS=$as_save_IFS
2156 test -z "$as_dir" && as_dir=.
2157 for ac_exec_ext in '' $ac_executable_extensions; do
2158 if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
2159 ac_cv_prog_CC="${ac_tool_prefix}cc"
2160 $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
2161 break 2
2162 fi
2163done
2164 done
2165IFS=$as_save_IFS
2166
2167fi
2168fi
2169CC=$ac_cv_prog_CC
2170if test -n "$CC"; then
2171 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
2172$as_echo "$CC" >&6; }
2173else
2174 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
2175$as_echo "no" >&6; }
2176fi
2177
2178
2179 fi
2180fi
2181if test -z "$CC"; then
2182 # Extract the first word of "cc", so it can be a program name with args.
2183set dummy cc; ac_word=$2
2184{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
2185$as_echo_n "checking for $ac_word... " >&6; }
2186if ${ac_cv_prog_CC+:} false; then :
2187 $as_echo_n "(cached) " >&6
2188else
2189 if test -n "$CC"; then
2190 ac_cv_prog_CC="$CC" # Let the user override the test.
2191else
2192 ac_prog_rejected=no
2193as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2194for as_dir in $PATH
2195do
2196 IFS=$as_save_IFS
2197 test -z "$as_dir" && as_dir=.
2198 for ac_exec_ext in '' $ac_executable_extensions; do
2199 if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
2200 if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
2201 ac_prog_rejected=yes
2202 continue
2203 fi
2204 ac_cv_prog_CC="cc"
2205 $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
2206 break 2
2207 fi
2208done
2209 done
2210IFS=$as_save_IFS
2211
2212if test $ac_prog_rejected = yes; then
2213 # We found a bogon in the path, so make sure we never use it.
2214 set dummy $ac_cv_prog_CC
2215 shift
2216 if test $# != 0; then
2217 # We chose a different compiler from the bogus one.
2218 # However, it has the same basename, so the bogon will be chosen
2219 # first if we set CC to just the basename; use the full file name.
2220 shift
2221 ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
2222 fi
2223fi
2224fi
2225fi
2226CC=$ac_cv_prog_CC
2227if test -n "$CC"; then
2228 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
2229$as_echo "$CC" >&6; }
2230else
2231 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
2232$as_echo "no" >&6; }
2233fi
2234
2235
2236fi
2237if test -z "$CC"; then
2238 if test -n "$ac_tool_prefix"; then
2239 for ac_prog in cl.exe
2240 do
2241 # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
2242set dummy $ac_tool_prefix$ac_prog; ac_word=$2
2243{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
2244$as_echo_n "checking for $ac_word... " >&6; }
2245if ${ac_cv_prog_CC+:} false; then :
2246 $as_echo_n "(cached) " >&6
2247else
2248 if test -n "$CC"; then
2249 ac_cv_prog_CC="$CC" # Let the user override the test.
2250else
2251as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2252for as_dir in $PATH
2253do
2254 IFS=$as_save_IFS
2255 test -z "$as_dir" && as_dir=.
2256 for ac_exec_ext in '' $ac_executable_extensions; do
2257 if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
2258 ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
2259 $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
2260 break 2
2261 fi
2262done
2263 done
2264IFS=$as_save_IFS
2265
2266fi
2267fi
2268CC=$ac_cv_prog_CC
2269if test -n "$CC"; then
2270 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
2271$as_echo "$CC" >&6; }
2272else
2273 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
2274$as_echo "no" >&6; }
2275fi
2276
2277
2278 test -n "$CC" && break
2279 done
2280fi
2281if test -z "$CC"; then
2282 ac_ct_CC=$CC
2283 for ac_prog in cl.exe
2284do
2285 # Extract the first word of "$ac_prog", so it can be a program name with args.
2286set dummy $ac_prog; ac_word=$2
2287{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
2288$as_echo_n "checking for $ac_word... " >&6; }
2289if ${ac_cv_prog_ac_ct_CC+:} false; then :
2290 $as_echo_n "(cached) " >&6
2291else
2292 if test -n "$ac_ct_CC"; then
2293 ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
2294else
2295as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2296for as_dir in $PATH
2297do
2298 IFS=$as_save_IFS
2299 test -z "$as_dir" && as_dir=.
2300 for ac_exec_ext in '' $ac_executable_extensions; do
2301 if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
2302 ac_cv_prog_ac_ct_CC="$ac_prog"
2303 $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
2304 break 2
2305 fi
2306done
2307 done
2308IFS=$as_save_IFS
2309
2310fi
2311fi
2312ac_ct_CC=$ac_cv_prog_ac_ct_CC
2313if test -n "$ac_ct_CC"; then
2314 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
2315$as_echo "$ac_ct_CC" >&6; }
2316else
2317 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
2318$as_echo "no" >&6; }
2319fi
2320
2321
2322 test -n "$ac_ct_CC" && break
2323done
2324
2325 if test "x$ac_ct_CC" = x; then
2326 CC=""
2327 else
2328 case $cross_compiling:$ac_tool_warned in
2329yes:)
2330{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
2331$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
2332ac_tool_warned=yes ;;
2333esac
2334 CC=$ac_ct_CC
2335 fi
2336fi
2337
2338fi
2339
2340
2341test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
2342$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
2343as_fn_error $? "no acceptable C compiler found in \$PATH
2344See \`config.log' for more details" "$LINENO" 5; }
2345
2346# Provide some information about the compiler.
2347$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
2348set X $ac_compile
2349ac_compiler=$2
2350for ac_option in --version -v -V -qversion; do
2351 { { ac_try="$ac_compiler $ac_option >&5"
2352case "(($ac_try" in
2353 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
2354 *) ac_try_echo=$ac_try;;
2355esac
2356eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
2357$as_echo "$ac_try_echo"; } >&5
2358 (eval "$ac_compiler $ac_option >&5") 2>conftest.err
2359 ac_status=$?
2360 if test -s conftest.err; then
2361 sed '10a\
2362... rest of stderr output deleted ...
2363 10q' conftest.err >conftest.er1
2364 cat conftest.er1 >&5
2365 fi
2366 rm -f conftest.er1 conftest.err
2367 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
2368 test $ac_status = 0; }
2369done
2370
2371cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2372/* end confdefs.h. */
2373
2374int
2375main ()
2376{
2377
2378 ;
2379 return 0;
2380}
2381_ACEOF
2382ac_clean_files_save=$ac_clean_files
2383ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
2384# Try to create an executable without -o first, disregard a.out.
2385# It will help us diagnose broken compilers, and finding out an intuition
2386# of exeext.
2387{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
2388$as_echo_n "checking whether the C compiler works... " >&6; }
2389ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
2390
2391# The possible output files:
2392ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
2393
2394ac_rmfiles=
2395for ac_file in $ac_files
2396do
2397 case $ac_file in
2398 *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
2399 * ) ac_rmfiles="$ac_rmfiles $ac_file";;
2400 esac
2401done
2402rm -f $ac_rmfiles
2403
2404if { { ac_try="$ac_link_default"
2405case "(($ac_try" in
2406 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
2407 *) ac_try_echo=$ac_try;;
2408esac
2409eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
2410$as_echo "$ac_try_echo"; } >&5
2411 (eval "$ac_link_default") 2>&5
2412 ac_status=$?
2413 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
2414 test $ac_status = 0; }; then :
2415 # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
2416# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
2417# in a Makefile. We should not override ac_cv_exeext if it was cached,
2418# so that the user can short-circuit this test for compilers unknown to
2419# Autoconf.
2420for ac_file in $ac_files ''
2421do
2422 test -f "$ac_file" || continue
2423 case $ac_file in
2424 *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
2425 ;;
2426 [ab].out )
2427 # We found the default executable, but exeext='' is most
2428 # certainly right.
2429 break;;
2430 *.* )
2431 if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
2432 then :; else
2433 ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
2434 fi
2435 # We set ac_cv_exeext here because the later test for it is not
2436 # safe: cross compilers may not add the suffix if given an `-o'
2437 # argument, so we may need to know it at that point already.
2438 # Even if this section looks crufty: it has the advantage of
2439 # actually working.
2440 break;;
2441 * )
2442 break;;
2443 esac
2444done
2445test "$ac_cv_exeext" = no && ac_cv_exeext=
2446
2447else
2448 ac_file=''
2449fi
2450if test -z "$ac_file"; then :
2451 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
2452$as_echo "no" >&6; }
2453$as_echo "$as_me: failed program was:" >&5
2454sed 's/^/| /' conftest.$ac_ext >&5
2455
2456{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
2457$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
2458as_fn_error 77 "C compiler cannot create executables
2459See \`config.log' for more details" "$LINENO" 5; }
2460else
2461 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
2462$as_echo "yes" >&6; }
2463fi
2464{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
2465$as_echo_n "checking for C compiler default output file name... " >&6; }
2466{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
2467$as_echo "$ac_file" >&6; }
2468ac_exeext=$ac_cv_exeext
2469
2470rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
2471ac_clean_files=$ac_clean_files_save
2472{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
2473$as_echo_n "checking for suffix of executables... " >&6; }
2474if { { ac_try="$ac_link"
2475case "(($ac_try" in
2476 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
2477 *) ac_try_echo=$ac_try;;
2478esac
2479eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
2480$as_echo "$ac_try_echo"; } >&5
2481 (eval "$ac_link") 2>&5
2482 ac_status=$?
2483 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
2484 test $ac_status = 0; }; then :
2485 # If both `conftest.exe' and `conftest' are `present' (well, observable)
2486# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
2487# work properly (i.e., refer to `conftest.exe'), while it won't with
2488# `rm'.
2489for ac_file in conftest.exe conftest conftest.*; do
2490 test -f "$ac_file" || continue
2491 case $ac_file in
2492 *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
2493 *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
2494 break;;
2495 * ) break;;
2496 esac
2497done
2498else
2499 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
2500$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
2501as_fn_error $? "cannot compute suffix of executables: cannot compile and link
2502See \`config.log' for more details" "$LINENO" 5; }
2503fi
2504rm -f conftest conftest$ac_cv_exeext
2505{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
2506$as_echo "$ac_cv_exeext" >&6; }
2507
2508rm -f conftest.$ac_ext
2509EXEEXT=$ac_cv_exeext
2510ac_exeext=$EXEEXT
2511cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2512/* end confdefs.h. */
2513#include <stdio.h>
2514int
2515main ()
2516{
2517FILE *f = fopen ("conftest.out", "w");
2518 return ferror (f) || fclose (f) != 0;
2519
2520 ;
2521 return 0;
2522}
2523_ACEOF
2524ac_clean_files="$ac_clean_files conftest.out"
2525# Check that the compiler produces executables we can run. If not, either
2526# the compiler is broken, or we cross compile.
2527{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
2528$as_echo_n "checking whether we are cross compiling... " >&6; }
2529if test "$cross_compiling" != yes; then
2530 { { ac_try="$ac_link"
2531case "(($ac_try" in
2532 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
2533 *) ac_try_echo=$ac_try;;
2534esac
2535eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
2536$as_echo "$ac_try_echo"; } >&5
2537 (eval "$ac_link") 2>&5
2538 ac_status=$?
2539 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
2540 test $ac_status = 0; }
2541 if { ac_try='./conftest$ac_cv_exeext'
2542 { { case "(($ac_try" in
2543 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
2544 *) ac_try_echo=$ac_try;;
2545esac
2546eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
2547$as_echo "$ac_try_echo"; } >&5
2548 (eval "$ac_try") 2>&5
2549 ac_status=$?
2550 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
2551 test $ac_status = 0; }; }; then
2552 cross_compiling=no
2553 else
2554 if test "$cross_compiling" = maybe; then
2555 cross_compiling=yes
2556 else
2557 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
2558$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
2559as_fn_error $? "cannot run C compiled programs.
2560If you meant to cross compile, use \`--host'.
2561See \`config.log' for more details" "$LINENO" 5; }
2562 fi
2563 fi
2564fi
2565{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
2566$as_echo "$cross_compiling" >&6; }
2567
2568rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
2569ac_clean_files=$ac_clean_files_save
2570{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
2571$as_echo_n "checking for suffix of object files... " >&6; }
2572if ${ac_cv_objext+:} false; then :
2573 $as_echo_n "(cached) " >&6
2574else
2575 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2576/* end confdefs.h. */
2577
2578int
2579main ()
2580{
2581
2582 ;
2583 return 0;
2584}
2585_ACEOF
2586rm -f conftest.o conftest.obj
2587if { { ac_try="$ac_compile"
2588case "(($ac_try" in
2589 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
2590 *) ac_try_echo=$ac_try;;
2591esac
2592eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
2593$as_echo "$ac_try_echo"; } >&5
2594 (eval "$ac_compile") 2>&5
2595 ac_status=$?
2596 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
2597 test $ac_status = 0; }; then :
2598 for ac_file in conftest.o conftest.obj conftest.*; do
2599 test -f "$ac_file" || continue;
2600 case $ac_file in
2601 *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
2602 *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
2603 break;;
2604 esac
2605done
2606else
2607 $as_echo "$as_me: failed program was:" >&5
2608sed 's/^/| /' conftest.$ac_ext >&5
2609
2610{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
2611$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
2612as_fn_error $? "cannot compute suffix of object files: cannot compile
2613See \`config.log' for more details" "$LINENO" 5; }
2614fi
2615rm -f conftest.$ac_cv_objext conftest.$ac_ext
2616fi
2617{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
2618$as_echo "$ac_cv_objext" >&6; }
2619OBJEXT=$ac_cv_objext
2620ac_objext=$OBJEXT
2621{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
2622$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
2623if ${ac_cv_c_compiler_gnu+:} false; then :
2624 $as_echo_n "(cached) " >&6
2625else
2626 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2627/* end confdefs.h. */
2628
2629int
2630main ()
2631{
2632#ifndef __GNUC__
2633 choke me
2634#endif
2635
2636 ;
2637 return 0;
2638}
2639_ACEOF
2640if ac_fn_c_try_compile "$LINENO"; then :
2641 ac_compiler_gnu=yes
2642else
2643 ac_compiler_gnu=no
2644fi
2645rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
2646ac_cv_c_compiler_gnu=$ac_compiler_gnu
2647
2648fi
2649{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
2650$as_echo "$ac_cv_c_compiler_gnu" >&6; }
2651if test $ac_compiler_gnu = yes; then
2652 GCC=yes
2653else
2654 GCC=
2655fi
2656ac_test_CFLAGS=${CFLAGS+set}
2657ac_save_CFLAGS=$CFLAGS
2658{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
2659$as_echo_n "checking whether $CC accepts -g... " >&6; }
2660if ${ac_cv_prog_cc_g+:} false; then :
2661 $as_echo_n "(cached) " >&6
2662else
2663 ac_save_c_werror_flag=$ac_c_werror_flag
2664 ac_c_werror_flag=yes
2665 ac_cv_prog_cc_g=no
2666 CFLAGS="-g"
2667 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2668/* end confdefs.h. */
2669
2670int
2671main ()
2672{
2673
2674 ;
2675 return 0;
2676}
2677_ACEOF
2678if ac_fn_c_try_compile "$LINENO"; then :
2679 ac_cv_prog_cc_g=yes
2680else
2681 CFLAGS=""
2682 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2683/* end confdefs.h. */
2684
2685int
2686main ()
2687{
2688
2689 ;
2690 return 0;
2691}
2692_ACEOF
2693if ac_fn_c_try_compile "$LINENO"; then :
2694
2695else
2696 ac_c_werror_flag=$ac_save_c_werror_flag
2697 CFLAGS="-g"
2698 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2699/* end confdefs.h. */
2700
2701int
2702main ()
2703{
2704
2705 ;
2706 return 0;
2707}
2708_ACEOF
2709if ac_fn_c_try_compile "$LINENO"; then :
2710 ac_cv_prog_cc_g=yes
2711fi
2712rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
2713fi
2714rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
2715fi
2716rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
2717 ac_c_werror_flag=$ac_save_c_werror_flag
2718fi
2719{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
2720$as_echo "$ac_cv_prog_cc_g" >&6; }
2721if test "$ac_test_CFLAGS" = set; then
2722 CFLAGS=$ac_save_CFLAGS
2723elif test $ac_cv_prog_cc_g = yes; then
2724 if test "$GCC" = yes; then
2725 CFLAGS="-g -O2"
2726 else
2727 CFLAGS="-g"
2728 fi
2729else
2730 if test "$GCC" = yes; then
2731 CFLAGS="-O2"
2732 else
2733 CFLAGS=
2734 fi
2735fi
2736{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
2737$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
2738if ${ac_cv_prog_cc_c89+:} false; then :
2739 $as_echo_n "(cached) " >&6
2740else
2741 ac_cv_prog_cc_c89=no
2742ac_save_CC=$CC
2743cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2744/* end confdefs.h. */
2745#include <stdarg.h>
2746#include <stdio.h>
2747struct stat;
2748/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
2749struct buf { int x; };
2750FILE * (*rcsopen) (struct buf *, struct stat *, int);
2751static char *e (p, i)
2752 char **p;
2753 int i;
2754{
2755 return p[i];
2756}
2757static char *f (char * (*g) (char **, int), char **p, ...)
2758{
2759 char *s;
2760 va_list v;
2761 va_start (v,p);
2762 s = g (p, va_arg (v,int));
2763 va_end (v);
2764 return s;
2765}
2766
2767/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
2768 function prototypes and stuff, but not '\xHH' hex character constants.
2769 These don't provoke an error unfortunately, instead are silently treated
2770 as 'x'. The following induces an error, until -std is added to get
2771 proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
2772 array size at least. It's necessary to write '\x00'==0 to get something
2773 that's true only with -std. */
2774int osf4_cc_array ['\x00' == 0 ? 1 : -1];
2775
2776/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
2777 inside strings and character constants. */
2778#define FOO(x) 'x'
2779int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
2780
2781int test (int i, double x);
2782struct s1 {int (*f) (int a);};
2783struct s2 {int (*f) (double a);};
2784int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
2785int argc;
2786char **argv;
2787int
2788main ()
2789{
2790return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
2791 ;
2792 return 0;
2793}
2794_ACEOF
2795for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
2796 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
2797do
2798 CC="$ac_save_CC $ac_arg"
2799 if ac_fn_c_try_compile "$LINENO"; then :
2800 ac_cv_prog_cc_c89=$ac_arg
2801fi
2802rm -f core conftest.err conftest.$ac_objext
2803 test "x$ac_cv_prog_cc_c89" != "xno" && break
2804done
2805rm -f conftest.$ac_ext
2806CC=$ac_save_CC
2807
2808fi
2809# AC_CACHE_VAL
2810case "x$ac_cv_prog_cc_c89" in
2811 x)
2812 { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
2813$as_echo "none needed" >&6; } ;;
2814 xno)
2815 { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
2816$as_echo "unsupported" >&6; } ;;
2817 *)
2818 CC="$CC $ac_cv_prog_cc_c89"
2819 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
2820$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
2821esac
2822if test "x$ac_cv_prog_cc_c89" != xno; then :
2823
2824fi
2825
2826ac_ext=c
2827ac_cpp='$CPP $CPPFLAGS'
2828ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
2829ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
2830ac_compiler_gnu=$ac_cv_c_compiler_gnu
2831
2832#AC_PROG_CXX
2833ac_aux_dir=
2834for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
2835 if test -f "$ac_dir/install-sh"; then
2836 ac_aux_dir=$ac_dir
2837 ac_install_sh="$ac_aux_dir/install-sh -c"
2838 break
2839 elif test -f "$ac_dir/install.sh"; then
2840 ac_aux_dir=$ac_dir
2841 ac_install_sh="$ac_aux_dir/install.sh -c"
2842 break
2843 elif test -f "$ac_dir/shtool"; then
2844 ac_aux_dir=$ac_dir
2845 ac_install_sh="$ac_aux_dir/shtool install -c"
2846 break
2847 fi
2848done
2849if test -z "$ac_aux_dir"; then
2850 as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
2851fi
2852
2853# These three variables are undocumented and unsupported,
2854# and are intended to be withdrawn in a future Autoconf release.
2855# They can cause serious problems if a builder's source tree is in a directory
2856# whose full name contains unusual characters.
2857ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
2858ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
2859ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
2860
2861
2862# Find a good install program. We prefer a C program (faster),
2863# so one script is as good as another. But avoid the broken or
2864# incompatible versions:
2865# SysV /etc/install, /usr/sbin/install
2866# SunOS /usr/etc/install
2867# IRIX /sbin/install
2868# AIX /bin/install
2869# AmigaOS /C/install, which installs bootblocks on floppy discs
2870# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
2871# AFS /usr/afsws/bin/install, which mishandles nonexistent args
2872# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
2873# OS/2's system install, which has a completely different semantic
2874# ./install, which can be erroneously created by make from ./install.sh.
2875# Reject install programs that cannot install multiple files.
2876{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
2877$as_echo_n "checking for a BSD-compatible install... " >&6; }
2878if test -z "$INSTALL"; then
2879if ${ac_cv_path_install+:} false; then :
2880 $as_echo_n "(cached) " >&6
2881else
2882 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2883for as_dir in $PATH
2884do
2885 IFS=$as_save_IFS
2886 test -z "$as_dir" && as_dir=.
2887 # Account for people who put trailing slashes in PATH elements.
2888case $as_dir/ in #((
2889 ./ | .// | /[cC]/* | \
2890 /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
2891 ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
2892 /usr/ucb/* ) ;;
2893 *)
2894 # OSF1 and SCO ODT 3.0 have their own names for install.
2895 # Don't use installbsd from OSF since it installs stuff as root
2896 # by default.
2897 for ac_prog in ginstall scoinst install; do
2898 for ac_exec_ext in '' $ac_executable_extensions; do
2899 if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
2900 if test $ac_prog = install &&
2901 grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
2902 # AIX install. It has an incompatible calling convention.
2903 :
2904 elif test $ac_prog = install &&
2905 grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
2906 # program-specific install script used by HP pwplus--don't use.
2907 :
2908 else
2909 rm -rf conftest.one conftest.two conftest.dir
2910 echo one > conftest.one
2911 echo two > conftest.two
2912 mkdir conftest.dir
2913 if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
2914 test -s conftest.one && test -s conftest.two &&
2915 test -s conftest.dir/conftest.one &&
2916 test -s conftest.dir/conftest.two
2917 then
2918 ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
2919 break 3
2920 fi
2921 fi
2922 fi
2923 done
2924 done
2925 ;;
2926esac
2927
2928 done
2929IFS=$as_save_IFS
2930
2931rm -rf conftest.one conftest.two conftest.dir
2932
2933fi
2934 if test "${ac_cv_path_install+set}" = set; then
2935 INSTALL=$ac_cv_path_install
2936 else
2937 # As a last resort, use the slow shell script. Don't cache a
2938 # value for INSTALL within a source directory, because that will
2939 # break other packages using the cache if that directory is
2940 # removed, or if the value is a relative name.
2941 INSTALL=$ac_install_sh
2942 fi
2943fi
2944{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
2945$as_echo "$INSTALL" >&6; }
2946
2947# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
2948# It thinks the first close brace ends the variable substitution.
2949test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
2950
2951test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
2952
2953test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
2954
2955if test -n "$ac_tool_prefix"; then
2956 # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
2957set dummy ${ac_tool_prefix}ranlib; ac_word=$2
2958{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
2959$as_echo_n "checking for $ac_word... " >&6; }
2960if ${ac_cv_prog_RANLIB+:} false; then :
2961 $as_echo_n "(cached) " >&6
2962else
2963 if test -n "$RANLIB"; then
2964 ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
2965else
2966as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2967for as_dir in $PATH
2968do
2969 IFS=$as_save_IFS
2970 test -z "$as_dir" && as_dir=.
2971 for ac_exec_ext in '' $ac_executable_extensions; do
2972 if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
2973 ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
2974 $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
2975 break 2
2976 fi
2977done
2978 done
2979IFS=$as_save_IFS
2980
2981fi
2982fi
2983RANLIB=$ac_cv_prog_RANLIB
2984if test -n "$RANLIB"; then
2985 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
2986$as_echo "$RANLIB" >&6; }
2987else
2988 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
2989$as_echo "no" >&6; }
2990fi
2991
2992
2993fi
2994if test -z "$ac_cv_prog_RANLIB"; then
2995 ac_ct_RANLIB=$RANLIB
2996 # Extract the first word of "ranlib", so it can be a program name with args.
2997set dummy ranlib; ac_word=$2
2998{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
2999$as_echo_n "checking for $ac_word... " >&6; }
3000if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
3001 $as_echo_n "(cached) " >&6
3002else
3003 if test -n "$ac_ct_RANLIB"; then
3004 ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
3005else
3006as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
3007for as_dir in $PATH
3008do
3009 IFS=$as_save_IFS
3010 test -z "$as_dir" && as_dir=.
3011 for ac_exec_ext in '' $ac_executable_extensions; do
3012 if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
3013 ac_cv_prog_ac_ct_RANLIB="ranlib"
3014 $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
3015 break 2
3016 fi
3017done
3018 done
3019IFS=$as_save_IFS
3020
3021fi
3022fi
3023ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
3024if test -n "$ac_ct_RANLIB"; then
3025 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
3026$as_echo "$ac_ct_RANLIB" >&6; }
3027else
3028 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
3029$as_echo "no" >&6; }
3030fi
3031
3032 if test "x$ac_ct_RANLIB" = x; then
3033 RANLIB=":"
3034 else
3035 case $cross_compiling:$ac_tool_warned in
3036yes:)
3037{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
3038$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
3039ac_tool_warned=yes ;;
3040esac
3041 RANLIB=$ac_ct_RANLIB
3042 fi
3043else
3044 RANLIB="$ac_cv_prog_RANLIB"
3045fi
3046
3047
3048HAVE_SECCOMP=""
3049# Check whether --enable-seccomp was given.
3050if test "${enable_seccomp+set}" = set; then :
3051 enableval=$enable_seccomp;
3052fi
3053
3054if test "x$enable_seccomp" != "xno"; then :
3055
3056 HAVE_SECCOMP="-DHAVE_SECCOMP"
3057
3058
3059fi
3060
3061HAVE_CHROOT=""
3062# Check whether --enable-chroot was given.
3063if test "${enable_chroot+set}" = set; then :
3064 enableval=$enable_chroot;
3065fi
3066
3067if test "x$enable_chroot" != "xno"; then :
3068
3069 HAVE_CHROOT="-DHAVE_CHROOT"
3070
3071
3072fi
3073
3074HAVE_BIND=""
3075# Check whether --enable-bind was given.
3076if test "${enable_bind+set}" = set; then :
3077 enableval=$enable_bind;
3078fi
3079
3080if test "x$enable_bind" != "xno"; then :
3081
3082 HAVE_BIND="-DHAVE_BIND"
3083
3084
3085fi
3086
3087
3088# checking pthread library
3089
3090{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
3091$as_echo_n "checking for main in -lpthread... " >&6; }
3092if ${ac_cv_lib_pthread_main+:} false; then :
3093 $as_echo_n "(cached) " >&6
3094else
3095 ac_check_lib_save_LIBS=$LIBS
3096LIBS="-lpthread $LIBS"
3097cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3098/* end confdefs.h. */
3099
3100
3101int
3102main ()
3103{
3104return main ();
3105 ;
3106 return 0;
3107}
3108_ACEOF
3109if ac_fn_c_try_link "$LINENO"; then :
3110 ac_cv_lib_pthread_main=yes
3111else
3112 ac_cv_lib_pthread_main=no
3113fi
3114rm -f core conftest.err conftest.$ac_objext \
3115 conftest$ac_exeext conftest.$ac_ext
3116LIBS=$ac_check_lib_save_LIBS
3117fi
3118{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
3119$as_echo "$ac_cv_lib_pthread_main" >&6; }
3120if test "x$ac_cv_lib_pthread_main" = xyes; then :
3121 cat >>confdefs.h <<_ACEOF
3122#define HAVE_LIBPTHREAD 1
3123_ACEOF
3124
3125 LIBS="-lpthread $LIBS"
3126
3127else
3128 as_fn_error $? "*** POSIX thread support not installed ***" "$LINENO" 5
3129fi
3130
3131ac_ext=c
3132ac_cpp='$CPP $CPPFLAGS'
3133ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
3134ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
3135ac_compiler_gnu=$ac_cv_c_compiler_gnu
3136{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
3137$as_echo_n "checking how to run the C preprocessor... " >&6; }
3138# On Suns, sometimes $CPP names a directory.
3139if test -n "$CPP" && test -d "$CPP"; then
3140 CPP=
3141fi
3142if test -z "$CPP"; then
3143 if ${ac_cv_prog_CPP+:} false; then :
3144 $as_echo_n "(cached) " >&6
3145else
3146 # Double quotes because CPP needs to be expanded
3147 for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
3148 do
3149 ac_preproc_ok=false
3150for ac_c_preproc_warn_flag in '' yes
3151do
3152 # Use a header file that comes with gcc, so configuring glibc
3153 # with a fresh cross-compiler works.
3154 # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
3155 # <limits.h> exists even on freestanding compilers.
3156 # On the NeXT, cc -E runs the code through the compiler's parser,
3157 # not just through cpp. "Syntax error" is here to catch this case.
3158 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3159/* end confdefs.h. */
3160#ifdef __STDC__
3161# include <limits.h>
3162#else
3163# include <assert.h>
3164#endif
3165 Syntax error
3166_ACEOF
3167if ac_fn_c_try_cpp "$LINENO"; then :
3168
3169else
3170 # Broken: fails on valid input.
3171continue
3172fi
3173rm -f conftest.err conftest.i conftest.$ac_ext
3174
3175 # OK, works on sane cases. Now check whether nonexistent headers
3176 # can be detected and how.
3177 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3178/* end confdefs.h. */
3179#include <ac_nonexistent.h>
3180_ACEOF
3181if ac_fn_c_try_cpp "$LINENO"; then :
3182 # Broken: success on invalid input.
3183continue
3184else
3185 # Passes both tests.
3186ac_preproc_ok=:
3187break
3188fi
3189rm -f conftest.err conftest.i conftest.$ac_ext
3190
3191done
3192# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
3193rm -f conftest.i conftest.err conftest.$ac_ext
3194if $ac_preproc_ok; then :
3195 break
3196fi
3197
3198 done
3199 ac_cv_prog_CPP=$CPP
3200
3201fi
3202 CPP=$ac_cv_prog_CPP
3203else
3204 ac_cv_prog_CPP=$CPP
3205fi
3206{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
3207$as_echo "$CPP" >&6; }
3208ac_preproc_ok=false
3209for ac_c_preproc_warn_flag in '' yes
3210do
3211 # Use a header file that comes with gcc, so configuring glibc
3212 # with a fresh cross-compiler works.
3213 # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
3214 # <limits.h> exists even on freestanding compilers.
3215 # On the NeXT, cc -E runs the code through the compiler's parser,
3216 # not just through cpp. "Syntax error" is here to catch this case.
3217 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3218/* end confdefs.h. */
3219#ifdef __STDC__
3220# include <limits.h>
3221#else
3222# include <assert.h>
3223#endif
3224 Syntax error
3225_ACEOF
3226if ac_fn_c_try_cpp "$LINENO"; then :
3227
3228else
3229 # Broken: fails on valid input.
3230continue
3231fi
3232rm -f conftest.err conftest.i conftest.$ac_ext
3233
3234 # OK, works on sane cases. Now check whether nonexistent headers
3235 # can be detected and how.
3236 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3237/* end confdefs.h. */
3238#include <ac_nonexistent.h>
3239_ACEOF
3240if ac_fn_c_try_cpp "$LINENO"; then :
3241 # Broken: success on invalid input.
3242continue
3243else
3244 # Passes both tests.
3245ac_preproc_ok=:
3246break
3247fi
3248rm -f conftest.err conftest.i conftest.$ac_ext
3249
3250done
3251# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
3252rm -f conftest.i conftest.err conftest.$ac_ext
3253if $ac_preproc_ok; then :
3254
3255else
3256 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
3257$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
3258as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
3259See \`config.log' for more details" "$LINENO" 5; }
3260fi
3261
3262ac_ext=c
3263ac_cpp='$CPP $CPPFLAGS'
3264ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
3265ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
3266ac_compiler_gnu=$ac_cv_c_compiler_gnu
3267
3268
3269{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
3270$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
3271if ${ac_cv_path_GREP+:} false; then :
3272 $as_echo_n "(cached) " >&6
3273else
3274 if test -z "$GREP"; then
3275 ac_path_GREP_found=false
3276 # Loop through the user's path and test for each of PROGNAME-LIST
3277 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
3278for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
3279do
3280 IFS=$as_save_IFS
3281 test -z "$as_dir" && as_dir=.
3282 for ac_prog in grep ggrep; do
3283 for ac_exec_ext in '' $ac_executable_extensions; do
3284 ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
3285 as_fn_executable_p "$ac_path_GREP" || continue
3286# Check for GNU ac_path_GREP and select it if it is found.
3287 # Check for GNU $ac_path_GREP
3288case `"$ac_path_GREP" --version 2>&1` in
3289*GNU*)
3290 ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
3291*)
3292 ac_count=0
3293 $as_echo_n 0123456789 >"conftest.in"
3294 while :
3295 do
3296 cat "conftest.in" "conftest.in" >"conftest.tmp"
3297 mv "conftest.tmp" "conftest.in"
3298 cp "conftest.in" "conftest.nl"
3299 $as_echo 'GREP' >> "conftest.nl"
3300 "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
3301 diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
3302 as_fn_arith $ac_count + 1 && ac_count=$as_val
3303 if test $ac_count -gt ${ac_path_GREP_max-0}; then
3304 # Best one so far, save it but keep looking for a better one
3305 ac_cv_path_GREP="$ac_path_GREP"
3306 ac_path_GREP_max=$ac_count
3307 fi
3308 # 10*(2^10) chars as input seems more than enough
3309 test $ac_count -gt 10 && break
3310 done
3311 rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
3312esac
3313
3314 $ac_path_GREP_found && break 3
3315 done
3316 done
3317 done
3318IFS=$as_save_IFS
3319 if test -z "$ac_cv_path_GREP"; then
3320 as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
3321 fi
3322else
3323 ac_cv_path_GREP=$GREP
3324fi
3325
3326fi
3327{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
3328$as_echo "$ac_cv_path_GREP" >&6; }
3329 GREP="$ac_cv_path_GREP"
3330
3331
3332{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
3333$as_echo_n "checking for egrep... " >&6; }
3334if ${ac_cv_path_EGREP+:} false; then :
3335 $as_echo_n "(cached) " >&6
3336else
3337 if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
3338 then ac_cv_path_EGREP="$GREP -E"
3339 else
3340 if test -z "$EGREP"; then
3341 ac_path_EGREP_found=false
3342 # Loop through the user's path and test for each of PROGNAME-LIST
3343 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
3344for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
3345do
3346 IFS=$as_save_IFS
3347 test -z "$as_dir" && as_dir=.
3348 for ac_prog in egrep; do
3349 for ac_exec_ext in '' $ac_executable_extensions; do
3350 ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
3351 as_fn_executable_p "$ac_path_EGREP" || continue
3352# Check for GNU ac_path_EGREP and select it if it is found.
3353 # Check for GNU $ac_path_EGREP
3354case `"$ac_path_EGREP" --version 2>&1` in
3355*GNU*)
3356 ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
3357*)
3358 ac_count=0
3359 $as_echo_n 0123456789 >"conftest.in"
3360 while :
3361 do
3362 cat "conftest.in" "conftest.in" >"conftest.tmp"
3363 mv "conftest.tmp" "conftest.in"
3364 cp "conftest.in" "conftest.nl"
3365 $as_echo 'EGREP' >> "conftest.nl"
3366 "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
3367 diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
3368 as_fn_arith $ac_count + 1 && ac_count=$as_val
3369 if test $ac_count -gt ${ac_path_EGREP_max-0}; then
3370 # Best one so far, save it but keep looking for a better one
3371 ac_cv_path_EGREP="$ac_path_EGREP"
3372 ac_path_EGREP_max=$ac_count
3373 fi
3374 # 10*(2^10) chars as input seems more than enough
3375 test $ac_count -gt 10 && break
3376 done
3377 rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
3378esac
3379
3380 $ac_path_EGREP_found && break 3
3381 done
3382 done
3383 done
3384IFS=$as_save_IFS
3385 if test -z "$ac_cv_path_EGREP"; then
3386 as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
3387 fi
3388else
3389 ac_cv_path_EGREP=$EGREP
3390fi
3391
3392 fi
3393fi
3394{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
3395$as_echo "$ac_cv_path_EGREP" >&6; }
3396 EGREP="$ac_cv_path_EGREP"
3397
3398
3399{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
3400$as_echo_n "checking for ANSI C header files... " >&6; }
3401if ${ac_cv_header_stdc+:} false; then :
3402 $as_echo_n "(cached) " >&6
3403else
3404 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3405/* end confdefs.h. */
3406#include <stdlib.h>
3407#include <stdarg.h>
3408#include <string.h>
3409#include <float.h>
3410
3411int
3412main ()
3413{
3414
3415 ;
3416 return 0;
3417}
3418_ACEOF
3419if ac_fn_c_try_compile "$LINENO"; then :
3420 ac_cv_header_stdc=yes
3421else
3422 ac_cv_header_stdc=no
3423fi
3424rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
3425
3426if test $ac_cv_header_stdc = yes; then
3427 # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
3428 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3429/* end confdefs.h. */
3430#include <string.h>
3431
3432_ACEOF
3433if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
3434 $EGREP "memchr" >/dev/null 2>&1; then :
3435
3436else
3437 ac_cv_header_stdc=no
3438fi
3439rm -f conftest*
3440
3441fi
3442
3443if test $ac_cv_header_stdc = yes; then
3444 # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
3445 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3446/* end confdefs.h. */
3447#include <stdlib.h>
3448
3449_ACEOF
3450if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
3451 $EGREP "free" >/dev/null 2>&1; then :
3452
3453else
3454 ac_cv_header_stdc=no
3455fi
3456rm -f conftest*
3457
3458fi
3459
3460if test $ac_cv_header_stdc = yes; then
3461 # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
3462 if test "$cross_compiling" = yes; then :
3463 :
3464else
3465 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3466/* end confdefs.h. */
3467#include <ctype.h>
3468#include <stdlib.h>
3469#if ((' ' & 0x0FF) == 0x020)
3470# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
3471# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
3472#else
3473# define ISLOWER(c) \
3474 (('a' <= (c) && (c) <= 'i') \
3475 || ('j' <= (c) && (c) <= 'r') \
3476 || ('s' <= (c) && (c) <= 'z'))
3477# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
3478#endif
3479
3480#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
3481int
3482main ()
3483{
3484 int i;
3485 for (i = 0; i < 256; i++)
3486 if (XOR (islower (i), ISLOWER (i))
3487 || toupper (i) != TOUPPER (i))
3488 return 2;
3489 return 0;
3490}
3491_ACEOF
3492if ac_fn_c_try_run "$LINENO"; then :
3493
3494else
3495 ac_cv_header_stdc=no
3496fi
3497rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
3498 conftest.$ac_objext conftest.beam conftest.$ac_ext
3499fi
3500
3501fi
3502fi
3503{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
3504$as_echo "$ac_cv_header_stdc" >&6; }
3505if test $ac_cv_header_stdc = yes; then
3506
3507$as_echo "#define STDC_HEADERS 1" >>confdefs.h
3508
3509fi
3510
3511# On IRIX 5.3, sys/types and inttypes.h are conflicting.
3512for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
3513 inttypes.h stdint.h unistd.h
3514do :
3515 as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
3516ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
3517"
3518if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
3519 cat >>confdefs.h <<_ACEOF
3520#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
3521_ACEOF
3522
3523fi
3524
3525done
3526
3527
3528ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
3529if test "x$ac_cv_header_pthread_h" = xyes; then :
3530
3531else
3532 as_fn_error $? "*** POSIX thread support not installed ***" "$LINENO" 5
3533fi
3534
3535
3536ac_fn_c_check_header_mongrel "$LINENO" "linux/seccomp.h" "ac_cv_header_linux_seccomp_h" "$ac_includes_default"
3537if test "x$ac_cv_header_linux_seccomp_h" = xyes; then :
3538 HAVE_SECCOMP_H="-DHAVE_SECCOMP_H"
3539else
3540 HAVE_SECCOMP_H=""
3541fi
3542
3543
3544
3545
3546ac_config_files="$ac_config_files Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/ftee/Makefile"
3547
3548cat >confcache <<\_ACEOF
3549# This file is a shell script that caches the results of configure
3550# tests run on this system so they can be shared between configure
3551# scripts and configure runs, see configure's option --config-cache.
3552# It is not useful on other systems. If it contains results you don't
3553# want to keep, you may remove or edit it.
3554#
3555# config.status only pays attention to the cache file if you give it
3556# the --recheck option to rerun configure.
3557#
3558# `ac_cv_env_foo' variables (set or unset) will be overridden when
3559# loading this file, other *unset* `ac_cv_foo' will be assigned the
3560# following values.
3561
3562_ACEOF
3563
3564# The following way of writing the cache mishandles newlines in values,
3565# but we know of no workaround that is simple, portable, and efficient.
3566# So, we kill variables containing newlines.
3567# Ultrix sh set writes to stderr and can't be redirected directly,
3568# and sets the high bit in the cache file unless we assign to the vars.
3569(
3570 for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
3571 eval ac_val=\$$ac_var
3572 case $ac_val in #(
3573 *${as_nl}*)
3574 case $ac_var in #(
3575 *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
3576$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
3577 esac
3578 case $ac_var in #(
3579 _ | IFS | as_nl) ;; #(
3580 BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
3581 *) { eval $ac_var=; unset $ac_var;} ;;
3582 esac ;;
3583 esac
3584 done
3585
3586 (set) 2>&1 |
3587 case $as_nl`(ac_space=' '; set) 2>&1` in #(
3588 *${as_nl}ac_space=\ *)
3589 # `set' does not quote correctly, so add quotes: double-quote
3590 # substitution turns \\\\ into \\, and sed turns \\ into \.
3591 sed -n \
3592 "s/'/'\\\\''/g;
3593 s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
3594 ;; #(
3595 *)
3596 # `set' quotes correctly as required by POSIX, so do not add quotes.
3597 sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
3598 ;;
3599 esac |
3600 sort
3601) |
3602 sed '
3603 /^ac_cv_env_/b end
3604 t clear
3605 :clear
3606 s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
3607 t end
3608 s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
3609 :end' >>confcache
3610if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
3611 if test -w "$cache_file"; then
3612 if test "x$cache_file" != "x/dev/null"; then
3613 { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
3614$as_echo "$as_me: updating cache $cache_file" >&6;}
3615 if test ! -f "$cache_file" || test -h "$cache_file"; then
3616 cat confcache >"$cache_file"
3617 else
3618 case $cache_file in #(
3619 */* | ?:*)
3620 mv -f confcache "$cache_file"$$ &&
3621 mv -f "$cache_file"$$ "$cache_file" ;; #(
3622 *)
3623 mv -f confcache "$cache_file" ;;
3624 esac
3625 fi
3626 fi
3627 else
3628 { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
3629$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
3630 fi
3631fi
3632rm -f confcache
3633
3634test "x$prefix" = xNONE && prefix=$ac_default_prefix
3635# Let make expand exec_prefix.
3636test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
3637
3638# Transform confdefs.h into DEFS.
3639# Protect against shell expansion while executing Makefile rules.
3640# Protect against Makefile macro expansion.
3641#
3642# If the first sed substitution is executed (which looks for macros that
3643# take arguments), then branch to the quote section. Otherwise,
3644# look for a macro that doesn't take arguments.
3645ac_script='
3646:mline
3647/\\$/{
3648 N
3649 s,\\\n,,
3650 b mline
3651}
3652t clear
3653:clear
3654s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
3655t quote
3656s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
3657t quote
3658b any
3659:quote
3660s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
3661s/\[/\\&/g
3662s/\]/\\&/g
3663s/\$/$$/g
3664H
3665:any
3666${
3667 g
3668 s/^\n//
3669 s/\n/ /g
3670 p
3671}
3672'
3673DEFS=`sed -n "$ac_script" confdefs.h`
3674
3675
3676ac_libobjs=
3677ac_ltlibobjs=
3678U=
3679for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
3680 # 1. Remove the extension, and $U if already installed.
3681 ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
3682 ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
3683 # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
3684 # will be set to the directory where LIBOBJS objects are built.
3685 as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
3686 as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
3687done
3688LIBOBJS=$ac_libobjs
3689
3690LTLIBOBJS=$ac_ltlibobjs
3691
3692
3693
3694: "${CONFIG_STATUS=./config.status}"
3695ac_write_fail=0
3696ac_clean_files_save=$ac_clean_files
3697ac_clean_files="$ac_clean_files $CONFIG_STATUS"
3698{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
3699$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
3700as_write_fail=0
3701cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
3702#! $SHELL
3703# Generated by $as_me.
3704# Run this file to recreate the current configuration.
3705# Compiler output produced by configure, useful for debugging
3706# configure, is in config.log if it exists.
3707
3708debug=false
3709ac_cs_recheck=false
3710ac_cs_silent=false
3711
3712SHELL=\${CONFIG_SHELL-$SHELL}
3713export SHELL
3714_ASEOF
3715cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
3716## -------------------- ##
3717## M4sh Initialization. ##
3718## -------------------- ##
3719
3720# Be more Bourne compatible
3721DUALCASE=1; export DUALCASE # for MKS sh
3722if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
3723 emulate sh
3724 NULLCMD=:
3725 # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
3726 # is contrary to our usage. Disable this feature.
3727 alias -g '${1+"$@"}'='"$@"'
3728 setopt NO_GLOB_SUBST
3729else
3730 case `(set -o) 2>/dev/null` in #(
3731 *posix*) :
3732 set -o posix ;; #(
3733 *) :
3734 ;;
3735esac
3736fi
3737
3738
3739as_nl='
3740'
3741export as_nl
3742# Printing a long string crashes Solaris 7 /usr/bin/printf.
3743as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
3744as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
3745as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
3746# Prefer a ksh shell builtin over an external printf program on Solaris,
3747# but without wasting forks for bash or zsh.
3748if test -z "$BASH_VERSION$ZSH_VERSION" \
3749 && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
3750 as_echo='print -r --'
3751 as_echo_n='print -rn --'
3752elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
3753 as_echo='printf %s\n'
3754 as_echo_n='printf %s'
3755else
3756 if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
3757 as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
3758 as_echo_n='/usr/ucb/echo -n'
3759 else
3760 as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
3761 as_echo_n_body='eval
3762 arg=$1;
3763 case $arg in #(
3764 *"$as_nl"*)
3765 expr "X$arg" : "X\\(.*\\)$as_nl";
3766 arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
3767 esac;
3768 expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
3769 '
3770 export as_echo_n_body
3771 as_echo_n='sh -c $as_echo_n_body as_echo'
3772 fi
3773 export as_echo_body
3774 as_echo='sh -c $as_echo_body as_echo'
3775fi
3776
3777# The user is always right.
3778if test "${PATH_SEPARATOR+set}" != set; then
3779 PATH_SEPARATOR=:
3780 (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
3781 (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
3782 PATH_SEPARATOR=';'
3783 }
3784fi
3785
3786
3787# IFS
3788# We need space, tab and new line, in precisely that order. Quoting is
3789# there to prevent editors from complaining about space-tab.
3790# (If _AS_PATH_WALK were called with IFS unset, it would disable word
3791# splitting by setting IFS to empty value.)
3792IFS=" "" $as_nl"
3793
3794# Find who we are. Look in the path if we contain no directory separator.
3795as_myself=
3796case $0 in #((
3797 *[\\/]* ) as_myself=$0 ;;
3798 *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
3799for as_dir in $PATH
3800do
3801 IFS=$as_save_IFS
3802 test -z "$as_dir" && as_dir=.
3803 test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
3804 done
3805IFS=$as_save_IFS
3806
3807 ;;
3808esac
3809# We did not find ourselves, most probably we were run as `sh COMMAND'
3810# in which case we are not to be found in the path.
3811if test "x$as_myself" = x; then
3812 as_myself=$0
3813fi
3814if test ! -f "$as_myself"; then
3815 $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
3816 exit 1
3817fi
3818
3819# Unset variables that we do not need and which cause bugs (e.g. in
3820# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
3821# suppresses any "Segmentation fault" message there. '((' could
3822# trigger a bug in pdksh 5.2.14.
3823for as_var in BASH_ENV ENV MAIL MAILPATH
3824do eval test x\${$as_var+set} = xset \
3825 && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
3826done
3827PS1='$ '
3828PS2='> '
3829PS4='+ '
3830
3831# NLS nuisances.
3832LC_ALL=C
3833export LC_ALL
3834LANGUAGE=C
3835export LANGUAGE
3836
3837# CDPATH.
3838(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
3839
3840
3841# as_fn_error STATUS ERROR [LINENO LOG_FD]
3842# ----------------------------------------
3843# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
3844# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
3845# script with STATUS, using 1 if that was 0.
3846as_fn_error ()
3847{
3848 as_status=$1; test $as_status -eq 0 && as_status=1
3849 if test "$4"; then
3850 as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
3851 $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
3852 fi
3853 $as_echo "$as_me: error: $2" >&2
3854 as_fn_exit $as_status
3855} # as_fn_error
3856
3857
3858# as_fn_set_status STATUS
3859# -----------------------
3860# Set $? to STATUS, without forking.
3861as_fn_set_status ()
3862{
3863 return $1
3864} # as_fn_set_status
3865
3866# as_fn_exit STATUS
3867# -----------------
3868# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
3869as_fn_exit ()
3870{
3871 set +e
3872 as_fn_set_status $1
3873 exit $1
3874} # as_fn_exit
3875
3876# as_fn_unset VAR
3877# ---------------
3878# Portably unset VAR.
3879as_fn_unset ()
3880{
3881 { eval $1=; unset $1;}
3882}
3883as_unset=as_fn_unset
3884# as_fn_append VAR VALUE
3885# ----------------------
3886# Append the text in VALUE to the end of the definition contained in VAR. Take
3887# advantage of any shell optimizations that allow amortized linear growth over
3888# repeated appends, instead of the typical quadratic growth present in naive
3889# implementations.
3890if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
3891 eval 'as_fn_append ()
3892 {
3893 eval $1+=\$2
3894 }'
3895else
3896 as_fn_append ()
3897 {
3898 eval $1=\$$1\$2
3899 }
3900fi # as_fn_append
3901
3902# as_fn_arith ARG...
3903# ------------------
3904# Perform arithmetic evaluation on the ARGs, and store the result in the
3905# global $as_val. Take advantage of shells that can avoid forks. The arguments
3906# must be portable across $(()) and expr.
3907if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
3908 eval 'as_fn_arith ()
3909 {
3910 as_val=$(( $* ))
3911 }'
3912else
3913 as_fn_arith ()
3914 {
3915 as_val=`expr "$@" || test $? -eq 1`
3916 }
3917fi # as_fn_arith
3918
3919
3920if expr a : '\(a\)' >/dev/null 2>&1 &&
3921 test "X`expr 00001 : '.*\(...\)'`" = X001; then
3922 as_expr=expr
3923else
3924 as_expr=false
3925fi
3926
3927if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
3928 as_basename=basename
3929else
3930 as_basename=false
3931fi
3932
3933if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
3934 as_dirname=dirname
3935else
3936 as_dirname=false
3937fi
3938
3939as_me=`$as_basename -- "$0" ||
3940$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
3941 X"$0" : 'X\(//\)$' \| \
3942 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
3943$as_echo X/"$0" |
3944 sed '/^.*\/\([^/][^/]*\)\/*$/{
3945 s//\1/
3946 q
3947 }
3948 /^X\/\(\/\/\)$/{
3949 s//\1/
3950 q
3951 }
3952 /^X\/\(\/\).*/{
3953 s//\1/
3954 q
3955 }
3956 s/.*/./; q'`
3957
3958# Avoid depending upon Character Ranges.
3959as_cr_letters='abcdefghijklmnopqrstuvwxyz'
3960as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
3961as_cr_Letters=$as_cr_letters$as_cr_LETTERS
3962as_cr_digits='0123456789'
3963as_cr_alnum=$as_cr_Letters$as_cr_digits
3964
3965ECHO_C= ECHO_N= ECHO_T=
3966case `echo -n x` in #(((((
3967-n*)
3968 case `echo 'xy\c'` in
3969 *c*) ECHO_T=' ';; # ECHO_T is single tab character.
3970 xy) ECHO_C='\c';;
3971 *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
3972 ECHO_T=' ';;
3973 esac;;
3974*)
3975 ECHO_N='-n';;
3976esac
3977
3978rm -f conf$$ conf$$.exe conf$$.file
3979if test -d conf$$.dir; then
3980 rm -f conf$$.dir/conf$$.file
3981else
3982 rm -f conf$$.dir
3983 mkdir conf$$.dir 2>/dev/null
3984fi
3985if (echo >conf$$.file) 2>/dev/null; then
3986 if ln -s conf$$.file conf$$ 2>/dev/null; then
3987 as_ln_s='ln -s'
3988 # ... but there are two gotchas:
3989 # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
3990 # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
3991 # In both cases, we have to default to `cp -pR'.
3992 ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
3993 as_ln_s='cp -pR'
3994 elif ln conf$$.file conf$$ 2>/dev/null; then
3995 as_ln_s=ln
3996 else
3997 as_ln_s='cp -pR'
3998 fi
3999else
4000 as_ln_s='cp -pR'
4001fi
4002rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
4003rmdir conf$$.dir 2>/dev/null
4004
4005
4006# as_fn_mkdir_p
4007# -------------
4008# Create "$as_dir" as a directory, including parents if necessary.
4009as_fn_mkdir_p ()
4010{
4011
4012 case $as_dir in #(
4013 -*) as_dir=./$as_dir;;
4014 esac
4015 test -d "$as_dir" || eval $as_mkdir_p || {
4016 as_dirs=
4017 while :; do
4018 case $as_dir in #(
4019 *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
4020 *) as_qdir=$as_dir;;
4021 esac
4022 as_dirs="'$as_qdir' $as_dirs"
4023 as_dir=`$as_dirname -- "$as_dir" ||
4024$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
4025 X"$as_dir" : 'X\(//\)[^/]' \| \
4026 X"$as_dir" : 'X\(//\)$' \| \
4027 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
4028$as_echo X"$as_dir" |
4029 sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
4030 s//\1/
4031 q
4032 }
4033 /^X\(\/\/\)[^/].*/{
4034 s//\1/
4035 q
4036 }
4037 /^X\(\/\/\)$/{
4038 s//\1/
4039 q
4040 }
4041 /^X\(\/\).*/{
4042 s//\1/
4043 q
4044 }
4045 s/.*/./; q'`
4046 test -d "$as_dir" && break
4047 done
4048 test -z "$as_dirs" || eval "mkdir $as_dirs"
4049 } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
4050
4051
4052} # as_fn_mkdir_p
4053if mkdir -p . 2>/dev/null; then
4054 as_mkdir_p='mkdir -p "$as_dir"'
4055else
4056 test -d ./-p && rmdir ./-p
4057 as_mkdir_p=false
4058fi
4059
4060
4061# as_fn_executable_p FILE
4062# -----------------------
4063# Test if FILE is an executable regular file.
4064as_fn_executable_p ()
4065{
4066 test -f "$1" && test -x "$1"
4067} # as_fn_executable_p
4068as_test_x='test -x'
4069as_executable_p=as_fn_executable_p
4070
4071# Sed expression to map a string onto a valid CPP name.
4072as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
4073
4074# Sed expression to map a string onto a valid variable name.
4075as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
4076
4077
4078exec 6>&1
4079## ----------------------------------- ##
4080## Main body of $CONFIG_STATUS script. ##
4081## ----------------------------------- ##
4082_ASEOF
4083test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
4084
4085cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4086# Save the log message, to keep $0 and so on meaningful, and to
4087# report actual input values of CONFIG_FILES etc. instead of their
4088# values after options handling.
4089ac_log="
4090This file was extended by firejail $as_me 0.9.28, which was
4091generated by GNU Autoconf 2.69. Invocation command line was
4092
4093 CONFIG_FILES = $CONFIG_FILES
4094 CONFIG_HEADERS = $CONFIG_HEADERS
4095 CONFIG_LINKS = $CONFIG_LINKS
4096 CONFIG_COMMANDS = $CONFIG_COMMANDS
4097 $ $0 $@
4098
4099on `(hostname || uname -n) 2>/dev/null | sed 1q`
4100"
4101
4102_ACEOF
4103
4104case $ac_config_files in *"
4105"*) set x $ac_config_files; shift; ac_config_files=$*;;
4106esac
4107
4108
4109
4110cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4111# Files that config.status was made for.
4112config_files="$ac_config_files"
4113
4114_ACEOF
4115
4116cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4117ac_cs_usage="\
4118\`$as_me' instantiates files and other configuration actions
4119from templates according to the current configuration. Unless the files
4120and actions are specified as TAGs, all are instantiated by default.
4121
4122Usage: $0 [OPTION]... [TAG]...
4123
4124 -h, --help print this help, then exit
4125 -V, --version print version number and configuration settings, then exit
4126 --config print configuration, then exit
4127 -q, --quiet, --silent
4128 do not print progress messages
4129 -d, --debug don't remove temporary files
4130 --recheck update $as_me by reconfiguring in the same conditions
4131 --file=FILE[:TEMPLATE]
4132 instantiate the configuration file FILE
4133
4134Configuration files:
4135$config_files
4136
4137Report bugs to <netblue30@yahoo.com>.
4138firejail home page: <http://firejail.sourceforge.net>."
4139
4140_ACEOF
4141cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4142ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
4143ac_cs_version="\\
4144firejail config.status 0.9.28
4145configured by $0, generated by GNU Autoconf 2.69,
4146 with options \\"\$ac_cs_config\\"
4147
4148Copyright (C) 2012 Free Software Foundation, Inc.
4149This config.status script is free software; the Free Software Foundation
4150gives unlimited permission to copy, distribute and modify it."
4151
4152ac_pwd='$ac_pwd'
4153srcdir='$srcdir'
4154INSTALL='$INSTALL'
4155test -n "\$AWK" || AWK=awk
4156_ACEOF
4157
4158cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4159# The default lists apply if the user does not specify any file.
4160ac_need_defaults=:
4161while test $# != 0
4162do
4163 case $1 in
4164 --*=?*)
4165 ac_option=`expr "X$1" : 'X\([^=]*\)='`
4166 ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
4167 ac_shift=:
4168 ;;
4169 --*=)
4170 ac_option=`expr "X$1" : 'X\([^=]*\)='`
4171 ac_optarg=
4172 ac_shift=:
4173 ;;
4174 *)
4175 ac_option=$1
4176 ac_optarg=$2
4177 ac_shift=shift
4178 ;;
4179 esac
4180
4181 case $ac_option in
4182 # Handling of the options.
4183 -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
4184 ac_cs_recheck=: ;;
4185 --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
4186 $as_echo "$ac_cs_version"; exit ;;
4187 --config | --confi | --conf | --con | --co | --c )
4188 $as_echo "$ac_cs_config"; exit ;;
4189 --debug | --debu | --deb | --de | --d | -d )
4190 debug=: ;;
4191 --file | --fil | --fi | --f )
4192 $ac_shift
4193 case $ac_optarg in
4194 *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
4195 '') as_fn_error $? "missing file argument" ;;
4196 esac
4197 as_fn_append CONFIG_FILES " '$ac_optarg'"
4198 ac_need_defaults=false;;
4199 --he | --h | --help | --hel | -h )
4200 $as_echo "$ac_cs_usage"; exit ;;
4201 -q | -quiet | --quiet | --quie | --qui | --qu | --q \
4202 | -silent | --silent | --silen | --sile | --sil | --si | --s)
4203 ac_cs_silent=: ;;
4204
4205 # This is an error.
4206 -*) as_fn_error $? "unrecognized option: \`$1'
4207Try \`$0 --help' for more information." ;;
4208
4209 *) as_fn_append ac_config_targets " $1"
4210 ac_need_defaults=false ;;
4211
4212 esac
4213 shift
4214done
4215
4216ac_configure_extra_args=
4217
4218if $ac_cs_silent; then
4219 exec 6>/dev/null
4220 ac_configure_extra_args="$ac_configure_extra_args --silent"
4221fi
4222
4223_ACEOF
4224cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4225if \$ac_cs_recheck; then
4226 set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
4227 shift
4228 \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
4229 CONFIG_SHELL='$SHELL'
4230 export CONFIG_SHELL
4231 exec "\$@"
4232fi
4233
4234_ACEOF
4235cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4236exec 5>>config.log
4237{
4238 echo
4239 sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
4240## Running $as_me. ##
4241_ASBOX
4242 $as_echo "$ac_log"
4243} >&5
4244
4245_ACEOF
4246cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4247_ACEOF
4248
4249cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4250
4251# Handling of arguments.
4252for ac_config_target in $ac_config_targets
4253do
4254 case $ac_config_target in
4255 "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
4256 "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;;
4257 "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;;
4258 "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;;
4259 "src/libtrace/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtrace/Makefile" ;;
4260 "src/ftee/Makefile") CONFIG_FILES="$CONFIG_FILES src/ftee/Makefile" ;;
4261
4262 *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
4263 esac
4264done
4265
4266
4267# If the user did not use the arguments to specify the items to instantiate,
4268# then the envvar interface is used. Set only those that are not.
4269# We use the long form for the default assignment because of an extremely
4270# bizarre bug on SunOS 4.1.3.
4271if $ac_need_defaults; then
4272 test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
4273fi
4274
4275# Have a temporary directory for convenience. Make it in the build tree
4276# simply because there is no reason against having it here, and in addition,
4277# creating and moving files from /tmp can sometimes cause problems.
4278# Hook for its removal unless debugging.
4279# Note that there is a small window in which the directory will not be cleaned:
4280# after its creation but before its name has been assigned to `$tmp'.
4281$debug ||
4282{
4283 tmp= ac_tmp=
4284 trap 'exit_status=$?
4285 : "${ac_tmp:=$tmp}"
4286 { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
4287' 0
4288 trap 'as_fn_exit 1' 1 2 13 15
4289}
4290# Create a (secure) tmp directory for tmp files.
4291
4292{
4293 tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
4294 test -d "$tmp"
4295} ||
4296{
4297 tmp=./conf$$-$RANDOM
4298 (umask 077 && mkdir "$tmp")
4299} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
4300ac_tmp=$tmp
4301
4302# Set up the scripts for CONFIG_FILES section.
4303# No need to generate them if there are no CONFIG_FILES.
4304# This happens for instance with `./config.status config.h'.
4305if test -n "$CONFIG_FILES"; then
4306
4307
4308ac_cr=`echo X | tr X '\015'`
4309# On cygwin, bash can eat \r inside `` if the user requested igncr.
4310# But we know of no other shell where ac_cr would be empty at this
4311# point, so we can use a bashism as a fallback.
4312if test "x$ac_cr" = x; then
4313 eval ac_cr=\$\'\\r\'
4314fi
4315ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
4316if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
4317 ac_cs_awk_cr='\\r'
4318else
4319 ac_cs_awk_cr=$ac_cr
4320fi
4321
4322echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
4323_ACEOF
4324
4325
4326{
4327 echo "cat >conf$$subs.awk <<_ACEOF" &&
4328 echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
4329 echo "_ACEOF"
4330} >conf$$subs.sh ||
4331 as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
4332ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
4333ac_delim='%!_!# '
4334for ac_last_try in false false false false false :; do
4335 . ./conf$$subs.sh ||
4336 as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
4337
4338 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
4339 if test $ac_delim_n = $ac_delim_num; then
4340 break
4341 elif $ac_last_try; then
4342 as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
4343 else
4344 ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
4345 fi
4346done
4347rm -f conf$$subs.sh
4348
4349cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4350cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
4351_ACEOF
4352sed -n '
4353h
4354s/^/S["/; s/!.*/"]=/
4355p
4356g
4357s/^[^!]*!//
4358:repl
4359t repl
4360s/'"$ac_delim"'$//
4361t delim
4362:nl
4363h
4364s/\(.\{148\}\)..*/\1/
4365t more1
4366s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
4367p
4368n
4369b repl
4370:more1
4371s/["\\]/\\&/g; s/^/"/; s/$/"\\/
4372p
4373g
4374s/.\{148\}//
4375t nl
4376:delim
4377h
4378s/\(.\{148\}\)..*/\1/
4379t more2
4380s/["\\]/\\&/g; s/^/"/; s/$/"/
4381p
4382b
4383:more2
4384s/["\\]/\\&/g; s/^/"/; s/$/"\\/
4385p
4386g
4387s/.\{148\}//
4388t delim
4389' <conf$$subs.awk | sed '
4390/^[^""]/{
4391 N
4392 s/\n//
4393}
4394' >>$CONFIG_STATUS || ac_write_fail=1
4395rm -f conf$$subs.awk
4396cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4397_ACAWK
4398cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
4399 for (key in S) S_is_set[key] = 1
4400 FS = ""
4401
4402}
4403{
4404 line = $ 0
4405 nfields = split(line, field, "@")
4406 substed = 0
4407 len = length(field[1])
4408 for (i = 2; i < nfields; i++) {
4409 key = field[i]
4410 keylen = length(key)
4411 if (S_is_set[key]) {
4412 value = S[key]
4413 line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
4414 len += length(value) + length(field[++i])
4415 substed = 1
4416 } else
4417 len += 1 + keylen
4418 }
4419
4420 print line
4421}
4422
4423_ACAWK
4424_ACEOF
4425cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4426if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
4427 sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
4428else
4429 cat
4430fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
4431 || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
4432_ACEOF
4433
4434# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
4435# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
4436# trailing colons and then remove the whole line if VPATH becomes empty
4437# (actually we leave an empty line to preserve line numbers).
4438if test "x$srcdir" = x.; then
4439 ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
4440h
4441s///
4442s/^/:/
4443s/[ ]*$/:/
4444s/:\$(srcdir):/:/g
4445s/:\${srcdir}:/:/g
4446s/:@srcdir@:/:/g
4447s/^:*//
4448s/:*$//
4449x
4450s/\(=[ ]*\).*/\1/
4451G
4452s/\n//
4453s/^[^=]*=[ ]*$//
4454}'
4455fi
4456
4457cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4458fi # test -n "$CONFIG_FILES"
4459
4460
4461eval set X " :F $CONFIG_FILES "
4462shift
4463for ac_tag
4464do
4465 case $ac_tag in
4466 :[FHLC]) ac_mode=$ac_tag; continue;;
4467 esac
4468 case $ac_mode$ac_tag in
4469 :[FHL]*:*);;
4470 :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
4471 :[FH]-) ac_tag=-:-;;
4472 :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
4473 esac
4474 ac_save_IFS=$IFS
4475 IFS=:
4476 set x $ac_tag
4477 IFS=$ac_save_IFS
4478 shift
4479 ac_file=$1
4480 shift
4481
4482 case $ac_mode in
4483 :L) ac_source=$1;;
4484 :[FH])
4485 ac_file_inputs=
4486 for ac_f
4487 do
4488 case $ac_f in
4489 -) ac_f="$ac_tmp/stdin";;
4490 *) # Look for the file first in the build tree, then in the source tree
4491 # (if the path is not absolute). The absolute path cannot be DOS-style,
4492 # because $ac_f cannot contain `:'.
4493 test -f "$ac_f" ||
4494 case $ac_f in
4495 [\\/$]*) false;;
4496 *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
4497 esac ||
4498 as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
4499 esac
4500 case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
4501 as_fn_append ac_file_inputs " '$ac_f'"
4502 done
4503
4504 # Let's still pretend it is `configure' which instantiates (i.e., don't
4505 # use $as_me), people would be surprised to read:
4506 # /* config.h. Generated by config.status. */
4507 configure_input='Generated from '`
4508 $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
4509 `' by configure.'
4510 if test x"$ac_file" != x-; then
4511 configure_input="$ac_file. $configure_input"
4512 { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
4513$as_echo "$as_me: creating $ac_file" >&6;}
4514 fi
4515 # Neutralize special characters interpreted by sed in replacement strings.
4516 case $configure_input in #(
4517 *\&* | *\|* | *\\* )
4518 ac_sed_conf_input=`$as_echo "$configure_input" |
4519 sed 's/[\\\\&|]/\\\\&/g'`;; #(
4520 *) ac_sed_conf_input=$configure_input;;
4521 esac
4522
4523 case $ac_tag in
4524 *:-:* | *:-) cat >"$ac_tmp/stdin" \
4525 || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
4526 esac
4527 ;;
4528 esac
4529
4530 ac_dir=`$as_dirname -- "$ac_file" ||
4531$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
4532 X"$ac_file" : 'X\(//\)[^/]' \| \
4533 X"$ac_file" : 'X\(//\)$' \| \
4534 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
4535$as_echo X"$ac_file" |
4536 sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
4537 s//\1/
4538 q
4539 }
4540 /^X\(\/\/\)[^/].*/{
4541 s//\1/
4542 q
4543 }
4544 /^X\(\/\/\)$/{
4545 s//\1/
4546 q
4547 }
4548 /^X\(\/\).*/{
4549 s//\1/
4550 q
4551 }
4552 s/.*/./; q'`
4553 as_dir="$ac_dir"; as_fn_mkdir_p
4554 ac_builddir=.
4555
4556case "$ac_dir" in
4557.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
4558*)
4559 ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
4560 # A ".." for each directory in $ac_dir_suffix.
4561 ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
4562 case $ac_top_builddir_sub in
4563 "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
4564 *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
4565 esac ;;
4566esac
4567ac_abs_top_builddir=$ac_pwd
4568ac_abs_builddir=$ac_pwd$ac_dir_suffix
4569# for backward compatibility:
4570ac_top_builddir=$ac_top_build_prefix
4571
4572case $srcdir in
4573 .) # We are building in place.
4574 ac_srcdir=.
4575 ac_top_srcdir=$ac_top_builddir_sub
4576 ac_abs_top_srcdir=$ac_pwd ;;
4577 [\\/]* | ?:[\\/]* ) # Absolute name.
4578 ac_srcdir=$srcdir$ac_dir_suffix;
4579 ac_top_srcdir=$srcdir
4580 ac_abs_top_srcdir=$srcdir ;;
4581 *) # Relative name.
4582 ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
4583 ac_top_srcdir=$ac_top_build_prefix$srcdir
4584 ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
4585esac
4586ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
4587
4588
4589 case $ac_mode in
4590 :F)
4591 #
4592 # CONFIG_FILE
4593 #
4594
4595 case $INSTALL in
4596 [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
4597 *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
4598 esac
4599_ACEOF
4600
4601cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4602# If the template does not know about datarootdir, expand it.
4603# FIXME: This hack should be removed a few years after 2.60.
4604ac_datarootdir_hack=; ac_datarootdir_seen=
4605ac_sed_dataroot='
4606/datarootdir/ {
4607 p
4608 q
4609}
4610/@datadir@/p
4611/@docdir@/p
4612/@infodir@/p
4613/@localedir@/p
4614/@mandir@/p'
4615case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
4616*datarootdir*) ac_datarootdir_seen=yes;;
4617*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
4618 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
4619$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
4620_ACEOF
4621cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4622 ac_datarootdir_hack='
4623 s&@datadir@&$datadir&g
4624 s&@docdir@&$docdir&g
4625 s&@infodir@&$infodir&g
4626 s&@localedir@&$localedir&g
4627 s&@mandir@&$mandir&g
4628 s&\\\${datarootdir}&$datarootdir&g' ;;
4629esac
4630_ACEOF
4631
4632# Neutralize VPATH when `$srcdir' = `.'.
4633# Shell code in configure.ac might set extrasub.
4634# FIXME: do we really want to maintain this feature?
4635cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4636ac_sed_extra="$ac_vpsub
4637$extrasub
4638_ACEOF
4639cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4640:t
4641/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
4642s|@configure_input@|$ac_sed_conf_input|;t t
4643s&@top_builddir@&$ac_top_builddir_sub&;t t
4644s&@top_build_prefix@&$ac_top_build_prefix&;t t
4645s&@srcdir@&$ac_srcdir&;t t
4646s&@abs_srcdir@&$ac_abs_srcdir&;t t
4647s&@top_srcdir@&$ac_top_srcdir&;t t
4648s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
4649s&@builddir@&$ac_builddir&;t t
4650s&@abs_builddir@&$ac_abs_builddir&;t t
4651s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
4652s&@INSTALL@&$ac_INSTALL&;t t
4653$ac_datarootdir_hack
4654"
4655eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
4656 >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
4657
4658test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
4659 { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
4660 { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
4661 "$ac_tmp/out"`; test -z "$ac_out"; } &&
4662 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
4663which seems to be undefined. Please make sure it is defined" >&5
4664$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
4665which seems to be undefined. Please make sure it is defined" >&2;}
4666
4667 rm -f "$ac_tmp/stdin"
4668 case $ac_file in
4669 -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
4670 *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
4671 esac \
4672 || as_fn_error $? "could not create $ac_file" "$LINENO" 5
4673 ;;
4674
4675
4676
4677 esac
4678
4679done # for ac_tag
4680
4681
4682as_fn_exit 0
4683_ACEOF
4684ac_clean_files=$ac_clean_files_save
4685
4686test $ac_write_fail = 0 ||
4687 as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
4688
4689
4690# configure is writing to config.log, and then calls config.status.
4691# config.status does its own redirection, appending to config.log.
4692# Unfortunately, on DOS this fails, as config.log is still kept open
4693# by configure, so config.status won't be able to write to it; its
4694# output is simply discarded. So we exec the FD to /dev/null,
4695# effectively closing config.log, so it can be properly (re)opened and
4696# appended to by config.status. When coming back to configure, we
4697# need to make the FD available again.
4698if test "$no_create" != yes; then
4699 ac_cs_success=:
4700 ac_config_status_args=
4701 test "$silent" = yes &&
4702 ac_config_status_args="$ac_config_status_args --quiet"
4703 exec 5>/dev/null
4704 $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
4705 exec 5>>config.log
4706 # Use ||, not &&, to avoid exiting from the if with $? = 1, which
4707 # would make configure fail if this is the last instruction.
4708 $ac_cs_success || as_fn_exit 1
4709fi
4710if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
4711 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
4712$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
4713fi
4714
4715
4716echo
4717echo "Configuration options:"
4718echo " prefix: $prefix"
4719echo " seccomp: $HAVE_SECCOMP"
4720echo " <linux/seccomp.h>: $HAVE_SECCOMP_H"
4721echo " chroot: $HAVE_CHROOT"
4722echo " bind: $HAVE_BIND"
4723echo
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 000000000..9e34aec20
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,52 @@
1AC_PREREQ([2.68])
2AC_INIT(firejail, 0.9.28, netblue30@yahoo.com, , http://firejail.sourceforge.net)
3AC_CONFIG_SRCDIR([src/firejail/main.c])
4#AC_CONFIG_HEADERS([config.h])
5
6
7AC_PROG_CC
8#AC_PROG_CXX
9AC_PROG_INSTALL
10AC_PROG_RANLIB
11
12HAVE_SECCOMP=""
13AC_ARG_ENABLE([seccomp],
14 AS_HELP_STRING([--disable-seccomp], [Disable seccomp]))
15AS_IF([test "x$enable_seccomp" != "xno"], [
16 HAVE_SECCOMP="-DHAVE_SECCOMP"
17 AC_SUBST(HAVE_SECCOMP)
18])
19
20HAVE_CHROOT=""
21AC_ARG_ENABLE([chroot],
22 AS_HELP_STRING([--disable-chroot], [Disable chroot]))
23AS_IF([test "x$enable_chroot" != "xno"], [
24 HAVE_CHROOT="-DHAVE_CHROOT"
25 AC_SUBST(HAVE_CHROOT)
26])
27
28HAVE_BIND=""
29AC_ARG_ENABLE([bind],
30 AS_HELP_STRING([--disable-bind], [Disable bind]))
31AS_IF([test "x$enable_bind" != "xno"], [
32 HAVE_BIND="-DHAVE_BIND"
33 AC_SUBST(HAVE_BIND)
34])
35
36
37# checking pthread library
38AC_CHECK_LIB([pthread], [main], [], AC_MSG_ERROR([*** POSIX thread support not installed ***]))
39AC_CHECK_HEADER(pthread.h,,AC_MSG_ERROR([*** POSIX thread support not installed ***]))
40AC_CHECK_HEADER([linux/seccomp.h], HAVE_SECCOMP_H="-DHAVE_SECCOMP_H", HAVE_SECCOMP_H="")
41AC_SUBST(HAVE_SECCOMP_H)
42
43AC_OUTPUT(Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/ftee/Makefile)
44
45echo
46echo "Configuration options:"
47echo " prefix: $prefix"
48echo " seccomp: $HAVE_SECCOMP"
49echo " <linux/seccomp.h>: $HAVE_SECCOMP_H"
50echo " chroot: $HAVE_CHROOT"
51echo " bind: $HAVE_BIND"
52echo
diff --git a/etc/audacious.profile b/etc/audacious.profile
new file mode 100644
index 000000000..23f223a29
--- /dev/null
+++ b/etc/audacious.profile
@@ -0,0 +1,8 @@
1# Audacious profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
8
diff --git a/etc/chromium-browser.profile b/etc/chromium-browser.profile
new file mode 100644
index 000000000..4cdc098d1
--- /dev/null
+++ b/etc/chromium-browser.profile
@@ -0,0 +1,3 @@
1# Chromium browser profile
2include /etc/firejail/chromium.profile
3
diff --git a/etc/chromium.profile b/etc/chromium.profile
new file mode 100644
index 000000000..4f6e7e450
--- /dev/null
+++ b/etc/chromium.profile
@@ -0,0 +1,7 @@
1# Chromium browser profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc chromium
5netfilter
6
7
diff --git a/etc/clementine.profile b/etc/clementine.profile
new file mode 100644
index 000000000..dd855cc62
--- /dev/null
+++ b/etc/clementine.profile
@@ -0,0 +1,7 @@
1# Clementine profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
diff --git a/etc/deadbeef.profile b/etc/deadbeef.profile
new file mode 100644
index 000000000..e2f5787cc
--- /dev/null
+++ b/etc/deadbeef.profile
@@ -0,0 +1,8 @@
1# DeaDBeeF profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
8
diff --git a/etc/deluge.profile b/etc/deluge.profile
new file mode 100644
index 000000000..138d0a133
--- /dev/null
+++ b/etc/deluge.profile
@@ -0,0 +1,9 @@
1# deluge profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7netfilter
8noroot
9
diff --git a/etc/disable-common.inc b/etc/disable-common.inc
new file mode 100644
index 000000000..926000411
--- /dev/null
+++ b/etc/disable-common.inc
@@ -0,0 +1,10 @@
1blacklist ${HOME}/.adobe
2blacklist ${HOME}/.macromedia
3blacklist ${HOME}/.mozilla
4blacklist ${HOME}/.icedove
5blacklist ${HOME}/.thunderbird
6blacklist ${HOME}/.config/midori
7blacklist ${HOME}/.config/opera
8blacklist ${HOME}/.config/chromium
9blacklist ${HOME}/.config/google-chrome
10blacklist ${HOME}/.filezilla
diff --git a/etc/disable-mgmt.inc b/etc/disable-mgmt.inc
new file mode 100644
index 000000000..f04619ea0
--- /dev/null
+++ b/etc/disable-mgmt.inc
@@ -0,0 +1,12 @@
1# system directories
2blacklist /sbin
3blacklist /usr/sbin
4
5# system management
6blacklist ${PATH}/umount
7blacklist ${PATH}/mount
8blacklist ${PATH}/fusermount
9blacklist ${PATH}/su
10blacklist ${PATH}/sudo
11blacklist ${PATH}/xinput
12blacklist ${PATH}/strace
diff --git a/etc/disable-secret.inc b/etc/disable-secret.inc
new file mode 100644
index 000000000..8ac1b3792
--- /dev/null
+++ b/etc/disable-secret.inc
@@ -0,0 +1,9 @@
1# HOME directory
2blacklist ${HOME}/.ssh
3tmpfs ${HOME}/.gnome2_private
4blacklist ${HOME}/.gnome2/keyrings
5blacklist ${HOME}/kde4/share/apps/kwallet
6blacklist ${HOME}/kde/share/apps/kwallet
7blacklist ${HOME}/.pki/nssdb
8blacklist ${HOME}/.gnupg
9blacklist ${HOME}/.local/share/recently-used.xbel
diff --git a/etc/dropbox.profile b/etc/dropbox.profile
new file mode 100644
index 000000000..82b54adb1
--- /dev/null
+++ b/etc/dropbox.profile
@@ -0,0 +1,7 @@
1# dropbox profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps
6seccomp
7noroot
diff --git a/etc/empathy.profile b/etc/empathy.profile
new file mode 100644
index 000000000..d24cae528
--- /dev/null
+++ b/etc/empathy.profile
@@ -0,0 +1,6 @@
1# Empathy profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
diff --git a/etc/evince.profile b/etc/evince.profile
new file mode 100644
index 000000000..4d96d5904
--- /dev/null
+++ b/etc/evince.profile
@@ -0,0 +1,8 @@
1# evince profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7netfilter
8noroot
diff --git a/etc/filezilla.profile b/etc/filezilla.profile
new file mode 100644
index 000000000..a54b5a734
--- /dev/null
+++ b/etc/filezilla.profile
@@ -0,0 +1,10 @@
1# FileZilla profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc .filezilla
5caps.drop all
6seccomp
7noroot
8netfilter
9
10
diff --git a/etc/firefox.profile b/etc/firefox.profile
new file mode 100644
index 000000000..dc3489d35
--- /dev/null
+++ b/etc/firefox.profile
@@ -0,0 +1,9 @@
1# Firejail profile for Mozilla Firefox (Iceweasel in Debian)
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc .mozilla
5caps.drop all
6seccomp
7netfilter
8noroot
9
diff --git a/etc/firejail.bash_completion b/etc/firejail.bash_completion
new file mode 100644
index 000000000..50eccf536
--- /dev/null
+++ b/etc/firejail.bash_completion
@@ -0,0 +1,86 @@
1# bash completion for firejail -*- shell-script -*-
2#********************************************************************
3# Script based on completions/configure script in bash-completion package in
4# Debian. The original package is release under GPL v2 license, the webpage is
5# http://bash-completion.alioth.debian.org
6#*******************************************************************
7
8__interfaces(){
9 cut -f 1 -d ':' /proc/net/dev | tail -n +3 | grep -v lo | xargs
10}
11
12
13_firejail()
14{
15 local cur prev words cword split
16 _init_completion -s || return
17
18 case $prev in
19 --help|--version|-debug-caps|--debug-syscalls|--list|--tree|--top|--join|--shutdown)
20 return 0
21 ;;
22 --profile)
23 _filedir
24 return 0
25 ;;
26 --chroot)
27 _filedir -d
28 return 0
29 ;;
30 --cgroup)
31 _filedir -d
32 return 0
33 ;;
34 --tmpfs)
35 _filedir
36 return 0
37 ;;
38 --blacklist)
39 _filedir
40 return 0
41 ;;
42 --read-only)
43 _filedir
44 return 0
45 ;;
46 --bind)
47 _filedir
48 return 0
49 ;;
50 --private)
51 _filedir
52 return 0
53 ;;
54 --shell)
55 _filedir
56 return 0
57 ;;
58 --net)
59 comps=$(__interfaces)
60 COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
61 return 0
62 ;;
63 esac
64
65 $split && return 0
66
67 # if $COMP_CONFIGURE_HINTS is not null, then completions of the form
68 # --option=SETTING will include 'SETTING' as a contextual hint
69 [[ "$cur" != -* ]] && _filedir && return 0
70
71 if [[ -n $COMP_CONFIGURE_HINTS ]]; then
72 COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | \
73 awk '/^ --[A-Za-z]/ { print $1; \
74 if ($2 ~ /--[A-Za-z]/) print $2 }' | sed -e 's/[[,].*//g' )" \
75 -- "$cur" ) )
76 [[ $COMPREPLY == *=* ]] && compopt -o nospace
77 else
78 COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) )
79 [[ $COMPREPLY == *= ]] && compopt -o nospace
80 fi
81
82} &&
83complete -F _firejail firejail
84
85
86
diff --git a/etc/firemon.bash_completion b/etc/firemon.bash_completion
new file mode 100644
index 000000000..befbf2388
--- /dev/null
+++ b/etc/firemon.bash_completion
@@ -0,0 +1,39 @@
1# bash completion for firemon -*- shell-script -*-
2#********************************************************************
3# Script based on completions/configure script in bash-completion package in
4# Debian. The original package is release under GPL v2 license, the webpage is
5# http://bash-completion.alioth.debian.org
6#*******************************************************************
7
8_firemon()
9{
10 local cur prev words cword split
11 _init_completion -s || return
12
13 case $prev in
14 --help|--version)
15 return
16 ;;
17 esac
18
19 $split && return 0
20
21 # if $COMP_CONFIGURE_HINTS is not null, then completions of the form
22 # --option=SETTING will include 'SETTING' as a contextual hint
23 [[ "$cur" != -* ]] && return 0
24
25 if [[ -n $COMP_CONFIGURE_HINTS ]]; then
26 COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | \
27 awk '/^ --[A-Za-z]/ { print $1; \
28 if ($2 ~ /--[A-Za-z]/) print $2 }' | sed -e 's/[[,].*//g' )" \
29 -- "$cur" ) )
30 [[ $COMPREPLY == *=* ]] && compopt -o nospace
31 else
32 COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) )
33 [[ $COMPREPLY == *= ]] && compopt -o nospace
34 fi
35} &&
36complete -F _firemon firemon
37
38
39
diff --git a/etc/generic.profile b/etc/generic.profile
new file mode 100644
index 000000000..83bf59e0a
--- /dev/null
+++ b/etc/generic.profile
@@ -0,0 +1,41 @@
1################################
2# Generic profile based on Firefox profile
3################################
4#include /etc/firejail/disable-mgmt.inc
5# system directories
6blacklist /sbin
7blacklist /usr/sbin
8# system management
9blacklist ${PATH}/umount
10blacklist ${PATH}/mount
11blacklist ${PATH}/fusermount
12blacklist ${PATH}/su
13blacklist ${PATH}/sudo
14blacklist ${PATH}/xinput
15blacklist ${PATH}/strace
16
17#include /etc/firejail/disable-secret.inc
18# HOME directory
19blacklist ${HOME}/.ssh
20tmpfs ${HOME}/.gnome2_private
21blacklist ${HOME}/.gnome2/keyrings
22blacklist ${HOME}/kde4/share/apps/kwallet
23blacklist ${HOME}/kde/share/apps/kwallet
24blacklist ${HOME}/.pki/nssdb
25blacklist ${HOME}/.gnupg
26blacklist ${HOME}/.local/share/recently-used.xbel
27
28blacklist ${HOME}/.adobe
29blacklist ${HOME}/.macromedia
30blacklist ${HOME}/.mozilla
31blacklist ${HOME}/.icedove
32blacklist ${HOME}/.thunderbird
33blacklist ${HOME}/.config/opera
34blacklist ${HOME}/.config/chromium
35blacklist ${HOME}/.config/google-chrome
36
37caps.drop all
38seccomp
39netfilter
40noroot
41
diff --git a/etc/gnome-mplayer.profile b/etc/gnome-mplayer.profile
new file mode 100644
index 000000000..b69cf3a57
--- /dev/null
+++ b/etc/gnome-mplayer.profile
@@ -0,0 +1,7 @@
1# GNOME MPlayer profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
diff --git a/etc/icecat.profile b/etc/icecat.profile
new file mode 100644
index 000000000..25d426ad2
--- /dev/null
+++ b/etc/icecat.profile
@@ -0,0 +1,2 @@
1# Firejail profile for GNU Icecat
2include /etc/firejail/firefox.profile
diff --git a/etc/icedove.profile b/etc/icedove.profile
new file mode 100644
index 000000000..057e0c9ef
--- /dev/null
+++ b/etc/icedove.profile
@@ -0,0 +1,3 @@
1# Firejail profile for Mozilla Thunderbird (Icedove in Debian)
2include /etc/firejail/thunderbird.profile
3
diff --git a/etc/iceweasel.profile b/etc/iceweasel.profile
new file mode 100644
index 000000000..e9b32846a
--- /dev/null
+++ b/etc/iceweasel.profile
@@ -0,0 +1,2 @@
1# Firejail profile for Mozilla Firefox (Iceweasel in Debian)
2include /etc/firejail/firefox.profile
diff --git a/etc/login.users b/etc/login.users
new file mode 100644
index 000000000..5d5969091
--- /dev/null
+++ b/etc/login.users
@@ -0,0 +1,14 @@
1# /etc/firejail/login.users - restricted user shell configuration
2#
3# Each user entry consists of a user name and firejail
4# program arguments:
5#
6# user name: arguments
7#
8# For example:
9#
10# netblue:--debug --net=none
11#
12# The extra arguments are inserted into program command line if firejail
13# was started as a login shell.
14
diff --git a/etc/midori.profile b/etc/midori.profile
new file mode 100644
index 000000000..5479ba172
--- /dev/null
+++ b/etc/midori.profile
@@ -0,0 +1,9 @@
1# Midory browser profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc midori
5caps.drop all
6seccomp
7netfilter
8noroot
9
diff --git a/etc/opera.profile b/etc/opera.profile
new file mode 100644
index 000000000..852f10719
--- /dev/null
+++ b/etc/opera.profile
@@ -0,0 +1,8 @@
1# Chromium browser profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc opera
5netfilter
6noroot
7
8
diff --git a/etc/pidgin.profile b/etc/pidgin.profile
new file mode 100644
index 000000000..6f5594919
--- /dev/null
+++ b/etc/pidgin.profile
@@ -0,0 +1,7 @@
1# Pidgin profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
diff --git a/etc/qbittorrent.profile b/etc/qbittorrent.profile
new file mode 100644
index 000000000..f85dfc994
--- /dev/null
+++ b/etc/qbittorrent.profile
@@ -0,0 +1,9 @@
1# abittorrent profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7netfilter
8noroot
9
diff --git a/etc/quassel.profile b/etc/quassel.profile
new file mode 100644
index 000000000..a2057ad01
--- /dev/null
+++ b/etc/quassel.profile
@@ -0,0 +1,7 @@
1# Quassel IRC profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
diff --git a/etc/rhythmbox.profile b/etc/rhythmbox.profile
new file mode 100644
index 000000000..42d4dc0fa
--- /dev/null
+++ b/etc/rhythmbox.profile
@@ -0,0 +1,7 @@
1# Rhythmbox profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
diff --git a/etc/server.profile b/etc/server.profile
new file mode 100644
index 000000000..bb15774fa
--- /dev/null
+++ b/etc/server.profile
@@ -0,0 +1,6 @@
1# generic server profile
2include /etc/firejail/disable-mgmt.inc sbin
3private
4private-dev
5seccomp
6
diff --git a/etc/thunderbird.profile b/etc/thunderbird.profile
new file mode 100644
index 000000000..8b63a6ec5
--- /dev/null
+++ b/etc/thunderbird.profile
@@ -0,0 +1,9 @@
1# Firejail profile for Mozilla Thunderbird (Icedove in Debian)
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc thunderbird icedove
5caps.drop all
6seccomp
7netfilter
8noroot
9
diff --git a/etc/totem.profile b/etc/totem.profile
new file mode 100644
index 000000000..50115deb5
--- /dev/null
+++ b/etc/totem.profile
@@ -0,0 +1,7 @@
1# Totem profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
diff --git a/etc/transmission-gtk.profile b/etc/transmission-gtk.profile
new file mode 100644
index 000000000..9ccece285
--- /dev/null
+++ b/etc/transmission-gtk.profile
@@ -0,0 +1,9 @@
1# transmission-gtk profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7netfilter
8noroot
9
diff --git a/etc/transmission-qt.profile b/etc/transmission-qt.profile
new file mode 100644
index 000000000..65a045f8e
--- /dev/null
+++ b/etc/transmission-qt.profile
@@ -0,0 +1,9 @@
1# transmission-qt profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7netfilter
8noroot
9
diff --git a/etc/vlc.profile b/etc/vlc.profile
new file mode 100644
index 000000000..76e1395f9
--- /dev/null
+++ b/etc/vlc.profile
@@ -0,0 +1,7 @@
1# VLC profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
diff --git a/etc/xchat.profile b/etc/xchat.profile
new file mode 100644
index 000000000..b8d8cb1e2
--- /dev/null
+++ b/etc/xchat.profile
@@ -0,0 +1,7 @@
1# XChat profile
2include /etc/firejail/disable-mgmt.inc
3include /etc/firejail/disable-secret.inc
4include /etc/firejail/disable-common.inc
5caps.drop all
6seccomp
7noroot
diff --git a/install.sh b/install.sh
new file mode 100755
index 000000000..b3ddf0423
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,2 @@
1#!/bin/bash
2echo "installing..."
diff --git a/mkdeb.sh b/mkdeb.sh
new file mode 100755
index 000000000..159649975
--- /dev/null
+++ b/mkdeb.sh
@@ -0,0 +1,96 @@
1#!/bin/bash
2
3# a code archive should already be available
4
5TOP=`pwd`
6CODE_ARCHIVE="$1-$2.tar.bz2"
7CODE_DIR="$1-$2"
8INSTALL_DIR=$TOP
9INSTALL_DIR+="/debian/usr"
10DEBIAN_CTRL_DIR=$TOP
11DEBIAN_CTRL_DIR+="/debian/DEBIAN"
12
13echo "*****************************************"
14echo "code archive: $CODE_ARCHIVE"
15echo "code directory: $CODE_DIR"
16echo "install directory: $INSTALL_DIR"
17echo "debian control directory: $DEBIAN_CTRL_DIR"
18echo "*****************************************"
19tar -xjvf $CODE_ARCHIVE
20mkdir -p $INSTALL_DIR
21cd $CODE_DIR
22./configure --prefix=$INSTALL_DIR
23make && make install
24
25# second compilation - the path to libtrace.so is hardcoded in firejail executable
26# pointing according to --prefix=$INSTALL_DIR. We need it to point to /usr/lib
27make distclean
28./configure --prefix=/usr
29make
30# install firejail executable in $TOP/$INSTALL_DIR
31strip src/firejail/firejail
32install -c -m 0755 src/firejail/firejail $INSTALL_DIR/bin/.
33chmod u+s $INSTALL_DIR/bin/firejail
34
35
36cd ..
37echo "*****************************************"
38SIZE=`du -s debian/usr`
39echo "install size $SIZE"
40echo "*****************************************"
41
42mv $INSTALL_DIR/share/doc/firejail/RELNOTES $INSTALL_DIR/share/doc/firejail/changelog.Debian
43gzip -9 $INSTALL_DIR/share/doc/firejail/changelog.Debian
44rm $INSTALL_DIR/share/doc/firejail/COPYING
45cp platform/debian/copyright $INSTALL_DIR/share/doc/firejail/.
46mkdir -p $DEBIAN_CTRL_DIR
47sed "s/FIREJAILVER/$2/g" platform/debian/control > $DEBIAN_CTRL_DIR/control
48mkdir -p debian/etc/firejail
49cp etc/chromium.profile debian/etc/firejail/.
50cp etc/chromium-browser.profile debian/etc/firejail/.
51cp etc/disable-mgmt.inc debian/etc/firejail/.
52cp etc/disable-secret.inc debian/etc/firejail/.
53cp etc/dropbox.profile debian/etc/firejail/.
54cp etc/evince.profile debian/etc/firejail/.
55cp etc/firefox.profile debian/etc/firejail/.
56cp etc/iceweasel.profile debian/etc/firejail/.
57cp etc/icedove.profile debian/etc/firejail/.
58cp etc/login* debian/etc/firejail/.
59cp etc/midori.profile debian/etc/firejail/.
60cp etc/opera.profile debian/etc/firejail/.
61cp etc/thunderbird.profile debian/etc/firejail/.
62cp etc/transmission-gtk.profile debian/etc/firejail/.
63cp etc/transmission-qt.profile debian/etc/firejail/.
64cp etc/vlc.profile debian/etc/firejail/.
65cp etc/audacious.profile debian/etc/firejail/.
66cp etc/clementine.profile debian/etc/firejail/.
67cp etc/gnome-mplayer.profile debian/etc/firejail/.
68cp etc/rhythmbox.profile debian/etc/firejail/.
69cp etc/totem.profile debian/etc/firejail/.
70cp etc/deluge.profile debian/etc/firejail/.
71cp etc/qbittorrent.profile debian/etc/firejail/.
72cp etc/generic.profile debian/etc/firejail/.
73cp etc/xchat.profile debian/etc/firejail/.
74cp etc/server.profile debian/etc/firejail/.
75cp etc/quassel.profile debian/etc/firejail/.
76cp etc/pidgin.profile debian/etc/firejail/.
77cp etc/filezilla.profile debian/etc/firejail/.
78cp etc/empathy.profile debian/etc/firejail/.
79cp etc/disable-common.inc debian/etc/firejail/.
80cp etc/deadbeef.profile debian/etc/firejail/.
81cp etc/icecat.profile debian/etc/firejail/.
82cp platform/debian/conffiles $DEBIAN_CTRL_DIR/.
83find ./debian -type d | xargs chmod 755
84dpkg-deb --build debian
85lintian debian.deb
86mv debian.deb firejail_$2_1_amd64.deb
87echo "if building a 32bit package, rename the deb file manually"
88rm -fr debian
89rm -fr $CODE_DIR
90
91
92
93
94
95
96
diff --git a/mkman.sh b/mkman.sh
new file mode 100755
index 000000000..f2a5ef3c6
--- /dev/null
+++ b/mkman.sh
@@ -0,0 +1,7 @@
1#!/bin/bash
2
3sed "s/VERSION/$1/g" $2 > $3
4MONTH=`date +%b`
5sed -i "s/MONTH/$MONTH/g" $3
6YEAR=`date +%Y`
7sed -i "s/YEAR/$YEAR/g" $3
diff --git a/platform/debian/conffiles b/platform/debian/conffiles
new file mode 100644
index 000000000..6f55cc021
--- /dev/null
+++ b/platform/debian/conffiles
@@ -0,0 +1,33 @@
1/etc/firejail/evince.profile
2/etc/firejail/disable-secret.inc
3/etc/firejail/chromium.profile
4/etc/firejail/midori.profile
5/etc/firejail/icedove.profile
6/etc/firejail/iceweasel.profile
7/etc/firejail/dropbox.profile
8/etc/firejail/login.users
9/etc/firejail/chromium-browser.profile
10/etc/firejail/disable-mgmt.inc
11/etc/firejail/firefox.profile
12/etc/firejail/opera.profile
13/etc/firejail/thunderbird.profile
14/etc/firejail/transmission-gtk.profile
15/etc/firejail/transmission-qt.profile
16/etc/firejail/vlc.profile
17/etc/firejail/audacious.profile
18/etc/firejail/clementine.profile
19/etc/firejail/gnome-mplayer.profile
20/etc/firejail/rhythmbox.profile
21/etc/firejail/totem.profile
22/etc/firejail/deluge.profile
23/etc/firejail/qbittorrent.profile
24/etc/firejail/generic.profile
25/etc/firejail/xchat.profile
26/etc/firejail/server.profile
27/etc/firejail/quassel.profile
28/etc/firejail/pidgin.profile
29/etc/firejail/filezilla.profile
30/etc/firejail/empathy.profile
31/etc/firejail/disable-common.inc
32/etc/firejail/deadbeef.profile
33/etc/firejail/icecat.profile
diff --git a/platform/debian/control b/platform/debian/control
new file mode 100644
index 000000000..18d857c36
--- /dev/null
+++ b/platform/debian/control
@@ -0,0 +1,20 @@
1Package: firejail
2Version: FIREJAILVER-1
3Architecture: amd64
4Maintainer: netblue30 <netblue30@yahoo.com>
5Installed-Size: 272
6Depends: libc6
7Section: admin
8Priority: extra
9Homepage: http://firejail.sourceforge.net
10Description: Linux namepaces sandbox program.
11 Firejail is a SUID sandbox program that reduces the risk of security
12 breaches by restricting the running environment of untrusted applications
13 using Linux namespaces and seccmp-bpf. It includes sandbox profiles for
14 Iceweasel/Mozilla Firefox, Chromium, Midori, Opera, Evince, Transmission
15 and VLC.
16 .
17 Firejail also expands the restricted shell facility found in bash by
18 adding Linux namespace support. It also supports sandboxing SSH users
19 upon login.
20
diff --git a/platform/debian/copyright b/platform/debian/copyright
new file mode 100644
index 000000000..7d8d0a2c7
--- /dev/null
+++ b/platform/debian/copyright
@@ -0,0 +1,30 @@
1
2This is the Debian/Ubuntu prepackaged version of firejail.
3
4 Firejail is a sandbox program that reduces the risk of security breaches
5 by restricting the running environment of untrusted applications using
6 Linux namespaces. It currently implements hostname, filesystem, PID, IPC
7 and networking stack isolation, and it runs on any recent Linux system. It
8 includes a sandbox profile for Mozilla Firefox.
9
10 Copyright (C) 2014,2015 Firejail Authors (see README file for more details)
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License along
23 with this program; if not, write to the Free Software Foundation, Inc., 51
24 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
25
26The complete text of the GNU General Public License can be found
27in /usr/share/common-licenses/GPL-2.
28
29Homepage: http://firejail.sourceforge.net.
30
diff --git a/platform/rpm/mkrpm.sh b/platform/rpm/mkrpm.sh
new file mode 100755
index 000000000..adac1de46
--- /dev/null
+++ b/platform/rpm/mkrpm.sh
@@ -0,0 +1,256 @@
1#!/bin/bash
2VERSION="0.9.26"
3rm -fr ~/rpmbuild
4rm -f firejail-$VERSION-1.x86_64.rpm
5
6mkdir -p ~/rpmbuild/{RPMS,SRPMS,BUILD,SOURCES,SPECS,tmp}
7cat <<EOF >~/.rpmmacros
8%_topdir %(echo $HOME)/rpmbuild
9%_tmppath %{_topdir}/tmp
10EOF
11
12cd ~/rpmbuild
13echo "building directory tree"
14
15mkdir -p firejail-$VERSION/usr/bin
16install -m 755 /usr/bin/firejail firejail-$VERSION/usr/bin/.
17install -m 755 /usr/bin/firemon firejail-$VERSION/usr/bin/.
18
19mkdir -p firejail-$VERSION/usr/lib/firejail
20install -m 644 /usr/lib/firejail/libtrace.so firejail-$VERSION/usr/lib/firejail/.
21install -m 755 /usr/lib/firejail/ftee firejail-$VERSION/usr/lib/firejail/.
22
23mkdir -p firejail-$VERSION/usr/share/man/man1
24install -m 644 /usr/share/man/man1/firejail.1.gz firejail-$VERSION/usr/share/man/man1/.
25install -m 644 /usr/share/man/man1/firemon.1.gz firejail-$VERSION/usr/share/man/man1/.
26
27mkdir -p firejail-$VERSION/usr/share/man/man5
28install -m 644 /usr/share/man/man5/firejail-profile.5.gz firejail-$VERSION/usr/share/man/man5/.
29
30mkdir -p firejail-$VERSION/usr/share/doc/packages/firejail
31install -m 644 /usr/share/doc/firejail/COPYING firejail-$VERSION/usr/share/doc/packages/firejail/.
32install -m 644 /usr/share/doc/firejail/README firejail-$VERSION/usr/share/doc/packages/firejail/.
33install -m 644 /usr/share/doc/firejail/RELNOTES firejail-$VERSION/usr/share/doc/packages/firejail/.
34
35mkdir -p firejail-$VERSION/etc/firejail
36install -m 644 /etc/firejail/chromium-browser.profile firejail-$VERSION/etc/firejail/chromium-browser.profile
37install -m 644 /etc/firejail/chromium.profile firejail-$VERSION/etc/firejail/chromium.profile
38install -m 644 /etc/firejail/dropbox.profile firejail-$VERSION/etc/firejail/dropbox.profile
39install -m 644 /etc/firejail/disable-secret.inc firejail-$VERSION/etc/firejail/disable-secret.inc
40install -m 644 /etc/firejail/disable-mgmt.inc firejail-$VERSION/etc/firejail/disable-mgmt.inc
41install -m 644 /etc/firejail/evince.profile firejail-$VERSION/etc/firejail/evince.profile
42install -m 644 /etc/firejail/firefox.profile firejail-$VERSION/etc/firejail/firefox.profile
43install -m 644 /etc/firejail/icedove.profile firejail-$VERSION/etc/firejail/icedove.profile
44install -m 644 /etc/firejail/iceweasel.profile firejail-$VERSION/etc/firejail/iceweasel.profile
45install -m 644 /etc/firejail/midori.profile firejail-$VERSION/etc/firejail/midori.profile
46install -m 644 /etc/firejail/thunderbird.profile firejail-$VERSION/etc/firejail/thunderbird.profile
47install -m 644 /etc/firejail/opera.profile firejail-$VERSION/etc/firejail/opera.profile
48install -m 644 /etc/firejail/transmission-gtk.profile firejail-$VERSION/etc/firejail/transmission-gtk.profile
49install -m 644 /etc/firejail/transmission-qt.profile firejail-$VERSION/etc/firejail/transmission-qt.profile
50install -m 644 /etc/firejail/vlc.profile firejail-$VERSION/etc/firejail/vlc.profile
51install -m 644 /etc/firejail/audacious.profile firejail-$VERSION/etc/firejail/audacious.profile
52install -m 644 /etc/firejail/clementine.profile firejail-$VERSION/etc/firejail/clementine.profile
53install -m 644 /etc/firejail/gnome-mplayer.profile firejail-$VERSION/etc/firejail/gnome-mplayer.profile
54install -m 644 /etc/firejail/rhythmbox.profile firejail-$VERSION/etc/firejail/rhythmbox.profile
55install -m 644 /etc/firejail/totem.profile firejail-$VERSION/etc/firejail/totem.profile
56install -m 644 /etc/firejail/deluge.profile firejail-$VERSION/etc/firejail/deluge.profile
57install -m 644 /etc/firejail/qbittorrent.profile firejail-$VERSION/etc/firejail/qbittorrent.profile
58install -m 644 /etc/firejail/generic.profile firejail-$VERSION/etc/firejail/generic.profile
59install -m 644 /etc/firejail/login.users firejail-$VERSION/etc/firejail/login.users
60
61mkdir -p firejail-$VERSION/usr/share/bash-completion/completions
62install -m 644 /usr/share/bash-completion/completions/firejail firejail-$VERSION/usr/share/bash-completion/completions/.
63
64echo "building tar.gz archive"
65tar -czvf firejail-$VERSION.tar.gz firejail-$VERSION
66
67cp firejail-$VERSION.tar.gz SOURCES/.
68
69echo "building config spec"
70cat <<EOF > SPECS/firejail.spec
71%define __spec_install_post %{nil}
72%define debug_package %{nil}
73%define __os_install_post %{_dbpath}/brp-compress
74
75Summary: Linux namepaces sandbox program
76Name: firejail
77Version: $VERSION
78Release: 1
79License: GPL+
80Group: Development/Tools
81SOURCE0 : %{name}-%{version}.tar.gz
82URL: http://firejail.sourceforege.net
83
84BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
85
86%description
87Firejail is a SUID sandbox program that reduces the risk of security
88breaches by restricting the running environment of untrusted applications
89using Linux namespaces. It includes a sandbox profile for Mozilla Firefox.
90
91%prep
92%setup -q
93
94%build
95
96%install
97rm -rf %{buildroot}
98mkdir -p %{buildroot}
99
100cp -a * %{buildroot}
101
102
103%clean
104rm -rf %{buildroot}
105
106
107%files
108%defattr(-,root,root,-)
109%config(noreplace) %{_sysconfdir}/%{name}/chromium-browser.profile
110%config(noreplace) %{_sysconfdir}/%{name}/chromium.profile
111%config(noreplace) %{_sysconfdir}/%{name}/disable-mgmt.inc
112%config(noreplace) %{_sysconfdir}/%{name}/disable-secret.inc
113%config(noreplace) %{_sysconfdir}/%{name}/dropbox.profile
114%config(noreplace) %{_sysconfdir}/%{name}/evince.profile
115%config(noreplace) %{_sysconfdir}/%{name}/firefox.profile
116%config(noreplace) %{_sysconfdir}/%{name}/icedove.profile
117%config(noreplace) %{_sysconfdir}/%{name}/iceweasel.profile
118%config(noreplace) %{_sysconfdir}/%{name}/login.users
119%config(noreplace) %{_sysconfdir}/%{name}/midori.profile
120%config(noreplace) %{_sysconfdir}/%{name}/opera.profile
121%config(noreplace) %{_sysconfdir}/%{name}/thunderbird.profile
122%config(noreplace) %{_sysconfdir}/%{name}/transmission-gtk.profile
123%config(noreplace) %{_sysconfdir}/%{name}/transmission-qt.profile
124%config(noreplace) %{_sysconfdir}/%{name}/vlc.profile
125%config(noreplace) %{_sysconfdir}/%{name}/audacious.profile
126%config(noreplace) %{_sysconfdir}/%{name}/clementine.profile
127%config(noreplace) %{_sysconfdir}/%{name}/gnome-mplayer.profile
128%config(noreplace) %{_sysconfdir}/%{name}/rhythmbox.profile
129%config(noreplace) %{_sysconfdir}/%{name}/totem.profile
130%config(noreplace) %{_sysconfdir}/%{name}/deluge.profile
131%config(noreplace) %{_sysconfdir}/%{name}/qbittorrent.profile
132%config(noreplace) %{_sysconfdir}/%{name}/generic.profile
133
134/usr/bin/firejail
135/usr/bin/firemon
136/usr/lib/firejail/libtrace.so
137/usr/lib/firejail/ftee
138/usr/share/doc/packages/firejail/COPYING
139/usr/share/doc/packages/firejail/README
140/usr/share/doc/packages/firejail/RELNOTES
141/usr/share/man/man1/firejail.1.gz
142/usr/share/man/man1/firemon.1.gz
143/usr/share/man/man5/firejail-profile.5.gz
144/usr/share/bash-completion/completions/firejail
145
146%post
147chmod u+s /usr/bin/firejail
148
149%changelog
150* Thu Apr 30 2015 netblue30 <netblue30@yahoo.com> 0.9.26-1
151 - private dev directory
152 - private.keep option for whitelisting home files in a new private directory
153 - user namespaces support, noroot option
154 - added Deluge and qBittorent profiles
155 - bugfixes
156
157* Sun Apr 5 2015 netblue30 <netblue30@yahoo.com> 0.9.24-1
158 - whitelist and blacklist seccomp filters
159 - doubledash option
160 - --shell=none support
161 - netfilter file support in profile files
162 - dns server support in profile files
163 - added --dns.print option
164 - added default profiles for Audoacious, Clementine, Rhythmbox and Totem.
165 - added --caps.drop=all in default profiles
166 - new syscalls in default seccomp filter: sysfs, sysctl, adjtimex, kcmp
167 - clock_adjtime, lookup_dcookie, perf_event_open, fanotify_init
168 - Bugfix: using /proc/sys/kernel/pid_max for the max number of pids
169 - two build patches from Reiner Herman (tickets 11, 12)
170 - man page patch from Reiner Herman (ticket 13)
171 - output patch (ticket 15) from sshirokov
172
173* Mon Mar 9 2015 netblue30 <netblue30@yahoo.com> 0.9.22-1
174 - Replaced --noip option with --ip=none
175 - Container stdout logging and log rotation
176 - Added process_vm_readv, process_vm_writev and mknod to
177 default seccomp blacklist
178 - Added CAP_MKNOD to default caps blacklist
179 - Blacklist and whitelist custom Linux capabilities filters
180 - macvlan device driver support for --net option
181 - DNS server support, --dns option
182 - Netfilter support
183 - Monitor network statistics, --netstats option
184 - Added profile for Mozilla Thunderbird/Icedove
185 - --overlay support for Linux kernels 3.18+
186 - Bugfix: preserve .Xauthority file in private mode (test with ssh -X)
187 - Bugfix: check uid/gid for cgroup
188
189* Fri Feb 6 2015 netblue30 <netblue30@yahoo.com> 0.9.20-1
190 - utmp, btmp and wtmp enhancements
191 - create empty /var/log/wtmp and /var/log/btmp files in sandbox
192 - generate a new /var/run/utmp file in sandbox
193 - CPU affinity, --cpu option
194 - Linux control groups support, --cgroup option
195 - Opera web browser support
196 - VLC support
197 - Added "empty" attribute to seccomp command to remove the default
198 - syscall list form seccomp blacklist
199 - Added --nogroups option to disable supplementary groups for regular
200 - users. root user always runs without supplementary groups.
201 - firemon enhancements
202 - display the command that started the sandbox
203 - added --caps option to display capabilities for all sandboxes
204 - added --cgroup option to display the control groups for all sandboxes
205 - added --cpu option to display CPU affinity for all sandboxes
206 - added --seccomp option to display seccomp setting for all sandboxes
207 - New compile time options: --disable-chroot, --disable-bind
208 - bugfixes
209
210* Sat Dec 27 2014 netblue30 <netblue30@yahoo.com> 0.9.18-1
211 - Support for tracing system, setuid, setgid, setfsuid, setfsgid syscalls
212 - Support for tracing setreuid, setregid, setresuid, setresguid syscalls
213 - Added profiles for transmission-gtk and transmission-qt
214 - bugfixes
215
216* Tue Nov 4 2014 netblue30 <netblue30@yahoo.com> 0.9.16-1
217 - Configurable private home directory
218 - Configurable default user shell
219 - Software configuration support for --docdir and DESTDIR
220 - Profile file support for include, caps, seccomp and private keywords
221 - Dropbox profile file
222 - Linux capabilities and seccomp filters enabled by default for Firefox,
223 Midori, Evince and Dropbox
224 - bugfixes
225
226* Wed Oct 8 2014 netblue30 <netblue30@yahoo.com> 0.9.14-1
227 - Linux capabilities and seccomp filters are automatically enabled in
228 chroot mode (--chroot option) if the sandbox is started as regular
229 user
230 - Added support for user defined seccomp blacklists
231 - Added syscall trace support
232 - Added --tmpfs option
233 - Added --balcklist option
234 - Added --read-only option
235 - Added --bind option
236 - Logging enhancements
237 - --overlay option was reactivated
238 - Added firemon support to print the ARP table for each sandbox
239 - Added firemon support to print the route table for each sandbox
240 - Added firemon support to print interface information for each sandbox
241 - bugfixes
242
243* Tue Sep 16 2014 netblue30 <netblue30@yahoo.com> 0.9.12-1
244 - Added capabilities support
245 - Added support for CentOS 7
246 - bugfixes
247
248EOF
249
250echo "building rpm"
251rpmbuild -ba SPECS/firejail.spec
252rpm -qpl RPMS/x86_64/firejail-$VERSION-1.x86_64.rpm
253cd ..
254rm -f firejail-$VERSION-1.x86_64.rpm
255cp rpmbuild/RPMS/x86_64/firejail-$VERSION-1.x86_64.rpm .
256
diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in
new file mode 100644
index 000000000..1f7b563c4
--- /dev/null
+++ b/src/firejail/Makefile.in
@@ -0,0 +1,28 @@
1all: firejail
2
3PREFIX=@prefix@
4VERSION=@PACKAGE_VERSION@
5NAME=@PACKAGE_NAME@
6HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
7HAVE_SECCOMP=@HAVE_SECCOMP@
8HAVE_CHROOT=@HAVE_CHROOT@
9HAVE_BIND=@HAVE_BIND@
10
11H_FILE_LIST = $(wildcard *.[h])
12C_FILE_LIST = $(wildcard *.c)
13OBJS = $(C_FILE_LIST:.c=.o)
14BINOBJS = $(foreach file, $(OBJS), $file)
15CFLAGS += -ggdb -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(PREFIX)"' $(HAVE_SECCOMP) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_BIND) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
16LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
17
18%.o : %.c $(H_FILE_LIST)
19 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
20
21firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o
22 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o ../lib/common.o $(LIBS)
23
24clean:; rm -f *.o firejail firejail.1 firejail.1.gz
25
26distclean: clean
27 rm -fr Makefile
28
diff --git a/src/firejail/arg-checking.txt b/src/firejail/arg-checking.txt
new file mode 100644
index 000000000..c1ab2cb21
--- /dev/null
+++ b/src/firejail/arg-checking.txt
@@ -0,0 +1,85 @@
1arg checking:
2
31. --output=filename
4 - not supported in profiles
5 - checking no "..",
6 - checking no link,
7 - checking no dir,
8 - checking same permissions,
9 - checking no hard links
10 - unit test
11
122. --chroot=dirname
13 - not supported in profiles
14 - expand "~"
15 - checking no "..",
16 - checking is dir,
17 - checking no link
18 - checking directory structure
19 - unit test
20
213. --bind=dirname1,dirname2, --bind=filename1,filenam2
22 - supported in profiles
23 - accepted only when running as root
24 - checking string chars
25 - checking no ".."
26 - unit test non root
27
284. --tmpfs=dirname
29 - supported in profiles
30 - checking string chars
31 - checking no ".."
32 - unit test
33
345. --blacklist=filename, --blacklist=dirname
35 - supported in profiles
36 - checking string chars
37 - checking no ".."
38 - unit test
39
406. --read-only=filename, --read-only=dirname
41 - supported in profiles
42 - checking string chars
43 - checking no ".."
44 - unit test
45
467. --profile=filename
47 - check access as real GID/UID
48 - checking no dir
49 - checking no link
50 - checking no ".."
51 - unit test
52
538. --private=dirname
54 - supported in profiles
55 - expand "~"
56 - check is dir
57 - check no link
58 - checking no ".."
59 - check same owner
60 - unit test
61
629. --private.keep=filelist
63 - supported in profiles
64 - checking no ".."
65 - checking file found
66 - checking same owner
67 - checking no link
68 - unit test
69
7010. --netfilter=filename
71 - supported in profiles
72 - check access as real GID/UID
73 - checking no dir
74 - checking no link
75 - checking no ".."
76 - unit test
77
7811. --shell=filename
79 - not supported in profiles
80 - check access as real GID/UID
81 - checking no dir
82 - checking no link
83 - checking no ".."
84 - unit test
85
diff --git a/src/firejail/arp.c b/src/firejail/arp.c
new file mode 100644
index 000000000..37f8716e7
--- /dev/null
+++ b/src/firejail/arp.c
@@ -0,0 +1,474 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/socket.h>
22#include <sys/ioctl.h>
23#include <linux/if_ether.h> //TCP/IP Protocol Suite for Linux
24#include <net/if.h>
25#include <netinet/in.h>
26#include <linux/ip.h>
27#include <linux/udp.h>
28#include <linux/tcp.h>
29#include <linux/if_packet.h>
30
31typedef struct arp_hdr_t {
32 uint16_t htype;
33 uint16_t ptype;
34 uint8_t hlen;
35 uint8_t plen;
36 uint16_t opcode;
37 uint8_t sender_mac[6];
38 uint8_t sender_ip[4];
39 uint8_t target_mac[6];
40 uint8_t target_ip[4];
41} ArpHdr;
42
43// returns 0 if the address is not in use, -1 otherwise
44int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
45 if (strlen(dev) > IFNAMSIZ) {
46 fprintf(stderr, "Error: invalid network device name %s\n", dev);
47 exit(1);
48 }
49
50 if (arg_debug)
51 printf("Trying %d.%d.%d.%d ...\n", PRINT_IP(destaddr));
52
53 // find interface address
54 int sock;
55 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
56 errExit("socket");
57
58 srcaddr = htonl(srcaddr);
59 destaddr = htonl(destaddr);
60
61 // Find interface MAC address
62 struct ifreq ifr;
63 memset(&ifr, 0, sizeof (ifr));
64 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
65 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
66 errExit("ioctl");
67 close(sock);
68
69 // configure layer2 socket address information
70 struct sockaddr_ll addr;
71 memset(&addr, 0, sizeof(addr));
72 if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
73 errExit("if_nametoindex");
74 addr.sll_family = AF_PACKET;
75 memcpy (addr.sll_addr, ifr.ifr_hwaddr.sa_data, 6);
76 addr.sll_halen = htons(6);
77
78 // build the arp packet header
79 ArpHdr hdr;
80 memset(&hdr, 0, sizeof(hdr));
81 hdr.htype = htons(1);
82 hdr.ptype = htons(ETH_P_IP);
83 hdr.hlen = 6;
84 hdr.plen = 4;
85 hdr.opcode = htons(1); //ARPOP_REQUEST
86 memcpy(hdr.sender_mac, ifr.ifr_hwaddr.sa_data, 6);
87 memcpy(hdr.sender_ip, (uint8_t *)&srcaddr, 4);
88 memcpy(hdr.target_ip, (uint8_t *)&destaddr, 4);
89
90 // buiild ethernet frame
91 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
92 memset(frame, 0, sizeof(frame));
93 frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
94 memcpy(frame + 6, ifr.ifr_hwaddr.sa_data, 6);
95 frame[12] = ETH_P_ARP / 256;
96 frame[13] = ETH_P_ARP % 256;
97 memcpy (frame + 14, &hdr, sizeof(hdr));
98
99 // open layer2 socket
100 if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
101 errExit("socket");
102
103 int len;
104 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
105 errExit("send");
106 fflush(0);
107
108 // wait not more than one second for an answer
109 fd_set fds;
110 FD_ZERO(&fds);
111 FD_SET(sock, &fds);
112 int maxfd = sock;
113 struct timeval ts;
114 ts.tv_sec = 1; // 1 second wait time
115 ts.tv_usec = 0;
116 while (1) {
117 int nready = select(maxfd + 1, &fds, (fd_set *) 0, (fd_set *) 0, &ts);
118 if (nready < 0)
119 errExit("select");
120 else if (nready == 0) { // timeout
121 close(sock);
122 return 0;
123 }
124 else {
125 // read the incoming packet
126 int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
127 if (len < 0) {
128 perror("recvfrom");
129 close(sock);
130 return -1;
131 }
132
133 // parse the incomming packet
134 if (len < 14 + sizeof(ArpHdr))
135 continue;
136 if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
137 continue;
138 memcpy(&hdr, frame + 14, sizeof(ArpHdr));
139 if (hdr.opcode == htons(1))
140 continue;
141 if (hdr.opcode == htons(2)) {
142 // check my mac and my address
143 if (memcmp(ifr.ifr_hwaddr.sa_data, hdr.target_mac, 6) != 0)
144 continue;
145 uint32_t ip;
146 memcpy(&ip, hdr.target_ip, 4);
147 if (ip != srcaddr) {
148 continue;
149 }
150 close(sock);
151 return -1;
152 }
153 }
154 }
155
156 // it will never get here!
157 close(sock);
158 return -1;
159}
160
161// assign a random IP address and check it
162// the address needs to be in the range if it --iprange was specified
163static uint32_t arp_random(const char *dev, Bridge *br) {
164 assert(dev);
165 assert(br);
166 uint32_t ifip = br->ip;
167 uint32_t ifmask = br->mask;
168 assert(ifip);
169 assert(ifmask);
170
171 if (arg_debug)
172 printf("ARP-scan %s, %d.%d.%d.%d/%d\n",
173 dev, PRINT_IP(ifip), mask2bits(ifmask));
174
175 // determine the range based on network address
176 uint32_t range = ~ifmask + 1; // the number of potential addresses
177 // this software is not supported for /31 networks
178 if (range < 4)
179 return 0; // the user will have to set the IP address manually
180 range -= 2; // subtract the network address and the broadcast address
181 uint32_t start = (ifip & ifmask) + 1;
182
183 // adjust range based on --iprange params
184 if (br->iprange_start && br->iprange_end) {
185 start = br->iprange_start;
186 range = br->iprange_end - br->iprange_start;
187 }
188
189 if (arg_debug)
190 printf("IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n",
191 PRINT_IP(start), PRINT_IP(start + range));
192
193 // generate a random address - 10 tries
194 uint32_t dest = 0;
195 int i = 0;
196 for (i = 0; i < 10; i++) {
197 dest = start + ((uint32_t) rand()) % range;
198 if (dest == ifip) // do not allow the interface address
199 continue; // try again
200
201 // if we've made it up to here, we have a valid address
202 break;
203 }
204 if (i == 10) // we failed 10 times
205 return 0;
206
207 // check address
208 uint32_t rv = arp_check(dev, dest, ifip);
209 if (!rv)
210 return dest;
211 return 0;
212}
213
214// go sequentially trough all IP addresses and assign the first one not in use
215static uint32_t arp_sequential(const char *dev, Bridge *br) {
216 assert(dev);
217 assert(br);
218 uint32_t ifip = br->ip;
219 uint32_t ifmask = br->mask;
220 assert(ifip);
221 assert(ifmask);
222
223 // range based on network address
224 uint32_t range = ~ifmask + 1; // the number of potential addresses
225 // this software is not supported for /31 networks
226 if (range < 4)
227 return 0; // the user will have to set the IP address manually
228 range -= 2; // subtract the network address and the broadcast address
229
230 // try all possible ip addresses in ascending order
231 // start address
232 uint32_t dest = (ifip & ifmask) + 1;
233 if (br->iprange_start)
234 dest = br->iprange_start;
235 // end address
236 uint32_t last = dest + range - 1;
237 if (br->iprange_end)
238 last = br->iprange_end;
239
240 if (arg_debug)
241 printf("Trying IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n",
242 PRINT_IP(dest), PRINT_IP(last));
243
244 // loop through addresses and stop as soon as you find an unused one
245 while (dest <= last) {
246 if (dest == ifip) {
247 dest++;
248 continue;
249 }
250 uint32_t rv = arp_check(dev, dest, ifip);
251 if (!rv)
252 return dest;
253 dest++;
254 }
255
256 return 0;
257}
258
259// assign an IP address first trying some random addresses, and if this fails
260// by doing an arp scan.
261//
262// dev is the name of the device to use in scanning,
263// br is bridge structure holding the ip address and mask to use in
264// arp packets. It also holds values for for the range of addresses
265// if --iprange was set by the user
266uint32_t arp_assign(const char *dev, Bridge *br) {
267 assert(br);
268 uint32_t ip = 0;
269
270 // try two random IP addresses
271 ip = arp_random(dev, br);
272 if (!ip)
273 ip = arp_random(dev, br);
274
275 // try all possible IP addresses one by one
276 if (!ip)
277 ip = arp_sequential(dev, br);
278
279 // print result
280 if (!ip) {
281 fprintf(stderr, "Error: cannot assign an IP address; it looks like all of them are in use.\n");
282 logerr("Cannot assign an IP address; it looks like all of them are in use.");
283 exit(1);
284 }
285
286 return ip;
287}
288
289// scan interface (--scan option)
290void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask) {
291 assert(dev);
292 assert(ifip);
293
294// printf("Scanning interface %s (%d.%d.%d.%d/%d)\n",
295// dev, PRINT_IP(ifip & ifmask), mask2bits(ifmask));
296
297 if (strlen(dev) > IFNAMSIZ) {
298 fprintf(stderr, "Error: invalid network device name %s\n", dev);
299 exit(1);
300 }
301
302 // find interface mac address
303 int sock;
304 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
305 errExit("socket");
306 struct ifreq ifr;
307 memset(&ifr, 0, sizeof (ifr));
308 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
309 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
310 errExit("ioctl");
311 close(sock);
312 uint8_t mac[6];
313 memcpy (mac, ifr.ifr_hwaddr.sa_data, 6);
314
315 // open layer2 socket
316 if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
317 errExit("socket");
318
319 // try all possible ip addresses in ascending order
320 uint32_t range = ~ifmask + 1; // the number of potential addresses
321 // this software is not supported for /31 networks
322 if (range < 4) {
323 fprintf(stderr, "Warning: this option is not supported for /31 networks\n");
324 close(sock);
325 return;
326 }
327
328 uint32_t dest = (ifip & ifmask) + 1;
329 uint32_t last = dest + range - 1;
330 uint32_t src = htonl(ifip);
331
332 // wait not more than one second for an answer
333 int header_printed = 0;
334 int last_ip = 0;
335 struct timeval ts;
336 ts.tv_sec = 2; // 2 seconds receive timeout
337 ts.tv_usec = 0;
338
339 while (1) {
340 fd_set rfds;
341 FD_ZERO(&rfds);
342 FD_SET(sock, &rfds);
343 fd_set wfds;
344 FD_ZERO(&wfds);
345 FD_SET(sock, &wfds);
346 int maxfd = sock;
347
348 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
349 memset(frame, 0, ETH_FRAME_LEN);
350
351 int nready;
352 if (dest < last)
353 nready = select(maxfd + 1, &rfds, &wfds, (fd_set *) 0, NULL);
354 else
355 nready = select(maxfd + 1, &rfds, (fd_set *) 0, (fd_set *) 0, &ts);
356
357 if (nready < 0)
358 errExit("select");
359
360 if (nready == 0) { // timeout
361 break;
362 }
363
364 if (FD_ISSET(sock, &wfds) && dest < last) {
365 // configure layer2 socket address information
366 struct sockaddr_ll addr;
367 memset(&addr, 0, sizeof(addr));
368 if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
369 errExit("if_nametoindex");
370 addr.sll_family = AF_PACKET;
371 memcpy (addr.sll_addr, mac, 6);
372 addr.sll_halen = htons(6);
373
374 // build the arp packet header
375 ArpHdr hdr;
376 memset(&hdr, 0, sizeof(hdr));
377 hdr.htype = htons(1);
378 hdr.ptype = htons(ETH_P_IP);
379 hdr.hlen = 6;
380 hdr.plen = 4;
381 hdr.opcode = htons(1); //ARPOP_REQUEST
382 memcpy(hdr.sender_mac, mac, 6);
383 memcpy(hdr.sender_ip, (uint8_t *)&src, 4);
384 uint32_t dst = htonl(dest);
385 memcpy(hdr.target_ip, (uint8_t *)&dst, 4);
386
387 // buiild ethernet frame
388 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
389 memset(frame, 0, sizeof(frame));
390 frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
391 memcpy(frame + 6, mac, 6);
392 frame[12] = ETH_P_ARP / 256;
393 frame[13] = ETH_P_ARP % 256;
394 memcpy (frame + 14, &hdr, sizeof(hdr));
395
396 // send packet
397 int len;
398 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
399 errExit("send");
400//printf("send %d bytes to %d.%d.%d.%d\n", len, PRINT_IP(dest));
401 fflush(0);
402 dest++;
403 }
404
405 if (FD_ISSET(sock, &rfds)) {
406 // read the incoming packet
407 int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
408 if (len < 0) {
409 perror("recvfrom");
410 }
411
412 // parse the incomming packet
413 if (len < 14 + sizeof(ArpHdr))
414 continue;
415
416 // look only at ARP packets
417 if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
418 continue;
419
420 ArpHdr hdr;
421 memcpy(&hdr, frame + 14, sizeof(ArpHdr));
422
423 if (hdr.opcode == htons(2)) {
424 // check my mac and my address
425 if (memcmp(mac, hdr.target_mac, 6) != 0)
426 continue;
427 uint32_t ip;
428 memcpy(&ip, hdr.target_ip, 4);
429 if (ip != src)
430 continue;
431 memcpy(&ip, hdr.sender_ip, 4);
432 ip = ntohl(ip);
433
434 if (ip == last_ip) // filter duplicates
435 continue;
436 last_ip = ip;
437
438 // printing
439 if (header_printed == 0) {
440 printf(" Network scan:\n");
441
442 // print parent interface
443 if (cfg.bridge0.configured && cfg.bridge0.ip && cfg.bridge0.macvlan &&
444 (cfg.bridge0.ip & cfg.bridge0.mask) == (ifip & cfg.bridge0.mask))
445 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
446 PRINT_MAC(cfg.bridge0.mac), PRINT_IP(cfg.bridge0.ip));
447
448 if (cfg.bridge1.configured && cfg.bridge1.ip && cfg.bridge1.macvlan &&
449 (cfg.bridge1.ip & cfg.bridge1.mask) == (ifip & cfg.bridge1.mask))
450 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
451 PRINT_MAC(cfg.bridge1.mac), PRINT_IP(cfg.bridge1.ip));
452
453 if (cfg.bridge2.configured && cfg.bridge2.ip && cfg.bridge2.macvlan &&
454 (cfg.bridge2.ip & cfg.bridge2.mask) == (ifip & cfg.bridge2.mask))
455 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
456 PRINT_MAC(cfg.bridge2.mac), PRINT_IP(cfg.bridge2.ip));
457
458 if (cfg.bridge3.configured && cfg.bridge3.ip && cfg.bridge3.macvlan &&
459 (cfg.bridge3.ip & cfg.bridge3.mask) == (ifip & cfg.bridge3.mask))
460 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
461 PRINT_MAC(cfg.bridge3.mac), PRINT_IP(cfg.bridge3.ip));
462
463 header_printed = 1;
464 }
465 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
466 PRINT_MAC(hdr.sender_mac), PRINT_IP(ip));
467 }
468 }
469 }
470
471 close(sock);
472}
473
474
diff --git a/src/firejail/bandwidth.c b/src/firejail/bandwidth.c
new file mode 100644
index 000000000..25dd7a0fb
--- /dev/null
+++ b/src/firejail/bandwidth.c
@@ -0,0 +1,483 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#define _GNU_SOURCE
21#include <stdio.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <net/if.h>
26#include "firejail.h"
27
28//***********************************
29// interface bandwidth linked list
30//***********************************
31typedef struct ifbw_t {
32 struct ifbw_t *next;
33 char *txt;
34} IFBW;
35IFBW *ifbw = NULL;
36
37
38#if 0
39static void ifbw_print(void) {
40 IFBW *ptr = ifbw;
41 while (ptr) {
42 printf("#%s#\n", ptr->txt);
43 ptr = ptr->next;
44 }
45}
46#endif
47
48static void ifbw_add(IFBW *ptr) {
49 assert(ptr);
50
51 if (ifbw != NULL)
52 ptr->next = ifbw;
53 ifbw = ptr;
54}
55
56
57IFBW *ifbw_find(const char *dev) {
58 assert(dev);
59 int len = strlen(dev);
60 assert(len);
61
62 if (ifbw == NULL)
63 return NULL;
64
65 IFBW *ptr = ifbw;
66 while (ptr) {
67 if (strncmp(ptr->txt, dev, len) == 0 && ptr->txt[len] == ':')
68 return ptr;
69 ptr = ptr->next;
70 }
71
72 return NULL;
73}
74
75void ifbw_remove(IFBW *r) {
76 if (ifbw == NULL)
77 return;
78
79 // remove the first element
80 if (ifbw == r) {
81 ifbw = ifbw->next;
82 return;
83 }
84
85 // walk the list
86 IFBW *ptr = ifbw->next;
87 IFBW *prev = ifbw;
88 while (ptr) {
89 if (ptr == r) {
90 prev->next = ptr->next;
91 return;
92 }
93
94 prev = ptr;
95 ptr = ptr->next;
96 }
97
98 return;
99}
100
101int fibw_count(viod) {
102 int rv = 0;
103 IFBW *ptr = ifbw;
104
105 while (ptr) {
106 rv++;
107 ptr = ptr->next;
108 }
109
110 return rv;
111}
112
113
114//***********************************
115// shm file handling
116//***********************************
117void shm_create_firejail_dir(void) {
118 struct stat s;
119 if (stat("/dev/shm/firejail", &s) == -1) {
120 /* coverity[toctou] */
121 if (mkdir("/dev/shm/firejail", 0777) == -1)
122 errExit("mkdir");
123 if (chown("/dev/shm/firejail", 0, 0) == -1)
124 errExit("chown");
125 }
126 else { // check /dev/shm/firejail directory belongs to root end exit if doesn't!
127 if (s.st_uid != 0 || s.st_gid != 0) {
128 fprintf(stderr, "Error: non-root %s directory, exiting...\n", "/dev/shm/firejail");
129 exit(1);
130 }
131 }
132}
133
134static void shm_create_bandwidth_file(pid_t pid) {
135 char *fname;
136 if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1)
137 errExit("asprintf");
138
139 // if the file already exists, do nothing
140 struct stat s;
141 if (stat(fname, &s) == 0) {
142 free(fname);
143 return;
144 }
145
146 // create an empty file and set mod and ownership
147 /* coverity[toctou] */
148 FILE *fp = fopen(fname, "w");
149 if (fp) {
150 fclose(fp);
151
152 /* coverity[toctou] */
153 if (chmod(fname, 0644) == -1)
154 errExit("chmod");
155 /* coverity[toctou] */
156 if (chown(fname, 0, 0) == -1)
157 errExit("chown");
158 }
159 else {
160 fprintf(stderr, "Error: cannot create bandwidth file in /dev/shm/firejail directory\n");
161 exit(1);
162 }
163
164 free(fname);
165}
166
167// delete shm bandwidth file
168void bandwidth_shm_del_file(pid_t pid) {
169 char *fname;
170 if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1)
171 errExit("asprintf");
172 unlink(fname);
173 free(fname);
174}
175
176void network_shm_del_file(pid_t pid) {
177 char *fname;
178 if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1)
179 errExit("asprintf");
180 unlink(fname);
181 free(fname);
182}
183
184void network_shm_set_file(pid_t pid) {
185 char *fname;
186 if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1)
187 errExit("asprintf");
188
189 // create an empty file and set mod and ownership
190 FILE *fp = fopen(fname, "w");
191 if (fp) {
192 if (cfg.bridge0.configured)
193 fprintf(fp, "%s:%s\n", cfg.bridge0.dev, cfg.bridge0.devsandbox);
194 if (cfg.bridge1.configured)
195 fprintf(fp, "%s:%s\n", cfg.bridge1.dev, cfg.bridge1.devsandbox);
196 if (cfg.bridge2.configured)
197 fprintf(fp, "%s:%s\n", cfg.bridge2.dev, cfg.bridge2.devsandbox);
198 if (cfg.bridge3.configured)
199 fprintf(fp, "%s:%s\n", cfg.bridge3.dev, cfg.bridge3.devsandbox);
200 fclose(fp);
201
202 if (chmod(fname, 0644) == -1)
203 errExit("chmod");
204 if (chown(fname, 0, 0) == -1)
205 errExit("chown");
206 }
207 else {
208 fprintf(stderr, "Error: cannot create network map file in /dev/shm/firejail directory\n");
209 exit(1);
210 }
211
212 free(fname);
213}
214
215
216void shm_read_bandwidth_file(pid_t pid) {
217 assert(ifbw == NULL);
218
219 char *fname;
220 if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1)
221 errExit("asprintf");
222
223 FILE *fp = fopen(fname, "r");
224 if (fp) {
225 char buf[1024];
226 while (fgets(buf, 1024,fp)) {
227 // remove '\n'
228 char *ptr = strchr(buf, '\n');
229 if (ptr)
230 *ptr = '\0';
231 if (strlen(buf) == 0)
232 continue;
233
234 // create a new IFBW entry
235 IFBW *ifbw_new = malloc(sizeof(IFBW));
236 if (!ifbw_new)
237 errExit("malloc");
238 memset(ifbw_new, 0, sizeof(IFBW));
239 ifbw_new->txt = strdup(buf);
240 if (!ifbw_new->txt)
241 errExit("strdup");
242
243 // add it to the linked list
244 ifbw_add(ifbw_new);
245 }
246
247 fclose(fp);
248 }
249}
250
251void shm_write_bandwidth_file(pid_t pid) {
252 if (ifbw == NULL)
253 return; // nothing to do
254
255 char *fname;
256 if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1)
257 errExit("asprintf");
258
259 FILE *fp = fopen(fname, "w");
260 if (fp) {
261 IFBW *ptr = ifbw;
262 while (ptr) {
263 fprintf(fp, "%s\n", ptr->txt);
264 ptr = ptr->next;
265 }
266 fclose(fp);
267 }
268 else {
269 fprintf(stderr, "Error: cannot write bandwidht file %s\n", fname);
270 exit(1);
271 }
272}
273
274//***********************************
275// add or remove interfaces
276//***********************************
277
278// remove interface from shm file
279void bandwidth_shm_remove(pid_t pid, const char *dev) {
280 // create bandwidth directory & file in case they are not in the filesystem yet
281 shm_create_firejail_dir();
282 shm_create_bandwidth_file(pid);
283
284 // read bandwidth file
285 shm_read_bandwidth_file(pid);
286
287 // find the element and remove it
288 IFBW *elem = ifbw_find(dev);
289 if (elem) {
290 ifbw_remove(elem);
291 shm_write_bandwidth_file(pid) ;
292 }
293
294 // remove the file if there are no entries in the list
295 if (ifbw == NULL) {
296 bandwidth_shm_del_file(pid);
297 }
298}
299
300// add interface to shm file
301void bandwidth_shm_set(pid_t pid, const char *dev, int down, int up) {
302 // create bandwidth directory & file in case they are not in the filesystem yet
303 shm_create_firejail_dir();
304 shm_create_bandwidth_file(pid);
305
306 // create the new text entry
307 char *txt;
308 if (asprintf(&txt, "%s: RX %dKB/s, TX %dKB/s", dev, down, up) == -1)
309 errExit("asprintf");
310
311 // read bandwidth file
312 shm_read_bandwidth_file(pid);
313
314 // look for an existing entry and replace the text
315 IFBW *ptr = ifbw_find(dev);
316 if (ptr) {
317 assert(ptr->txt);
318 free(ptr->txt);
319 ptr->txt = txt;
320 }
321 // ... or add a new entry
322 else {
323 IFBW *ifbw_new = malloc(sizeof(IFBW));
324 if (!ifbw_new)
325 errExit("malloc");
326 memset(ifbw_new, 0, sizeof(IFBW));
327 ifbw_new->txt = txt;
328
329 // add it to the linked list
330 ifbw_add(ifbw_new);
331 }
332 shm_write_bandwidth_file(pid) ;
333}
334
335
336//***********************************
337// command execution
338//***********************************
339void bandwidth_name(const char *name, const char *command, const char *dev, int down, int up) {
340 if (!name || strlen(name) == 0) {
341 fprintf(stderr, "Error: invalid sandbox name\n");
342 exit(1);
343 }
344 pid_t pid;
345 if (name2pid(name, &pid)) {
346 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
347 exit(1);
348 }
349
350 bandwidth_pid(pid, command, dev, down, up);
351}
352
353void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up) {
354 //************************
355 // verify sandbox
356 //************************
357 char *comm = pid_proc_comm(pid);
358 if (!comm) {
359 fprintf(stderr, "Error: cannot find sandbox\n");
360 exit(1);
361 }
362
363 // remove \n and check for firejail sandbox
364 char *ptr = strchr(comm, '\n');
365 if (ptr)
366 *ptr = '\0';
367 if (strcmp(comm, "firejail") != 0) {
368 fprintf(stderr, "Error: cannot find sandbox\n");
369 exit(1);
370 }
371 free(comm);
372
373 // check network namespace
374 char *cmd = pid_proc_cmdline(pid);
375 if (!cmd || strstr(cmd, "--net") == NULL) {
376 fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n");
377 exit(1);
378 }
379 free(cmd);
380
381
382 //************************
383 // join the network namespace
384 //************************
385 pid_t child;
386 if (find_child(pid, &child) == -1) {
387 fprintf(stderr, "Error: cannot join the network namespace\n");
388 exit(1);
389 }
390 if (join_namespace(child, "net")) {
391 fprintf(stderr, "Error: cannot join the network namespace\n");
392 exit(1);
393 }
394
395 // set shm file
396 if (strcmp(command, "set") == 0)
397 bandwidth_shm_set(pid, dev, down, up);
398 else if (strcmp(command, "clear") == 0)
399 bandwidth_shm_remove(pid, dev);
400
401 //************************
402 // build command
403 //************************
404 char *devname = NULL;
405 if (dev) {
406 // read shm network map file
407 char *fname;
408 if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1)
409 errExit("asprintf");
410 FILE *fp = fopen(fname, "r");
411 if (!fp) {
412 fprintf(stderr, "Error: cannot read netowk map filel %s\n", fname);
413 exit(1);
414 }
415
416 char buf[1024];
417 int len = strlen(dev);
418 while (fgets(buf, 1024, fp)) {
419 // remove '\n'
420 char *ptr = strchr(buf, '\n');
421 if (ptr)
422 *ptr = '\0';
423 if (*buf == '\0')
424 break;
425
426 if (strncmp(buf, dev, len) == 0 && buf[len] == ':') {
427 devname = strdup(buf + len + 1);
428 if (!devname)
429 errExit("strdup");
430 // check device in namespace
431 if (if_nametoindex(devname) == 0) {
432 fprintf(stderr, "Error: cannot find network device %s\n", devname);
433 exit(1);
434 }
435 break;
436 }
437 }
438 free(fname);
439 fclose(fp);
440 }
441
442 // build fshaper.sh command
443 cmd = NULL;
444 if (devname) {
445 if (strcmp(command, "set") == 0) {
446 if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s %s %d %d",
447 PREFIX, command, devname, down, up) == -1)
448 errExit("asprintf");
449 }
450 else {
451 if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s %s",
452 PREFIX, command, devname) == -1)
453 errExit("asprintf");
454 }
455 }
456 else {
457 if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s", PREFIX, command) == -1)
458 errExit("asprintf");
459 }
460 assert(cmd);
461
462 // wipe out environment variables
463 environ = NULL;
464
465 //************************
466 // build command
467 //************************
468 // elevate privileges
469 if (setreuid(0, 0))
470 errExit("setreuid");
471 if (setregid(0, 0))
472 errExit("setregid");
473
474 char *arg[4];
475 arg[0] = "/bin/bash";
476 arg[1] = "-c";
477 arg[2] = cmd;
478 arg[3] = NULL;
479 execvp("/bin/bash", arg);
480
481 // it will never get here
482 exit(0);
483}
diff --git a/src/firejail/caps.c b/src/firejail/caps.c
new file mode 100644
index 000000000..d8777c0db
--- /dev/null
+++ b/src/firejail/caps.c
@@ -0,0 +1,453 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include "firejail.h"
22#include <errno.h>
23#include <linux/filter.h>
24#include <stddef.h>
25#include <linux/capability.h>
26#include <linux/audit.h>
27#include <sys/prctl.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31
32extern int capget(cap_user_header_t hdrp, cap_user_data_t datap);
33extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
34
35
36typedef struct {
37 char *name;
38 int nr;
39} CapsEntry;
40
41static CapsEntry capslist[] = {
42//
43// code generated using tools/extract-caps
44// updated manually based on kernel 3.18/include/linux/capability.h (added block suspend and audit_read
45//
46#ifdef CAP_CHOWN
47 {"chown", CAP_CHOWN },
48#endif
49#ifdef CAP_DAC_OVERRIDE
50 {"dac_override", CAP_DAC_OVERRIDE },
51#endif
52#ifdef CAP_DAC_READ_SEARCH
53 {"dac_read_search", CAP_DAC_READ_SEARCH },
54#endif
55#ifdef CAP_FOWNER
56 {"fowner", CAP_FOWNER },
57#endif
58#ifdef CAP_FSETID
59 {"fsetid", CAP_FSETID },
60#endif
61#ifdef CAP_KILL
62 {"kill", CAP_KILL },
63#endif
64#ifdef CAP_SETGID
65 {"setgid", CAP_SETGID },
66#endif
67#ifdef CAP_SETUID
68 {"setuid", CAP_SETUID },
69#endif
70#ifdef CAP_SETPCAP
71 {"setpcap", CAP_SETPCAP },
72#endif
73#ifdef CAP_LINUX_IMMUTABLE
74 {"linux_immutable", CAP_LINUX_IMMUTABLE },
75#endif
76#ifdef CAP_NET_BIND_SERVICE
77 {"net_bind_service", CAP_NET_BIND_SERVICE },
78#endif
79#ifdef CAP_NET_BROADCAST
80 {"net_broadcast", CAP_NET_BROADCAST },
81#endif
82#ifdef CAP_NET_ADMIN
83 {"net_admin", CAP_NET_ADMIN },
84#endif
85#ifdef CAP_NET_RAW
86 {"net_raw", CAP_NET_RAW },
87#endif
88#ifdef CAP_IPC_LOCK
89 {"ipc_lock", CAP_IPC_LOCK },
90#endif
91#ifdef CAP_IPC_OWNER
92 {"ipc_owner", CAP_IPC_OWNER },
93#endif
94#ifdef CAP_SYS_MODULE
95 {"sys_module", CAP_SYS_MODULE },
96#endif
97#ifdef CAP_SYS_RAWIO
98 {"sys_rawio", CAP_SYS_RAWIO },
99#endif
100#ifdef CAP_SYS_CHROOT
101 {"sys_chroot", CAP_SYS_CHROOT },
102#endif
103#ifdef CAP_SYS_PTRACE
104 {"sys_ptrace", CAP_SYS_PTRACE },
105#endif
106#ifdef CAP_SYS_PACCT
107 {"sys_pacct", CAP_SYS_PACCT },
108#endif
109#ifdef CAP_SYS_ADMIN
110 {"sys_admin", CAP_SYS_ADMIN },
111#endif
112#ifdef CAP_SYS_BOOT
113 {"sys_boot", CAP_SYS_BOOT },
114#endif
115#ifdef CAP_SYS_NICE
116 {"sys_nice", CAP_SYS_NICE },
117#endif
118#ifdef CAP_SYS_RESOURCE
119 {"sys_resource", CAP_SYS_RESOURCE },
120#endif
121#ifdef CAP_SYS_TIME
122 {"sys_time", CAP_SYS_TIME },
123#endif
124#ifdef CAP_SYS_TTY_CONFIG
125 {"sys_tty_config", CAP_SYS_TTY_CONFIG },
126#endif
127#ifdef CAP_MKNOD
128 {"mknod", CAP_MKNOD },
129#endif
130#ifdef CAP_LEASE
131 {"lease", CAP_LEASE },
132#endif
133#ifdef CAP_AUDIT_WRITE
134 {"audit_write", CAP_AUDIT_WRITE },
135#endif
136#ifdef CAP_AUDIT_CONTROL
137 {"audit_control", CAP_AUDIT_CONTROL },
138#endif
139#ifdef CAP_SETFCAP
140 {"setfcap", CAP_SETFCAP },
141#endif
142#ifdef CAP_MAC_OVERRIDE
143 {"mac_override", CAP_MAC_OVERRIDE },
144#endif
145#ifdef CAP_MAC_ADMIN
146 {"mac_admin", CAP_MAC_ADMIN },
147#endif
148#ifdef CAP_SYSLOG
149 {"syslog", CAP_SYSLOG },
150#endif
151#ifdef CAP_WAKE_ALARM
152 {"wake_alarm", CAP_WAKE_ALARM },
153#endif
154// not in Debian 7
155#ifdef CAP_BLOCK_SUSPEND
156 {"block_suspend", CAP_BLOCK_SUSPEND },
157#else
158 {"block_suspend", 36 },
159#endif
160#ifdef CAP_AUDIT_READ
161 {"audit_read", CAP_AUDIT_READ },
162#else
163 {"audit_read", 37 },
164#endif
165
166//
167// end of generated code
168//
169}; // end of capslist
170
171const char *caps_find_nr(int nr) {
172 int i;
173 int elems = sizeof(capslist) / sizeof(capslist[0]);
174 for (i = 0; i < elems; i++) {
175 if (nr == capslist[i].nr)
176 return capslist[i].name;
177 }
178
179 return "unknown";
180}
181
182// return -1 if error, or syscall number
183static int caps_find_name(const char *name) {
184 int i;
185 int elems = sizeof(capslist) / sizeof(capslist[0]);
186 for (i = 0; i < elems; i++) {
187 if (strcmp(name, capslist[i].name) == 0)
188 return capslist[i].nr;
189 }
190
191 return -1;
192}
193
194// return 1 if error, 0 if OK
195int caps_check_list(const char *clist, void (*callback)(int)) {
196 // don't allow empty lists
197 if (clist == NULL || *clist == '\0') {
198 fprintf(stderr, "Error: empty capabilities lists are not allowed\n");
199 return -1;
200 }
201
202 // work on a copy of the string
203 char *str = strdup(clist);
204 if (!str)
205 errExit("strdup");
206
207 char *ptr = str;
208 char *start = str;
209 while (*ptr != '\0') {
210 if (islower(*ptr) || isdigit(*ptr) || *ptr == '_')
211 ;
212 else if (*ptr == ',') {
213 *ptr = '\0';
214 int nr = caps_find_name(start);
215 if (nr == -1) {
216 fprintf(stderr, "Error: capability %s not found\n", start);
217 free(str);
218 return -1;
219 }
220 else if (callback != NULL)
221 callback(nr);
222
223 start = ptr + 1;
224 }
225 ptr++;
226 }
227 if (*start != '\0') {
228 int nr = caps_find_name(start);
229 if (nr == -1) {
230 fprintf(stderr, "Error: capability %s not found\n", start);
231 free(str);
232 return -1;
233 }
234 else if (callback != NULL)
235 callback(nr);
236 }
237
238 free(str);
239 return 0;
240}
241
242void caps_print(void) {
243 int i;
244 int elems = sizeof(capslist) / sizeof(capslist[0]);
245
246 // check current caps supported by the kernel
247 int cnt = 0;
248 unsigned long cap;
249 for (cap=0; cap <= 63; cap++) {
250 int code = prctl(PR_CAPBSET_DROP, cap, 0, 0, 0);
251 if (code == 0)
252 cnt++;
253 }
254 printf("Your kernel supports %d capabilities.\n", cnt);
255
256 for (i = 0; i < elems; i++) {
257 printf("%d\t- %s\n", capslist[i].nr, capslist[i].name);
258 }
259}
260
261
262
263
264// enabled by default
265int caps_default_filter(void) {
266 // drop capabilities
267 if (prctl(PR_CAPBSET_DROP, CAP_SYS_MODULE, 0, 0, 0) && arg_debug)
268 fprintf(stderr, "Warning: cannot drop CAP_SYS_MODULE");
269 else if (arg_debug)
270 printf("Drop CAP_SYS_MODULE\n");
271
272 if (prctl(PR_CAPBSET_DROP, CAP_SYS_RAWIO, 0, 0, 0) && arg_debug)
273 fprintf(stderr, "Warning: cannot drop CAP_SYS_RAWIO");
274 else if (arg_debug)
275 printf("Drop CAP_SYS_RAWIO\n");
276
277 if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0) && arg_debug)
278 fprintf(stderr, "Warning: cannot drop CAP_SYS_BOOT");
279 else if (arg_debug)
280 printf("Drop CAP_SYS_BOOT\n");
281
282 if (prctl(PR_CAPBSET_DROP, CAP_SYS_NICE, 0, 0, 0) && arg_debug)
283 fprintf(stderr, "Warning: cannot drop CAP_SYS_NICE");
284 else if (arg_debug)
285 printf("Drop CAP_SYS_NICE\n");
286
287 if (prctl(PR_CAPBSET_DROP, CAP_SYS_TTY_CONFIG, 0, 0, 0) && arg_debug)
288 fprintf(stderr, "Warning: cannot drop CAP_SYS_TTY_CONFIG");
289 else if (arg_debug)
290 printf("Drop CAP_SYS_TTY_CONFIG\n");
291
292 if (prctl(PR_CAPBSET_DROP, CAP_SYSLOG, 0, 0, 0) && arg_debug)
293 fprintf(stderr, "Warning: cannot drop CAP_SYSLOG");
294 else if (arg_debug)
295 printf("Drop CAP_SYSLOG\n");
296
297 if (prctl(PR_CAPBSET_DROP, CAP_MKNOD, 0, 0, 0) && arg_debug)
298 fprintf(stderr, "Warning: cannot drop CAP_MKNOD");
299 else if (arg_debug)
300 printf("Drop CAP_MKNOD\n");
301
302 if (prctl(PR_CAPBSET_DROP, CAP_SYS_ADMIN, 0, 0, 0) && arg_debug)
303 fprintf(stderr, "Warning: cannot drop CAP_SYS_ADMIN");
304 else if (arg_debug)
305 printf("Drop CAP_SYS_ADMIN\n");
306
307 return 0;
308}
309
310void caps_drop_all(void) {
311 if (arg_debug)
312 printf("Droping all capabilities\n");
313
314 unsigned long cap;
315 for (cap=0; cap <= 63; cap++) {
316 int code = prctl(PR_CAPBSET_DROP, cap, 0, 0, 0);
317 if (code == -1 && errno != EINVAL)
318 errExit("PR_CAPBSET_DROP");
319 }
320}
321
322
323void caps_set(uint64_t caps) {
324 if (arg_debug)
325 printf("Set caps filter %llx\n", (unsigned long long) caps);
326
327 unsigned long i;
328 uint64_t mask = 1LLU;
329 for (i = 0; i < 64; i++, mask <<= 1) {
330 if ((mask & caps) == 0) {
331 int code = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
332 if (code == -1 && errno != EINVAL)
333 errExit("PR_CAPBSET_DROP");
334 }
335 }
336}
337
338
339static uint64_t filter;
340
341static void caps_set_bit(int nr) {
342 uint64_t mask = 1LLU << nr;
343 filter |= mask;
344}
345static void caps_reset_bit(int nr) {
346 uint64_t mask = 1LLU << nr;
347 filter &= ~mask;
348}
349
350void caps_drop_list(const char *clist) {
351 filter = 0;
352 filter--;
353 caps_check_list(clist, caps_reset_bit);
354 caps_set(filter);
355}
356
357void caps_keep_list(const char *clist) {
358 filter = 0;
359 caps_check_list(clist, caps_set_bit);
360 caps_set(filter);
361}
362
363#define MAXBUF 4098
364static uint64_t extract_caps(int pid) {
365 char *file;
366 if (asprintf(&file, "/proc/%d/status", pid) == -1) {
367 errExit("asprintf");
368 exit(1);
369 }
370
371 FILE *fp = fopen(file, "r");
372 if (!fp) {
373 printf("Error: cannot open %s\n", file);
374 free(file);
375 exit(1);
376 }
377
378 char buf[MAXBUF];
379 while (fgets(buf, MAXBUF, fp)) {
380 if (strncmp(buf, "CapBnd:", 7) == 0) {
381 char *ptr = buf + 8;
382 unsigned long long val;
383 sscanf(ptr, "%llx", &val);
384 free(file);
385 fclose(fp);
386 return val;
387 }
388 }
389 fclose(fp);
390 free(file);
391 printf("Error: cannot read caps configuration\n");
392 exit(1);
393}
394
395
396void caps_print_filter_name(const char *name) {
397 if (!name || strlen(name) == 0) {
398 fprintf(stderr, "Error: invalid sandbox name\n");
399 exit(1);
400 }
401 pid_t pid;
402 if (name2pid(name, &pid)) {
403 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
404 exit(1);
405 }
406
407 caps_print_filter(pid);
408}
409
410void caps_print_filter(pid_t pid) {
411 // if the pid is that of a firejail process, use the pid of the first child process
412 char *comm = pid_proc_comm(pid);
413 if (comm) {
414 // remove \n
415 char *ptr = strchr(comm, '\n');
416 if (ptr)
417 *ptr = '\0';
418 if (strcmp(comm, "firejail") == 0) {
419 pid_t child;
420 if (find_child(pid, &child) == 0) {
421 pid = child;
422 }
423 }
424 free(comm);
425 }
426
427 // check privileges for non-root users
428 uid_t uid = getuid();
429 if (uid != 0) {
430 struct stat s;
431 char *dir;
432 if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
433 errExit("asprintf");
434 if (stat(dir, &s) < 0)
435 errExit("stat");
436 if (s.st_uid != uid) {
437 printf("Error: permission denied.\n");
438 exit(1);
439 }
440 }
441
442 uint64_t caps = extract_caps(pid);
443 drop_privs(1);
444
445 int i;
446 uint64_t mask;
447 int elems = sizeof(capslist) / sizeof(capslist[0]);
448 for (i = 0, mask = 1; i < elems; i++, mask <<= 1) {
449 printf("%-18.18s - %s\n", capslist[i].name, (mask & caps)? "enabled": "disabled");
450 }
451
452 exit(0);
453}
diff --git a/src/firejail/cgroup.c b/src/firejail/cgroup.c
new file mode 100644
index 000000000..7366a6699
--- /dev/null
+++ b/src/firejail/cgroup.c
@@ -0,0 +1,118 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/stat.h>
22
23#define MAXBUF 4096
24
25void save_cgroup(void) {
26 if (cfg.cgroup == NULL)
27 return;
28
29 char *fname;
30 if (asprintf(&fname, "%s/cgroup", MNT_DIR) == -1)
31 errExit(fname);
32
33 FILE *fp = fopen(fname, "w");
34 if (fp) {
35 fprintf(fp, "%s", cfg.cgroup);
36 fflush(0);
37 fclose(fp);
38 if (chown(fname, 0, 0) < 0)
39 errExit("chown");
40 }
41 else {
42 fprintf(stderr, "Error: cannot save cgroup\n");
43 free(fname);
44 exit(1);
45 }
46
47 free(fname);
48}
49
50void load_cgroup(const char *fname) {
51 if (!fname)
52 return;
53
54 FILE *fp = fopen(fname, "r");
55 if (fp) {
56 char buf[MAXBUF];
57 if (fgets(buf, MAXBUF, fp)) {
58 cfg.cgroup = strdup(buf);
59 if (!cfg.cgroup)
60 errExit("strdup");
61 }
62 else
63 goto errout;
64
65 fclose(fp);
66 return;
67 }
68errout:
69 fprintf(stderr, "Warrning: cannot load control group\n");
70 if (fp)
71 fclose(fp);
72}
73
74
75void set_cgroup(const char *path) {
76 // path starts with /sys/fs/cgroup
77 if (strncmp(path, "/sys/fs/cgroup", 14) != 0)
78 goto errout;
79
80 // path ends in tasks
81 char *ptr = strstr(path, "tasks");
82 if (!ptr)
83 goto errout;
84 if (*(ptr + 5) != '\0')
85 goto errout;
86
87 // no .. traversal
88 ptr = strstr(path, "..");
89 if (ptr)
90 goto errout;
91
92 // tasks file exists
93 struct stat s;
94 if (stat(path, &s) == -1)
95 goto errout;
96
97 // task file belongs to the user running the sandbox
98 if (s.st_uid != getuid() && s.st_gid != getgid())
99 goto errout2;
100
101 // add the task to cgroup
102 /* coverity[toctou] */
103 FILE *fp = fopen(path, "a");
104 if (!fp)
105 goto errout;
106 pid_t pid = getpid();
107 int rv = fprintf(fp, "%d\n", pid);
108 (void) rv;
109 fclose(fp);
110 return;
111
112errout:
113 fprintf(stderr, "Error: invalid cgroup\n");
114 exit(1);
115errout2:
116 fprintf(stderr, "Error: you don't have permissions to use this control group\n");
117 exit(1);
118}
diff --git a/src/firejail/cpu.c b/src/firejail/cpu.c
new file mode 100644
index 000000000..633081a3f
--- /dev/null
+++ b/src/firejail/cpu.c
@@ -0,0 +1,141 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sched.h>
22
23// converts a numeric cpu value in the corresponding bit mask
24static void set_cpu(const char *str) {
25 if (strlen(str) == 0)
26 return;
27
28 int val = atoi(str);
29 if (val < 0 || val >= 32) {
30 fprintf(stderr, "Error: invalid cpu number. Accepted values are between 0 and 31.\n");
31 exit(1);
32 }
33
34 uint32_t mask = 1;
35 int i;
36 for (i = 0; i < val; i++, mask <<= 1);
37 cfg.cpus |= mask;
38}
39
40void read_cpu_list(const char *str) {
41 char *tmp = strdup(str);
42 if (tmp == NULL)
43 errExit("strdup");
44
45 char *ptr = tmp;
46 while (*ptr != '\0') {
47 if (*ptr == ',' || isdigit(*ptr))
48 ;
49 else {
50 fprintf(stderr, "Error: invalid cpu list\n");
51 exit(1);
52 }
53 ptr++;
54 }
55
56 char *start = tmp;
57 ptr = tmp;
58 while (*ptr != '\0') {
59 if (*ptr == ',') {
60 *ptr = '\0';
61 set_cpu(start);
62 start = ptr + 1;
63 }
64 ptr++;
65 }
66 set_cpu(start);
67 free(tmp);
68}
69
70void save_cpu(void) {
71 if (cfg.cpus == 0)
72 return;
73
74 char *fname;
75 if (asprintf(&fname, "%s/cpu", MNT_DIR) == -1)
76 errExit("asprintf");
77 FILE *fp = fopen(fname, "w");
78 if (fp) {
79 fprintf(fp, "%x\n", cfg.cpus);
80 fclose(fp);
81 if (chown(fname, 0, 0) < 0)
82 errExit("chown");
83 }
84 else {
85 fprintf(stderr, "Error: cannot save cpu affinity mask\n");
86 free(fname);
87 exit(1);
88 }
89
90 free(fname);
91}
92
93void load_cpu(const char *fname) {
94 if (!fname)
95 return;
96
97 FILE *fp = fopen(fname, "r");
98 if (fp) {
99 unsigned tmp;
100 int rv = fscanf(fp, "%x", &tmp);
101 if (rv)
102 cfg.cpus = (uint32_t) tmp;
103 fclose(fp);
104 }
105 else
106 fprintf(stderr, "Warning: cannot load cpu affinity mask\n");
107}
108
109void set_cpu_affinity(void) {
110 // set cpu affinity
111 cpu_set_t mask;
112 CPU_ZERO(&mask);
113
114 int i;
115 uint32_t m = 1;
116 for (i = 0; i < 32; i++, m <<= 1) {
117 if (cfg.cpus & m)
118 CPU_SET(i, &mask);
119 }
120
121 if (sched_setaffinity(0, sizeof(mask), &mask) == -1) {
122 fprintf(stderr, "Warning: cannot set cpu affinity\n");
123 fprintf(stderr, " ");
124 perror("sched_setaffinity");
125 }
126
127 // verify cpu affinity
128 cpu_set_t mask2;
129 CPU_ZERO(&mask2);
130 if (sched_getaffinity(0, sizeof(mask2), &mask2) == -1) {
131 fprintf(stderr, "Warning: cannot verify cpu affinity\n");
132 fprintf(stderr, " ");
133 perror("sched_getaffinity");
134 }
135 else {
136 if (CPU_EQUAL(&mask, &mask2))
137 printf("CPU affinity set\n");
138 else
139 printf("CPU affinity not set\n");
140 }
141}
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
new file mode 100644
index 000000000..2ec6e54c9
--- /dev/null
+++ b/src/firejail/firejail.h
@@ -0,0 +1,354 @@
1/*
2 * Copyright (C) 2014, 2015 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#ifndef FIREJAIL_H
21#define FIREJAIL_H
22#include "../include/common.h"
23
24#define USELOCK
25#define FIREJAIL_DIR "/tmp/firejail"
26#define RO_DIR "/tmp/firejail/firejail.ro.dir"
27#define RO_FILE "/tmp/firejail/firejail.ro.file"
28#define MNT_DIR "/tmp/firejail/mnt"
29#define OVERLAY_DIR "/tmp/firejail/overlay"
30#define HOME_DIR "/tmp/firejail/mnt/home"
31#define MAX_INCLUDE_LEVEL 6
32
33// main.c
34typedef struct bridge_t {
35 // on the host
36 char *dev; // interface device name: bridge or regular ethernet
37 uint32_t ip; // interface device IP address
38 uint32_t mask; // interface device mask
39 uint8_t mac[6]; // interface mac address
40
41 // inside the sandbox
42 char *devsandbox; // name of the device inside the sandbox
43 uint32_t ipsandbox; // ip address inside the sandbox
44 uint8_t macsandbox[6]; // mac address inside the sandbox
45 uint32_t iprange_start;// iprange arp scan start range
46 uint32_t iprange_end; // iprange arp scan end range
47
48 // flags
49 uint8_t arg_ip_none; // --ip=none
50 uint8_t macvlan; // set by --net=eth0 (or eth1, ...); reset by --net=br0 (or br1, ...)
51 uint8_t configured;
52 uint8_t scan; // set by --scan
53} Bridge;
54
55typedef struct profile_entry_t {
56 struct profile_entry_t *next;
57 char *data;
58}ProfileEntry;
59
60typedef struct config_t {
61 // user data
62 char *username;
63 char *homedir;
64
65 // filesystem
66 ProfileEntry *profile;
67 char *chrootdir; // chroot directory
68 char *home_private; // private home directory
69 char *home_private_keep; // keep list for private home directory
70 char *cwd; // current working directory
71
72 // networking
73 char *hostname;
74 uint32_t defaultgw; // default gateway
75 Bridge bridge0;
76 Bridge bridge1;
77 Bridge bridge2;
78 Bridge bridge3;
79 uint32_t dns1; // up to 3 IP addresses for dns servers
80 uint32_t dns2;
81 uint32_t dns3;
82
83 // rlimits
84 unsigned rlimit_nofile;
85 unsigned rlimit_nproc;
86 unsigned rlimit_fsize;
87 unsigned rlimit_sigpending;
88
89 // cpu affinity and control groups
90 uint32_t cpus;
91 char *cgroup;
92
93
94 // command line
95 char *command_line;
96 char *command_name;
97 char *shell;
98 char **original_argv;
99 int original_argc;
100 int original_program_index;
101} Config;
102extern Config cfg;
103
104static inline int any_bridge_configured(void) {
105 if (cfg.bridge3.configured || cfg.bridge2.configured || cfg.bridge1.configured || cfg.bridge0.configured)
106 return 1;
107 else
108 return 0;
109}
110extern int arg_private; // mount private /home and /tmp directory
111extern int arg_debug; // print debug messages
112extern int arg_nonetwork; // --net=none
113extern int arg_command; // -c
114extern int arg_overlay; // --overlay
115extern int arg_zsh; // use zsh as default shell
116extern int arg_csh; // use csh as default shell
117
118extern int arg_seccomp; // enable default seccomp filter
119extern char *arg_seccomp_list;// optional seccomp list on top of default filter
120extern char *arg_seccomp_list_drop; // seccomp drop list
121extern char *arg_seccomp_list_keep; // seccomp keep list
122
123extern int arg_caps_default_filter; // enable default capabilities filter
124extern int arg_caps_drop; // drop list
125extern int arg_caps_drop_all; // drop all capabilities
126extern int arg_caps_keep; // keep list
127extern char *arg_caps_list; // optional caps list
128
129extern int arg_trace; // syscall tracing support
130extern int arg_rlimit_nofile; // rlimit nofile
131extern int arg_rlimit_nproc; // rlimit nproc
132extern int arg_rlimit_fsize; // rlimit fsize
133extern int arg_rlimit_sigpending;// rlimit sigpending
134extern int arg_nox11; // kill the program if x11 unix domain socket is accessed
135extern int arg_nodbus; // kill the program if D-Bus is accessed
136extern int arg_nogroups; // disable supplementary groups
137extern int arg_noroot; // create a new user namespace and disable root user
138extern int arg_netfilter; // enable netfilter
139extern char *arg_netfilter_file; // netfilter file
140extern int arg_doubledash; // double dash
141extern int arg_shell_none; // run the program directly without a shell
142extern int arg_private_dev; // private dev directory
143extern int arg_scan; // arp-scan all interfaces
144
145extern int parent_to_child_fds[2];
146extern int child_to_parent_fds[2];
147extern pid_t sandbox_pid;
148
149
150
151#define MAX_ARGS 128 // maximum number of command arguments (argc)
152extern char *fullargv[MAX_ARGS];
153extern int fullargc;
154
155// main.c
156void check_user_namespace(void);
157
158// sandbox.c
159int sandbox(void* sandbox_arg);
160
161// network_main.c
162void net_configure_bridge(Bridge *br, char *dev_name);
163void net_configure_sandbox_ip(Bridge *br);
164void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child);
165void net_check_cfg(void);
166void net_dns_print_name(const char *name);
167void net_dns_print(pid_t pid);
168
169// network.c
170void net_if_up(const char *ifname);
171void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask);
172int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6]);
173int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw);
174void net_ifprint(void);
175void net_bridge_add_interface(const char *bridge, const char *dev);
176uint32_t network_get_defaultgw(void);
177int net_config_mac(const char *ifname, const unsigned char mac[6]);
178int net_get_mac(const char *ifname, unsigned char mac[6]);
179
180// fs.c
181// build /tmp/firejail directory
182void fs_build_firejail_dir(void);
183// build /tmp/firejail/mnt directory
184void fs_build_mnt_dir(void);
185// blacklist files or directoies by mounting empty files on top of them
186void fs_blacklist(const char *homedir);
187//void fs_blacklist(char **blacklist, const char *homedir);
188// remount a directory read-only
189void fs_rdonly(const char *dir);
190// mount /proc and /sys directories
191void fs_proc_sys_dev_boot(void);
192// build a basic read-only filesystem
193void fs_basic_fs(void);
194// mount overlayfs on top of / directory
195void fs_overlayfs(void);
196// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
197void fs_chroot(const char *rootdir);
198int fs_check_chroot_dir(const char *rootdir);
199
200// profile.c
201// find and read the profile specified by name from dir directory
202int profile_find(const char *name, const char *dir);
203// read a profile file
204void profile_read(const char *fname, const char *skip1, const char *skip2);
205// check profile line; if line == 0, this was generated from a command line option
206// return 1 if the command is to be added to the linked list of profile commands
207// return 0 if the command was already executed inside the function
208int profile_check_line(char *ptr, int lineno);
209// add a profile entry in cfg.profile list; use str to populate the list
210void profile_add(char *str);
211
212// list.c
213void list(void);
214void tree(void);
215void top(void);
216void netstats(void);
217
218// usage.c
219void usage(void);
220
221// join.c
222void join(pid_t pid, const char *homedir, int argc, char **argv, int index);
223void join_name(const char *name, const char *homedir, int argc, char **argv, int index);
224void shut(pid_t pid);
225void shut_name(const char *name);
226
227// restricted_shell.c
228extern char *restricted_user;
229int restricted_shell(const char *user);
230
231// arp.c
232// returns 0 if the address is not in use, -1 otherwise
233int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr);
234// assign an IP address using arp scanning
235uint32_t arp_assign(const char *dev, Bridge *br);
236// scan interface (--scan option)
237void arp_scan(const char *dev, uint32_t srcaddr, uint32_t srcmask);
238
239// veth.c
240int net_create_veth(const char *dev, const char *nsdev, unsigned pid);
241int net_create_macvlan(const char *dev, const char *parent, unsigned pid);
242
243// util.c
244void drop_privs(int nogroups);
245void extract_command_name(const char *str);
246void logsignal(int s);
247void logmsg(const char *msg);
248void logargs(int argc, char **argv) ;
249void logerr(const char *msg);
250int copy_file(const char *srcname, const char *destname);
251char *get_link(const char *fname);
252int is_dir(const char *fname);
253int is_link(const char *fname);
254char *line_remove_spaces(const char *buf);
255char *split_comma(char *str);
256int not_unsigned(const char *str);
257int find_child(pid_t parent, pid_t *child);
258void check_private_dir(void);
259void update_map(char *mapping, char *map_file);
260void wait_for_other(int fd);
261void notify_other(int fd);
262
263// fs_var.c
264void fs_var_log(void); // mounting /var/log
265void fs_var_lib(void); // various other fixes for software in /var directory
266void fs_var_cache(void); // various other fixes for software in /var/cache directory
267void fs_var_run(void);
268void fs_var_lock(void);
269void fs_var_tmp(void);
270void fs_var_utmp(void);
271void dbg_test_dir(const char *dir);
272
273// fs_dev.c
274void fs_dev_shm(void);
275void fs_private_dev(void);
276
277// fs_home.c
278// private mode (--private)
279void fs_private(void);
280// private mode (--private=homedir)
281void fs_private_homedir(void);
282// private mode (--private.keep=list)
283void fs_private_home_list(void);
284// check directory linst specified by user (--private.keep option) - exit if it fails
285void fs_check_home_list(void);
286// check new private home directory (--private= option) - exit if it fails
287void fs_check_private_dir(void);
288
289
290// seccomp.c
291int seccomp_filter_drop(void);
292int seccomp_filter_keep(void);
293void seccomp_set(void);
294void seccomp_print_filter_name(const char *name);
295void seccomp_print_filter(pid_t pid);
296
297// caps.c
298int caps_default_filter(void);
299void caps_print(void);
300void caps_drop_all(void);
301void caps_set(uint64_t caps);
302int caps_check_list(const char *clist, void (*callback)(int));
303void caps_drop_list(const char *clist);
304void caps_keep_list(const char *clist);
305void caps_print_filter(pid_t pid);
306void caps_print_filter_name(const char *name);
307
308// syscall.c
309const char *syscall_find_nr(int nr);
310// return -1 if error, 0 if no error
311int syscall_check_list(const char *slist, void (*callback)(int));
312// print all available syscalls
313void syscall_print(void);
314
315// fs_trace.c
316void fs_trace_preload(void);
317void fs_trace(void);
318
319// fs_hostname.c
320void fs_hostname(const char *hostname);
321void fs_resolvconf(void);
322
323// rlimit.c
324void set_rlimits(void);
325
326// cpu.c
327void read_cpu_list(const char *str);
328void set_cpu_affinity(void);
329void load_cpu(const char *fname);
330void save_cpu(void);
331
332// cgroup.c
333void save_cgroup(void);
334void load_cgroup(const char *fname);
335void set_cgroup(const char *path);
336
337// output.c
338void check_output(int argc, char **argv);
339
340// netfilter.c
341void check_netfilter_file(const char *fname);
342void netfilter(const char *fname);
343
344// bandwidth.c
345void shm_create_firejail_dir(void);
346void bandwidth_shm_del_file(pid_t pid);
347void bandwidth_shm_set(pid_t pid, const char *dev, int down, int up);
348void bandwidth_name(const char *name, const char *command, const char *dev, int down, int up);
349void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up);
350void network_shm_del_file(pid_t pid);
351void network_shm_set_file(pid_t pid);
352
353
354#endif \ No newline at end of file
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
new file mode 100644
index 000000000..1fc1c0942
--- /dev/null
+++ b/src/firejail/fs.c
@@ -0,0 +1,825 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <errno.h>
28
29// build /tmp/firejail directory
30void fs_build_firejail_dir(void) {
31 struct stat s;
32
33 if (stat(FIREJAIL_DIR, &s)) {
34 if (arg_debug)
35 printf("Creating %s directory\n", FIREJAIL_DIR);
36 /* coverity[toctou] */
37 int rv = mkdir(FIREJAIL_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
38 if (rv == -1)
39 errExit("mkdir");
40 if (chown(FIREJAIL_DIR, 0, 0) < 0)
41 errExit("chown");
42 if (chmod(FIREJAIL_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
43 errExit("chmod");
44 }
45 else { // check /tmp/firejail directory belongs to root end exit if doesn't!
46 if (s.st_uid != 0 || s.st_gid != 0) {
47 fprintf(stderr, "Error: non-root %s directory, exiting...\n", FIREJAIL_DIR);
48 exit(1);
49 }
50 }
51}
52
53
54// build /tmp/firejail/mnt directory
55static int tmpfs_mounted = 0;
56void fs_build_mnt_dir(void) {
57 struct stat s;
58 fs_build_firejail_dir();
59
60 // create /tmp/firejail directory
61 if (stat(MNT_DIR, &s)) {
62 if (arg_debug)
63 printf("Creating %s directory\n", MNT_DIR);
64 /* coverity[toctou] */
65 int rv = mkdir(MNT_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
66 if (rv == -1)
67 errExit("mkdir");
68 if (chown(MNT_DIR, 0, 0) < 0)
69 errExit("chown");
70 if (chmod(MNT_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
71 errExit("chmod");
72 }
73
74 // ... and mount tmpfs on top of it
75 if (!tmpfs_mounted) {
76 // mount tmpfs on top of /tmp/firejail/mnt
77 if (arg_debug)
78 printf("Mounting tmpfs on %s directory\n", MNT_DIR);
79 if (mount("tmpfs", MNT_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
80 errExit("mounting /tmp/firejail/mnt");
81 tmpfs_mounted = 1;
82 }
83}
84
85// build /tmp/firejail/overlay directory
86void fs_build_overlay_dir(void) {
87 struct stat s;
88 fs_build_firejail_dir();
89
90 // create /tmp/firejail directory
91 if (stat(OVERLAY_DIR, &s)) {
92 if (arg_debug)
93 printf("Creating %s directory\n", MNT_DIR);
94 /* coverity[toctou] */
95 int rv = mkdir(OVERLAY_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
96 if (rv == -1)
97 errExit("mkdir");
98 if (chown(OVERLAY_DIR, 0, 0) < 0)
99 errExit("chown");
100 if (chmod(OVERLAY_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
101 errExit("chmod");
102 }
103}
104
105
106
107
108
109//***********************************************
110// process profile file
111//***********************************************
112typedef enum {
113 BLACKLIST_FILE,
114 MOUNT_READONLY,
115 MOUNT_TMPFS,
116 OPERATION_MAX
117} OPERATION;
118
119
120static char *create_empty_dir(void) {
121 struct stat s;
122 fs_build_firejail_dir();
123
124 if (stat(RO_DIR, &s)) {
125 /* coverity[toctou] */
126 int rv = mkdir(RO_DIR, S_IRUSR | S_IXUSR);
127 if (rv == -1)
128 errExit("mkdir");
129 if (chown(RO_DIR, 0, 0) < 0)
130 errExit("chown");
131 }
132
133 return RO_DIR;
134}
135
136static char *create_empty_file(void) {
137 struct stat s;
138 fs_build_firejail_dir();
139
140 if (stat(RO_FILE, &s)) {
141 /* coverity[toctou] */
142 FILE *fp = fopen(RO_FILE, "w");
143 if (!fp)
144 errExit("fopen");
145 fclose(fp);
146 if (chown(RO_FILE, 0, 0) < 0)
147 errExit("chown");
148 if (chmod(RO_FILE, S_IRUSR) < 0)
149 errExit("chown");
150 }
151
152 return RO_FILE;
153}
154
155static void disable_file(OPERATION op, const char *fname, const char *emptydir, const char *emptyfile) {
156 assert(fname);
157 assert(emptydir);
158 assert(emptyfile);
159 assert(op <OPERATION_MAX);
160
161 // if the file is a link, follow the link
162 char *lnk = NULL;
163 if (is_link(fname)) {
164 lnk = get_link(fname);
165 if (lnk)
166 fname = lnk;
167 else
168 fprintf(stderr, "Warning: cannot follow link %s, skipping...\n", fname);
169 }
170
171 // if the file is not present, do nothing
172 struct stat s;
173 if (stat(fname, &s) == -1) {
174 if (lnk)
175 free(lnk);
176 return;
177 }
178
179 // modify the file
180 if (op == BLACKLIST_FILE) {
181 if (arg_debug)
182 printf("Disable %s\n", fname);
183 if (S_ISDIR(s.st_mode)) {
184 if (mount(emptydir, fname, "none", MS_BIND, "mode=400,gid=0") < 0)
185 errExit("disable file");
186 }
187 else {
188 if (mount(emptyfile, fname, "none", MS_BIND, "mode=400,gid=0") < 0)
189 errExit("disable file");
190 }
191 }
192 else if (op == MOUNT_READONLY) {
193 if (arg_debug)
194 printf("Mounting read-only %s\n", fname);
195 fs_rdonly(fname);
196 }
197 else if (op == MOUNT_TMPFS) {
198 if (S_ISDIR(s.st_mode)) {
199 if (arg_debug)
200 printf("Mounting tmpfs on %s\n", fname);
201 // preserve owner and mode for the directory
202 if (mount("tmpfs", fname, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, 0) < 0)
203 errExit("mounting tmpfs");
204 /* coverity[toctou] */
205 if (chown(fname, s.st_uid, s.st_gid) == -1)
206 errExit("mounting tmpfs chmod");
207 }
208 else
209 printf("Warning: %s is not a directory; cannot mount a tmpfs on top of it.\n", fname);
210 }
211 else
212 assert(0);
213
214 if (lnk)
215 free(lnk);
216}
217
218static void globbing(OPERATION op, const char *fname, const char *emptydir, const char *emptyfile) {
219 assert(fname);
220 assert(emptydir);
221 assert(emptyfile);
222
223 // filename globbing: expand * macro and continue processing for every single file
224 if (strchr(fname, '*')) {
225 glob_t globbuf;
226 globbuf.gl_offs = 0;
227 glob(fname, GLOB_DOOFFS, NULL, &globbuf);
228 int i;
229 for (i = 0; i < globbuf.gl_pathc; i++) {
230 assert(globbuf.gl_pathv[i]);
231 disable_file(op, globbuf.gl_pathv[i], emptydir, emptyfile);
232 }
233 }
234 else
235 disable_file(op, fname, emptydir, emptyfile);
236}
237
238static void expand_path(OPERATION op, const char *path, const char *fname, const char *emptydir, const char *emptyfile) {
239 assert(path);
240 assert(fname);
241 assert(emptydir);
242 assert(emptyfile);
243 char newname[strlen(path) + strlen(fname) + 1];
244 sprintf(newname, "%s%s", path, fname);
245
246 globbing(op, newname, emptydir, emptyfile);
247}
248
249// blacklist files or directoies by mounting empty files on top of them
250void fs_blacklist(const char *homedir) {
251 ProfileEntry *entry = cfg.profile;
252 if (!entry)
253 return;
254
255 char *emptydir = create_empty_dir();
256 char *emptyfile = create_empty_file();
257
258 while (entry) {
259 OPERATION op = OPERATION_MAX;
260 char *ptr;
261
262 // process blacklist command
263 if (strncmp(entry->data, "bind", 4) == 0) {
264 char *dname1 = entry->data + 5;
265 char *dname2 = split_comma(dname1);
266 if (dname2 == NULL) {
267 fprintf(stderr, "Error: second directory missing in bind command\n");
268 entry = entry->next;
269 continue;
270 }
271 struct stat s;
272 if (stat(dname1, &s) == -1) {
273 fprintf(stderr, "Error: cannot find directories for bind command\n");
274 entry = entry->next;
275 continue;
276 }
277 if (stat(dname2, &s) == -1) {
278 fprintf(stderr, "Error: cannot find directories for bind command\n");
279 entry = entry->next;
280 continue;
281 }
282
283 // mount --bind olddir newdir
284 if (arg_debug)
285 printf("Mount-bind %s on top of %s\n", dname1, dname2);
286 // preserve dname2 mode and ownership
287 if (mount(dname1, dname2, NULL, MS_BIND|MS_REC, NULL) < 0)
288 errExit("mount bind");
289 /* coverity[toctou] */
290 if (chown(dname2, s.st_uid, s.st_gid) == -1)
291 errExit("mount-bind chown");
292 /* coverity[toctou] */
293 if (chmod(dname2, s.st_mode) == -1)
294 errExit("mount-bind chmod");
295
296 entry = entry->next;
297 continue;
298 }
299
300 // process blacklist command
301 if (strncmp(entry->data, "blacklist", 9) == 0) {
302 ptr = entry->data + 10;
303 op = BLACKLIST_FILE;
304 }
305 else if (strncmp(entry->data, "read-only", 9) == 0) {
306 ptr = entry->data + 10;
307 op = MOUNT_READONLY;
308 }
309 else if (strncmp(entry->data, "tmpfs", 5) == 0) {
310 ptr = entry->data + 6;
311 op = MOUNT_TMPFS;
312 }
313 else {
314 fprintf(stderr, "Error: invalid profile line %s\n", entry->data);
315 entry = entry->next;
316 continue;
317 }
318
319 // replace home macro in blacklist array
320 char *new_name = NULL;
321 if (strncmp(ptr, "${HOME}", 7) == 0) {
322 if (asprintf(&new_name, "%s%s", homedir, ptr + 7) == -1)
323 errExit("asprintf");
324 ptr = new_name;
325 }
326
327 // expand path macro - look for the file in /bin, /usr/bin, /sbin and /usr/sbin directories
328 if (strncmp(ptr, "${PATH}", 7) == 0) {
329 expand_path(op, "/bin", ptr + 7, emptydir, emptyfile);
330 expand_path(op, "/sbin", ptr + 7, emptydir, emptyfile);
331 expand_path(op, "/usr/bin", ptr + 7, emptydir, emptyfile);
332 expand_path(op, "/usr/sbin", ptr + 7, emptydir, emptyfile);
333 }
334 else
335 globbing(op, ptr, emptydir, emptyfile);
336
337 if (new_name)
338 free(new_name);
339 entry = entry->next;
340 }
341}
342
343//***********************************************
344// mount namespace
345//***********************************************
346
347// remount a directory read-only
348void fs_rdonly(const char *dir) {
349 assert(dir);
350 // check directory exists
351 struct stat s;
352 int rv = stat(dir, &s);
353 if (rv == 0) {
354 // mount --bind /bin /bin
355 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0)
356 errExit("mount read-only");
357 // mount --bind -o remount,ro /bin
358 if (mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0)
359 errExit("mount read-only");
360 }
361}
362void fs_rdonly_noexit(const char *dir) {
363 assert(dir);
364 // check directory exists
365 struct stat s;
366 int rv = stat(dir, &s);
367 if (rv == 0) {
368 int merr = 0;
369 // mount --bind /bin /bin
370 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0)
371 merr = 1;
372 // mount --bind -o remount,ro /bin
373 if (mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0)
374 merr = 1;
375 if (merr)
376 fprintf(stderr, "Warning: cannot mount %s read-only\n", dir);
377 }
378}
379
380// mount /proc and /sys directories
381void fs_proc_sys_dev_boot(void) {
382 struct stat s;
383
384 if (arg_debug)
385 printf("Remounting /proc and /proc/sys filesystems\n");
386 if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_REC, NULL) < 0)
387 errExit("mounting /proc");
388
389 // remount /proc/sys readonly
390 if (mount("/proc/sys", "/proc/sys", NULL, MS_BIND | MS_REC, NULL) < 0)
391 errExit("mounting /proc/sys");
392
393 if (mount(NULL, "/proc/sys", NULL, MS_BIND | MS_REMOUNT | MS_RDONLY | MS_REC, NULL) < 0)
394 errExit("mounting /proc/sys");
395
396
397 /* Mount a version of /sys that describes the network namespace */
398 if (arg_debug)
399 printf("Remounting /sys directory\n");
400 if (umount2("/sys", MNT_DETACH) < 0)
401 fprintf(stderr, "Warning: failed to unmount /sys\n");
402 if (mount("sysfs", "/sys", "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REC, NULL) < 0)
403 fprintf(stderr, "Warning: failed to mount /sys\n");
404
405// if (mount("sysfs", "/sys", "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REC, NULL) < 0)
406// errExit("mounting /sys");
407
408
409 // mounting firejail kernel module files
410 if (stat("/proc/firejail-uptime", &s) == 0) {
411 errno = 0;
412 FILE *fp = fopen("/proc/firejail", "w");
413 int cnt = 0;
414 while (errno == EBUSY && cnt < 10) {
415 if (!fp) {
416 int s = random();
417 s /= 200000;
418 usleep(s);
419 fp = fopen("/proc/firejail", "w");
420 }
421 else
422 break;
423 }
424 if (!fp) {
425 fprintf(stderr, "Error: cannot register sandbox with firejail-lkm\n");
426 exit(1);
427 }
428 if (fp) {
429 // registration
430 fprintf(fp, "register\n");
431 fflush(0);
432 // filtering x11 connect calls
433 if (arg_nox11) {
434 fprintf(fp, "no connect unix /tmp/.X11\n");
435 fflush(0);
436 printf("X11 access disabled\n");
437 }
438 if (arg_nodbus) {
439 fprintf(fp, "no connect unix /var/run/dbus/system_bus_socket\n");
440 fflush(0);
441 fprintf(fp, "no connect unix /tmp/dbus\n");
442 fflush(0);
443 printf("D-Bus access disabled\n");
444 }
445 fclose(fp);
446 if (mount("/proc/firejail-uptime", "/proc/uptime", NULL, MS_BIND|MS_REC, NULL) < 0)
447 fprintf(stderr, "Warning: cannot mount /proc/firejail-uptime\n");
448 }
449 }
450
451 // Disable SysRq
452 // a linux box can be shut down easily using the following commands (as root):
453 // # echo 1 > /proc/sys/kernel/sysrq
454 // #echo b > /proc/sysrq-trigger
455 // for more information see https://www.kernel.org/doc/Documentation/sysrq.txt
456 if (arg_debug)
457 printf("Disable /proc/sysrq-trigger\n");
458 fs_rdonly_noexit("/proc/sysrq-trigger");
459
460 // disable hotplug and uevent_helper
461 if (arg_debug)
462 printf("Disable /proc/sys/kernel/hotplug\n");
463 fs_rdonly_noexit("/proc/sys/kernel/hotplug");
464 if (arg_debug)
465 printf("Disable /sys/kernel/uevent_helper\n");
466 fs_rdonly_noexit("/sys/kernel/uevent_helper");
467
468 // read-only /proc/irq and /proc/bus
469 if (arg_debug)
470 printf("Disable /proc/irq\n");
471 fs_rdonly_noexit("/proc/irq");
472 if (arg_debug)
473 printf("Disable /proc/bus\n");
474 fs_rdonly_noexit("/proc/bus");
475
476 // disable /proc/kcore
477 disable_file(BLACKLIST_FILE, "/proc/kcore", "not used", "/dev/null");
478
479 // disable /proc/kallsyms
480 disable_file(BLACKLIST_FILE, "/proc/kallsyms", "not used", "/dev/null");
481
482 // disable /boot
483 if (stat("/boot", &s) == 0) {
484 if (arg_debug)
485 printf("Mounting a new /boot directory\n");
486 if (mount("tmpfs", "/boot", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
487 errExit("mounting /boot directory");
488 }
489
490 // disable /dev/port
491 if (stat("/dev/port", &s) == 0) {
492 disable_file(BLACKLIST_FILE, "/dev/port", "not used", "/dev/null");
493 }
494}
495
496static void sanitize_home(void) {
497 // extract current /home directory data
498 struct dirent *dir;
499 DIR *d = opendir("/home");
500 if (d == NULL)
501 return;
502
503 char *emptydir = create_empty_dir();
504 while ((dir = readdir(d))) {
505 if(strcmp(dir->d_name, "." ) == 0 || strcmp(dir->d_name, ".." ) == 0)
506 continue;
507
508 if (dir->d_type == DT_DIR ) {
509 // get properties
510 struct stat s;
511 char *name;
512 if (asprintf(&name, "/home/%s", dir->d_name) == -1)
513 continue;
514 if (stat(name, &s) == -1)
515 continue;
516 if (S_ISLNK(s.st_mode)) {
517 free(name);
518 continue;
519 }
520
521 if (strcmp(name, cfg.homedir) == 0)
522 continue;
523
524// printf("directory %u %u:%u #%s#\n",
525// s.st_mode,
526// s.st_uid,
527// s.st_gid,
528// name);
529
530 // disable directory
531 disable_file(BLACKLIST_FILE, name, emptydir, "not used");
532 free(name);
533 }
534 }
535 closedir(d);
536}
537
538
539
540
541
542
543// build a basic read-only filesystem
544void fs_basic_fs(void) {
545 if (arg_debug)
546 printf("Mounting read-only /bin, /sbin, /lib, /lib64, /usr, /etc, /var\n");
547 fs_rdonly("/bin");
548 fs_rdonly("/sbin");
549 fs_rdonly("/lib");
550 fs_rdonly("/lib64");
551 fs_rdonly("/usr");
552 fs_rdonly("/etc");
553 fs_rdonly("/var");
554
555 // update /var directory in order to support multiple sandboxes running on the same root directory
556 if (!arg_private_dev)
557 fs_dev_shm();
558 fs_var_lock();
559 fs_var_tmp();
560 fs_var_log();
561 fs_var_lib();
562 fs_var_cache();
563 fs_var_utmp();
564
565 // only in user mode
566 if (getuid())
567 sanitize_home();
568}
569
570
571// mount overlayfs on top of / directory
572// mounting an overlay and chrooting into it:
573//
574// Old Ubuntu kernel
575// # cd ~
576// # mkdir -p overlay/root
577// # mkdir -p overlay/diff
578// # mount -t overlayfs -o lowerdir=/,upperdir=/root/overlay/diff overlayfs /root/overlay/root
579// # chroot /root/overlay/root
580// to shutdown, first exit the chroot and then unmount the overlay
581// # exit
582// # umount /root/overlay/root
583//
584// Kernels 3.18+
585// # cd ~
586// # mkdir -p overlay/root
587// # mkdir -p overlay/diff
588// # mkdir -p overlay/work
589// # mount -t overlay -o lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work overlay /root/overlay/root
590// # cat /etc/mtab | grep overlay
591// /root/overlay /root/overlay/root overlay rw,relatime,lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work 0 0
592// # chroot /root/overlay/root
593// to shutdown, first exit the chroot and then unmount the overlay
594// # exit
595// # umount /root/overlay/root
596
597
598// to do: fix the code below; also, it might work without /dev; impose seccomp/caps filters when not root
599#include <sys/utsname.h>
600void fs_overlayfs(void) {
601 // check kernel version
602 struct utsname u;
603 int rv = uname(&u);
604 if (rv != 0)
605 errExit("uname");
606 int major;
607 int minor;
608 if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
609 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
610 exit(1);
611 }
612
613 if (arg_debug)
614 printf("Linux kernel version %d.%d\n", major, minor);
615 int oldkernel = 0;
616 if (major < 3) {
617 fprintf(stderr, "Error: minimum kernel version required 3.x\n");
618 exit(1);
619 }
620 if (major == 3 && minor < 18)
621 oldkernel = 1;
622
623 // build overlay directories
624 fs_build_mnt_dir();
625
626 char *oroot;
627 if(asprintf(&oroot, "%s/oroot", MNT_DIR) == -1)
628 errExit("asprintf");
629 if (mkdir(oroot, S_IRWXU | S_IRWXG | S_IRWXO))
630 errExit("mkdir");
631 if (chown(oroot, 0, 0) < 0)
632 errExit("chown");
633 if (chmod(oroot, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
634 errExit("chmod");
635
636 char *odiff;
637 if(asprintf(&odiff, "%s/odiff", MNT_DIR) == -1)
638 errExit("asprintf");
639 if (mkdir(odiff, S_IRWXU | S_IRWXG | S_IRWXO))
640 errExit("mkdir");
641 if (chown(odiff, 0, 0) < 0)
642 errExit("chown");
643 if (chmod(odiff, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
644 errExit("chmod");
645
646 char *owork;
647 if(asprintf(&owork, "%s/owork", MNT_DIR) == -1)
648 errExit("asprintf");
649 if (mkdir(owork, S_IRWXU | S_IRWXG | S_IRWXO))
650 errExit("mkdir");
651 if (chown(owork, 0, 0) < 0)
652 errExit("chown");
653 if (chmod(owork, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
654 errExit("chmod");
655
656 // mount overlayfs
657 if (arg_debug)
658 printf("Mounting OverlayFS\n");
659 char *option;
660 if (oldkernel) { // old Ubuntu/OpenSUSE kernels
661 if (asprintf(&option, "lowerdir=/,upperdir=%s", odiff) == -1)
662 errExit("asprintf");
663 if (mount("overlayfs", oroot, "overlayfs", MS_MGC_VAL, option) < 0)
664 errExit("mounting overlayfs");
665 }
666 else { // kernel 3.18 or newer
667 if (asprintf(&option, "lowerdir=/,upperdir=%s,workdir=%s", odiff, owork) == -1)
668 errExit("asprintf");
669 if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0)
670 errExit("mounting overlayfs");
671 }
672
673 // mount-bind dev directory
674 if (arg_debug)
675 printf("Mounting /dev\n");
676 char *dev;
677 if (asprintf(&dev, "%s/dev", oroot) == -1)
678 errExit("asprintf");
679 if (mount("/dev", dev, NULL, MS_BIND|MS_REC, NULL) < 0)
680 errExit("mounting /dev");
681
682 // chroot in the new filesystem
683 if (chroot(oroot) == -1)
684 errExit("chroot");
685 // update /var directory in order to support multiple sandboxes running on the same root directory
686 if (!arg_private_dev)
687 fs_dev_shm();
688 fs_var_lock();
689 fs_var_tmp();
690 fs_var_log();
691 fs_var_lib();
692 fs_var_cache();
693 fs_var_utmp();
694
695 // only in user mode
696 if (getuid())
697 sanitize_home();
698
699 // cleanup and exit
700 free(option);
701 free(oroot);
702 free(odiff);
703}
704
705
706
707#ifdef HAVE_CHROOT
708// return 1 if error
709int fs_check_chroot_dir(const char *rootdir) {
710 assert(rootdir);
711 struct stat s;
712 char *name;
713
714 // check /dev
715 if (asprintf(&name, "%s/dev", rootdir) == -1)
716 errExit("asprintf");
717 if (stat(name, &s) == -1) {
718 fprintf(stderr, "Error: cannot find /dev in chroot directory\n");
719 return 1;
720 }
721 free(name);
722
723 // check /var/tmp
724 if (asprintf(&name, "%s/var/tmp", rootdir) == -1)
725 errExit("asprintf");
726 if (stat(name, &s) == -1) {
727 fprintf(stderr, "Error: cannot find /var/tmp in chroot directory\n");
728 return 1;
729 }
730 free(name);
731
732 // check /proc
733 if (asprintf(&name, "%s/proc", rootdir) == -1)
734 errExit("asprintf");
735 if (stat(name, &s) == -1) {
736 fprintf(stderr, "Error: cannot find /proc in chroot directory\n");
737 return 1;
738 }
739 free(name);
740
741 // check /proc
742 if (asprintf(&name, "%s/tmp", rootdir) == -1)
743 errExit("asprintf");
744 if (stat(name, &s) == -1) {
745 fprintf(stderr, "Error: cannot find /tmp in chroot directory\n");
746 return 1;
747 }
748 free(name);
749
750 // check /bin/bash
751 if (asprintf(&name, "%s/bin/bash", rootdir) == -1)
752 errExit("asprintf");
753 if (stat(name, &s) == -1) {
754 fprintf(stderr, "Error: cannot find /bin/bash in chroot directory\n");
755 return 1;
756 }
757 free(name);
758
759 return 0;
760}
761
762// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
763void fs_chroot(const char *rootdir) {
764 assert(rootdir);
765
766 //***********************************
767 // mount-bind a /dev in rootdir
768 //***********************************
769 // mount /dev
770 char *newdev;
771 if (asprintf(&newdev, "%s/dev", rootdir) == -1)
772 errExit("asprintf");
773 if (arg_debug)
774 printf("Mounting /dev on %s\n", newdev);
775 if (mount("/dev", newdev, NULL, MS_BIND|MS_REC, NULL) < 0)
776 errExit("mounting /dev");
777
778 // some older distros don't have a /run directory
779 // create one by default
780 // no exit on error, let the user deal with any problems
781 char *rundir;
782 if (asprintf(&rundir, "%s/run", rootdir) == -1)
783 errExit("asprintf");
784 if (!is_dir(rundir)) {
785 int rv = mkdir(rundir, S_IRWXU | S_IRWXG | S_IRWXO);
786 (void) rv;
787 rv = chown(rundir, 0, 0);
788 (void) rv;
789 }
790
791 // copy /etc/resolv.conf in chroot directory
792 // if resolv.conf in chroot is a symbolic link, this will fail
793 // no exit on error, let the user deal with the problem
794 char *fname;
795 if (asprintf(&fname, "%s/etc/resolv.conf", rootdir) == -1)
796 errExit("asprintf");
797 if (arg_debug)
798 printf("Updating /etc/resolv.conf in %s\n", fname);
799 if (copy_file("/etc/resolv.conf", fname) == -1)
800 fprintf(stderr, "Warning: /etc/resolv.conf not initialized\n");
801
802 // chroot into the new directory
803 if (arg_debug)
804 printf("Chrooting into %s\n", rootdir);
805 if (chroot(rootdir) < 0)
806 errExit("chroot");
807
808 // update /var directory in order to support multiple sandboxes running on the same root directory
809 if (!arg_private_dev)
810 fs_dev_shm();
811 fs_var_lock();
812 fs_var_tmp();
813 fs_var_log();
814 fs_var_lib();
815 fs_var_cache();
816 fs_var_utmp();
817
818 // only in user mode
819 if (getuid())
820 sanitize_home();
821
822}
823#endif
824
825
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
new file mode 100644
index 000000000..80bd11582
--- /dev/null
+++ b/src/firejail/fs_dev.c
@@ -0,0 +1,163 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <pwd.h>
28#ifndef _BSD_SOURCE
29#define _BSD_SOURCE
30#endif
31#include <sys/types.h>
32
33static void create_char_dev(const char *path, mode_t mode, int major, int minor) {
34 dev_t dev = makedev(major, minor);
35 int rv = mknod(path, S_IFCHR | mode, dev);
36 if (rv == -1)
37 goto errexit;
38
39
40 if (chmod(path, mode) < 0)
41 goto errexit;
42 if (chown(path, 0, 0) < 0)
43 goto errexit;
44
45 return;
46
47errexit:
48 fprintf(stderr, "Error: cannot create %s device\n", path);
49 exit(1);
50}
51
52static void create_link(const char *oldpath, const char *newpath) {
53 if (symlink(oldpath, newpath) == -1)
54 goto errexit;
55 if (chown(newpath, 0, 0) < 0)
56 goto errexit;
57 return;
58
59errexit:
60 fprintf(stderr, "Error: cannot create %s device\n", newpath);
61 exit(1);
62}
63
64void fs_private_dev(void){
65 // install a new /dev directory
66 if (arg_debug)
67 printf("Mounting tmpfs on /dev\n");
68 if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
69 errExit("mounting /dev");
70
71 // create /dev/shm
72 if (arg_debug)
73 printf("Create /dev/shm directory\n");
74 int rv = mkdir("/dev/shm", S_IRWXU | S_IRWXG | S_IRWXO);
75 if (rv == -1)
76 errExit("mkdir");
77 if (chown("/dev/shm", 0, 0) < 0)
78 errExit("chown");
79 if (chmod("/dev/shm", S_IRWXU | S_IRWXG | S_IRWXO) < 0)
80 errExit("chmod");
81
82 // create devices
83 create_char_dev("/dev/zero", 0666, 1, 5); // mknod -m 666 /dev/zero c 1 5
84 create_char_dev("/dev/null", 0666, 1, 3); // mknod -m 666 /dev/null c 1 3
85 create_char_dev("/dev/full", 0666, 1, 7); // mknod -m 666 /dev/full c 1 7
86 create_char_dev("/dev/random", 0666, 1, 8); // Mknod -m 666 /dev/random c 1 8
87 create_char_dev("/dev/urandom", 0666, 1, 9); // mknod -m 666 /dev/urandom c 1 9
88 create_char_dev("/dev/tty", 0666, 5, 0); // mknod -m 666 /dev/tty c 5 0
89#if 0
90 create_dev("/dev/tty0", "mknod -m 666 /dev/tty0 c 4 0");
91 create_dev("/dev/console", "mknod -m 622 /dev/console c 5 1");
92#endif
93
94 // pseudo-terminal
95 rv = mkdir("/dev/pts", 0755);
96 if (rv == -1)
97 errExit("mkdir");
98 if (chown("/dev/pts", 0, 0) < 0)
99 errExit("chown");
100 if (chmod("/dev/pts", 0755) < 0)
101 errExit("chmod");
102 create_char_dev("/dev/pts/ptmx", 0666, 5, 2); //"mknod -m 666 /dev/pts/ptmx c 5 2");
103 create_link("/dev/pts/ptmx", "/dev/ptmx");
104 // mount -vt devpts -o newinstance -o ptmxmode=0666 devpts //dev/pts
105 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance,ptmxmode=0666") < 0)
106 errExit("mounting /dev/pts");
107
108#if 0
109 // stdin, stdout, stderr
110 create_link("/proc/self/fd", "/dev/fd");
111 create_link("/proc/self/fd/0", "/dev/stdin");
112 create_link("/proc/self/fd/1", "/dev/stdout");
113 create_link("/proc/self/fd/2", "/dev/stderr");
114#endif
115}
116
117
118void fs_dev_shm(void) {
119 uid_t uid = getuid(); // set a new shm only if we started as root
120 if (uid)
121 return;
122
123 if (is_dir("/dev/shm")) {
124 if (arg_debug)
125 printf("Mounting tmpfs on /dev/shm\n");
126 if (mount("tmpfs", "/dev/shm", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
127 errExit("mounting /dev/shm");
128 }
129 else {
130 char *lnk = get_link("/dev/shm");
131 if (lnk) {
132 // convert a link such as "../shm" into "/shm"
133 char *lnk2 = lnk;
134 int cnt = 0;
135 while (strncmp(lnk2, "../", 3) == 0) {
136 cnt++;
137 lnk2 = lnk2 + 3;
138 }
139 if (cnt != 0)
140 lnk2 = lnk + (cnt - 1) * 3 + 2;
141
142 if (!is_dir(lnk2)) {
143 // create directory
144 if (mkdir(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
145 errExit("mkdir");
146 if (chown(lnk2, 0, 0))
147 errExit("chown");
148 if (chmod(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
149 errExit("chmod");
150 }
151 if (arg_debug)
152 printf("Mounting tmpfs on %s on behalf of /dev/shm\n", lnk2);
153 if (mount("tmpfs", lnk2, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
154 errExit("mounting /var/tmp");
155 free(lnk);
156 }
157 else {
158 fprintf(stderr, "Warning: /dev/shm not mounted\n");
159 dbg_test_dir("/dev/shm");
160 }
161
162 }
163}
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
new file mode 100644
index 000000000..853e3930b
--- /dev/null
+++ b/src/firejail/fs_home.c
@@ -0,0 +1,494 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/mount.h>
22#include <linux/limits.h>
23#include <glob.h>
24#include <dirent.h>
25#include <fcntl.h>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <sys/wait.h>
29#include <unistd.h>
30#include <grp.h>
31
32static void skel(const char *homedir, uid_t u, gid_t g) {
33 char *fname;
34 // zsh
35 if (arg_zsh) {
36 // copy skel files
37 if (asprintf(&fname, "%s/.zshrc", homedir) == -1)
38 errExit("asprintf");
39 struct stat s;
40 // don't copy it if we already have the file
41 if (stat(fname, &s) == 0)
42 return;
43 if (stat("/etc/skel/.zshrc", &s) == 0) {
44 if (copy_file("/etc/skel/.zshrc", fname) == 0) {
45 if (chown(fname, u, g) == -1)
46 errExit("chown");
47 }
48 }
49 else { //
50 FILE *fp = fopen(fname, "w");
51 if (fp) {
52 fprintf(fp, "\n");
53 fclose(fp);
54 if (chown(fname, u, g) == -1)
55 errExit("chown");
56 if (chmod(fname, S_IRUSR | S_IWUSR) < 0)
57 errExit("chown");
58 }
59 }
60 free(fname);
61 }
62 // csh
63 else if (arg_csh) {
64 // copy skel files
65 if (asprintf(&fname, "%s/.cshrc", homedir) == -1)
66 errExit("asprintf");
67 struct stat s;
68 // don't copy it if we already have the file
69 if (stat(fname, &s) == 0)
70 return;
71 if (stat("/etc/skel/.cshrc", &s) == 0) {
72 if (copy_file("/etc/skel/.cshrc", fname) == 0) {
73 if (chown(fname, u, g) == -1)
74 errExit("chown");
75 }
76 }
77 else { //
78 /* coverity[toctou] */
79 FILE *fp = fopen(fname, "w");
80 if (fp) {
81 fprintf(fp, "\n");
82 fclose(fp);
83 if (chown(fname, u, g) == -1)
84 errExit("chown");
85 if (chmod(fname, S_IRUSR | S_IWUSR) < 0)
86 errExit("chown");
87 }
88 }
89 free(fname);
90 }
91 // bash etc.
92 else {
93 // copy skel files
94 if (asprintf(&fname, "%s/.bashrc", homedir) == -1)
95 errExit("asprintf");
96 struct stat s;
97 // don't copy it if we already have the file
98 if (stat(fname, &s) == 0)
99 return;
100 if (stat("/etc/skel/.bashrc", &s) == 0) {
101 if (copy_file("/etc/skel/.bashrc", fname) == 0) {
102 /* coverity[toctou] */
103 if (chown(fname, u, g) == -1)
104 errExit("chown");
105 }
106 }
107 free(fname);
108 }
109}
110
111static int store_xauthority(void) {
112 // put a copy of .Xauthority in MNT_DIR
113 fs_build_mnt_dir();
114
115 char *src;
116 char *dest;
117 if (asprintf(&src, "%s/.Xauthority", cfg.homedir) == -1)
118 errExit("asprintf");
119 if (asprintf(&dest, "%s/.Xauthority", MNT_DIR) == -1)
120 errExit("asprintf");
121
122 struct stat s;
123 if (stat(src, &s) == 0) {
124 int rv = copy_file(src, dest);
125 if (rv) {
126 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
127 return 0;
128 }
129 return 1; // file copied
130 }
131
132 return 0;
133}
134
135static void copy_xauthority(void) {
136 // put a copy of .Xauthority in MNT_DIR
137 fs_build_mnt_dir();
138
139 char *src;
140 char *dest;
141 if (asprintf(&dest, "%s/.Xauthority", cfg.homedir) == -1)
142 errExit("asprintf");
143 if (asprintf(&src, "%s/.Xauthority", MNT_DIR) == -1)
144 errExit("asprintf");
145 int rv = copy_file(src, dest);
146 if (rv)
147 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
148
149 // set permissions and ownership
150 if (chown(dest, getuid(), getgid()) < 0)
151 errExit("chown");
152 if (chmod(dest, S_IRUSR | S_IWUSR) < 0)
153 errExit("chmod");
154
155 // delete the temporary file
156 unlink(src);
157}
158
159// private mode (--private=homedir):
160// mount homedir on top of /home/user,
161// tmpfs on top of /root in nonroot mode,
162// tmpfs on top of /tmp in root mode,
163// set skel files,
164// restore .Xauthority
165void fs_private_homedir(void) {
166 char *homedir = cfg.homedir;
167 char *private_homedir = cfg.home_private;
168 assert(homedir);
169 assert(private_homedir);
170
171 int xflag = store_xauthority();
172
173 uid_t u = getuid();
174 gid_t g = getgid();
175 struct stat s;
176 if (stat(homedir, &s) == -1) {
177 fprintf(stderr, "Error: cannot find user home directory\n");
178 exit(1);
179 }
180
181
182 // mount bind private_homedir on top of homedir
183 if (arg_debug)
184 printf("Mount-bind %s on top of %s\n", private_homedir, homedir);
185 if (mount(private_homedir, homedir, NULL, MS_BIND|MS_REC, NULL) < 0)
186 errExit("mount bind");
187// preserve mode and ownership
188// if (chown(homedir, s.st_uid, s.st_gid) == -1)
189// errExit("mount-bind chown");
190// if (chmod(homedir, s.st_mode) == -1)
191// errExit("mount-bind chmod");
192
193 if (u != 0) {
194 // mask /root
195 if (arg_debug)
196 printf("Mounting a new /root directory\n");
197 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0)
198 errExit("mounting home directory");
199 }
200 else {
201 // mask /home
202 if (arg_debug)
203 printf("Mounting a new /home directory\n");
204 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
205 errExit("mounting home directory");
206
207 // mask /tmp only in root mode; KDE keeps all kind of sockets in /tmp!
208 if (arg_debug)
209 printf("Mounting a new /tmp directory\n");
210 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
211 errExit("mounting tmp directory");
212 }
213
214
215 skel(homedir, u, g);
216 if (xflag)
217 copy_xauthority();
218}
219
220// private mode (--private):
221// mount tmpfs over /home/user,
222// tmpfs on top of /root in nonroot mode,
223// tmpfs on top of /tmp in root mode
224// set skel files,
225// restore .Xauthority
226void fs_private(void) {
227 char *homedir = cfg.homedir;
228 assert(homedir);
229 uid_t u = getuid();
230 gid_t g = getgid();
231
232 int xflag = store_xauthority();
233
234 // mask /home
235 if (arg_debug)
236 printf("Mounting a new /home directory\n");
237 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
238 errExit("mounting home directory");
239
240 // mask /root
241 if (arg_debug)
242 printf("Mounting a new /root directory\n");
243 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0)
244 errExit("mounting home directory");
245
246 if (u != 0) {
247 // create /home/user
248 if (arg_debug)
249 printf("Create a new user directory\n");
250 int rv = mkdir(homedir, S_IRWXU);
251 if (rv == -1)
252 errExit("mkdir");
253 if (chown(homedir, u, g) < 0)
254 errExit("chown");
255 }
256 else {
257 // mask tmp only in root mode; KDE keeps all kind of sockets in /tmp!
258 if (arg_debug)
259 printf("Mounting a new /tmp directory\n");
260 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
261 errExit("mounting tmp directory");
262 }
263
264 skel(homedir, u, g);
265 if (xflag)
266 copy_xauthority();
267}
268
269static void check_dir_or_file(const char *name) {
270 assert(name);
271 struct stat s;
272 char *fname;
273 if (asprintf(&fname, "%s/%s", cfg.homedir, name) == -1)
274 errExit("asprintf");
275 if (arg_debug)
276 printf("***************Checking %s\n", fname);
277 if (stat(fname, &s) == -1) {
278 fprintf(stderr, "Error: file %s not found.\n", fname);
279 exit(1);
280 }
281
282 // check uid
283 uid_t uid = getuid();
284 gid_t gid = getgid();
285 if (s.st_uid != uid || s.st_gid != gid) {
286 fprintf(stderr, "Error: only files or directories created by the current user are allowed.\n");
287 exit(1);
288 }
289
290 // dir or regular file
291 if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) {
292 free(fname);
293 return;
294 }
295
296 if (!is_link(fname)) {
297 free(fname);
298 return;
299 }
300
301 fprintf(stderr, "Error: invalid file type, %s.\n", fname);
302 exit(1);
303}
304
305// check directory linst specified by user (--private.keep option) - exit if it fails
306void fs_check_home_list(void) {
307 if (strstr(cfg.home_private_keep, "..")) {
308 fprintf(stderr, "Error: invalid private.keep list\n");
309 exit(1);
310 }
311
312 char *dlist = strdup(cfg.home_private_keep);
313 if (!dlist)
314 errExit("strdup");
315
316 char *ptr = strtok(dlist, ",");
317 check_dir_or_file(ptr);
318 while ((ptr = strtok(NULL, ",")) != NULL)
319 check_dir_or_file(ptr);
320
321 free(dlist);
322}
323
324// check new private home directory (--private= option) - exit if it fails
325void fs_check_private_dir(void) {
326 // if the directory starts with ~, expand the home directory
327 if (*cfg.home_private == '~') {
328 char *tmp;
329 if (asprintf(&tmp, "%s%s", cfg.homedir, cfg.home_private + 1) == -1)
330 errExit("asprintf");
331 cfg.home_private = tmp;
332 }
333
334 if (!is_dir(cfg.home_private) || is_link(cfg.home_private) || strstr(cfg.home_private, "..")) {
335 fprintf(stderr, "Error: invalid private directory\n");
336 exit(1);
337 }
338
339 // check home directory and chroot home directory have the same owner
340 struct stat s2;
341 int rv = stat(cfg.home_private, &s2);
342 if (rv < 0) {
343 fprintf(stderr, "Error: cannot find %s directory\n", cfg.home_private);
344 exit(1);
345 }
346
347 struct stat s1;
348 rv = stat(cfg.homedir, &s1);
349 if (rv < 0) {
350 fprintf(stderr, "Error: cannot find %s directory, full path name required\n", cfg.homedir);
351 exit(1);
352 }
353 if (s1.st_uid != s2.st_uid) {
354 printf("Error: the two home directories must have the same owner\n");
355 exit(1);
356 }
357}
358
359#if 0
360static int mkpath(char* file_path, mode_t mode) {
361 assert(file_path && *file_path);
362 char* p;
363 for (p=strchr(file_path+1, '/'); p; p=strchr(p+1, '/')) {
364 *p='\0';
365 if (mkdir(file_path, mode)==-1) {
366 if (errno!=EEXIST) { *p='/'; return -1; }
367 }
368 *p='/';
369 }
370 return 0;
371}
372#endif
373
374static void duplicate(char *fname) {
375 char *cmd;
376
377 // copy the file
378 if (asprintf(&cmd, "cp -a --parents %s/%s %s", cfg.homedir, fname, HOME_DIR) == -1)
379 errExit("asprintf");
380 if (arg_debug)
381 printf("%s\n", cmd);
382 if (system(cmd))
383 errExit("system cp -a --parents");
384 free(cmd);
385}
386
387
388// private mode (--private.keep=list):
389// mount homedir on top of /home/user,
390// tmpfs on top of /root in nonroot mode,
391// tmpfs on top of /tmp in root mode,
392// set skel files,
393// restore .Xauthority
394void fs_private_home_list(void) {
395 char *homedir = cfg.homedir;
396 char *private_list = cfg.home_private_keep;
397 assert(homedir);
398 assert(private_list);
399
400 int xflag = store_xauthority();
401
402 uid_t u = getuid();
403 gid_t g = getgid();
404 struct stat s;
405 if (stat(homedir, &s) == -1) {
406 fprintf(stderr, "Error: cannot find user home directory\n");
407 exit(1);
408 }
409
410 // create /tmp/firejail/mnt/home directory
411 fs_build_mnt_dir();
412 int rv = mkdir(HOME_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
413 if (rv == -1)
414 errExit("mkdir");
415 if (chown(HOME_DIR, u, g) < 0)
416 errExit("chown");
417 if (chmod(HOME_DIR, 0755) < 0)
418 errExit("chmod");
419
420 // copy the list of files in the new home directory
421 // using a new child process without root privileges
422 pid_t child = fork();
423 if (child < 0)
424 errExit("fork");
425 if (child == 0) {
426 if (arg_debug)
427 printf("Copying files in the new home:\n");
428
429 // drop privileges
430 if (setgroups(0, NULL) < 0)
431 errExit("setgroups");
432 if (setgid(getgid()) < 0)
433 errExit("setgid/getgid");
434 if (setuid(getuid()) < 0)
435 errExit("setuid/getuid");
436
437 // copy the list of files in the new home directory
438 char *dlist = strdup(cfg.home_private_keep);
439 if (!dlist)
440 errExit("strdup");
441
442 char *ptr = strtok(dlist, ",");
443 duplicate(ptr);
444
445 while ((ptr = strtok(NULL, ",")) != NULL)
446 duplicate(ptr);
447 free(dlist);
448 exit(0);
449 }
450 // wait for the child to finish
451 waitpid(child, NULL, 0);
452
453 // mount bind private_homedir on top of homedir
454 char *newhome;
455 if (asprintf(&newhome, "%s%s", HOME_DIR, cfg.homedir) == -1)
456 errExit("asprintf");
457
458 if (arg_debug)
459 printf("Mount-bind %s on top of %s\n", newhome, homedir);
460 if (mount(newhome, homedir, NULL, MS_BIND|MS_REC, NULL) < 0)
461 errExit("mount bind");
462// preserve mode and ownership
463// if (chown(homedir, s.st_uid, s.st_gid) == -1)
464// errExit("mount-bind chown");
465// if (chmod(homedir, s.st_mode) == -1)
466// errExit("mount-bind chmod");
467
468 if (u != 0) {
469 // mask /root
470 if (arg_debug)
471 printf("Mounting a new /root directory\n");
472 if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0)
473 errExit("mounting home directory");
474 }
475 else {
476 // mask /home
477 if (arg_debug)
478 printf("Mounting a new /home directory\n");
479 if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
480 errExit("mounting home directory");
481
482 // mask /tmp only in root mode; KDE keeps all kind of sockets in /tmp!
483 if (arg_debug)
484 printf("Mounting a new /tmp directory\n");
485 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
486 errExit("mounting tmp directory");
487 }
488
489 skel(homedir, u, g);
490 if (xflag)
491 copy_xauthority();
492
493}
494
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c
new file mode 100644
index 000000000..fb3fc530e
--- /dev/null
+++ b/src/firejail/fs_hostname.c
@@ -0,0 +1,157 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27
28void fs_hostname(const char *hostname) {
29 struct stat s;
30 fs_build_mnt_dir();
31
32 // create a new /etc/hostname
33 if (stat("/etc/hostname", &s) == 0) {
34 if (arg_debug)
35 printf("Creating a new /etc/hostname file\n");
36 char *fhost;
37 if (asprintf(&fhost, "%s/hostname", MNT_DIR) == -1)
38 errExit("asprintf");
39 FILE *fp = fopen(fhost, "w");
40 if (!fp) {
41 fprintf(stderr, "Error: cannot create %s\n", fhost);
42 free(fhost);
43 exit(1);
44 }
45 fprintf(fp, "%s\n", hostname);
46 fclose(fp);
47
48 // mode and owner
49 if (chown(fhost, 0, 0) < 0)
50 errExit("chown");
51 if (chmod(fhost, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
52 errExit("chmod");
53
54 // bind-mount the file on top of /etc/hostname
55 if (mount(fhost, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0)
56 errExit("mount bind /etc/hostname");
57 free(fhost);
58 }
59
60 // create a new /etc/hosts
61 if (stat("/etc/hosts", &s) == 0) {
62 if (arg_debug)
63 printf("Creating a new /etc/hosts file\n");
64 char *fhost;
65 if (asprintf(&fhost, "%s/hosts", MNT_DIR) == -1)
66 errExit("asprintf");
67 // copy /etc/host into our new file, and modify it on the fly
68 /* coverity[toctou] */
69 FILE *fp1 = fopen("/etc/hosts", "r");
70 if (!fp1) {
71 fprintf(stderr, "Error: cannot open /etc/hosts\n");
72 free(fhost);
73 exit(1);
74 }
75 FILE *fp2 = fopen(fhost, "w");
76 if (!fp2) {
77 fprintf(stderr, "Error: cannot create %s\n", fhost);
78 free(fhost);
79 exit(1);
80 }
81
82 char buf[4096];
83 while (fgets(buf, sizeof(buf), fp1)) {
84 // remove '\n'
85 char *ptr = strchr(buf, '\n');
86 if (ptr)
87 *ptr = '\0';
88
89 // copy line
90 if (strstr(buf, "127.0.0.1"))
91 fprintf(fp2, "%s %s\n", buf, hostname);
92 else
93 fprintf(fp2, "%s\n", buf);
94 }
95 fclose(fp1);
96 fclose(fp2);
97
98 // mode and owner
99 if (chown(fhost, 0, 0) < 0)
100 errExit("chown");
101 if (chmod(fhost, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
102 errExit("chmod");
103
104 // bind-mount the file on top of /etc/hostname
105 if (mount(fhost, "/etc/hosts", NULL, MS_BIND|MS_REC, NULL) < 0)
106 errExit("mount bind /etc/hosts");
107 free(fhost);
108 }
109}
110
111void fs_resolvconf(void) {
112 if (cfg.dns1 == 0)
113 return;
114
115 struct stat s;
116 fs_build_mnt_dir();
117
118 // create a new /etc/hostname
119 if (stat("/etc/resolv.conf", &s) == 0) {
120 if (arg_debug)
121 printf("Creating a new /etc/resolv.conf file\n");
122 char *fname;
123 if (asprintf(&fname, "%s/resolv.conf", MNT_DIR) == -1)
124 errExit("asprintf");
125 FILE *fp = fopen(fname, "w");
126 if (!fp) {
127 fprintf(stderr, "Error: cannot create %s\n", fname);
128 free(fname);
129 exit(1);
130 }
131
132 if (cfg.dns1)
133 fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
134 if (cfg.dns2)
135 fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
136 if (cfg.dns3)
137 fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
138 fclose(fp);
139
140 // mode and owner
141 if (chown(fname, 0, 0) < 0)
142 errExit("chown");
143 if (chmod(fname, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
144 errExit("chmod");
145
146 // bind-mount the file on top of /etc/hostname
147 if (mount(fname, "/etc/resolv.conf", NULL, MS_BIND|MS_REC, NULL) < 0)
148 errExit("mount bind /etc/resolv.conf");
149 free(fname);
150 }
151 else {
152 fprintf(stderr, "Error: cannot set DNS servers, /etc/resolv.conf file is missing\n");
153 exit(1);
154 }
155}
156
157
diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c
new file mode 100644
index 000000000..1c7ef5cbe
--- /dev/null
+++ b/src/firejail/fs_trace.c
@@ -0,0 +1,76 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <pwd.h>
28
29void fs_trace_preload(void) {
30 struct stat s;
31
32 // create an empty /etc/ld.so.preload
33 if (stat("/etc/ld.so.preload", &s)) {
34 if (arg_debug)
35 printf("Creating an empty /etc/ld.so.preload file\n");
36 /* coverity[toctou] */
37 FILE *fp = fopen("/etc/ld.so.preload", "w");
38 if (!fp)
39 errExit("fopen");
40 fclose(fp);
41 if (chown("/etc/ld.so.preload", 0, 0) < 0)
42 errExit("chown");
43 if (chmod("/etc/ld.so.preload", S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
44 errExit("chmod");
45 }
46}
47
48void fs_trace(void) {
49 // create /tmp/firejail/mnt directory
50 fs_build_mnt_dir();
51
52 // create the new ld.so.preload file and mount-bind it
53 if (arg_debug)
54 printf("Create the new ld.so.preload file\n");
55 char *preload;
56 if (asprintf(&preload, "%s/ld.so.preload", MNT_DIR) == -1)
57 errExit("asprintf");
58 FILE *fp = fopen(preload, "w");
59 if (!fp)
60 errExit("fopen");
61 fprintf(fp, "%s/lib/firejail/libtrace.so\n", PREFIX);
62 fclose(fp);
63 if (chown(preload, 0, 0) < 0)
64 errExit("chown");
65 if (chmod(preload, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH ) < 0)
66 errExit("chmod");
67
68 // mount the new preload file
69 if (arg_debug)
70 printf("Mount the new ld.so.preload file\n");
71 if (mount(preload, "/etc/ld.so.preload", NULL, MS_BIND|MS_REC, NULL) < 0)
72 errExit("mount bind ls.so.preload");
73}
74
75
76 \ No newline at end of file
diff --git a/src/firejail/fs_var.c b/src/firejail/fs_var.c
new file mode 100644
index 000000000..ee0f81828
--- /dev/null
+++ b/src/firejail/fs_var.c
@@ -0,0 +1,388 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <pwd.h>
28#include <utmp.h>
29#include <time.h>
30
31typedef struct dirdata_t{
32 struct dirdata_t *next;
33 char *name;
34 mode_t st_mode;
35 uid_t st_uid;
36 gid_t st_gid;
37} DirData;
38
39static DirData *dirlist = NULL;
40
41static void release_all(void) {
42 DirData *ptr = dirlist;
43 while (ptr) {
44 DirData *next = ptr->next;
45 free(ptr->name);
46 free(ptr);
47 ptr = next;
48 }
49 dirlist = NULL;
50}
51
52static void build_list(const char *srcdir) {
53 // extract current /var/log directory data
54 struct dirent *dir;
55 DIR *d = opendir(srcdir);
56 if (d == NULL)
57 return;
58
59 while ((dir = readdir(d))) {
60 if(strcmp(dir->d_name, "." ) == 0 || strcmp(dir->d_name, ".." ) == 0)
61 continue;
62
63 if (dir->d_type == DT_DIR ) {
64 // get properties
65 struct stat s;
66 char *name;
67 if (asprintf(&name, "%s/%s", srcdir, dir->d_name) == -1)
68 continue;
69 if (stat(name, &s) == -1)
70 continue;
71 if (S_ISLNK(s.st_mode)) {
72 free(name);
73 continue;
74 }
75
76// printf("directory %u %u:%u %s\n",
77// s.st_mode,
78// s.st_uid,
79// s.st_gid,
80// dir->d_name);
81
82 DirData *ptr = malloc(sizeof(DirData));
83 if (ptr == NULL)
84 errExit("malloc");
85 memset(ptr, 0, sizeof(DirData));
86 ptr->name = name;
87 ptr->st_mode = s.st_mode;
88 ptr->st_uid = s.st_uid;
89 ptr->st_gid = s.st_gid;
90 ptr->next = dirlist;
91 dirlist = ptr;
92 }
93 }
94 closedir(d);
95}
96
97static void build_dirs(void) {
98 // create directories under /var/log
99 DirData *ptr = dirlist;
100 while (ptr) {
101 if (mkdir(ptr->name, ptr->st_mode))
102 errExit("mkdir");
103 if (chown(ptr->name, ptr->st_uid, ptr->st_gid))
104 errExit("chown");
105 ptr = ptr->next;
106 }
107}
108
109void fs_var_log(void) {
110 build_list("/var/log");
111
112 // create /var/log if it does't exit
113 if (is_dir("/var/log")) {
114 // extract group id for /var/log/wtmp
115 struct stat s;
116 gid_t wtmp_group = 0;
117 if (stat("/var/log/wtmp", &s) == 0)
118 wtmp_group = s.st_gid;
119
120 // mount a tmpfs on top of /var/log
121 if (arg_debug)
122 printf("Mounting tmpfs on /var/log\n");
123 if (mount("tmpfs", "/var/log", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
124 errExit("mounting /var/log");
125
126 build_dirs();
127 release_all();
128
129 // create an empty /var/log/wtmp file
130 /* coverity[toctou] */
131 FILE *fp = fopen("/var/log/wtmp", "w");
132 if (fp)
133 fclose(fp);
134 if (chown("/var/log/wtmp", 0, wtmp_group) < 0)
135 errExit("chown");
136 if (chmod("/var/log/wtmp", S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH ) < 0)
137 errExit("chmod");
138
139 // create an empty /var/log/btmp file
140 fp = fopen("/var/log/btmp", "w");
141 if (fp)
142 fclose(fp);
143 if (chown("/var/log/btmp", 0, wtmp_group) < 0)
144 errExit("chown");
145 if (chmod("/var/log/btmp", S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP) < 0)
146 errExit("chmod");
147 }
148 else
149 fprintf(stderr, "Warning: cannot mount tmpfs in top of /var/log\n");
150}
151
152void fs_var_lib(void) {
153 struct stat s;
154
155 // ISC DHCP multiserver
156 if (stat("/var/lib/dhcp", &s) == 0) {
157 if (arg_debug)
158 printf("Mounting tmpfs on /var/lib/dhcp\n");
159 if (mount("tmpfs", "/var/lib/dhcp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
160 errExit("mounting /var/lib/dhcp");
161
162 // isc dhcp server requires a /var/lib/dhcp/dhcpd.leases file
163 FILE *fp = fopen("/var/lib/dhcp/dhcpd.leases", "w");
164
165 if (fp) {
166 fprintf(fp, "\n");
167 fclose(fp);
168 if (chown("/var/lib/dhcp/dhcpd.leases", 0, 0) == -1)
169 errExit("chown");
170 if (chmod("/var/lib/dhcp/dhcpd.leases", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
171 errExit("chmod");
172 }
173 }
174
175 // nginx multiserver
176 if (stat("/var/lib/nginx", &s) == 0) {
177 if (arg_debug)
178 printf("Mounting tmpfs on /var/lib/nginx\n");
179 if (mount("tmpfs", "/var/lib/nginx", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
180 errExit("mounting /var/lib/nginx");
181 }
182
183 // net-snmp multiserver
184 if (stat("/var/lib/snmp", &s) == 0) {
185 if (arg_debug)
186 printf("Mounting tmpfs on /var/lib/snmp\n");
187 if (mount("tmpfs", "/var/lib/snmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
188 errExit("mounting /var/lib/snmp");
189 }
190
191 // this is where sudo remembers its state
192 if (stat("/var/lib/sudo", &s) == 0) {
193 if (arg_debug)
194 printf("Mounting tmpfs on /var/lib/sudo\n");
195 if (mount("tmpfs", "/var/lib/sudo", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
196 errExit("mounting /var/lib/sudo");
197 }
198}
199
200void fs_var_cache(void) {
201 struct stat s;
202
203 if (stat("/var/cache/apache2", &s) == 0) {
204 if (arg_debug)
205 printf("Mounting tmpfs on /var/cache/apache2\n");
206 if (mount("tmpfs", "/var/cache/apache2", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
207 errExit("mounting /var/cahce/apache2");
208 }
209
210 if (stat("/var/cache/lighttpd", &s) == 0) {
211 if (arg_debug)
212 printf("Mounting tmpfs on /var/cache/lighttpd\n");
213 if (mount("tmpfs", "/var/cache/lighttpd", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
214 errExit("mounting /var/cache/lighttpd");
215
216 struct passwd *p = getpwnam("www-data");
217 uid_t uid = 0;
218 gid_t gid = 0;
219 if (p) {
220 uid = p->pw_uid;
221 gid = p->pw_gid;
222 }
223
224 int rv = mkdir("/var/cache/lighttpd/compress", S_IRWXU | S_IRWXG | S_IRWXO);
225 if (rv == -1)
226 errExit("mkdir");
227 if (chown("/var/cache/lighttpd/compress", uid, gid) < 0)
228 errExit("chown");
229
230 rv = mkdir("/var/cache/lighttpd/uploads", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
231 if (rv == -1)
232 errExit("mkdir");
233 if (chown("/var/cache/lighttpd/uploads", uid, gid) < 0)
234 errExit("chown");
235 }
236}
237
238void dbg_test_dir(const char *dir) {
239 if (arg_debug) {
240 if (is_dir(dir))
241 printf("%s is a directory\n", dir);
242 if (is_link(dir)) {
243 char *lnk = get_link(dir);
244 if (lnk) {
245 printf("%s is a symbolic link to %s\n", dir, lnk);
246 free(lnk);
247 }
248 }
249 }
250}
251
252
253void fs_var_lock(void) {
254
255 if (is_dir("/var/lock")) {
256 if (arg_debug)
257 printf("Mounting tmpfs on /var/lock\n");
258 if (mount("tmpfs", "/var/lock", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
259 errExit("mounting /lock");
260 }
261 else {
262 char *lnk = get_link("/var/lock");
263 if (lnk) {
264 // convert a link such as "../shm" into "/shm"
265 char *lnk2 = lnk;
266 int cnt = 0;
267 while (strncmp(lnk2, "../", 3) == 0) {
268 cnt++;
269 lnk2 = lnk2 + 3;
270 }
271 if (cnt != 0)
272 lnk2 = lnk + (cnt - 1) * 3 + 2;
273
274 if (!is_dir(lnk2)) {
275 // create directory
276 if (mkdir(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
277 errExit("mkdir");
278 if (chown(lnk2, 0, 0))
279 errExit("chown");
280 if (chmod(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
281 errExit("chmod");
282 }
283 if (arg_debug)
284 printf("Mounting tmpfs on %s on behalf of /var/lock\n", lnk2);
285 if (mount("tmpfs", lnk2, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
286 errExit("mounting /var/lock");
287 free(lnk);
288 }
289 else {
290 fprintf(stderr, "Warning: /var/lock not mounted\n");
291 dbg_test_dir("/var/lock");
292 }
293 }
294}
295
296void fs_var_tmp(void) {
297
298 if (!is_link("/var/tmp")) {
299 if (arg_debug)
300 printf("Mounting tmpfs on /var/tmp\n");
301 if (mount("tmpfs", "/var/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
302 errExit("mounting /var/tmp");
303 }
304 else {
305 fprintf(stderr, "Warning: /var/tmp not mounted\n");
306 dbg_test_dir("/var/tmp");
307 }
308}
309
310void fs_var_utmp(void) {
311 struct stat s;
312
313 // extract utmp group id
314 gid_t utmp_group = 0;
315 if (stat("/var/run/utmp", &s) == 0)
316 utmp_group = s.st_gid;
317 else {
318 fprintf(stderr, "Warning: cannot find /var/run/utmp\n");
319 return;
320 }
321
322 // create /tmp/firejail/mnt directory
323 fs_build_mnt_dir();
324
325 // create a new utmp file
326 if (arg_debug)
327 printf("Create the new utmp file\n");
328 char *utmp;
329 if (asprintf(&utmp, "%s/utmp", MNT_DIR) == -1)
330 errExit("asprintf");
331 FILE *fp = fopen(utmp, "w");
332 if (!fp)
333 errExit("fopen");
334
335 // read current utmp
336 struct utmp *u;
337 struct utmp u_boot;
338 setutent();
339 while ((u = getutent()) != NULL) {
340 if (u->ut_type == BOOT_TIME) {
341 memcpy(&u_boot, u, sizeof(u_boot));
342 u_boot.ut_tv.tv_sec = (unsigned) time(NULL);
343 }
344 }
345 endutent();
346
347 // save new utmp file
348 fwrite(&u_boot, sizeof(u_boot), 1, fp);
349 fclose(fp);
350 if (chown(utmp, 0, utmp_group) < 0)
351 errExit("chown");
352 if (chmod(utmp, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH ) < 0)
353 errExit("chmod");
354
355 // mount the new utmp file
356 if (arg_debug)
357 printf("Mount the new utmp file\n");
358 if (mount(utmp, "/var/run/utmp", NULL, MS_BIND|MS_REC, NULL) < 0)
359 errExit("mount bind utmp");
360}
361
362
363#if 0
364Testing servers:
365
366brctl addbr br0
367ifconfig br0 10.10.20.1/24
368
369apt-get install snmpd
370insserv -r snmpd
371sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/snmpd start; sleep inf"
372
373apt-get install apache2
374insserv -r apache2
375sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/apache2 start; sleep inf"
376
377apt-get install nginx
378insserv -r nginx
379sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/nginx start; sleep inf"
380
381apt-get install lighttpd
382insserv -r lighttpd
383sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/lighttpd start; sleep inf"
384
385apt-get install isc-dhcp-server
386insserv -r isc-dhcp-server
387sudo firejail --net=br0 --ip=10.10.20.10 "/etc/init.d/rsyslog start; /etc/init.d/ssh start; /etc/init.d/isc-dhcp-server start; sleep inf"
388#endif
diff --git a/src/firejail/join.c b/src/firejail/join.c
new file mode 100644
index 000000000..e2d2ca7fc
--- /dev/null
+++ b/src/firejail/join.c
@@ -0,0 +1,364 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/stat.h>
22#include <sys/wait.h>
23#include <fcntl.h>
24#include <unistd.h>
25#include <sys/prctl.h>
26
27static int apply_caps = 0;
28static uint64_t caps = 0;
29static int apply_seccomp = 0;
30#define BUFLEN 4096
31
32static void extract_command(int argc, char **argv, int index) {
33 if (index >= argc)
34 return;
35
36 // doubledash followed by positional parameters
37 if (strcmp(argv[index], "--") == 0) {
38 arg_doubledash = 1;
39 index++;
40 if (index >= argc)
41 return;
42 }
43
44 // first argv needs to be a valid command
45 if (arg_doubledash == 0 && *argv[index] == '-') {
46 fprintf(stderr, "Error: invalid option %s after --join\n", argv[index]);
47 exit(1);
48 }
49
50
51 int len = 0;
52 int i;
53 // calculate command length
54 for (i = index; i < argc; i++) {
55 len += strlen(argv[i]) + 1;
56 }
57 assert(len > 0);
58
59 // build command
60 cfg.command_line = malloc(len + 1);
61 *cfg.command_line = '\0';
62 for (i = index; i < argc; i++) {
63 strcat(cfg.command_line, argv[i]);
64 strcat(cfg.command_line, " ");
65 }
66 if (arg_debug)
67 printf("Extracted command #%s#\n", cfg.command_line);
68}
69
70static void extract_nogroups(pid_t pid) {
71 char *fname;
72 if (asprintf(&fname, "/proc/%d/root%s/groups", pid, MNT_DIR) == -1)
73 errExit("asprintf");
74
75 struct stat s;
76 if (stat(fname, &s) == -1)
77 return;
78
79 arg_nogroups = 1;
80 free(fname);
81}
82
83static void extract_cpu(pid_t pid) {
84 char *fname;
85 if (asprintf(&fname, "/proc/%d/root%s/cpu", pid, MNT_DIR) == -1)
86 errExit("asprintf");
87
88 struct stat s;
89 if (stat(fname, &s) == -1)
90 return;
91
92 // there is a cpu file in MNT_DIR; load the information from the file
93 load_cpu(fname);
94 free(fname);
95}
96
97static void extract_cgroup(pid_t pid) {
98 char *fname;
99 if (asprintf(&fname, "/proc/%d/root%s/cgroup", pid, MNT_DIR) == -1)
100 errExit("asprintf");
101
102 struct stat s;
103 if (stat(fname, &s) == -1)
104 return;
105
106 // there is a cgroup file in MNT_DIR; load the information from the file
107 load_cgroup(fname);
108 free(fname);
109}
110
111static void extract_caps_seccomp(pid_t pid) {
112 // open stat file
113 char *file;
114 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
115 perror("asprintf");
116 exit(1);
117 }
118 FILE *fp = fopen(file, "r");
119 if (!fp) {
120 free(file);
121 fprintf(stderr, "Error: cannot open stat file for process %u\n", pid);
122 exit(1);
123 }
124
125 char buf[BUFLEN];
126 while (fgets(buf, BUFLEN - 1, fp)) {
127 if (strncmp(buf, "Seccomp:", 8) == 0) {
128 char *ptr = buf + 8;
129 int val;
130 sscanf(ptr, "%d", &val);
131 if (val == 2)
132 apply_seccomp = 1;
133 break;
134 }
135 else if (strncmp(buf, "CapBnd:", 7) == 0) {
136 char *ptr = buf + 8;
137 unsigned long long val;
138 sscanf(ptr, "%llx", &val);
139 apply_caps = 1;
140 caps = val;
141 }
142 }
143 fclose(fp);
144 free(file);
145}
146
147void extract_user_namespace(pid_t pid) {
148 // test user namespaces available in the kernel
149 struct stat s1;
150 struct stat s2;
151 struct stat s3;
152 if (stat("/proc/self/ns/user", &s1) == 0 &&
153 stat("/proc/self/uid_map", &s2) == 0 &&
154 stat("/proc/self/gid_map", &s3) == 0);
155 else
156 return;
157
158 // read uid map
159 char *uidmap;
160 if (asprintf(&uidmap, "/proc/%u/uid_map", pid) == -1)
161 errExit("asprintf");
162 FILE *fp = fopen(uidmap, "r");
163 if (!fp) {
164 free(uidmap);
165 return;
166 }
167
168 // check uid map
169 int u1;
170 int u2;
171 if (fscanf(fp, "%d %d", &u1, &u2) == 2) {
172 if (arg_debug)
173 printf("User namespace detected: %s, %d, %d\n", uidmap, u1, u2);
174 if (u1 != 0 || u2 != 0)
175 arg_noroot = 1;
176 }
177 fclose(fp);
178 free(uidmap);
179}
180
181void join_name(const char *name, const char *homedir, int argc, char **argv, int index) {
182 if (!name || strlen(name) == 0) {
183 fprintf(stderr, "Error: invalid sandbox name\n");
184 exit(1);
185 }
186 pid_t pid;
187 if (name2pid(name, &pid)) {
188 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
189 exit(1);
190 }
191
192 join(pid, homedir, argc, argv, index);
193}
194
195void join(pid_t pid, const char *homedir, int argc, char **argv, int index) {
196 extract_command(argc, argv, index);
197
198 // if the pid is that of a firejail process, use the pid of the first child process
199 char *comm = pid_proc_comm(pid);
200 if (comm) {
201 // remove \n
202 char *ptr = strchr(comm, '\n');
203 if (ptr)
204 *ptr = '\0';
205 if (strcmp(comm, "firejail") == 0) {
206 pid_t child;
207 if (find_child(pid, &child) == 0) {
208 pid = child;
209 printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
210 }
211 }
212 free(comm);
213 }
214
215 // check privileges for non-root users
216 uid_t uid = getuid();
217 if (uid != 0) {
218 struct stat s;
219 char *dir;
220 if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
221 errExit("asprintf");
222 if (stat(dir, &s) < 0)
223 errExit("stat");
224 if (s.st_uid != uid) {
225 fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
226 exit(1);
227 }
228 }
229
230 // in user mode set caps seccomp, cpu, cgroup, etc
231 if (getuid() != 0) {
232 extract_caps_seccomp(pid);
233 extract_cpu(pid);
234 extract_cgroup(pid);
235 extract_nogroups(pid);
236 extract_user_namespace(pid);
237 }
238
239 // set cgroup
240 if (cfg.cgroup)
241 set_cgroup(cfg.cgroup);
242
243 // join namespaces
244 if (join_namespace(pid, "ipc"))
245 exit(1);
246 if (join_namespace(pid, "net"))
247 exit(1);
248 if (join_namespace(pid, "pid"))
249 exit(1);
250 if (join_namespace(pid, "uts"))
251 exit(1);
252 if (join_namespace(pid, "mnt"))
253 exit(1);
254
255 pid_t child = fork();
256 if (child < 0)
257 errExit("fork");
258 if (child == 0) {
259 // chroot into /proc/PID/root directory
260 char *rootdir;
261 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
262 errExit("asprintf");
263
264 int rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
265 if (rv == 0)
266 printf("changing root to %s\n", rootdir);
267
268 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
269 if (chdir("/") < 0)
270 errExit("chdir");
271 if (homedir) {
272 struct stat s;
273 if (stat(homedir, &s) == 0) {
274 /* coverity[toctou] */
275 if (chdir(homedir) < 0)
276 errExit("chdir");
277 }
278 }
279
280 // set cpu affinity
281 if (cfg.cpus)
282 set_cpu_affinity();
283
284 // set caps filter
285 if (apply_caps == 1)
286 caps_set(caps);
287#ifdef HAVE_SECCOMP
288 // set seccomp filter
289 if (apply_seccomp == 1)
290 seccomp_set();
291#endif
292
293 // fix qt 4.8
294 if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
295 errExit("setenv");
296 if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
297 errExit("setenv");
298
299 // mount user namespace or drop privileges
300 if (arg_noroot) {
301 if (arg_debug)
302 printf("Joining user namespace\n");
303 if (join_namespace(1, "user"))
304 exit(1);
305 }
306 else
307 drop_privs(arg_nogroups);
308
309 // set prompt color to green
310 //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
311 if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
312 errExit("setenv");
313
314 // run icmdline trough /bin/bash
315 if (cfg.command_line == NULL)
316 // replace the process with a regular bash session
317 execlp("/bin/bash", "/bin/bash", NULL);
318 else {
319 // run the command supplied by the user
320 int cwd = 0;
321 if (cfg.cwd) {
322 if (chdir(cfg.cwd) == 0)
323 cwd = 1;
324 }
325
326 if (!cwd) {
327 if (chdir("/") < 0)
328 errExit("chdir");
329 if (cfg.homedir) {
330 struct stat s;
331 if (stat(cfg.homedir, &s) == 0) {
332 if (chdir(cfg.homedir) < 0)
333 errExit("chdir");
334 }
335 }
336 }
337
338 char *arg[5];
339 arg[0] = "/bin/bash";
340 arg[1] = "-c";
341 if (arg_debug)
342 printf("Starting %s\n", cfg.command_line);
343 if (!arg_doubledash) {
344 arg[2] = cfg.command_line;
345 arg[3] = NULL;
346 }
347 else {
348 arg[2] = "--";
349 arg[3] = cfg.command_line;
350 arg[4] = NULL;
351 }
352 execvp("/bin/bash", arg);
353 }
354
355 // it will never get here!!!
356 }
357
358 // wait for the child to finish
359 waitpid(child, NULL, 0);
360 exit(0);
361}
362
363
364
diff --git a/src/firejail/list.c b/src/firejail/list.c
new file mode 100644
index 000000000..c2c4e801f
--- /dev/null
+++ b/src/firejail/list.c
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21
22void top(void) {
23 drop_privs(1);
24
25 char *arg[4];
26 arg[0] = "bash";
27 arg[1] = "-c";
28 arg[2] = "firemon --top";
29 arg[3] = NULL;
30 execvp("/bin/bash", arg);
31}
32
33void netstats(void) {
34 drop_privs(1);
35
36 char *arg[4];
37 arg[0] = "bash";
38 arg[1] = "-c";
39 arg[2] = "firemon --netstats";
40 arg[3] = NULL;
41 execvp("/bin/bash", arg);
42}
43
44void list(void) {
45 drop_privs(1);
46
47 char *arg[4];
48 arg[0] = "bash";
49 arg[1] = "-c";
50 arg[2] = "firemon --list";
51 arg[3] = NULL;
52 execvp("/bin/bash", arg);
53}
54
55void tree(void) {
56 drop_privs(1);
57
58 char *arg[4];
59 arg[0] = "bash";
60 arg[1] = "-c";
61 arg[2] = "firemon --tree";
62 arg[3] = NULL;
63 execvp("/bin/bash", arg);
64}
65
diff --git a/src/firejail/main.c b/src/firejail/main.c
new file mode 100644
index 000000000..78971aa86
--- /dev/null
+++ b/src/firejail/main.c
@@ -0,0 +1,1168 @@
1/*
2 * Copyright (C) 2014, 2015 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20#include "firejail.h"
21#include "../include/pid.h"
22#define _GNU_SOURCE
23#include <sys/utsname.h>
24#include <sched.h>
25#include <sys/mount.h>
26#include <sys/wait.h>
27#include <sys/stat.h>
28#include <fcntl.h>
29#include <dirent.h>
30#include <pwd.h>
31#include <errno.h>
32#include <limits.h>
33#include <sys/file.h>
34#include <sys/prctl.h>
35#include <signal.h>
36#include <time.h>
37#include <net/if.h>
38
39#if 0
40#include <sys/times.h>
41{
42struct tms tm;
43clock_t systick = times(&tm);
44printf("time %s:%d %u\n", __FILE__, __LINE__, (uint32_t) systick);
45}
46#endif
47
48#define STACK_SIZE (1024 * 1024)
49static char child_stack[STACK_SIZE]; // space for child's stack
50Config cfg; // configuration
51int arg_private = 0; // mount private /home and /tmp directoryu
52int arg_debug = 0; // print debug messages
53int arg_nonetwork = 0; // --net=none
54int arg_command = 0; // -c
55int arg_overlay = 0; // --overlay
56int arg_zsh = 0; // use zsh as default shell
57int arg_csh = 0; // use csh as default shell
58
59int arg_seccomp = 0; // enable default seccomp filter
60char *arg_seccomp_list = NULL; // optional seccomp list on top of default filter
61char *arg_seccomp_list_drop = NULL; // seccomp drop list
62char *arg_seccomp_list_keep = NULL; // seccomp keep list
63
64int arg_caps_default_filter = 0; // enable default capabilities filter
65int arg_caps_drop = 0; // drop list
66int arg_caps_drop_all = 0; // drop all capabilities
67int arg_caps_keep = 0; // keep list
68char *arg_caps_list = NULL; // optional caps list
69
70int arg_trace = 0; // syscall tracing support
71int arg_rlimit_nofile = 0; // rlimit nofile
72int arg_rlimit_nproc = 0; // rlimit nproc
73int arg_rlimit_fsize = 0; // rlimit fsize
74int arg_rlimit_sigpending = 0; // rlimit fsize
75int arg_nox11 = 0; // kill the program if x11 unix domain socket is accessed
76int arg_nodbus = 0; // kill the program if D-Bus is accessed
77int arg_nogroups = 0; // disable supplementary groups
78int arg_noroot = 0; // create a new user namespace and disable root user
79int arg_netfilter; // enable netfilter
80char *arg_netfilter_file = NULL; // netfilter file
81int arg_doubledash = 0; // double dash
82int arg_shell_none = 0; // run the program directly without a shell
83int arg_private_dev = 0; // private dev directory
84int arg_scan = 0; // arp-scan all interfaces
85
86int parent_to_child_fds[2];
87int child_to_parent_fds[2];
88
89char *fullargv[MAX_ARGS]; // expanded argv for restricted shell
90int fullargc = 0;
91static pid_t child = 0;
92pid_t sandbox_pid;
93
94static void myexit(int rv) {
95 logmsg("exiting...");
96 if (!arg_command)
97 printf("\nparent is shutting down, bye...\n");
98
99 struct stat s;
100 if (stat("/proc/firejail", &s) == 0) {
101 /* coverity[toctou] */
102 FILE *fp = fopen("/proc/firejail", "w");
103 if (fp) {
104 // deregistration
105 fprintf(fp, "release\n");
106 fflush(0);
107 fclose(fp);
108 }
109 }
110
111 // delete sandbox files in shared memory
112 bandwidth_shm_del_file(sandbox_pid); // bandwidht file
113 network_shm_del_file(sandbox_pid); // network map file
114
115 exit(rv);
116}
117
118static void my_handler(int s){
119 printf("\nSignal %d caught, shutting down the child process\n", s);
120 logsignal(s);
121 kill(child, SIGKILL);
122 myexit(1);
123}
124
125static void extract_user_data(void) {
126 // check suid
127 if (geteuid()) {
128 fprintf(stderr, "Error: the sandbox is not setuid root\n");
129 exit(1);
130 }
131
132 struct passwd *pw = getpwuid(getuid());
133 if (!pw)
134 errExit("getpwuid");
135 cfg.username = strdup(pw->pw_name);
136 if (!cfg.username)
137 errExit("strdup");
138
139 // build home directory name
140 cfg.homedir = NULL;
141 if (pw->pw_dir != NULL) {
142 cfg.homedir = strdup(pw->pw_dir);
143 if (!cfg.homedir)
144 errExit("strdup");
145 }
146 else {
147 fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username);
148 exit(1);
149 }
150
151 cfg.cwd = getcwd(NULL, 0);
152}
153
154
155
156
157static inline Bridge *last_bridge_configured(void) {
158 if (cfg.bridge3.configured)
159 return &cfg.bridge3;
160 else if (cfg.bridge2.configured)
161 return &cfg.bridge2;
162 else if (cfg.bridge1.configured)
163 return &cfg.bridge1;
164 else if (cfg.bridge0.configured)
165 return &cfg.bridge0;
166 else
167 return NULL;
168}
169
170
171
172// return 1 if error, 0 if a valid pid was found
173static int read_pid(char *str, pid_t *pid) {
174 char *endptr;
175 errno = 0;
176 pid_t pidtmp = strtol(str, &endptr, 10);
177 if ((errno == ERANGE && (pidtmp == LONG_MAX || pidtmp == LONG_MIN))
178 || (errno != 0 && pidtmp == 0)) {
179 return 1;
180 }
181 if (endptr == str) {
182 return 1;
183 }
184 *pid = pidtmp;
185 return 0;
186}
187
188static void init_cfg(void) {
189 memset(&cfg, 0, sizeof(cfg));
190
191 cfg.bridge0.devsandbox = "eth0";
192 cfg.bridge1.devsandbox = "eth1";
193 cfg.bridge2.devsandbox = "eth2";
194 cfg.bridge3.devsandbox = "eth3";
195
196 extract_user_data();
197}
198
199static void check_network(Bridge *br) {
200 assert(br);
201 if (br->macvlan == 0) // for bridge devices check network range or arp-scan and assign address
202 net_configure_sandbox_ip(br);
203 else if (br->ipsandbox) { // for macvlan check network range
204 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
205 if (rv) {
206 fprintf(stderr, "%s", rv);
207 exit(1);
208 }
209 }
210}
211
212
213void check_user_namespace(void) {
214 if (getuid() == 0) {
215 fprintf(stderr, "Error: --noroot option cannot be used when starting the sandbox as root.\n");
216 exit(1);
217 }
218
219 // test user namespaces available in the kernel
220 struct stat s1;
221 struct stat s2;
222 struct stat s3;
223 if (stat("/proc/self/ns/user", &s1) == 0 &&
224 stat("/proc/self/uid_map", &s2) == 0 &&
225 stat("/proc/self/gid_map", &s3) == 0)
226 arg_noroot = 1;
227 else {
228 fprintf(stderr, "Warning: user namespaces not available in the current kernel.\n");
229 arg_noroot = 0;
230 }
231}
232
233//*******************************************
234// Main program
235//*******************************************
236int main(int argc, char **argv) {
237 int i;
238 int prog_index = -1; // index in argv where the program command starts
239 int lockfd = -1;
240 int arg_ipc = 0;
241 int arg_cgroup = 0;
242 int custom_profile = 0; // custom profile loaded
243
244 // initialize globals
245 init_cfg();
246 cfg.original_argv = argv;
247 cfg.original_argc = argc;
248
249
250 // initialize random number generator
251 sandbox_pid = getpid();
252 time_t t = time(NULL);
253 srand(t ^ sandbox_pid);
254
255 // check firejail directories
256 fs_build_firejail_dir();
257 shm_create_firejail_dir();
258 bandwidth_shm_del_file(sandbox_pid);
259
260 // is this a login shell?
261 if (*argv[0] == '-') {
262 fullargc = restricted_shell(cfg.username);
263 if (fullargc) {
264 int j;
265 for (i = 1, j = fullargc; i < argc && j < MAX_ARGS; i++, j++, fullargc++)
266 fullargv[j] = argv[i];
267
268 // replace argc/argv with fullargc/fullargv
269 argv = fullargv;
270 argc = j;
271 }
272 }
273 else {
274 // check --output option and execute it;
275 check_output(argc, argv); // the function will not return if --output option was found
276 }
277
278 // parse arguments
279 for (i = 1; i < argc; i++) {
280 //*************************************
281 // basic arguments
282 //*************************************
283 if (strcmp(argv[i], "--help") == 0 ||
284 strcmp(argv[i], "-?") == 0) {
285 usage();
286 exit(0);
287 }
288 else if (strcmp(argv[i], "--version") == 0) {
289 printf("firejail version %s\n", VERSION);
290 exit(0);
291 }
292 else if (strcmp(argv[i], "--debug") == 0)
293 arg_debug = 1;
294
295 else if (strncmp(argv[i], "--bandwidth=", 12) == 0) {
296 logargs(argc, argv);
297
298 // extract the command
299 if ((i + 1) == argc) {
300 fprintf(stderr, "Error: command expected after --bandwidth option\n");
301 exit(1);
302 }
303 char *cmd = argv[i + 1];
304 if (strcmp(cmd, "status") && strcmp(cmd, "clear") && strcmp(cmd, "set")) {
305 fprintf(stderr, "Error: invalid --bandwidth command\n");
306 exit(1);
307 }
308
309 // extract network name
310 char *dev = NULL;
311 int down = 0;
312 int up = 0;
313 if (strcmp(cmd, "set") == 0 || strcmp(cmd, "clear") == 0) {
314 // extract device name
315 if ((i + 2) == argc) {
316 fprintf(stderr, "Error: network name expected after --bandwidth %s option\n", cmd);
317 exit(1);
318 }
319 dev = argv[i + 2];
320
321 // check device name
322 if (if_nametoindex(dev) == 0) {
323 fprintf(stderr, "Error: network device %s not found\n", dev);
324 exit(1);
325 }
326
327 // extract bandwidth
328 if (strcmp(cmd, "set") == 0) {
329 if ((i + 4) >= argc) {
330 fprintf(stderr, "Error: invalid --bandwidth set command\n");
331 exit(1);
332 }
333
334 down = atoi(argv[i + 3]);
335 if (down < 0) {
336 fprintf(stderr, "Error: invalid download speed\n");
337 exit(1);
338 }
339 up = atoi(argv[i + 4]);
340 if (up < 0) {
341 fprintf(stderr, "Error: invalid upload speed\n");
342 exit(1);
343 }
344 }
345 }
346
347 // extract pid or sandbox name
348 pid_t pid;
349 if (read_pid(argv[i] + 12, &pid) == 0)
350 bandwidth_pid(pid, cmd, dev, down, up);
351 else
352 bandwidth_name(argv[i] + 12, cmd, dev, down, up);
353
354 // it will never get here
355 exit(0);
356 }
357
358 //*************************************
359 // independent commands - the program will exit!
360 //*************************************
361#ifdef HAVE_SECCOMP
362 else if (strcmp(argv[i], "--debug-syscalls") == 0) {
363 syscall_print();
364 exit(0);
365 }
366 else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) {
367 // join sandbox by pid or by name
368 pid_t pid;
369 if (read_pid(argv[i] + 16, &pid) == 0)
370 seccomp_print_filter(pid);
371 else
372 seccomp_print_filter_name(argv[i] + 16);
373
374 // it will never get here!!!
375 exit(0);
376 }
377#endif
378 else if (strncmp(argv[i], "--caps.print=", 13) == 0) {
379 // join sandbox by pid or by name
380 pid_t pid;
381 if (read_pid(argv[i] + 13, &pid) == 0)
382 caps_print_filter(pid);
383 else
384 caps_print_filter_name(argv[i] + 13);
385
386 // it will never get here!!!
387 exit(0);
388 }
389
390 else if (strncmp(argv[i], "--dns.print=", 12) == 0) {
391 // join sandbox by pid or by name
392 pid_t pid;
393 if (read_pid(argv[i] + 12, &pid) == 0)
394 net_dns_print(pid);
395 else
396 net_dns_print_name(argv[i] + 12);
397
398 // it will never get here!!!
399 exit(0);
400 }
401 else if (strcmp(argv[i], "--debug-caps") == 0) {
402 caps_print();
403 exit(0);
404 }
405 else if (strcmp(argv[i], "--list") == 0) {
406 list();
407 exit(0);
408 }
409 else if (strcmp(argv[i], "--tree") == 0) {
410 tree();
411 exit(0);
412 }
413 else if (strcmp(argv[i], "--top") == 0) {
414 top();
415 exit(0);
416 }
417 else if (strcmp(argv[i], "--netstats") == 0) {
418 netstats();
419 exit(0);
420 }
421 else if (strncmp(argv[i], "--join=", 7) == 0) {
422 logargs(argc, argv);
423
424 // join sandbox by pid or by name
425 pid_t pid;
426 if (read_pid(argv[i] + 7, &pid) == 0)
427 join(pid, cfg.homedir, argc, argv, i + 1);
428 else
429 join_name(argv[i] + 7, cfg.homedir, argc, argv, i + 1);
430
431 // it will never get here!!!
432 exit(0);
433 }
434 else if (strncmp(argv[i], "--shutdown=", 11) == 0) {
435 logargs(argc, argv);
436
437 // shutdown sandbox by pid or by name
438 pid_t pid;
439 if (read_pid(argv[i] + 11, &pid) == 0)
440 shut(pid);
441 else
442 shut_name(argv[i] + 11);
443
444 // it will never get here!!!
445 exit(0);
446 }
447
448 //*************************************
449 // filtering
450 //*************************************
451#ifdef HAVE_SECCOMP
452 else if (strcmp(argv[i], "--seccomp") == 0) {
453 if (arg_seccomp) {
454 fprintf(stderr, "Error: seccomp already enabled\n");
455 exit(1);
456 }
457 arg_seccomp = 1;
458 }
459 else if (strncmp(argv[i], "--seccomp=", 10) == 0) {
460 if (arg_seccomp) {
461 fprintf(stderr, "Error: seccomp already enabled\n");
462 exit(1);
463 }
464 arg_seccomp = 1;
465 arg_seccomp_list = strdup(argv[i] + 10);
466 if (!arg_seccomp_list)
467 errExit("strdup");
468 }
469 else if (strncmp(argv[i], "--seccomp.drop=", 15) == 0) {
470 if (arg_seccomp) {
471 fprintf(stderr, "Error: seccomp already enabled\n");
472 exit(1);
473 }
474 arg_seccomp = 1;
475 arg_seccomp_list_drop = strdup(argv[i] + 15);
476 if (!arg_seccomp_list_drop)
477 errExit("strdup");
478 }
479 else if (strncmp(argv[i], "--seccomp.keep=", 15) == 0) {
480 if (arg_seccomp) {
481 fprintf(stderr, "Error: seccomp already enabled\n");
482 exit(1);
483 }
484 arg_seccomp = 1;
485 arg_seccomp_list_keep = strdup(argv[i] + 15);
486 if (!arg_seccomp_list_keep)
487 errExit("strdup");
488 }
489#endif
490 else if (strcmp(argv[i], "--caps") == 0)
491 arg_caps_default_filter = 1;
492 else if (strcmp(argv[i], "--caps.drop=all") == 0)
493 arg_caps_drop_all = 1;
494 else if (strncmp(argv[i], "--caps.drop=", 12) == 0) {
495 arg_caps_drop = 1;
496 arg_caps_list = strdup(argv[i] + 12);
497 if (!arg_caps_list)
498 errExit("strdup");
499 // verify caps list and exit if problems
500 if (caps_check_list(arg_caps_list, NULL))
501 return 1;
502 }
503 else if (strncmp(argv[i], "--caps.keep=", 12) == 0) {
504 arg_caps_keep = 1;
505 arg_caps_list = strdup(argv[i] + 12);
506 if (!arg_caps_list)
507 errExit("strdup");
508 // verify caps list and exit if problems
509 if (caps_check_list(arg_caps_list, NULL))
510 return 1;
511 }
512
513
514 else if (strcmp(argv[i], "--trace") == 0)
515 arg_trace = 1;
516 else if (strncmp(argv[i], "--rlimit-nofile=", 16) == 0) {
517 if (not_unsigned(argv[i] + 16)) {
518 fprintf(stderr, "Error: invalid rlimt nofile\n");
519 exit(1);
520 }
521 sscanf(argv[i] + 16, "%u", &cfg.rlimit_nofile);
522 arg_rlimit_nofile = 1;
523 }
524 else if (strncmp(argv[i], "--rlimit-nproc=", 15) == 0) {
525 if (not_unsigned(argv[i] + 15)) {
526 fprintf(stderr, "Error: invalid rlimt nproc\n");
527 exit(1);
528 }
529 sscanf(argv[i] + 15, "%u", &cfg.rlimit_nproc);
530 arg_rlimit_nproc = 1;
531 }
532 else if (strncmp(argv[i], "--rlimit-fsize=", 15) == 0) {
533 if (not_unsigned(argv[i] + 15)) {
534 fprintf(stderr, "Error: invalid rlimt fsize\n");
535 exit(1);
536 }
537 sscanf(argv[i] + 15, "%u", &cfg.rlimit_fsize);
538 arg_rlimit_fsize = 1;
539 }
540 else if (strncmp(argv[i], "--rlimit-sigpending=", 20) == 0) {
541 if (not_unsigned(argv[i] + 20)) {
542 fprintf(stderr, "Error: invalid rlimt sigpending\n");
543 exit(1);
544 }
545 sscanf(argv[i] + 20, "%u", &cfg.rlimit_sigpending);
546 arg_rlimit_sigpending = 1;
547 }
548 else if (strncmp(argv[i], "--ipc-namespace", 15) == 0)
549 arg_ipc = 1;
550 else if (strncmp(argv[i], "--cpu=", 6) == 0)
551 read_cpu_list(argv[i] + 6);
552 else if (strcmp(argv[i], "--nox11") == 0) {
553 // check if firejail lkm is present
554 struct stat s;
555 if (stat("/proc/firejail", &s) < 0) {
556 fprintf(stderr, "Error: firejail Linux kernel module not found. The module"
557 " is required for --nox11 option to work.\n");
558 exit(1);
559 }
560 arg_nox11 = 1;
561 }
562 else if (strcmp(argv[i], "--nodbus") == 0) {
563 // check if firejail lkm is present
564 struct stat s;
565 if (stat("/proc/firejail", &s) < 0) {
566 fprintf(stderr, "Error: firejail Linux kernel module not found. The module"
567 " is required for --nodbus option to work.\n");
568 exit(1);
569 }
570 arg_nodbus = 1;
571 }
572 else if (strncmp(argv[i], "--cgroup=", 9) == 0) {
573 if (arg_cgroup) {
574 fprintf(stderr, "Error: only a cgroup can be defined\n");
575 exit(1);
576 }
577 arg_cgroup = 1;
578 cfg.cgroup = strdup(argv[i] + 9);
579 if (!cfg.cgroup)
580 errExit("strdup");
581 set_cgroup(cfg.cgroup);
582 }
583
584 //*************************************
585 // filesystem
586 //*************************************
587#ifdef HAVE_BIND
588 else if (strncmp(argv[i], "--bind=", 7) == 0) {
589 char *line;
590 if (asprintf(&line, "bind %s", argv[i] + 7) == -1)
591 errExit("asprintf");
592
593 profile_check_line(line, 0); // will exit if something wrong
594 profile_add(line);
595 }
596#endif
597 else if (strncmp(argv[i], "--tmpfs=", 8) == 0) {
598 char *line;
599 if (asprintf(&line, "tmpfs %s", argv[i] + 8) == -1)
600 errExit("asprintf");
601
602 profile_check_line(line, 0); // will exit if something wrong
603 profile_add(line);
604 }
605 else if (strncmp(argv[i], "--blacklist=", 12) == 0) {
606 char *line;
607 if (asprintf(&line, "blacklist %s", argv[i] + 12) == -1)
608 errExit("asprintf");
609
610 profile_check_line(line, 0); // will exit if something wrong
611 profile_add(line);
612 }
613 else if (strncmp(argv[i], "--read-only=", 12) == 0) {
614 char *line;
615 if (asprintf(&line, "read-only %s", argv[i] + 12) == -1)
616 errExit("asprintf");
617
618 profile_check_line(line, 0); // will exit if something wrong
619 profile_add(line);
620 }
621 else if (strcmp(argv[i], "--overlay") == 0) {
622 if (cfg.chrootdir) {
623 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
624 exit(1);
625 }
626 arg_overlay = 1;
627 }
628 else if (strncmp(argv[i], "--profile=", 10) == 0) {
629 // multiple profile files are allowed!
630 char *ptr = argv[i] + 10;
631 if (is_dir(ptr) || is_link(ptr) || strstr(ptr, "..")) {
632 fprintf(stderr, "Error: invalid profile file\n");
633 exit(1);
634 }
635
636 // access call checks as real UID/GID, not as effective UID/GID
637 if (access(argv[i] + 10, R_OK)) {
638 fprintf(stderr, "Error: cannot access profile file\n");
639 return 1;
640 }
641
642 profile_read(argv[i] + 10, NULL, NULL);
643 custom_profile = 1;
644 }
645#ifdef HAVE_CHROOT
646 else if (strncmp(argv[i], "--chroot=", 9) == 0) {
647 if (arg_overlay) {
648 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
649 exit(1);
650 }
651
652 // extract chroot dirname
653 cfg.chrootdir = argv[i] + 9;
654 // if the directory starts with ~, expand the home directory
655 if (*cfg.chrootdir == '~') {
656 char *tmp;
657 if (asprintf(&tmp, "%s%s", cfg.homedir, cfg.chrootdir + 1) == -1)
658 errExit("asprintf");
659 cfg.chrootdir = tmp;
660 }
661
662 // check chroot dirname exists
663 if (strstr(cfg.chrootdir, "..") || !is_dir(cfg.chrootdir) || is_link(cfg.chrootdir)) {
664 fprintf(stderr, "Error: invalid directory %s\n", cfg.chrootdir);
665 return 1;
666 }
667
668 // check chroot directory structure
669 if (fs_check_chroot_dir(cfg.chrootdir)) {
670 fprintf(stderr, "Error: invalid chroot\n");
671 exit(1);
672 }
673 }
674#endif
675 else if (strcmp(argv[i], "--private") == 0)
676 arg_private = 1;
677 else if (strncmp(argv[i], "--private=", 10) == 0) {
678 if (cfg.home_private_keep) {
679 fprintf(stderr, "Error: a private list of files was already defined with --private.keep option.\n");
680 exit(1);
681 }
682
683 // extract private home dirname
684 cfg.home_private = argv[i] + 10;
685 fs_check_private_dir();
686 arg_private = 1;
687 }
688 else if (strncmp(argv[i], "--private.keep=", 15) == 0) {
689 if (cfg.home_private) {
690 fprintf(stderr, "Error: a private home directory was already defined with --private option.\n");
691 exit(1);
692 }
693
694 // extract private home dirname
695 cfg.home_private_keep = argv[i] + 15;
696 fs_check_home_list();
697 arg_private = 1;
698 }
699 else if (strcmp(argv[i], "--private-dev") == 0) {
700 arg_private_dev = 1;
701 }
702
703
704
705 //*************************************
706 // hostname, etc
707 //*************************************
708 else if (strncmp(argv[i], "--name=", 7) == 0) {
709 cfg.hostname = argv[i] + 7;
710 if (strlen(cfg.hostname) == 0) {
711 fprintf(stderr, "Error: please provide a name for sandbox\n");
712 return 1;
713 }
714 }
715 else if (strcmp(argv[i], "--nogroups") == 0)
716 arg_nogroups = 1;
717 else if (strcmp(argv[i], "--noroot") == 0) {
718 check_user_namespace();
719 }
720
721 //*************************************
722 // network
723 //*************************************
724 else if (strncmp(argv[i], "--net=", 6) == 0) {
725 if (strcmp(argv[i] + 6, "none") == 0) {
726 arg_nonetwork = 1;
727 cfg.bridge0.configured = 0;
728 cfg.bridge1.configured = 0;
729 cfg.bridge2.configured = 0;
730 cfg.bridge3.configured = 0;
731 continue;
732 }
733 if (strcmp(argv[i] + 6, "lo") == 0) {
734 fprintf(stderr, "Error: cannot attach to lo device\n");
735 exit(1);
736 }
737
738 Bridge *br;
739 if (cfg.bridge0.configured == 0)
740 br = &cfg.bridge0;
741 else if (cfg.bridge1.configured == 0)
742 br = &cfg.bridge1;
743 else if (cfg.bridge2.configured == 0)
744 br = &cfg.bridge2;
745 else if (cfg.bridge3.configured == 0)
746 br = &cfg.bridge3;
747 else {
748 fprintf(stderr, "Error: maximum 4 network devices allowed\n");
749 return 1;
750 }
751 net_configure_bridge(br, argv[i] + 6);
752 }
753 else if (strcmp(argv[i], "--scan") == 0) {
754 arg_scan = 1;
755 }
756 else if (strncmp(argv[i], "--iprange=", 10) == 0) {
757 Bridge *br = last_bridge_configured();
758 if (br == NULL) {
759 fprintf(stderr, "Error: no network device configured\n");
760 return 1;
761 }
762 if (br->iprange_start || br->iprange_end) {
763 fprintf(stderr, "Error: cannot configure the IP range twice for the same interface\n");
764 return 1;
765 }
766
767 // parse option arguments
768 char *firstip = argv[i] + 10;
769 char *secondip = firstip;
770 while (*secondip != '\0') {
771 if (*secondip == ',')
772 break;
773 secondip++;
774 }
775 if (*secondip == '\0') {
776 fprintf(stderr, "Error: invalid IP range\n");
777 return 1;
778 }
779 *secondip = '\0';
780 secondip++;
781
782 // check addresses
783 if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) ||
784 br->iprange_start >= br->iprange_end) {
785 fprintf(stderr, "Error: invalid IP range\n");
786 return 1;
787 }
788 if (in_netrange(br->iprange_start, br->ip, br->mask) || in_netrange(br->iprange_end, br->ip, br->mask)) {
789 fprintf(stderr, "Error: IP range addresses not in network range\n");
790 return 1;
791 }
792 }
793 else if (strncmp(argv[i], "--mac=", 6) == 0) {
794 Bridge *br = last_bridge_configured();
795 if (br == NULL) {
796 fprintf(stderr, "Error: no network device configured\n");
797 return 1;
798 }
799 if (mac_not_zero(br->macsandbox)) {
800 fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n");
801 return 1;
802 }
803
804 // read the address
805 if (atomac(argv[i] + 6, br->macsandbox)) {
806 fprintf(stderr, "Error: invalid MAC address\n");
807 return 1;
808 }
809 }
810 else if (strncmp(argv[i], "--ip=", 5) == 0) {
811 Bridge *br = last_bridge_configured();
812 if (br == NULL) {
813 fprintf(stderr, "Error: no network device configured\n");
814 return 1;
815 }
816 if (br->arg_ip_none || br->ipsandbox) {
817 fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n");
818 return 1;
819 }
820
821 // configure this IP address for the last bridge defined
822 if (strcmp(argv[i] + 5, "none") == 0)
823 br->arg_ip_none = 1;
824 else {
825 if (atoip(argv[i] + 5, &br->ipsandbox)) {
826 fprintf(stderr, "Error: invalid IP address\n");
827 return 1;
828 }
829 }
830 }
831 else if (strncmp(argv[i], "--defaultgw=", 12) == 0) {
832 if (atoip(argv[i] + 12, &cfg.defaultgw)) {
833 fprintf(stderr, "Error: invalid IP address\n");
834 return 1;
835 }
836 }
837 else if (strncmp(argv[i], "--dns=", 6) == 0) {
838 uint32_t dns;
839 if (atoip(argv[i] + 6, &dns)) {
840 fprintf(stderr, "Error: invalid DNS server IP address\n");
841 return 1;
842 }
843
844 if (cfg.dns1 == 0)
845 cfg.dns1 = dns;
846 else if (cfg.dns2 == 0)
847 cfg.dns2 = dns;
848 else if (cfg.dns3 == 0)
849 cfg.dns3 = dns;
850 else {
851 fprintf(stderr, "Error: up to 3 DNS servers can be specified\n");
852 return 1;
853 }
854 }
855 else if (strcmp(argv[i], "--netfilter") == 0)
856 arg_netfilter = 1;
857 else if (strncmp(argv[i], "--netfilter=", 12) == 0) {
858 arg_netfilter = 1;
859 arg_netfilter_file = argv[i] + 12;
860 check_netfilter_file(arg_netfilter_file);
861 }
862
863 //*************************************
864 // command
865 //*************************************
866 else if (strcmp(argv[i], "--csh") == 0) {
867 if (arg_shell_none) {
868 fprintf(stderr, "Error: --shell=none was already specified.\n");
869 return 1;
870 }
871 if (arg_zsh || cfg.shell ) {
872 fprintf(stderr, "Error: only one default user shell can be specified\n");
873 return 1;
874 }
875 arg_csh = 1;
876 }
877 else if (strcmp(argv[i], "--zsh") == 0) {
878 if (arg_shell_none) {
879 fprintf(stderr, "Error: --shell=none was already specified.\n");
880 return 1;
881 }
882 if (arg_csh || cfg.shell ) {
883 fprintf(stderr, "Error: only one default user shell can be specified\n");
884 return 1;
885 }
886 arg_zsh = 1;
887 }
888 else if (strcmp(argv[i], "--shell=none") == 0) {
889 arg_shell_none = 1;
890 if (arg_csh || arg_zsh || cfg.shell) {
891 fprintf(stderr, "Error: a shell was already specified\n");
892 return 1;
893 }
894 }
895 else if (strncmp(argv[i], "--shell=", 8) == 0) {
896 if (arg_shell_none) {
897 fprintf(stderr, "Error: --shell=none was already specified.\n");
898 return 1;
899 }
900 if (arg_csh || arg_zsh || cfg.shell) {
901 fprintf(stderr, "Error: only one user shell can be specified\n");
902 return 1;
903 }
904 cfg.shell = argv[i] + 8;
905
906 if (is_dir(cfg.shell) || is_link(cfg.shell) || strstr(cfg.shell, "..")) {
907 fprintf(stderr, "Error: invalid shell\n");
908 exit(1);
909 }
910
911 // access call checks as real UID/GID, not as effective UID/GID
912 if (access(cfg.shell, R_OK)) {
913 fprintf(stderr, "Error: cannot access shell file\n");
914 exit(1);
915 }
916 }
917 else if (strcmp(argv[i], "-c") == 0) {
918 arg_command = 1;
919 if (i == (argc - 1)) {
920 fprintf(stderr, "Error: option -c requires an argument\n");
921 return 1;
922 }
923 }
924 else if (strcmp(argv[i], "--") == 0) {
925 // double dash - positional params to follow
926 arg_doubledash = 1;
927 i++;
928 if (i >= argc) {
929 fprintf(stderr, "Error: program name not found\n");
930 exit(1);
931 }
932 extract_command_name(argv[i]);
933 prog_index = i;
934 cfg.original_program_index = i;
935 break;
936 }
937 else {
938 // is this an invalid option?
939 if (*argv[i] == '-') {
940 fprintf(stderr, "Error: invalid %s command line option\n", argv[i]);
941 return 1;
942 }
943
944 // we have a program name coming
945 extract_command_name(argv[i]);
946 prog_index = i;
947 cfg.original_program_index = i;
948 break;
949 }
950 }
951
952 // check network configuration options - it will exit if anything went wrong
953 net_check_cfg();
954
955 // check user namespace (--noroot) options
956 if (arg_noroot) {
957 if (arg_overlay) {
958 fprintf(stderr, "Error: --overlay and --noroot are mutually exclusive.\n");
959 exit(1);
960 }
961 else if (cfg.chrootdir) {
962 fprintf(stderr, "Error: --chroot and --noroot are mutually exclusive.\n");
963 exit(1);
964 }
965 }
966
967 // log command
968 logargs(argc, argv);
969 if (fullargc) {
970 char *msg;
971 if (asprintf(&msg, "user %s entering restricted shell", cfg.username) == -1)
972 errExit("asprintf");
973 logmsg(msg);
974 free(msg);
975 }
976
977 // build the sandbox command
978 if (prog_index == -1 && arg_zsh) {
979 cfg.command_line = "/usr/bin/zsh";
980 cfg.command_name = "zsh";
981 }
982 else if (prog_index == -1 && arg_csh) {
983 cfg.command_line = "/bin/csh";
984 cfg.command_name = "csh";
985 }
986 else if (prog_index == -1 && cfg.shell) {
987 cfg.command_line = cfg.shell;
988 cfg.command_name = cfg.shell;
989 }
990 else if (prog_index == -1) {
991 cfg.command_line = "/bin/bash";
992 cfg.command_name = "bash";
993 }
994 else {
995 // calculate the length of the command
996 int i;
997 int len = 0;
998 int argcnt = argc - prog_index;
999 for (i = 0; i < argcnt; i++)
1000 len += strlen(argv[i + prog_index]) + 1; // + ' '
1001
1002 // build the string
1003 cfg.command_line = malloc(len + 1); // + '\0'
1004 if (!cfg.command_line)
1005 errExit("malloc");
1006 char *ptr = cfg.command_line;
1007 for (i = 0; i < argcnt; i++) {
1008 sprintf(ptr, "%s ", argv[i + prog_index]);
1009 ptr += strlen(ptr);
1010 }
1011 }
1012
1013 // load the profile
1014 {
1015 assert(cfg.command_name);
1016 if (arg_debug)
1017 printf("Command name #%s#\n", cfg.command_name);
1018 if (!custom_profile) {
1019 // look for a profile in ~/.config/firejail directory
1020 char *usercfgdir;
1021 if (asprintf(&usercfgdir, "%s/.config/firejail", cfg.homedir) == -1)
1022 errExit("asprintf");
1023 int rv = profile_find(cfg.command_name, usercfgdir);
1024 free(usercfgdir);
1025 custom_profile = rv;
1026 }
1027 if (!custom_profile) {
1028 // look for a user profile in /etc/firejail directory
1029 int rv = profile_find(cfg.command_name, "/etc/firejail");
1030 custom_profile = rv;
1031 }
1032 }
1033
1034 // check and assign an IP address - for macvlan it will be done again in the sandbox!
1035 if (any_bridge_configured()) {
1036 lockfd = open("/tmp/firejail/firejail.lock", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
1037 if (lockfd != -1) {
1038 int rv = fchown(lockfd, 0, 0);
1039 (void) rv;
1040 flock(lockfd, LOCK_EX);
1041 }
1042
1043 check_network(&cfg.bridge0);
1044 check_network(&cfg.bridge1);
1045 check_network(&cfg.bridge2);
1046 check_network(&cfg.bridge3);
1047
1048 // save network mapping in shared memory
1049 network_shm_set_file(sandbox_pid);
1050 }
1051
1052 // create the parent-child communication pipe
1053 if (pipe(parent_to_child_fds) < 0)
1054 errExit("pipe");
1055 if (pipe(child_to_parent_fds) < 0)
1056 errExit("pipe");
1057
1058 // clone environment
1059 int flags = CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD;
1060
1061 // in root mode also enable CLONE_NEWIPC
1062 // in user mode CLONE_NEWIPC will break MIT Shared Memory Extension (MIT-SHM)
1063 if (getuid() == 0 || arg_ipc)
1064 flags |= CLONE_NEWIPC;
1065
1066 if (any_bridge_configured() || arg_nonetwork) {
1067 flags |= CLONE_NEWNET;
1068 }
1069 else if (arg_debug)
1070 printf("Using the local network stack\n");
1071
1072 child = clone(sandbox,
1073 child_stack + STACK_SIZE,
1074 flags,
1075 NULL);
1076 if (child == -1)
1077 errExit("clone");
1078
1079 if (!arg_command) {
1080 printf("Parent pid %u, child pid %u\n", sandbox_pid, child);
1081 // print the path of the new log directory
1082 if (getuid() == 0) // only for root
1083 printf("The new log directory is /proc/%d/root/var/log\n", child);
1084 }
1085
1086
1087
1088 // create veth pair or macvlan device
1089 if (cfg.bridge0.configured && !arg_nonetwork) {
1090 if (cfg.bridge0.macvlan == 0)
1091 net_configure_veth_pair(&cfg.bridge0, "eth0", child);
1092 else
1093 net_create_macvlan(cfg.bridge0.devsandbox, cfg.bridge0.dev, child);
1094 }
1095
1096 if (cfg.bridge1.configured && !arg_nonetwork) {
1097 if (cfg.bridge1.macvlan == 0)
1098 net_configure_veth_pair(&cfg.bridge1, "eth1", child);
1099 else
1100 net_create_macvlan(cfg.bridge1.devsandbox, cfg.bridge1.dev, child);
1101 }
1102
1103 if (cfg.bridge2.configured && !arg_nonetwork) {
1104 if (cfg.bridge2.macvlan == 0)
1105 net_configure_veth_pair(&cfg.bridge2, "eth2", child);
1106 else
1107 net_create_macvlan(cfg.bridge2.devsandbox, cfg.bridge2.dev, child);
1108 }
1109
1110 if (cfg.bridge3.configured && !arg_nonetwork) {
1111 if (cfg.bridge3.macvlan == 0)
1112 net_configure_veth_pair(&cfg.bridge3, "eth3", child);
1113 else
1114 net_create_macvlan(cfg.bridge3.devsandbox, cfg.bridge3.dev, child);
1115 }
1116
1117 // close each end of the unused pipes
1118 close(parent_to_child_fds[0]);
1119 close(child_to_parent_fds[1]);
1120
1121 // notify child that base setup is complete
1122 notify_other(parent_to_child_fds[1]);
1123
1124 // wait for child to create new user namespace with CLONE_NEWUSER
1125 wait_for_other(child_to_parent_fds[0]);
1126 close(child_to_parent_fds[0]);
1127
1128 if (arg_noroot) {
1129 // update the UID and GID maps in the new child user namespace
1130 // uid
1131 char *map_path;
1132 if (asprintf(&map_path, "/proc/%d/uid_map", child) == -1)
1133 errExit("asprintf");
1134 char *map;
1135 uid_t uid = getuid();
1136 if (asprintf(&map, "%d %d 1", uid, uid) == -1)
1137 errExit("asprintf");
1138 update_map(map, map_path);
1139 free(map);
1140 free(map_path);
1141
1142 //gid
1143 if (asprintf(&map_path, "/proc/%d/gid_map", child) == -1)
1144 errExit("asprintf");
1145 gid_t gid = getgid();
1146 if (asprintf(&map, "%d %d 1", gid, gid) == -1)
1147 errExit("asprintf");
1148 update_map(map, map_path);
1149 free(map);
1150 free(map_path);
1151 }
1152
1153 // notify child that UID/GID mapping is complete
1154 notify_other(parent_to_child_fds[1]);
1155 close(parent_to_child_fds[1]);
1156
1157 if (lockfd != -1)
1158 flock(lockfd, LOCK_UN);
1159
1160 // handle CTRL-C in parent
1161 signal (SIGINT, my_handler);
1162 signal (SIGTERM, my_handler);
1163
1164 // wait for the child to finish
1165 waitpid(child, NULL, 0);
1166 myexit(0);
1167 return 0;
1168}
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
new file mode 100644
index 000000000..dbed4ac30
--- /dev/null
+++ b/src/firejail/netfilter.c
@@ -0,0 +1,164 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24#include <sys/wait.h>
25#include <fcntl.h>
26
27static char *client_filter =
28"*filter\n"
29":INPUT DROP [0:0]\n"
30":FORWARD DROP [0:0]\n"
31":OUTPUT ACCEPT [0:0]\n"
32"-A INPUT -i lo -j ACCEPT\n"
33"# echo replay is handled by -m state RELEATED/ESTABLISHED below\n"
34"#-A INPUT -p icmp --icmp-type echo-reply -j ACCEPT\n"
35"-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
36"-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT\n"
37"-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT\n"
38"-A INPUT -p icmp --icmp-type echo-request -j ACCEPT \n"
39"COMMIT\n";
40
41void check_netfilter_file(const char *fname) {
42 if (is_dir(fname) || is_link(fname) || strstr(fname, "..")) {
43 fprintf(stderr, "Error: invalid network filter file\n");
44 exit(1);
45 }
46
47 // access call checks as real UID/GID, not as effective UID/GID
48 if (access(fname, R_OK)) {
49 fprintf(stderr, "Error: cannot access network filter file\n");
50 exit(1);
51 }
52}
53
54
55void netfilter(const char *fname) {
56 // default filter
57 char *filter = client_filter;
58
59 // custom filter
60 int allocated = 0;
61 if (fname) {
62 // buffer the filter
63 struct stat s;
64 if (stat(fname, &s) == -1) {
65 fprintf(stderr, "Error: cannot find network filter file\n");
66 exit(1);
67 }
68
69 filter = malloc(s.st_size + 1); // + '\0'
70 memset(filter, 0, s.st_size + 1);
71 if (!filter)
72 errExit("malloc");
73
74 /* coverity[toctou] */
75 FILE *fp = fopen(fname, "r");
76 if (!fp) {
77 fprintf(stderr, "Error: cannot open network filter file\n");
78 exit(1);
79 }
80
81 size_t sz = fread(filter, 1, s.st_size, fp);
82 if (sz != s.st_size) {
83 fprintf(stderr, "Error: cannot read network filter file\n");
84 exit(1);
85 }
86 fclose(fp);
87 allocated = 1;
88 }
89
90 // mount a tempfs on top of /tmp directory
91 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
92 errExit("mounting /tmp");
93
94 // create the filter file
95 FILE *fp = fopen("/tmp/netfilter", "w");
96 if (!fp) {
97 fprintf(stderr, "Error: cannot open /tmp/netfilter file\n");
98 exit(1);
99 }
100 fprintf(fp, "%s\n", filter);
101 fclose(fp);
102
103 // find iptables command
104 struct stat s;
105 char *iptables = NULL;
106 char *iptables_restore = NULL;
107 if (stat("/sbin/iptables", &s) == 0) {
108 iptables = "/sbin/iptables";
109 iptables_restore = "/sbin/iptables-restore";
110 }
111 else if (stat("/usr/sbin/iptables", &s) == 0) {
112 iptables = "/usr/sbin/iptables";
113 iptables_restore = "/usr/sbin/iptables-restore";
114 }
115 if (iptables == NULL || iptables_restore == NULL) {
116 fprintf(stderr, "Error: iptables command not found\n");
117 goto doexit;
118 }
119
120 // push filter
121 pid_t child = fork();
122 if (child < 0)
123 errExit("fork");
124 if (child == 0) {
125 if (arg_debug)
126 printf("Installing network filter:\n%s\n", filter);
127
128 int fd;
129 if((fd = open("/tmp/netfilter", O_RDONLY)) == -1) {
130 fprintf(stderr,"Error: cannot open /tmp/netfilter\n");
131 exit(1);
132 }
133 dup2(fd,STDIN_FILENO);
134 close(fd);
135
136 // wipe out environment variables
137 environ = NULL;
138 execl(iptables_restore, iptables_restore, NULL);
139 // it will never get here!!!
140 }
141 // wait for the child to finish
142 waitpid(child, NULL, 0);
143
144 // debug
145 if (arg_debug) {
146 child = fork();
147 if (child < 0)
148 errExit("fork");
149 if (child == 0) {
150 environ = NULL;
151 execl(iptables, iptables, "-vL", NULL);
152 // it will never get here!!!
153 }
154 // wait for the child to finish
155 waitpid(child, NULL, 0);
156 }
157
158doexit:
159 // unmount /tmp
160 umount("/tmp");
161
162 if (allocated)
163 free(filter);
164}
diff --git a/src/firejail/network.c b/src/firejail/network.c
new file mode 100644
index 000000000..6a1d52744
--- /dev/null
+++ b/src/firejail/network.c
@@ -0,0 +1,362 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20#include "firejail.h"
21#include <arpa/inet.h>
22#include <sys/socket.h>
23#include <sys/ioctl.h>
24#include <netdb.h>
25#include <ifaddrs.h>
26#include <net/if.h>
27#include <net/if_arp.h>
28#include <net/route.h>
29#include <linux/if_bridge.h>
30
31// scan interfaces in current namespace and print IP address/mask for each interface
32void net_ifprint(void) {
33 uint32_t ip;
34 uint32_t mask;
35 struct ifaddrs *ifaddr, *ifa;
36
37 if (getifaddrs(&ifaddr) == -1)
38 errExit("getifaddrs");
39
40 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
41 "Interface", "MAC", "IP", "Mask", "Status");
42 // walk through the linked list
43 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
44 if (ifa->ifa_addr == NULL)
45 continue;
46
47 if (ifa->ifa_addr->sa_family == AF_INET) {
48 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
49 mask = ntohl(si->sin_addr.s_addr);
50 si = (struct sockaddr_in *) ifa->ifa_addr;
51 ip = ntohl(si->sin_addr.s_addr);
52
53 // interface status
54 char *status;
55 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
56 status = "UP";
57 else
58 status = "DOWN";
59
60 // ip address and mask
61 char ipstr[30];
62 sprintf(ipstr, "%d.%d.%d.%d", PRINT_IP(ip));
63 char maskstr[30];
64 sprintf(maskstr, "%d.%d.%d.%d", PRINT_IP(mask));
65
66 // mac address
67 unsigned char mac[6];
68 net_get_mac(ifa->ifa_name, mac);
69 char macstr[30];
70 if (strcmp(ifa->ifa_name, "lo") == 0)
71 macstr[0] = '\0';
72 else
73 sprintf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac));
74
75 // print
76 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
77 ifa->ifa_name, macstr, ipstr, maskstr, status);
78
79 // network scanning
80 if (!arg_scan) // scanning disabled
81 continue;
82 if (strcmp(ifa->ifa_name, "lo") == 0) // no loopbabck scanning
83 continue;
84 if (mask2bits(mask) < 16) // not scanning large networks
85 continue;
86 if (!ip) // if not configured
87 continue;
88 // only if the interface is up and running
89 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
90 arp_scan(ifa->ifa_name, ip, mask);
91 }
92 }
93 freeifaddrs(ifaddr);
94}
95
96
97// return -1 if the interface was not found; if the interface was found retrn 0 and fill in IP address and mask
98int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6]) {
99 assert(bridge);
100 assert(ip);
101 assert(mask);
102 int rv = -1;
103 struct ifaddrs *ifaddr, *ifa;
104
105 if (getifaddrs(&ifaddr) == -1)
106 errExit("getifaddrs");
107
108 // walk through the linked list; if the interface is found, extract IP address and mask
109 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
110 if (ifa->ifa_addr == NULL)
111 continue;
112 if (strcmp(ifa->ifa_name, bridge) != 0)
113 continue;
114
115 if (ifa->ifa_addr->sa_family == AF_INET) {
116 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
117 *mask = ntohl(si->sin_addr.s_addr);
118 si = (struct sockaddr_in *) ifa->ifa_addr;
119 *ip = ntohl(si->sin_addr.s_addr);
120 if (strcmp(ifa->ifa_name, "lo") != 0)
121 net_get_mac(ifa->ifa_name, mac);
122
123 rv = 0;
124 break;
125 }
126 }
127
128 freeifaddrs(ifaddr);
129 return rv;
130}
131
132// bring interface up
133void net_if_up(const char *ifname) {
134 if (strlen(ifname) > IFNAMSIZ) {
135 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
136 exit(1);
137 }
138
139 int sock = socket(AF_INET,SOCK_DGRAM,0);
140 if (sock < 0)
141 errExit("socket");
142
143 // get the existing interface flags
144 struct ifreq ifr;
145 memset(&ifr, 0, sizeof(ifr));
146 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
147 ifr.ifr_addr.sa_family = AF_INET;
148
149 // read the existing flags
150 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
151 close(sock);
152 errExit("ioctl");
153 }
154
155 ifr.ifr_flags |= IFF_UP;
156
157 // set the new flags
158 if (ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0) {
159 close(sock);
160 errExit("ioctl");
161 }
162
163 // checking
164 // read the existing flags
165 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
166 close(sock);
167 errExit("ioctl");
168 }
169
170 // wait not more than 500ms for the interface to come up
171 int cnt = 0;
172 while (cnt < 50) {
173 usleep(10000); // sleep 10ms
174
175 // read the existing flags
176 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
177 close(sock);
178 errExit("ioctl");
179 }
180 if (ifr.ifr_flags & IFF_RUNNING)
181 break;
182 cnt++;
183 }
184
185 close(sock);
186}
187
188// configure interface
189void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask) {
190 if (strlen(ifname) > IFNAMSIZ) {
191 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
192 exit(1);
193 }
194
195 int sock = socket(AF_INET,SOCK_DGRAM,0);
196 if (sock < 0)
197 errExit("socket");
198
199 struct ifreq ifr;
200 memset(&ifr, 0, sizeof(ifr));
201 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
202 ifr.ifr_addr.sa_family = AF_INET;
203
204 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip);
205 if (ioctl( sock, SIOCSIFADDR, &ifr ) < 0) {
206 close(sock);
207 errExit("ioctl");
208 }
209
210 if (ip != 0) {
211 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(mask);
212 if (ioctl( sock, SIOCSIFNETMASK, &ifr ) < 0) {
213 close(sock);
214 errExit("ioctl");
215 }
216 }
217
218 close(sock);
219 usleep(10000); // sleep 10ms
220}
221
222
223// add an IP route, return -1 if error, 0 if the route was added
224int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) {
225 int sock;
226 struct rtentry route;
227 struct sockaddr_in *addr;
228 int err = 0;
229
230 // create the socket
231 if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
232 errExit("socket");
233
234 memset(&route, 0, sizeof(route));
235
236 addr = (struct sockaddr_in*) &route.rt_gateway;
237 addr->sin_family = AF_INET;
238 addr->sin_addr.s_addr = htonl(gw);
239
240 addr = (struct sockaddr_in*) &route.rt_dst;
241 addr->sin_family = AF_INET;
242 addr->sin_addr.s_addr = htonl(ip);
243
244 addr = (struct sockaddr_in*) &route.rt_genmask;
245 addr->sin_family = AF_INET;
246 addr->sin_addr.s_addr = htonl(mask);
247
248 route.rt_flags = RTF_UP | RTF_GATEWAY;
249 route.rt_metric = 0;
250 if ((err = ioctl(sock, SIOCADDRT, &route)) != 0) {
251 close(sock);
252 return -1;
253 }
254
255 close(sock);
256 return 0;
257}
258
259
260// add a veth device to a bridge
261void net_bridge_add_interface(const char *bridge, const char *dev) {
262 if (strlen(bridge) > IFNAMSIZ) {
263 fprintf(stderr, "Error: invalid network device name %s\n", bridge);
264 exit(1);
265 }
266
267 struct ifreq ifr;
268 int err;
269 int ifindex = if_nametoindex(dev);
270
271 if (ifindex <= 0)
272 errExit("if_nametoindex");
273
274 int sock;
275 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
276 errExit("socket");
277
278 memset(&ifr, 0, sizeof(ifr));
279 strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
280#ifdef SIOCBRADDIF
281 ifr.ifr_ifindex = ifindex;
282 err = ioctl(sock, SIOCBRADDIF, &ifr);
283 if (err < 0)
284#endif
285 {
286 unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 };
287
288 ifr.ifr_data = (char *) args;
289 err = ioctl(sock, SIOCDEVPRIVATE, &ifr);
290 }
291 (void) err;
292 close(sock);
293}
294
295#define BUFSIZE 1024
296uint32_t network_get_defaultgw(void) {
297 FILE *fp = fopen("/proc/self/net/route", "r");
298 if (!fp)
299 errExit("fopen");
300
301 char buf[BUFSIZE];
302 uint32_t retval = 0;
303 while (fgets(buf, BUFSIZE, fp)) {
304 if (strncmp(buf, "Iface", 5) == 0)
305 continue;
306
307 char *ptr = buf;
308 while (*ptr != ' ' && *ptr != '\t')
309 ptr++;
310 while (*ptr == ' ' || *ptr == '\t')
311 ptr++;
312
313 unsigned dest;
314 unsigned gw;
315 int rv = sscanf(ptr, "%x %x", &dest, &gw);
316 if (rv == 2 && dest == 0) {
317 retval = ntohl(gw);
318 break;
319 }
320 }
321
322 fclose(fp);
323 return retval;
324}
325
326int net_config_mac(const char *ifname, const unsigned char mac[6]) {
327 struct ifreq ifr;
328 int sock;
329
330 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
331 errExit("socket");
332
333 memset(&ifr, 0, sizeof(ifr));
334 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
335 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
336 memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
337
338 if (ioctl(sock, SIOCSIFHWADDR, &ifr) == -1)
339 errExit("ioctl");
340 close(sock);
341 return 0;
342}
343
344int net_get_mac(const char *ifname, unsigned char mac[6]) {
345
346 struct ifreq ifr;
347 int sock;
348
349 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
350 errExit("socket");
351
352 memset(&ifr, 0, sizeof(ifr));
353 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
354 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
355
356 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1)
357 errExit("ioctl");
358 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
359
360 close(sock);
361 return 0;
362}
diff --git a/src/firejail/network.txt b/src/firejail/network.txt
new file mode 100644
index 000000000..673d5b941
--- /dev/null
+++ b/src/firejail/network.txt
@@ -0,0 +1,95 @@
1struct Bridge {
2 char *dev; // bridge device name
3 uint32_t ip; // bridge device IP address
4 uint32_t mask; // bridge device mask
5 uint32_t ipsandbox // sandbox interface IP address
6}
7
8net_configure_bridge(br, device) {
9 br->dev = devname;
10 br->ip = extracted from kernel device - using net_get_if_addr() in network.c
11 br->mask = extracted from kernel device - using net_get_if_addr() in network.c
12 check available network range; /31 networks are not supported
13}
14
15net_configure_sandbox_ip(br) {
16 if br->ip_snadbox
17 check br->ipsandbox inside the bridge network
18 arp_check(br->ipsandbox) // send an arp req to check if anybody else is using this address
19 else
20 br->ipsandbox = arp_assign();
21}
22
23net_configure_veth_pair {
24 create a veth pair
25 place one interface end in the bridge
26 place the other end in the namespace of the child process
27}
28
29net_bridge_wait_ip {
30 arp_check br->ipsandbox address to come up
31 wait for not more than 5 seconds
32}
33
34main() {
35
36 foreach argv[i] {
37 if --net
38 br = next bridge available
39 net_configure_bridge(br, device name from argv[i]);
40 else if --ip
41 br = last bridge configured
42 br->ipsandbox = ip address extracted from argv[i]
43 else if --defaultgw
44 cfg.defaultgw = ip address extracted from argv[i]
45 }
46
47 net_check_cfg(); // check the validity of network configuration so far
48
49 if (any bridge configured) {
50 lock /var/lock/firejail.lock file
51 for each bridge
52 net_configure_sandbox_ip(br)
53 }
54
55 clone (new network namespace if any bridge configured or --net=none)
56
57 if (any bridge configured) {
58 for each bridge
59 net_configure_veth_pair
60 }
61
62 notify child init is done
63
64 if (any bridge configured) {
65 for each bridge
66 net_bridge_wait_ip
67 unlock /var/lock/firejail.lock file
68 }
69
70 wait on child
71 exit
72}
73
74
75******************************************************
76* macvlan notes
77******************************************************
78Configure a macvlan interface
79
80# ip link add virtual0 link eth0 type macvlan mode bridge
81(you can configure it with # ifconfig virtual0 192.168.1.52/24 up)
82
83Create a new network namespace and move the interface in the new network namespace
84
85# ip netns add dummy0
86# ip link set virtual0 netns dummy0
87
88Join the namespace and configure the interfaces
89
90# ip netns exec dummy0 bash
91# ifconfig lo up
92# ifconfig virtual0 192.168.1.52/24
93
94Investigate ipvlan interface - added to linux kernel 3.19
95https://github.com/torvalds/linux/blob/master/Documentation/networking/ipvlan.txt
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c
new file mode 100644
index 000000000..c2459b0cd
--- /dev/null
+++ b/src/firejail/network_main.c
@@ -0,0 +1,268 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include "firejail.h"
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <net/if.h>
26
27// configure bridge structure
28// - extract ip address and mask from the bridge interface
29void net_configure_bridge(Bridge *br, char *dev_name) {
30 assert(br);
31 assert(dev_name);
32
33 br->dev = dev_name;
34
35 // check the bridge device exists
36 char sysbridge[30 + strlen(br->dev)];
37 sprintf(sysbridge, "/sys/class/net/%s/bridge", br->dev);
38 struct stat s;
39 int rv = stat(sysbridge, &s);
40 if (rv == 0) {
41 // this is a bridge device
42 br->macvlan = 0;
43 }
44 else {
45 // is this a regular Ethernet interface
46 if (if_nametoindex(br->dev) > 0) {
47 br->macvlan = 1;
48 char *newname;
49 if (asprintf(&newname, "%s-%u", br->devsandbox, getpid()) == -1)
50 errExit("asprintf");
51 br->devsandbox = newname;
52 }
53 else {
54 fprintf(stderr, "Error: cannot find network device %s\n", br->dev);
55 exit(1);
56 }
57 }
58
59 if (net_get_if_addr(br->dev, &br->ip, &br->mask, br->mac)) {
60 fprintf(stderr, "Error: interface %s is not configured\n", br->dev);
61 exit(1);
62 }
63 if (arg_debug) {
64 if (br->macvlan == 0)
65 printf("Bridge device %s at %d.%d.%d.%d/%d\n",
66 br->dev, PRINT_IP(br->ip), mask2bits(br->mask));
67 else
68 printf("macvlan parent device %s at %d.%d.%d.%d/%d\n",
69 br->dev, PRINT_IP(br->ip), mask2bits(br->mask));
70 }
71
72 uint32_t range = ~br->mask + 1; // the number of potential addresses
73 // this software is not supported for /31 networks
74 if (range < 4) {
75 fprintf(stderr, "Error: the software is not supported for /31 networks\n");
76 exit(1);
77 }
78 br->configured = 1;
79}
80
81
82void net_configure_sandbox_ip(Bridge *br) {
83 assert(br);
84 if (br->configured == 0)
85 return;
86
87 if (br->arg_ip_none)
88 br->ipsandbox = 0;
89 else if (br->ipsandbox) {
90 // check network range
91 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
92 if (rv) {
93 fprintf(stderr, "%s", rv);
94 exit(1);
95 }
96 // send an ARP request and check if there is anybody on this IP address
97 if (arp_check(br->dev, br->ipsandbox, br->ip)) {
98 fprintf(stderr, "Error: IP address %d.%d.%d.%d is already in use\n", PRINT_IP(br->ipsandbox));
99 exit(1);
100 }
101 }
102 else
103 // ip address assigned by arp-scan for a bridge device
104 br->ipsandbox = arp_assign(br->dev, br); //br->ip, br->mask);
105}
106
107
108// create a veth pair
109// - br - bridge device
110// - ifname - interface name in sandbox namespace
111// - child - child process running the namespace
112
113void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) {
114 assert(br);
115 if (br->configured == 0)
116 return;
117
118 // create a veth pair
119 char *dev;
120 if (asprintf(&dev, "veth%u%s", getpid(), ifname) < 0)
121 errExit("asprintf");
122 net_create_veth(dev, ifname, child);
123
124 // bring up the interface
125 net_if_up(dev);
126
127 // add interface to the bridge
128 net_bridge_add_interface(br->dev, dev);
129
130 char *msg;
131 if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1)
132 errExit("asprintf");
133 logmsg(msg);
134 fflush(0);
135 free(msg);
136}
137
138// the default address should be in the range of at least on of the bridge devices
139void check_default_gw(uint32_t defaultgw) {
140 assert(defaultgw);
141
142 if (cfg.bridge0.configured) {
143 char *rv = in_netrange(defaultgw, cfg.bridge0.ip, cfg.bridge0.mask);
144 if (rv == 0)
145 return;
146 }
147 if (cfg.bridge1.configured) {
148 char *rv = in_netrange(defaultgw, cfg.bridge1.ip, cfg.bridge1.mask);
149 if (rv == 0)
150 return;
151 }
152 if (cfg.bridge2.configured) {
153 char *rv = in_netrange(defaultgw, cfg.bridge2.ip, cfg.bridge2.mask);
154 if (rv == 0)
155 return;
156 }
157 if (cfg.bridge3.configured) {
158 char *rv = in_netrange(defaultgw, cfg.bridge3.ip, cfg.bridge3.mask);
159 if (rv == 0)
160 return;
161 }
162
163 fprintf(stderr, "Error: default gateway %d.%d.%d.%d is not in the range of any network\n", PRINT_IP(defaultgw));
164 exit(1);
165}
166
167void net_check_cfg(void) {
168 int net_configured = 0;
169 if (cfg.bridge0.configured)
170 net_configured++;
171 if (cfg.bridge1.configured)
172 net_configured++;
173 if (cfg.bridge2.configured)
174 net_configured++;
175 if (cfg.bridge3.configured)
176 net_configured++;
177
178 // --defaultgw requires a network
179 if (cfg.defaultgw && net_configured == 0) {
180 fprintf(stderr, "Error: option --defaultgw requires at least one network to be configured\n");
181 exit(1);
182 }
183
184 if (net_configured == 0) // nothing to check
185 return;
186
187 // --net=none
188 if (arg_nonetwork && net_configured) {
189 fprintf(stderr, "Error: --net and --net=none are mutually exclusive\n");
190 exit(1);
191 }
192
193 // check default gateway address or assign one
194 assert(cfg.bridge0.configured);
195 if (cfg.defaultgw)
196 check_default_gw(cfg.defaultgw);
197 else {
198 // first network is a regular bridge
199 if (cfg.bridge0.macvlan == 0)
200 cfg.defaultgw = cfg.bridge0.ip;
201 // first network is a mac device
202 else {
203 // get the host default gw
204 uint32_t gw = network_get_defaultgw();
205 // check the gateway is network range
206 if (in_netrange(gw, cfg.bridge0.ip, cfg.bridge0.mask))
207 gw = 0;
208 cfg.defaultgw = gw;
209 }
210 }
211}
212
213
214
215void net_dns_print_name(const char *name) {
216 if (!name || strlen(name) == 0) {
217 fprintf(stderr, "Error: invalid sandbox name\n");
218 exit(1);
219 }
220 pid_t pid;
221 if (name2pid(name, &pid)) {
222 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
223 exit(1);
224 }
225
226 net_dns_print(pid);
227}
228
229#define MAXBUF 4096
230void net_dns_print(pid_t pid) {
231 // drop privileges - will not be able to read /etc/resolv.conf for --noroot option
232// drop_privs(1);
233
234 // if the pid is that of a firejail process, use the pid of the first child process
235 char *comm = pid_proc_comm(pid);
236 if (comm) {
237 // remove \n
238 char *ptr = strchr(comm, '\n');
239 if (ptr)
240 *ptr = '\0';
241 if (strcmp(comm, "firejail") == 0) {
242 pid_t child;
243 if (find_child(pid, &child) == 0) {
244 pid = child;
245 }
246 }
247 free(comm);
248 }
249
250 char *fname;
251 if (asprintf(&fname, "/proc/%d/root/etc/resolv.conf", pid) == -1)
252 errExit("asprintf");
253
254 // access /etc/resolv.conf
255 FILE *fp = fopen(fname, "r");
256 if (!fp) {
257 fprintf(stderr, "Error: cannot access /etc/resolv.conf\n");
258 exit(1);
259 }
260
261 char buf[MAXBUF];
262 while (fgets(buf, MAXBUF, fp))
263 printf("%s", buf);
264 printf("\n");
265 fclose(fp);
266 free(fname);
267 exit(0);
268}
diff --git a/src/firejail/output.c b/src/firejail/output.c
new file mode 100644
index 000000000..32adac108
--- /dev/null
+++ b/src/firejail/output.c
@@ -0,0 +1,84 @@
1#include "firejail.h"
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <unistd.h>
5
6void check_output(int argc, char **argv) {
7 int i;
8 char *outfile = NULL;
9// drop_privs(0);
10
11 int found = 0;
12 for (i = 1; i < argc; i++) {
13 if (strncmp(argv[i], "--output=", 9) == 0) {
14 found = 1;
15 outfile = argv[i] + 9;
16
17 // do not accept directories, links, and files with ".."
18 if (strstr(outfile, "..") || is_link(outfile) || is_dir(outfile)) {
19 fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n");
20 exit(1);
21 }
22
23 struct stat s;
24 if (stat(outfile, &s) == 0) {
25 // check permissions
26 if (s.st_uid != getuid() || s.st_gid != getgid()) {
27 fprintf(stderr, "Error: the output file needs to be owned by the current user.\n");
28 exit(1);
29 }
30
31 // check hard links
32 if (s.st_nlink != 1) {
33 fprintf(stderr, "Error: no hard links allowed.\n");
34 exit(1);
35 }
36 }
37
38 // drop privileges and try to open the file for writing
39 drop_privs(0);
40 /* coverity[toctou] */
41 FILE *fp = fopen(outfile, "a");
42 if (!fp) {
43 fprintf(stderr, "Error: cannot open output file %s\n", outfile);
44 exit(1);
45 }
46 fclose(fp);
47 break;
48 }
49 }
50 if (!found)
51 return;
52
53
54 // build the new command line
55 int len = 0;
56 for (i = 0; i < argc; i++) {
57 len += strlen(argv[i]) + 1; // + ' '
58 }
59 len += 50 + strlen(outfile); // tee command
60
61 char *cmd = malloc(len + 1); // + '\0'
62 if (!cmd)
63 errExit("malloc");
64
65 char *ptr = cmd;
66 for (i = 0; i < argc; i++) {
67 if (strncmp(argv[i], "--output=", 9) == 0)
68 continue;
69 ptr += sprintf(ptr, "%s ", argv[i]);
70 }
71 sprintf(ptr, "| %s/lib/firejail/ftee %s", PREFIX, outfile);
72
73 // run command
74 char *a[4];
75 a[0] = "/bin/bash";
76 a[1] = "-c";
77 a[2] = cmd;
78 a[3] = NULL;
79
80 execvp(a[0], a);
81
82 perror("execvp");
83 exit(1);
84}
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
new file mode 100644
index 000000000..343907584
--- /dev/null
+++ b/src/firejail/profile.c
@@ -0,0 +1,444 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <dirent.h>
22#include <sys/stat.h>
23
24#define MAX_READ 8192 // line buffer for profile files
25
26// find and read the profile specified by name from dir directory
27int profile_find(const char *name, const char *dir) {
28 assert(name);
29 assert(dir);
30
31 int rv = 0;
32 DIR *dp;
33 char *pname;
34 if (asprintf(&pname, "%s.profile", name) == -1)
35 errExit("asprintf");
36
37 dp = opendir (dir);
38 if (dp != NULL) {
39 struct dirent *ep;
40 while ((ep = readdir(dp)) != NULL) {
41 if (strcmp(ep->d_name, pname) == 0) {
42 if (arg_debug)
43 printf("Found %s profile in %s directory\n", name, dir);
44 char *etcpname;
45 if (asprintf(&etcpname, "%s/%s", dir, pname) == -1)
46 errExit("asprintf");
47 profile_read(etcpname, NULL, NULL);
48 free(etcpname);
49 rv = 1;
50 break;
51 }
52 }
53 (void) closedir (dp);
54 }
55
56 free(pname);
57 return rv;
58}
59
60
61//***************************************************
62// run-time profiles
63//***************************************************
64static void check_file_name(char *ptr, int lineno) {
65 if (strncmp(ptr, "${HOME}", 7) == 0)
66 ptr += 7;
67 else if (strncmp(ptr, "${PATH}", 7) == 0)
68 ptr += 7;
69
70 int len = strlen(ptr);
71 // file globbing ('*') is allowed
72 if (strcspn(ptr, "\\&!?\"'<>%^(){}[];, ") != len) {
73 if (lineno == 0)
74 fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr);
75 else
76 fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
77 exit(1);
78 }
79}
80
81
82// check profile line; if line == 0, this was generated from a command line option
83// return 1 if the command is to be added to the linked list of profile commands
84// return 0 if the command was already executed inside the function
85int profile_check_line(char *ptr, int lineno) {
86 // seccomp, caps, private, user namespace
87 if (strcmp(ptr, "noroot") == 0) {
88 check_user_namespace();
89 return 0;
90 }
91 else if (strcmp(ptr, "seccomp") == 0) {
92 arg_seccomp = 1;
93 return 0;
94 }
95 else if (strcmp(ptr, "caps") == 0) {
96 arg_caps_default_filter = 1;
97 return 0;
98 }
99 else if (strcmp(ptr, "caps.drop all") == 0) {
100 arg_caps_drop_all = 1;
101 return 0;
102 }
103 else if (strcmp(ptr, "shell none") == 0) {
104 arg_shell_none = 1;
105 return 0;
106 }
107 else if (strcmp(ptr, "private") == 0) {
108 arg_private = 1;
109 return 0;
110 }
111 else if (strcmp(ptr, "private-dev") == 0) {
112 arg_private_dev = 1;
113 return 0;
114 }
115 else if (strcmp(ptr, "nogroups") == 0) {
116 arg_nogroups = 1;
117 return 0;
118 }
119 else if (strcmp(ptr, "netfilter") == 0) {
120 arg_netfilter = 1;
121 return 0;
122 }
123 else if (strncmp(ptr, "netfilter ", 10) == 0) {
124 arg_netfilter = 1;
125 arg_netfilter_file = strdup(ptr + 10);
126 if (!arg_netfilter_file)
127 errExit("strdup");
128 check_netfilter_file(arg_netfilter_file);
129 return 0;
130 }
131
132 // seccomp drop list on top of default list
133 if (strncmp(ptr, "seccomp ", 8) == 0) {
134 arg_seccomp = 1;
135#ifdef HAVE_SECCOMP
136 arg_seccomp_list = strdup(ptr + 8);
137 if (!arg_seccomp_list)
138 errExit("strdup");
139#endif
140 return 0;
141 }
142
143 // seccomp drop list without default list
144 if (strncmp(ptr, "seccomp.drop ", 13) == 0) {
145 arg_seccomp = 1;
146#ifdef HAVE_SECCOMP
147 arg_seccomp_list_drop = strdup(ptr + 13);
148 if (!arg_seccomp_list_drop)
149 errExit("strdup");
150#endif
151 return 0;
152 }
153
154 // seccomp keep list
155 if (strncmp(ptr, "seccomp.keep ", 13) == 0) {
156 arg_seccomp = 1;
157#ifdef HAVE_SECCOMP
158 arg_seccomp_list_keep= strdup(ptr + 13);
159 if (!arg_seccomp_list_keep)
160 errExit("strdup");
161#endif
162 return 0;
163 }
164
165 // caps drop list
166 if (strncmp(ptr, "caps.drop ", 10) == 0) {
167 arg_caps_drop = 1;
168 arg_caps_list = strdup(ptr + 10);
169 if (!arg_caps_list)
170 errExit("strdup");
171 // verify seccomp list and exit if problems
172 if (caps_check_list(arg_caps_list, NULL))
173 exit(1);
174 return 0;
175 }
176
177 // caps keep list
178 if (strncmp(ptr, "caps.keep ", 10) == 0) {
179 arg_caps_keep = 1;
180 arg_caps_list = strdup(ptr + 10);
181 if (!arg_caps_list)
182 errExit("strdup");
183 // verify seccomp list and exit if problems
184 if (caps_check_list(arg_caps_list, NULL))
185 exit(1);
186 return 0;
187 }
188
189 // dns
190 if (strncmp(ptr, "dns ", 4) == 0) {
191 uint32_t dns;
192 if (atoip(ptr + 4, &dns)) {
193 fprintf(stderr, "Error: invalid DNS server IP address\n");
194 return 1;
195 }
196
197 if (cfg.dns1 == 0)
198 cfg.dns1 = dns;
199 else if (cfg.dns2 == 0)
200 cfg.dns2 = dns;
201 else if (cfg.dns3 == 0)
202 cfg.dns3 = dns;
203 else {
204 fprintf(stderr, "Error: up to 3 DNS servers can be specified\n");
205 return 1;
206 }
207 return 0;
208 }
209
210 // cpu affinity
211 if (strncmp(ptr, "cpu ", 4) == 0) {
212 read_cpu_list(ptr + 4);
213 return 0;
214 }
215
216 // cgroup
217 if (strncmp(ptr, "cgroup ", 7) == 0) {
218 set_cgroup(ptr + 7);
219 return 0;
220 }
221
222 // private directory
223 if (strncmp(ptr, "private ", 8) == 0) {
224 cfg.home_private = ptr + 8;
225 fs_check_private_dir();
226 arg_private = 1;
227 return 0;
228 }
229
230 // private list of files and directories
231 if (strncmp(ptr, "private.keep ", 13) == 0) {
232 cfg.home_private_keep = ptr + 13;
233 fs_check_home_list();
234 arg_private = 1;
235 return 0;
236 }
237
238 // filesystem bind
239 if (strncmp(ptr, "bind ", 5) == 0) {
240 if (getuid() != 0) {
241 fprintf(stderr, "Error: --bind option is available only if running as root\n");
242 exit(1);
243 }
244
245 // extract two directories
246 char *dname1 = ptr + 5;
247 char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories
248 if (dname2 == NULL) {
249 fprintf(stderr, "Error: mising second directory for bind\n");
250 exit(1);
251 }
252
253 // check directories
254 check_file_name(dname1, lineno);
255 check_file_name(dname2, lineno);
256 if (strstr(dname1, "..") || strstr(dname2, "..")) {
257 fprintf(stderr, "Error: invalid file name.\n");
258 exit(1);
259 }
260
261 // insert comma back
262 *(dname2 - 1) = ',';
263 return 1;
264 }
265
266 // rlimit
267 if (strncmp(ptr, "rlimit", 6) == 0) {
268 if (strncmp(ptr, "rlimit-nofile ", 14) == 0) {
269 ptr += 14;
270 if (not_unsigned(ptr)) {
271 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
272 exit(1);
273 }
274 sscanf(ptr, "%u", &cfg.rlimit_nofile);
275 arg_rlimit_nofile = 1;
276 }
277 else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) {
278 ptr += 13;
279 if (not_unsigned(ptr)) {
280 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
281 exit(1);
282 }
283 sscanf(ptr, "%u", &cfg.rlimit_nproc);
284 arg_rlimit_nproc = 1;
285 }
286 else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) {
287 ptr += 13;
288 if (not_unsigned(ptr)) {
289 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
290 exit(1);
291 }
292 sscanf(ptr, "%u", &cfg.rlimit_fsize);
293 arg_rlimit_fsize = 1;
294 }
295 else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) {
296 ptr += 18;
297 if (not_unsigned(ptr)) {
298 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
299 exit(1);
300 }
301 sscanf(ptr, "%u", &cfg.rlimit_sigpending);
302 arg_rlimit_sigpending = 1;
303 }
304 else {
305 fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
306 exit(1);
307 }
308
309 return 0;
310 }
311
312 // rest of filesystem
313 if (strncmp(ptr, "blacklist ", 10) == 0)
314 ptr += 10;
315 else if (strncmp(ptr, "read-only ", 10) == 0)
316 ptr += 10;
317 else if (strncmp(ptr, "tmpfs ", 6) == 0)
318 ptr += 6;
319 else {
320 if (lineno == 0)
321 fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr);
322 else
323 fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
324 exit(1);
325 }
326
327 // some characters just don't belong in filenames
328 check_file_name(ptr, lineno);
329 if (strstr(ptr, "..")) {
330 if (lineno == 0)
331 fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr);
332 else
333 fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
334 exit(1);
335 }
336 return 1;
337}
338
339// add a profile entry in cfg.profile list; use str to populate the list
340void profile_add(char *str) {
341 ProfileEntry *prf = malloc(sizeof(ProfileEntry));
342 if (!prf)
343 errExit("malloc");
344 prf->next = NULL;
345 prf->data = str;
346
347 // add prf to the list
348 if (cfg.profile == NULL) {
349 cfg.profile = prf;
350 return;
351 }
352 ProfileEntry *ptr = cfg.profile;
353 while (ptr->next != NULL)
354 ptr = ptr->next;
355 ptr->next = prf;
356}
357
358// read a profile file
359static int include_level = 0;
360// skip1, skip2 - if the string is found in the line, the line is not interpreted
361void profile_read(const char *fname, const char *skip1, const char *skip2) {
362 // exit program if maximum include level was reached
363 if (include_level > MAX_INCLUDE_LEVEL) {
364 fprintf(stderr, "Error: maximum profile include level was reached\n");
365 exit(1);
366 }
367
368 if (strlen(fname) == 0) {
369 fprintf(stderr, "Error: invalid profile file\n");
370 exit(1);
371 }
372
373 // open profile file:
374 FILE *fp = fopen(fname, "r");
375 if (fp == NULL) {
376 fprintf(stderr, "Error: cannot open profile file\n");
377 exit(1);
378 }
379
380 fprintf(stderr, "Reading profile %s\n", fname);
381
382 // read the file line by line
383 char buf[MAX_READ + 1];
384 int lineno = 0;
385 while (fgets(buf, MAX_READ, fp)) {
386 ++lineno;
387 // remove empty space - ptr in allocated memory
388 char *ptr = line_remove_spaces(buf);
389 if (ptr == NULL)
390 continue;
391
392 // comments
393 if (*ptr == '#' || *ptr == '\0') {
394 free(ptr);
395 continue;
396 }
397
398 // process include
399 if (strncmp(ptr, "include ", 8) == 0) {
400 include_level++;
401
402 // extract profile filename and new skip params
403 char *newprofile = ptr + 8; // profile name
404 char *newskip1 = NULL; // new skip1
405 char *newskip2 = NULL; // new skip2
406 char *p = newprofile;
407 while (*p != '\0') {
408 if (*p == ' ') {
409 *p = '\0';
410 if (newskip1 == NULL)
411 newskip1 = p + 1;
412 else if (newskip2 == NULL)
413 newskip2 = p + 1;
414 }
415 p++;
416 }
417
418 // recursivity
419 profile_read(newprofile, newskip1, newskip2);
420 include_level--;
421 free(ptr);
422 continue;
423 }
424
425 // skip
426 if (skip1) {
427 if (strstr(ptr, skip1)) {
428 free(ptr);
429 continue;
430 }
431 }
432 if (skip2) {
433 if (strstr(ptr, skip2)) {
434 free(ptr);
435 continue;
436 }
437 }
438
439 // verify syntax, exit in case of error
440 if (profile_check_line(ptr, lineno))
441 profile_add(ptr);
442 }
443 fclose(fp);
444}
diff --git a/src/firejail/restricted_shell.c b/src/firejail/restricted_shell.c
new file mode 100644
index 000000000..ba3aae759
--- /dev/null
+++ b/src/firejail/restricted_shell.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21
22#define MAX_READ 4096 // maximum line length
23char *restricted_user = NULL;
24
25
26int restricted_shell(const char *user) {
27 assert(user);
28
29 // open profile file:
30 FILE *fp = fopen("/etc/firejail/login.users", "r");
31 if (fp == NULL)
32 return 0;
33
34 int lineno = 0;
35 char buf[MAX_READ];
36 while (fgets(buf, MAX_READ, fp)) {
37 lineno++;
38
39 // remove empty spaces at the beginning of the line
40 char *ptr = buf;
41 while (*ptr == ' ' || *ptr == '\t') {
42 ptr++;
43 }
44 if (*ptr == '\n' || *ptr == '#')
45 continue;
46
47 // parse line
48 char *usr = ptr;
49 char *args = strchr(usr, ':');
50 if (args == NULL) {
51 fprintf(stderr, "Error: users.conf line %d\n", lineno);
52 exit(1);
53 }
54 *args = '\0';
55 args++;
56 ptr = strchr(args, '\n');
57 if (ptr)
58 *ptr = '\0';
59
60 if (strcmp(user, usr) == 0) {
61 restricted_user = strdup(user);
62 // extract program arguments
63
64 fullargv[0] = "firejail";
65 int i;
66 ptr = args;
67 for (i = 1; i < MAX_ARGS; i++) {
68 fullargv[i] = ptr;
69 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
70 ptr++;
71 if (*ptr != '\0') {
72 *ptr ='\0';
73 fullargv[i] = strdup(fullargv[i]);
74 if (fullargv[i] == NULL) {
75 fprintf(stderr, "Error: cannot allocate memory\n");
76 exit(1);
77 }
78 ptr++;
79 while (*ptr == ' ' || *ptr == '\t')
80 ptr++;
81 if (*ptr != '\0')
82 continue;
83 }
84 fullargv[i] = strdup(fullargv[i]);
85 fclose(fp);
86 return i + 1;
87 }
88 fprintf(stderr, "Error: too many program arguments in users.conf line %d\n", lineno);
89 exit(1);
90 }
91 }
92 fclose(fp);
93
94 return 0;
95}
96
diff --git a/src/firejail/rlimit.c b/src/firejail/rlimit.c
new file mode 100644
index 000000000..6c755a08d
--- /dev/null
+++ b/src/firejail/rlimit.c
@@ -0,0 +1,62 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/time.h>
22#include <sys/resource.h>
23
24void set_rlimits(void) {
25 // resource limits
26 struct rlimit rl;
27 if (arg_rlimit_nofile) {
28 rl.rlim_cur = (rlim_t) cfg.rlimit_nofile;
29 rl.rlim_max = (rlim_t) cfg.rlimit_nofile;
30 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
31 errExit("setrlimit");
32 if (arg_debug)
33 printf("Config rlimit: number of open file descriptors %u\n", cfg.rlimit_nofile);
34 }
35
36 if (arg_rlimit_nproc) {
37 rl.rlim_cur = (rlim_t) cfg.rlimit_nproc;
38 rl.rlim_max = (rlim_t) cfg.rlimit_nproc;
39 if (setrlimit(RLIMIT_NPROC, &rl) == -1)
40 errExit("setrlimit");
41 if (arg_debug)
42 printf("Config rlimit: number of processes %u\n", cfg.rlimit_nproc);
43 }
44
45 if (arg_rlimit_fsize) {
46 rl.rlim_cur = (rlim_t) cfg.rlimit_fsize;
47 rl.rlim_max = (rlim_t) cfg.rlimit_fsize;
48 if (setrlimit(RLIMIT_FSIZE, &rl) == -1)
49 errExit("setrlimit");
50 if (arg_debug)
51 printf("Config rlimit: maximum file size %u\n", cfg.rlimit_fsize);
52 }
53
54 if (arg_rlimit_sigpending) {
55 rl.rlim_cur = (rlim_t) cfg.rlimit_sigpending;
56 rl.rlim_max = (rlim_t) cfg.rlimit_sigpending;
57 if (setrlimit(RLIMIT_SIGPENDING, &rl) == -1)
58 errExit("setrlimit");
59 if (arg_debug)
60 printf("Config rlimit: maximum number of signals pending %u\n", cfg.rlimit_sigpending);
61 }
62}
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
new file mode 100644
index 000000000..3f5fb51fa
--- /dev/null
+++ b/src/firejail/sandbox.c
@@ -0,0 +1,490 @@
1/*
2 * Copyright (C) 2014, 2015 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "firejail.h"
22#include <sys/mount.h>
23#include <sys/wait.h>
24#include <sys/stat.h>
25#include <sys/prctl.h>
26#include <sys/time.h>
27#include <sys/resource.h>
28
29#include <sched.h>
30#ifndef CLONE_NEWUSER
31#define CLONE_NEWUSER 0x10000000
32#endif
33
34static void set_caps(void) {
35 if (arg_caps_drop_all)
36 caps_drop_all();
37 else if (arg_caps_drop)
38 caps_drop_list(arg_caps_list);
39 else if (arg_caps_keep)
40 caps_keep_list(arg_caps_list);
41 else if (arg_caps_default_filter)
42 caps_default_filter();
43}
44
45void save_nogroups(void) {
46 if (arg_nogroups == 0)
47 return;
48
49 char *fname;
50 if (asprintf(&fname, "%s/groups", MNT_DIR) == -1)
51 errExit("asprintf");
52 FILE *fp = fopen(fname, "w");
53 if (fp) {
54 fprintf(fp, "\n");
55 fclose(fp);
56 if (chown(fname, 0, 0) < 0)
57 errExit("chown");
58 }
59 else {
60 fprintf(stderr, "Error: cannot save nogroups state\n");
61 free(fname);
62 exit(1);
63 }
64
65 free(fname);
66}
67
68static void sandbox_if_up(Bridge *br) {
69 assert(br);
70 if (!br->configured)
71 return;
72
73 char *dev = br->devsandbox;
74 net_if_up(dev);
75
76 if (br->arg_ip_none == 1); // do nothing
77 else if (br->arg_ip_none == 0 && br->macvlan == 0) {
78 if (br->ipsandbox == br->ip) {
79 fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev);
80 exit(1);
81 }
82
83 // just assign the address
84 assert(br->ipsandbox);
85 if (arg_debug)
86 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev);
87 net_if_ip(dev, br->ipsandbox, br->mask);
88 net_if_up(dev);
89 }
90 else if (br->arg_ip_none == 0 && br->macvlan == 1) {
91 // reassign the macvlan address
92 if (br->ipsandbox == 0)
93 // ip address assigned by arp-scan for a macvlan device
94 br->ipsandbox = arp_assign(dev, br); //br->ip, br->mask);
95 else {
96 if (br->ipsandbox == br->ip) {
97 fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev);
98 exit(1);
99 }
100
101 uint32_t rv = arp_check(dev, br->ipsandbox, br->ip);
102 if (rv) {
103 fprintf(stderr, "Error: the address %d.%d.%d.%d is already in use.\n", PRINT_IP(br->ipsandbox));
104 exit(1);
105 }
106 }
107
108 if (arg_debug)
109 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev);
110 net_if_ip(dev, br->ipsandbox, br->mask);
111 net_if_up(dev);
112 }
113}
114
115static void chk_chroot(void) {
116 // if we are starting firejail inside some other container technology, we don't care about this
117 char *mycont = getenv("container");
118 if (mycont)
119 return;
120
121 // check if this is a regular chroot
122 struct stat s;
123 if (stat("/", &s) == 0) {
124 if (s.st_ino != 2)
125 return;
126 }
127
128 fprintf(stderr, "Error: cannot mount filesystem as slave\n");
129 exit(1);
130}
131
132int sandbox(void* sandbox_arg) {
133 pid_t child_pid = getpid();
134 if (arg_debug)
135 printf("Initializing child process\n");
136
137 // close each end of the unused pipes
138 close(parent_to_child_fds[1]);
139 close(child_to_parent_fds[0]);
140
141 // wait for parent to do base setup
142 wait_for_other(parent_to_child_fds[0]);
143
144 if (arg_debug && child_pid == 1)
145 printf("PID namespace installed\n");
146
147 //****************************
148 // set hostname
149 //****************************
150 if (cfg.hostname) {
151 if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0)
152 errExit("sethostname");
153 }
154
155 //****************************
156 // mount namespace
157 //****************************
158 // mount events are not forwarded between the host the sandbox
159 if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
160 chk_chroot();
161 }
162
163 //****************************
164 // netfilter
165 //****************************
166 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter
167 netfilter(arg_netfilter_file);
168 }
169
170 //****************************
171 // trace pre-install
172 //****************************
173 if (arg_trace)
174 fs_trace_preload();
175
176 //****************************
177 // configure filesystem
178 //****************************
179#ifdef HAVE_CHROOT
180 if (cfg.chrootdir) {
181 fs_chroot(cfg.chrootdir);
182 // force caps and seccomp if not started as root
183 if (getuid() != 0) {
184 // force default seccomp inside the chroot, no keep or drop list
185 // the list build on top of the default drop list is kept intact
186 arg_seccomp = 1;
187 if (arg_seccomp_list_drop) {
188 free(arg_seccomp_list_drop);
189 arg_seccomp_list_drop = NULL;
190 }
191 if (arg_seccomp_list_keep) {
192 free(arg_seccomp_list_keep);
193 arg_seccomp_list_keep = NULL;
194 }
195
196 // disable all capabilities
197 if (arg_caps_default_filter || arg_caps_list)
198 fprintf(stderr, "Warning: all capabilities disabled for a regular user during chroot\n");
199 arg_caps_drop_all = 1;
200
201 // drop all supplementary groups; /etc/group file inside chroot
202 // is controlled by a regular usr
203 arg_nogroups = 1;
204 printf("Dropping all Linux capabilities and enforcing default seccomp filter\n");
205 }
206
207 //****************************
208 // trace pre-install, this time inside chroot
209 //****************************
210 if (arg_trace)
211 fs_trace_preload();
212 }
213 else
214#endif
215 if (arg_overlay)
216 fs_overlayfs();
217 else
218 fs_basic_fs();
219
220
221 //****************************
222 // set hostname in /etc/hostname
223 //****************************
224 if (cfg.hostname) {
225 fs_hostname(cfg.hostname);
226 }
227
228 //****************************
229 // apply the profile file
230 //****************************
231 if (cfg.profile)
232 fs_blacklist(cfg.homedir);
233
234 //****************************
235 // private mode
236 //****************************
237 if (arg_private) {
238 if (cfg.home_private) // --private=
239 fs_private_homedir();
240 else if (cfg.home_private_keep) // --private.keep=
241 fs_private_home_list();
242 else // --private
243 fs_private();
244 }
245
246 if (arg_private_dev)
247 fs_private_dev();
248
249 //****************************
250 // install trace
251 //****************************
252 if (arg_trace)
253 fs_trace();
254
255 //****************************
256 // update /proc, /dev, /boot directorymy
257 //****************************
258 fs_proc_sys_dev_boot();
259
260 //****************************
261 // networking
262 //****************************
263 if (arg_nonetwork) {
264 net_if_up("lo");
265 }
266 else if (any_bridge_configured()) {
267 // configure lo and eth0...eth3
268 net_if_up("lo");
269
270 if (mac_not_zero(cfg.bridge0.macsandbox))
271 net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox);
272 sandbox_if_up(&cfg.bridge0);
273
274 if (mac_not_zero(cfg.bridge1.macsandbox))
275 net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox);
276 sandbox_if_up(&cfg.bridge1);
277
278 if (mac_not_zero(cfg.bridge2.macsandbox))
279 net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox);
280 sandbox_if_up(&cfg.bridge2);
281
282 if (mac_not_zero(cfg.bridge3.macsandbox))
283 net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox);
284 sandbox_if_up(&cfg.bridge3);
285
286 // add a default route
287 if (cfg.defaultgw) {
288 // set the default route
289 if (net_add_route(0, 0, cfg.defaultgw))
290 fprintf(stderr, "Warning: cannot configure default route\n");
291 }
292
293 if (arg_debug)
294 printf("Network namespace enabled\n");
295 }
296
297 // if any dns server is configured, it is time to set it now
298 fs_resolvconf();
299
300 // print network configuration
301 if (any_bridge_configured() || cfg.defaultgw || cfg.dns1) {
302 printf("\n");
303 if (any_bridge_configured())
304 net_ifprint();
305 if (cfg.defaultgw != 0)
306 printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw));
307 if (cfg.dns1 != 0)
308 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
309 if (cfg.dns2 != 0)
310 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
311 if (cfg.dns3 != 0)
312 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
313 printf("\n");
314 }
315
316
317
318 //****************************
319 // start executable
320 //****************************
321 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
322 int cwd = 0;
323 if (cfg.cwd) {
324 if (chdir(cfg.cwd) == 0)
325 cwd = 1;
326 }
327
328 if (!cwd) {
329 if (chdir("/") < 0)
330 errExit("chdir");
331 if (cfg.homedir) {
332 struct stat s;
333 if (stat(cfg.homedir, &s) == 0) {
334 /* coverity[toctou] */
335 if (chdir(cfg.homedir) < 0)
336 errExit("chdir");
337 }
338 }
339 }
340
341 // set environment
342 // fix qt 4.8
343 if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
344 errExit("setenv");
345 if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
346 errExit("setenv");
347 if (arg_zsh && setenv("SHELL", "/usr/bin/zsh", 1) < 0)
348 errExit("setenv");
349 if (arg_csh && setenv("SHELL", "/bin/csh", 1) < 0)
350 errExit("setenv");
351 if (cfg.shell && setenv("SHELL", cfg.shell, 1) < 0)
352 errExit("setenv");
353 // set prompt color to green
354 //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
355 if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
356 errExit("setenv");
357
358
359 // set capabilities
360 if (!arg_noroot)
361 set_caps();
362
363 // set rlimits
364 set_rlimits();
365
366 // set seccomp
367#ifdef HAVE_SECCOMP
368 // if a keep list is available, disregard the drop list
369 if (arg_seccomp == 1) {
370 if (arg_seccomp_list_keep)
371 seccomp_filter_keep(); // this will also save the fmyilter to MNT_DIR/seccomp file
372 else
373 seccomp_filter_drop(); // this will also save the filter to MNT_DIR/seccomp file
374 }
375#endif
376
377 // set cpu affinity
378 if (cfg.cpus) {
379 save_cpu(); // save cpu affinity mask to MNT_DIR/cpu file
380 set_cpu_affinity();
381 }
382
383 // save cgroup in MNT_DIR/cgroup file
384 if (cfg.cgroup)
385 save_cgroup();
386
387 //****************************************
388 // drop privileges or create a new user namespace
389 //****************************************
390 save_nogroups();
391 if (arg_noroot) {
392 int rv = unshare(CLONE_NEWUSER);
393 if (rv == -1) {
394 fprintf(stderr, "Warning: cannot mount a new user namespace\n");
395 perror("unshare");
396 drop_privs(arg_nogroups);
397 }
398 }
399 else
400 drop_privs(arg_nogroups);
401
402 // notify parent that new user namespace has been created so a proper
403 // UID/GID map can be setup
404 notify_other(child_to_parent_fds[1]);
405 close(child_to_parent_fds[1]);
406
407 // wait for parent to finish setting up a proper UID/GID map
408 wait_for_other(parent_to_child_fds[0]);
409 close(parent_to_child_fds[0]);
410
411 // somehow, the new user namespace resets capabilities;
412 // we need to do them again
413 if (arg_noroot) {
414 set_caps();
415 if (arg_debug)
416 printf("User namespace (noroot) installed\n");
417 }
418
419
420 //****************************************
421 // start the program without using a shell
422 //****************************************
423 if (arg_shell_none) {
424 if (arg_debug) {
425 int i;
426 for (i = cfg.original_program_index; i < cfg.original_argc; i++) {
427 if (cfg.original_argv[i] == NULL)
428 break;
429 printf("execvp argument %d: %s\n", i - cfg.original_program_index, cfg.original_argv[i]);
430 }
431 }
432
433 if (!arg_command)
434 printf("Child process initialized\n");
435 execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index + 1]);
436 }
437 //****************************************
438 // start the program using a shell
439 //****************************************
440 else {
441 // choose the shell requested by the user, or use bash as default
442 char *sh;
443 if (cfg.shell)
444 sh = cfg.shell;
445 else if (arg_zsh)
446 sh = "/usr/bin/zsh";
447 else if (arg_csh)
448 sh = "/bin/csh";
449 else
450 sh = "/bin/bash";
451
452 char *arg[5];
453 int index = 0;
454 arg[index++] = sh;
455 arg[index++] = "-c";
456 assert(cfg.command_line);
457 if (arg_debug)
458 printf("Starting %s\n", cfg.command_line);
459 if (arg_doubledash)
460 arg[index++] = "--";
461 arg[index++] = cfg.command_line;
462 arg[index] = NULL;
463 assert(index < 5);
464
465 if (arg_debug) {
466 char *msg;
467 if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1)
468 errExit("asprintf");
469 logmsg(msg);
470 free(msg);
471 }
472
473 if (arg_debug) {
474 int i;
475 for (i = 0; i < 5; i++) {
476 if (arg[i] == NULL)
477 break;
478 printf("execvp argument %d: %s\n", i, arg[i]);
479 }
480 }
481
482 if (!arg_command)
483 printf("Child process initialized\n");
484 execvp(sh, arg);
485 }
486
487
488 perror("execvp");
489 return 0;
490}
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
new file mode 100644
index 000000000..c03eb6848
--- /dev/null
+++ b/src/firejail/seccomp.c
@@ -0,0 +1,658 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21/* default seccomp filter
22 // seccomp
23 struct sock_filter filter[] = {
24 VALIDATE_ARCHITECTURE,
25 EXAMINE_SYSCALL,
26 BLACKLIST(SYS_mount), // mount/unmount filesystems
27 BLACKLIST(SYS_umount2),
28 BLACKLIST(SYS_ptrace), // trace processes
29 BLACKLIST(SYS_kexec_load), // loading a different kernel
30 BLACKLIST(SYS_open_by_handle_at), // open by handle
31 BLACKLIST(SYS_init_module), // kernel module handling
32#ifdef SYS_finit_module // introduced in 2013
33 BLACKLIST(SYS_finit_module),
34#endif
35 BLACKLIST(SYS_delete_module),
36 BLACKLIST(SYS_iopl), // io permisions
37#ifdef SYS_ioperm
38 BLACKLIST(SYS_ioperm),
39#endif
40SYS_iopl
41 BLACKLIST(SYS_iopl), // io permisions
42#endif
43#ifdef SYS_ni_syscall), // new io permisions call on arm devices
44 BLACKLIST(SYS_ni_syscall),
45#endif
46 BLACKLIST(SYS_swapon), // swap on/off
47 BLACKLIST(SYS_swapoff),
48 BLACKLIST(SYS_syslog), // kernel printk control
49 RETURN_ALLOW
50 };
51*/
52#ifdef HAVE_SECCOMP
53#include "firejail.h"
54#include <errno.h>
55#include <linux/filter.h>
56#include <sys/syscall.h>
57#include <linux/capability.h>
58#include <linux/audit.h>
59#include <sys/stat.h>
60#include <fcntl.h>
61
62#include <sys/prctl.h>
63#ifndef PR_SET_NO_NEW_PRIVS
64# define PR_SET_NO_NEW_PRIVS 38
65#endif
66
67#if HAVE_SECCOMP_H
68#include <linux/seccomp.h>
69#else
70#define SECCOMP_MODE_FILTER 2
71#define SECCOMP_RET_KILL 0x00000000U
72#define SECCOMP_RET_TRAP 0x00030000U
73#define SECCOMP_RET_ALLOW 0x7fff0000U
74#define SECCOMP_RET_ERRNO 0x00050000U
75#define SECCOMP_RET_DATA 0x0000ffffU
76struct seccomp_data {
77 int nr;
78 __u32 arch;
79 __u64 instruction_pointer;
80 __u64 args[6];
81};
82#endif
83
84#if defined(__i386__)
85# define ARCH_NR AUDIT_ARCH_I386
86#elif defined(__x86_64__)
87# define ARCH_NR AUDIT_ARCH_X86_64
88#elif defined(__arm__)
89# define ARCH_NR AUDIT_ARCH_ARM
90#else
91# warning "Platform does not support seccomp filter yet"
92# define ARCH_NR 0
93#endif
94
95
96#define VALIDATE_ARCHITECTURE \
97 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \
98 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
99 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
100
101#define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
102 (offsetof(struct seccomp_data, nr)))
103
104#define BLACKLIST(syscall_nr) \
105 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \
106 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
107
108#define WHITELIST(syscall_nr) \
109 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \
110 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
111
112#define RETURN_ALLOW \
113 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
114
115#define KILL_PROCESS \
116 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
117
118#define SECSIZE 128 // initial filter size
119static struct sock_filter *sfilter = NULL;
120static int sfilter_alloc_size = 0;
121static int sfilter_index = 0;
122
123// debug filter
124void filter_debug(void) {
125 // start filter
126 struct sock_filter filter[] = {
127 VALIDATE_ARCHITECTURE,
128 EXAMINE_SYSCALL
129 };
130
131 // print sizes
132 printf("SECCOMP Filter:\n");
133 if (sfilter == NULL) {
134 printf("SECCOMP filter not allocated\n");
135 return;
136 }
137 if (sfilter_index < 4)
138 return;
139
140 // test the start of the filter
141 if (memcmp(sfilter, filter, sizeof(filter)) == 0) {
142 printf(" VALIDATE_ARCHITECTURE\n");
143 printf(" EXAMINE_SYSCAL\n");
144 }
145
146 // loop trough blacklists
147 int i = 4;
148 while (i < sfilter_index) {
149 // minimal parsing!
150 unsigned char *ptr = (unsigned char *) &sfilter[i];
151 int *nr = (int *) (ptr + 4);
152 if (*ptr == 0x15 && *(ptr +14) == 0xff && *(ptr + 15) == 0x7f ) {
153 printf(" WHITELIST %d %s\n", *nr, syscall_find_nr(*nr));
154 i += 2;
155 }
156 else if (*ptr == 0x15 && *(ptr +14) == 0 && *(ptr + 15) == 0) {
157 printf(" BLACKLIST %d %s\n", *nr, syscall_find_nr(*nr));
158 i += 2;
159 }
160 else if (*ptr == 0x06 && *(ptr +6) == 0 && *(ptr + 7) == 0 ) {
161 printf(" KILL_PROCESS\n");
162 i++;
163 }
164 else if (*ptr == 0x06 && *(ptr +6) == 0xff && *(ptr + 7) == 0x7f ) {
165 printf(" RETURN_ALLOW\n");
166 i++;
167 }
168 else {
169 printf(" UNKNOWN ENTRY!!!\n");
170 i++;
171 }
172 }
173}
174
175// initialize filter
176static void filter_init(void) {
177 if (sfilter) {
178 assert(0);
179 return;
180 }
181
182 if (arg_debug)
183 printf("Initialize seccomp filter\n");
184 // allocate a filter of SECSIZE
185 sfilter = malloc(sizeof(struct sock_filter) * SECSIZE);
186 if (!sfilter)
187 errExit("malloc");
188 memset(sfilter, 0, sizeof(struct sock_filter) * SECSIZE);
189 sfilter_alloc_size = SECSIZE;
190
191 // copy the start entries
192 struct sock_filter filter[] = {
193 VALIDATE_ARCHITECTURE,
194 EXAMINE_SYSCALL
195 };
196 sfilter_index = sizeof(filter) / sizeof(struct sock_filter);
197 memcpy(sfilter, filter, sizeof(filter));
198}
199
200static void filter_realloc(void) {
201 assert(sfilter);
202 assert(sfilter_alloc_size);
203 assert(sfilter_index);
204 if (arg_debug)
205 printf("Allocating more seccomp filter entries\n");
206
207 // allocate the new memory
208 struct sock_filter *old = sfilter;
209 sfilter = malloc(sizeof(struct sock_filter) * (sfilter_alloc_size + SECSIZE));
210 if (!sfilter)
211 errExit("malloc");
212 memset(sfilter, 0, sizeof(struct sock_filter) * (sfilter_alloc_size + SECSIZE));
213
214 // copy old filter
215 memcpy(sfilter, old, sizeof(struct sock_filter) * sfilter_alloc_size);
216 sfilter_alloc_size += SECSIZE;
217}
218
219static void filter_add_whitelist(int syscall) {
220 assert(sfilter);
221 assert(sfilter_alloc_size);
222 assert(sfilter_index);
223 if (arg_debug)
224 printf("Whitelisting syscall %d %s\n", syscall, syscall_find_nr(syscall));
225
226 if ((sfilter_index + 2) > sfilter_alloc_size)
227 filter_realloc();
228
229 struct sock_filter filter[] = {
230 WHITELIST(syscall)
231 };
232#if 0
233{
234 int i;
235 unsigned char *ptr = (unsigned char *) &filter[0];
236 for (i = 0; i < sizeof(filter); i++, ptr++)
237 printf("%x, ", (*ptr) & 0xff);
238 printf("\n");
239}
240#endif
241 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
242 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
243}
244
245static void filter_add_blacklist(int syscall) {
246 assert(sfilter);
247 assert(sfilter_alloc_size);
248 assert(sfilter_index);
249 if (arg_debug)
250 printf("Blacklisting syscall %d %s\n", syscall, syscall_find_nr(syscall));
251
252 if ((sfilter_index + 2) > sfilter_alloc_size)
253 filter_realloc();
254
255 struct sock_filter filter[] = {
256 BLACKLIST(syscall)
257 };
258#if 0
259{
260 int i;
261 unsigned char *ptr = (unsigned char *) &filter[0];
262 for (i = 0; i < sizeof(filter); i++, ptr++)
263 printf("%x, ", (*ptr) & 0xff);
264 printf("\n");
265}
266#endif
267 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
268 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
269}
270
271static void filter_end_blacklist(void) {
272 assert(sfilter);
273 assert(sfilter_alloc_size);
274 assert(sfilter_index);
275 if (arg_debug)
276 printf("Ending syscall filter\n");
277
278 if ((sfilter_index + 2) > sfilter_alloc_size)
279 filter_realloc();
280
281 struct sock_filter filter[] = {
282 RETURN_ALLOW
283 };
284#if 0
285{
286 int i;
287 unsigned char *ptr = (unsigned char *) &filter[0];
288 for (i = 0; i < sizeof(filter); i++, ptr++)
289 printf("%x, ", (*ptr) & 0xff);
290 printf("\n");
291}
292#endif
293 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
294 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
295}
296
297static void filter_end_whitelist(void) {
298 assert(sfilter);
299 assert(sfilter_alloc_size);
300 assert(sfilter_index);
301 if (arg_debug)
302 printf("Ending syscall filter\n");
303
304 if ((sfilter_index + 2) > sfilter_alloc_size)
305 filter_realloc();
306
307 struct sock_filter filter[] = {
308 KILL_PROCESS
309 };
310#if 0
311{
312 int i;
313 unsigned char *ptr = (unsigned char *) &filter[0];
314 for (i = 0; i < sizeof(filter); i++, ptr++)
315 printf("%x, ", (*ptr) & 0xff);
316 printf("\n");
317}
318#endif
319 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
320 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
321}
322
323
324// save seccomp filter in /tmp/firejail/mnt/seccomp
325static void write_seccomp_file(void) {
326 fs_build_mnt_dir();
327 assert(sfilter);
328
329 char *fname;
330 if (asprintf(&fname, "%s/seccomp", MNT_DIR) == -1)
331 errExit("asprintf");
332 int fd = open(fname, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
333 if (fd == -1)
334 errExit("open");
335
336 if (arg_debug)
337 printf("Save seccomp filter, size %lu bytes\n", sfilter_index * sizeof(struct sock_filter));
338 errno = 0;
339 ssize_t sz = write(fd, sfilter, sfilter_index * sizeof(struct sock_filter));
340 if (sz != (sfilter_index * sizeof(struct sock_filter))) {
341 fprintf(stderr, "Error: cannot save seccomp filter\n");
342 exit(1);
343 }
344 close(fd);
345 if (chown(fname, 0, 0) < 0)
346 errExit("chown");
347 free(fname);
348}
349
350// read seccomp filter from /tmp/firejail/mnt/seccomp
351static void read_seccomp_file(char *file_name) {
352 assert(sfilter == NULL && sfilter_index == 0);
353
354 char *fname;
355 if (file_name)
356 fname = file_name;
357 else {
358 if (asprintf(&fname, "%s/seccomp", MNT_DIR) == -1)
359 errExit("asprintf");
360 }
361
362 // check file
363 struct stat s;
364 if (stat(fname, &s) == -1) {
365 fprintf(stderr, "Error: seccomp file not found\n");
366 exit(1);
367 }
368 ssize_t sz = s.st_size;
369 if (sz == 0 || (sz % sizeof(struct sock_filter)) != 0) {
370 fprintf(stderr, "Error: invalid seccomp file\n");
371 exit(1);
372 }
373 sfilter = malloc(sz);
374 if (!sfilter)
375 errExit("malloc");
376
377 // read file
378 /* coverity[toctou] */
379 int fd = open(fname,O_RDONLY);
380 if (fd == -1)
381 errExit("open");
382 errno = 0;
383 ssize_t size = read(fd, sfilter, sz);
384 if (size != sz) {
385 fprintf(stderr, "Error: invalid seccomp file\n");
386 exit(1);
387 }
388 sfilter_index = sz / sizeof(struct sock_filter);
389
390 if (arg_debug)
391 printf("Read seccomp filter, size %lu bytes\n", sfilter_index * sizeof(struct sock_filter));
392
393 close(fd);
394 free(fname);
395
396 if (arg_debug)
397 filter_debug();
398}
399
400
401// drop filter for seccomp option
402int seccomp_filter_drop(void) {
403 filter_init();
404
405 // default seccomp
406 if (arg_seccomp_list_drop == NULL) {
407#ifdef SYS_mount
408 filter_add_blacklist(SYS_mount);
409#endif
410#ifdef SYS_umount2
411 filter_add_blacklist(SYS_umount2);
412#endif
413#ifdef SYS_ptrace
414 filter_add_blacklist(SYS_ptrace);
415#endif
416#ifdef SYS_kexec_load
417 filter_add_blacklist(SYS_kexec_load);
418#endif
419#ifdef SYS_open_by_handle_at
420 filter_add_blacklist(SYS_open_by_handle_at);
421#endif
422#ifdef SYS_init_module
423 filter_add_blacklist(SYS_init_module);
424#endif
425#ifdef SYS_finit_module // introduced in 2013
426 filter_add_blacklist(SYS_finit_module);
427#endif
428#ifdef SYS_delete_module
429 filter_add_blacklist(SYS_delete_module);
430#endif
431#ifdef SYS_iopl
432 filter_add_blacklist(SYS_iopl);
433#endif
434#ifdef SYS_ioperm
435 filter_add_blacklist(SYS_ioperm);
436#endif
437#ifdef SYS_ni_syscall // new io permisions call on arm devices
438 filter_add_blacklist(SYS_ni_syscall);
439#endif
440#ifdef SYS_swapon
441 filter_add_blacklist(SYS_swapon);
442#endif
443#ifdef SYS_swapoff
444 filter_add_blacklist(SYS_swapoff);
445#endif
446#ifdef SYS_syslog
447 filter_add_blacklist(SYS_syslog);
448#endif
449#ifdef SYS_process_vm_readv
450 filter_add_blacklist(SYS_process_vm_readv);
451#endif
452#ifdef SYS_process_vm_writev
453 filter_add_blacklist(SYS_process_vm_writev);
454#endif
455#ifdef SYS_mknod
456 filter_add_blacklist(SYS_mknod);
457#endif
458
459 // new syscalls in 0.9,23
460#ifdef SYS_sysfs
461 filter_add_blacklist(SYS_sysfs);
462#endif
463#ifdef SYS__sysctl
464 filter_add_blacklist(SYS__sysctl);
465#endif
466#ifdef SYS_adjtimex
467 filter_add_blacklist(SYS_adjtimex);
468#endif
469#ifdef SYS_clock_adjtime
470 filter_add_blacklist(SYS_clock_adjtime);
471#endif
472#ifdef SYS_lookup_dcookie
473 filter_add_blacklist(SYS_lookup_dcookie);
474#endif
475#ifdef SYS_perf_event_open
476 filter_add_blacklist(SYS_perf_event_open);
477#endif
478#ifdef SYS_fanotify_init
479 filter_add_blacklist(SYS_fanotify_init);
480#endif
481#ifdef SYS_kcmp
482 filter_add_blacklist(SYS_kcmp);
483#endif
484 }
485
486 // default seccomp filter with additional drop list
487 if (arg_seccomp_list && arg_seccomp_list_drop == NULL) {
488 if (syscall_check_list(arg_seccomp_list, filter_add_blacklist)) {
489 fprintf(stderr, "Error: cannot load seccomp filter\n");
490 exit(1);
491 }
492 }
493 // drop list
494 else if (arg_seccomp_list == NULL && arg_seccomp_list_drop) {
495 if (syscall_check_list(arg_seccomp_list_drop, filter_add_blacklist)) {
496 fprintf(stderr, "Error: cannot load seccomp filter\n");
497 exit(1);
498 }
499 }
500
501
502 filter_end_blacklist();
503 if (arg_debug)
504 filter_debug();
505
506 // save seccomp filter in /tmp/firejail/mnt/seccomp
507 // in order to use it in --join operations
508 write_seccomp_file();
509
510
511 struct sock_fprog prog = {
512 .len = sfilter_index,
513 .filter = sfilter,
514 };
515
516 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
517 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
518 return 1;
519 }
520 else if (arg_debug) {
521 printf("seccomp enabled\n");
522 }
523
524 return 0;
525}
526
527// keep filter for seccomp option
528int seccomp_filter_keep(void) {
529 filter_init();
530
531 // these 4 syscalls are used by firejail after the seccomp filter is initialized
532 filter_add_whitelist(SYS_setuid);
533 filter_add_whitelist(SYS_setgid);
534 filter_add_whitelist(SYS_setgroups);
535 filter_add_whitelist(SYS_dup);
536
537 // apply keep list
538 if (arg_seccomp_list_keep) {
539 if (syscall_check_list(arg_seccomp_list_keep, filter_add_whitelist)) {
540 fprintf(stderr, "Error: cannot load seccomp filter\n");
541 exit(1);
542 }
543 }
544
545 filter_end_whitelist();
546 if (arg_debug)
547 filter_debug();
548
549 // save seccomp filter in /tmp/firejail/mnt/seccomp
550 // in order to use it in --join operations
551 write_seccomp_file();
552
553
554 struct sock_fprog prog = {
555 .len = sfilter_index,
556 .filter = sfilter,
557 };
558
559 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
560 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
561 return 1;
562 }
563 else if (arg_debug) {
564 printf("seccomp enabled\n");
565 }
566
567 return 0;
568}
569
570
571
572void seccomp_set(void) {
573 // read seccomp filter from /tmp/firejail/mnt/seccomp
574 read_seccomp_file(NULL);
575
576 // apply filter
577 struct sock_fprog prog = {
578 .len = sfilter_index,
579 .filter = sfilter,
580 };
581
582 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
583 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
584 return;
585 }
586 else if (arg_debug) {
587 printf("seccomp enabled\n");
588 }
589}
590
591void seccomp_print_filter_name(const char *name) {
592 if (!name || strlen(name) == 0) {
593 fprintf(stderr, "Error: invalid sandbox name\n");
594 exit(1);
595 }
596 pid_t pid;
597 if (name2pid(name, &pid)) {
598 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
599 exit(1);
600 }
601
602 seccomp_print_filter(pid);
603}
604
605void seccomp_print_filter(pid_t pid) {
606 // if the pid is that of a firejail process, use the pid of the first child process
607 char *comm = pid_proc_comm(pid);
608 if (comm) {
609 // remove \n
610 char *ptr = strchr(comm, '\n');
611 if (ptr)
612 *ptr = '\0';
613 if (strcmp(comm, "firejail") == 0) {
614 pid_t child;
615 if (find_child(pid, &child) == 0) {
616 pid = child;
617 }
618 }
619 free(comm);
620 }
621
622 // check privileges for non-root users
623 uid_t uid = getuid();
624 if (uid != 0) {
625 struct stat s;
626 char *dir;
627 if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
628 errExit("asprintf");
629 if (stat(dir, &s) < 0)
630 errExit("stat");
631 if (s.st_uid != uid) {
632 printf("Error: permission denied.\n");
633 exit(1);
634 }
635 }
636
637
638 // find the seccomp filter
639 char *fname;
640 if (asprintf(&fname, "/proc/%d/root/tmp/firejail/mnt/seccomp", pid) == -1)
641 errExit("asprintf");
642
643 struct stat s;
644 if (stat(fname, &s) == -1) {
645 printf("Cannot access seccomp filter.\n");
646 exit(1);
647 }
648
649 // read and print the filter
650 read_seccomp_file(fname);
651 drop_privs(1);
652 filter_debug();
653
654 exit(0);
655}
656
657#endif // HAVE_SECCOMP
658
diff --git a/src/firejail/shutdown.c b/src/firejail/shutdown.c
new file mode 100644
index 000000000..b666996df
--- /dev/null
+++ b/src/firejail/shutdown.c
@@ -0,0 +1,98 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21#include <sys/stat.h>
22#include <sys/wait.h>
23#include <fcntl.h>
24#include <sys/prctl.h>
25
26void shut_name(const char *name) {
27 if (!name || strlen(name) == 0) {
28 fprintf(stderr, "Error: invalid sandbox name\n");
29 exit(1);
30 }
31
32 pid_t pid;
33 if (name2pid(name, &pid)) {
34 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
35 exit(1);
36 }
37
38 shut(pid);
39}
40
41void shut(pid_t pid) {
42 pid_t parent = pid;
43 // if the pid is that of a firejail process, use the pid of a child process inside the sandbox
44 char *comm = pid_proc_comm(pid);
45 if (comm) {
46 // remove \n
47 char *ptr = strchr(comm, '\n');
48 if (ptr)
49 *ptr = '\0';
50 if (strcmp(comm, "firejail") == 0) {
51 pid_t child;
52 if (find_child(pid, &child) == 0) {
53 pid = child;
54 printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
55 }
56 }
57 free(comm);
58 }
59
60 // check privileges for non-root users
61 uid_t uid = getuid();
62 if (uid != 0) {
63 struct stat s;
64 char *dir;
65 if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
66 errExit("asprintf");
67 if (stat(dir, &s) < 0)
68 errExit("stat");
69 if (s.st_uid != uid) {
70 fprintf(stderr, "Error: permission is denied to shutdown a sandbox created by a different user.\n");
71 exit(1);
72 }
73 }
74
75 printf("Sending SIGTERM to %u\n", pid);
76 kill(pid, SIGTERM);
77 sleep(2);
78
79 // if the process is still running, terminate it using SIGKILL
80 // try to open stat file
81 char *file;
82 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
83 perror("asprintf");
84 exit(1);
85 }
86 FILE *fp = fopen(file, "r");
87 if (!fp)
88 return;
89 fclose(fp);
90
91 // kill the process and also the parent
92 printf("Sending SIGKILL to %u\n", pid);
93 kill(pid, SIGKILL);
94 if (parent != pid) {
95 printf("Sending SIGKILL to %u\n", parent);
96 kill(parent, SIGKILL);
97 }
98}
diff --git a/src/firejail/syscall.c b/src/firejail/syscall.c
new file mode 100644
index 000000000..50bff7f5a
--- /dev/null
+++ b/src/firejail/syscall.c
@@ -0,0 +1,4942 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#ifdef HAVE_SECCOMP
22#include "firejail.h"
23#include <sys/syscall.h>
24
25typedef struct {
26 char *name;
27 int nr;
28} SyscallEntry;
29
30static SyscallEntry syslist[] = {
31//
32// code generated using tools/extract-syscall
33//
34#ifndef _SYSCALL_H
35#endif
36#if !defined __x86_64__
37#ifdef SYS__llseek
38#ifdef __NR__llseek
39 {"_llseek", __NR__llseek},
40#endif
41#endif
42#ifdef SYS__newselect
43#ifdef __NR__newselect
44 {"_newselect", __NR__newselect},
45#endif
46#endif
47#ifdef SYS__sysctl
48#ifdef __NR__sysctl
49 {"_sysctl", __NR__sysctl},
50#endif
51#endif
52#ifdef SYS_access
53#ifdef __NR_access
54 {"access", __NR_access},
55#endif
56#endif
57#ifdef SYS_acct
58#ifdef __NR_acct
59 {"acct", __NR_acct},
60#endif
61#endif
62#ifdef SYS_add_key
63#ifdef __NR_add_key
64 {"add_key", __NR_add_key},
65#endif
66#endif
67#ifdef SYS_adjtimex
68#ifdef __NR_adjtimex
69 {"adjtimex", __NR_adjtimex},
70#endif
71#endif
72#ifdef SYS_afs_syscall
73#ifdef __NR_afs_syscall
74 {"afs_syscall", __NR_afs_syscall},
75#endif
76#endif
77#ifdef SYS_alarm
78#ifdef __NR_alarm
79 {"alarm", __NR_alarm},
80#endif
81#endif
82#ifdef SYS_bdflush
83#ifdef __NR_bdflush
84 {"bdflush", __NR_bdflush},
85#endif
86#endif
87#ifdef SYS_break
88#ifdef __NR_break
89 {"break", __NR_break},
90#endif
91#endif
92#ifdef SYS_brk
93#ifdef __NR_brk
94 {"brk", __NR_brk},
95#endif
96#endif
97#ifdef SYS_capget
98#ifdef __NR_capget
99 {"capget", __NR_capget},
100#endif
101#endif
102#ifdef SYS_capset
103#ifdef __NR_capset
104 {"capset", __NR_capset},
105#endif
106#endif
107#ifdef SYS_chdir
108#ifdef __NR_chdir
109 {"chdir", __NR_chdir},
110#endif
111#endif
112#ifdef SYS_chmod
113#ifdef __NR_chmod
114 {"chmod", __NR_chmod},
115#endif
116#endif
117#ifdef SYS_chown
118#ifdef __NR_chown
119 {"chown", __NR_chown},
120#endif
121#endif
122#ifdef SYS_chown32
123#ifdef __NR_chown32
124 {"chown32", __NR_chown32},
125#endif
126#endif
127#ifdef SYS_chroot
128#ifdef __NR_chroot
129 {"chroot", __NR_chroot},
130#endif
131#endif
132#ifdef SYS_clock_adjtime
133#ifdef __NR_clock_adjtime
134 {"clock_adjtime", __NR_clock_adjtime},
135#endif
136#endif
137#ifdef SYS_clock_getres
138#ifdef __NR_clock_getres
139 {"clock_getres", __NR_clock_getres},
140#endif
141#endif
142#ifdef SYS_clock_gettime
143#ifdef __NR_clock_gettime
144 {"clock_gettime", __NR_clock_gettime},
145#endif
146#endif
147#ifdef SYS_clock_nanosleep
148#ifdef __NR_clock_nanosleep
149 {"clock_nanosleep", __NR_clock_nanosleep},
150#endif
151#endif
152#ifdef SYS_clock_settime
153#ifdef __NR_clock_settime
154 {"clock_settime", __NR_clock_settime},
155#endif
156#endif
157#ifdef SYS_clone
158#ifdef __NR_clone
159 {"clone", __NR_clone},
160#endif
161#endif
162#ifdef SYS_close
163#ifdef __NR_close
164 {"close", __NR_close},
165#endif
166#endif
167#ifdef SYS_creat
168#ifdef __NR_creat
169 {"creat", __NR_creat},
170#endif
171#endif
172#ifdef SYS_create_module
173#ifdef __NR_create_module
174 {"create_module", __NR_create_module},
175#endif
176#endif
177#ifdef SYS_delete_module
178#ifdef __NR_delete_module
179 {"delete_module", __NR_delete_module},
180#endif
181#endif
182#ifdef SYS_dup
183#ifdef __NR_dup
184 {"dup", __NR_dup},
185#endif
186#endif
187#ifdef SYS_dup2
188#ifdef __NR_dup2
189 {"dup2", __NR_dup2},
190#endif
191#endif
192#ifdef SYS_dup3
193#ifdef __NR_dup3
194 {"dup3", __NR_dup3},
195#endif
196#endif
197#ifdef SYS_epoll_create
198#ifdef __NR_epoll_create
199 {"epoll_create", __NR_epoll_create},
200#endif
201#endif
202#ifdef SYS_epoll_create1
203#ifdef __NR_epoll_create1
204 {"epoll_create1", __NR_epoll_create1},
205#endif
206#endif
207#ifdef SYS_epoll_ctl
208#ifdef __NR_epoll_ctl
209 {"epoll_ctl", __NR_epoll_ctl},
210#endif
211#endif
212#ifdef SYS_epoll_pwait
213#ifdef __NR_epoll_pwait
214 {"epoll_pwait", __NR_epoll_pwait},
215#endif
216#endif
217#ifdef SYS_epoll_wait
218#ifdef __NR_epoll_wait
219 {"epoll_wait", __NR_epoll_wait},
220#endif
221#endif
222#ifdef SYS_eventfd
223#ifdef __NR_eventfd
224 {"eventfd", __NR_eventfd},
225#endif
226#endif
227#ifdef SYS_eventfd2
228#ifdef __NR_eventfd2
229 {"eventfd2", __NR_eventfd2},
230#endif
231#endif
232#ifdef SYS_execve
233#ifdef __NR_execve
234 {"execve", __NR_execve},
235#endif
236#endif
237#ifdef SYS_exit
238#ifdef __NR_exit
239 {"exit", __NR_exit},
240#endif
241#endif
242#ifdef SYS_exit_group
243#ifdef __NR_exit_group
244 {"exit_group", __NR_exit_group},
245#endif
246#endif
247#ifdef SYS_faccessat
248#ifdef __NR_faccessat
249 {"faccessat", __NR_faccessat},
250#endif
251#endif
252#ifdef SYS_fadvise64
253#ifdef __NR_fadvise64
254 {"fadvise64", __NR_fadvise64},
255#endif
256#endif
257#ifdef SYS_fadvise64_64
258#ifdef __NR_fadvise64_64
259 {"fadvise64_64", __NR_fadvise64_64},
260#endif
261#endif
262#ifdef SYS_fallocate
263#ifdef __NR_fallocate
264 {"fallocate", __NR_fallocate},
265#endif
266#endif
267#ifdef SYS_fanotify_init
268#ifdef __NR_fanotify_init
269 {"fanotify_init", __NR_fanotify_init},
270#endif
271#endif
272#ifdef SYS_fanotify_mark
273#ifdef __NR_fanotify_mark
274 {"fanotify_mark", __NR_fanotify_mark},
275#endif
276#endif
277#ifdef SYS_fchdir
278#ifdef __NR_fchdir
279 {"fchdir", __NR_fchdir},
280#endif
281#endif
282#ifdef SYS_fchmod
283#ifdef __NR_fchmod
284 {"fchmod", __NR_fchmod},
285#endif
286#endif
287#ifdef SYS_fchmodat
288#ifdef __NR_fchmodat
289 {"fchmodat", __NR_fchmodat},
290#endif
291#endif
292#ifdef SYS_fchown
293#ifdef __NR_fchown
294 {"fchown", __NR_fchown},
295#endif
296#endif
297#ifdef SYS_fchown32
298#ifdef __NR_fchown32
299 {"fchown32", __NR_fchown32},
300#endif
301#endif
302#ifdef SYS_fchownat
303#ifdef __NR_fchownat
304 {"fchownat", __NR_fchownat},
305#endif
306#endif
307#ifdef SYS_fcntl
308#ifdef __NR_fcntl
309 {"fcntl", __NR_fcntl},
310#endif
311#endif
312#ifdef SYS_fcntl64
313#ifdef __NR_fcntl64
314 {"fcntl64", __NR_fcntl64},
315#endif
316#endif
317#ifdef SYS_fdatasync
318#ifdef __NR_fdatasync
319 {"fdatasync", __NR_fdatasync},
320#endif
321#endif
322#ifdef SYS_fgetxattr
323#ifdef __NR_fgetxattr
324 {"fgetxattr", __NR_fgetxattr},
325#endif
326#endif
327#ifdef SYS_finit_module
328#ifdef __NR_finit_module
329 {"finit_module", __NR_finit_module},
330#endif
331#endif
332#ifdef SYS_flistxattr
333#ifdef __NR_flistxattr
334 {"flistxattr", __NR_flistxattr},
335#endif
336#endif
337#ifdef SYS_flock
338#ifdef __NR_flock
339 {"flock", __NR_flock},
340#endif
341#endif
342#ifdef SYS_fork
343#ifdef __NR_fork
344 {"fork", __NR_fork},
345#endif
346#endif
347#ifdef SYS_fremovexattr
348#ifdef __NR_fremovexattr
349 {"fremovexattr", __NR_fremovexattr},
350#endif
351#endif
352#ifdef SYS_fsetxattr
353#ifdef __NR_fsetxattr
354 {"fsetxattr", __NR_fsetxattr},
355#endif
356#endif
357#ifdef SYS_fstat
358#ifdef __NR_fstat
359 {"fstat", __NR_fstat},
360#endif
361#endif
362#ifdef SYS_fstat64
363#ifdef __NR_fstat64
364 {"fstat64", __NR_fstat64},
365#endif
366#endif
367#ifdef SYS_fstatat64
368#ifdef __NR_fstatat64
369 {"fstatat64", __NR_fstatat64},
370#endif
371#endif
372#ifdef SYS_fstatfs
373#ifdef __NR_fstatfs
374 {"fstatfs", __NR_fstatfs},
375#endif
376#endif
377#ifdef SYS_fstatfs64
378#ifdef __NR_fstatfs64
379 {"fstatfs64", __NR_fstatfs64},
380#endif
381#endif
382#ifdef SYS_fsync
383#ifdef __NR_fsync
384 {"fsync", __NR_fsync},
385#endif
386#endif
387#ifdef SYS_ftime
388#ifdef __NR_ftime
389 {"ftime", __NR_ftime},
390#endif
391#endif
392#ifdef SYS_ftruncate
393#ifdef __NR_ftruncate
394 {"ftruncate", __NR_ftruncate},
395#endif
396#endif
397#ifdef SYS_ftruncate64
398#ifdef __NR_ftruncate64
399 {"ftruncate64", __NR_ftruncate64},
400#endif
401#endif
402#ifdef SYS_futex
403#ifdef __NR_futex
404 {"futex", __NR_futex},
405#endif
406#endif
407#ifdef SYS_futimesat
408#ifdef __NR_futimesat
409 {"futimesat", __NR_futimesat},
410#endif
411#endif
412#ifdef SYS_get_kernel_syms
413#ifdef __NR_get_kernel_syms
414 {"get_kernel_syms", __NR_get_kernel_syms},
415#endif
416#endif
417#ifdef SYS_get_mempolicy
418#ifdef __NR_get_mempolicy
419 {"get_mempolicy", __NR_get_mempolicy},
420#endif
421#endif
422#ifdef SYS_get_robust_list
423#ifdef __NR_get_robust_list
424 {"get_robust_list", __NR_get_robust_list},
425#endif
426#endif
427#ifdef SYS_get_thread_area
428#ifdef __NR_get_thread_area
429 {"get_thread_area", __NR_get_thread_area},
430#endif
431#endif
432#ifdef SYS_getcpu
433#ifdef __NR_getcpu
434 {"getcpu", __NR_getcpu},
435#endif
436#endif
437#ifdef SYS_getcwd
438#ifdef __NR_getcwd
439 {"getcwd", __NR_getcwd},
440#endif
441#endif
442#ifdef SYS_getdents
443#ifdef __NR_getdents
444 {"getdents", __NR_getdents},
445#endif
446#endif
447#ifdef SYS_getdents64
448#ifdef __NR_getdents64
449 {"getdents64", __NR_getdents64},
450#endif
451#endif
452#ifdef SYS_getegid
453#ifdef __NR_getegid
454 {"getegid", __NR_getegid},
455#endif
456#endif
457#ifdef SYS_getegid32
458#ifdef __NR_getegid32
459 {"getegid32", __NR_getegid32},
460#endif
461#endif
462#ifdef SYS_geteuid
463#ifdef __NR_geteuid
464 {"geteuid", __NR_geteuid},
465#endif
466#endif
467#ifdef SYS_geteuid32
468#ifdef __NR_geteuid32
469 {"geteuid32", __NR_geteuid32},
470#endif
471#endif
472#ifdef SYS_getgid
473#ifdef __NR_getgid
474 {"getgid", __NR_getgid},
475#endif
476#endif
477#ifdef SYS_getgid32
478#ifdef __NR_getgid32
479 {"getgid32", __NR_getgid32},
480#endif
481#endif
482#ifdef SYS_getgroups
483#ifdef __NR_getgroups
484 {"getgroups", __NR_getgroups},
485#endif
486#endif
487#ifdef SYS_getgroups32
488#ifdef __NR_getgroups32
489 {"getgroups32", __NR_getgroups32},
490#endif
491#endif
492#ifdef SYS_getitimer
493#ifdef __NR_getitimer
494 {"getitimer", __NR_getitimer},
495#endif
496#endif
497#ifdef SYS_getpgid
498#ifdef __NR_getpgid
499 {"getpgid", __NR_getpgid},
500#endif
501#endif
502#ifdef SYS_getpgrp
503#ifdef __NR_getpgrp
504 {"getpgrp", __NR_getpgrp},
505#endif
506#endif
507#ifdef SYS_getpid
508#ifdef __NR_getpid
509 {"getpid", __NR_getpid},
510#endif
511#endif
512#ifdef SYS_getpmsg
513#ifdef __NR_getpmsg
514 {"getpmsg", __NR_getpmsg},
515#endif
516#endif
517#ifdef SYS_getppid
518#ifdef __NR_getppid
519 {"getppid", __NR_getppid},
520#endif
521#endif
522#ifdef SYS_getpriority
523#ifdef __NR_getpriority
524 {"getpriority", __NR_getpriority},
525#endif
526#endif
527#ifdef SYS_getresgid
528#ifdef __NR_getresgid
529 {"getresgid", __NR_getresgid},
530#endif
531#endif
532#ifdef SYS_getresgid32
533#ifdef __NR_getresgid32
534 {"getresgid32", __NR_getresgid32},
535#endif
536#endif
537#ifdef SYS_getresuid
538#ifdef __NR_getresuid
539 {"getresuid", __NR_getresuid},
540#endif
541#endif
542#ifdef SYS_getresuid32
543#ifdef __NR_getresuid32
544 {"getresuid32", __NR_getresuid32},
545#endif
546#endif
547#ifdef SYS_getrlimit
548#ifdef __NR_getrlimit
549 {"getrlimit", __NR_getrlimit},
550#endif
551#endif
552#ifdef SYS_getrusage
553#ifdef __NR_getrusage
554 {"getrusage", __NR_getrusage},
555#endif
556#endif
557#ifdef SYS_getsid
558#ifdef __NR_getsid
559 {"getsid", __NR_getsid},
560#endif
561#endif
562#ifdef SYS_gettid
563#ifdef __NR_gettid
564 {"gettid", __NR_gettid},
565#endif
566#endif
567#ifdef SYS_gettimeofday
568#ifdef __NR_gettimeofday
569 {"gettimeofday", __NR_gettimeofday},
570#endif
571#endif
572#ifdef SYS_getuid
573#ifdef __NR_getuid
574 {"getuid", __NR_getuid},
575#endif
576#endif
577#ifdef SYS_getuid32
578#ifdef __NR_getuid32
579 {"getuid32", __NR_getuid32},
580#endif
581#endif
582#ifdef SYS_getxattr
583#ifdef __NR_getxattr
584 {"getxattr", __NR_getxattr},
585#endif
586#endif
587#ifdef SYS_gtty
588#ifdef __NR_gtty
589 {"gtty", __NR_gtty},
590#endif
591#endif
592#ifdef SYS_idle
593#ifdef __NR_idle
594 {"idle", __NR_idle},
595#endif
596#endif
597#ifdef SYS_init_module
598#ifdef __NR_init_module
599 {"init_module", __NR_init_module},
600#endif
601#endif
602#ifdef SYS_inotify_add_watch
603#ifdef __NR_inotify_add_watch
604 {"inotify_add_watch", __NR_inotify_add_watch},
605#endif
606#endif
607#ifdef SYS_inotify_init
608#ifdef __NR_inotify_init
609 {"inotify_init", __NR_inotify_init},
610#endif
611#endif
612#ifdef SYS_inotify_init1
613#ifdef __NR_inotify_init1
614 {"inotify_init1", __NR_inotify_init1},
615#endif
616#endif
617#ifdef SYS_inotify_rm_watch
618#ifdef __NR_inotify_rm_watch
619 {"inotify_rm_watch", __NR_inotify_rm_watch},
620#endif
621#endif
622#ifdef SYS_io_cancel
623#ifdef __NR_io_cancel
624 {"io_cancel", __NR_io_cancel},
625#endif
626#endif
627#ifdef SYS_io_destroy
628#ifdef __NR_io_destroy
629 {"io_destroy", __NR_io_destroy},
630#endif
631#endif
632#ifdef SYS_io_getevents
633#ifdef __NR_io_getevents
634 {"io_getevents", __NR_io_getevents},
635#endif
636#endif
637#ifdef SYS_io_setup
638#ifdef __NR_io_setup
639 {"io_setup", __NR_io_setup},
640#endif
641#endif
642#ifdef SYS_io_submit
643#ifdef __NR_io_submit
644 {"io_submit", __NR_io_submit},
645#endif
646#endif
647#ifdef SYS_ioctl
648#ifdef __NR_ioctl
649 {"ioctl", __NR_ioctl},
650#endif
651#endif
652#ifdef SYS_ioperm
653#ifdef __NR_ioperm
654 {"ioperm", __NR_ioperm},
655#endif
656#endif
657#ifdef SYS_iopl
658#ifdef __NR_iopl
659 {"iopl", __NR_iopl},
660#endif
661#endif
662#ifdef SYS_ioprio_get
663#ifdef __NR_ioprio_get
664 {"ioprio_get", __NR_ioprio_get},
665#endif
666#endif
667#ifdef SYS_ioprio_set
668#ifdef __NR_ioprio_set
669 {"ioprio_set", __NR_ioprio_set},
670#endif
671#endif
672#ifdef SYS_ipc
673#ifdef __NR_ipc
674 {"ipc", __NR_ipc},
675#endif
676#endif
677#ifdef SYS_kcmp
678#ifdef __NR_kcmp
679 {"kcmp", __NR_kcmp},
680#endif
681#endif
682#ifdef SYS_kexec_load
683#ifdef __NR_kexec_load
684 {"kexec_load", __NR_kexec_load},
685#endif
686#endif
687#ifdef SYS_keyctl
688#ifdef __NR_keyctl
689 {"keyctl", __NR_keyctl},
690#endif
691#endif
692#ifdef SYS_kill
693#ifdef __NR_kill
694 {"kill", __NR_kill},
695#endif
696#endif
697#ifdef SYS_lchown
698#ifdef __NR_lchown
699 {"lchown", __NR_lchown},
700#endif
701#endif
702#ifdef SYS_lchown32
703#ifdef __NR_lchown32
704 {"lchown32", __NR_lchown32},
705#endif
706#endif
707#ifdef SYS_lgetxattr
708#ifdef __NR_lgetxattr
709 {"lgetxattr", __NR_lgetxattr},
710#endif
711#endif
712#ifdef SYS_link
713#ifdef __NR_link
714 {"link", __NR_link},
715#endif
716#endif
717#ifdef SYS_linkat
718#ifdef __NR_linkat
719 {"linkat", __NR_linkat},
720#endif
721#endif
722#ifdef SYS_listxattr
723#ifdef __NR_listxattr
724 {"listxattr", __NR_listxattr},
725#endif
726#endif
727#ifdef SYS_llistxattr
728#ifdef __NR_llistxattr
729 {"llistxattr", __NR_llistxattr},
730#endif
731#endif
732#ifdef SYS_lock
733#ifdef __NR_lock
734 {"lock", __NR_lock},
735#endif
736#endif
737#ifdef SYS_lookup_dcookie
738#ifdef __NR_lookup_dcookie
739 {"lookup_dcookie", __NR_lookup_dcookie},
740#endif
741#endif
742#ifdef SYS_lremovexattr
743#ifdef __NR_lremovexattr
744 {"lremovexattr", __NR_lremovexattr},
745#endif
746#endif
747#ifdef SYS_lseek
748#ifdef __NR_lseek
749 {"lseek", __NR_lseek},
750#endif
751#endif
752#ifdef SYS_lsetxattr
753#ifdef __NR_lsetxattr
754 {"lsetxattr", __NR_lsetxattr},
755#endif
756#endif
757#ifdef SYS_lstat
758#ifdef __NR_lstat
759 {"lstat", __NR_lstat},
760#endif
761#endif
762#ifdef SYS_lstat64
763#ifdef __NR_lstat64
764 {"lstat64", __NR_lstat64},
765#endif
766#endif
767#ifdef SYS_madvise
768#ifdef __NR_madvise
769 {"madvise", __NR_madvise},
770#endif
771#endif
772#ifdef SYS_mbind
773#ifdef __NR_mbind
774 {"mbind", __NR_mbind},
775#endif
776#endif
777#ifdef SYS_migrate_pages
778#ifdef __NR_migrate_pages
779 {"migrate_pages", __NR_migrate_pages},
780#endif
781#endif
782#ifdef SYS_mincore
783#ifdef __NR_mincore
784 {"mincore", __NR_mincore},
785#endif
786#endif
787#ifdef SYS_mkdir
788#ifdef __NR_mkdir
789 {"mkdir", __NR_mkdir},
790#endif
791#endif
792#ifdef SYS_mkdirat
793#ifdef __NR_mkdirat
794 {"mkdirat", __NR_mkdirat},
795#endif
796#endif
797#ifdef SYS_mknod
798#ifdef __NR_mknod
799 {"mknod", __NR_mknod},
800#endif
801#endif
802#ifdef SYS_mknodat
803#ifdef __NR_mknodat
804 {"mknodat", __NR_mknodat},
805#endif
806#endif
807#ifdef SYS_mlock
808#ifdef __NR_mlock
809 {"mlock", __NR_mlock},
810#endif
811#endif
812#ifdef SYS_mlockall
813#ifdef __NR_mlockall
814 {"mlockall", __NR_mlockall},
815#endif
816#endif
817#ifdef SYS_mmap
818#ifdef __NR_mmap
819 {"mmap", __NR_mmap},
820#endif
821#endif
822#ifdef SYS_mmap2
823#ifdef __NR_mmap2
824 {"mmap2", __NR_mmap2},
825#endif
826#endif
827#ifdef SYS_modify_ldt
828#ifdef __NR_modify_ldt
829 {"modify_ldt", __NR_modify_ldt},
830#endif
831#endif
832#ifdef SYS_mount
833#ifdef __NR_mount
834 {"mount", __NR_mount},
835#endif
836#endif
837#ifdef SYS_move_pages
838#ifdef __NR_move_pages
839 {"move_pages", __NR_move_pages},
840#endif
841#endif
842#ifdef SYS_mprotect
843#ifdef __NR_mprotect
844 {"mprotect", __NR_mprotect},
845#endif
846#endif
847#ifdef SYS_mpx
848#ifdef __NR_mpx
849 {"mpx", __NR_mpx},
850#endif
851#endif
852#ifdef SYS_mq_getsetattr
853#ifdef __NR_mq_getsetattr
854 {"mq_getsetattr", __NR_mq_getsetattr},
855#endif
856#endif
857#ifdef SYS_mq_notify
858#ifdef __NR_mq_notify
859 {"mq_notify", __NR_mq_notify},
860#endif
861#endif
862#ifdef SYS_mq_open
863#ifdef __NR_mq_open
864 {"mq_open", __NR_mq_open},
865#endif
866#endif
867#ifdef SYS_mq_timedreceive
868#ifdef __NR_mq_timedreceive
869 {"mq_timedreceive", __NR_mq_timedreceive},
870#endif
871#endif
872#ifdef SYS_mq_timedsend
873#ifdef __NR_mq_timedsend
874 {"mq_timedsend", __NR_mq_timedsend},
875#endif
876#endif
877#ifdef SYS_mq_unlink
878#ifdef __NR_mq_unlink
879 {"mq_unlink", __NR_mq_unlink},
880#endif
881#endif
882#ifdef SYS_mremap
883#ifdef __NR_mremap
884 {"mremap", __NR_mremap},
885#endif
886#endif
887#ifdef SYS_msync
888#ifdef __NR_msync
889 {"msync", __NR_msync},
890#endif
891#endif
892#ifdef SYS_munlock
893#ifdef __NR_munlock
894 {"munlock", __NR_munlock},
895#endif
896#endif
897#ifdef SYS_munlockall
898#ifdef __NR_munlockall
899 {"munlockall", __NR_munlockall},
900#endif
901#endif
902#ifdef SYS_munmap
903#ifdef __NR_munmap
904 {"munmap", __NR_munmap},
905#endif
906#endif
907#ifdef SYS_name_to_handle_at
908#ifdef __NR_name_to_handle_at
909 {"name_to_handle_at", __NR_name_to_handle_at},
910#endif
911#endif
912#ifdef SYS_nanosleep
913#ifdef __NR_nanosleep
914 {"nanosleep", __NR_nanosleep},
915#endif
916#endif
917#ifdef SYS_nfsservctl
918#ifdef __NR_nfsservctl
919 {"nfsservctl", __NR_nfsservctl},
920#endif
921#endif
922#ifdef SYS_nice
923#ifdef __NR_nice
924 {"nice", __NR_nice},
925#endif
926#endif
927#ifdef SYS_oldfstat
928#ifdef __NR_oldfstat
929 {"oldfstat", __NR_oldfstat},
930#endif
931#endif
932#ifdef SYS_oldlstat
933#ifdef __NR_oldlstat
934 {"oldlstat", __NR_oldlstat},
935#endif
936#endif
937#ifdef SYS_oldolduname
938#ifdef __NR_oldolduname
939 {"oldolduname", __NR_oldolduname},
940#endif
941#endif
942#ifdef SYS_oldstat
943#ifdef __NR_oldstat
944 {"oldstat", __NR_oldstat},
945#endif
946#endif
947#ifdef SYS_olduname
948#ifdef __NR_olduname
949 {"olduname", __NR_olduname},
950#endif
951#endif
952#ifdef SYS_open
953#ifdef __NR_open
954 {"open", __NR_open},
955#endif
956#endif
957#ifdef SYS_open_by_handle_at
958#ifdef __NR_open_by_handle_at
959 {"open_by_handle_at", __NR_open_by_handle_at},
960#endif
961#endif
962#ifdef SYS_openat
963#ifdef __NR_openat
964 {"openat", __NR_openat},
965#endif
966#endif
967#ifdef SYS_pause
968#ifdef __NR_pause
969 {"pause", __NR_pause},
970#endif
971#endif
972#ifdef SYS_perf_event_open
973#ifdef __NR_perf_event_open
974 {"perf_event_open", __NR_perf_event_open},
975#endif
976#endif
977#ifdef SYS_personality
978#ifdef __NR_personality
979 {"personality", __NR_personality},
980#endif
981#endif
982#ifdef SYS_pipe
983#ifdef __NR_pipe
984 {"pipe", __NR_pipe},
985#endif
986#endif
987#ifdef SYS_pipe2
988#ifdef __NR_pipe2
989 {"pipe2", __NR_pipe2},
990#endif
991#endif
992#ifdef SYS_pivot_root
993#ifdef __NR_pivot_root
994 {"pivot_root", __NR_pivot_root},
995#endif
996#endif
997#ifdef SYS_poll
998#ifdef __NR_poll
999 {"poll", __NR_poll},
1000#endif
1001#endif
1002#ifdef SYS_ppoll
1003#ifdef __NR_ppoll
1004 {"ppoll", __NR_ppoll},
1005#endif
1006#endif
1007#ifdef SYS_prctl
1008#ifdef __NR_prctl
1009 {"prctl", __NR_prctl},
1010#endif
1011#endif
1012#ifdef SYS_pread64
1013#ifdef __NR_pread64
1014 {"pread64", __NR_pread64},
1015#endif
1016#endif
1017#ifdef SYS_preadv
1018#ifdef __NR_preadv
1019 {"preadv", __NR_preadv},
1020#endif
1021#endif
1022#ifdef SYS_prlimit64
1023#ifdef __NR_prlimit64
1024 {"prlimit64", __NR_prlimit64},
1025#endif
1026#endif
1027#ifdef SYS_process_vm_readv
1028#ifdef __NR_process_vm_readv
1029 {"process_vm_readv", __NR_process_vm_readv},
1030#endif
1031#endif
1032#ifdef SYS_process_vm_writev
1033#ifdef __NR_process_vm_writev
1034 {"process_vm_writev", __NR_process_vm_writev},
1035#endif
1036#endif
1037#ifdef SYS_prof
1038#ifdef __NR_prof
1039 {"prof", __NR_prof},
1040#endif
1041#endif
1042#ifdef SYS_profil
1043#ifdef __NR_profil
1044 {"profil", __NR_profil},
1045#endif
1046#endif
1047#ifdef SYS_pselect6
1048#ifdef __NR_pselect6
1049 {"pselect6", __NR_pselect6},
1050#endif
1051#endif
1052#ifdef SYS_ptrace
1053#ifdef __NR_ptrace
1054 {"ptrace", __NR_ptrace},
1055#endif
1056#endif
1057#ifdef SYS_putpmsg
1058#ifdef __NR_putpmsg
1059 {"putpmsg", __NR_putpmsg},
1060#endif
1061#endif
1062#ifdef SYS_pwrite64
1063#ifdef __NR_pwrite64
1064 {"pwrite64", __NR_pwrite64},
1065#endif
1066#endif
1067#ifdef SYS_pwritev
1068#ifdef __NR_pwritev
1069 {"pwritev", __NR_pwritev},
1070#endif
1071#endif
1072#ifdef SYS_query_module
1073#ifdef __NR_query_module
1074 {"query_module", __NR_query_module},
1075#endif
1076#endif
1077#ifdef SYS_quotactl
1078#ifdef __NR_quotactl
1079 {"quotactl", __NR_quotactl},
1080#endif
1081#endif
1082#ifdef SYS_read
1083#ifdef __NR_read
1084 {"read", __NR_read},
1085#endif
1086#endif
1087#ifdef SYS_readahead
1088#ifdef __NR_readahead
1089 {"readahead", __NR_readahead},
1090#endif
1091#endif
1092#ifdef SYS_readdir
1093#ifdef __NR_readdir
1094 {"readdir", __NR_readdir},
1095#endif
1096#endif
1097#ifdef SYS_readlink
1098#ifdef __NR_readlink
1099 {"readlink", __NR_readlink},
1100#endif
1101#endif
1102#ifdef SYS_readlinkat
1103#ifdef __NR_readlinkat
1104 {"readlinkat", __NR_readlinkat},
1105#endif
1106#endif
1107#ifdef SYS_readv
1108#ifdef __NR_readv
1109 {"readv", __NR_readv},
1110#endif
1111#endif
1112#ifdef SYS_reboot
1113#ifdef __NR_reboot
1114 {"reboot", __NR_reboot},
1115#endif
1116#endif
1117#ifdef SYS_recvmmsg
1118#ifdef __NR_recvmmsg
1119 {"recvmmsg", __NR_recvmmsg},
1120#endif
1121#endif
1122#ifdef SYS_remap_file_pages
1123#ifdef __NR_remap_file_pages
1124 {"remap_file_pages", __NR_remap_file_pages},
1125#endif
1126#endif
1127#ifdef SYS_removexattr
1128#ifdef __NR_removexattr
1129 {"removexattr", __NR_removexattr},
1130#endif
1131#endif
1132#ifdef SYS_rename
1133#ifdef __NR_rename
1134 {"rename", __NR_rename},
1135#endif
1136#endif
1137#ifdef SYS_renameat
1138#ifdef __NR_renameat
1139 {"renameat", __NR_renameat},
1140#endif
1141#endif
1142#ifdef SYS_request_key
1143#ifdef __NR_request_key
1144 {"request_key", __NR_request_key},
1145#endif
1146#endif
1147#ifdef SYS_restart_syscall
1148#ifdef __NR_restart_syscall
1149 {"restart_syscall", __NR_restart_syscall},
1150#endif
1151#endif
1152#ifdef SYS_rmdir
1153#ifdef __NR_rmdir
1154 {"rmdir", __NR_rmdir},
1155#endif
1156#endif
1157#ifdef SYS_rt_sigaction
1158#ifdef __NR_rt_sigaction
1159 {"rt_sigaction", __NR_rt_sigaction},
1160#endif
1161#endif
1162#ifdef SYS_rt_sigpending
1163#ifdef __NR_rt_sigpending
1164 {"rt_sigpending", __NR_rt_sigpending},
1165#endif
1166#endif
1167#ifdef SYS_rt_sigprocmask
1168#ifdef __NR_rt_sigprocmask
1169 {"rt_sigprocmask", __NR_rt_sigprocmask},
1170#endif
1171#endif
1172#ifdef SYS_rt_sigqueueinfo
1173#ifdef __NR_rt_sigqueueinfo
1174 {"rt_sigqueueinfo", __NR_rt_sigqueueinfo},
1175#endif
1176#endif
1177#ifdef SYS_rt_sigreturn
1178#ifdef __NR_rt_sigreturn
1179 {"rt_sigreturn", __NR_rt_sigreturn},
1180#endif
1181#endif
1182#ifdef SYS_rt_sigsuspend
1183#ifdef __NR_rt_sigsuspend
1184 {"rt_sigsuspend", __NR_rt_sigsuspend},
1185#endif
1186#endif
1187#ifdef SYS_rt_sigtimedwait
1188#ifdef __NR_rt_sigtimedwait
1189 {"rt_sigtimedwait", __NR_rt_sigtimedwait},
1190#endif
1191#endif
1192#ifdef SYS_rt_tgsigqueueinfo
1193#ifdef __NR_rt_tgsigqueueinfo
1194 {"rt_tgsigqueueinfo", __NR_rt_tgsigqueueinfo},
1195#endif
1196#endif
1197#ifdef SYS_sched_get_priority_max
1198#ifdef __NR_sched_get_priority_max
1199 {"sched_get_priority_max", __NR_sched_get_priority_max},
1200#endif
1201#endif
1202#ifdef SYS_sched_get_priority_min
1203#ifdef __NR_sched_get_priority_min
1204 {"sched_get_priority_min", __NR_sched_get_priority_min},
1205#endif
1206#endif
1207#ifdef SYS_sched_getaffinity
1208#ifdef __NR_sched_getaffinity
1209 {"sched_getaffinity", __NR_sched_getaffinity},
1210#endif
1211#endif
1212#ifdef SYS_sched_getparam
1213#ifdef __NR_sched_getparam
1214 {"sched_getparam", __NR_sched_getparam},
1215#endif
1216#endif
1217#ifdef SYS_sched_getscheduler
1218#ifdef __NR_sched_getscheduler
1219 {"sched_getscheduler", __NR_sched_getscheduler},
1220#endif
1221#endif
1222#ifdef SYS_sched_rr_get_interval
1223#ifdef __NR_sched_rr_get_interval
1224 {"sched_rr_get_interval", __NR_sched_rr_get_interval},
1225#endif
1226#endif
1227#ifdef SYS_sched_setaffinity
1228#ifdef __NR_sched_setaffinity
1229 {"sched_setaffinity", __NR_sched_setaffinity},
1230#endif
1231#endif
1232#ifdef SYS_sched_setparam
1233#ifdef __NR_sched_setparam
1234 {"sched_setparam", __NR_sched_setparam},
1235#endif
1236#endif
1237#ifdef SYS_sched_setscheduler
1238#ifdef __NR_sched_setscheduler
1239 {"sched_setscheduler", __NR_sched_setscheduler},
1240#endif
1241#endif
1242#ifdef SYS_sched_yield
1243#ifdef __NR_sched_yield
1244 {"sched_yield", __NR_sched_yield},
1245#endif
1246#endif
1247#ifdef SYS_select
1248#ifdef __NR_select
1249 {"select", __NR_select},
1250#endif
1251#endif
1252#ifdef SYS_sendfile
1253#ifdef __NR_sendfile
1254 {"sendfile", __NR_sendfile},
1255#endif
1256#endif
1257#ifdef SYS_sendfile64
1258#ifdef __NR_sendfile64
1259 {"sendfile64", __NR_sendfile64},
1260#endif
1261#endif
1262#ifdef SYS_sendmmsg
1263#ifdef __NR_sendmmsg
1264 {"sendmmsg", __NR_sendmmsg},
1265#endif
1266#endif
1267#ifdef SYS_set_mempolicy
1268#ifdef __NR_set_mempolicy
1269 {"set_mempolicy", __NR_set_mempolicy},
1270#endif
1271#endif
1272#ifdef SYS_set_robust_list
1273#ifdef __NR_set_robust_list
1274 {"set_robust_list", __NR_set_robust_list},
1275#endif
1276#endif
1277#ifdef SYS_set_thread_area
1278#ifdef __NR_set_thread_area
1279 {"set_thread_area", __NR_set_thread_area},
1280#endif
1281#endif
1282#ifdef SYS_set_tid_address
1283#ifdef __NR_set_tid_address
1284 {"set_tid_address", __NR_set_tid_address},
1285#endif
1286#endif
1287#ifdef SYS_setdomainname
1288#ifdef __NR_setdomainname
1289 {"setdomainname", __NR_setdomainname},
1290#endif
1291#endif
1292#ifdef SYS_setfsgid
1293#ifdef __NR_setfsgid
1294 {"setfsgid", __NR_setfsgid},
1295#endif
1296#endif
1297#ifdef SYS_setfsgid32
1298#ifdef __NR_setfsgid32
1299 {"setfsgid32", __NR_setfsgid32},
1300#endif
1301#endif
1302#ifdef SYS_setfsuid
1303#ifdef __NR_setfsuid
1304 {"setfsuid", __NR_setfsuid},
1305#endif
1306#endif
1307#ifdef SYS_setfsuid32
1308#ifdef __NR_setfsuid32
1309 {"setfsuid32", __NR_setfsuid32},
1310#endif
1311#endif
1312#ifdef SYS_setgid
1313#ifdef __NR_setgid
1314 {"setgid", __NR_setgid},
1315#endif
1316#endif
1317#ifdef SYS_setgid32
1318#ifdef __NR_setgid32
1319 {"setgid32", __NR_setgid32},
1320#endif
1321#endif
1322#ifdef SYS_setgroups
1323#ifdef __NR_setgroups
1324 {"setgroups", __NR_setgroups},
1325#endif
1326#endif
1327#ifdef SYS_setgroups32
1328#ifdef __NR_setgroups32
1329 {"setgroups32", __NR_setgroups32},
1330#endif
1331#endif
1332#ifdef SYS_sethostname
1333#ifdef __NR_sethostname
1334 {"sethostname", __NR_sethostname},
1335#endif
1336#endif
1337#ifdef SYS_setitimer
1338#ifdef __NR_setitimer
1339 {"setitimer", __NR_setitimer},
1340#endif
1341#endif
1342#ifdef SYS_setns
1343#ifdef __NR_setns
1344 {"setns", __NR_setns},
1345#endif
1346#endif
1347#ifdef SYS_setpgid
1348#ifdef __NR_setpgid
1349 {"setpgid", __NR_setpgid},
1350#endif
1351#endif
1352#ifdef SYS_setpriority
1353#ifdef __NR_setpriority
1354 {"setpriority", __NR_setpriority},
1355#endif
1356#endif
1357#ifdef SYS_setregid
1358#ifdef __NR_setregid
1359 {"setregid", __NR_setregid},
1360#endif
1361#endif
1362#ifdef SYS_setregid32
1363#ifdef __NR_setregid32
1364 {"setregid32", __NR_setregid32},
1365#endif
1366#endif
1367#ifdef SYS_setresgid
1368#ifdef __NR_setresgid
1369 {"setresgid", __NR_setresgid},
1370#endif
1371#endif
1372#ifdef SYS_setresgid32
1373#ifdef __NR_setresgid32
1374 {"setresgid32", __NR_setresgid32},
1375#endif
1376#endif
1377#ifdef SYS_setresuid
1378#ifdef __NR_setresuid
1379 {"setresuid", __NR_setresuid},
1380#endif
1381#endif
1382#ifdef SYS_setresuid32
1383#ifdef __NR_setresuid32
1384 {"setresuid32", __NR_setresuid32},
1385#endif
1386#endif
1387#ifdef SYS_setreuid
1388#ifdef __NR_setreuid
1389 {"setreuid", __NR_setreuid},
1390#endif
1391#endif
1392#ifdef SYS_setreuid32
1393#ifdef __NR_setreuid32
1394 {"setreuid32", __NR_setreuid32},
1395#endif
1396#endif
1397#ifdef SYS_setrlimit
1398#ifdef __NR_setrlimit
1399 {"setrlimit", __NR_setrlimit},
1400#endif
1401#endif
1402#ifdef SYS_setsid
1403#ifdef __NR_setsid
1404 {"setsid", __NR_setsid},
1405#endif
1406#endif
1407#ifdef SYS_settimeofday
1408#ifdef __NR_settimeofday
1409 {"settimeofday", __NR_settimeofday},
1410#endif
1411#endif
1412#ifdef SYS_setuid
1413#ifdef __NR_setuid
1414 {"setuid", __NR_setuid},
1415#endif
1416#endif
1417#ifdef SYS_setuid32
1418#ifdef __NR_setuid32
1419 {"setuid32", __NR_setuid32},
1420#endif
1421#endif
1422#ifdef SYS_setxattr
1423#ifdef __NR_setxattr
1424 {"setxattr", __NR_setxattr},
1425#endif
1426#endif
1427#ifdef SYS_sgetmask
1428#ifdef __NR_sgetmask
1429 {"sgetmask", __NR_sgetmask},
1430#endif
1431#endif
1432#ifdef SYS_sigaction
1433#ifdef __NR_sigaction
1434 {"sigaction", __NR_sigaction},
1435#endif
1436#endif
1437#ifdef SYS_sigaltstack
1438#ifdef __NR_sigaltstack
1439 {"sigaltstack", __NR_sigaltstack},
1440#endif
1441#endif
1442#ifdef SYS_signal
1443#ifdef __NR_signal
1444 {"signal", __NR_signal},
1445#endif
1446#endif
1447#ifdef SYS_signalfd
1448#ifdef __NR_signalfd
1449 {"signalfd", __NR_signalfd},
1450#endif
1451#endif
1452#ifdef SYS_signalfd4
1453#ifdef __NR_signalfd4
1454 {"signalfd4", __NR_signalfd4},
1455#endif
1456#endif
1457#ifdef SYS_sigpending
1458#ifdef __NR_sigpending
1459 {"sigpending", __NR_sigpending},
1460#endif
1461#endif
1462#ifdef SYS_sigprocmask
1463#ifdef __NR_sigprocmask
1464 {"sigprocmask", __NR_sigprocmask},
1465#endif
1466#endif
1467#ifdef SYS_sigreturn
1468#ifdef __NR_sigreturn
1469 {"sigreturn", __NR_sigreturn},
1470#endif
1471#endif
1472#ifdef SYS_sigsuspend
1473#ifdef __NR_sigsuspend
1474 {"sigsuspend", __NR_sigsuspend},
1475#endif
1476#endif
1477#ifdef SYS_socketcall
1478#ifdef __NR_socketcall
1479 {"socketcall", __NR_socketcall},
1480#endif
1481#endif
1482#ifdef SYS_splice
1483#ifdef __NR_splice
1484 {"splice", __NR_splice},
1485#endif
1486#endif
1487#ifdef SYS_ssetmask
1488#ifdef __NR_ssetmask
1489 {"ssetmask", __NR_ssetmask},
1490#endif
1491#endif
1492#ifdef SYS_stat
1493#ifdef __NR_stat
1494 {"stat", __NR_stat},
1495#endif
1496#endif
1497#ifdef SYS_stat64
1498#ifdef __NR_stat64
1499 {"stat64", __NR_stat64},
1500#endif
1501#endif
1502#ifdef SYS_statfs
1503#ifdef __NR_statfs
1504 {"statfs", __NR_statfs},
1505#endif
1506#endif
1507#ifdef SYS_statfs64
1508#ifdef __NR_statfs64
1509 {"statfs64", __NR_statfs64},
1510#endif
1511#endif
1512#ifdef SYS_stime
1513#ifdef __NR_stime
1514 {"stime", __NR_stime},
1515#endif
1516#endif
1517#ifdef SYS_stty
1518#ifdef __NR_stty
1519 {"stty", __NR_stty},
1520#endif
1521#endif
1522#ifdef SYS_swapoff
1523#ifdef __NR_swapoff
1524 {"swapoff", __NR_swapoff},
1525#endif
1526#endif
1527#ifdef SYS_swapon
1528#ifdef __NR_swapon
1529 {"swapon", __NR_swapon},
1530#endif
1531#endif
1532#ifdef SYS_symlink
1533#ifdef __NR_symlink
1534 {"symlink", __NR_symlink},
1535#endif
1536#endif
1537#ifdef SYS_symlinkat
1538#ifdef __NR_symlinkat
1539 {"symlinkat", __NR_symlinkat},
1540#endif
1541#endif
1542#ifdef SYS_sync
1543#ifdef __NR_sync
1544 {"sync", __NR_sync},
1545#endif
1546#endif
1547#ifdef SYS_sync_file_range
1548#ifdef __NR_sync_file_range
1549 {"sync_file_range", __NR_sync_file_range},
1550#endif
1551#endif
1552#ifdef SYS_syncfs
1553#ifdef __NR_syncfs
1554 {"syncfs", __NR_syncfs},
1555#endif
1556#endif
1557#ifdef SYS_sysfs
1558#ifdef __NR_sysfs
1559 {"sysfs", __NR_sysfs},
1560#endif
1561#endif
1562#ifdef SYS_sysinfo
1563#ifdef __NR_sysinfo
1564 {"sysinfo", __NR_sysinfo},
1565#endif
1566#endif
1567#ifdef SYS_syslog
1568#ifdef __NR_syslog
1569 {"syslog", __NR_syslog},
1570#endif
1571#endif
1572#ifdef SYS_tee
1573#ifdef __NR_tee
1574 {"tee", __NR_tee},
1575#endif
1576#endif
1577#ifdef SYS_tgkill
1578#ifdef __NR_tgkill
1579 {"tgkill", __NR_tgkill},
1580#endif
1581#endif
1582#ifdef SYS_time
1583#ifdef __NR_time
1584 {"time", __NR_time},
1585#endif
1586#endif
1587#ifdef SYS_timer_create
1588#ifdef __NR_timer_create
1589 {"timer_create", __NR_timer_create},
1590#endif
1591#endif
1592#ifdef SYS_timer_delete
1593#ifdef __NR_timer_delete
1594 {"timer_delete", __NR_timer_delete},
1595#endif
1596#endif
1597#ifdef SYS_timer_getoverrun
1598#ifdef __NR_timer_getoverrun
1599 {"timer_getoverrun", __NR_timer_getoverrun},
1600#endif
1601#endif
1602#ifdef SYS_timer_gettime
1603#ifdef __NR_timer_gettime
1604 {"timer_gettime", __NR_timer_gettime},
1605#endif
1606#endif
1607#ifdef SYS_timer_settime
1608#ifdef __NR_timer_settime
1609 {"timer_settime", __NR_timer_settime},
1610#endif
1611#endif
1612#ifdef SYS_timerfd_create
1613#ifdef __NR_timerfd_create
1614 {"timerfd_create", __NR_timerfd_create},
1615#endif
1616#endif
1617#ifdef SYS_timerfd_gettime
1618#ifdef __NR_timerfd_gettime
1619 {"timerfd_gettime", __NR_timerfd_gettime},
1620#endif
1621#endif
1622#ifdef SYS_timerfd_settime
1623#ifdef __NR_timerfd_settime
1624 {"timerfd_settime", __NR_timerfd_settime},
1625#endif
1626#endif
1627#ifdef SYS_times
1628#ifdef __NR_times
1629 {"times", __NR_times},
1630#endif
1631#endif
1632#ifdef SYS_tkill
1633#ifdef __NR_tkill
1634 {"tkill", __NR_tkill},
1635#endif
1636#endif
1637#ifdef SYS_truncate
1638#ifdef __NR_truncate
1639 {"truncate", __NR_truncate},
1640#endif
1641#endif
1642#ifdef SYS_truncate64
1643#ifdef __NR_truncate64
1644 {"truncate64", __NR_truncate64},
1645#endif
1646#endif
1647#ifdef SYS_ugetrlimit
1648#ifdef __NR_ugetrlimit
1649 {"ugetrlimit", __NR_ugetrlimit},
1650#endif
1651#endif
1652#ifdef SYS_ulimit
1653#ifdef __NR_ulimit
1654 {"ulimit", __NR_ulimit},
1655#endif
1656#endif
1657#ifdef SYS_umask
1658#ifdef __NR_umask
1659 {"umask", __NR_umask},
1660#endif
1661#endif
1662#ifdef SYS_umount
1663#ifdef __NR_umount
1664 {"umount", __NR_umount},
1665#endif
1666#endif
1667#ifdef SYS_umount2
1668#ifdef __NR_umount2
1669 {"umount2", __NR_umount2},
1670#endif
1671#endif
1672#ifdef SYS_uname
1673#ifdef __NR_uname
1674 {"uname", __NR_uname},
1675#endif
1676#endif
1677#ifdef SYS_unlink
1678#ifdef __NR_unlink
1679 {"unlink", __NR_unlink},
1680#endif
1681#endif
1682#ifdef SYS_unlinkat
1683#ifdef __NR_unlinkat
1684 {"unlinkat", __NR_unlinkat},
1685#endif
1686#endif
1687#ifdef SYS_unshare
1688#ifdef __NR_unshare
1689 {"unshare", __NR_unshare},
1690#endif
1691#endif
1692#ifdef SYS_uselib
1693#ifdef __NR_uselib
1694 {"uselib", __NR_uselib},
1695#endif
1696#endif
1697#ifdef SYS_ustat
1698#ifdef __NR_ustat
1699 {"ustat", __NR_ustat},
1700#endif
1701#endif
1702#ifdef SYS_utime
1703#ifdef __NR_utime
1704 {"utime", __NR_utime},
1705#endif
1706#endif
1707#ifdef SYS_utimensat
1708#ifdef __NR_utimensat
1709 {"utimensat", __NR_utimensat},
1710#endif
1711#endif
1712#ifdef SYS_utimes
1713#ifdef __NR_utimes
1714 {"utimes", __NR_utimes},
1715#endif
1716#endif
1717#ifdef SYS_vfork
1718#ifdef __NR_vfork
1719 {"vfork", __NR_vfork},
1720#endif
1721#endif
1722#ifdef SYS_vhangup
1723#ifdef __NR_vhangup
1724 {"vhangup", __NR_vhangup},
1725#endif
1726#endif
1727#ifdef SYS_vm86
1728#ifdef __NR_vm86
1729 {"vm86", __NR_vm86},
1730#endif
1731#endif
1732#ifdef SYS_vm86old
1733#ifdef __NR_vm86old
1734 {"vm86old", __NR_vm86old},
1735#endif
1736#endif
1737#ifdef SYS_vmsplice
1738#ifdef __NR_vmsplice
1739 {"vmsplice", __NR_vmsplice},
1740#endif
1741#endif
1742#ifdef SYS_vserver
1743#ifdef __NR_vserver
1744 {"vserver", __NR_vserver},
1745#endif
1746#endif
1747#ifdef SYS_wait4
1748#ifdef __NR_wait4
1749 {"wait4", __NR_wait4},
1750#endif
1751#endif
1752#ifdef SYS_waitid
1753#ifdef __NR_waitid
1754 {"waitid", __NR_waitid},
1755#endif
1756#endif
1757#ifdef SYS_waitpid
1758#ifdef __NR_waitpid
1759 {"waitpid", __NR_waitpid},
1760#endif
1761#endif
1762#ifdef SYS_write
1763#ifdef __NR_write
1764 {"write", __NR_write},
1765#endif
1766#endif
1767#ifdef SYS_writev
1768#ifdef __NR_writev
1769 {"writev", __NR_writev},
1770#endif
1771#endif
1772#endif
1773#if defined __x86_64__ && defined __LP64__
1774#ifdef SYS__sysctl
1775#ifdef __NR__sysctl
1776 {"_sysctl", __NR__sysctl},
1777#endif
1778#endif
1779#ifdef SYS_accept
1780#ifdef __NR_accept
1781 {"accept", __NR_accept},
1782#endif
1783#endif
1784#ifdef SYS_accept4
1785#ifdef __NR_accept4
1786 {"accept4", __NR_accept4},
1787#endif
1788#endif
1789#ifdef SYS_access
1790#ifdef __NR_access
1791 {"access", __NR_access},
1792#endif
1793#endif
1794#ifdef SYS_acct
1795#ifdef __NR_acct
1796 {"acct", __NR_acct},
1797#endif
1798#endif
1799#ifdef SYS_add_key
1800#ifdef __NR_add_key
1801 {"add_key", __NR_add_key},
1802#endif
1803#endif
1804#ifdef SYS_adjtimex
1805#ifdef __NR_adjtimex
1806 {"adjtimex", __NR_adjtimex},
1807#endif
1808#endif
1809#ifdef SYS_afs_syscall
1810#ifdef __NR_afs_syscall
1811 {"afs_syscall", __NR_afs_syscall},
1812#endif
1813#endif
1814#ifdef SYS_alarm
1815#ifdef __NR_alarm
1816 {"alarm", __NR_alarm},
1817#endif
1818#endif
1819#ifdef SYS_arch_prctl
1820#ifdef __NR_arch_prctl
1821 {"arch_prctl", __NR_arch_prctl},
1822#endif
1823#endif
1824#ifdef SYS_bind
1825#ifdef __NR_bind
1826 {"bind", __NR_bind},
1827#endif
1828#endif
1829#ifdef SYS_brk
1830#ifdef __NR_brk
1831 {"brk", __NR_brk},
1832#endif
1833#endif
1834#ifdef SYS_capget
1835#ifdef __NR_capget
1836 {"capget", __NR_capget},
1837#endif
1838#endif
1839#ifdef SYS_capset
1840#ifdef __NR_capset
1841 {"capset", __NR_capset},
1842#endif
1843#endif
1844#ifdef SYS_chdir
1845#ifdef __NR_chdir
1846 {"chdir", __NR_chdir},
1847#endif
1848#endif
1849#ifdef SYS_chmod
1850#ifdef __NR_chmod
1851 {"chmod", __NR_chmod},
1852#endif
1853#endif
1854#ifdef SYS_chown
1855#ifdef __NR_chown
1856 {"chown", __NR_chown},
1857#endif
1858#endif
1859#ifdef SYS_chroot
1860#ifdef __NR_chroot
1861 {"chroot", __NR_chroot},
1862#endif
1863#endif
1864#ifdef SYS_clock_adjtime
1865#ifdef __NR_clock_adjtime
1866 {"clock_adjtime", __NR_clock_adjtime},
1867#endif
1868#endif
1869#ifdef SYS_clock_getres
1870#ifdef __NR_clock_getres
1871 {"clock_getres", __NR_clock_getres},
1872#endif
1873#endif
1874#ifdef SYS_clock_gettime
1875#ifdef __NR_clock_gettime
1876 {"clock_gettime", __NR_clock_gettime},
1877#endif
1878#endif
1879#ifdef SYS_clock_nanosleep
1880#ifdef __NR_clock_nanosleep
1881 {"clock_nanosleep", __NR_clock_nanosleep},
1882#endif
1883#endif
1884#ifdef SYS_clock_settime
1885#ifdef __NR_clock_settime
1886 {"clock_settime", __NR_clock_settime},
1887#endif
1888#endif
1889#ifdef SYS_clone
1890#ifdef __NR_clone
1891 {"clone", __NR_clone},
1892#endif
1893#endif
1894#ifdef SYS_close
1895#ifdef __NR_close
1896 {"close", __NR_close},
1897#endif
1898#endif
1899#ifdef SYS_connect
1900#ifdef __NR_connect
1901 {"connect", __NR_connect},
1902#endif
1903#endif
1904#ifdef SYS_creat
1905#ifdef __NR_creat
1906 {"creat", __NR_creat},
1907#endif
1908#endif
1909#ifdef SYS_create_module
1910#ifdef __NR_create_module
1911 {"create_module", __NR_create_module},
1912#endif
1913#endif
1914#ifdef SYS_delete_module
1915#ifdef __NR_delete_module
1916 {"delete_module", __NR_delete_module},
1917#endif
1918#endif
1919#ifdef SYS_dup
1920#ifdef __NR_dup
1921 {"dup", __NR_dup},
1922#endif
1923#endif
1924#ifdef SYS_dup2
1925#ifdef __NR_dup2
1926 {"dup2", __NR_dup2},
1927#endif
1928#endif
1929#ifdef SYS_dup3
1930#ifdef __NR_dup3
1931 {"dup3", __NR_dup3},
1932#endif
1933#endif
1934#ifdef SYS_epoll_create
1935#ifdef __NR_epoll_create
1936 {"epoll_create", __NR_epoll_create},
1937#endif
1938#endif
1939#ifdef SYS_epoll_create1
1940#ifdef __NR_epoll_create1
1941 {"epoll_create1", __NR_epoll_create1},
1942#endif
1943#endif
1944#ifdef SYS_epoll_ctl
1945#ifdef __NR_epoll_ctl
1946 {"epoll_ctl", __NR_epoll_ctl},
1947#endif
1948#endif
1949#ifdef SYS_epoll_ctl_old
1950#ifdef __NR_epoll_ctl_old
1951 {"epoll_ctl_old", __NR_epoll_ctl_old},
1952#endif
1953#endif
1954#ifdef SYS_epoll_pwait
1955#ifdef __NR_epoll_pwait
1956 {"epoll_pwait", __NR_epoll_pwait},
1957#endif
1958#endif
1959#ifdef SYS_epoll_wait
1960#ifdef __NR_epoll_wait
1961 {"epoll_wait", __NR_epoll_wait},
1962#endif
1963#endif
1964#ifdef SYS_epoll_wait_old
1965#ifdef __NR_epoll_wait_old
1966 {"epoll_wait_old", __NR_epoll_wait_old},
1967#endif
1968#endif
1969#ifdef SYS_eventfd
1970#ifdef __NR_eventfd
1971 {"eventfd", __NR_eventfd},
1972#endif
1973#endif
1974#ifdef SYS_eventfd2
1975#ifdef __NR_eventfd2
1976 {"eventfd2", __NR_eventfd2},
1977#endif
1978#endif
1979#ifdef SYS_execve
1980#ifdef __NR_execve
1981 {"execve", __NR_execve},
1982#endif
1983#endif
1984#ifdef SYS_exit
1985#ifdef __NR_exit
1986 {"exit", __NR_exit},
1987#endif
1988#endif
1989#ifdef SYS_exit_group
1990#ifdef __NR_exit_group
1991 {"exit_group", __NR_exit_group},
1992#endif
1993#endif
1994#ifdef SYS_faccessat
1995#ifdef __NR_faccessat
1996 {"faccessat", __NR_faccessat},
1997#endif
1998#endif
1999#ifdef SYS_fadvise64
2000#ifdef __NR_fadvise64
2001 {"fadvise64", __NR_fadvise64},
2002#endif
2003#endif
2004#ifdef SYS_fallocate
2005#ifdef __NR_fallocate
2006 {"fallocate", __NR_fallocate},
2007#endif
2008#endif
2009#ifdef SYS_fanotify_init
2010#ifdef __NR_fanotify_init
2011 {"fanotify_init", __NR_fanotify_init},
2012#endif
2013#endif
2014#ifdef SYS_fanotify_mark
2015#ifdef __NR_fanotify_mark
2016 {"fanotify_mark", __NR_fanotify_mark},
2017#endif
2018#endif
2019#ifdef SYS_fchdir
2020#ifdef __NR_fchdir
2021 {"fchdir", __NR_fchdir},
2022#endif
2023#endif
2024#ifdef SYS_fchmod
2025#ifdef __NR_fchmod
2026 {"fchmod", __NR_fchmod},
2027#endif
2028#endif
2029#ifdef SYS_fchmodat
2030#ifdef __NR_fchmodat
2031 {"fchmodat", __NR_fchmodat},
2032#endif
2033#endif
2034#ifdef SYS_fchown
2035#ifdef __NR_fchown
2036 {"fchown", __NR_fchown},
2037#endif
2038#endif
2039#ifdef SYS_fchownat
2040#ifdef __NR_fchownat
2041 {"fchownat", __NR_fchownat},
2042#endif
2043#endif
2044#ifdef SYS_fcntl
2045#ifdef __NR_fcntl
2046 {"fcntl", __NR_fcntl},
2047#endif
2048#endif
2049#ifdef SYS_fdatasync
2050#ifdef __NR_fdatasync
2051 {"fdatasync", __NR_fdatasync},
2052#endif
2053#endif
2054#ifdef SYS_fgetxattr
2055#ifdef __NR_fgetxattr
2056 {"fgetxattr", __NR_fgetxattr},
2057#endif
2058#endif
2059#ifdef SYS_finit_module
2060#ifdef __NR_finit_module
2061 {"finit_module", __NR_finit_module},
2062#endif
2063#endif
2064#ifdef SYS_flistxattr
2065#ifdef __NR_flistxattr
2066 {"flistxattr", __NR_flistxattr},
2067#endif
2068#endif
2069#ifdef SYS_flock
2070#ifdef __NR_flock
2071 {"flock", __NR_flock},
2072#endif
2073#endif
2074#ifdef SYS_fork
2075#ifdef __NR_fork
2076 {"fork", __NR_fork},
2077#endif
2078#endif
2079#ifdef SYS_fremovexattr
2080#ifdef __NR_fremovexattr
2081 {"fremovexattr", __NR_fremovexattr},
2082#endif
2083#endif
2084#ifdef SYS_fsetxattr
2085#ifdef __NR_fsetxattr
2086 {"fsetxattr", __NR_fsetxattr},
2087#endif
2088#endif
2089#ifdef SYS_fstat
2090#ifdef __NR_fstat
2091 {"fstat", __NR_fstat},
2092#endif
2093#endif
2094#ifdef SYS_fstatfs
2095#ifdef __NR_fstatfs
2096 {"fstatfs", __NR_fstatfs},
2097#endif
2098#endif
2099#ifdef SYS_fsync
2100#ifdef __NR_fsync
2101 {"fsync", __NR_fsync},
2102#endif
2103#endif
2104#ifdef SYS_ftruncate
2105#ifdef __NR_ftruncate
2106 {"ftruncate", __NR_ftruncate},
2107#endif
2108#endif
2109#ifdef SYS_futex
2110#ifdef __NR_futex
2111 {"futex", __NR_futex},
2112#endif
2113#endif
2114#ifdef SYS_futimesat
2115#ifdef __NR_futimesat
2116 {"futimesat", __NR_futimesat},
2117#endif
2118#endif
2119#ifdef SYS_get_kernel_syms
2120#ifdef __NR_get_kernel_syms
2121 {"get_kernel_syms", __NR_get_kernel_syms},
2122#endif
2123#endif
2124#ifdef SYS_get_mempolicy
2125#ifdef __NR_get_mempolicy
2126 {"get_mempolicy", __NR_get_mempolicy},
2127#endif
2128#endif
2129#ifdef SYS_get_robust_list
2130#ifdef __NR_get_robust_list
2131 {"get_robust_list", __NR_get_robust_list},
2132#endif
2133#endif
2134#ifdef SYS_get_thread_area
2135#ifdef __NR_get_thread_area
2136 {"get_thread_area", __NR_get_thread_area},
2137#endif
2138#endif
2139#ifdef SYS_getcpu
2140#ifdef __NR_getcpu
2141 {"getcpu", __NR_getcpu},
2142#endif
2143#endif
2144#ifdef SYS_getcwd
2145#ifdef __NR_getcwd
2146 {"getcwd", __NR_getcwd},
2147#endif
2148#endif
2149#ifdef SYS_getdents
2150#ifdef __NR_getdents
2151 {"getdents", __NR_getdents},
2152#endif
2153#endif
2154#ifdef SYS_getdents64
2155#ifdef __NR_getdents64
2156 {"getdents64", __NR_getdents64},
2157#endif
2158#endif
2159#ifdef SYS_getegid
2160#ifdef __NR_getegid
2161 {"getegid", __NR_getegid},
2162#endif
2163#endif
2164#ifdef SYS_geteuid
2165#ifdef __NR_geteuid
2166 {"geteuid", __NR_geteuid},
2167#endif
2168#endif
2169#ifdef SYS_getgid
2170#ifdef __NR_getgid
2171 {"getgid", __NR_getgid},
2172#endif
2173#endif
2174#ifdef SYS_getgroups
2175#ifdef __NR_getgroups
2176 {"getgroups", __NR_getgroups},
2177#endif
2178#endif
2179#ifdef SYS_getitimer
2180#ifdef __NR_getitimer
2181 {"getitimer", __NR_getitimer},
2182#endif
2183#endif
2184#ifdef SYS_getpeername
2185#ifdef __NR_getpeername
2186 {"getpeername", __NR_getpeername},
2187#endif
2188#endif
2189#ifdef SYS_getpgid
2190#ifdef __NR_getpgid
2191 {"getpgid", __NR_getpgid},
2192#endif
2193#endif
2194#ifdef SYS_getpgrp
2195#ifdef __NR_getpgrp
2196 {"getpgrp", __NR_getpgrp},
2197#endif
2198#endif
2199#ifdef SYS_getpid
2200#ifdef __NR_getpid
2201 {"getpid", __NR_getpid},
2202#endif
2203#endif
2204#ifdef SYS_getpmsg
2205#ifdef __NR_getpmsg
2206 {"getpmsg", __NR_getpmsg},
2207#endif
2208#endif
2209#ifdef SYS_getppid
2210#ifdef __NR_getppid
2211 {"getppid", __NR_getppid},
2212#endif
2213#endif
2214#ifdef SYS_getpriority
2215#ifdef __NR_getpriority
2216 {"getpriority", __NR_getpriority},
2217#endif
2218#endif
2219#ifdef SYS_getresgid
2220#ifdef __NR_getresgid
2221 {"getresgid", __NR_getresgid},
2222#endif
2223#endif
2224#ifdef SYS_getresuid
2225#ifdef __NR_getresuid
2226 {"getresuid", __NR_getresuid},
2227#endif
2228#endif
2229#ifdef SYS_getrlimit
2230#ifdef __NR_getrlimit
2231 {"getrlimit", __NR_getrlimit},
2232#endif
2233#endif
2234#ifdef SYS_getrusage
2235#ifdef __NR_getrusage
2236 {"getrusage", __NR_getrusage},
2237#endif
2238#endif
2239#ifdef SYS_getsid
2240#ifdef __NR_getsid
2241 {"getsid", __NR_getsid},
2242#endif
2243#endif
2244#ifdef SYS_getsockname
2245#ifdef __NR_getsockname
2246 {"getsockname", __NR_getsockname},
2247#endif
2248#endif
2249#ifdef SYS_getsockopt
2250#ifdef __NR_getsockopt
2251 {"getsockopt", __NR_getsockopt},
2252#endif
2253#endif
2254#ifdef SYS_gettid
2255#ifdef __NR_gettid
2256 {"gettid", __NR_gettid},
2257#endif
2258#endif
2259#ifdef SYS_gettimeofday
2260#ifdef __NR_gettimeofday
2261 {"gettimeofday", __NR_gettimeofday},
2262#endif
2263#endif
2264#ifdef SYS_getuid
2265#ifdef __NR_getuid
2266 {"getuid", __NR_getuid},
2267#endif
2268#endif
2269#ifdef SYS_getxattr
2270#ifdef __NR_getxattr
2271 {"getxattr", __NR_getxattr},
2272#endif
2273#endif
2274#ifdef SYS_init_module
2275#ifdef __NR_init_module
2276 {"init_module", __NR_init_module},
2277#endif
2278#endif
2279#ifdef SYS_inotify_add_watch
2280#ifdef __NR_inotify_add_watch
2281 {"inotify_add_watch", __NR_inotify_add_watch},
2282#endif
2283#endif
2284#ifdef SYS_inotify_init
2285#ifdef __NR_inotify_init
2286 {"inotify_init", __NR_inotify_init},
2287#endif
2288#endif
2289#ifdef SYS_inotify_init1
2290#ifdef __NR_inotify_init1
2291 {"inotify_init1", __NR_inotify_init1},
2292#endif
2293#endif
2294#ifdef SYS_inotify_rm_watch
2295#ifdef __NR_inotify_rm_watch
2296 {"inotify_rm_watch", __NR_inotify_rm_watch},
2297#endif
2298#endif
2299#ifdef SYS_io_cancel
2300#ifdef __NR_io_cancel
2301 {"io_cancel", __NR_io_cancel},
2302#endif
2303#endif
2304#ifdef SYS_io_destroy
2305#ifdef __NR_io_destroy
2306 {"io_destroy", __NR_io_destroy},
2307#endif
2308#endif
2309#ifdef SYS_io_getevents
2310#ifdef __NR_io_getevents
2311 {"io_getevents", __NR_io_getevents},
2312#endif
2313#endif
2314#ifdef SYS_io_setup
2315#ifdef __NR_io_setup
2316 {"io_setup", __NR_io_setup},
2317#endif
2318#endif
2319#ifdef SYS_io_submit
2320#ifdef __NR_io_submit
2321 {"io_submit", __NR_io_submit},
2322#endif
2323#endif
2324#ifdef SYS_ioctl
2325#ifdef __NR_ioctl
2326 {"ioctl", __NR_ioctl},
2327#endif
2328#endif
2329#ifdef SYS_ioperm
2330#ifdef __NR_ioperm
2331 {"ioperm", __NR_ioperm},
2332#endif
2333#endif
2334#ifdef SYS_iopl
2335#ifdef __NR_iopl
2336 {"iopl", __NR_iopl},
2337#endif
2338#endif
2339#ifdef SYS_ioprio_get
2340#ifdef __NR_ioprio_get
2341 {"ioprio_get", __NR_ioprio_get},
2342#endif
2343#endif
2344#ifdef SYS_ioprio_set
2345#ifdef __NR_ioprio_set
2346 {"ioprio_set", __NR_ioprio_set},
2347#endif
2348#endif
2349#ifdef SYS_kcmp
2350#ifdef __NR_kcmp
2351 {"kcmp", __NR_kcmp},
2352#endif
2353#endif
2354#ifdef SYS_kexec_load
2355#ifdef __NR_kexec_load
2356 {"kexec_load", __NR_kexec_load},
2357#endif
2358#endif
2359#ifdef SYS_keyctl
2360#ifdef __NR_keyctl
2361 {"keyctl", __NR_keyctl},
2362#endif
2363#endif
2364#ifdef SYS_kill
2365#ifdef __NR_kill
2366 {"kill", __NR_kill},
2367#endif
2368#endif
2369#ifdef SYS_lchown
2370#ifdef __NR_lchown
2371 {"lchown", __NR_lchown},
2372#endif
2373#endif
2374#ifdef SYS_lgetxattr
2375#ifdef __NR_lgetxattr
2376 {"lgetxattr", __NR_lgetxattr},
2377#endif
2378#endif
2379#ifdef SYS_link
2380#ifdef __NR_link
2381 {"link", __NR_link},
2382#endif
2383#endif
2384#ifdef SYS_linkat
2385#ifdef __NR_linkat
2386 {"linkat", __NR_linkat},
2387#endif
2388#endif
2389#ifdef SYS_listen
2390#ifdef __NR_listen
2391 {"listen", __NR_listen},
2392#endif
2393#endif
2394#ifdef SYS_listxattr
2395#ifdef __NR_listxattr
2396 {"listxattr", __NR_listxattr},
2397#endif
2398#endif
2399#ifdef SYS_llistxattr
2400#ifdef __NR_llistxattr
2401 {"llistxattr", __NR_llistxattr},
2402#endif
2403#endif
2404#ifdef SYS_lookup_dcookie
2405#ifdef __NR_lookup_dcookie
2406 {"lookup_dcookie", __NR_lookup_dcookie},
2407#endif
2408#endif
2409#ifdef SYS_lremovexattr
2410#ifdef __NR_lremovexattr
2411 {"lremovexattr", __NR_lremovexattr},
2412#endif
2413#endif
2414#ifdef SYS_lseek
2415#ifdef __NR_lseek
2416 {"lseek", __NR_lseek},
2417#endif
2418#endif
2419#ifdef SYS_lsetxattr
2420#ifdef __NR_lsetxattr
2421 {"lsetxattr", __NR_lsetxattr},
2422#endif
2423#endif
2424#ifdef SYS_lstat
2425#ifdef __NR_lstat
2426 {"lstat", __NR_lstat},
2427#endif
2428#endif
2429#ifdef SYS_madvise
2430#ifdef __NR_madvise
2431 {"madvise", __NR_madvise},
2432#endif
2433#endif
2434#ifdef SYS_mbind
2435#ifdef __NR_mbind
2436 {"mbind", __NR_mbind},
2437#endif
2438#endif
2439#ifdef SYS_migrate_pages
2440#ifdef __NR_migrate_pages
2441 {"migrate_pages", __NR_migrate_pages},
2442#endif
2443#endif
2444#ifdef SYS_mincore
2445#ifdef __NR_mincore
2446 {"mincore", __NR_mincore},
2447#endif
2448#endif
2449#ifdef SYS_mkdir
2450#ifdef __NR_mkdir
2451 {"mkdir", __NR_mkdir},
2452#endif
2453#endif
2454#ifdef SYS_mkdirat
2455#ifdef __NR_mkdirat
2456 {"mkdirat", __NR_mkdirat},
2457#endif
2458#endif
2459#ifdef SYS_mknod
2460#ifdef __NR_mknod
2461 {"mknod", __NR_mknod},
2462#endif
2463#endif
2464#ifdef SYS_mknodat
2465#ifdef __NR_mknodat
2466 {"mknodat", __NR_mknodat},
2467#endif
2468#endif
2469#ifdef SYS_mlock
2470#ifdef __NR_mlock
2471 {"mlock", __NR_mlock},
2472#endif
2473#endif
2474#ifdef SYS_mlockall
2475#ifdef __NR_mlockall
2476 {"mlockall", __NR_mlockall},
2477#endif
2478#endif
2479#ifdef SYS_mmap
2480#ifdef __NR_mmap
2481 {"mmap", __NR_mmap},
2482#endif
2483#endif
2484#ifdef SYS_modify_ldt
2485#ifdef __NR_modify_ldt
2486 {"modify_ldt", __NR_modify_ldt},
2487#endif
2488#endif
2489#ifdef SYS_mount
2490#ifdef __NR_mount
2491 {"mount", __NR_mount},
2492#endif
2493#endif
2494#ifdef SYS_move_pages
2495#ifdef __NR_move_pages
2496 {"move_pages", __NR_move_pages},
2497#endif
2498#endif
2499#ifdef SYS_mprotect
2500#ifdef __NR_mprotect
2501 {"mprotect", __NR_mprotect},
2502#endif
2503#endif
2504#ifdef SYS_mq_getsetattr
2505#ifdef __NR_mq_getsetattr
2506 {"mq_getsetattr", __NR_mq_getsetattr},
2507#endif
2508#endif
2509#ifdef SYS_mq_notify
2510#ifdef __NR_mq_notify
2511 {"mq_notify", __NR_mq_notify},
2512#endif
2513#endif
2514#ifdef SYS_mq_open
2515#ifdef __NR_mq_open
2516 {"mq_open", __NR_mq_open},
2517#endif
2518#endif
2519#ifdef SYS_mq_timedreceive
2520#ifdef __NR_mq_timedreceive
2521 {"mq_timedreceive", __NR_mq_timedreceive},
2522#endif
2523#endif
2524#ifdef SYS_mq_timedsend
2525#ifdef __NR_mq_timedsend
2526 {"mq_timedsend", __NR_mq_timedsend},
2527#endif
2528#endif
2529#ifdef SYS_mq_unlink
2530#ifdef __NR_mq_unlink
2531 {"mq_unlink", __NR_mq_unlink},
2532#endif
2533#endif
2534#ifdef SYS_mremap
2535#ifdef __NR_mremap
2536 {"mremap", __NR_mremap},
2537#endif
2538#endif
2539#ifdef SYS_msgctl
2540#ifdef __NR_msgctl
2541 {"msgctl", __NR_msgctl},
2542#endif
2543#endif
2544#ifdef SYS_msgget
2545#ifdef __NR_msgget
2546 {"msgget", __NR_msgget},
2547#endif
2548#endif
2549#ifdef SYS_msgrcv
2550#ifdef __NR_msgrcv
2551 {"msgrcv", __NR_msgrcv},
2552#endif
2553#endif
2554#ifdef SYS_msgsnd
2555#ifdef __NR_msgsnd
2556 {"msgsnd", __NR_msgsnd},
2557#endif
2558#endif
2559#ifdef SYS_msync
2560#ifdef __NR_msync
2561 {"msync", __NR_msync},
2562#endif
2563#endif
2564#ifdef SYS_munlock
2565#ifdef __NR_munlock
2566 {"munlock", __NR_munlock},
2567#endif
2568#endif
2569#ifdef SYS_munlockall
2570#ifdef __NR_munlockall
2571 {"munlockall", __NR_munlockall},
2572#endif
2573#endif
2574#ifdef SYS_munmap
2575#ifdef __NR_munmap
2576 {"munmap", __NR_munmap},
2577#endif
2578#endif
2579#ifdef SYS_name_to_handle_at
2580#ifdef __NR_name_to_handle_at
2581 {"name_to_handle_at", __NR_name_to_handle_at},
2582#endif
2583#endif
2584#ifdef SYS_nanosleep
2585#ifdef __NR_nanosleep
2586 {"nanosleep", __NR_nanosleep},
2587#endif
2588#endif
2589#ifdef SYS_newfstatat
2590#ifdef __NR_newfstatat
2591 {"newfstatat", __NR_newfstatat},
2592#endif
2593#endif
2594#ifdef SYS_nfsservctl
2595#ifdef __NR_nfsservctl
2596 {"nfsservctl", __NR_nfsservctl},
2597#endif
2598#endif
2599#ifdef SYS_open
2600#ifdef __NR_open
2601 {"open", __NR_open},
2602#endif
2603#endif
2604#ifdef SYS_open_by_handle_at
2605#ifdef __NR_open_by_handle_at
2606 {"open_by_handle_at", __NR_open_by_handle_at},
2607#endif
2608#endif
2609#ifdef SYS_openat
2610#ifdef __NR_openat
2611 {"openat", __NR_openat},
2612#endif
2613#endif
2614#ifdef SYS_pause
2615#ifdef __NR_pause
2616 {"pause", __NR_pause},
2617#endif
2618#endif
2619#ifdef SYS_perf_event_open
2620#ifdef __NR_perf_event_open
2621 {"perf_event_open", __NR_perf_event_open},
2622#endif
2623#endif
2624#ifdef SYS_personality
2625#ifdef __NR_personality
2626 {"personality", __NR_personality},
2627#endif
2628#endif
2629#ifdef SYS_pipe
2630#ifdef __NR_pipe
2631 {"pipe", __NR_pipe},
2632#endif
2633#endif
2634#ifdef SYS_pipe2
2635#ifdef __NR_pipe2
2636 {"pipe2", __NR_pipe2},
2637#endif
2638#endif
2639#ifdef SYS_pivot_root
2640#ifdef __NR_pivot_root
2641 {"pivot_root", __NR_pivot_root},
2642#endif
2643#endif
2644#ifdef SYS_poll
2645#ifdef __NR_poll
2646 {"poll", __NR_poll},
2647#endif
2648#endif
2649#ifdef SYS_ppoll
2650#ifdef __NR_ppoll
2651 {"ppoll", __NR_ppoll},
2652#endif
2653#endif
2654#ifdef SYS_prctl
2655#ifdef __NR_prctl
2656 {"prctl", __NR_prctl},
2657#endif
2658#endif
2659#ifdef SYS_pread64
2660#ifdef __NR_pread64
2661 {"pread64", __NR_pread64},
2662#endif
2663#endif
2664#ifdef SYS_preadv
2665#ifdef __NR_preadv
2666 {"preadv", __NR_preadv},
2667#endif
2668#endif
2669#ifdef SYS_prlimit64
2670#ifdef __NR_prlimit64
2671 {"prlimit64", __NR_prlimit64},
2672#endif
2673#endif
2674#ifdef SYS_process_vm_readv
2675#ifdef __NR_process_vm_readv
2676 {"process_vm_readv", __NR_process_vm_readv},
2677#endif
2678#endif
2679#ifdef SYS_process_vm_writev
2680#ifdef __NR_process_vm_writev
2681 {"process_vm_writev", __NR_process_vm_writev},
2682#endif
2683#endif
2684#ifdef SYS_pselect6
2685#ifdef __NR_pselect6
2686 {"pselect6", __NR_pselect6},
2687#endif
2688#endif
2689#ifdef SYS_ptrace
2690#ifdef __NR_ptrace
2691 {"ptrace", __NR_ptrace},
2692#endif
2693#endif
2694#ifdef SYS_putpmsg
2695#ifdef __NR_putpmsg
2696 {"putpmsg", __NR_putpmsg},
2697#endif
2698#endif
2699#ifdef SYS_pwrite64
2700#ifdef __NR_pwrite64
2701 {"pwrite64", __NR_pwrite64},
2702#endif
2703#endif
2704#ifdef SYS_pwritev
2705#ifdef __NR_pwritev
2706 {"pwritev", __NR_pwritev},
2707#endif
2708#endif
2709#ifdef SYS_query_module
2710#ifdef __NR_query_module
2711 {"query_module", __NR_query_module},
2712#endif
2713#endif
2714#ifdef SYS_quotactl
2715#ifdef __NR_quotactl
2716 {"quotactl", __NR_quotactl},
2717#endif
2718#endif
2719#ifdef SYS_read
2720#ifdef __NR_read
2721 {"read", __NR_read},
2722#endif
2723#endif
2724#ifdef SYS_readahead
2725#ifdef __NR_readahead
2726 {"readahead", __NR_readahead},
2727#endif
2728#endif
2729#ifdef SYS_readlink
2730#ifdef __NR_readlink
2731 {"readlink", __NR_readlink},
2732#endif
2733#endif
2734#ifdef SYS_readlinkat
2735#ifdef __NR_readlinkat
2736 {"readlinkat", __NR_readlinkat},
2737#endif
2738#endif
2739#ifdef SYS_readv
2740#ifdef __NR_readv
2741 {"readv", __NR_readv},
2742#endif
2743#endif
2744#ifdef SYS_reboot
2745#ifdef __NR_reboot
2746 {"reboot", __NR_reboot},
2747#endif
2748#endif
2749#ifdef SYS_recvfrom
2750#ifdef __NR_recvfrom
2751 {"recvfrom", __NR_recvfrom},
2752#endif
2753#endif
2754#ifdef SYS_recvmmsg
2755#ifdef __NR_recvmmsg
2756 {"recvmmsg", __NR_recvmmsg},
2757#endif
2758#endif
2759#ifdef SYS_recvmsg
2760#ifdef __NR_recvmsg
2761 {"recvmsg", __NR_recvmsg},
2762#endif
2763#endif
2764#ifdef SYS_remap_file_pages
2765#ifdef __NR_remap_file_pages
2766 {"remap_file_pages", __NR_remap_file_pages},
2767#endif
2768#endif
2769#ifdef SYS_removexattr
2770#ifdef __NR_removexattr
2771 {"removexattr", __NR_removexattr},
2772#endif
2773#endif
2774#ifdef SYS_rename
2775#ifdef __NR_rename
2776 {"rename", __NR_rename},
2777#endif
2778#endif
2779#ifdef SYS_renameat
2780#ifdef __NR_renameat
2781 {"renameat", __NR_renameat},
2782#endif
2783#endif
2784#ifdef SYS_request_key
2785#ifdef __NR_request_key
2786 {"request_key", __NR_request_key},
2787#endif
2788#endif
2789#ifdef SYS_restart_syscall
2790#ifdef __NR_restart_syscall
2791 {"restart_syscall", __NR_restart_syscall},
2792#endif
2793#endif
2794#ifdef SYS_rmdir
2795#ifdef __NR_rmdir
2796 {"rmdir", __NR_rmdir},
2797#endif
2798#endif
2799#ifdef SYS_rt_sigaction
2800#ifdef __NR_rt_sigaction
2801 {"rt_sigaction", __NR_rt_sigaction},
2802#endif
2803#endif
2804#ifdef SYS_rt_sigpending
2805#ifdef __NR_rt_sigpending
2806 {"rt_sigpending", __NR_rt_sigpending},
2807#endif
2808#endif
2809#ifdef SYS_rt_sigprocmask
2810#ifdef __NR_rt_sigprocmask
2811 {"rt_sigprocmask", __NR_rt_sigprocmask},
2812#endif
2813#endif
2814#ifdef SYS_rt_sigqueueinfo
2815#ifdef __NR_rt_sigqueueinfo
2816 {"rt_sigqueueinfo", __NR_rt_sigqueueinfo},
2817#endif
2818#endif
2819#ifdef SYS_rt_sigreturn
2820#ifdef __NR_rt_sigreturn
2821 {"rt_sigreturn", __NR_rt_sigreturn},
2822#endif
2823#endif
2824#ifdef SYS_rt_sigsuspend
2825#ifdef __NR_rt_sigsuspend
2826 {"rt_sigsuspend", __NR_rt_sigsuspend},
2827#endif
2828#endif
2829#ifdef SYS_rt_sigtimedwait
2830#ifdef __NR_rt_sigtimedwait
2831 {"rt_sigtimedwait", __NR_rt_sigtimedwait},
2832#endif
2833#endif
2834#ifdef SYS_rt_tgsigqueueinfo
2835#ifdef __NR_rt_tgsigqueueinfo
2836 {"rt_tgsigqueueinfo", __NR_rt_tgsigqueueinfo},
2837#endif
2838#endif
2839#ifdef SYS_sched_get_priority_max
2840#ifdef __NR_sched_get_priority_max
2841 {"sched_get_priority_max", __NR_sched_get_priority_max},
2842#endif
2843#endif
2844#ifdef SYS_sched_get_priority_min
2845#ifdef __NR_sched_get_priority_min
2846 {"sched_get_priority_min", __NR_sched_get_priority_min},
2847#endif
2848#endif
2849#ifdef SYS_sched_getaffinity
2850#ifdef __NR_sched_getaffinity
2851 {"sched_getaffinity", __NR_sched_getaffinity},
2852#endif
2853#endif
2854#ifdef SYS_sched_getparam
2855#ifdef __NR_sched_getparam
2856 {"sched_getparam", __NR_sched_getparam},
2857#endif
2858#endif
2859#ifdef SYS_sched_getscheduler
2860#ifdef __NR_sched_getscheduler
2861 {"sched_getscheduler", __NR_sched_getscheduler},
2862#endif
2863#endif
2864#ifdef SYS_sched_rr_get_interval
2865#ifdef __NR_sched_rr_get_interval
2866 {"sched_rr_get_interval", __NR_sched_rr_get_interval},
2867#endif
2868#endif
2869#ifdef SYS_sched_setaffinity
2870#ifdef __NR_sched_setaffinity
2871 {"sched_setaffinity", __NR_sched_setaffinity},
2872#endif
2873#endif
2874#ifdef SYS_sched_setparam
2875#ifdef __NR_sched_setparam
2876 {"sched_setparam", __NR_sched_setparam},
2877#endif
2878#endif
2879#ifdef SYS_sched_setscheduler
2880#ifdef __NR_sched_setscheduler
2881 {"sched_setscheduler", __NR_sched_setscheduler},
2882#endif
2883#endif
2884#ifdef SYS_sched_yield
2885#ifdef __NR_sched_yield
2886 {"sched_yield", __NR_sched_yield},
2887#endif
2888#endif
2889#ifdef SYS_security
2890#ifdef __NR_security
2891 {"security", __NR_security},
2892#endif
2893#endif
2894#ifdef SYS_select
2895#ifdef __NR_select
2896 {"select", __NR_select},
2897#endif
2898#endif
2899#ifdef SYS_semctl
2900#ifdef __NR_semctl
2901 {"semctl", __NR_semctl},
2902#endif
2903#endif
2904#ifdef SYS_semget
2905#ifdef __NR_semget
2906 {"semget", __NR_semget},
2907#endif
2908#endif
2909#ifdef SYS_semop
2910#ifdef __NR_semop
2911 {"semop", __NR_semop},
2912#endif
2913#endif
2914#ifdef SYS_semtimedop
2915#ifdef __NR_semtimedop
2916 {"semtimedop", __NR_semtimedop},
2917#endif
2918#endif
2919#ifdef SYS_sendfile
2920#ifdef __NR_sendfile
2921 {"sendfile", __NR_sendfile},
2922#endif
2923#endif
2924#ifdef SYS_sendmmsg
2925#ifdef __NR_sendmmsg
2926 {"sendmmsg", __NR_sendmmsg},
2927#endif
2928#endif
2929#ifdef SYS_sendmsg
2930#ifdef __NR_sendmsg
2931 {"sendmsg", __NR_sendmsg},
2932#endif
2933#endif
2934#ifdef SYS_sendto
2935#ifdef __NR_sendto
2936 {"sendto", __NR_sendto},
2937#endif
2938#endif
2939#ifdef SYS_set_mempolicy
2940#ifdef __NR_set_mempolicy
2941 {"set_mempolicy", __NR_set_mempolicy},
2942#endif
2943#endif
2944#ifdef SYS_set_robust_list
2945#ifdef __NR_set_robust_list
2946 {"set_robust_list", __NR_set_robust_list},
2947#endif
2948#endif
2949#ifdef SYS_set_thread_area
2950#ifdef __NR_set_thread_area
2951 {"set_thread_area", __NR_set_thread_area},
2952#endif
2953#endif
2954#ifdef SYS_set_tid_address
2955#ifdef __NR_set_tid_address
2956 {"set_tid_address", __NR_set_tid_address},
2957#endif
2958#endif
2959#ifdef SYS_setdomainname
2960#ifdef __NR_setdomainname
2961 {"setdomainname", __NR_setdomainname},
2962#endif
2963#endif
2964#ifdef SYS_setfsgid
2965#ifdef __NR_setfsgid
2966 {"setfsgid", __NR_setfsgid},
2967#endif
2968#endif
2969#ifdef SYS_setfsuid
2970#ifdef __NR_setfsuid
2971 {"setfsuid", __NR_setfsuid},
2972#endif
2973#endif
2974#ifdef SYS_setgid
2975#ifdef __NR_setgid
2976 {"setgid", __NR_setgid},
2977#endif
2978#endif
2979#ifdef SYS_setgroups
2980#ifdef __NR_setgroups
2981 {"setgroups", __NR_setgroups},
2982#endif
2983#endif
2984#ifdef SYS_sethostname
2985#ifdef __NR_sethostname
2986 {"sethostname", __NR_sethostname},
2987#endif
2988#endif
2989#ifdef SYS_setitimer
2990#ifdef __NR_setitimer
2991 {"setitimer", __NR_setitimer},
2992#endif
2993#endif
2994#ifdef SYS_setns
2995#ifdef __NR_setns
2996 {"setns", __NR_setns},
2997#endif
2998#endif
2999#ifdef SYS_setpgid
3000#ifdef __NR_setpgid
3001 {"setpgid", __NR_setpgid},
3002#endif
3003#endif
3004#ifdef SYS_setpriority
3005#ifdef __NR_setpriority
3006 {"setpriority", __NR_setpriority},
3007#endif
3008#endif
3009#ifdef SYS_setregid
3010#ifdef __NR_setregid
3011 {"setregid", __NR_setregid},
3012#endif
3013#endif
3014#ifdef SYS_setresgid
3015#ifdef __NR_setresgid
3016 {"setresgid", __NR_setresgid},
3017#endif
3018#endif
3019#ifdef SYS_setresuid
3020#ifdef __NR_setresuid
3021 {"setresuid", __NR_setresuid},
3022#endif
3023#endif
3024#ifdef SYS_setreuid
3025#ifdef __NR_setreuid
3026 {"setreuid", __NR_setreuid},
3027#endif
3028#endif
3029#ifdef SYS_setrlimit
3030#ifdef __NR_setrlimit
3031 {"setrlimit", __NR_setrlimit},
3032#endif
3033#endif
3034#ifdef SYS_setsid
3035#ifdef __NR_setsid
3036 {"setsid", __NR_setsid},
3037#endif
3038#endif
3039#ifdef SYS_setsockopt
3040#ifdef __NR_setsockopt
3041 {"setsockopt", __NR_setsockopt},
3042#endif
3043#endif
3044#ifdef SYS_settimeofday
3045#ifdef __NR_settimeofday
3046 {"settimeofday", __NR_settimeofday},
3047#endif
3048#endif
3049#ifdef SYS_setuid
3050#ifdef __NR_setuid
3051 {"setuid", __NR_setuid},
3052#endif
3053#endif
3054#ifdef SYS_setxattr
3055#ifdef __NR_setxattr
3056 {"setxattr", __NR_setxattr},
3057#endif
3058#endif
3059#ifdef SYS_shmat
3060#ifdef __NR_shmat
3061 {"shmat", __NR_shmat},
3062#endif
3063#endif
3064#ifdef SYS_shmctl
3065#ifdef __NR_shmctl
3066 {"shmctl", __NR_shmctl},
3067#endif
3068#endif
3069#ifdef SYS_shmdt
3070#ifdef __NR_shmdt
3071 {"shmdt", __NR_shmdt},
3072#endif
3073#endif
3074#ifdef SYS_shmget
3075#ifdef __NR_shmget
3076 {"shmget", __NR_shmget},
3077#endif
3078#endif
3079#ifdef SYS_shutdown
3080#ifdef __NR_shutdown
3081 {"shutdown", __NR_shutdown},
3082#endif
3083#endif
3084#ifdef SYS_sigaltstack
3085#ifdef __NR_sigaltstack
3086 {"sigaltstack", __NR_sigaltstack},
3087#endif
3088#endif
3089#ifdef SYS_signalfd
3090#ifdef __NR_signalfd
3091 {"signalfd", __NR_signalfd},
3092#endif
3093#endif
3094#ifdef SYS_signalfd4
3095#ifdef __NR_signalfd4
3096 {"signalfd4", __NR_signalfd4},
3097#endif
3098#endif
3099#ifdef SYS_socket
3100#ifdef __NR_socket
3101 {"socket", __NR_socket},
3102#endif
3103#endif
3104#ifdef SYS_socketpair
3105#ifdef __NR_socketpair
3106 {"socketpair", __NR_socketpair},
3107#endif
3108#endif
3109#ifdef SYS_splice
3110#ifdef __NR_splice
3111 {"splice", __NR_splice},
3112#endif
3113#endif
3114#ifdef SYS_stat
3115#ifdef __NR_stat
3116 {"stat", __NR_stat},
3117#endif
3118#endif
3119#ifdef SYS_statfs
3120#ifdef __NR_statfs
3121 {"statfs", __NR_statfs},
3122#endif
3123#endif
3124#ifdef SYS_swapoff
3125#ifdef __NR_swapoff
3126 {"swapoff", __NR_swapoff},
3127#endif
3128#endif
3129#ifdef SYS_swapon
3130#ifdef __NR_swapon
3131 {"swapon", __NR_swapon},
3132#endif
3133#endif
3134#ifdef SYS_symlink
3135#ifdef __NR_symlink
3136 {"symlink", __NR_symlink},
3137#endif
3138#endif
3139#ifdef SYS_symlinkat
3140#ifdef __NR_symlinkat
3141 {"symlinkat", __NR_symlinkat},
3142#endif
3143#endif
3144#ifdef SYS_sync
3145#ifdef __NR_sync
3146 {"sync", __NR_sync},
3147#endif
3148#endif
3149#ifdef SYS_sync_file_range
3150#ifdef __NR_sync_file_range
3151 {"sync_file_range", __NR_sync_file_range},
3152#endif
3153#endif
3154#ifdef SYS_syncfs
3155#ifdef __NR_syncfs
3156 {"syncfs", __NR_syncfs},
3157#endif
3158#endif
3159#ifdef SYS_sysfs
3160#ifdef __NR_sysfs
3161 {"sysfs", __NR_sysfs},
3162#endif
3163#endif
3164#ifdef SYS_sysinfo
3165#ifdef __NR_sysinfo
3166 {"sysinfo", __NR_sysinfo},
3167#endif
3168#endif
3169#ifdef SYS_syslog
3170#ifdef __NR_syslog
3171 {"syslog", __NR_syslog},
3172#endif
3173#endif
3174#ifdef SYS_tee
3175#ifdef __NR_tee
3176 {"tee", __NR_tee},
3177#endif
3178#endif
3179#ifdef SYS_tgkill
3180#ifdef __NR_tgkill
3181 {"tgkill", __NR_tgkill},
3182#endif
3183#endif
3184#ifdef SYS_time
3185#ifdef __NR_time
3186 {"time", __NR_time},
3187#endif
3188#endif
3189#ifdef SYS_timer_create
3190#ifdef __NR_timer_create
3191 {"timer_create", __NR_timer_create},
3192#endif
3193#endif
3194#ifdef SYS_timer_delete
3195#ifdef __NR_timer_delete
3196 {"timer_delete", __NR_timer_delete},
3197#endif
3198#endif
3199#ifdef SYS_timer_getoverrun
3200#ifdef __NR_timer_getoverrun
3201 {"timer_getoverrun", __NR_timer_getoverrun},
3202#endif
3203#endif
3204#ifdef SYS_timer_gettime
3205#ifdef __NR_timer_gettime
3206 {"timer_gettime", __NR_timer_gettime},
3207#endif
3208#endif
3209#ifdef SYS_timer_settime
3210#ifdef __NR_timer_settime
3211 {"timer_settime", __NR_timer_settime},
3212#endif
3213#endif
3214#ifdef SYS_timerfd_create
3215#ifdef __NR_timerfd_create
3216 {"timerfd_create", __NR_timerfd_create},
3217#endif
3218#endif
3219#ifdef SYS_timerfd_gettime
3220#ifdef __NR_timerfd_gettime
3221 {"timerfd_gettime", __NR_timerfd_gettime},
3222#endif
3223#endif
3224#ifdef SYS_timerfd_settime
3225#ifdef __NR_timerfd_settime
3226 {"timerfd_settime", __NR_timerfd_settime},
3227#endif
3228#endif
3229#ifdef SYS_times
3230#ifdef __NR_times
3231 {"times", __NR_times},
3232#endif
3233#endif
3234#ifdef SYS_tkill
3235#ifdef __NR_tkill
3236 {"tkill", __NR_tkill},
3237#endif
3238#endif
3239#ifdef SYS_truncate
3240#ifdef __NR_truncate
3241 {"truncate", __NR_truncate},
3242#endif
3243#endif
3244#ifdef SYS_tuxcall
3245#ifdef __NR_tuxcall
3246 {"tuxcall", __NR_tuxcall},
3247#endif
3248#endif
3249#ifdef SYS_umask
3250#ifdef __NR_umask
3251 {"umask", __NR_umask},
3252#endif
3253#endif
3254#ifdef SYS_umount2
3255#ifdef __NR_umount2
3256 {"umount2", __NR_umount2},
3257#endif
3258#endif
3259#ifdef SYS_uname
3260#ifdef __NR_uname
3261 {"uname", __NR_uname},
3262#endif
3263#endif
3264#ifdef SYS_unlink
3265#ifdef __NR_unlink
3266 {"unlink", __NR_unlink},
3267#endif
3268#endif
3269#ifdef SYS_unlinkat
3270#ifdef __NR_unlinkat
3271 {"unlinkat", __NR_unlinkat},
3272#endif
3273#endif
3274#ifdef SYS_unshare
3275#ifdef __NR_unshare
3276 {"unshare", __NR_unshare},
3277#endif
3278#endif
3279#ifdef SYS_uselib
3280#ifdef __NR_uselib
3281 {"uselib", __NR_uselib},
3282#endif
3283#endif
3284#ifdef SYS_ustat
3285#ifdef __NR_ustat
3286 {"ustat", __NR_ustat},
3287#endif
3288#endif
3289#ifdef SYS_utime
3290#ifdef __NR_utime
3291 {"utime", __NR_utime},
3292#endif
3293#endif
3294#ifdef SYS_utimensat
3295#ifdef __NR_utimensat
3296 {"utimensat", __NR_utimensat},
3297#endif
3298#endif
3299#ifdef SYS_utimes
3300#ifdef __NR_utimes
3301 {"utimes", __NR_utimes},
3302#endif
3303#endif
3304#ifdef SYS_vfork
3305#ifdef __NR_vfork
3306 {"vfork", __NR_vfork},
3307#endif
3308#endif
3309#ifdef SYS_vhangup
3310#ifdef __NR_vhangup
3311 {"vhangup", __NR_vhangup},
3312#endif
3313#endif
3314#ifdef SYS_vmsplice
3315#ifdef __NR_vmsplice
3316 {"vmsplice", __NR_vmsplice},
3317#endif
3318#endif
3319#ifdef SYS_vserver
3320#ifdef __NR_vserver
3321 {"vserver", __NR_vserver},
3322#endif
3323#endif
3324#ifdef SYS_wait4
3325#ifdef __NR_wait4
3326 {"wait4", __NR_wait4},
3327#endif
3328#endif
3329#ifdef SYS_waitid
3330#ifdef __NR_waitid
3331 {"waitid", __NR_waitid},
3332#endif
3333#endif
3334#ifdef SYS_write
3335#ifdef __NR_write
3336 {"write", __NR_write},
3337#endif
3338#endif
3339#ifdef SYS_writev
3340#ifdef __NR_writev
3341 {"writev", __NR_writev},
3342#endif
3343#endif
3344#endif
3345#if defined __x86_64__ && defined __ILP32__
3346#ifdef SYS_accept
3347#ifdef __NR_accept
3348 {"accept", __NR_accept},
3349#endif
3350#endif
3351#ifdef SYS_accept4
3352#ifdef __NR_accept4
3353 {"accept4", __NR_accept4},
3354#endif
3355#endif
3356#ifdef SYS_access
3357#ifdef __NR_access
3358 {"access", __NR_access},
3359#endif
3360#endif
3361#ifdef SYS_acct
3362#ifdef __NR_acct
3363 {"acct", __NR_acct},
3364#endif
3365#endif
3366#ifdef SYS_add_key
3367#ifdef __NR_add_key
3368 {"add_key", __NR_add_key},
3369#endif
3370#endif
3371#ifdef SYS_adjtimex
3372#ifdef __NR_adjtimex
3373 {"adjtimex", __NR_adjtimex},
3374#endif
3375#endif
3376#ifdef SYS_afs_syscall
3377#ifdef __NR_afs_syscall
3378 {"afs_syscall", __NR_afs_syscall},
3379#endif
3380#endif
3381#ifdef SYS_alarm
3382#ifdef __NR_alarm
3383 {"alarm", __NR_alarm},
3384#endif
3385#endif
3386#ifdef SYS_arch_prctl
3387#ifdef __NR_arch_prctl
3388 {"arch_prctl", __NR_arch_prctl},
3389#endif
3390#endif
3391#ifdef SYS_bind
3392#ifdef __NR_bind
3393 {"bind", __NR_bind},
3394#endif
3395#endif
3396#ifdef SYS_brk
3397#ifdef __NR_brk
3398 {"brk", __NR_brk},
3399#endif
3400#endif
3401#ifdef SYS_capget
3402#ifdef __NR_capget
3403 {"capget", __NR_capget},
3404#endif
3405#endif
3406#ifdef SYS_capset
3407#ifdef __NR_capset
3408 {"capset", __NR_capset},
3409#endif
3410#endif
3411#ifdef SYS_chdir
3412#ifdef __NR_chdir
3413 {"chdir", __NR_chdir},
3414#endif
3415#endif
3416#ifdef SYS_chmod
3417#ifdef __NR_chmod
3418 {"chmod", __NR_chmod},
3419#endif
3420#endif
3421#ifdef SYS_chown
3422#ifdef __NR_chown
3423 {"chown", __NR_chown},
3424#endif
3425#endif
3426#ifdef SYS_chroot
3427#ifdef __NR_chroot
3428 {"chroot", __NR_chroot},
3429#endif
3430#endif
3431#ifdef SYS_clock_adjtime
3432#ifdef __NR_clock_adjtime
3433 {"clock_adjtime", __NR_clock_adjtime},
3434#endif
3435#endif
3436#ifdef SYS_clock_getres
3437#ifdef __NR_clock_getres
3438 {"clock_getres", __NR_clock_getres},
3439#endif
3440#endif
3441#ifdef SYS_clock_gettime
3442#ifdef __NR_clock_gettime
3443 {"clock_gettime", __NR_clock_gettime},
3444#endif
3445#endif
3446#ifdef SYS_clock_nanosleep
3447#ifdef __NR_clock_nanosleep
3448 {"clock_nanosleep", __NR_clock_nanosleep},
3449#endif
3450#endif
3451#ifdef SYS_clock_settime
3452#ifdef __NR_clock_settime
3453 {"clock_settime", __NR_clock_settime},
3454#endif
3455#endif
3456#ifdef SYS_clone
3457#ifdef __NR_clone
3458 {"clone", __NR_clone},
3459#endif
3460#endif
3461#ifdef SYS_close
3462#ifdef __NR_close
3463 {"close", __NR_close},
3464#endif
3465#endif
3466#ifdef SYS_connect
3467#ifdef __NR_connect
3468 {"connect", __NR_connect},
3469#endif
3470#endif
3471#ifdef SYS_creat
3472#ifdef __NR_creat
3473 {"creat", __NR_creat},
3474#endif
3475#endif
3476#ifdef SYS_delete_module
3477#ifdef __NR_delete_module
3478 {"delete_module", __NR_delete_module},
3479#endif
3480#endif
3481#ifdef SYS_dup
3482#ifdef __NR_dup
3483 {"dup", __NR_dup},
3484#endif
3485#endif
3486#ifdef SYS_dup2
3487#ifdef __NR_dup2
3488 {"dup2", __NR_dup2},
3489#endif
3490#endif
3491#ifdef SYS_dup3
3492#ifdef __NR_dup3
3493 {"dup3", __NR_dup3},
3494#endif
3495#endif
3496#ifdef SYS_epoll_create
3497#ifdef __NR_epoll_create
3498 {"epoll_create", __NR_epoll_create},
3499#endif
3500#endif
3501#ifdef SYS_epoll_create1
3502#ifdef __NR_epoll_create1
3503 {"epoll_create1", __NR_epoll_create1},
3504#endif
3505#endif
3506#ifdef SYS_epoll_ctl
3507#ifdef __NR_epoll_ctl
3508 {"epoll_ctl", __NR_epoll_ctl},
3509#endif
3510#endif
3511#ifdef SYS_epoll_pwait
3512#ifdef __NR_epoll_pwait
3513 {"epoll_pwait", __NR_epoll_pwait},
3514#endif
3515#endif
3516#ifdef SYS_epoll_wait
3517#ifdef __NR_epoll_wait
3518 {"epoll_wait", __NR_epoll_wait},
3519#endif
3520#endif
3521#ifdef SYS_eventfd
3522#ifdef __NR_eventfd
3523 {"eventfd", __NR_eventfd},
3524#endif
3525#endif
3526#ifdef SYS_eventfd2
3527#ifdef __NR_eventfd2
3528 {"eventfd2", __NR_eventfd2},
3529#endif
3530#endif
3531#ifdef SYS_execve
3532#ifdef __NR_execve
3533 {"execve", __NR_execve},
3534#endif
3535#endif
3536#ifdef SYS_exit
3537#ifdef __NR_exit
3538 {"exit", __NR_exit},
3539#endif
3540#endif
3541#ifdef SYS_exit_group
3542#ifdef __NR_exit_group
3543 {"exit_group", __NR_exit_group},
3544#endif
3545#endif
3546#ifdef SYS_faccessat
3547#ifdef __NR_faccessat
3548 {"faccessat", __NR_faccessat},
3549#endif
3550#endif
3551#ifdef SYS_fadvise64
3552#ifdef __NR_fadvise64
3553 {"fadvise64", __NR_fadvise64},
3554#endif
3555#endif
3556#ifdef SYS_fallocate
3557#ifdef __NR_fallocate
3558 {"fallocate", __NR_fallocate},
3559#endif
3560#endif
3561#ifdef SYS_fanotify_init
3562#ifdef __NR_fanotify_init
3563 {"fanotify_init", __NR_fanotify_init},
3564#endif
3565#endif
3566#ifdef SYS_fanotify_mark
3567#ifdef __NR_fanotify_mark
3568 {"fanotify_mark", __NR_fanotify_mark},
3569#endif
3570#endif
3571#ifdef SYS_fchdir
3572#ifdef __NR_fchdir
3573 {"fchdir", __NR_fchdir},
3574#endif
3575#endif
3576#ifdef SYS_fchmod
3577#ifdef __NR_fchmod
3578 {"fchmod", __NR_fchmod},
3579#endif
3580#endif
3581#ifdef SYS_fchmodat
3582#ifdef __NR_fchmodat
3583 {"fchmodat", __NR_fchmodat},
3584#endif
3585#endif
3586#ifdef SYS_fchown
3587#ifdef __NR_fchown
3588 {"fchown", __NR_fchown},
3589#endif
3590#endif
3591#ifdef SYS_fchownat
3592#ifdef __NR_fchownat
3593 {"fchownat", __NR_fchownat},
3594#endif
3595#endif
3596#ifdef SYS_fcntl
3597#ifdef __NR_fcntl
3598 {"fcntl", __NR_fcntl},
3599#endif
3600#endif
3601#ifdef SYS_fdatasync
3602#ifdef __NR_fdatasync
3603 {"fdatasync", __NR_fdatasync},
3604#endif
3605#endif
3606#ifdef SYS_fgetxattr
3607#ifdef __NR_fgetxattr
3608 {"fgetxattr", __NR_fgetxattr},
3609#endif
3610#endif
3611#ifdef SYS_finit_module
3612#ifdef __NR_finit_module
3613 {"finit_module", __NR_finit_module},
3614#endif
3615#endif
3616#ifdef SYS_flistxattr
3617#ifdef __NR_flistxattr
3618 {"flistxattr", __NR_flistxattr},
3619#endif
3620#endif
3621#ifdef SYS_flock
3622#ifdef __NR_flock
3623 {"flock", __NR_flock},
3624#endif
3625#endif
3626#ifdef SYS_fork
3627#ifdef __NR_fork
3628 {"fork", __NR_fork},
3629#endif
3630#endif
3631#ifdef SYS_fremovexattr
3632#ifdef __NR_fremovexattr
3633 {"fremovexattr", __NR_fremovexattr},
3634#endif
3635#endif
3636#ifdef SYS_fsetxattr
3637#ifdef __NR_fsetxattr
3638 {"fsetxattr", __NR_fsetxattr},
3639#endif
3640#endif
3641#ifdef SYS_fstat
3642#ifdef __NR_fstat
3643 {"fstat", __NR_fstat},
3644#endif
3645#endif
3646#ifdef SYS_fstatfs
3647#ifdef __NR_fstatfs
3648 {"fstatfs", __NR_fstatfs},
3649#endif
3650#endif
3651#ifdef SYS_fsync
3652#ifdef __NR_fsync
3653 {"fsync", __NR_fsync},
3654#endif
3655#endif
3656#ifdef SYS_ftruncate
3657#ifdef __NR_ftruncate
3658 {"ftruncate", __NR_ftruncate},
3659#endif
3660#endif
3661#ifdef SYS_futex
3662#ifdef __NR_futex
3663 {"futex", __NR_futex},
3664#endif
3665#endif
3666#ifdef SYS_futimesat
3667#ifdef __NR_futimesat
3668 {"futimesat", __NR_futimesat},
3669#endif
3670#endif
3671#ifdef SYS_get_mempolicy
3672#ifdef __NR_get_mempolicy
3673 {"get_mempolicy", __NR_get_mempolicy},
3674#endif
3675#endif
3676#ifdef SYS_get_robust_list
3677#ifdef __NR_get_robust_list
3678 {"get_robust_list", __NR_get_robust_list},
3679#endif
3680#endif
3681#ifdef SYS_getcpu
3682#ifdef __NR_getcpu
3683 {"getcpu", __NR_getcpu},
3684#endif
3685#endif
3686#ifdef SYS_getcwd
3687#ifdef __NR_getcwd
3688 {"getcwd", __NR_getcwd},
3689#endif
3690#endif
3691#ifdef SYS_getdents
3692#ifdef __NR_getdents
3693 {"getdents", __NR_getdents},
3694#endif
3695#endif
3696#ifdef SYS_getdents64
3697#ifdef __NR_getdents64
3698 {"getdents64", __NR_getdents64},
3699#endif
3700#endif
3701#ifdef SYS_getegid
3702#ifdef __NR_getegid
3703 {"getegid", __NR_getegid},
3704#endif
3705#endif
3706#ifdef SYS_geteuid
3707#ifdef __NR_geteuid
3708 {"geteuid", __NR_geteuid},
3709#endif
3710#endif
3711#ifdef SYS_getgid
3712#ifdef __NR_getgid
3713 {"getgid", __NR_getgid},
3714#endif
3715#endif
3716#ifdef SYS_getgroups
3717#ifdef __NR_getgroups
3718 {"getgroups", __NR_getgroups},
3719#endif
3720#endif
3721#ifdef SYS_getitimer
3722#ifdef __NR_getitimer
3723 {"getitimer", __NR_getitimer},
3724#endif
3725#endif
3726#ifdef SYS_getpeername
3727#ifdef __NR_getpeername
3728 {"getpeername", __NR_getpeername},
3729#endif
3730#endif
3731#ifdef SYS_getpgid
3732#ifdef __NR_getpgid
3733 {"getpgid", __NR_getpgid},
3734#endif
3735#endif
3736#ifdef SYS_getpgrp
3737#ifdef __NR_getpgrp
3738 {"getpgrp", __NR_getpgrp},
3739#endif
3740#endif
3741#ifdef SYS_getpid
3742#ifdef __NR_getpid
3743 {"getpid", __NR_getpid},
3744#endif
3745#endif
3746#ifdef SYS_getpmsg
3747#ifdef __NR_getpmsg
3748 {"getpmsg", __NR_getpmsg},
3749#endif
3750#endif
3751#ifdef SYS_getppid
3752#ifdef __NR_getppid
3753 {"getppid", __NR_getppid},
3754#endif
3755#endif
3756#ifdef SYS_getpriority
3757#ifdef __NR_getpriority
3758 {"getpriority", __NR_getpriority},
3759#endif
3760#endif
3761#ifdef SYS_getresgid
3762#ifdef __NR_getresgid
3763 {"getresgid", __NR_getresgid},
3764#endif
3765#endif
3766#ifdef SYS_getresuid
3767#ifdef __NR_getresuid
3768 {"getresuid", __NR_getresuid},
3769#endif
3770#endif
3771#ifdef SYS_getrlimit
3772#ifdef __NR_getrlimit
3773 {"getrlimit", __NR_getrlimit},
3774#endif
3775#endif
3776#ifdef SYS_getrusage
3777#ifdef __NR_getrusage
3778 {"getrusage", __NR_getrusage},
3779#endif
3780#endif
3781#ifdef SYS_getsid
3782#ifdef __NR_getsid
3783 {"getsid", __NR_getsid},
3784#endif
3785#endif
3786#ifdef SYS_getsockname
3787#ifdef __NR_getsockname
3788 {"getsockname", __NR_getsockname},
3789#endif
3790#endif
3791#ifdef SYS_getsockopt
3792#ifdef __NR_getsockopt
3793 {"getsockopt", __NR_getsockopt},
3794#endif
3795#endif
3796#ifdef SYS_gettid
3797#ifdef __NR_gettid
3798 {"gettid", __NR_gettid},
3799#endif
3800#endif
3801#ifdef SYS_gettimeofday
3802#ifdef __NR_gettimeofday
3803 {"gettimeofday", __NR_gettimeofday},
3804#endif
3805#endif
3806#ifdef SYS_getuid
3807#ifdef __NR_getuid
3808 {"getuid", __NR_getuid},
3809#endif
3810#endif
3811#ifdef SYS_getxattr
3812#ifdef __NR_getxattr
3813 {"getxattr", __NR_getxattr},
3814#endif
3815#endif
3816#ifdef SYS_init_module
3817#ifdef __NR_init_module
3818 {"init_module", __NR_init_module},
3819#endif
3820#endif
3821#ifdef SYS_inotify_add_watch
3822#ifdef __NR_inotify_add_watch
3823 {"inotify_add_watch", __NR_inotify_add_watch},
3824#endif
3825#endif
3826#ifdef SYS_inotify_init
3827#ifdef __NR_inotify_init
3828 {"inotify_init", __NR_inotify_init},
3829#endif
3830#endif
3831#ifdef SYS_inotify_init1
3832#ifdef __NR_inotify_init1
3833 {"inotify_init1", __NR_inotify_init1},
3834#endif
3835#endif
3836#ifdef SYS_inotify_rm_watch
3837#ifdef __NR_inotify_rm_watch
3838 {"inotify_rm_watch", __NR_inotify_rm_watch},
3839#endif
3840#endif
3841#ifdef SYS_io_cancel
3842#ifdef __NR_io_cancel
3843 {"io_cancel", __NR_io_cancel},
3844#endif
3845#endif
3846#ifdef SYS_io_destroy
3847#ifdef __NR_io_destroy
3848 {"io_destroy", __NR_io_destroy},
3849#endif
3850#endif
3851#ifdef SYS_io_getevents
3852#ifdef __NR_io_getevents
3853 {"io_getevents", __NR_io_getevents},
3854#endif
3855#endif
3856#ifdef SYS_io_setup
3857#ifdef __NR_io_setup
3858 {"io_setup", __NR_io_setup},
3859#endif
3860#endif
3861#ifdef SYS_io_submit
3862#ifdef __NR_io_submit
3863 {"io_submit", __NR_io_submit},
3864#endif
3865#endif
3866#ifdef SYS_ioctl
3867#ifdef __NR_ioctl
3868 {"ioctl", __NR_ioctl},
3869#endif
3870#endif
3871#ifdef SYS_ioperm
3872#ifdef __NR_ioperm
3873 {"ioperm", __NR_ioperm},
3874#endif
3875#endif
3876#ifdef SYS_iopl
3877#ifdef __NR_iopl
3878 {"iopl", __NR_iopl},
3879#endif
3880#endif
3881#ifdef SYS_ioprio_get
3882#ifdef __NR_ioprio_get
3883 {"ioprio_get", __NR_ioprio_get},
3884#endif
3885#endif
3886#ifdef SYS_ioprio_set
3887#ifdef __NR_ioprio_set
3888 {"ioprio_set", __NR_ioprio_set},
3889#endif
3890#endif
3891#ifdef SYS_kcmp
3892#ifdef __NR_kcmp
3893 {"kcmp", __NR_kcmp},
3894#endif
3895#endif
3896#ifdef SYS_kexec_load
3897#ifdef __NR_kexec_load
3898 {"kexec_load", __NR_kexec_load},
3899#endif
3900#endif
3901#ifdef SYS_keyctl
3902#ifdef __NR_keyctl
3903 {"keyctl", __NR_keyctl},
3904#endif
3905#endif
3906#ifdef SYS_kill
3907#ifdef __NR_kill
3908 {"kill", __NR_kill},
3909#endif
3910#endif
3911#ifdef SYS_lchown
3912#ifdef __NR_lchown
3913 {"lchown", __NR_lchown},
3914#endif
3915#endif
3916#ifdef SYS_lgetxattr
3917#ifdef __NR_lgetxattr
3918 {"lgetxattr", __NR_lgetxattr},
3919#endif
3920#endif
3921#ifdef SYS_link
3922#ifdef __NR_link
3923 {"link", __NR_link},
3924#endif
3925#endif
3926#ifdef SYS_linkat
3927#ifdef __NR_linkat
3928 {"linkat", __NR_linkat},
3929#endif
3930#endif
3931#ifdef SYS_listen
3932#ifdef __NR_listen
3933 {"listen", __NR_listen},
3934#endif
3935#endif
3936#ifdef SYS_listxattr
3937#ifdef __NR_listxattr
3938 {"listxattr", __NR_listxattr},
3939#endif
3940#endif
3941#ifdef SYS_llistxattr
3942#ifdef __NR_llistxattr
3943 {"llistxattr", __NR_llistxattr},
3944#endif
3945#endif
3946#ifdef SYS_lookup_dcookie
3947#ifdef __NR_lookup_dcookie
3948 {"lookup_dcookie", __NR_lookup_dcookie},
3949#endif
3950#endif
3951#ifdef SYS_lremovexattr
3952#ifdef __NR_lremovexattr
3953 {"lremovexattr", __NR_lremovexattr},
3954#endif
3955#endif
3956#ifdef SYS_lseek
3957#ifdef __NR_lseek
3958 {"lseek", __NR_lseek},
3959#endif
3960#endif
3961#ifdef SYS_lsetxattr
3962#ifdef __NR_lsetxattr
3963 {"lsetxattr", __NR_lsetxattr},
3964#endif
3965#endif
3966#ifdef SYS_lstat
3967#ifdef __NR_lstat
3968 {"lstat", __NR_lstat},
3969#endif
3970#endif
3971#ifdef SYS_madvise
3972#ifdef __NR_madvise
3973 {"madvise", __NR_madvise},
3974#endif
3975#endif
3976#ifdef SYS_mbind
3977#ifdef __NR_mbind
3978 {"mbind", __NR_mbind},
3979#endif
3980#endif
3981#ifdef SYS_migrate_pages
3982#ifdef __NR_migrate_pages
3983 {"migrate_pages", __NR_migrate_pages},
3984#endif
3985#endif
3986#ifdef SYS_mincore
3987#ifdef __NR_mincore
3988 {"mincore", __NR_mincore},
3989#endif
3990#endif
3991#ifdef SYS_mkdir
3992#ifdef __NR_mkdir
3993 {"mkdir", __NR_mkdir},
3994#endif
3995#endif
3996#ifdef SYS_mkdirat
3997#ifdef __NR_mkdirat
3998 {"mkdirat", __NR_mkdirat},
3999#endif
4000#endif
4001#ifdef SYS_mknod
4002#ifdef __NR_mknod
4003 {"mknod", __NR_mknod},
4004#endif
4005#endif
4006#ifdef SYS_mknodat
4007#ifdef __NR_mknodat
4008 {"mknodat", __NR_mknodat},
4009#endif
4010#endif
4011#ifdef SYS_mlock
4012#ifdef __NR_mlock
4013 {"mlock", __NR_mlock},
4014#endif
4015#endif
4016#ifdef SYS_mlockall
4017#ifdef __NR_mlockall
4018 {"mlockall", __NR_mlockall},
4019#endif
4020#endif
4021#ifdef SYS_mmap
4022#ifdef __NR_mmap
4023 {"mmap", __NR_mmap},
4024#endif
4025#endif
4026#ifdef SYS_modify_ldt
4027#ifdef __NR_modify_ldt
4028 {"modify_ldt", __NR_modify_ldt},
4029#endif
4030#endif
4031#ifdef SYS_mount
4032#ifdef __NR_mount
4033 {"mount", __NR_mount},
4034#endif
4035#endif
4036#ifdef SYS_move_pages
4037#ifdef __NR_move_pages
4038 {"move_pages", __NR_move_pages},
4039#endif
4040#endif
4041#ifdef SYS_mprotect
4042#ifdef __NR_mprotect
4043 {"mprotect", __NR_mprotect},
4044#endif
4045#endif
4046#ifdef SYS_mq_getsetattr
4047#ifdef __NR_mq_getsetattr
4048 {"mq_getsetattr", __NR_mq_getsetattr},
4049#endif
4050#endif
4051#ifdef SYS_mq_notify
4052#ifdef __NR_mq_notify
4053 {"mq_notify", __NR_mq_notify},
4054#endif
4055#endif
4056#ifdef SYS_mq_open
4057#ifdef __NR_mq_open
4058 {"mq_open", __NR_mq_open},
4059#endif
4060#endif
4061#ifdef SYS_mq_timedreceive
4062#ifdef __NR_mq_timedreceive
4063 {"mq_timedreceive", __NR_mq_timedreceive},
4064#endif
4065#endif
4066#ifdef SYS_mq_timedsend
4067#ifdef __NR_mq_timedsend
4068 {"mq_timedsend", __NR_mq_timedsend},
4069#endif
4070#endif
4071#ifdef SYS_mq_unlink
4072#ifdef __NR_mq_unlink
4073 {"mq_unlink", __NR_mq_unlink},
4074#endif
4075#endif
4076#ifdef SYS_mremap
4077#ifdef __NR_mremap
4078 {"mremap", __NR_mremap},
4079#endif
4080#endif
4081#ifdef SYS_msgctl
4082#ifdef __NR_msgctl
4083 {"msgctl", __NR_msgctl},
4084#endif
4085#endif
4086#ifdef SYS_msgget
4087#ifdef __NR_msgget
4088 {"msgget", __NR_msgget},
4089#endif
4090#endif
4091#ifdef SYS_msgrcv
4092#ifdef __NR_msgrcv
4093 {"msgrcv", __NR_msgrcv},
4094#endif
4095#endif
4096#ifdef SYS_msgsnd
4097#ifdef __NR_msgsnd
4098 {"msgsnd", __NR_msgsnd},
4099#endif
4100#endif
4101#ifdef SYS_msync
4102#ifdef __NR_msync
4103 {"msync", __NR_msync},
4104#endif
4105#endif
4106#ifdef SYS_munlock
4107#ifdef __NR_munlock
4108 {"munlock", __NR_munlock},
4109#endif
4110#endif
4111#ifdef SYS_munlockall
4112#ifdef __NR_munlockall
4113 {"munlockall", __NR_munlockall},
4114#endif
4115#endif
4116#ifdef SYS_munmap
4117#ifdef __NR_munmap
4118 {"munmap", __NR_munmap},
4119#endif
4120#endif
4121#ifdef SYS_name_to_handle_at
4122#ifdef __NR_name_to_handle_at
4123 {"name_to_handle_at", __NR_name_to_handle_at},
4124#endif
4125#endif
4126#ifdef SYS_nanosleep
4127#ifdef __NR_nanosleep
4128 {"nanosleep", __NR_nanosleep},
4129#endif
4130#endif
4131#ifdef SYS_newfstatat
4132#ifdef __NR_newfstatat
4133 {"newfstatat", __NR_newfstatat},
4134#endif
4135#endif
4136#ifdef SYS_open
4137#ifdef __NR_open
4138 {"open", __NR_open},
4139#endif
4140#endif
4141#ifdef SYS_open_by_handle_at
4142#ifdef __NR_open_by_handle_at
4143 {"open_by_handle_at", __NR_open_by_handle_at},
4144#endif
4145#endif
4146#ifdef SYS_openat
4147#ifdef __NR_openat
4148 {"openat", __NR_openat},
4149#endif
4150#endif
4151#ifdef SYS_pause
4152#ifdef __NR_pause
4153 {"pause", __NR_pause},
4154#endif
4155#endif
4156#ifdef SYS_perf_event_open
4157#ifdef __NR_perf_event_open
4158 {"perf_event_open", __NR_perf_event_open},
4159#endif
4160#endif
4161#ifdef SYS_personality
4162#ifdef __NR_personality
4163 {"personality", __NR_personality},
4164#endif
4165#endif
4166#ifdef SYS_pipe
4167#ifdef __NR_pipe
4168 {"pipe", __NR_pipe},
4169#endif
4170#endif
4171#ifdef SYS_pipe2
4172#ifdef __NR_pipe2
4173 {"pipe2", __NR_pipe2},
4174#endif
4175#endif
4176#ifdef SYS_pivot_root
4177#ifdef __NR_pivot_root
4178 {"pivot_root", __NR_pivot_root},
4179#endif
4180#endif
4181#ifdef SYS_poll
4182#ifdef __NR_poll
4183 {"poll", __NR_poll},
4184#endif
4185#endif
4186#ifdef SYS_ppoll
4187#ifdef __NR_ppoll
4188 {"ppoll", __NR_ppoll},
4189#endif
4190#endif
4191#ifdef SYS_prctl
4192#ifdef __NR_prctl
4193 {"prctl", __NR_prctl},
4194#endif
4195#endif
4196#ifdef SYS_pread64
4197#ifdef __NR_pread64
4198 {"pread64", __NR_pread64},
4199#endif
4200#endif
4201#ifdef SYS_preadv
4202#ifdef __NR_preadv
4203 {"preadv", __NR_preadv},
4204#endif
4205#endif
4206#ifdef SYS_prlimit64
4207#ifdef __NR_prlimit64
4208 {"prlimit64", __NR_prlimit64},
4209#endif
4210#endif
4211#ifdef SYS_process_vm_readv
4212#ifdef __NR_process_vm_readv
4213 {"process_vm_readv", __NR_process_vm_readv},
4214#endif
4215#endif
4216#ifdef SYS_process_vm_writev
4217#ifdef __NR_process_vm_writev
4218 {"process_vm_writev", __NR_process_vm_writev},
4219#endif
4220#endif
4221#ifdef SYS_pselect6
4222#ifdef __NR_pselect6
4223 {"pselect6", __NR_pselect6},
4224#endif
4225#endif
4226#ifdef SYS_ptrace
4227#ifdef __NR_ptrace
4228 {"ptrace", __NR_ptrace},
4229#endif
4230#endif
4231#ifdef SYS_putpmsg
4232#ifdef __NR_putpmsg
4233 {"putpmsg", __NR_putpmsg},
4234#endif
4235#endif
4236#ifdef SYS_pwrite64
4237#ifdef __NR_pwrite64
4238 {"pwrite64", __NR_pwrite64},
4239#endif
4240#endif
4241#ifdef SYS_pwritev
4242#ifdef __NR_pwritev
4243 {"pwritev", __NR_pwritev},
4244#endif
4245#endif
4246#ifdef SYS_quotactl
4247#ifdef __NR_quotactl
4248 {"quotactl", __NR_quotactl},
4249#endif
4250#endif
4251#ifdef SYS_read
4252#ifdef __NR_read
4253 {"read", __NR_read},
4254#endif
4255#endif
4256#ifdef SYS_readahead
4257#ifdef __NR_readahead
4258 {"readahead", __NR_readahead},
4259#endif
4260#endif
4261#ifdef SYS_readlink
4262#ifdef __NR_readlink
4263 {"readlink", __NR_readlink},
4264#endif
4265#endif
4266#ifdef SYS_readlinkat
4267#ifdef __NR_readlinkat
4268 {"readlinkat", __NR_readlinkat},
4269#endif
4270#endif
4271#ifdef SYS_readv
4272#ifdef __NR_readv
4273 {"readv", __NR_readv},
4274#endif
4275#endif
4276#ifdef SYS_reboot
4277#ifdef __NR_reboot
4278 {"reboot", __NR_reboot},
4279#endif
4280#endif
4281#ifdef SYS_recvfrom
4282#ifdef __NR_recvfrom
4283 {"recvfrom", __NR_recvfrom},
4284#endif
4285#endif
4286#ifdef SYS_recvmmsg
4287#ifdef __NR_recvmmsg
4288 {"recvmmsg", __NR_recvmmsg},
4289#endif
4290#endif
4291#ifdef SYS_recvmsg
4292#ifdef __NR_recvmsg
4293 {"recvmsg", __NR_recvmsg},
4294#endif
4295#endif
4296#ifdef SYS_remap_file_pages
4297#ifdef __NR_remap_file_pages
4298 {"remap_file_pages", __NR_remap_file_pages},
4299#endif
4300#endif
4301#ifdef SYS_removexattr
4302#ifdef __NR_removexattr
4303 {"removexattr", __NR_removexattr},
4304#endif
4305#endif
4306#ifdef SYS_rename
4307#ifdef __NR_rename
4308 {"rename", __NR_rename},
4309#endif
4310#endif
4311#ifdef SYS_renameat
4312#ifdef __NR_renameat
4313 {"renameat", __NR_renameat},
4314#endif
4315#endif
4316#ifdef SYS_request_key
4317#ifdef __NR_request_key
4318 {"request_key", __NR_request_key},
4319#endif
4320#endif
4321#ifdef SYS_restart_syscall
4322#ifdef __NR_restart_syscall
4323 {"restart_syscall", __NR_restart_syscall},
4324#endif
4325#endif
4326#ifdef SYS_rmdir
4327#ifdef __NR_rmdir
4328 {"rmdir", __NR_rmdir},
4329#endif
4330#endif
4331#ifdef SYS_rt_sigaction
4332#ifdef __NR_rt_sigaction
4333 {"rt_sigaction", __NR_rt_sigaction},
4334#endif
4335#endif
4336#ifdef SYS_rt_sigpending
4337#ifdef __NR_rt_sigpending
4338 {"rt_sigpending", __NR_rt_sigpending},
4339#endif
4340#endif
4341#ifdef SYS_rt_sigprocmask
4342#ifdef __NR_rt_sigprocmask
4343 {"rt_sigprocmask", __NR_rt_sigprocmask},
4344#endif
4345#endif
4346#ifdef SYS_rt_sigqueueinfo
4347#ifdef __NR_rt_sigqueueinfo
4348 {"rt_sigqueueinfo", __NR_rt_sigqueueinfo},
4349#endif
4350#endif
4351#ifdef SYS_rt_sigreturn
4352#ifdef __NR_rt_sigreturn
4353 {"rt_sigreturn", __NR_rt_sigreturn},
4354#endif
4355#endif
4356#ifdef SYS_rt_sigsuspend
4357#ifdef __NR_rt_sigsuspend
4358 {"rt_sigsuspend", __NR_rt_sigsuspend},
4359#endif
4360#endif
4361#ifdef SYS_rt_sigtimedwait
4362#ifdef __NR_rt_sigtimedwait
4363 {"rt_sigtimedwait", __NR_rt_sigtimedwait},
4364#endif
4365#endif
4366#ifdef SYS_rt_tgsigqueueinfo
4367#ifdef __NR_rt_tgsigqueueinfo
4368 {"rt_tgsigqueueinfo", __NR_rt_tgsigqueueinfo},
4369#endif
4370#endif
4371#ifdef SYS_sched_get_priority_max
4372#ifdef __NR_sched_get_priority_max
4373 {"sched_get_priority_max", __NR_sched_get_priority_max},
4374#endif
4375#endif
4376#ifdef SYS_sched_get_priority_min
4377#ifdef __NR_sched_get_priority_min
4378 {"sched_get_priority_min", __NR_sched_get_priority_min},
4379#endif
4380#endif
4381#ifdef SYS_sched_getaffinity
4382#ifdef __NR_sched_getaffinity
4383 {"sched_getaffinity", __NR_sched_getaffinity},
4384#endif
4385#endif
4386#ifdef SYS_sched_getparam
4387#ifdef __NR_sched_getparam
4388 {"sched_getparam", __NR_sched_getparam},
4389#endif
4390#endif
4391#ifdef SYS_sched_getscheduler
4392#ifdef __NR_sched_getscheduler
4393 {"sched_getscheduler", __NR_sched_getscheduler},
4394#endif
4395#endif
4396#ifdef SYS_sched_rr_get_interval
4397#ifdef __NR_sched_rr_get_interval
4398 {"sched_rr_get_interval", __NR_sched_rr_get_interval},
4399#endif
4400#endif
4401#ifdef SYS_sched_setaffinity
4402#ifdef __NR_sched_setaffinity
4403 {"sched_setaffinity", __NR_sched_setaffinity},
4404#endif
4405#endif
4406#ifdef SYS_sched_setparam
4407#ifdef __NR_sched_setparam
4408 {"sched_setparam", __NR_sched_setparam},
4409#endif
4410#endif
4411#ifdef SYS_sched_setscheduler
4412#ifdef __NR_sched_setscheduler
4413 {"sched_setscheduler", __NR_sched_setscheduler},
4414#endif
4415#endif
4416#ifdef SYS_sched_yield
4417#ifdef __NR_sched_yield
4418 {"sched_yield", __NR_sched_yield},
4419#endif
4420#endif
4421#ifdef SYS_security
4422#ifdef __NR_security
4423 {"security", __NR_security},
4424#endif
4425#endif
4426#ifdef SYS_select
4427#ifdef __NR_select
4428 {"select", __NR_select},
4429#endif
4430#endif
4431#ifdef SYS_semctl
4432#ifdef __NR_semctl
4433 {"semctl", __NR_semctl},
4434#endif
4435#endif
4436#ifdef SYS_semget
4437#ifdef __NR_semget
4438 {"semget", __NR_semget},
4439#endif
4440#endif
4441#ifdef SYS_semop
4442#ifdef __NR_semop
4443 {"semop", __NR_semop},
4444#endif
4445#endif
4446#ifdef SYS_semtimedop
4447#ifdef __NR_semtimedop
4448 {"semtimedop", __NR_semtimedop},
4449#endif
4450#endif
4451#ifdef SYS_sendfile
4452#ifdef __NR_sendfile
4453 {"sendfile", __NR_sendfile},
4454#endif
4455#endif
4456#ifdef SYS_sendmmsg
4457#ifdef __NR_sendmmsg
4458 {"sendmmsg", __NR_sendmmsg},
4459#endif
4460#endif
4461#ifdef SYS_sendmsg
4462#ifdef __NR_sendmsg
4463 {"sendmsg", __NR_sendmsg},
4464#endif
4465#endif
4466#ifdef SYS_sendto
4467#ifdef __NR_sendto
4468 {"sendto", __NR_sendto},
4469#endif
4470#endif
4471#ifdef SYS_set_mempolicy
4472#ifdef __NR_set_mempolicy
4473 {"set_mempolicy", __NR_set_mempolicy},
4474#endif
4475#endif
4476#ifdef SYS_set_robust_list
4477#ifdef __NR_set_robust_list
4478 {"set_robust_list", __NR_set_robust_list},
4479#endif
4480#endif
4481#ifdef SYS_set_tid_address
4482#ifdef __NR_set_tid_address
4483 {"set_tid_address", __NR_set_tid_address},
4484#endif
4485#endif
4486#ifdef SYS_setdomainname
4487#ifdef __NR_setdomainname
4488 {"setdomainname", __NR_setdomainname},
4489#endif
4490#endif
4491#ifdef SYS_setfsgid
4492#ifdef __NR_setfsgid
4493 {"setfsgid", __NR_setfsgid},
4494#endif
4495#endif
4496#ifdef SYS_setfsuid
4497#ifdef __NR_setfsuid
4498 {"setfsuid", __NR_setfsuid},
4499#endif
4500#endif
4501#ifdef SYS_setgid
4502#ifdef __NR_setgid
4503 {"setgid", __NR_setgid},
4504#endif
4505#endif
4506#ifdef SYS_setgroups
4507#ifdef __NR_setgroups
4508 {"setgroups", __NR_setgroups},
4509#endif
4510#endif
4511#ifdef SYS_sethostname
4512#ifdef __NR_sethostname
4513 {"sethostname", __NR_sethostname},
4514#endif
4515#endif
4516#ifdef SYS_setitimer
4517#ifdef __NR_setitimer
4518 {"setitimer", __NR_setitimer},
4519#endif
4520#endif
4521#ifdef SYS_setns
4522#ifdef __NR_setns
4523 {"setns", __NR_setns},
4524#endif
4525#endif
4526#ifdef SYS_setpgid
4527#ifdef __NR_setpgid
4528 {"setpgid", __NR_setpgid},
4529#endif
4530#endif
4531#ifdef SYS_setpriority
4532#ifdef __NR_setpriority
4533 {"setpriority", __NR_setpriority},
4534#endif
4535#endif
4536#ifdef SYS_setregid
4537#ifdef __NR_setregid
4538 {"setregid", __NR_setregid},
4539#endif
4540#endif
4541#ifdef SYS_setresgid
4542#ifdef __NR_setresgid
4543 {"setresgid", __NR_setresgid},
4544#endif
4545#endif
4546#ifdef SYS_setresuid
4547#ifdef __NR_setresuid
4548 {"setresuid", __NR_setresuid},
4549#endif
4550#endif
4551#ifdef SYS_setreuid
4552#ifdef __NR_setreuid
4553 {"setreuid", __NR_setreuid},
4554#endif
4555#endif
4556#ifdef SYS_setrlimit
4557#ifdef __NR_setrlimit
4558 {"setrlimit", __NR_setrlimit},
4559#endif
4560#endif
4561#ifdef SYS_setsid
4562#ifdef __NR_setsid
4563 {"setsid", __NR_setsid},
4564#endif
4565#endif
4566#ifdef SYS_setsockopt
4567#ifdef __NR_setsockopt
4568 {"setsockopt", __NR_setsockopt},
4569#endif
4570#endif
4571#ifdef SYS_settimeofday
4572#ifdef __NR_settimeofday
4573 {"settimeofday", __NR_settimeofday},
4574#endif
4575#endif
4576#ifdef SYS_setuid
4577#ifdef __NR_setuid
4578 {"setuid", __NR_setuid},
4579#endif
4580#endif
4581#ifdef SYS_setxattr
4582#ifdef __NR_setxattr
4583 {"setxattr", __NR_setxattr},
4584#endif
4585#endif
4586#ifdef SYS_shmat
4587#ifdef __NR_shmat
4588 {"shmat", __NR_shmat},
4589#endif
4590#endif
4591#ifdef SYS_shmctl
4592#ifdef __NR_shmctl
4593 {"shmctl", __NR_shmctl},
4594#endif
4595#endif
4596#ifdef SYS_shmdt
4597#ifdef __NR_shmdt
4598 {"shmdt", __NR_shmdt},
4599#endif
4600#endif
4601#ifdef SYS_shmget
4602#ifdef __NR_shmget
4603 {"shmget", __NR_shmget},
4604#endif
4605#endif
4606#ifdef SYS_shutdown
4607#ifdef __NR_shutdown
4608 {"shutdown", __NR_shutdown},
4609#endif
4610#endif
4611#ifdef SYS_sigaltstack
4612#ifdef __NR_sigaltstack
4613 {"sigaltstack", __NR_sigaltstack},
4614#endif
4615#endif
4616#ifdef SYS_signalfd
4617#ifdef __NR_signalfd
4618 {"signalfd", __NR_signalfd},
4619#endif
4620#endif
4621#ifdef SYS_signalfd4
4622#ifdef __NR_signalfd4
4623 {"signalfd4", __NR_signalfd4},
4624#endif
4625#endif
4626#ifdef SYS_socket
4627#ifdef __NR_socket
4628 {"socket", __NR_socket},
4629#endif
4630#endif
4631#ifdef SYS_socketpair
4632#ifdef __NR_socketpair
4633 {"socketpair", __NR_socketpair},
4634#endif
4635#endif
4636#ifdef SYS_splice
4637#ifdef __NR_splice
4638 {"splice", __NR_splice},
4639#endif
4640#endif
4641#ifdef SYS_stat
4642#ifdef __NR_stat
4643 {"stat", __NR_stat},
4644#endif
4645#endif
4646#ifdef SYS_statfs
4647#ifdef __NR_statfs
4648 {"statfs", __NR_statfs},
4649#endif
4650#endif
4651#ifdef SYS_swapoff
4652#ifdef __NR_swapoff
4653 {"swapoff", __NR_swapoff},
4654#endif
4655#endif
4656#ifdef SYS_swapon
4657#ifdef __NR_swapon
4658 {"swapon", __NR_swapon},
4659#endif
4660#endif
4661#ifdef SYS_symlink
4662#ifdef __NR_symlink
4663 {"symlink", __NR_symlink},
4664#endif
4665#endif
4666#ifdef SYS_symlinkat
4667#ifdef __NR_symlinkat
4668 {"symlinkat", __NR_symlinkat},
4669#endif
4670#endif
4671#ifdef SYS_sync
4672#ifdef __NR_sync
4673 {"sync", __NR_sync},
4674#endif
4675#endif
4676#ifdef SYS_sync_file_range
4677#ifdef __NR_sync_file_range
4678 {"sync_file_range", __NR_sync_file_range},
4679#endif
4680#endif
4681#ifdef SYS_syncfs
4682#ifdef __NR_syncfs
4683 {"syncfs", __NR_syncfs},
4684#endif
4685#endif
4686#ifdef SYS_sysfs
4687#ifdef __NR_sysfs
4688 {"sysfs", __NR_sysfs},
4689#endif
4690#endif
4691#ifdef SYS_sysinfo
4692#ifdef __NR_sysinfo
4693 {"sysinfo", __NR_sysinfo},
4694#endif
4695#endif
4696#ifdef SYS_syslog
4697#ifdef __NR_syslog
4698 {"syslog", __NR_syslog},
4699#endif
4700#endif
4701#ifdef SYS_tee
4702#ifdef __NR_tee
4703 {"tee", __NR_tee},
4704#endif
4705#endif
4706#ifdef SYS_tgkill
4707#ifdef __NR_tgkill
4708 {"tgkill", __NR_tgkill},
4709#endif
4710#endif
4711#ifdef SYS_time
4712#ifdef __NR_time
4713 {"time", __NR_time},
4714#endif
4715#endif
4716#ifdef SYS_timer_create
4717#ifdef __NR_timer_create
4718 {"timer_create", __NR_timer_create},
4719#endif
4720#endif
4721#ifdef SYS_timer_delete
4722#ifdef __NR_timer_delete
4723 {"timer_delete", __NR_timer_delete},
4724#endif
4725#endif
4726#ifdef SYS_timer_getoverrun
4727#ifdef __NR_timer_getoverrun
4728 {"timer_getoverrun", __NR_timer_getoverrun},
4729#endif
4730#endif
4731#ifdef SYS_timer_gettime
4732#ifdef __NR_timer_gettime
4733 {"timer_gettime", __NR_timer_gettime},
4734#endif
4735#endif
4736#ifdef SYS_timer_settime
4737#ifdef __NR_timer_settime
4738 {"timer_settime", __NR_timer_settime},
4739#endif
4740#endif
4741#ifdef SYS_timerfd_create
4742#ifdef __NR_timerfd_create
4743 {"timerfd_create", __NR_timerfd_create},
4744#endif
4745#endif
4746#ifdef SYS_timerfd_gettime
4747#ifdef __NR_timerfd_gettime
4748 {"timerfd_gettime", __NR_timerfd_gettime},
4749#endif
4750#endif
4751#ifdef SYS_timerfd_settime
4752#ifdef __NR_timerfd_settime
4753 {"timerfd_settime", __NR_timerfd_settime},
4754#endif
4755#endif
4756#ifdef SYS_times
4757#ifdef __NR_times
4758 {"times", __NR_times},
4759#endif
4760#endif
4761#ifdef SYS_tkill
4762#ifdef __NR_tkill
4763 {"tkill", __NR_tkill},
4764#endif
4765#endif
4766#ifdef SYS_truncate
4767#ifdef __NR_truncate
4768 {"truncate", __NR_truncate},
4769#endif
4770#endif
4771#ifdef SYS_tuxcall
4772#ifdef __NR_tuxcall
4773 {"tuxcall", __NR_tuxcall},
4774#endif
4775#endif
4776#ifdef SYS_umask
4777#ifdef __NR_umask
4778 {"umask", __NR_umask},
4779#endif
4780#endif
4781#ifdef SYS_umount2
4782#ifdef __NR_umount2
4783 {"umount2", __NR_umount2},
4784#endif
4785#endif
4786#ifdef SYS_uname
4787#ifdef __NR_uname
4788 {"uname", __NR_uname},
4789#endif
4790#endif
4791#ifdef SYS_unlink
4792#ifdef __NR_unlink
4793 {"unlink", __NR_unlink},
4794#endif
4795#endif
4796#ifdef SYS_unlinkat
4797#ifdef __NR_unlinkat
4798 {"unlinkat", __NR_unlinkat},
4799#endif
4800#endif
4801#ifdef SYS_unshare
4802#ifdef __NR_unshare
4803 {"unshare", __NR_unshare},
4804#endif
4805#endif
4806#ifdef SYS_ustat
4807#ifdef __NR_ustat
4808 {"ustat", __NR_ustat},
4809#endif
4810#endif
4811#ifdef SYS_utime
4812#ifdef __NR_utime
4813 {"utime", __NR_utime},
4814#endif
4815#endif
4816#ifdef SYS_utimensat
4817#ifdef __NR_utimensat
4818 {"utimensat", __NR_utimensat},
4819#endif
4820#endif
4821#ifdef SYS_utimes
4822#ifdef __NR_utimes
4823 {"utimes", __NR_utimes},
4824#endif
4825#endif
4826#ifdef SYS_vfork
4827#ifdef __NR_vfork
4828 {"vfork", __NR_vfork},
4829#endif
4830#endif
4831#ifdef SYS_vhangup
4832#ifdef __NR_vhangup
4833 {"vhangup", __NR_vhangup},
4834#endif
4835#endif
4836#ifdef SYS_vmsplice
4837#ifdef __NR_vmsplice
4838 {"vmsplice", __NR_vmsplice},
4839#endif
4840#endif
4841#ifdef SYS_wait4
4842#ifdef __NR_wait4
4843 {"wait4", __NR_wait4},
4844#endif
4845#endif
4846#ifdef SYS_waitid
4847#ifdef __NR_waitid
4848 {"waitid", __NR_waitid},
4849#endif
4850#endif
4851#ifdef SYS_write
4852#ifdef __NR_write
4853 {"write", __NR_write},
4854#endif
4855#endif
4856#ifdef SYS_writev
4857#ifdef __NR_writev
4858 {"writev", __NR_writev},
4859#endif
4860#endif
4861#endif
4862
4863//
4864// end of generated code
4865//
4866}; // end of syslist
4867
4868const char *syscall_find_nr(int nr) {
4869 int i;
4870 int elems = sizeof(syslist) / sizeof(syslist[0]);
4871 for (i = 0; i < elems; i++) {
4872 if (nr == syslist[i].nr)
4873 return syslist[i].name;
4874 }
4875
4876 return "unknown";
4877}
4878
4879// return -1 if error, or syscall number
4880static int syscall_find_name(const char *name) {
4881 int i;
4882 int elems = sizeof(syslist) / sizeof(syslist[0]);
4883 for (i = 0; i < elems; i++) {
4884 if (strcmp(name, syslist[i].name) == 0)
4885 return syslist[i].nr;
4886 }
4887
4888 return -1;
4889}
4890
4891// return 1 if error, 0 if OK
4892int syscall_check_list(const char *slist, void (*callback)(int)) {
4893 // don't allow empty lists
4894 if (slist == NULL || *slist == '\0') {
4895 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
4896 return -1;
4897 }
4898
4899 // work on a copy of the string
4900 char *str = strdup(slist);
4901 if (!str)
4902 errExit("strdup");
4903
4904 char *ptr = str;
4905 char *start = str;
4906 while (*ptr != '\0') {
4907 if (islower(*ptr) || isdigit(*ptr) || *ptr == '_')
4908 ;
4909 else if (*ptr == ',') {
4910 *ptr = '\0';
4911 int nr = syscall_find_name(start);
4912 if (nr == -1)
4913 fprintf(stderr, "Warning: syscall %s not found\n", start);
4914 else if (callback != NULL)
4915 callback(nr);
4916
4917 start = ptr + 1;
4918 }
4919 ptr++;
4920 }
4921 if (*start != '\0') {
4922 int nr = syscall_find_name(start);
4923 if (nr == -1)
4924 fprintf(stderr, "Warning: syscall %s not found\n", start);
4925 else if (callback != NULL)
4926 callback(nr);
4927 }
4928
4929 free(str);
4930 return 0;
4931}
4932
4933void syscall_print(void) {
4934 int i;
4935 int elems = sizeof(syslist) / sizeof(syslist[0]);
4936 for (i = 0; i < elems; i++) {
4937 printf("%d\t- %s\n", syslist[i].nr, syslist[i].name);
4938 }
4939 printf("\n");
4940}
4941
4942#endif // HAVE_SECCOMP
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
new file mode 100644
index 000000000..71ae203ff
--- /dev/null
+++ b/src/firejail/usage.c
@@ -0,0 +1,312 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firejail.h"
21
22void usage(void) {
23 printf("firejail - version %s\n\n", VERSION);
24 printf("Firejail is a SUID sandbox program that reduces the risk of security breaches by\n");
25 printf("restricting the running environment of untrusted applications using Linux\n");
26 printf("namespaces. It includes a sandbox profile for Mozilla Firefox.\n\n");
27 printf("\n");
28 printf("Usage: firejail [options] [program and arguments]\n\n");
29 printf("\n");
30 printf("Without any options, the sandbox consists of a filesystem chroot build from the\n");
31 printf("current system directories mounted read-only, and new PID and IPC\n");
32 printf("namespaces. If no program is specified as an argument, /bin/bash is started by\n");
33 printf("default in the sandbox.\n\n");
34 printf("\n");
35 printf("Options:\n\n");
36 printf("\t-- - signal the end of options and disables further option processing.\n\n");
37 printf("\t--bandwidth=name - set bandwidth limits for the sandbox identified\n");
38 printf("\t\tby name, see Traffic Shaping section for more details.\n\n");
39 printf("\t--bandwidth=pid - set bandwidth limits for the sandbox identified\n");
40 printf("\t\tby PID, see Traffic Shaping section for more details.\n\n");
41#ifdef HAVE_BIND
42 printf("\t--bind=dirname1,dirname2 - mount-bind dirname1 on top of dirname2.\n\n");
43 printf("\t--bind=filename1,dirname2 - mount-bind filename1 on top of filename2.\n\n");
44#endif
45 printf("\t--blacklist=dirname_or_filename - blacklist directory or file.\n\n");
46 printf("\t-c - execute command and exit.\n\n");
47 printf("\t--caps - enable default Linux capabilities filter. The filter disables\n");
48 printf("\t\tCAP_SYS_MODULE, CAP_SYS_RAWIO, CAP_SYS_BOOT, CAP_SYS_NICE,\n");
49 printf("\t\tCAP_SYS_TTY_CONFIG, CAP_SYSLOG, CAP_MKNOD, CAP_SYS_ADMIN.\n\n");
50 printf("\t--caps.drop=all - drop all capabilities.\n\n");
51 printf("\t--caps.drop=capability,capability,capability - blacklist Linux\n");
52 printf("\t\tcapabilities filter.\n\n");
53 printf("\t--caps.keep=capability,capability,capability - whitelist Linux\n");
54 printf("\t\tcapabilities filter.\n\n");
55 printf("\t--caps.print=name - print the caps filter for the sandbox identified\n");
56 printf("\t\tby name.\n\n");
57 printf("\t--caps.print=pid - print the caps filter for the sandbox identified\n");
58 printf("\t\tby PID.\n\n");
59 printf("\t--cgroup=tasks-file - place the sandbox in the specified control group.\n");
60 printf("\t\ttasks-file is the full path of cgroup tasks file.\n");
61 printf("\t\tExample: --cgroup=/sys/fs/cgroup/g1/tasks\n\n");
62#ifdef HAVE_CHROOT
63 printf("\t--chroot=dirname - chroot into dirname directory.\n\n");
64#endif
65 printf("\t--cpu=cpu-number,cpu-number - set cpu affinity.\n");
66 printf("\t\tExample: cpu=0,1,2\n\n");
67 printf("\t--csh - use /bin/csh as default shell.\n\n");
68 printf("\t--debug - print sandbox debug messages.\n\n");
69 printf("\t--debug-syscalls - print all recognized system calls in the current\n");
70 printf("\t\tFirejail software build and exit.\n\n");
71 printf("\t--debug-caps - print all recognized capabilities in the current\n");
72 printf("\t\tFirejail software build and exit.\n\n");
73 printf("\t--defaultgw=address - use this address as default gateway in the new\n");
74 printf("\t\tnetwork namespace.\n\n");
75 printf("\t--dns=address - set a DNS server for the sandbox. Up to three DNS\n");
76 printf("\t\tservers can be defined.\n\n");
77 printf("\t--dns.print=name - print DNS configuration for the sandbox identified\n");
78 printf("\t\tby name.\n\n");
79 printf("\t--dns.print=pid - print DNS configuration of the sandbox identified.\n");
80 printf("\t\tby PID.\n\n");
81 printf("\t--help, -? - this help screen.\n\n");
82 printf("\t--ip=address - set interface IP address.\n\n");
83 printf("\t--ip=none - no IP address and no default gateway address are configured\n");
84 printf("\t\tin the new network namespace. Use this option in case you intend\n");
85 printf("\t\tto start an external DHCP client in the sandbox.\n\n");
86 printf("\t--iprange=address,address - configure an IP address in this range\n\n");
87 printf("\t--ipc-namespace - enable a new IPC namespace if the sandbox was started\n");
88 printf("\t\tas a regular user. IPC namespace is enabled by default only if\n");
89 printf("\t\tthe sandbox is started as root.\n\n");
90 printf("\t--join=name - join the sandbox identified by name.\n\n");
91 printf("\t--join=pid - join the sandbox identified by PID.\n\n");
92 printf("\t--list - list all sandboxes.\n\n");
93 printf("\t--mac=xx:xx:xx:xx:xx:xx - set interface MAC address.\n\n");
94 printf("\t--name=name - set sandbox hostname.\n\n");
95 printf("\t--net=bridgename - enable network namespaces and connect to this bridge\n");
96 printf("\t\tdevice. Unless specified with option --ip and --defaultgw, an\n");
97 printf("\t\tIP address and a default gateway will be assigned automatically\n");
98 printf("\t\tto the sandbox. The IP address is checked using ARP before\n");
99 printf("\t\tassignment. The IP address assigned as default gateway is the\n");
100 printf("\t\tbridge device IP address. Up to four --net devices can\n");
101 printf("\t\tbe defined. Mixing bridge and macvlan devices is allowed.\n\n");
102 printf("\t--net=ethernet_interface - enable network namespaces and connect\n");
103 printf("\t\tto this ethernet_interface using the standard Linux macvlan\n");
104 printf("\t\tdriver. Unless specified with option --ip and --defaultgw, an\n");
105 printf("\t\tIP address and a default gateway will be assigned automatically\n");
106 printf("\t\tto the sandbox. The IP address is checked using ARP before\n");
107 printf("\t\tassignment. The IP address assigned as default gateway is the\n");
108 printf("\t\tdefault gateway of the host. Up to four --net devices can\n");
109 printf("\t\tbe defined. Mixing bridge and macvlan devices is allowed.\n\n");
110 printf("\t--net=none - enable a new, unconnected network namespace.\n\n");
111
112 printf("\t--netfilter - enable the default client network filter in the new\n");
113 printf("\t\tnetwork namespace:\n\n");
114 printf("\t\t*filter\n");
115 printf("\t\t:INPUT DROP [0:0]\n");
116 printf("\t\t:FORWARD DROP [0:0]\n");
117 printf("\t\t:OUTPUT ACCEPT [0:0]\n");
118 printf("\t\t-A INPUT -i lo -j ACCEPT\n");
119 printf("\t\t-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n");
120 printf("\t\t-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT\n");
121 printf("\t\t-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT\n");
122 printf("\t\t-A INPUT -p icmp --icmp-type echo-request -j ACCEPT \n");
123 printf("\t\tCOMMIT\n\n");
124 printf("\t--netfilter=filename - enable the network filter specified by\n");
125 printf("\t\tfilename in the new network namespace. The filter file format\n");
126 printf("\t\tis the format of iptables-save and iptable-restore commands.\n\n");
127
128 printf("\t--netstats - monitor network statistics for sandboxes creating a new\n");
129 printf("\t\tnetwork namespace.\n\n");
130 printf("\t--nogroups - disable supplementary groups. Without this option,\n");
131 printf("\t\tsupplementary groups are enabled for the user starting the\n");
132 printf("\t\tsandbox. For root user supplementary groups are always\n");
133 printf("\t\tdisabled.\n\n");
134
135 printf("\t--noroot - install a user namespace with a single user - the current\n");
136 printf("\t\tuser. root user does not exist in the new namespace. This option\n");
137 printf("\t\tis not supported for --chroot and --overlay configurations.\n\n");
138
139 printf("\t--output=logfile - stdout logging and log rotation. Copy stdout to\n");
140 printf("\t\tlogfile, and keep the size of the file under 500KB using log\n");
141 printf("\t\trotation. Five files with prefixes .1 to .5 are used in\n");
142 printf("\t\trotation.\n\n");
143 printf("\t--overlay - mount a filesystem overlay on top of the current filesystem.\n");
144 printf("\t\t(OverlayFS support is required in Linux kernel for this option\n");
145 printf("\t\tto work)\n\n");
146
147 printf("\t--private - mount new /root and /home/user directories in temporary\n");
148 printf("\t\tfilesystems. All modifications are discarded when the sandbox is\n");
149 printf("\t\tclosed.\n\n");
150 printf("\t--private=directory - use directory as user home.\n\n");
151 printf("\t--private.keep=file,directory - build a new user home in a temporary\n");
152 printf("\t\tfilesystem, and copy the files and directories in the list in\n");
153 printf("\t\tthe new home. All modifications are discarded when the sandbox\n");
154 printf("\t\tis closed.\n\n");
155 printf("\t--private-dev - create a new /dev directory. Only null, full, zero, tty,\n");
156 printf("\t\tpst, ptms, random, urandom and shm devices are available.\n\n");
157
158 printf("\t--profile=filename - use a custom profile.\n\n");
159 printf("\t--read-only=dirname_or_filename - set directory or file read-only.\n\n");
160 printf("\t--rlimit-fsize=number - set the maximum file size that can be created\n");
161 printf("\t\tby a process.\n\n");
162 printf("\t--rlimit-nofile=number - set the maximum number of files that can be\n");
163 printf("\t\topened by a process.\n\n");
164 printf("\t--rlimit-nproc=number - set the maximum number of processes that can be\n");
165 printf("\t\tcreated for the real user ID of the calling process.\n\n");
166 printf("\t--rlimit-sigpending=number - set the maximum number of pending signals\n");
167 printf("\t\tfor a process.\n\n");
168
169 printf("\t--scan - ARP-scan all the networks from inside a network namespace.\n");
170 printf("\t\tThis makes it possible to detect macvlan kernel device drivers\n");
171 printf("\t\trunning on the current host.\n\n");
172
173#ifdef HAVE_SECCOMP
174 printf("\t--seccomp - enable seccomp filter and blacklist the syscalls in the\n");
175 printf("\t\tlist. The default list is as follows: mount, umount2,\n");
176 printf("\t\tptrace, kexec_load, open_by_handle_at, init_module,\n");
177 printf("\t\tfinit_module, delete_module, iopl, ioperm, swapon, swapoff,\n");
178 printf("\t\tmknode, syslog, process_vm_readv and process_vm_writev\n");
179 printf("\t\tsysfs,_sysctl, adjtimex, clock_adjtime, lookup_dcookie,\n");
180 printf("\t\tperf_event_open, fanotify_init and kcmp.\n\n");
181
182 printf("\t--seccomp=syscall,syscall,syscall - enable seccomp filter, blacklist the\n");
183 printf("\t\tdefault syscall list and the syscalls specified by the command.\n\n");
184
185 printf("\t--seccomp.drop=syscall,syscall,syscall - enable seccomp filter, and\n");
186 printf("\t\tblacklist the syscalls specified by the command.\n\n");
187
188 printf("\t--seccomp.keep=syscall,syscall,syscall - enable seccomp filter, and\n");
189 printf("\t\twhitelist the syscalls specified by the command.\n\n");
190
191 printf("\t--seccomp.print=name - print the seccomp filter for the sandbox\n");
192 printf("\t\tidentified by name.\n\n");
193 printf("\t--seccomp.print=pid - print the seccomp filter for the sandbox\n");
194 printf("\t\tidentified by PID.\n\n");
195#endif
196
197 printf("\t--shell=none - run the program directly without a user shell.\n\n");
198 printf("\t--shell=program - set default user shell.\n\n");
199 printf("\t--shutdown=name - shutdown the sandbox identified by name.\n\n");
200 printf("\t--shutdown=pid - shutdown the sandbox identified by PID.\n\n");
201 printf("\t--tmpfs=dirname - mount a tmpfs filesystem on directory dirname.\n\n");
202 printf("\t--top - monitor the most CPU-intensive sandboxes.\n\n");
203 printf("\t--trace - trace open, access and connect system calls.\n\n");
204 printf("\t--tree - print a tree of all sandboxed processes.\n\n");
205 printf("\t--version - print program version and exit.\n\n");
206 printf("\t--zsh - use /usr/bin/zsh as default shell.\n\n");
207 printf("\n");
208 printf("\n");
209
210
211 printf("Traffic Shaping\n\n");
212
213 printf("Network bandwidth is an expensive resource shared among all sandboxes\n");
214 printf("running on a system. Traffic shaping allows the user to increase network\n");
215 printf("performance by controlling the amount of data that flows into and out of the\n");
216 printf("sandboxes. Firejail implements a simple rate-limiting shaper based on Linux\n");
217 printf("command tc. The shaper works at sandbox level, and can be used only for\n");
218 printf("sandboxes configured with new network namespaces.\n\n");
219
220 printf("Set rate-limits:\n");
221 printf("\tfirejail --bandwidth={name|pid} set network-name down-speed up-speed\n\n");
222 printf("Clear rate-limits:\n");
223 printf("\tfirejail --bandwidth={name|pid} clear network-name\n\n");
224 printf("Status:\n");
225 printf("\tfirejail --bandwidth={name|pid} status\n\n");
226 printf("where:\n");
227 printf("\tname - sandbox name\n");
228 printf("\tpid - sandbox pid\n");
229 printf("\tnetwork-name - network name as used by --net option\n");
230 printf("\tdown-speed - download speed in KB/s (decimal kilobyte per second)\n");
231 printf("\tup-speed - upload speed in KB/s (decimal kilobyte per second)\n");
232 printf("\n");
233 printf("Example:\n");
234 printf("\t$ firejail --name=mybrowser --net=eth0 firefox &\n");
235 printf("\t$ firejail --bandwidth=mybrowser set eth0 80 20\n");
236 printf("\t$ firejail --bandwidth=mybrowser status\n");
237 printf("\t$ firejail --bandwidth=mybrowser clear eth0\n");
238 printf("\n");
239 printf("\n");
240
241
242
243 printf("Monitoring\n\n");
244
245 printf("Option --list prints a list of all sandboxes. The format for each entry is as\n");
246 printf("follows:\n\n");
247 printf("\tPID:USER:Command\n\n");
248
249 printf("Option --tree prints the tree of processes running in the sandbox. The format\n");
250 printf("for each process entry is as follows:\n\n");
251 printf("\tPID:USER:Command\n\n");
252
253 printf("Option --top is similar to the UNIX top command, however it applies only to\n");
254 printf("sandboxes. Listed below are the available fields (columns) in alphabetical\n");
255 printf("order:\n\n");
256 printf("\tCommand - command used to start the sandbox.\n");
257 printf("\tCPU%% - CPU usage, the sandbox share of the elapsed CPU time since the\n");
258 printf("\t last screen update\n");
259 printf("\tPID - Unique process ID for the task controlling the sandbox.\n");
260 printf("\tPrcs - number of processes running in sandbox, including the controlling\n");
261 printf("\t process.\n");
262 printf("\tRES - Resident Memory Size (KiB), sandbox non-swapped physical memory.\n");
263 printf("\t It is a sum of the RES values for all processes running in the\n");
264 printf("\t sandbox.\n");
265 printf("\tSHR - Shared Memory Size (KiB), it reflects memory shared with other\n");
266 printf("\t processes. It is a sum of the SHR values for all processes running\n");
267 printf("\t in the sandbox, including the controlling process.\n");
268 printf("\tUptime - sandbox running time in hours:minutes:seconds format.\n");
269 printf("\tUser - The owner of the sandbox.\n");
270 printf("\n");
271 printf("\n");
272 printf("Profile files\n\n");
273 printf("Several command line configuration options can be passed to the program using\n");
274 printf("profile files. Default Firejail profile files are stored in /etc/firejail\n");
275 printf("directory, user profile files are stored in ~/.config/firejail directory. See\n");
276 printf("man 5 firejail-profile for more information.\n\n");
277 printf("\n");
278 printf("Restricted shell\n\n");
279 printf("To configure a restricted shell, replace /bin/bash with /usr/bin/firejail i\n");
280 printf("/etc/password file for each user that needs to be restricted.\n");
281 printf("Alternatively, you can specify /usr/bin/firejail in adduser command:\n\n");
282 printf(" adduser --shell /usr/bin/firejail username\n\n");
283 printf("Arguments to be passed to firejail executable upon login are declared in\n");
284 printf("/etc/firejail/login.users file.\n\n");
285 printf("\n");
286 printf("Examples:\n\n");
287 printf(" $ firejail\n");
288 printf(" start a regular /bin/bash session in sandbox\n");
289 printf(" $ firejail firefox\n");
290 printf(" start Mozilla Firefox\n");
291 printf(" $ firejail --seccomp firefox\n");
292 printf(" start Mozilla Firefox in a seccomp sandbox\n");
293 printf(" $ firejail --caps firefox\n");
294 printf(" start Mozilla Firefox in a Linux capabilities sandbox\n");
295 printf(" $ firejail --debug firefox\n");
296 printf(" debug Firefox sandbox\n");
297 printf(" $ firejail --private\n");
298 printf(" start a /bin/bash session with a new tmpfs home directory\n");
299 printf(" $ firejail --net=br0 ip=10.10.20.10\n");
300 printf(" start a /bin/bash session in a new network namespace; the session is\n");
301 printf(" connected to the main network using br0 bridge device, an IP address\n");
302 printf(" of 10.10.20.10 is assigned to the sandbox\n");
303 printf(" $ firejail --net=br0 --net=br1 --net=br2\n");
304 printf(" start a /bin/bash session in a new network namespace and connect it\n");
305 printf(" to br0, br1, and br2 host bridge devices\n");
306 printf(" $ firejail --list\n");
307 printf(" list all running sandboxes\n");
308 printf("\n");
309 printf("License GPL version 2 or later\n");
310 printf("Homepage: http://firejail.sourceforge.net\n");
311 printf("\n");
312}
diff --git a/src/firejail/util.c b/src/firejail/util.c
new file mode 100644
index 000000000..2c50caf17
--- /dev/null
+++ b/src/firejail/util.c
@@ -0,0 +1,480 @@
1/*
2 * Copyright (C) 2014, 2015 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20#include "firejail.h"
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <syslog.h>
24#include <errno.h>
25#include <dirent.h>
26#include <grp.h>
27
28#define MAX_GROUPS 1024
29// drop privileges
30// - for root group or if nogroups is set, supplementary groups are not configured
31void drop_privs(int nogroups) {
32 gid_t gid = getgid();
33
34 // configure supplementary groups
35 if (gid == 0 || nogroups) {
36 if (setgroups(0, NULL) < 0)
37 errExit("setgroups");
38 if (arg_debug)
39 printf("Username %s, no supplementary groups\n", cfg.username);
40 }
41 else {
42 assert(cfg.username);
43 gid_t groups[MAX_GROUPS];
44 int ngroups = MAX_GROUPS;
45 int rv = getgrouplist(cfg.username, gid, groups, &ngroups);
46
47 if (arg_debug && rv) {
48 printf("Username %s, groups ", cfg.username);
49 int i;
50 for (i = 0; i < ngroups; i++)
51 printf("%u, ", groups[i]);
52 printf("\n");
53 }
54
55 if (rv == -1) {
56 fprintf(stderr, "Warning: cannot extract supplementary group list, dropping them\n");
57 if (setgroups(0, NULL) < 0)
58 errExit("setgroups");
59 }
60 else {
61 rv = setgroups(ngroups, groups);
62 if (rv) {
63 fprintf(stderr, "Warning: cannot set supplementary group list, dropping them\n");
64 if (setgroups(0, NULL) < 0)
65 errExit("setgroups");
66 }
67 }
68 }
69
70 // set uid/gid
71 if (setgid(getgid()) < 0)
72 errExit("setgid/getgid");
73 if (setuid(getuid()) < 0)
74 errExit("setuid/getuid");
75}
76
77
78void logsignal(int s) {
79 if (!arg_debug)
80 return;
81
82 openlog("firejail", LOG_NDELAY | LOG_PID, LOG_USER);
83 syslog(LOG_INFO, "Signal %d caught", s);
84 closelog();
85}
86
87
88void logmsg(const char *msg) {
89 if (!arg_debug)
90 return;
91
92 openlog("firejail", LOG_NDELAY | LOG_PID, LOG_USER);
93 syslog(LOG_INFO, "%s\n", msg);
94 closelog();
95}
96
97
98void logargs(int argc, char **argv) {
99 if (!arg_debug)
100 return;
101
102 int i;
103 int len = 0;
104
105 // calculate message length
106 for (i = 0; i < argc; i++)
107 len += strlen(argv[i]) + 1; // + ' '
108
109 // build message
110 char msg[len + 1];
111 char *ptr = msg;
112 for (i = 0; i < argc; i++) {
113 sprintf(ptr, "%s ", argv[i]);
114 ptr += strlen(ptr);
115 }
116
117 // log message
118 logmsg(msg);
119}
120
121
122void logerr(const char *msg) {
123 if (!arg_debug)
124 return;
125
126 openlog("firejail", LOG_NDELAY | LOG_PID, LOG_USER);
127 syslog(LOG_ERR, "%s\n", msg);
128 closelog();
129}
130
131
132// return -1 if error, 0 if no error
133int copy_file(const char *srcname, const char *destname) {
134 assert(srcname);
135 assert(destname);
136
137 // open source
138 int src = open(srcname, O_RDONLY);
139 if (src < 0) {
140 fprintf(stderr, "Warning: cannot open %s, file not copied\n", srcname);
141 return -1;
142 }
143
144 // open destination
145 int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
146 if (dst < 0) {
147 fprintf(stderr, "Warning: cannot open %s, file not copied\n", destname);
148 close(src);
149 return -1;
150 }
151
152 // copy
153 ssize_t len;
154 static const int BUFLEN = 1024;
155 unsigned char buf[BUFLEN];
156 while ((len = read(src, buf, BUFLEN)) > 0) {
157 int done = 0;
158 while (done != len) {
159 int rv = write(dst, buf + done, len - done);
160 if (rv == -1) {
161 close(src);
162 close(dst);
163 return -1;
164 }
165
166 done += rv;
167 }
168 }
169
170 close(src);
171 close(dst);
172 return 0;
173}
174
175
176char *get_link(const char *fname) {
177 assert(fname);
178 struct stat sb;
179 char *linkname;
180 ssize_t r;
181
182 if (lstat(fname, &sb) == -1)
183 return NULL;
184
185 linkname = malloc(sb.st_size + 1);
186 if (linkname == NULL)
187 return NULL;
188 memset(linkname, 0, sb.st_size + 1);
189
190 r = readlink(fname, linkname, sb.st_size + 1);
191 if (r < 0) {
192 free(linkname);
193 return NULL;
194 }
195 return linkname;
196}
197
198
199// return 1 if the file is a directory
200int is_dir(const char *fname) {
201 assert(fname);
202 if (*fname == '\0')
203 return 0;
204
205 // if fname doesn't end in '/', add one
206 int rv;
207 struct stat s;
208 if (fname[strlen(fname) - 1] == '/')
209 rv = stat(fname, &s);
210 else {
211 char *tmp;
212 if (asprintf(&tmp, "%s/", fname) == -1) {
213 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
214 errExit("asprintf");
215 }
216 rv = stat(tmp, &s);
217 free(tmp);
218 }
219
220 if (rv == -1)
221 return 0;
222
223 if (S_ISDIR(s.st_mode))
224 return 1;
225
226 return 0;
227}
228
229// return 1 if the file is a link
230int is_link(const char *fname) {
231 assert(fname);
232 if (*fname == '\0')
233 return 0;
234
235 struct stat s;
236 if (lstat(fname, &s) == 0) {
237 if (S_ISLNK(s.st_mode))
238 return 1;
239 }
240
241 return 0;
242}
243
244
245// remove multiple spaces and return allocated memory
246char *line_remove_spaces(const char *buf) {
247 assert(buf);
248 if (strlen(buf) == 0)
249 return NULL;
250
251 // allocate memory for the new string
252 char *rv = malloc(strlen(buf) + 1);
253 if (rv == NULL)
254 errExit("malloc");
255
256 // remove space at start of line
257 const char *ptr1 = buf;
258 while (*ptr1 == ' ' || *ptr1 == '\t')
259 ptr1++;
260
261 // copy data and remove additional spaces
262 char *ptr2 = rv;
263 int state = 0;
264 while (*ptr1 != '\0') {
265 if (*ptr1 == '\n' || *ptr1 == '\r')
266 break;
267
268 if (state == 0) {
269 if (*ptr1 != ' ' && *ptr1 != '\t')
270 *ptr2++ = *ptr1++;
271 else {
272 *ptr2++ = ' ';
273 ptr1++;
274 state = 1;
275 }
276 }
277 else { // state == 1
278 while (*ptr1 == ' ' || *ptr1 == '\t')
279 ptr1++;
280 state = 0;
281 }
282 }
283
284 // strip last blank character if any
285 if (*(ptr2 - 1) == ' ')
286 --ptr2;
287 *ptr2 = '\0';
288 // if (arg_debug)
289 // printf("Processing line #%s#\n", rv);
290
291 return rv;
292}
293
294
295char *split_comma(char *str) {
296 if (str == NULL || *str == '\0')
297 return NULL;
298 char *ptr = strchr(str, ',');
299 if (!ptr)
300 return NULL;
301 *ptr = '\0';
302 ptr++;
303 if (*ptr == '\0')
304 return NULL;
305 return ptr;
306}
307
308
309int not_unsigned(const char *str) {
310 int rv = 0;
311 const char *ptr = str;
312 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') {
313 if (!isdigit(*ptr)) {
314 rv = 1;
315 break;
316 }
317 ptr++;
318 }
319
320 return rv;
321}
322
323
324#define BUFLEN 4096
325// find the first child for this parent; return 1 if error
326int find_child(pid_t parent, pid_t *child) {
327 *child = 0; // use it to flag a found child
328
329 DIR *dir;
330 if (!(dir = opendir("/proc"))) {
331 // sleep 2 seconds and try again
332 sleep(2);
333 if (!(dir = opendir("/proc"))) {
334 fprintf(stderr, "Error: cannot open /proc directory\n");
335 exit(1);
336 }
337 }
338
339 struct dirent *entry;
340 char *end;
341 while (*child == 0 && (entry = readdir(dir))) {
342 pid_t pid = strtol(entry->d_name, &end, 10);
343 if (end == entry->d_name || *end)
344 continue;
345 if (pid == parent)
346 continue;
347
348 // open stat file
349 char *file;
350 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
351 perror("asprintf");
352 exit(1);
353 }
354 FILE *fp = fopen(file, "r");
355 if (!fp) {
356 free(file);
357 continue;
358 }
359
360 // look for firejail executable name
361 char buf[BUFLEN];
362 while (fgets(buf, BUFLEN - 1, fp)) {
363 if (strncmp(buf, "PPid:", 5) == 0) {
364 char *ptr = buf + 5;
365 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
366 ptr++;
367 }
368 if (*ptr == '\0') {
369 fprintf(stderr, "Error: cannot read /proc file\n");
370 exit(1);
371 }
372 if (parent == atoi(ptr))
373 *child = pid;
374 break; // stop reading the file
375 }
376 }
377 fclose(fp);
378 free(file);
379 }
380 closedir(dir);
381
382 return (*child)? 0:1; // 0 = found, 1 = not found
383}
384
385
386
387void extract_command_name(const char *str) {
388 assert(str);
389 cfg.command_name = strdup(str);
390 if (!cfg.command_name)
391 errExit("strdup");
392
393 // restrict the command name to the first word
394 char *ptr = cfg.command_name;
395 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
396 ptr++;
397 *ptr = '\0';
398
399 // remove the path: /usr/bin/firefox becomes firefox
400 ptr = strrchr(cfg.command_name, '/');
401 if (ptr) {
402 ptr++;
403 if (*ptr == '\0') {
404 fprintf(stderr, "Error: invalid command name\n");
405 exit(1);
406 }
407
408 char *tmp = strdup(ptr);
409 if (!tmp)
410 errExit("strdup");
411 free(cfg.command_name);
412 cfg.command_name = tmp;
413 }
414}
415
416
417void update_map(char *mapping, char *map_file) {
418 int fd, j;
419 size_t map_len; /* Length of 'mapping' */
420
421 /* Replace commas in mapping string with newlines */
422
423 map_len = strlen(mapping);
424 for (j = 0; j < map_len; j++)
425 if (mapping[j] == ',')
426 mapping[j] = '\n';
427
428 fd = open(map_file, O_RDWR);
429 if (fd == -1) {
430 fprintf(stderr, "Error: cannot open %s: %s\n", map_file, strerror(errno));
431 exit(EXIT_FAILURE);
432 }
433
434 if (write(fd, mapping, map_len) != map_len) {
435 fprintf(stderr, "Error: cannot write to %s: %s\n", map_file, strerror(errno));
436 exit(EXIT_FAILURE);
437 }
438
439 close(fd);
440}
441
442
443void wait_for_other(int fd) {
444 //****************************
445 // wait for the parent to be initialized
446 //****************************
447 char childstr[BUFLEN + 1];
448 int newfd = dup(fd);
449 if (newfd == -1)
450 errExit("dup");
451 FILE* stream;
452 stream = fdopen(newfd, "r");
453 *childstr = '\0';
454 if (fgets(childstr, BUFLEN, stream)) {
455 // remove \n)
456 char *ptr = childstr;
457 while(*ptr !='\0' && *ptr != '\n')
458 ptr++;
459 if (*ptr == '\0')
460 errExit("fgets");
461 *ptr = '\0';
462 }
463 else {
464 fprintf(stderr, "Error: cannot establish communication with the parent, exiting...\n");
465 exit(1);
466 }
467 fclose(stream);
468}
469
470
471void notify_other(int fd) {
472 FILE* stream;
473 int newfd = dup(fd);
474 if (newfd == -1)
475 errExit("dup");
476 stream = fdopen(newfd, "w");
477 fprintf(stream, "%u\n", getpid());
478 fflush(stream);
479 fclose(stream);
480}
diff --git a/src/firejail/veth.c b/src/firejail/veth.c
new file mode 100644
index 000000000..ecc31f18d
--- /dev/null
+++ b/src/firejail/veth.c
@@ -0,0 +1,191 @@
1/* code based on iproute2 ip/iplink.c, modified to be included in firejail project
2 *
3 * Original source code:
4 *
5 * Information:
6 * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2
7 *
8 * Download:
9 * http://www.kernel.org/pub/linux/utils/net/iproute2/
10 *
11 * Repository:
12 * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
13 *
14 * License: GPL v2
15 *
16 * Original copyright header
17 *
18 * iplink.c "ip link".
19 *
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version
23 * 2 of the License, or (at your option) any later version.
24 *
25 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
26 *
27 */
28 /*
29 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
30 *
31 * This file is part of firejail project
32 *
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License as published by
35 * the Free Software Foundation; either version 2 of the License, or
36 * (at your option) any later version.
37 *
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
42 *
43 * You should have received a copy of the GNU General Public License along
44 * with this program; if not, write to the Free Software Foundation, Inc.,
45 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
46*/
47
48#include "firejail.h"
49#include "../include/libnetlink.h"
50#include <linux/veth.h>
51
52struct iplink_req
53{
54 struct nlmsghdr n;
55 struct ifinfomsg i;
56 char buf[1024];
57};
58
59static struct rtnl_handle rth = { .fd = -1 };
60
61int net_create_veth(const char *dev, const char *nsdev, unsigned pid) {
62 int len;
63 struct iplink_req req;
64
65 if (arg_debug)
66 printf("create veth %s/%s/%u\n", dev, nsdev, pid);
67 assert(dev);
68 assert(nsdev);
69 assert(pid);
70
71 if (rtnl_open(&rth, 0) < 0) {
72 fprintf(stderr, "cannot open netlink\n");
73 exit(1);
74 }
75
76 memset(&req, 0, sizeof(req));
77
78 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
79 req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
80 req.n.nlmsg_type = RTM_NEWLINK;
81 req.i.ifi_family = 0;
82
83 if (dev) {
84 len = strlen(dev) + 1;
85 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, len);
86 }
87
88 struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
89 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
90 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "veth", strlen("veth"));
91
92 struct rtattr * data = NLMSG_TAIL(&req.n);
93 addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
94
95 struct rtattr * peerdata = NLMSG_TAIL(&req.n);
96 addattr_l (&req.n, sizeof(req), VETH_INFO_PEER, NULL, 0);
97 req.n.nlmsg_len += sizeof(struct ifinfomsg);
98
99 // place the link in the child namespace
100 addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4);
101
102 if (nsdev) {
103 int len = strlen(nsdev) + 1;
104 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, nsdev, len);
105 }
106 peerdata->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)peerdata;
107
108 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
109 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
110
111 // send message
112 if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
113 exit(2);
114
115 return 0;
116}
117
118
119int net_create_macvlan(const char *dev, const char *parent, unsigned pid) {
120 int len;
121 struct iplink_req req;
122 if (arg_debug)
123 printf("create macvlan %s, parent %s\n", dev, parent);
124 assert(dev);
125 assert(parent);
126
127 if (rtnl_open(&rth, 0) < 0) {
128 fprintf(stderr, "cannot open netlink\n");
129 exit(1);
130 }
131
132 memset(&req, 0, sizeof(req));
133
134 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
135 req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
136 req.n.nlmsg_type = RTM_NEWLINK;
137 req.i.ifi_family = 0;
138
139 // we start with the parent
140 int parent_ifindex = 2;
141 addattr_l(&req.n, sizeof(req), IFLA_LINK, &parent_ifindex, 4);
142
143 // add new interface name
144 len = strlen(dev) + 1;
145 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, len);
146
147 // place the interface in child namespace
148 addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4);
149
150
151 // add link info for the new interface
152 struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
153 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
154 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "macvlan", strlen("macvlan"));
155
156 // set macvlan bridge mode
157 struct rtattr * data = NLMSG_TAIL(&req.n);
158 addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
159 int macvlan_type = MACVLAN_MODE_BRIDGE;
160 addattr_l (&req.n, sizeof(req), IFLA_INFO_KIND, &macvlan_type, 4);
161
162 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
163// req.n.nlmsg_len += sizeof(struct ifinfomsg);
164
165
166 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
167 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
168
169 // send message
170 if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
171 exit(2);
172
173 return 0;
174}
175
176/*
177int main(int argc, char **argv) {
178 printf("Hello\n");
179
180
181 char *dev = argv[3];
182 char *nsdev = argv[8];
183 unsigned pid;
184 sscanf(argv[10], "%u", &pid);
185
186
187 net_create_veth(dev, nsdev, pid);
188
189 return 0;
190}
191*/ \ No newline at end of file
diff --git a/src/firemon/Makefile.in b/src/firemon/Makefile.in
new file mode 100644
index 000000000..425289695
--- /dev/null
+++ b/src/firemon/Makefile.in
@@ -0,0 +1,24 @@
1all: firemon
2
3PREFIX=@prefix@
4VERSION=@PACKAGE_VERSION@
5NAME=@PACKAGE_NAME@
6
7H_FILE_LIST = $(wildcard *.[h])
8C_FILE_LIST = $(wildcard *.c)
9OBJS = $(C_FILE_LIST:.c=.o)
10BINOBJS = $(foreach file, $(OBJS), $file)
11CFLAGS += -ggdb -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
12LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now
13
14%.o : %.c $(H_FILE_LIST)
15 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
16
17firemon: $(OBJS) ../lib/common.o ../lib/pid.o
18 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/pid.o $(LIBS)
19
20clean:; rm -f *.o firemon
21
22distclean: clean
23 rm -fr Makefile
24
diff --git a/src/firemon/arp.c b/src/firemon/arp.c
new file mode 100644
index 000000000..71beb0630
--- /dev/null
+++ b/src/firemon/arp.c
@@ -0,0 +1,99 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#define MAXBUF 4096
22
23static void print_arp(const char *fname) {
24 FILE *fp = fopen(fname, "r");
25 if (!fp)
26 return;
27
28 printf(" ARP Table:\n");
29 char buf[MAXBUF];
30 while (fgets(buf, MAXBUF, fp)) {
31 // remove blanks, \n
32 char *ptr = buf;
33 while (*ptr == ' ' || *ptr == '\t')
34 ptr++;
35 char *start = ptr;
36 if (*start == '\0')
37 continue;
38 ptr = strchr(ptr, '\n');
39 if (ptr)
40 *ptr = '\0';
41
42 // remove table header
43 //IP address HW type Flags HW address Mask Device
44 if (strncmp(start, "IP address", 10) == 0)
45 continue;
46
47 // extract data
48 char ip[64];
49 char type[64];
50 char flags[64];
51 char mac[64];
52 char mask[64];
53 char device[64];
54 int rv = sscanf(start, "%s %s %s %s %s %s\n", ip, type, flags, mac, mask, device);
55 if (rv != 6)
56 continue;
57
58 // destination ip
59 unsigned a, b, c, d;
60 if (sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d) != 4 || a > 255 || b > 255 || c > 255 || d > 255)
61 continue;
62 uint32_t destip = a * 0x1000000 + b * 0x10000 + c * 0x100 + d;
63 if (strcmp(flags, "0x0") == 0)
64 printf(" %d.%d.%d.%d dev %s FAILED\n",
65 PRINT_IP(destip), device);
66 else
67 printf(" %d.%d.%d.%d dev %s lladdr %s REACHABLE\n",
68 PRINT_IP(destip), device, mac);
69 }
70
71 fclose(fp);
72
73}
74
75void arp(pid_t pid) {
76 if (getuid() == 0)
77 firemon_drop_privs();
78
79 pid_read(pid);
80
81 // print processes
82 int i;
83 for (i = 0; i < max_pids; i++) {
84 if (pids[i].level == 1) {
85 pid_print_list(i, 0);
86 int child = find_child(i);
87 if (child != -1) {
88 char *fname;
89 if (asprintf(&fname, "/proc/%d/net/arp", child) == -1)
90 errExit("asprintf");
91 print_arp(fname);
92 free(fname);
93 printf("\n");
94 }
95 }
96 }
97}
98
99
diff --git a/src/firemon/caps.c b/src/firemon/caps.c
new file mode 100644
index 000000000..4ae9ab28d
--- /dev/null
+++ b/src/firemon/caps.c
@@ -0,0 +1,69 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#define MAXBUF 4098
22
23static void print_caps(int pid) {
24 char *file;
25 if (asprintf(&file, "/proc/%d/status", pid) == -1) {
26 errExit("asprintf");
27 exit(1);
28 }
29
30 FILE *fp = fopen(file, "r");
31 if (!fp) {
32 printf(" Error: cannot open %s\n", file);
33 free(file);
34 return;
35 }
36
37 char buf[MAXBUF];
38 while (fgets(buf, MAXBUF, fp)) {
39 if (strncmp(buf, "CapBnd:", 7) == 0) {
40 printf(" %s", buf);
41 fflush(0);
42 free(file);
43 fclose(fp);
44 return;
45 }
46 }
47 fclose(fp);
48 free(file);
49}
50
51void caps(pid_t pid) {
52 if (getuid() == 0)
53 firemon_drop_privs();
54
55 pid_read(pid); // include all processes
56
57 // print processes
58 int i;
59 for (i = 0; i < max_pids; i++) {
60 if (pids[i].level == 1) {
61 pid_print_list(i, 0);
62 int child = find_child(i);
63 if (child != -1)
64 print_caps(child);
65 }
66 }
67 printf("\n");
68}
69
diff --git a/src/firemon/cgroup.c b/src/firemon/cgroup.c
new file mode 100644
index 000000000..214aefaf9
--- /dev/null
+++ b/src/firemon/cgroup.c
@@ -0,0 +1,64 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#define MAXBUF 4098
22
23static void print_cgroup(int pid) {
24 char *file;
25 if (asprintf(&file, "/proc/%d/cgroup", pid) == -1) {
26 errExit("asprintf");
27 exit(1);
28 }
29
30 FILE *fp = fopen(file, "r");
31 if (!fp) {
32 printf(" Error: cannot open %s\n", file);
33 free(file);
34 return;
35 }
36
37 char buf[MAXBUF];
38 if (fgets(buf, MAXBUF, fp)) {
39 printf(" %s", buf);
40 fflush(0);
41 }
42
43 fclose(fp);
44 free(file);
45}
46
47void cgroup(pid_t pid) {
48 if (getuid() == 0)
49 firemon_drop_privs();
50
51 pid_read(pid);
52
53 // print processes
54 int i;
55 for (i = 0; i < max_pids; i++) {
56 if (pids[i].level == 1) {
57 pid_print_list(i, 0);
58 int child = find_child(i);
59 if (child != -1)
60 print_cgroup(child);
61 }
62 }
63}
64
diff --git a/src/firemon/cpu.c b/src/firemon/cpu.c
new file mode 100644
index 000000000..d5d20d1b8
--- /dev/null
+++ b/src/firemon/cpu.c
@@ -0,0 +1,68 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#define MAXBUF 4098
22
23static void print_cpu(int pid) {
24 char *file;
25 if (asprintf(&file, "/proc/%d/status", pid) == -1) {
26 errExit("asprintf");
27 exit(1);
28 }
29
30 FILE *fp = fopen(file, "r");
31 if (!fp) {
32 printf(" Error: cannot open %s\n", file);
33 free(file);
34 return;
35 }
36
37 char buf[MAXBUF];
38 while (fgets(buf, MAXBUF, fp)) {
39 if (strncmp(buf, "Cpus_allowed_list:", 18) == 0) {
40 printf(" %s", buf);
41 fflush(0);
42 free(file);
43 fclose(fp);
44 return;
45 }
46 }
47 fclose(fp);
48 free(file);
49}
50
51void cpu(pid_t pid) {
52 if (getuid() == 0)
53 firemon_drop_privs();
54
55 pid_read(pid);
56
57 // print processes
58 int i;
59 for (i = 0; i < max_pids; i++) {
60 if (pids[i].level == 1) {
61 pid_print_list(i, 0);
62 int child = find_child(i);
63 if (child != -1)
64 print_cpu(child);
65 }
66 }
67}
68
diff --git a/src/firemon/firemon.c b/src/firemon/firemon.c
new file mode 100644
index 000000000..d77d11a7a
--- /dev/null
+++ b/src/firemon/firemon.c
@@ -0,0 +1,222 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#include <signal.h>
22#include <termios.h>
23#include <sys/ioctl.h>
24#include <sys/prctl.h>
25#include <grp.h>
26
27
28static int arg_route = 0;
29static int arg_arp = 0;
30static int arg_tree = 0;
31static int arg_interface = 0;
32static int arg_seccomp = 0;
33static int arg_caps = 0;
34static int arg_cpu = 0;
35static int arg_cgroup = 0;
36int arg_nowrap = 0;
37
38static struct termios tlocal; // startup terminal setting
39static struct termios twait; // no wait on key press
40static int terminal_set = 0;
41
42static void my_handler(int s){
43 if (terminal_set)
44 tcsetattr(0, TCSANOW, &tlocal);
45 exit(0);
46}
47
48// find the first child process for the specified pid
49// return -1 if not found
50int find_child(int id) {
51 int i;
52 for (i = 0; i < max_pids; i++) {
53 if (pids[i].level == 2 && pids[i].parent == id)
54 return i;
55 }
56
57 return -1;
58}
59
60// drop privileges
61void firemon_drop_privs(void) {
62 // drop privileges
63 if (setgroups(0, NULL) < 0)
64 errExit("setgroups");
65 if (setgid(getgid()) < 0)
66 errExit("setgid/getgid");
67 if (setuid(getuid()) < 0)
68 errExit("setuid/getuid");
69}
70
71// sleep and wait for a key to be pressed
72void firemon_sleep(int st) {
73 if (terminal_set == 0) {
74 tcgetattr(0, &twait); // get current terminal attirbutes; 0 is the file descriptor for stdin
75 memcpy(&tlocal, &twait, sizeof(tlocal));
76 twait.c_lflag &= ~ICANON; // disable canonical mode
77 twait.c_lflag &= ~ECHO; // no echo
78 twait.c_cc[VMIN] = 1; // wait until at least one keystroke available
79 twait.c_cc[VTIME] = 0; // no timeout
80 terminal_set = 1;
81 }
82 tcsetattr(0, TCSANOW, &twait);
83
84
85 fd_set fds;
86 FD_ZERO(&fds);
87 FD_SET(0,&fds);
88 int maxfd = 1;
89
90 struct timeval ts;
91 ts.tv_sec = st;
92 ts.tv_usec = 0;
93
94 int ready = select(maxfd, &fds, (fd_set *) 0, (fd_set *) 0, &ts);
95 (void) ready;
96 if( FD_ISSET(0, &fds)) {
97 getchar();
98 tcsetattr(0, TCSANOW, &tlocal);
99 printf("\n");
100 exit(0);
101 }
102 tcsetattr(0, TCSANOW, &tlocal);
103}
104
105
106int main(int argc, char **argv) {
107 unsigned pid = 0;
108 int i;
109
110 // handle CTRL-C
111 signal (SIGINT, my_handler);
112 signal (SIGTERM, my_handler);
113
114 for (i = 1; i < argc; i++) {
115 // default options
116 if (strcmp(argv[i], "--help") == 0 ||
117 strcmp(argv[i], "-?") == 0) {
118 usage();
119 return 0;
120 }
121 else if (strcmp(argv[i], "--version") == 0) {
122 printf("firemon version %s\n\n", VERSION);
123 return 0;
124 }
125
126 // options without a pid argument
127 else if (strcmp(argv[i], "--top") == 0) {
128 top(); // never to return
129 }
130 else if (strcmp(argv[i], "--list") == 0) {
131 list();
132 return 0;
133 }
134 else if (strcmp(argv[i], "--netstats") == 0) {
135 netstats();
136 return 0;
137 }
138
139
140 // cumulative options with or without a pid argument
141 else if (strcmp(argv[i], "--cgroup") == 0) {
142 arg_cgroup = 1;
143 }
144 else if (strcmp(argv[i], "--cpu") == 0) {
145 arg_cpu = 1;
146 }
147 else if (strcmp(argv[i], "--seccomp") == 0) {
148 arg_seccomp = 1;
149 }
150 else if (strcmp(argv[i], "--caps") == 0) {
151 arg_caps = 1;
152 }
153 else if (strcmp(argv[i], "--tree") == 0) {
154 arg_tree = 1;
155 }
156 else if (strcmp(argv[i], "--interface") == 0) {
157 arg_interface = 1;
158 }
159 else if (strcmp(argv[i], "--route") == 0) {
160 arg_route = 1;
161 }
162 else if (strcmp(argv[i], "--arp") == 0) {
163 arg_arp = 1;
164 }
165
166 else if (strncmp(argv[i], "--name=", 7) == 0) {
167 char *name = argv[i] + 7;
168 if (name2pid(name, (pid_t *) &pid)) {
169 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
170 return 1;
171 }
172 }
173
174 // etc
175 else if (strcmp(argv[i], "--nowrap") == 0)
176 arg_nowrap = 1;
177
178 // invalid option
179 else if (*argv[i] == '-') {
180 fprintf(stderr, "Error: invalid option\n");
181 return 1;
182 }
183
184 // PID argument
185 else {
186 // this should be a pid number
187 char *ptr = argv[i];
188 while (*ptr != '\0') {
189 if (!isdigit(*ptr)) {
190 fprintf(stderr, "Error: not a valid PID number\n");
191 exit(1);
192 }
193 ptr++;
194 }
195
196 sscanf(argv[i], "%u", &pid);
197 break;
198 }
199 }
200
201 if (arg_tree)
202 tree((pid_t) pid);
203 if (arg_interface)
204 interface((pid_t) pid);
205 if (arg_route)
206 route((pid_t) pid);
207 if (arg_arp)
208 arp((pid_t) pid);
209 if (arg_seccomp)
210 seccomp((pid_t) pid);
211 if (arg_caps)
212 caps((pid_t) pid);
213 if (arg_cpu)
214 cpu((pid_t) pid);
215 if (arg_cgroup)
216 cgroup((pid_t) pid);
217
218 if (!arg_route && !arg_arp && !arg_interface && !arg_tree && !arg_caps && !arg_seccomp)
219 procevent((pid_t) pid); // never to return
220
221 return 0;
222}
diff --git a/src/firemon/firemon.h b/src/firemon/firemon.h
new file mode 100644
index 000000000..59b1f352c
--- /dev/null
+++ b/src/firemon/firemon.h
@@ -0,0 +1,84 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#ifndef FIREMON_H
21#define FIREMON_H
22#define _GNU_SOURCE
23#include <stdlib.h>
24#include <stdio.h>
25#include <ctype.h>
26#include <string.h>
27#include <errno.h>
28#include <stdint.h>
29#include "../include/pid.h"
30#include "../include/common.h"
31
32// clear screen
33static inline void firemon_clrscr(void) {
34 printf("\033[2J\033[1;1H");
35 fflush(0);
36}
37
38// firemon.c
39extern int arg_nowrap;
40int find_child(int id);
41void firemon_drop_privs(void);
42void firemon_sleep(int st);
43
44
45// procevent.c
46void procevent(pid_t pid);
47
48// usage.c
49void usage(void);
50
51// top.c
52void top(void);
53
54// list.c
55void list(void);
56
57// interface.c
58void interface(pid_t pid);
59
60// arp.c
61void arp(pid_t pid);
62
63// route.c
64void route(pid_t pid);
65
66// caps.c
67void caps(pid_t pid);
68
69// seccomp.c
70void seccomp(pid_t pid);
71
72// cpu.c
73void cpu(pid_t pid);
74
75// cgroup.c
76void cgroup(pid_t pid);
77
78// tree.c
79void tree(pid_t pid);
80
81// netstats.c
82void netstats(void);
83
84#endif
diff --git a/src/firemon/interface.c b/src/firemon/interface.c
new file mode 100644
index 000000000..52a9c33cd
--- /dev/null
+++ b/src/firemon/interface.c
@@ -0,0 +1,176 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#include <sys/types.h>
22#include <sys/wait.h>
23#include <netdb.h>
24#include <arpa/inet.h>
25#include <ifaddrs.h>
26#include <net/if.h>
27#include <linux/connector.h>
28#include <linux/netlink.h>
29#include <linux/if_link.h>
30#include <linux/sockios.h>
31#include <sys/ioctl.h>
32
33//#include <net/route.h>
34//#include <linux/if_bridge.h>
35
36// print IP addresses for all interfaces
37static void net_ifprint(void) {
38 uint32_t ip;
39 uint32_t mask;
40 struct ifaddrs *ifaddr, *ifa;
41
42 int fd;
43 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
44 fprintf(stderr, "Error: cannot open AF_INET socket\n");
45 exit(1);
46 }
47
48 if (getifaddrs(&ifaddr) == -1)
49 errExit("getifaddrs");
50
51 // walk through the linked list
52 printf(" Link status:\n");
53 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
54 if (ifa->ifa_addr == NULL)
55 continue;
56
57 if (ifa->ifa_addr->sa_family == AF_PACKET) {
58 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) {
59 if (ifa->ifa_data != NULL) {
60 struct rtnl_link_stats *stats = ifa->ifa_data;
61
62 // extract mac address
63 struct ifreq ifr;
64 memset(&ifr, 0, sizeof(ifr));
65 strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ);
66 int rv = ioctl (fd, SIOCGIFHWADDR, &ifr);
67
68 if (rv == 0)
69 printf(" %s UP, %02x:%02x:%02x:%02x:%02x:%02x\n",
70 ifa->ifa_name, PRINT_MAC((unsigned char *) &ifr.ifr_hwaddr.sa_data));
71 else
72 printf(" %s UP\n", ifa->ifa_name);
73
74 printf(" tx/rx: %u/%u packets, %u/%u bytes\n",
75 stats->tx_packets, stats->rx_packets,
76 stats->tx_bytes, stats->rx_bytes);
77 }
78 }
79 else
80 printf(" %s DOWN\n", ifa->ifa_name);
81 }
82 }
83
84
85 // walk through the linked list
86 printf(" IPv4 status:\n");
87 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
88 if (ifa->ifa_addr == NULL)
89 continue;
90
91 if (ifa->ifa_addr->sa_family == AF_INET) {
92 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
93 mask = ntohl(si->sin_addr.s_addr);
94 si = (struct sockaddr_in *) ifa->ifa_addr;
95 ip = ntohl(si->sin_addr.s_addr);
96
97 char *status;
98 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
99 status = "UP";
100 else
101 status = "DOWN";
102
103 printf(" %s %s, %d.%d.%d.%d/%u\n",
104 ifa->ifa_name, status, PRINT_IP(ip), mask2bits(mask));
105 }
106 }
107
108
109 // walk through the linked list
110 printf(" IPv6 status:\n");
111 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
112 if (ifa->ifa_addr == NULL)
113 continue;
114
115 if (ifa->ifa_addr->sa_family == AF_INET6) {
116 char host[NI_MAXHOST];
117 int s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
118 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
119 if (s == 0) {
120 char *ptr;
121 if ((ptr = strchr(host, '%')) != NULL)
122 *ptr = '\0';
123 char *status;
124 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
125 status = "UP";
126 else
127 status = "DOWN";
128
129 printf(" %s %s, %s\n", ifa->ifa_name, status, host);
130 }
131 }
132 }
133
134 freeifaddrs(ifaddr);
135 close(fd);
136}
137
138static void print_sandbox(pid_t pid) {
139 pid_t child = fork();
140 if (child == -1)
141 return;
142
143 if (child == 0) {
144 int rv = join_namespace(pid, "net");
145 if (rv)
146 return;
147 net_ifprint();
148 printf("\n");
149 exit(0);
150 }
151
152 // wait for the child to finish
153 waitpid(child, NULL, 0);
154}
155
156void interface(pid_t pid) {
157 if (getuid() != 0) {
158 fprintf(stderr, "Error: you need to be root to run this command\n");
159 exit(1);
160 }
161
162 pid_read(pid); // a pid of 0 will include all processes
163
164 // print processes
165 int i;
166 for (i = 0; i < max_pids; i++) {
167 if (pids[i].level == 1) {
168 pid_print_list(i, 0);
169 int child = find_child(i);
170 if (child != -1) {
171 print_sandbox(child);
172 }
173 }
174 }
175}
176
diff --git a/src/firemon/list.c b/src/firemon/list.c
new file mode 100644
index 000000000..6a997bde1
--- /dev/null
+++ b/src/firemon/list.c
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21
22void list(void) {
23 if (getuid() == 0)
24 firemon_drop_privs();
25
26 pid_read(0); // include all processes
27
28 // print processes
29 int i;
30 for (i = 0; i < max_pids; i++) {
31 if (pids[i].level == 1)
32 pid_print_list(i, 0);
33 }
34}
35
diff --git a/src/firemon/netstats.c b/src/firemon/netstats.c
new file mode 100644
index 000000000..6c4a767f1
--- /dev/null
+++ b/src/firemon/netstats.c
@@ -0,0 +1,214 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#include <termios.h>
22#include <sys/ioctl.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <unistd.h>
26
27#define MAXBUF 4096
28
29static char *get_header(void) {
30 char *rv;
31 if (asprintf(&rv, "%-5.5s %-9.9s %-10.10s %-10.10s %s",
32 "PID", "User", "RX(KB/s)", "TX(KB/s)", "Command") == -1)
33 errExit("asprintf");
34
35 return rv;
36}
37
38void get_stats(int parent) {
39 // find the first child
40 int child = -1;
41 for (child = parent + 1; child < max_pids; child++) {
42 if (pids[child].parent == parent)
43 break;
44 }
45
46 if (child == -1)
47 goto errexit;
48
49 // open /proc/child/net/dev file and read rx and tx
50 char *fname;
51 if (asprintf(&fname, "/proc/%d/net/dev", child) == -1)
52 errExit("asprintf");
53 FILE *fp = fopen(fname, "r");
54 if (!fp) {
55 free(fname);
56 goto errexit;
57 }
58
59 char buf[MAXBUF];
60 long long unsigned rx = 0;
61 long long unsigned tx = 0;
62 while (fgets(buf, MAXBUF, fp)) {
63 if (strncmp(buf, "Inter", 5) == 0)
64 continue;
65 if (strncmp(buf, " face", 5) == 0)
66 continue;
67
68 char *ptr = buf;
69 while (*ptr != '\0' && *ptr != ':') {
70 ptr++;
71 }
72
73 if (*ptr == '\0') {
74 fclose(fp);
75 free(fname);
76 goto errexit;
77 }
78 ptr++;
79
80 long long unsigned rxval;
81 long long unsigned txval;
82 unsigned a, b, c, d, e, f, g;
83 sscanf(ptr, "%llu %u %u %u %u %u %u %u %llu",
84 &rxval, &a, &b, &c, &d, &e, &f, &g, &txval);
85 rx += rxval;
86 tx += txval;
87 }
88
89 // store data
90 pids[parent].rx_delta = rx - pids[parent].rx;
91 pids[parent].rx = rx;
92 pids[parent].tx_delta = tx - pids[parent].tx;
93 pids[parent].tx = tx;
94
95
96 free(fname);
97 fclose(fp);
98 return;
99
100errexit:
101 pids[parent].rx = 0;
102 pids[parent].tx = 0;
103 pids[parent].rx_delta = 0;
104 pids[parent].tx_delta = 0;
105}
106
107
108static void print_proc(int index, int itv, int col) {
109 // command
110 char *cmd = pid_proc_cmdline(index);
111 char *ptrcmd;
112 if (cmd == NULL) {
113 if (pids[index].zombie)
114 ptrcmd = "(zombie)";
115 else
116 ptrcmd = "";
117 }
118 else
119 ptrcmd = cmd;
120 // if the command doesn't have a --net= option, don't print
121 if (strstr(ptrcmd, "--net=") == NULL) {
122 if (cmd)
123 free(cmd);
124 return;
125 }
126
127 // pid
128 char pidstr[10];
129 snprintf(pidstr, 10, "%u", index);
130
131 // user
132 char *user = pid_get_user_name(pids[index].uid);
133 char *ptruser;
134 if (user)
135 ptruser = user;
136 else
137 ptruser = "";
138
139
140 float rx_kbps = ((float) pids[index].rx_delta / 1000) / itv;
141 char ptrrx[15];
142 sprintf(ptrrx, "%.03f", rx_kbps);
143
144 float tx_kbps = ((float) pids[index].tx_delta / 1000) / itv;
145 char ptrtx[15];
146 sprintf(ptrtx, "%.03f", tx_kbps);
147
148 char buf[1024 + 1];
149 snprintf(buf, 1024, "%-5.5s %-9.9s %-10.10s %-10.10s %s",
150 pidstr, ptruser, ptrrx, ptrtx, ptrcmd);
151 if (col < 1024)
152 buf[col] = '\0';
153 printf("%s\n", buf);
154
155 if (cmd)
156 free(cmd);
157 if (user)
158 free(user);
159
160}
161
162void netstats(void) {
163 if (getuid() == 0)
164 firemon_drop_privs();
165
166 pid_read(0); // include all processes
167
168 printf("Displaying network statistics only for sandboxes using a new network namespace.\n");
169
170 // print processes
171 while (1) {
172 // set pid table
173 int i;
174 int itv = 5; // 5 second interval
175 pid_read(0); // todo: preserve the last calculation if any, so we don't have to do get_stats()
176
177 // start rx/tx measurements
178 for (i = 0; i < max_pids; i++) {
179 if (pids[i].level == 1)
180 get_stats(i);
181 }
182
183 // wait 5 seconds
184 firemon_sleep(itv);
185
186 // grab screen size
187 struct winsize sz;
188 int row = 24;
189 int col = 80;
190 if (!ioctl(0, TIOCGWINSZ, &sz)) {
191 col = sz.ws_col;
192 row = sz.ws_row;
193 }
194
195 // start printing
196 firemon_clrscr();
197 char *header = get_header();
198 if (strlen(header) > col)
199 header[col] = '\0';
200 printf("%s\n", header);
201 if (row > 0)
202 row--;
203 free(header);
204
205 // start rx/tx measurements
206 for (i = 0; i < max_pids; i++) {
207 if (pids[i].level == 1) {
208 get_stats(i);
209 print_proc(i, itv, col);
210 }
211 }
212 }
213}
214
diff --git a/src/firemon/procevent.c b/src/firemon/procevent.c
new file mode 100644
index 000000000..d2b5f7bbf
--- /dev/null
+++ b/src/firemon/procevent.c
@@ -0,0 +1,377 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#include <sys/socket.h>
22#include <linux/connector.h>
23#include <linux/netlink.h>
24#include <linux/cn_proc.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
28#include <arpa/inet.h>
29#include <time.h>
30#define PIDS_BUFLEN 4096
31#define SERVER_PORT 889 // 889-899 is left unassigned by IANA
32
33static int pid_is_firejail(pid_t pid) {
34 uid_t rv = 0;
35
36 // open stat file
37 char *file;
38 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
39 perror("asprintf");
40 exit(1);
41 }
42 FILE *fp = fopen(file, "r");
43 if (!fp) {
44 free(file);
45 return 0;
46 }
47
48 // look for firejail executable name
49 char buf[PIDS_BUFLEN];
50 while (fgets(buf, PIDS_BUFLEN - 1, fp)) {
51 if (strncmp(buf, "Name:", 5) == 0) {
52 char *ptr = buf + 5;
53 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
54 ptr++;
55 }
56 if (*ptr == '\0')
57 goto doexit;
58 if (strncmp(ptr, "firejail", 8) == 0)
59 rv = 1;
60// if (strncmp(ptr, "lxc-execute", 11) == 0)
61// rv = 1;
62 break;
63 }
64 }
65doexit:
66 fclose(fp);
67 free(file);
68 return rv;
69}
70
71
72static int procevent_netlink_setup(void) {
73 // open socket for process event connector
74 int sock;
75 if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR)) < 0) {
76 fprintf(stderr, "Error: cannot open netlink socket\n");
77 exit(1);
78 }
79
80 // bind socket
81 struct sockaddr_nl addr;
82 memset(&addr, 0, sizeof(addr));
83 addr.nl_pid = getpid();
84 addr.nl_family = AF_NETLINK;
85 addr.nl_groups = CN_IDX_PROC;
86 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
87 fprintf(stderr, "Error: cannot bind to netlink socket\n");
88 exit(1);
89 }
90
91 // send monitoring message
92 struct nlmsghdr nlmsghdr;
93 memset(&nlmsghdr, 0, sizeof(nlmsghdr));
94 nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg) + sizeof(enum proc_cn_mcast_op));
95 nlmsghdr.nlmsg_pid = getpid();
96 nlmsghdr.nlmsg_type = NLMSG_DONE;
97
98 struct cn_msg cn_msg;
99 memset(&cn_msg, 0, sizeof(cn_msg));
100 cn_msg.id.idx = CN_IDX_PROC;
101 cn_msg.id.val = CN_VAL_PROC;
102 cn_msg.len = sizeof(enum proc_cn_mcast_op);
103
104 struct iovec iov[3];
105 iov[0].iov_base = &nlmsghdr;
106 iov[0].iov_len = sizeof(nlmsghdr);
107 iov[1].iov_base = &cn_msg;
108 iov[1].iov_len = sizeof(cn_msg);
109
110 enum proc_cn_mcast_op op = PROC_CN_MCAST_LISTEN;
111 iov[2].iov_base = &op;
112 iov[2].iov_len = sizeof(op);
113
114 if (writev(sock, iov, 3) == -1) {
115 fprintf(stderr, "Error: cannot write to netlink socket\n");
116 exit(1);
117 }
118
119 return sock;
120}
121
122
123static int procevent_monitor(const int sock, pid_t mypid) {
124 ssize_t len;
125 struct nlmsghdr *nlmsghdr;
126
127 // timeout in order to re-enable firejail module trace
128 struct timeval tv;
129 tv.tv_sec = 30;
130 tv.tv_usec = 0;
131
132 while (1) {
133#define BUFFSIZE 4096
134 char __attribute__ ((aligned(NLMSG_ALIGNTO)))buf[BUFFSIZE];
135
136 fd_set readfds;
137 int max;
138 FD_ZERO(&readfds);
139 FD_SET(sock, &readfds);
140 max = sock;
141 max++;
142
143 int rv = select(max, &readfds, NULL, NULL, &tv);
144 if (rv == -1) {
145 fprintf(stderr, "recv: %s\n", strerror(errno));
146 return -1;
147 }
148
149 // timeout
150 if (rv == 0) {
151 tv.tv_sec = 30;
152 tv.tv_usec = 0;
153 continue;
154 }
155
156
157 if ((len = recv(sock, buf, sizeof(buf), 0)) == 0) {
158 return 0;
159 }
160 if (len == -1) {
161 if (errno == EINTR) {
162 return 0;
163 } else {
164 fprintf(stderr,"recv: %s\n", strerror(errno));
165 return -1;
166 }
167 }
168
169 for (nlmsghdr = (struct nlmsghdr *)buf;
170 NLMSG_OK (nlmsghdr, len);
171 nlmsghdr = NLMSG_NEXT (nlmsghdr, len)) {
172
173 struct cn_msg *cn_msg;
174 struct proc_event *proc_ev;
175 struct tm tm;
176 time_t now;
177
178 if ((nlmsghdr->nlmsg_type == NLMSG_ERROR) ||
179 (nlmsghdr->nlmsg_type == NLMSG_NOOP))
180 continue;
181
182 cn_msg = NLMSG_DATA(nlmsghdr);
183 if ((cn_msg->id.idx != CN_IDX_PROC) ||
184 (cn_msg->id.val != CN_VAL_PROC))
185 continue;
186
187 (void)time(&now);
188 (void)localtime_r(&now, &tm);
189 char line[PIDS_BUFLEN];
190 char *lineptr = line;
191 sprintf(lineptr, "%2.2d:%2.2d:%2.2d", tm.tm_hour, tm.tm_min, tm.tm_sec);
192 lineptr += strlen(lineptr);
193
194 proc_ev = (struct proc_event *)cn_msg->data;
195 pid_t pid = 0;
196 pid_t child = 0;
197 int remove_pid = 0;
198 switch (proc_ev->what) {
199 case PROC_EVENT_FORK:
200 if (proc_ev->event_data.fork.child_pid !=
201 proc_ev->event_data.fork.child_tgid)
202 continue; // this is a thread, not a process
203 pid = proc_ev->event_data.fork.parent_tgid;
204 if (pids[pid].level > 0) {
205 child = proc_ev->event_data.fork.child_tgid;
206 child %= max_pids;
207 pids[child].level = pids[pid].level + 1;
208 pids[child].uid = pid_get_uid(child);
209 }
210 sprintf(lineptr, " fork");
211 break;
212 case PROC_EVENT_EXEC:
213 pid = proc_ev->event_data.exec.process_tgid;
214 sprintf(lineptr, " exec");
215 break;
216
217 case PROC_EVENT_EXIT:
218 if (proc_ev->event_data.exit.process_pid !=
219 proc_ev->event_data.exit.process_tgid)
220 continue; // this is a thread, not a process
221
222 pid = proc_ev->event_data.exit.process_tgid;
223 remove_pid = 1;
224 sprintf(lineptr, " exit");
225 break;
226
227 case PROC_EVENT_UID:
228 pid = proc_ev->event_data.id.process_tgid;
229 sprintf(lineptr, " uid ");
230 break;
231
232 case PROC_EVENT_GID:
233 pid = proc_ev->event_data.id.process_tgid;
234 sprintf(lineptr, " gid ");
235 break;
236
237 case PROC_EVENT_SID:
238 pid = proc_ev->event_data.sid.process_tgid;
239 sprintf(lineptr, " sid ");
240 break;
241
242 default:
243 sprintf(lineptr, "\n");
244 continue;
245 }
246
247 int add_new = 0;
248 if (pids[pid].level < 0) // not a firejail process
249 continue;
250 else if (pids[pid].level == 0) { // new porcess, do we track it?
251 if (pid_is_firejail(pid) && mypid == 0) {
252 pids[pid].level = 1;
253 add_new = 1;
254 }
255 else {
256 pids[pid].level = -1;
257 continue;
258 }
259 }
260
261 lineptr += strlen(lineptr);
262 sprintf(lineptr, " %u", pid);
263 lineptr += strlen(lineptr);
264
265 char *user = pids[pid].user;
266 if (!user)
267 user = pid_get_user_name(pids[pid].uid);
268 if (user) {
269 pids[pid].user = user;
270 sprintf(lineptr, " (%s)", user);
271 lineptr += strlen(lineptr);
272 }
273
274
275 int sandbox_closed = 0; // exit sandbox flag
276 char *cmd = pids[pid].cmd;
277 if (!cmd) {
278 cmd = pid_proc_cmdline(pid);
279 }
280 if (add_new) {
281 if (!cmd)
282 sprintf(lineptr, " NEW SANDBOX\n");
283 else
284 sprintf(lineptr, " NEW SANDBOX: %s\n", cmd);
285 lineptr += strlen(lineptr);
286 }
287 else if (proc_ev->what == PROC_EVENT_EXIT && pids[pid].level == 1) {
288 sprintf(lineptr, " EXIT SANDBOX\n");
289 lineptr += strlen(lineptr);
290 if (mypid == pid)
291 sandbox_closed = 1;
292 }
293 else {
294 if (!cmd) {
295 cmd = pid_proc_cmdline(pid);
296 }
297 if (cmd == NULL)
298 sprintf(lineptr, "\n");
299 else {
300 sprintf(lineptr, " %s\n", cmd);
301 free(cmd);
302 }
303 lineptr += strlen(lineptr);
304 }
305 (void) lineptr;
306
307 // print the event
308 printf("%s", line);
309 fflush(0);
310
311 // unflag pid for exit events
312 if (remove_pid) {
313 if (pids[pid].user)
314 free(pids[pid].user);
315 if (pids[pid].cmd)
316 free(pids[pid].cmd);
317 memset(&pids[pid], 0, sizeof(Process));
318 }
319
320 // print forked child
321 if (child) {
322 cmd = pid_proc_cmdline(child);
323 if (cmd) {
324 printf("\tchild %u %s\n", child, cmd);
325 free(cmd);
326 }
327 else
328 printf("\tchild %u\n", child);
329 }
330
331 // on uid events the uid is changing
332 if (proc_ev->what == PROC_EVENT_UID) {
333 if (pids[pid].user)
334 free(pids[pid].user);
335 pids[pid].user = 0;
336 pids[pid].uid = pid_get_uid(pid);
337 }
338
339 if (sandbox_closed)
340 exit(0);
341 }
342 }
343 return 0;
344}
345
346static void procevent_print_pids(void) {
347 // print files
348 int i;
349 for (i = 0; i < max_pids; i++) {
350 if (pids[i].level == 1)
351 pid_print_tree(i, 0, 1);
352 }
353 printf("\n");
354}
355
356void procevent(pid_t pid) {
357 // need to be root for this
358 if (getuid() != 0) {
359 fprintf(stderr, "Error: you need to be root to get process events\n");
360 exit(1);
361 }
362
363 // read and print sandboxed processes
364 pid_read(pid);
365 procevent_print_pids();
366
367 // monitor using netlink
368 int sock = procevent_netlink_setup();
369 if (sock < 0) {
370 fprintf(stderr, "Error: cannot open netlink socket\n");
371 exit(1);
372 }
373
374 procevent_monitor(sock, pid); // it will never return from here
375 assert(0);
376 close(sock); // quiet static analyzers
377}
diff --git a/src/firemon/route.c b/src/firemon/route.c
new file mode 100644
index 000000000..7f559c7b5
--- /dev/null
+++ b/src/firemon/route.c
@@ -0,0 +1,213 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#include <assert.h>
22#include <arpa/inet.h>
23#define MAXBUF 4096
24
25typedef struct iflist_t {
26 struct iflist_t *next;
27 uint32_t ip;
28} IfList;
29static IfList *ifs = NULL;
30static char last_start[MAXBUF + 1];
31
32static IfList *list_find(uint32_t ip, uint32_t mask) {
33 IfList *ptr = ifs;
34 while (ptr) {
35 if ((ptr->ip & mask) == (ip & mask))
36 return ptr;
37 ptr = ptr->next;
38 }
39
40 return NULL;
41}
42
43static void extract_if(const char *fname) {
44 // clear interface list
45 while (ifs) {
46 IfList *tmp = ifs->next;
47 free(ifs);
48 ifs = tmp;
49 }
50 assert(ifs == NULL);
51
52 FILE *fp = fopen(fname, "r");
53 if (!fp)
54 return;
55
56 char buf[MAXBUF];
57 int state = 0; // 0 -wait for Local
58 //
59 while (fgets(buf, MAXBUF, fp)) {
60 // remove blanks, \n
61 char *ptr = buf;
62 while (*ptr == ' ' || *ptr == '\t')
63 ptr++;
64 char *start = ptr;
65 if (*start == '\0')
66 continue;
67 ptr = strchr(ptr, '\n');
68 if (ptr)
69 *ptr = '\0';
70
71 if (state == 0) {
72 if (strncmp(buf, "Local:", 6) == 0) {
73 state = 1;
74 continue;
75 }
76 }
77 else if (state == 1) {
78 // remove broadcast addresses
79 if (strstr(start,"BROADCAST"))
80 continue;
81 else if (*start == '+')
82 continue;
83 else if (*start == '|') {
84 memset(last_start, 0, MAXBUF + 1);
85 strncpy(last_start, start, MAXBUF);
86 continue;
87 }
88 else if (strstr(buf, "LOCAL")) {
89// printf("%s %s\n", last_start, start);
90 unsigned mbits;
91 sscanf(start, "/%u", &mbits);
92 if (mbits != 32)
93 continue;
94
95 unsigned a, b, c, d;
96 if (sscanf(last_start, "|-- %u.%u.%u.%u", &a, &b, &c, &d) != 4 || a > 255 || b > 255 || c > 255 || d > 255)
97 continue;
98
99 IfList *newif = malloc(sizeof(IfList));
100 if (!newif)
101 errExit("malloc");
102 newif->ip = a * 0x1000000 + b * 0x10000 + c * 0x100 + d;
103 newif->next = ifs;
104 ifs = newif;
105 }
106 }
107 }
108
109 fclose(fp);
110
111
112}
113
114static void print_route(const char *fname) {
115 FILE *fp = fopen(fname, "r");
116 if (!fp)
117 return;
118
119 printf(" Route table:\n");
120 char buf[MAXBUF];
121 while (fgets(buf, MAXBUF, fp)) {
122 // remove blanks, \n
123 char *ptr = buf;
124 while (*ptr == ' ' || *ptr == '\t')
125 ptr++;
126 char *start = ptr;
127 if (*start == '\0')
128 continue;
129 ptr = strchr(ptr, '\n');
130 if (ptr)
131 *ptr = '\0';
132
133 // remove table header
134 //Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
135 if (strncmp(start, "Iface", 5) == 0)
136 continue;
137
138 // extract data
139 char ifname[64];
140 char destination[64];
141 char gateway[64];
142 char flags[64];
143 char refcnt[64];
144 char use[64];
145 char metric[64];
146 char mask[64];
147 int rv = sscanf(start, "%s %s %s %s %s %s %s %s\n", ifname, destination, gateway, flags, refcnt, use, metric, mask);
148 if (rv != 8)
149 continue;
150
151 // destination ip
152 uint32_t destip;
153 sscanf(destination, "%x", &destip);
154 destip = ntohl(destip);
155 uint32_t destmask;
156 sscanf(mask, "%x", &destmask);
157 destmask = ntohl(destmask);
158 uint32_t gw;
159 sscanf(gateway, "%x", &gw);
160 gw = ntohl(gw);
161
162// printf("#%s# #%s# #%s# #%s# #%s# #%s# #%s# #%s#\n", ifname, destination, gateway, flags, refcnt, use, metric, mask);
163 if (gw != 0)
164 printf(" %u.%u.%u.%u/%u via %u.%u.%u.%u, dev %s, metric %s\n",
165 PRINT_IP(destip), mask2bits(destmask),
166 PRINT_IP(gw),
167 ifname,
168 metric);
169 else { // this is an interface
170 IfList *ifentry = list_find(destip, destmask);
171 if (ifentry) {
172 printf(" %u.%u.%u.%u/%u, dev %s, scope link src %d.%d.%d.%d\n",
173 PRINT_IP(destip), mask2bits(destmask),
174 ifname,
175 PRINT_IP(ifentry->ip));
176 }
177 }
178 }
179
180 fclose(fp);
181
182}
183
184void route(pid_t pid) {
185 if (getuid() == 0)
186 firemon_drop_privs();
187
188 pid_read(pid);
189
190 // print processes
191 int i;
192 for (i = 0; i < max_pids; i++) {
193 if (pids[i].level == 1) {
194 pid_print_list(i, 0);
195 int child = find_child(i);
196 if (child != -1) {
197 char *fname;
198 if (asprintf(&fname, "/proc/%d/net/fib_trie", child) == -1)
199 errExit("asprintf");
200 extract_if(fname);
201 free(fname);
202
203 if (asprintf(&fname, "/proc/%d/net/route", child) == -1)
204 errExit("asprintf");
205 print_route(fname);
206 free(fname);
207 printf("\n");
208 }
209 }
210 }
211}
212
213
diff --git a/src/firemon/seccomp.c b/src/firemon/seccomp.c
new file mode 100644
index 000000000..4ffc93f2e
--- /dev/null
+++ b/src/firemon/seccomp.c
@@ -0,0 +1,69 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21
22#define MAXBUF 4098
23static void print_seccomp(int pid) {
24 char *file;
25 if (asprintf(&file, "/proc/%d/status", pid) == -1) {
26 errExit("asprintf");
27 exit(1);
28 }
29
30 FILE *fp = fopen(file, "r");
31 if (!fp) {
32 printf(" Error: cannot open %s\n", file);
33 free(file);
34 return;
35 }
36
37 char buf[MAXBUF];
38 while (fgets(buf, MAXBUF, fp)) {
39 if (strncmp(buf, "Seccomp:", 8) == 0) {
40 printf(" %s", buf);
41 fflush(0);
42 fclose(fp);
43 free(file);
44 return;
45 }
46 }
47 fclose(fp);
48 free(file);
49}
50
51void seccomp(pid_t pid) {
52 if (getuid() == 0)
53 firemon_drop_privs();
54
55 pid_read(pid); // include all processes
56
57 // print processes
58 int i;
59 for (i = 0; i < max_pids; i++) {
60 if (pids[i].level == 1) {
61 pid_print_list(i, 0);
62 int child = find_child(i);
63 if (child != -1)
64 print_seccomp(child);
65 }
66 }
67 printf("\n");
68}
69
diff --git a/src/firemon/top.c b/src/firemon/top.c
new file mode 100644
index 000000000..1eb753694
--- /dev/null
+++ b/src/firemon/top.c
@@ -0,0 +1,297 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21#include <termios.h>
22#include <sys/ioctl.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <unistd.h>
26
27static unsigned pgs_rss = 0;
28static unsigned pgs_shared = 0;
29static unsigned clocktick = 0;
30static unsigned long long sysuptime = 0;
31
32static char *get_header(void) {
33 char *rv;
34 if (asprintf(&rv, "%-5.5s %-9.9s %-8.8s %-8.8s %-5.5s %-4.4s %-9.9s %s",
35 "PID", "User", "RES(KiB)", "SHR(KiB)", "CPU%", "Prcs", "Uptime", "Command") == -1)
36 errExit("asprintf");
37
38 return rv;
39}
40
41
42// recursivity!!!
43static char *print_top(unsigned index, unsigned parent, unsigned *utime, unsigned *stime, unsigned itv, float *cpu, int *cnt) {
44 char *rv = NULL;
45
46 char procdir[20];
47 snprintf(procdir, 20, "/proc/%u", index);
48 struct stat s;
49 if (stat(procdir, &s) == -1)
50 return NULL;
51
52 if (pids[index].level == 1) {
53 pgs_rss = 0;
54 pgs_shared = 0;
55 *utime = 0;
56 *stime = 0;
57 *cnt = 0;
58 }
59
60 (*cnt)++;
61 pid_getmem(index, &pgs_rss, &pgs_shared);
62 unsigned utmp;
63 unsigned stmp;
64 pid_get_cpu_time(index, &utmp, &stmp);
65 *utime += utmp;
66 *stime += stmp;
67
68
69 int i;
70 for (i = index + 1; i < max_pids; i++) {
71 if (pids[i].parent == index)
72 print_top(i, index, utime, stime, itv, cpu, cnt);
73 }
74
75 if (pids[index].level == 1) {
76 // pid
77 char pidstr[10];
78 snprintf(pidstr, 10, "%u", index);
79
80 // command
81 char *cmd = pid_proc_cmdline(index);
82 char *ptrcmd;
83 if (cmd == NULL) {
84 if (pids[index].zombie)
85 ptrcmd = "(zombie)";
86 else
87 ptrcmd = "";
88 }
89 else
90 ptrcmd = cmd;
91
92 // user
93 char *user = pid_get_user_name(pids[index].uid);
94 char *ptruser;
95 if (user)
96 ptruser = user;
97 else
98 ptruser = "";
99
100 // memory
101 int pgsz = getpagesize();
102 char rss[10];
103 snprintf(rss, 10, "%u", pgs_rss * pgsz / 1024);
104 char shared[10];
105 snprintf(shared, 10, "%u", pgs_shared * pgsz / 1024);
106
107 // uptime
108 unsigned long long uptime = pid_get_start_time(index);
109 if (clocktick == 0)
110 clocktick = sysconf(_SC_CLK_TCK);
111 uptime /= clocktick;
112 uptime = sysuptime - uptime;
113 unsigned sec = uptime % 60;
114 uptime -= sec;
115 uptime /= 60;
116 unsigned min = uptime % 60;
117 uptime -= min;
118 uptime /= 60;
119 unsigned hour = uptime;
120 char uptime_str[50];
121 snprintf(uptime_str, 50, "%02u:%02u:%02u", hour, min, sec);
122
123 // cpu
124 itv *= clocktick;
125 float ud = (float) (*utime - pids[index].utime) / itv * 100;
126 float sd = (float) (*stime - pids[index].stime) / itv * 100;
127 float cd = ud + sd;
128 *cpu = cd;
129 char cpu_str[10];
130 snprintf(cpu_str, 10, "%2.1f", cd);
131
132 // process count
133 char prcs_str[10];
134 snprintf(prcs_str, 10, "%d", *cnt);
135
136 if (asprintf(&rv, "%-5.5s %-9.9s %-8.8s %-8.8s %-5.5s %-4.4s %-9.9s %s",
137 pidstr, ptruser, rss, shared, cpu_str, prcs_str, uptime_str, ptrcmd) == -1)
138 errExit("asprintf");
139
140 if (cmd)
141 free(cmd);
142 if (user)
143 free(user);
144
145 }
146
147 return rv;
148}
149
150
151typedef struct node_t {
152 struct node_t *next;
153 char *line;
154 float cpu;
155} Node;
156
157static Node *head = NULL;
158
159static void head_clear(void) {
160 Node *ptr = head;
161 while (ptr) {
162 if (ptr->line)
163 free(ptr->line);
164 Node *next = ptr->next;
165 free(ptr);
166 ptr = next;
167 }
168
169 head = NULL;
170}
171
172static void head_add(float cpu, char *line) {
173 // allocate a new node structure
174 Node *node = malloc(sizeof(Node));
175 if (!node)
176 errExit("malloc");
177 node->line = line;
178 node->cpu = cpu;
179 node->next = NULL;
180
181 // insert in first list position
182 if (head == NULL || head->cpu < cpu) {
183 node->next = head;
184 head = node;
185 return;
186 }
187
188 // insert in the right place
189 Node *ptr = head;
190 while (1) {
191 // last position
192 Node *current = ptr->next;
193 if (current == NULL) {
194 ptr->next = node;
195 return;
196 }
197
198 // current position
199 if (current->cpu < cpu) {
200 ptr->next = node;
201 node->next = current;
202 return;
203 }
204
205 ptr = current;
206 }
207}
208
209void head_print(int col, int row) {
210 Node *ptr = head;
211 int current = 0;
212 while (ptr) {
213 if (current >= row)
214 break;
215
216 if (strlen(ptr->line) > col)
217 ptr->line[col] = '\0';
218
219 if (ptr->next == NULL || current == (row - 1)) {
220 printf("%s", ptr->line);
221 fflush(0);
222 }
223 else
224 printf("%s\n", ptr->line);
225
226 ptr = ptr->next;
227 current++;
228 }
229}
230
231void top(void) {
232 if (getuid() == 0)
233 firemon_drop_privs();
234
235 while (1) {
236 // clear linked list
237 head_clear();
238
239 // set pid table
240 int i;
241 int itv = 5; // 5 second interval
242 pid_read(0);
243
244 // start cpu measurements
245 unsigned utime = 0;
246 unsigned stime = 0;
247 for (i = 0; i < max_pids; i++) {
248 if (pids[i].level == 1)
249 pid_store_cpu(i, 0, &utime, &stime);
250 }
251
252 // wait 5 seconds
253 firemon_sleep(itv);
254
255 // grab screen size
256 struct winsize sz;
257 int row = 24;
258 int col = 80;
259 if (!ioctl(0, TIOCGWINSZ, &sz)) {
260 col = sz.ws_col;
261 row = sz.ws_row;
262 }
263
264 // start printing
265 firemon_clrscr();
266 char *header = get_header();
267 if (strlen(header) > col)
268 header[col] = '\0';
269 printf("%s\n", header);
270 if (row > 0)
271 row--;
272 free(header);
273
274 // find system uptime
275 FILE *fp = fopen("/proc/uptime", "r");
276 if (fp) {
277 float f;
278 int rv = fscanf(fp, "%f", &f);
279 (void) rv;
280 sysuptime = (unsigned long long) f;
281 fclose(fp);
282 }
283
284 // print processes
285 for (i = 0; i < max_pids; i++) {
286 if (pids[i].level == 1) {
287 float cpu = 0;
288 int cnt = 0; // process count
289 char *line = print_top(i, 0, &utime, &stime, itv, &cpu, &cnt);
290 if (line)
291 head_add(cpu, line);
292 }
293 }
294 head_print(col, row);
295 }
296}
297
diff --git a/src/firemon/tree.c b/src/firemon/tree.c
new file mode 100644
index 000000000..97e0e1f13
--- /dev/null
+++ b/src/firemon/tree.c
@@ -0,0 +1,36 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21
22void tree(pid_t pid) {
23 if (getuid() == 0)
24 firemon_drop_privs();
25
26 pid_read(pid); // include all processes
27
28 // print processes
29 int i;
30 for (i = 0; i < max_pids; i++) {
31 if (pids[i].level == 1)
32 pid_print_tree(i, 0, arg_nowrap);
33 }
34 printf("\n");
35}
36
diff --git a/src/firemon/usage.c b/src/firemon/usage.c
new file mode 100644
index 000000000..52788807a
--- /dev/null
+++ b/src/firemon/usage.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "firemon.h"
21
22void usage(void) {
23 printf("firemon - version %s\n", VERSION);
24 printf("Usage: firemon [OPTIONS] [PID]\n\n");
25 printf("Monitor processes started in a Firejail sandbox. Without any PID specified,\n");
26 printf("all processes started by Firejail are monitored. Descendants of these processes\n");
27 printf("are also being monitored.\n\n");
28 printf("Options:\n");
29 printf("\t--arp - print ARP table for each sandbox.\n\n");
30 printf("\t--caps - print capabilities configuration for each sandbox.\n\n");
31 printf("\t--cgroup - print control group information for each sandbox.\n\n");
32 printf("\t--cpu - print CPU affinity for each sandbox.\n\n");
33 printf("\t--help, -? - this help screen.\n\n");
34 printf("\t--interface - print network interface information for each sandbox.\n\n");
35 printf("\t--list - list all sandboxes.\n\n");
36 printf("\t--name=name - print information only about named sandbox.\n\n");
37 printf("\t--netstats - monitor network statistics for sandboxes creating a new\n");
38 printf("\t\tnetwork namespace.\n\n");
39 printf("\t--route - print route table for each sandbox.\n\n");
40 printf("\t--seccomp - print seccomp configuration for each sandbox.\n\n");
41 printf("\t--tree - print a tree of all sandboxed processes.\n\n");
42 printf("\t--top - monitor the most CPU-intensive sandboxes.\n\n");
43 printf("\t--version - print program version and exit.\n\n");
44
45 printf("Without any options, firemon monitors all fork, exec, id change, and exit events\n");
46 printf("in the sandbox. Monitoring a specific PID is also supported.\n\n");
47
48 printf("Option --list prints a list of all sandboxes. The format for each entry is as\n");
49 printf("follows:\n\n");
50 printf("\tPID:USER:Command\n\n");
51
52 printf("Option --tree prints the tree of processes running in the sandbox. The format\n");
53 printf("for each process entry is as follows:\n\n");
54 printf("\tPID:USER:Command\n\n");
55
56 printf("Option --top is similar to the UNIX top command, however it applies only to\n");
57 printf("sandboxes. Listed below are the available fields (columns) in alphabetical\n");
58 printf("order:\n\n");
59 printf("\tCommand - command used to start the sandbox.\n");
60 printf("\tCPU%% - CPU usage, the sandbox share of the elapsed CPU time since the\n");
61 printf("\t last screen update\n");
62 printf("\tPID - Unique process ID for the task controlling the sandbox.\n");
63 printf("\tPrcs - number of processes running in sandbox, including the controlling\n");
64 printf("\t process.\n");
65 printf("\tRES - Resident Memory Size (KiB), sandbox non-swapped physical memory.\n");
66 printf("\t It is a sum of the RES values for all processes running in the\n");
67 printf("\t sandbox.\n");
68 printf("\tSHR - Shared Memory Size (KiB), it reflects memory shared with other\n");
69 printf("\t processes. It is a sum of the SHR values for all processes running\n");
70 printf("\t in the sandbox, including the controlling process.\n");
71 printf("\tUptime - sandbox running time in hours:minutes:seconds format.\n");
72 printf("\tUser - The owner of the sandbox.\n");
73 printf("\n");
74 printf("License GPL version 2 or later\n");
75 printf("Homepage: http://firejail.sourceforge.net\n");
76 printf("\n");
77}
diff --git a/src/fshaper/fshaper.sh b/src/fshaper/fshaper.sh
new file mode 100755
index 000000000..4045fd5a4
--- /dev/null
+++ b/src/fshaper/fshaper.sh
@@ -0,0 +1,69 @@
1#!/bin/bash
2
3usage() {
4 echo "Usage:"
5 echo " fshaper.sh --status"
6 echo " fshaper.sh --clear device"
7 echo " fshaper.sh --set device download-speed upload-speed"
8}
9
10if [ "$1" = "--status" ]; then
11 /sbin/tc -s qdisc ls
12 /sbin/tc -s class ls
13 exit
14fi
15
16if [ "$1" = "--clear" ]; then
17 if [ $# -ne 2 ]; then
18 echo "Error: invalid command"
19 usage
20 exit
21 fi
22
23 DEV=$2
24 echo "Removing bandwith limits"
25 /sbin/tc qdisc del dev $DEV root 2> /dev/null > /dev/null
26 /sbin/tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null
27 exit
28
29fi
30
31if [ "$1" = "--set" ]; then
32 DEV=$2
33 echo "Removing bandwith limit"
34 /sbin/tc qdisc del dev $DEV ingress #2> /dev/null > /dev/null
35
36 if [ $# -ne 4 ]; then
37 echo "Error: missing parameters"
38 usage
39 exit
40 fi
41
42 DEV=$2
43 echo "Configuring interface $DEV "
44
45 IN=$3
46 IN=$((${IN} * 8))
47 echo "Download speed ${IN}kbps"
48
49 OUT=$4
50 OUT=$((${OUT} * 8))
51 echo "Upload speed ${OUT}kbps"
52
53 echo "cleaning limits"
54 /sbin/tc qdisc del dev $DEV root 2> /dev/null > /dev/null
55 /sbin/tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null
56
57 echo "configuring tc ingress"
58 /sbin/tc qdisc add dev $DEV handle ffff: ingress #2> /dev/null > /dev/null
59 /sbin/tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \
60 0.0.0.0/0 police rate ${IN}kbit burst 10k drop flowid :1 #2> /dev/null > /dev/null
61
62 echo "configuring tc egress"
63 /sbin/tc qdisc add dev $DEV root tbf rate ${OUT}kbit latency 25ms burst 10k #2> /dev/null > /dev/null
64 exit
65fi
66
67echo "Error: missing parameters"
68usage
69exit 1
diff --git a/src/ftee/Makefile.in b/src/ftee/Makefile.in
new file mode 100644
index 000000000..6911f0a3c
--- /dev/null
+++ b/src/ftee/Makefile.in
@@ -0,0 +1,24 @@
1all: ftee
2
3PREFIX=@prefix@
4VERSION=@PACKAGE_VERSION@
5NAME=@PACKAGE_NAME@
6
7H_FILE_LIST = $(wildcard *.[h])
8C_FILE_LIST = $(wildcard *.c)
9OBJS = $(C_FILE_LIST:.c=.o)
10BINOBJS = $(foreach file, $(OBJS), $file)
11CFLAGS += -ggdb -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(PREFIX)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
12LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
13
14%.o : %.c $(H_FILE_LIST)
15 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
16
17ftee: $(OBJS)
18 $(CC) $(LDFLAGS) -o $@ $(OBJS)
19
20clean:; rm -f *.o ftee
21
22distclean: clean
23 rm -fr Makefile
24
diff --git a/src/ftee/ftee.h b/src/ftee/ftee.h
new file mode 100644
index 000000000..a28cc5bb5
--- /dev/null
+++ b/src/ftee/ftee.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#ifndef FTEE_H
21#define FTEE_H
22#include "../include/common.h"
23
24#endif \ No newline at end of file
diff --git a/src/ftee/main.c b/src/ftee/main.c
new file mode 100644
index 000000000..4dca3cf48
--- /dev/null
+++ b/src/ftee/main.c
@@ -0,0 +1,228 @@
1#include "ftee.h"
2#include <errno.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <unistd.h>
6#define MAXBUF 512
7
8static unsigned char buf[MAXBUF];
9
10static FILE *out_fp = NULL;
11static int out_cnt = 0;
12static int out_max = 500 * 1024;
13
14static void log_close(void) {
15 if (out_fp) {
16 fclose(out_fp);
17 out_fp = NULL;
18 }
19}
20
21static void log_rotate(const char *fname) {
22 struct stat s;
23 int index = strlen(fname);
24 char *name1 = malloc(index + 2 + 1);
25 char *name2 = malloc(index + 2 + 1);
26 if (!name1 || !name2)
27 errExit("malloc");
28 strcpy(name1, fname);
29 strcpy(name2, fname);
30 fflush(0);
31
32 // delete filename.5
33 sprintf(name1 + index, ".5");
34 if (stat(name1, &s) == 0) {
35 int rv = unlink(name1);
36 if (rv == -1)
37 perror("unlink");
38 }
39
40 // move files 1 to 4 down one position
41 sprintf(name2 + index, ".4");
42 if (stat(name2, &s) == 0) {
43 int rv = rename(name2, name1);
44 if (rv == -1)
45 perror("rename");
46 }
47
48 sprintf(name1 + index, ".3");
49 if (stat(name1, &s) == 0) {
50 int rv = rename(name1, name2);
51 if (rv == -1)
52 perror("rename");
53 }
54
55 sprintf(name2 + index, ".2");
56 if (stat(name2, &s) == 0) {
57 /* coverity[toctou] */
58 int rv = rename(name2, name1);
59 if (rv == -1)
60 perror("rename");
61 }
62
63 sprintf(name1 + index, ".1");
64 if (stat(name1, &s) == 0) {
65 int rv = rename(name1, name2);
66 if (rv == -1)
67 perror("rename");
68 }
69
70 // move the first file
71 if (out_fp)
72 fclose(out_fp);
73
74 out_fp = NULL;
75 if (stat(fname, &s) == 0) {
76 int rv = rename(fname, name1);
77 if (rv == -1)
78 perror("rename");
79 }
80
81 free(name1);
82 free(name2);
83}
84
85static void log_write(const unsigned char *str, int len, const char *fname) {
86 assert(fname);
87
88 if (out_fp == NULL) {
89 out_fp = fopen(fname, "w");
90 if (!out_fp) {
91 fprintf(stderr, "Error: cannot open log file %s\n", fname);
92 exit(1);
93 }
94 out_cnt = 0;
95 }
96
97 // rotate files
98 out_cnt += len;
99 if (out_cnt >= out_max) {
100 log_rotate(fname);
101
102 // reopen the first file
103 if (out_fp)
104 fclose(out_fp);
105 out_fp = fopen(fname, "w");
106 if (!out_fp) {
107 fprintf(stderr, "Error: cannot open log file %s\n", fname);
108 exit(1);
109 }
110 out_cnt = len;
111 }
112
113 fwrite(str, len, 1, out_fp);
114 fflush(0);
115}
116
117
118// return 1 if the file is a directory
119static int is_dir(const char *fname) {
120 assert(fname);
121 if (*fname == '\0')
122 return 0;
123
124 // if fname doesn't end in '/', add one
125 int rv;
126 struct stat s;
127 if (fname[strlen(fname) - 1] == '/')
128 rv = stat(fname, &s);
129 else {
130 char *tmp;
131 if (asprintf(&tmp, "%s/", fname) == -1) {
132 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
133 exit(1);
134 }
135 rv = stat(tmp, &s);
136 free(tmp);
137 }
138
139 if (rv == -1)
140 return 0;
141
142 if (S_ISDIR(s.st_mode))
143 return 1;
144
145 return 0;
146}
147
148// return 1 if the file is a link
149static int is_link(const char *fname) {
150 assert(fname);
151 if (*fname == '\0')
152 return 0;
153
154 struct stat s;
155 if (lstat(fname, &s) == 0) {
156 if (S_ISLNK(s.st_mode))
157 return 1;
158 }
159
160 return 0;
161}
162
163
164
165
166
167static void usage(void) {
168 printf("Usage: ftee filename\n");
169}
170
171int main(int argc, char **argv) {
172 if (argc < 2) {
173 fprintf(stderr, "Error: please provide a filename to store the program output\n");
174 usage();
175 exit(1);
176 }
177 char *fname = argv[1];
178
179
180 // do not accept directories, links, and files with ".."
181 if (strstr(fname, "..") || is_link(fname) || is_dir(fname)) {
182 fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n");
183 exit(1);
184 }
185
186 struct stat s;
187 if (stat(fname, &s) == 0) {
188 // check permissions
189 if (s.st_uid != getuid() || s.st_gid != getgid()) {
190 fprintf(stderr, "Error: the output file needs to be owned by the current user.\n");
191 exit(1);
192 }
193
194 // check hard links
195 if (s.st_nlink != 1) {
196 fprintf(stderr, "Error: no hard links allowed.\n");
197 exit(1);
198 }
199 }
200
201 // check if we can append to this file
202 /* coverity[toctou] */
203 FILE *fp = fopen(fname, "a");
204 if (!fp) {
205 fprintf(stderr, "Error: cannot open output file %s\n", fname);
206 exit(1);
207 }
208 fclose(fp);
209
210
211 // preserve the last log file
212 log_rotate(fname);
213
214 setvbuf (stdout, NULL, _IONBF, 0);
215 while(1) {
216 int n = read(0, buf, sizeof(buf));
217 if (n < 0 && errno == EINTR)
218 continue;
219 if (n <= 0)
220 break;
221
222 fwrite(buf, n, 1, stdout);
223 log_write(buf, n, fname);
224 }
225
226 log_close();
227 return 0;
228}
diff --git a/src/include/common.h b/src/include/common.h
new file mode 100644
index 000000000..7ce1e9290
--- /dev/null
+++ b/src/include/common.h
@@ -0,0 +1,115 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#ifndef COMMON_H
22#define COMMON_H
23#define _GNU_SOURCE
24#include <stdio.h>
25#include <sys/types.h>
26#include <unistd.h>
27#include <stdlib.h>
28#include <stdint.h>
29#include <stddef.h>
30#include <string.h>
31#include <ctype.h>
32#include <assert.h>
33
34#define errExit(msg) do { char msgout[500]; sprintf(msgout, "Error %s:%s(%d)", msg, __FUNCTION__, __LINE__); perror(msgout); exit(1);} while (0)
35
36// macro to print ip addresses in a printf statement
37#define PRINT_IP(A) \
38((int) (((A) >> 24) & 0xFF)), ((int) (((A) >> 16) & 0xFF)), ((int) (((A) >> 8) & 0xFF)), ((int) ( (A) & 0xFF))
39
40// macro to print a mac addresses in a printf statement
41#define PRINT_MAC(A) \
42((unsigned) (*(A)) & 0xff), ((unsigned) (*((A) + 1) & 0xff)), ((unsigned) (*((A) + 2) & 0xff)), \
43((unsigned) (*((A) + 3)) & 0xff), ((unsigned) (*((A) + 4) & 0xff)), ((unsigned) (*((A) + 5)) & 0xff)
44
45// the number of bits in a network mask
46static inline uint8_t mask2bits(uint32_t mask) {
47 uint32_t tmp = 0x80000000;
48 int i;
49 uint8_t rv = 0;
50
51 for (i = 0; i < 32; i++, tmp >>= 1) {
52 if (tmp & mask)
53 rv++;
54 else
55 break;
56 }
57 return rv;
58}
59
60// read an IPv4 address and convert it to uint32_t
61static inline int atoip(const char *str, uint32_t *ip) {
62 unsigned a, b, c, d;
63
64 if (sscanf(str, "%u.%u.%u.%u", &a, &b, &c, &d) != 4 || a > 255 || b > 255 || c > 255 || d > 255)
65 return 1;
66
67 *ip = a * 0x1000000 + b * 0x10000 + c * 0x100 + d;
68 return 0;
69}
70
71// verify an ip address is in the network range given by ifip and mask
72static inline char *in_netrange(uint32_t ip, uint32_t ifip, uint32_t ifmask) {
73 if ((ip & ifmask) != (ifip & ifmask))
74 return "Error: the IP address is not in the interface range\n";
75 else if ((ip & ifmask) == ip)
76 return "Error: the IP address is a network address\n";
77 else if ((ip | ~ifmask) == ip)
78 return "Error: the IP address is a network address\n";
79 return NULL;
80}
81
82// read a mac address
83static inline int atomac(char *str, unsigned char macAddr[6]) {
84 unsigned mac[6];
85
86 if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 6)
87 return 1;
88
89 int i;
90 for (i = 0; i < 6; i++) {
91 if (mac[i] > 0xff)
92 return 1;
93
94 macAddr[i] = (unsigned char) mac[i];
95 }
96
97 return 0;
98}
99
100// check a mac address is configured
101static inline int mac_not_zero(const unsigned char mac[6]) {
102 int i;
103 for (i = 0; i < 6; i++) {
104 if (mac[i] != 0)
105 return 1;
106 }
107
108 return 0;
109}
110
111int join_namespace(pid_t pid, char *type);
112int name2pid(const char *name, pid_t *pid);
113char *pid_proc_comm(const pid_t pid);
114char *pid_proc_cmdline(const pid_t pid);
115#endif
diff --git a/src/include/libnetlink.h b/src/include/libnetlink.h
new file mode 100644
index 000000000..e9cd6b186
--- /dev/null
+++ b/src/include/libnetlink.h
@@ -0,0 +1,163 @@
1/* file extracted from iproute2 software package
2 *
3 * Original source code:
4 *
5 * Information:
6 * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2
7 *
8 * Download:
9 * http://www.kernel.org/pub/linux/utils/net/iproute2/
10 *
11 * Repository:
12 * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
13 *
14 * License: GPL v2
15 */
16
17
18#ifndef __LIBNETLINK_H__
19#define __LIBNETLINK_H__ 1
20
21#define _GNU_SOURCE
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdint.h>
25#include <string.h>
26#include <asm/types.h>
27#include <linux/netlink.h>
28#include <linux/rtnetlink.h>
29#include <linux/if_link.h>
30#include <linux/if_addr.h>
31#include <linux/neighbour.h>
32
33struct rtnl_handle
34{
35 int fd;
36 struct sockaddr_nl local;
37 struct sockaddr_nl peer;
38 __u32 seq;
39 __u32 dump;
40};
41
42extern int rcvbuf;
43
44extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions);
45extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol);
46extern void rtnl_close(struct rtnl_handle *rth);
47extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type);
48extern int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int fam, int type,
49 __u32 filt_mask);
50extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
51
52typedef int (*rtnl_filter_t)(const struct sockaddr_nl *,
53 struct nlmsghdr *n, void *);
54
55struct rtnl_dump_filter_arg
56{
57 rtnl_filter_t filter;
58 void *arg1;
59};
60
61extern int rtnl_dump_filter_l(struct rtnl_handle *rth,
62 const struct rtnl_dump_filter_arg *arg);
63extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter,
64 void *arg);
65extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
66 unsigned groups, struct nlmsghdr *answer);
67extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int);
68extern int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int);
69
70extern int addattr(struct nlmsghdr *n, int maxlen, int type);
71extern int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data);
72extern int addattr16(struct nlmsghdr *n, int maxlen, int type, __u16 data);
73extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data);
74extern int addattr64(struct nlmsghdr *n, int maxlen, int type, __u64 data);
75extern int addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *data);
76
77extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen);
78extern int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len);
79extern struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type);
80extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest);
81extern struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, const void *data, int len);
82extern int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *nest);
83extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
84extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen);
85
86extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
87extern int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
88 int len, unsigned short flags);
89extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len);
90extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len);
91
92#define parse_rtattr_nested(tb, max, rta) \
93 (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
94
95#define parse_rtattr_nested_compat(tb, max, rta, data, len) \
96 ({ data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
97 __parse_rtattr_nested_compat(tb, max, rta, len); })
98
99static inline __u8 rta_getattr_u8(const struct rtattr *rta)
100{
101 return *(__u8 *)RTA_DATA(rta);
102}
103static inline __u16 rta_getattr_u16(const struct rtattr *rta)
104{
105 return *(__u16 *)RTA_DATA(rta);
106}
107static inline __u32 rta_getattr_u32(const struct rtattr *rta)
108{
109 return *(__u32 *)RTA_DATA(rta);
110}
111static inline __u64 rta_getattr_u64(const struct rtattr *rta)
112{
113 __u64 tmp;
114 memcpy(&tmp, RTA_DATA(rta), sizeof(__u64));
115 return tmp;
116}
117static inline const char *rta_getattr_str(const struct rtattr *rta)
118{
119 return (const char *)RTA_DATA(rta);
120}
121
122extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler,
123 void *jarg);
124extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
125 void *jarg);
126
127#define NLMSG_TAIL(nmsg) \
128 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
129
130#ifndef IFA_RTA
131#define IFA_RTA(r) \
132 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
133#endif
134#ifndef IFA_PAYLOAD
135#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
136#endif
137
138#ifndef IFLA_RTA
139#define IFLA_RTA(r) \
140 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
141#endif
142#ifndef IFLA_PAYLOAD
143#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
144#endif
145
146#ifndef NDA_RTA
147#define NDA_RTA(r) \
148 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
149#endif
150#ifndef NDA_PAYLOAD
151#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
152#endif
153
154#ifndef NDTA_RTA
155#define NDTA_RTA(r) \
156 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndtmsg))))
157#endif
158#ifndef NDTA_PAYLOAD
159#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
160#endif
161
162#endif /* __LIBNETLINK_H__ */
163
diff --git a/src/include/pid.h b/src/include/pid.h
new file mode 100644
index 000000000..aaadaa542
--- /dev/null
+++ b/src/include/pid.h
@@ -0,0 +1,58 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#ifndef PID_H
21#define PID_H
22extern int max_pids;
23
24
25#define _GNU_SOURCE
26#include <stdio.h>
27#include <sys/types.h>
28#include <unistd.h>
29typedef struct {
30 short level; // -1 not a firejail process, 0 not investigated yet, 1 firejail process, > 1 firejail child
31 unsigned char zombie;
32 pid_t parent;
33 uid_t uid;
34 char *user;
35 char *cmd;
36 unsigned utime;
37 unsigned stime;
38 unsigned long long rx; // network rx, bytes
39 unsigned long long tx; // networking tx, bytes
40 unsigned rx_delta;
41 unsigned tx_delta;
42} Process;
43//extern Process pids[max_pids];
44extern Process *pids;
45
46// pid functions
47void pid_getmem(unsigned pid, unsigned *rss, unsigned *shared);
48void pid_get_cpu_time(unsigned pid, unsigned *utime, unsigned *stime);
49unsigned long long pid_get_start_time(unsigned pid);
50uid_t pid_get_uid(pid_t pid);
51char *pid_get_user_name(uid_t uid);
52// print functions
53void pid_print_tree(unsigned index, unsigned parent, int nowrap);
54void pid_print_list(unsigned index, int nowrap);
55void pid_store_cpu(unsigned index, unsigned parent, unsigned *utime, unsigned *stime);
56void pid_read(pid_t mon_pid);
57
58#endif
diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in
new file mode 100644
index 000000000..6e6be1910
--- /dev/null
+++ b/src/lib/Makefile.in
@@ -0,0 +1,20 @@
1PREFIX=@prefix@
2VERSION=@PACKAGE_VERSION@
3NAME=@PACKAGE_NAME@
4
5H_FILE_LIST = $(wildcard *.[h])
6C_FILE_LIST = $(wildcard *.c)
7OBJS = $(C_FILE_LIST:.c=.o)
8BINOBJS = $(foreach file, $(OBJS), $file)
9CFLAGS += -ggdb -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security
10LDFLAGS:=-pic -Wl,-z,relro -Wl,-z,now
11
12all: $(OBJS)
13
14%.o : %.c $(H_FILE_LIST)
15 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
16
17clean:; rm -f $(OBJS)
18
19distclean: clean
20 rm -fr Makefile
diff --git a/src/lib/common.c b/src/lib/common.c
new file mode 100644
index 000000000..6d928abbb
--- /dev/null
+++ b/src/lib/common.c
@@ -0,0 +1,192 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#define _GNU_SOURCE
21#include <stdio.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <sys/wait.h>
25#include <fcntl.h>
26#include <sys/syscall.h>
27#include <errno.h>
28#include <unistd.h>
29#include <sys/prctl.h>
30#include <signal.h>
31#include <dirent.h>
32#include <string.h>
33#include "../include/common.h"
34
35int join_namespace(pid_t pid, char *type) {
36 char *path;
37 if (asprintf(&path, "/proc/%u/ns/%s", pid, type) == -1)
38 errExit("asprintf");
39
40 int fd = open(path, O_RDONLY);
41 if (fd < 0) {
42 free(path);
43 fprintf(stderr, "Error: cannot open /proc/%u/ns/%s.\n", pid, type);
44 return -1;
45 }
46
47 if (syscall(__NR_setns, fd, 0) < 0) {
48 free(path);
49 fprintf(stderr, "Error: cannot join namespace %s.\n", type);
50 close(fd);
51 return -1;
52 }
53
54 close(fd);
55 free(path);
56 return 0;
57}
58
59// return 1 if error
60int name2pid(const char *name, pid_t *pid) {
61 pid_t parent = getpid();
62
63 DIR *dir;
64 if (!(dir = opendir("/proc"))) {
65 // sleep 2 seconds and try again
66 sleep(2);
67 if (!(dir = opendir("/proc"))) {
68 fprintf(stderr, "Error: cannot open /proc directory\n");
69 exit(1);
70 }
71 }
72
73 struct dirent *entry;
74 char *end;
75 while ((entry = readdir(dir))) {
76 pid_t newpid = strtol(entry->d_name, &end, 10);
77 if (end == entry->d_name || *end)
78 continue;
79 if (newpid == parent)
80 continue;
81
82 // check if this is a firejail executable
83 char *comm = pid_proc_comm(newpid);
84 if (comm) {
85 // remove \n
86 char *ptr = strchr(comm, '\n');
87 if (ptr)
88 *ptr = '\0';
89 if (strcmp(comm, "firejail")) {
90 free(comm);
91 continue;
92 }
93 free(comm);
94 }
95
96 char *cmd = pid_proc_cmdline(newpid);
97 if (cmd) {
98 // mark the end of the name
99 char *ptr = strstr(cmd, "--name=");
100 char *start = ptr;
101 if (!ptr) {
102 free(cmd);
103 continue;
104 }
105 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
106 ptr++;
107 *ptr = '\0';
108 int rv = strcmp(start + 7, name);
109 if (rv == 0) {
110 free(cmd);
111 *pid = newpid;
112 closedir(dir);
113 return 0;
114 }
115 free(cmd);
116 }
117 }
118 closedir(dir);
119 return 1;
120}
121
122#define BUFLEN 4096
123char *pid_proc_comm(const pid_t pid) {
124 // open /proc/pid/cmdline file
125 char *fname;
126 int fd;
127 if (asprintf(&fname, "/proc/%d//comm", pid) == -1)
128 return NULL;
129 if ((fd = open(fname, O_RDONLY)) < 0) {
130 free(fname);
131 return NULL;
132 }
133 free(fname);
134
135 // read file
136 unsigned char buffer[BUFLEN];
137 ssize_t len;
138 if ((len = read(fd, buffer, sizeof(buffer) - 1)) <= 0) {
139 close(fd);
140 return NULL;
141 }
142 buffer[len] = '\0';
143 close(fd);
144
145 // return a malloc copy of the command line
146 char *rv = strdup((char *) buffer);
147 if (strlen(rv) == 0) {
148 free(rv);
149 return NULL;
150 }
151 return rv;
152}
153
154char *pid_proc_cmdline(const pid_t pid) {
155 // open /proc/pid/cmdline file
156 char *fname;
157 int fd;
158 if (asprintf(&fname, "/proc/%d/cmdline", pid) == -1)
159 return NULL;
160 if ((fd = open(fname, O_RDONLY)) < 0) {
161 free(fname);
162 return NULL;
163 }
164 free(fname);
165
166 // read file
167 unsigned char buffer[BUFLEN];
168 ssize_t len;
169 if ((len = read(fd, buffer, sizeof(buffer) - 1)) <= 0) {
170 close(fd);
171 return NULL;
172 }
173 buffer[len] = '\0';
174 close(fd);
175
176 // clean data
177 int i;
178 for (i = 0; i < len; i++) {
179 if (buffer[i] == '\0')
180 buffer[i] = ' ';
181 if (buffer[i] >= 0x80) // execv in progress!!!
182 return NULL;
183 }
184
185 // return a malloc copy of the command line
186 char *rv = strdup((char *) buffer);
187 if (strlen(rv) == 0) {
188 free(rv);
189 return NULL;
190 }
191 return rv;
192}
diff --git a/src/lib/libnetlink.c b/src/lib/libnetlink.c
new file mode 100644
index 000000000..264632a01
--- /dev/null
+++ b/src/lib/libnetlink.c
@@ -0,0 +1,803 @@
1/* file extracted from iproute2 software package
2 *
3 * Original source code:
4 *
5 * Information:
6 * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2
7 *
8 * Download:
9 * http://www.kernel.org/pub/linux/utils/net/iproute2/
10 *
11 * Repository:
12 * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
13 *
14 * License: GPL v2
15 *
16 * Original copyright header
17 *
18 * libnetlink.c RTnetlink service routines.
19 *
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version
23 * 2 of the License, or (at your option) any later version.
24 *
25 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
26 *
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <syslog.h>
33#include <fcntl.h>
34#include <net/if_arp.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <string.h>
38#include <errno.h>
39#include <time.h>
40#include <sys/uio.h>
41
42#include "../include/libnetlink.h"
43
44int rcvbuf = 1024 * 1024;
45
46void rtnl_close(struct rtnl_handle *rth)
47{
48 if (rth->fd >= 0) {
49 close(rth->fd);
50 rth->fd = -1;
51 }
52}
53
54int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
55 int protocol)
56{
57 socklen_t addr_len;
58 int sndbuf = 32768;
59
60 memset(rth, 0, sizeof(*rth));
61
62 rth->fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol);
63 if (rth->fd < 0) {
64 perror("Cannot open netlink socket");
65 return -1;
66 }
67
68 if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) {
69 perror("SO_SNDBUF");
70 return -1;
71 }
72
73 if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) {
74 perror("SO_RCVBUF");
75 return -1;
76 }
77
78 memset(&rth->local, 0, sizeof(rth->local));
79 rth->local.nl_family = AF_NETLINK;
80 rth->local.nl_groups = subscriptions;
81
82 if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
83 perror("Cannot bind netlink socket");
84 return -1;
85 }
86 addr_len = sizeof(rth->local);
87 if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
88 perror("Cannot getsockname");
89 return -1;
90 }
91 if (addr_len != sizeof(rth->local)) {
92 fprintf(stderr, "Wrong address length %d\n", addr_len);
93 return -1;
94 }
95 if (rth->local.nl_family != AF_NETLINK) {
96 fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
97 return -1;
98 }
99 rth->seq = time(NULL);
100 return 0;
101}
102
103int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
104{
105 return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE);
106}
107
108int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
109{
110 return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF);
111}
112
113int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int family, int type,
114 __u32 filt_mask)
115{
116 struct {
117 struct nlmsghdr nlh;
118 struct ifinfomsg ifm;
119 /* attribute has to be NLMSG aligned */
120 struct rtattr ext_req __attribute__ ((aligned(NLMSG_ALIGNTO)));
121 __u32 ext_filter_mask;
122 } req;
123
124 memset(&req, 0, sizeof(req));
125 req.nlh.nlmsg_len = sizeof(req);
126 req.nlh.nlmsg_type = type;
127 req.nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST;
128 req.nlh.nlmsg_pid = 0;
129 req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
130 req.ifm.ifi_family = family;
131
132 req.ext_req.rta_type = IFLA_EXT_MASK;
133 req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32));
134 req.ext_filter_mask = filt_mask;
135
136 return send(rth->fd, (void*)&req, sizeof(req), 0);
137}
138
139int rtnl_send(struct rtnl_handle *rth, const void *buf, int len)
140{
141 return send(rth->fd, buf, len, 0);
142}
143
144int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len)
145{
146 struct nlmsghdr *h;
147 int status;
148 char resp[1024];
149
150 status = send(rth->fd, buf, len, 0);
151 if (status < 0)
152 return status;
153
154 /* Check for immediate errors */
155 status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK);
156 if (status < 0) {
157 if (errno == EAGAIN)
158 return 0;
159 return -1;
160 }
161
162 for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status);
163 h = NLMSG_NEXT(h, status)) {
164 if (h->nlmsg_type == NLMSG_ERROR) {
165 struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
166 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
167 fprintf(stderr, "ERROR truncated\n");
168 else
169 errno = -err->error;
170 return -1;
171 }
172 }
173
174 return 0;
175}
176
177int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
178{
179 struct nlmsghdr nlh;
180 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
181 struct iovec iov[2] = {
182 { .iov_base = &nlh, .iov_len = sizeof(nlh) },
183 { .iov_base = req, .iov_len = len }
184 };
185 struct msghdr msg = {
186 .msg_name = &nladdr,
187 .msg_namelen = sizeof(nladdr),
188 .msg_iov = iov,
189 .msg_iovlen = 2,
190 };
191
192 nlh.nlmsg_len = NLMSG_LENGTH(len);
193 nlh.nlmsg_type = type;
194 nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST;
195 nlh.nlmsg_pid = 0;
196 nlh.nlmsg_seq = rth->dump = ++rth->seq;
197
198 return sendmsg(rth->fd, &msg, 0);
199}
200
201int rtnl_dump_filter_l(struct rtnl_handle *rth,
202 const struct rtnl_dump_filter_arg *arg)
203{
204 struct sockaddr_nl nladdr;
205 struct iovec iov;
206 struct msghdr msg = {
207 .msg_name = &nladdr,
208 .msg_namelen = sizeof(nladdr),
209 .msg_iov = &iov,
210 .msg_iovlen = 1,
211 };
212 char buf[16384];
213 int dump_intr = 0;
214
215 iov.iov_base = buf;
216 while (1) {
217 int status;
218 const struct rtnl_dump_filter_arg *a;
219 int found_done = 0;
220 int msglen = 0;
221
222 iov.iov_len = sizeof(buf);
223 status = recvmsg(rth->fd, &msg, 0);
224
225 if (status < 0) {
226 if (errno == EINTR || errno == EAGAIN)
227 continue;
228 fprintf(stderr, "netlink receive error %s (%d)\n",
229 strerror(errno), errno);
230 return -1;
231 }
232
233 if (status == 0) {
234 fprintf(stderr, "EOF on netlink\n");
235 return -1;
236 }
237
238 for (a = arg; a->filter; a++) {
239 struct nlmsghdr *h = (struct nlmsghdr*)buf;
240 msglen = status;
241
242 while (NLMSG_OK(h, msglen)) {
243 int err;
244
245 if (nladdr.nl_pid != 0 ||
246 h->nlmsg_pid != rth->local.nl_pid ||
247 h->nlmsg_seq != rth->dump)
248 goto skip_it;
249
250 if (h->nlmsg_flags & NLM_F_DUMP_INTR)
251 dump_intr = 1;
252
253 if (h->nlmsg_type == NLMSG_DONE) {
254 found_done = 1;
255 break; /* process next filter */
256 }
257 if (h->nlmsg_type == NLMSG_ERROR) {
258 struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
259 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
260 fprintf(stderr,
261 "ERROR truncated\n");
262 } else {
263 errno = -err->error;
264 perror("RTNETLINK answers");
265 }
266 return -1;
267 }
268 err = a->filter(&nladdr, h, a->arg1);
269 if (err < 0)
270 return err;
271
272skip_it:
273 h = NLMSG_NEXT(h, msglen);
274 }
275 }
276
277 if (found_done) {
278 if (dump_intr)
279 fprintf(stderr,
280 "Dump was interrupted and may be inconsistent.\n");
281 return 0;
282 }
283
284 if (msg.msg_flags & MSG_TRUNC) {
285 fprintf(stderr, "Message truncated\n");
286 continue;
287 }
288 if (msglen) {
289 fprintf(stderr, "!!!Remnant of size %d\n", msglen);
290 exit(1);
291 }
292 }
293}
294
295int rtnl_dump_filter(struct rtnl_handle *rth,
296 rtnl_filter_t filter,
297 void *arg1)
298{
299 const struct rtnl_dump_filter_arg a[2] = {
300 { .filter = filter, .arg1 = arg1, },
301 { .filter = NULL, .arg1 = NULL, },
302 };
303
304 return rtnl_dump_filter_l(rth, a);
305}
306
307int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
308 unsigned groups, struct nlmsghdr *answer)
309{
310 int status;
311 unsigned seq;
312 struct nlmsghdr *h;
313 struct sockaddr_nl nladdr;
314 struct iovec iov = {
315 .iov_base = (void*) n,
316 .iov_len = n->nlmsg_len
317 };
318 struct msghdr msg = {
319 .msg_name = &nladdr,
320 .msg_namelen = sizeof(nladdr),
321 .msg_iov = &iov,
322 .msg_iovlen = 1,
323 };
324 char buf[16384];
325
326 memset(&nladdr, 0, sizeof(nladdr));
327 nladdr.nl_family = AF_NETLINK;
328 nladdr.nl_pid = peer;
329 nladdr.nl_groups = groups;
330
331 n->nlmsg_seq = seq = ++rtnl->seq;
332
333 if (answer == NULL)
334 n->nlmsg_flags |= NLM_F_ACK;
335
336 status = sendmsg(rtnl->fd, &msg, 0);
337
338 if (status < 0) {
339 perror("Cannot talk to rtnetlink");
340 return -1;
341 }
342
343 memset(buf,0,sizeof(buf));
344
345 iov.iov_base = buf;
346
347 while (1) {
348 iov.iov_len = sizeof(buf);
349 status = recvmsg(rtnl->fd, &msg, 0);
350
351 if (status < 0) {
352 if (errno == EINTR || errno == EAGAIN)
353 continue;
354 fprintf(stderr, "netlink receive error %s (%d)\n",
355 strerror(errno), errno);
356 return -1;
357 }
358 if (status == 0) {
359 fprintf(stderr, "EOF on netlink\n");
360 return -1;
361 }
362 if (msg.msg_namelen != sizeof(nladdr)) {
363 fprintf(stderr, "sender address length == %d\n", msg.msg_namelen);
364 exit(1);
365 }
366 for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
367 int len = h->nlmsg_len;
368 int l = len - sizeof(*h);
369
370 if (l < 0 || len>status) {
371 if (msg.msg_flags & MSG_TRUNC) {
372 fprintf(stderr, "Truncated message\n");
373 return -1;
374 }
375 fprintf(stderr, "!!!malformed message: len=%d\n", len);
376 exit(1);
377 }
378
379 if (nladdr.nl_pid != peer ||
380 h->nlmsg_pid != rtnl->local.nl_pid ||
381 h->nlmsg_seq != seq) {
382 /* Don't forget to skip that message. */
383 status -= NLMSG_ALIGN(len);
384 h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
385 continue;
386 }
387
388 if (h->nlmsg_type == NLMSG_ERROR) {
389 struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
390 if (l < sizeof(struct nlmsgerr)) {
391 fprintf(stderr, "ERROR truncated\n");
392 } else {
393 if (!err->error) {
394 if (answer)
395 memcpy(answer, h, h->nlmsg_len);
396 return 0;
397 }
398
399 fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error));
400 errno = -err->error;
401 }
402 return -1;
403 }
404 if (answer) {
405 memcpy(answer, h, h->nlmsg_len);
406 return 0;
407 }
408
409 fprintf(stderr, "Unexpected reply!!!\n");
410
411 status -= NLMSG_ALIGN(len);
412 h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
413 }
414 if (msg.msg_flags & MSG_TRUNC) {
415 fprintf(stderr, "Message truncated\n");
416 continue;
417 }
418 if (status) {
419 fprintf(stderr, "!!!Remnant of size %d\n", status);
420 exit(1);
421 }
422 }
423}
424
425int rtnl_listen(struct rtnl_handle *rtnl,
426 rtnl_filter_t handler,
427 void *jarg)
428{
429 int status;
430 struct nlmsghdr *h;
431 struct sockaddr_nl nladdr;
432 struct iovec iov;
433 struct msghdr msg = {
434 .msg_name = &nladdr,
435 .msg_namelen = sizeof(nladdr),
436 .msg_iov = &iov,
437 .msg_iovlen = 1,
438 };
439 char buf[8192];
440
441 memset(&nladdr, 0, sizeof(nladdr));
442 nladdr.nl_family = AF_NETLINK;
443 nladdr.nl_pid = 0;
444 nladdr.nl_groups = 0;
445
446 iov.iov_base = buf;
447 while (1) {
448 iov.iov_len = sizeof(buf);
449 status = recvmsg(rtnl->fd, &msg, 0);
450
451 if (status < 0) {
452 if (errno == EINTR || errno == EAGAIN)
453 continue;
454 fprintf(stderr, "netlink receive error %s (%d)\n",
455 strerror(errno), errno);
456 if (errno == ENOBUFS)
457 continue;
458 return -1;
459 }
460 if (status == 0) {
461 fprintf(stderr, "EOF on netlink\n");
462 return -1;
463 }
464 if (msg.msg_namelen != sizeof(nladdr)) {
465 fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
466 exit(1);
467 }
468 for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
469 int err;
470 int len = h->nlmsg_len;
471 int l = len - sizeof(*h);
472
473 if (l<0 || len>status) {
474 if (msg.msg_flags & MSG_TRUNC) {
475 fprintf(stderr, "Truncated message\n");
476 return -1;
477 }
478 fprintf(stderr, "!!!malformed message: len=%d\n", len);
479 exit(1);
480 }
481
482 err = handler(&nladdr, h, jarg);
483 if (err < 0)
484 return err;
485
486 status -= NLMSG_ALIGN(len);
487 h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
488 }
489 if (msg.msg_flags & MSG_TRUNC) {
490 fprintf(stderr, "Message truncated\n");
491 continue;
492 }
493 if (status) {
494 fprintf(stderr, "!!!Remnant of size %d\n", status);
495 exit(1);
496 }
497 }
498}
499
500int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler,
501 void *jarg)
502{
503 int status;
504 struct sockaddr_nl nladdr;
505 char buf[8192];
506 struct nlmsghdr *h = (void*)buf;
507
508 memset(&nladdr, 0, sizeof(nladdr));
509 nladdr.nl_family = AF_NETLINK;
510 nladdr.nl_pid = 0;
511 nladdr.nl_groups = 0;
512
513 while (1) {
514 int err, len;
515 int l;
516
517 status = fread(&buf, 1, sizeof(*h), rtnl);
518
519 if (status < 0) {
520 if (errno == EINTR)
521 continue;
522 perror("rtnl_from_file: fread");
523 return -1;
524 }
525 if (status == 0)
526 return 0;
527
528 len = h->nlmsg_len;
529 l = len - sizeof(*h);
530
531 if (l<0 || len>sizeof(buf)) {
532 fprintf(stderr, "!!!malformed message: len=%d @%lu\n",
533 len, ftell(rtnl));
534 return -1;
535 }
536
537 status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
538
539 if (status < 0) {
540 perror("rtnl_from_file: fread");
541 return -1;
542 }
543 if (status < l) {
544 fprintf(stderr, "rtnl-from_file: truncated message\n");
545 return -1;
546 }
547
548 err = handler(&nladdr, h, jarg);
549 if (err < 0)
550 return err;
551 }
552}
553
554int addattr(struct nlmsghdr *n, int maxlen, int type)
555{
556 return addattr_l(n, maxlen, type, NULL, 0);
557}
558
559int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data)
560{
561 return addattr_l(n, maxlen, type, &data, sizeof(__u8));
562}
563
564int addattr16(struct nlmsghdr *n, int maxlen, int type, __u16 data)
565{
566 return addattr_l(n, maxlen, type, &data, sizeof(__u16));
567}
568
569int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
570{
571 return addattr_l(n, maxlen, type, &data, sizeof(__u32));
572}
573
574int addattr64(struct nlmsghdr *n, int maxlen, int type, __u64 data)
575{
576 return addattr_l(n, maxlen, type, &data, sizeof(__u64));
577}
578
579int addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str)
580{
581 return addattr_l(n, maxlen, type, str, strlen(str)+1);
582}
583
584
585
586int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
587 int alen)
588{
589
590#if 0
591printf("%d: %s\n", __LINE__, __FUNCTION__);
592printf("\ttype %d - ", type);
593if (type == IFLA_LINK) {
594 printf("IFLA_LINK\n");
595 int i;
596 printf("\tdata - ");
597 for (i = 0; i < alen; i++)
598 printf("%02x, ", *((unsigned char *)data + i));
599 printf("\n");
600}
601else if (type == IFLA_IFNAME) {
602 printf("IFLA_IFNAME\n");
603 printf("\tdata - #%s#\n", data);
604}
605else if (type == IFLA_LINKINFO) printf("IFLA_LINKINFO\n");
606else if (type == IFLA_ADDRESS) {
607 printf("IFLA_ADDRESS or IFLA_INFO_KIND\n");
608 int i;
609 printf("\tdata - ");
610 for (i = 0; i < alen; i++)
611 printf("%02x, ", *((unsigned char *)data + i));
612 printf("\n");
613}
614else if (type == IFLA_BROADCAST) printf("IFLA_BROADCAST or IFLA_INFO_DATA\n");
615
616printf("\tdata length: %d\n", alen);
617#endif
618
619 int len = RTA_LENGTH(alen);
620 struct rtattr *rta;
621
622 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
623 fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
624 return -1;
625 }
626 rta = NLMSG_TAIL(n);
627 rta->rta_type = type;
628 rta->rta_len = len;
629 memcpy(RTA_DATA(rta), data, alen);
630 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
631 return 0;
632}
633
634#if 0
635int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
636 int alen)
637{
638printf("%s: adding type %d, length %d ", __FUNCTION__, type, alen);
639if (type == IFLA_INFO_KIND) {
640if (alen)
641 printf("(IFLA_INFO_KIND %s)\n", (char *)data);
642else
643printf("(VETH_INFO_PEER)\n");
644}
645else if (type == IFLA_IFNAME) {
646printf("(IFLA_IFNAME %s)\n", (char *) data);
647}
648else if (type == IFLA_NET_NS_PID) {
649printf("(IFLA_NET_NS_PID %u)\n", *((unsigned *) data));
650}
651else if (type == IFLA_LINKINFO)
652printf("(IFLA_LINKINFO)\n");
653else if (type == IFLA_INFO_DATA)
654printf("(IFLA_INFO_DATA)\n");
655else
656 printf("\n");
657
658 int len = RTA_LENGTH(alen);
659 struct rtattr *rta;
660
661 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
662 fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
663 return -1;
664 }
665 rta = NLMSG_TAIL(n);
666 rta->rta_type = type;
667 rta->rta_len = len;
668 memcpy(RTA_DATA(rta), data, alen);
669 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
670 return 0;
671}
672#endif
673
674int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len)
675{
676 if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) {
677 fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen);
678 return -1;
679 }
680
681 memcpy(NLMSG_TAIL(n), data, len);
682 memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len);
683 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len);
684 return 0;
685}
686
687struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type)
688{
689 struct rtattr *nest = NLMSG_TAIL(n);
690
691 addattr_l(n, maxlen, type, NULL, 0);
692 return nest;
693}
694
695int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
696{
697 nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest;
698 return n->nlmsg_len;
699}
700
701struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type,
702 const void *data, int len)
703{
704 struct rtattr *start = NLMSG_TAIL(n);
705
706 addattr_l(n, maxlen, type, data, len);
707 addattr_nest(n, maxlen, type);
708 return start;
709}
710
711int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *start)
712{
713 struct rtattr *nest = (void *)start + NLMSG_ALIGN(start->rta_len);
714
715 start->rta_len = (void *)NLMSG_TAIL(n) - (void *)start;
716 addattr_nest_end(n, nest);
717 return n->nlmsg_len;
718}
719
720int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
721{
722 int len = RTA_LENGTH(4);
723 struct rtattr *subrta;
724
725 if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
726 fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen);
727 return -1;
728 }
729 subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
730 subrta->rta_type = type;
731 subrta->rta_len = len;
732 memcpy(RTA_DATA(subrta), &data, 4);
733 rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
734 return 0;
735}
736
737int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
738 const void *data, int alen)
739{
740 struct rtattr *subrta;
741 int len = RTA_LENGTH(alen);
742
743 if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) {
744 fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen);
745 return -1;
746 }
747 subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
748 subrta->rta_type = type;
749 subrta->rta_len = len;
750 memcpy(RTA_DATA(subrta), data, alen);
751 rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len);
752 return 0;
753}
754
755int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
756{
757 return parse_rtattr_flags(tb, max, rta, len, 0);
758}
759
760int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
761 int len, unsigned short flags)
762{
763 unsigned short type;
764
765 memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
766 while (RTA_OK(rta, len)) {
767 type = rta->rta_type & ~flags;
768 if ((type <= max) && (!tb[type]))
769 tb[type] = rta;
770 rta = RTA_NEXT(rta,len);
771 }
772 if (len)
773 fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
774 return 0;
775}
776
777int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len)
778{
779 int i = 0;
780
781 memset(tb, 0, sizeof(struct rtattr *) * max);
782 while (RTA_OK(rta, len)) {
783 if (rta->rta_type <= max && i < max)
784 tb[i++] = rta;
785 rta = RTA_NEXT(rta,len);
786 }
787 if (len)
788 fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
789 return i;
790}
791
792int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta,
793 int len)
794{
795 if (RTA_PAYLOAD(rta) < len)
796 return -1;
797 if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
798 rta = RTA_DATA(rta) + RTA_ALIGN(len);
799 return parse_rtattr_nested(tb, max, rta);
800 }
801 memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
802 return 0;
803}
diff --git a/src/lib/pid.c b/src/lib/pid.c
new file mode 100644
index 000000000..a0261ead2
--- /dev/null
+++ b/src/lib/pid.c
@@ -0,0 +1,392 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "../include/common.h"
21#include "../include/pid.h"
22#include <string.h>
23#include <sys/types.h>
24#include <pwd.h>
25#include <sys/ioctl.h>
26#include <dirent.h>
27
28#define PIDS_BUFLEN 4096
29//Process pids[max_pids];
30Process *pids = NULL;
31int max_pids=32769;
32#define PIDS_BUFLEN 4096
33
34// get the memory associated with this pid
35void pid_getmem(unsigned pid, unsigned *rss, unsigned *shared) {
36 // open stat file
37 char *file;
38 if (asprintf(&file, "/proc/%u/statm", pid) == -1) {
39 perror("asprintf");
40 exit(1);
41 }
42 FILE *fp = fopen(file, "r");
43 if (!fp) {
44 free(file);
45 return;
46 }
47 free(file);
48
49 unsigned a, b, c;
50 if (3 != fscanf(fp, "%u %u %u", &a, &b, &c)) {
51 fclose(fp);
52 return;
53 }
54 *rss += b;
55 *shared += c;
56 fclose(fp);
57}
58
59
60void pid_get_cpu_time(unsigned pid, unsigned *utime, unsigned *stime) {
61 // open stat file
62 char *file;
63 if (asprintf(&file, "/proc/%u/stat", pid) == -1) {
64 perror("asprintf");
65 exit(1);
66 }
67 FILE *fp = fopen(file, "r");
68 if (!fp) {
69 free(file);
70 return;
71 }
72 free(file);
73
74 char line[PIDS_BUFLEN];
75 if (fgets(line, PIDS_BUFLEN - 1, fp)) {
76 char *ptr = line;
77 // jump 13 fields
78 int i;
79 for (i = 0; i < 13; i++) {
80 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
81 ptr++;
82 if (*ptr == '\0')
83 goto myexit;
84 ptr++;
85 }
86 if (2 != sscanf(ptr, "%u %u", utime, stime))
87 goto myexit;
88 }
89
90myexit:
91 fclose(fp);
92}
93
94unsigned long long pid_get_start_time(unsigned pid) {
95 // open stat file
96 char *file;
97 if (asprintf(&file, "/proc/%u/stat", pid) == -1) {
98 perror("asprintf");
99 exit(1);
100 }
101 FILE *fp = fopen(file, "r");
102 if (!fp) {
103 free(file);
104 return 0;
105 }
106 free(file);
107
108 char line[PIDS_BUFLEN];
109 unsigned long long retval = 0;
110 if (fgets(line, PIDS_BUFLEN - 1, fp)) {
111 char *ptr = line;
112 // jump 21 fields
113 int i;
114 for (i = 0; i < 21; i++) {
115 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
116 ptr++;
117 if (*ptr == '\0')
118 goto myexit;
119 ptr++;
120 }
121 if (1 != sscanf(ptr, "%llu", &retval))
122 goto myexit;
123 }
124
125myexit:
126 fclose(fp);
127 return retval;
128}
129
130char *pid_get_user_name(uid_t uid) {
131 struct passwd *pw = getpwuid(uid);
132 if (pw)
133 return strdup(pw->pw_name);
134 return NULL;
135}
136
137uid_t pid_get_uid(pid_t pid) {
138 uid_t rv = 0;
139
140 // open stat file
141 char *file;
142 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
143 perror("asprintf");
144 exit(1);
145 }
146 FILE *fp = fopen(file, "r");
147 if (!fp) {
148 free(file);
149 return 0;
150 }
151
152 // look for firejail executable name
153 char buf[PIDS_BUFLEN];
154 while (fgets(buf, PIDS_BUFLEN - 1, fp)) {
155 if (strncmp(buf, "Uid:", 4) == 0) {
156 char *ptr = buf + 5;
157 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
158 ptr++;
159 }
160 if (*ptr == '\0')
161 goto doexit;
162
163 rv = atoi(ptr);
164 break; // break regardless!
165 }
166 }
167doexit:
168 fclose(fp);
169 free(file);
170 return rv;
171}
172
173static void print_elem(unsigned index, int nowrap) {
174 // get terminal size
175 struct winsize sz;
176 int col = 0;
177 if (isatty(STDIN_FILENO)) {
178 if (!ioctl(0, TIOCGWINSZ, &sz))
179 col = sz.ws_col;
180 }
181
182 // indent
183 char indent[(pids[index].level - 1) * 2 + 1];
184 memset(indent, ' ', sizeof(indent));
185 indent[(pids[index].level - 1) * 2] = '\0';
186
187 // get data
188 uid_t uid = pids[index].uid;
189 char *cmd = pid_proc_cmdline(index);
190 char *user = pid_get_user_name(uid);
191 char *allocated = user;
192 if (user ==NULL)
193 user = "";
194 if (cmd) {
195 if (col < 4 || nowrap)
196 printf("%s%u:%s:%s\n", indent, index, user, cmd);
197 else {
198 char *out;
199 if (asprintf(&out, "%s%u:%s:%s\n", indent, index, user, cmd) == -1)
200 errExit("asprintf");
201 int len = strlen(out);
202 if (len > col) {
203 out[col] = '\0';
204 out[col - 1] = '\n';
205 }
206 printf("%s", out);
207 free(out);
208 }
209
210 free(cmd);
211 }
212 else {
213 if (pids[index].zombie)
214 printf("%s%u: (zombie)\n", indent, index);
215 else
216 printf("%s%u:\n", indent, index);
217 }
218 if (allocated)
219 free(allocated);
220}
221
222// recursivity!!!
223void pid_print_tree(unsigned index, unsigned parent, int nowrap) {
224 print_elem(index, nowrap);
225
226 int i;
227 for (i = index + 1; i < max_pids; i++) {
228 if (pids[i].parent == index)
229 pid_print_tree(i, index, nowrap);
230 }
231
232 for (i = 0; i < index; i++) {
233 if (pids[i].parent == index)
234 pid_print_tree(i, index, nowrap);
235 }
236}
237
238void pid_print_list(unsigned index, int nowrap) {
239 print_elem(index, nowrap);
240}
241
242// recursivity!!!
243void pid_store_cpu(unsigned index, unsigned parent, unsigned *utime, unsigned *stime) {
244 if (pids[index].level == 1) {
245 *utime = 0;
246 *stime = 0;
247 }
248
249 unsigned utmp = 0;
250 unsigned stmp = 0;
251 pid_get_cpu_time(index, &utmp, &stmp);
252 *utime += utmp;
253 *stime += stmp;
254
255 int i;
256 for (i = index + 1; i < max_pids; i++) {
257 if (pids[i].parent == index)
258 pid_store_cpu(i, index, utime, stime);
259 }
260
261 if (pids[index].level == 1) {
262 pids[index].utime = *utime;
263 pids[index].stime = *stime;
264 }
265}
266
267// mon_pid: pid of sandbox to be monitored, 0 if all sandboxes are included
268void pid_read(pid_t mon_pid) {
269 if (pids == NULL) {
270 FILE *fp = fopen("/proc/sys/kernel/pid_max", "r");
271 if (fp) {
272 int val;
273 if (fscanf(fp, "%d", &val) == 1) {
274 if (val >= max_pids)
275 max_pids = val + 1;
276 }
277 fclose(fp);
278 }
279 pids = malloc(sizeof(Process) * max_pids);
280 if (pids == NULL)
281 errExit("malloc");
282 }
283 memset(pids, 0, sizeof(Process) * max_pids);
284 pid_t mypid = getpid();
285
286 DIR *dir;
287 if (!(dir = opendir("/proc"))) {
288 // sleep 2 seconds and try again
289 sleep(2);
290 if (!(dir = opendir("/proc"))) {
291 fprintf(stderr, "Error: cannot open /proc directory\n");
292 exit(1);
293 }
294 }
295
296 pid_t child = -1;
297 struct dirent *entry;
298 char *end;
299 while (child < 0 && (entry = readdir(dir))) {
300 pid_t pid = strtol(entry->d_name, &end, 10);
301 pid %= max_pids;
302 if (end == entry->d_name || *end)
303 continue;
304 if (pid == mypid)
305 continue;
306
307 // open stat file
308 char *file;
309 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
310 perror("asprintf");
311 exit(1);
312 }
313 FILE *fp = fopen(file, "r");
314 if (!fp) {
315 free(file);
316 continue;
317 }
318
319 // look for firejail executable name
320 char buf[PIDS_BUFLEN];
321 while (fgets(buf, PIDS_BUFLEN - 1, fp)) {
322 if (strncmp(buf, "Name:", 5) == 0) {
323 char *ptr = buf + 5;
324 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
325 ptr++;
326 }
327 if (*ptr == '\0') {
328 fprintf(stderr, "Error: cannot read /proc file\n");
329 exit(1);
330 }
331
332 if (mon_pid == 0 && strncmp(ptr, "firejail", 8) == 0) {
333 pids[pid].level = 1;
334 }
335 else if (mon_pid == pid && strncmp(ptr, "firejail", 8) == 0) {
336 pids[pid].level = 1;
337 }
338// else if (mon_pid == 0 && strncmp(ptr, "lxc-execute", 11) == 0) {
339// pids[pid].level = 1;
340// }
341// else if (mon_pid == pid && strncmp(ptr, "lxc-execute", 11) == 0) {
342// pids[pid].level = 1;
343// }
344 else
345 pids[pid].level = -1;
346 }
347 if (strncmp(buf, "State:", 6) == 0) {
348 if (strstr(buf, "(zombie)"))
349 pids[pid].zombie = 1;
350 }
351 else if (strncmp(buf, "PPid:", 5) == 0) {
352 char *ptr = buf + 5;
353 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
354 ptr++;
355 }
356 if (*ptr == '\0') {
357 fprintf(stderr, "Error: cannot read /proc file\n");
358 exit(1);
359 }
360 unsigned parent = atoi(ptr);
361 parent %= max_pids;
362 if (pids[parent].level > 0) {
363 pids[pid].level = pids[parent].level + 1;
364 }
365 pids[pid].parent = parent;
366 }
367 else if (strncmp(buf, "Uid:", 4) == 0) {
368 char *ptr = buf + 5;
369 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
370 ptr++;
371 }
372 if (*ptr == '\0') {
373 fprintf(stderr, "Error: cannot read /proc file\n");
374 exit(1);
375 }
376 pids[pid].uid = atoi(ptr);
377 break;
378 }
379 }
380 fclose(fp);
381 free(file);
382 }
383 closedir(dir);
384
385 pid_t pid;
386 for (pid = 0; pid < max_pids; pid++) {
387 int parent = pids[pid].parent;
388 if (pids[parent].level > 0) {
389 pids[pid].level = pids[parent].level + 1;
390 }
391 }
392}
diff --git a/src/libtrace/Makefile.in b/src/libtrace/Makefile.in
new file mode 100644
index 000000000..8848fc08c
--- /dev/null
+++ b/src/libtrace/Makefile.in
@@ -0,0 +1,25 @@
1PREFIX=@prefix@
2VERSION=@PACKAGE_VERSION@
3NAME=@PACKAGE_NAME@
4
5H_FILE_LIST = $(wildcard *.[h])
6C_FILE_LIST = $(wildcard *.c)
7OBJS = $(C_FILE_LIST:.c=.o)
8BINOBJS = $(foreach file, $(OBJS), $file)
9CFLAGS += -ggdb -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security
10LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now
11
12all: libtrace.so
13
14%.o : %.c $(H_FILE_LIST)
15 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
16
17# gcc -shared -fPIC -ldl traceopen.c -o traceopen.so
18libtrace.so: $(OBJS)
19 $(CC) $(LDFLAGS) -shared -fPIC -z relro -o $@ $(OBJS) -ldl
20
21
22clean:; rm -f $(OBJS) libtrace.so
23
24distclean: clean
25 rm -fr Makefile
diff --git a/src/libtrace/libtrace.c b/src/libtrace/libtrace.c
new file mode 100644
index 000000000..a785ec698
--- /dev/null
+++ b/src/libtrace/libtrace.c
@@ -0,0 +1,609 @@
1#define _GNU_SOURCE
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <dlfcn.h>
6#include <sys/types.h>
7#include <unistd.h>
8#include <sys/socket.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11#include <sys/un.h>
12#include <sys/stat.h>
13
14// break recursivity on fopen call
15typedef FILE *(*orig_fopen_t)(const char *pathname, const char *mode);
16static orig_fopen_t orig_fopen = NULL;
17typedef FILE *(*orig_fopen64_t)(const char *pathname, const char *mode);
18static orig_fopen64_t orig_fopen64 = NULL;
19
20//
21// pid
22//
23static pid_t mypid = 0;
24static inline pid_t pid(void) {
25 if (!mypid)
26 mypid = getpid();
27 return mypid;
28}
29
30//
31// process name
32//
33#define MAXNAME 16
34static char myname[MAXNAME];
35static int nameinit = 0;
36static char *name(void) {
37 if (!nameinit) {
38 // initialize the name of the process based on /proc/PID/comm
39 memset(myname, 0, MAXNAME);
40
41 pid_t p = pid();
42 char *fname;
43 if (asprintf(&fname, "/proc/%u/comm", p) == -1)
44 return "unknown";
45
46 // read file
47 if (!orig_fopen)
48 orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen");
49 FILE *fp = orig_fopen(fname, "r");
50 if (!fp)
51 return "unknown";
52 if (fgets(myname, MAXNAME, fp) == NULL) {
53 fclose(fp);
54 free(fname);
55 return "unknown";
56 }
57
58 // clean '\n'
59 char *ptr = strchr(myname, '\n');
60 if (ptr)
61 *ptr = '\0';
62
63 fclose(fp);
64 free(fname);
65 nameinit = 1;
66 }
67
68 return myname;
69}
70
71//
72// network
73//
74typedef struct {
75 int val;
76 char *name;
77} XTable;
78
79static XTable socket_type[] = {
80#ifdef SOCK_STREAM
81 { SOCK_STREAM, "SOCK_STREAM" },
82#endif
83#ifdef SOCK_DGRAM
84 { SOCK_DGRAM, "SOCK_DGRAM" },
85#endif
86#ifdef SOCK_RAW
87 { SOCK_RAW, "SOCK_RAW" },
88#endif
89#ifdef SOCK_RDM
90 { SOCK_RDM, "SOCK_RDM" },
91#endif
92#ifdef SOCK_SEQPACKET
93 { SOCK_SEQPACKET, "SOCK_SEQPACKET" },
94#endif
95#ifdef SOCK_DCCP
96 { SOCK_DCCP, "SOCK_DCCP" },
97#endif
98 { 0, NULL} // NULL terminated
99};
100
101static XTable socket_domain[] = {
102#ifdef AF_INET
103 { AF_INET, "AF_INET" },
104#endif
105#ifdef AF_INET6
106 { AF_INET6, "AF_INET6" },
107#endif
108#ifdef AF_LOCAL
109 { AF_LOCAL, "AF_LOCAL" },
110#endif
111#ifdef AF_PACKET
112 { AF_PACKET, "AF_PACKET" },
113#endif
114#ifdef AF_IPX
115 { AF_IPX, "AF_IPX" },
116#endif
117#ifdef AF_NETLINK
118 { AF_NETLINK, "AF_NETLINK" },
119#endif
120#ifdef AF_X25
121 { AF_X25, "AF_X25" },
122#endif
123#ifdef AF_AX25
124 { AF_AX25, "AF_AX25" },
125#endif
126#ifdef AF_ATMPVC
127 { AF_ATMPVC, "AF_ATMPVC" },
128#endif
129#ifdef AF_APPLETALK
130 { AF_APPLETALK, "AF_APPLETALK" },
131#endif
132 { 0, NULL} // NULL terminated
133};
134
135static XTable socket_protocol[] = {
136#ifdef IPPROTO_IP
137 { IPPROTO_IP, "IPPROTO_IP" },
138#endif
139#ifdef IPPROTO_ICMP
140 { IPPROTO_ICMP, "IPPROTO_ICMP" },
141#endif
142#ifdef IPPROTO_IGMP
143 { IPPROTO_IGMP, "IPPROTO_IGMP" },
144#endif
145#ifdef IPPROTO_IPIP
146 { IPPROTO_IPIP, "IPPROTO_IPIP" },
147#endif
148#ifdef IPPROTO_TCP
149 { IPPROTO_TCP, "IPPROTO_TCP" },
150#endif
151#ifdef IPPROTO_EGP
152 { IPPROTO_EGP, "IPPROTO_EGP" },
153#endif
154#ifdef IPPROTO_PUP
155 { IPPROTO_PUP, "IPPROTO_PUP" },
156#endif
157#ifdef IPPROTO_UDP
158 { IPPROTO_UDP, "IPPROTO_UDP" },
159#endif
160#ifdef IPPROTO_IDP
161 { IPPROTO_IDP, "IPPROTO_IDP" },
162#endif
163#ifdef IPPROTO_DCCP
164 { IPPROTO_DCCP, "IPPROTO_DCCP" },
165#endif
166#ifdef IPPROTO_RSVP
167 { IPPROTO_RSVP, "IPPROTO_RSVP" },
168#endif
169#ifdef IPPROTO_GRE
170 { IPPROTO_GRE, "IPPROTO_GRE" },
171#endif
172#ifdef IPPROTO_IPV6
173 { IPPROTO_IPV6, "IPPROTO_IPV6" },
174#endif
175#ifdef IPPROTO_ESP
176 { IPPROTO_ESP, "IPPROTO_ESP" },
177#endif
178#ifdef IPPROTO_AH
179 { IPPROTO_AH, "IPPROTO_AH" },
180#endif
181#ifdef IPPROTO_BEETPH
182 { IPPROTO_BEETPH, "IPPROTO_BEETPH" },
183#endif
184#ifdef IPPROTO_PIM
185 { IPPROTO_PIM, "IPPROTO_PIM" },
186#endif
187#ifdef IPPROTO_COMP
188 { IPPROTO_COMP, "IPPROTO_COMP" },
189#endif
190#ifdef IPPROTO_SCTP
191 { IPPROTO_SCTP, "IPPROTO_SCTP" },
192#endif
193#ifdef IPPROTO_UDPLITE
194 { IPPROTO_UDPLITE, "IPPROTO_UDPLITE" },
195#endif
196#ifdef IPPROTO_RAW
197 { IPPROTO_RAW, "IPPROTO_RAW" },
198#endif
199 { 0, NULL} // NULL terminated
200};
201
202static char *translate(XTable *table, int val) {
203 while (table->name != NULL) {
204 if (val == table->val)
205 return table->name;
206 table++;
207 }
208
209 return NULL;
210}
211
212static void print_sockaddr(const char *call, const struct sockaddr *addr) {
213 if (addr->sa_family == AF_INET) {
214 struct sockaddr_in *a = (struct sockaddr_in *) addr;
215 printf("%u:%s:%s %s:%u\n", pid(), name(), call, inet_ntoa(a->sin_addr), ntohs(a->sin_port));
216 }
217 else if (addr->sa_family == AF_INET6) {
218 struct sockaddr_in6 *a = (struct sockaddr_in6 *) addr;
219 char str[INET6_ADDRSTRLEN];
220 inet_ntop(AF_INET6, &(a->sin6_addr), str, INET6_ADDRSTRLEN);
221 printf("%u:%s:%s %s\n", pid(), name(), call, str);
222 }
223 else if (addr->sa_family == AF_UNIX) {
224 struct sockaddr_un *a = (struct sockaddr_un *) addr;
225 if (a->sun_path[0])
226 printf("%u:%s:%s %s\n", pid(), name(), call, a->sun_path);
227 else
228 printf("%u:%s:%s @%s\n", pid(), name(), call, a->sun_path + 1);
229 }
230 else {
231 printf("%u:%s:%s family %d\n", pid(), name(), call, addr->sa_family);
232 }
233}
234
235//
236// syscalls
237//
238
239// open
240typedef int (*orig_open_t)(const char *pathname, int flags, mode_t mode);
241static orig_open_t orig_open = NULL;
242int open(const char *pathname, int flags, mode_t mode) {
243 if (!orig_open)
244 orig_open = (orig_open_t)dlsym(RTLD_NEXT, "open");
245
246 int rv = orig_open(pathname, flags, mode);
247 printf("%u:%s:open %s\n", pid(), name(), pathname);
248 return rv;
249}
250
251typedef int (*orig_open64_t)(const char *pathname, int flags, mode_t mode);
252static orig_open64_t orig_open64 = NULL;
253int open64(const char *pathname, int flags, mode_t mode) {
254 if (!orig_open64)
255 orig_open64 = (orig_open64_t)dlsym(RTLD_NEXT, "open64");
256
257 int rv = orig_open64(pathname, flags, mode);
258 printf("%u:%s:open64 %s\n", pid(), name(), pathname);
259 return rv;
260}
261
262// openat
263typedef int (*orig_openat_t)(int dirfd, const char *pathname, int flags, mode_t mode);
264static orig_openat_t orig_openat = NULL;
265int openat(int dirfd, const char *pathname, int flags, mode_t mode) {
266 if (!orig_openat)
267 orig_openat = (orig_openat_t)dlsym(RTLD_NEXT, "openat");
268
269 int rv = orig_openat(dirfd, pathname, flags, mode);
270 printf("%u:%s:openat %s\n", pid(), name(), pathname);
271 return rv;
272}
273
274typedef int (*orig_openat64_t)(int dirfd, const char *pathname, int flags, mode_t mode);
275static orig_openat64_t orig_openat64 = NULL;
276int openat64(int dirfd, const char *pathname, int flags, mode_t mode) {
277 if (!orig_openat64)
278 orig_openat64 = (orig_openat64_t)dlsym(RTLD_NEXT, "openat64");
279
280 int rv = orig_openat64(dirfd, pathname, flags, mode);
281 printf("%u:%s:openat64 %s\n", pid(), name(), pathname);
282 return rv;
283}
284
285
286// fopen
287FILE *fopen(const char *pathname, const char *mode) {
288 if (!orig_fopen)
289 orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen");
290
291 FILE *rv = orig_fopen(pathname, mode);
292 printf("%u:%s:fopen %s\n", pid(), name(), pathname);
293 return rv;
294}
295
296FILE *fopen64(const char *pathname, const char *mode) {
297 if (!orig_fopen64)
298 orig_fopen64 = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen64");
299
300 FILE *rv = orig_fopen64(pathname, mode);
301 printf("%u:%s:fopen64 %s\n", pid(), name(), pathname);
302 return rv;
303}
304
305
306// freopen
307typedef FILE *(*orig_freopen_t)(const char *pathname, const char *mode, FILE *stream);
308static orig_freopen_t orig_freopen = NULL;
309FILE *freopen(const char *pathname, const char *mode, FILE *stream) {
310 if (!orig_freopen)
311 orig_freopen = (orig_freopen_t)dlsym(RTLD_NEXT, "freopen");
312
313 FILE *rv = orig_freopen(pathname, mode, stream);
314 printf("%u:%s:freopen %s\n", pid(), name(), pathname);
315 return rv;
316}
317
318typedef FILE *(*orig_freopen64_t)(const char *pathname, const char *mode, FILE *stream);
319static orig_freopen64_t orig_freopen64 = NULL;
320FILE *freopen64(const char *pathname, const char *mode, FILE *stream) {
321 if (!orig_freopen64)
322 orig_freopen64 = (orig_freopen64_t)dlsym(RTLD_NEXT, "freopen64");
323
324 FILE *rv = orig_freopen64(pathname, mode, stream);
325 printf("%u:%s:freopen64 %s\n", pid(), name(), pathname);
326 return rv;
327}
328
329// unlink
330typedef int (*orig_unlink_t)(const char *pathname);
331static orig_unlink_t orig_unlink = NULL;
332int unlink(const char *pathname) {
333 if (!orig_unlink)
334 orig_unlink = (orig_unlink_t)dlsym(RTLD_NEXT, "unlink");
335
336 int rv = orig_unlink(pathname);
337 printf("%u:%s:unlink %s\n", pid(), name(), pathname);
338 return rv;
339}
340
341typedef int (*orig_unlinkat_t)(int dirfd, const char *pathname, int flags);
342static orig_unlinkat_t orig_unlinkat = NULL;
343int unlinkat(int dirfd, const char *pathname, int flags) {
344 if (!orig_unlinkat)
345 orig_unlinkat = (orig_unlinkat_t)dlsym(RTLD_NEXT, "unlinkat");
346
347 int rv = orig_unlinkat(dirfd, pathname, flags);
348 printf("%u:%s:unlinkat %s\n", pid(), name(), pathname);
349 return rv;
350}
351
352// mkdir/mkdirat/rmdir
353typedef int (*orig_mkdir_t)(const char *pathname, mode_t mode);
354static orig_mkdir_t orig_mkdir = NULL;
355int mkdir(const char *pathname, mode_t mode) {
356 if (!orig_mkdir)
357 orig_mkdir = (orig_mkdir_t)dlsym(RTLD_NEXT, "mkdir");
358
359 int rv = orig_mkdir(pathname, mode);
360 printf("%u:%s:mkdir %s\n", pid(), name(), pathname);
361 return rv;
362}
363
364typedef int (*orig_mkdirat_t)(int dirfd, const char *pathname, mode_t mode);
365static orig_mkdirat_t orig_mkdirat = NULL;
366int mkdirat(int dirfd, const char *pathname, mode_t mode) {
367 if (!orig_mkdirat)
368 orig_mkdirat = (orig_mkdirat_t)dlsym(RTLD_NEXT, "mkdirat");
369
370 int rv = orig_mkdirat(dirfd, pathname, mode);
371 printf("%u:%s:mkdirat %s\n", pid(), name(), pathname);
372 return rv;
373}
374
375typedef int (*orig_rmdir_t)(const char *pathname);
376static orig_rmdir_t orig_rmdir = NULL;
377int rmdir(const char *pathname) {
378 if (!orig_rmdir)
379 orig_rmdir = (orig_rmdir_t)dlsym(RTLD_NEXT, "rmdir");
380
381 int rv = orig_rmdir(pathname);
382 printf("%u:%s:rmdir %s\n", pid(), name(), pathname);
383 return rv;
384}
385
386// stat
387typedef int (*orig_stat_t)(const char *pathname, struct stat *buf);
388static orig_stat_t orig_stat = NULL;
389int stat(const char *pathname, struct stat *buf) {
390 if (!orig_stat)
391 orig_stat = (orig_stat_t)dlsym(RTLD_NEXT, "stat");
392
393 int rv = orig_stat(pathname, buf);
394 printf("%u:%s:stat %s\n", pid(), name(), pathname);
395 return rv;
396}
397
398typedef int (*orig_stat64_t)(const char *pathname, struct stat64 *buf);
399static orig_stat64_t orig_stat64 = NULL;
400int stat64(const char *pathname, struct stat64 *buf) {
401 if (!orig_stat)
402 orig_stat64 = (orig_stat64_t)dlsym(RTLD_NEXT, "stat");
403
404 int rv = orig_stat64(pathname, buf);
405 printf("%u:%s:stat %s\n", pid(), name(), pathname);
406 return rv;
407}
408
409
410// access
411typedef int (*orig_access_t)(const char *pathname, int mode);
412static orig_access_t orig_access = NULL;
413int access(const char *pathname, int mode) {
414 if (!orig_access)
415 orig_access = (orig_access_t)dlsym(RTLD_NEXT, "access");
416
417 int rv = orig_access(pathname, mode);
418 printf("%u:%s:access %s\n", pid(), name(), pathname);
419 return rv;
420}
421
422
423// connect
424typedef int (*orig_connect_t)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
425static orig_connect_t orig_connect = NULL;
426int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
427 if (!orig_connect)
428 orig_connect = (orig_connect_t)dlsym(RTLD_NEXT, "connect");
429
430 int rv = orig_connect(sockfd, addr, addrlen);
431 print_sockaddr("connect", addr);
432
433 return rv;
434}
435
436// socket
437typedef int (*orig_socket_t)(int domain, int type, int protocol);
438static orig_socket_t orig_socket = NULL;
439static char buf[1024];
440int socket(int domain, int type, int protocol) {
441 if (!orig_socket)
442 orig_socket = (orig_socket_t)dlsym(RTLD_NEXT, "socket");
443
444 int rv = orig_socket(domain, type, protocol);
445 char *ptr = buf;
446 ptr += sprintf(ptr, "%u:%s:socket ", pid(), name());
447 char *str = translate(socket_domain, domain);
448 if (str == NULL)
449 ptr += sprintf(ptr, "%d ", domain);
450 else
451 ptr += sprintf(ptr, "%s ", str);
452
453 int t = type; // glibc uses higher bits for various other purposes
454#ifdef SOCK_CLOEXEC
455 t &= ~SOCK_CLOEXEC;
456#endif
457#ifdef SOCK_NONBLOCK
458 t &= ~SOCK_NONBLOCK;
459#endif
460 str = translate(socket_type, t);
461 if (str == NULL)
462 ptr += sprintf(ptr, "%d ", type);
463 else
464 ptr += sprintf(ptr, "%s ", str);
465
466 str = translate(socket_protocol, protocol);
467 if (str == NULL)
468 ptr += sprintf(ptr, "%d", protocol);
469 else
470 ptr += sprintf(ptr, "%s", str);
471
472 printf("%s\n", buf);
473 return rv;
474}
475
476// bind
477typedef int (*orig_bind_t)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
478static orig_bind_t orig_bind = NULL;
479int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
480 if (!orig_bind)
481 orig_bind = (orig_bind_t)dlsym(RTLD_NEXT, "bind");
482
483 int rv = orig_bind(sockfd, addr, addrlen);
484 print_sockaddr("bind", addr);
485
486 return rv;
487}
488
489#if 0 //todo: fix compilation problems
490typedef int (*orig_accept_t)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
491static orig_accept_t orig_accept = NULL;
492int accept(int sockfd, struct sockaddr *addr, socklen_t addrlen) {
493 if (!orig_accept)
494 orig_accept = (orig_accept_t)dlsym(RTLD_NEXT, "accept");
495
496 int rv = orig_accept(sockfd, addr, addrlen);
497 print_sockaddr("accept", addr);
498
499 return rv;
500}
501#endif
502
503typedef int (*orig_system_t)(const char *command);
504static orig_system_t orig_system = NULL;
505int system(const char *command) {
506 if (!orig_system)
507 orig_system = (orig_system_t)dlsym(RTLD_NEXT, "system");
508
509 int rv = orig_system(command);
510 printf("%u:%s:system %s\n", pid(), name(), command);
511
512 return rv;
513}
514
515typedef int (*orig_setuid_t)(uid_t uid);
516static orig_setuid_t orig_setuid = NULL;
517int setuid(uid_t uid) {
518 if (!orig_setuid)
519 orig_setuid = (orig_setuid_t)dlsym(RTLD_NEXT, "setuid");
520
521 int rv = orig_setuid(uid);
522 printf("%u:%s:setuid %d\n", pid(), name(), uid);
523
524 return rv;
525}
526
527typedef int (*orig_setgid_t)(gid_t gid);
528static orig_setgid_t orig_setgid = NULL;
529int setgid(gid_t gid) {
530 if (!orig_setgid)
531 orig_setgid = (orig_setgid_t)dlsym(RTLD_NEXT, "setgid");
532
533 int rv = orig_setgid(gid);
534 printf("%u:%s:setgid %d\n", pid(), name(), gid);
535
536 return rv;
537}
538
539typedef int (*orig_setfsuid_t)(uid_t uid);
540static orig_setfsuid_t orig_setfsuid = NULL;
541int setfsuid(uid_t uid) {
542 if (!orig_setfsuid)
543 orig_setfsuid = (orig_setfsuid_t)dlsym(RTLD_NEXT, "setfsuid");
544
545 int rv = orig_setfsuid(uid);
546 printf("%u:%s:setfsuid %d\n", pid(), name(), uid);
547
548 return rv;
549}
550
551typedef int (*orig_setfsgid_t)(gid_t gid);
552static orig_setfsgid_t orig_setfsgid = NULL;
553int setfsgid(gid_t gid) {
554 if (!orig_setfsgid)
555 orig_setfsgid = (orig_setfsgid_t)dlsym(RTLD_NEXT, "setfsgid");
556
557 int rv = orig_setfsgid(gid);
558 printf("%u:%s:setfsgid %d\n", pid(), name(), gid);
559
560 return rv;
561}
562
563typedef int (*orig_setreuid_t)(uid_t ruid, uid_t euid);
564static orig_setreuid_t orig_setreuid = NULL;
565int setreuid(uid_t ruid, uid_t euid) {
566 if (!orig_setreuid)
567 orig_setreuid = (orig_setreuid_t)dlsym(RTLD_NEXT, "setreuid");
568
569 int rv = orig_setreuid(ruid, euid);
570 printf("%u:%s:setreuid %d %d\n", pid(), name(), ruid, euid);
571
572 return rv;
573}
574
575typedef int (*orig_setregid_t)(gid_t rgid, gid_t egid);
576static orig_setregid_t orig_setregid = NULL;
577int setregid(gid_t rgid, gid_t egid) {
578 if (!orig_setregid)
579 orig_setregid = (orig_setregid_t)dlsym(RTLD_NEXT, "setregid");
580
581 int rv = orig_setregid(rgid, egid);
582 printf("%u:%s:setregid %d %d\n", pid(), name(), rgid, egid);
583
584 return rv;
585}
586
587typedef int (*orig_setresuid_t)(uid_t ruid, uid_t euid, uid_t suid);
588static orig_setresuid_t orig_setresuid = NULL;
589int setresuid(uid_t ruid, uid_t euid, uid_t suid) {
590 if (!orig_setresuid)
591 orig_setresuid = (orig_setresuid_t)dlsym(RTLD_NEXT, "setresuid");
592
593 int rv = orig_setresuid(ruid, euid, suid);
594 printf("%u:%s:setresuid %d %d %d\n", pid(), name(), ruid, euid, suid);
595
596 return rv;
597}
598
599typedef int (*orig_setresgid_t)(gid_t rgid, gid_t egid, gid_t sgid);
600static orig_setresgid_t orig_setresgid = NULL;
601int setresgid(gid_t rgid, gid_t egid, gid_t sgid) {
602 if (!orig_setresgid)
603 orig_setresgid = (orig_setresgid_t)dlsym(RTLD_NEXT, "setresgid");
604
605 int rv = orig_setresgid(rgid, egid, sgid);
606 printf("%u:%s:setresgid %d %d %d\n", pid(), name(), rgid, egid, sgid);
607
608 return rv;
609} \ No newline at end of file
diff --git a/src/man/firejail-login.txt b/src/man/firejail-login.txt
new file mode 100644
index 000000000..6613dc044
--- /dev/null
+++ b/src/man/firejail-login.txt
@@ -0,0 +1,36 @@
1.TH man 5 "MONTH YEAR" "VERSION" "firejail login.users man page"
2.SH NAME
3login.users \- Login file syntax for Firejail
4
5.SH DESCRIPTION
6/etc/firejail/login.users file describes additional arguments passed to firejail executable
7upon user logging into a Firejail restircted shell. Each user entry in the file consists of
8a user name followed by the arguments passed to firejail. The format is as follows:
9
10 user_name: arguments
11
12Example:
13
14 netblue:--debug --net=none
15
16.SH RESTRICTED SHELL
17To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in
18/etc/password file for each user that needs to be restricted. Alternatively,
19you can specify /usr/bin/firejail in adduser command:
20
21adduser \-\-shell /usr/bin/firejail username
22
23.SH FILES
24/etc/firejail/login.users
25
26.SH LICENSE
27Firejail is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
28.PP
29Homepage: http://firejail.sourceforge.net
30.SH SEE ALSO
31\&\flfirejail\fR\|(1),
32\&\flfiremon\fR\|(1),
33\&\flfirejail-profile\fR\|(5)
34
35
36
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
new file mode 100644
index 000000000..46da19ecd
--- /dev/null
+++ b/src/man/firejail-profile.txt
@@ -0,0 +1,181 @@
1.TH man 5 "MONTH YEAR" "VERSION" "firejail profiles man page"
2.SH NAME
3profile \- Profile file syntax for Firejail
4
5.SH USAGE
6.TP
7firejail \-\-profile=filename.profile
8
9.SH DESCRIPTION
10Several Firejail command line configuration options can be passed to the program using
11profile files. Default Firejail profile files are stored in /etc/firejail
12directory and ~/.config/firejail directory.
13
14.SH Scripting
15Include and comment support:
16
17.TP
18\f\include other.profile
19Include other.profile file.
20.TP
21# this is a comment
22
23.SH Filesystem
24These profile entries define a chroot filesystem built on top of the existing
25host filesystem. Each line describes a file element that is removed from
26the filesystem (\fBblacklist\fR), a read-only file or directory (\fBread-only\fR),
27a tmpfs mounted on top of an existing directory (\fBtmpfs\fR),
28or mount-bind a directory or file on top of another directory or file (\fBbind\fR).
29Use \fBprivate\fR to set private mode.
30File globbing is supported, and PATH and HOME directories are searched.
31Examples:
32.TP
33\f\blacklist /usr/bin
34Remove /usr/bin directory.
35.TP
36\f\blacklist /etc/password
37Remove /etc/password file.
38.TP
39\f\read-only /etc/password
40Read-only /etc/password file.
41.TP
42tmpfs /etc
43Mount an empty tmpfs filesystem on top of /etc directory.
44.TP
45bind /root/config/ssh,/etc/ssh
46Mount-bind /root/config/ssh on /etc/ssh.
47.TP
48\f\blacklist /usr/bin/gcc*
49Remove all gcc files in /usr/bin (file globbing).
50.TP
51\f\blacklist ${PATH}/ifconfig
52Remove ifconfig command from the regular path directories.
53.TP
54\f\blacklist ${HOME}/.ssh
55Remove .ssh directory from user home directory.
56.TP
57\f\private
58Mount new /root and /home/user directories in temporary
59filesystems. All modifications are discarded when the sandbox is
60closed.
61.TP
62\f\private directory
63Use directory as user home.
64.TP
65\f\private.keep file,directory
66Build a new user home in a temporary
67filesystem, and copy the files and directories in the list in the
68new home. All modifications are discarded when the sandbox is
69closed.
70.TP
71\f\private-dev
72Create a new /dev directory. Only null, full, zero, tty, pts, ptmx, random, urandom and shm devices are available.
73
74.SH Filters
75\fBcaps\fR and \fBseccomp\fR enable Linux capabilities and seccomp filters. Examples:
76
77.TP
78caps
79Enable default Linux capabilities filter.
80.TP
81caps.drop all
82Blacklist all Linux capabilities.
83.TP
84caps.drop capability,capability,capability
85Blacklist Linux capabilities filter.
86.TP
87caps.drop capability,capability,capability
88Whitelist Linux capabilities filter.
89.TP
90\f\seccomp
91Enable default seccomp filter.
92.TP
93\f\seccomp syscall,syscall,syscall
94Enable seccomp filter and blacklist the system calls in the list on top of default seccomp filter.
95.TP
96\f\seccomp.drop syscall,syscall,syscall
97Enable seccomp filter and blacklist the system calls in the list.
98.TP
99\f\seccomp.keep syscall,syscall,syscall
100Enable seccomp filter and whitelist the system calls in the list.
101
102
103.SH User Namespace
104Use \fBnoroot\fR to enable an user namespace. The namespace has only one user, the current user.
105There is no root account defined in the namespace.
106
107.TP
108noroot
109Enable an user namespace without root user defined.
110
111
112.SH Resource limits
113These profile entries define the limits on system resources (rlimits) for the processes inside the sandbox.
114The limits can be modified inside the sandbox using the regular \fBulimt\fR command. Examples:
115
116.TP
117\f\rlimit-fsize 1024
118Set the maximum file size that can be created by a process to 1024 bytes.
119.TP
120\f\rlimit-nproc 1000
121Set the maximum number of processes that can be created for the real user ID of the calling process to 1000.
122.TP
123\f\rlimit-nofile 500
124Set the maximum number of files that can be opened by a process to 500.
125.TP
126\f\rlimit-sigpending 200
127Set the maximum number of processes that can be created for the real user ID of the calling process to 200.
128
129.SH CPU Affinity
130Set the CPU cores available for this sandbox. Examples:
131
132.TP
133cpu 1,2,3
134Use only CPU cores 0, 1 and 2.
135
136.SH Control Groups
137Place the sandbox in an existing control group specified by the full path of the task file. Example:
138
139.TP
140cgroup /sys/fs/cgroup/g1/tasks
141The sandbox is placed in g1 control group.
142
143.SH User Environment
144
145.TP
146nogroups
147Disable supplementary user groups
148.TP
149shell none
150Run the program directly, without a shell.
151
152.SH Networking
153Networking features available in profile files.
154
155.TP
156netfilter
157If a new network namespace is created, enabled default network filter.
158
159.TP
160netfilter filename
161If a new network namespace is created, enabled the network filter in filename.
162
163.TP
164dns address
165Set a DNS server for the sandbox. Up to three DNS servers can be defined.
166
167
168.SH FILES
169/etc/firejail/filename.profile, $HOME/.config/firejail/filename.profile
170
171.SH LICENSE
172Firejail is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
173.PP
174Homepage: http://firejail.sourceforge.net
175.SH SEE ALSO
176\&\flfirejail\fR\|(1),
177\&\flfiremon\fR\|(1),
178\&\flfirejail-login\fR\|(5)
179
180
181
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
new file mode 100644
index 000000000..51f21975e
--- /dev/null
+++ b/src/man/firejail.txt
@@ -0,0 +1,1196 @@
1.TH man 1 "MONTH YEAR" "VERSION" "firejail man page"
2.SH NAME
3Firejail \- Linux namespaces sandbox program
4.SH SYNOPSIS
5Start a sandbox:
6.PP
7.RS
8firejail [OPTIONS] [program and arguments]
9.RE
10.PP
11Network traffic shaping for an existing sandbox:
12.PP
13.RS
14firejail \-\-bandwidth={<name>|<PID>} bandwidth-command
15.RE
16.PP
17Monitoring:
18.PP
19.RS
20firejail {\-\-list | \-\-netstats | \-\-top | \-\-tree}
21.RE
22.PP
23Miscellaneous:
24.PP
25.RS
26firejail {\-? | \-\-debug-caps | \-\-debug-syscalls | \-\-help |
27.br
28\-\-version}
29.RE
30.SH DESCRIPTION
31Firejail is a SUID sandbox program that reduces the risk of security breaches by
32restricting the running environment of untrusted applications using Linux
33namespaces, seccomp-bpf and Linux capabilities.
34It allows a process and all its descendants to have their own private view of the
35globally shared kernel resources, such as the network stack, process table, mount table.
36Firejail can work in a SELinux or AppArmor environment,
37and it is integrated with Linux Control Groups.
38.PP
39Written in C with virtually no dependencies, the software runs on any Linux computer with a 3.x kernel version
40or newer.
41It can sandbox any type of processes: servers, graphical applications, and even user login sessions.
42The software includes sandbox profiles for a number of more common
43Linux programs, such as Mozilla Firefox, Chromium, VLC, Transmission etc.
44.SH USAGE
45Without any options, the sandbox consists of a chroot filesystem build in a new mount namespace,
46and new PID and UTS namespaces. IPC, network and user namespaces can be added using the command line options.
47The default Firejail filesystem is based on the host filesystem with the main directories mounted read-only.
48Only /home, /tmp and /var directories are writable.
49.PP
50If no program is specified as an argument, /bin/bash is started by default.
51Examples:
52.PP
53$ firejail [OPTIONS] # starting a /bin/bash shell
54.PP
55$ firejail [OPTIONS] firefox # starting Mozilla Firefox
56.PP
57Multiple commands can be run in sandbox using regular bash logic operators:
58.PP
59$ sudo firejail [OPTIONS] "/etc/init.d/nginx start && sleep inf"
60.PP
61In the previous example, "sleep inf" command is required in order to keep the session open for the daemon program.
62
63.SH OPTIONS
64.TP
65\fB\-\-
66Signal the end of options and disables further option processing.
67.TP
68\fB\-\-bandwidth=name
69Set bandwidth limits for the sandbox identified by name, see TRAFFIC SHAPING section for more details.
70.TP
71\fB\-\-bandwidth=pid
72Set bandwidth limits for the sandbox identified by PID, see TRAFFIC SHAPING section for more details.
73.TP
74\fB\-\-bind=dirname1,dirname2
75Mount-bind dirname1 on top of dirname2. This option is only available when running the sandbox as root.
76.br
77
78.br
79Example:
80.br
81# firejail \-\-bind=/config/www,/var/www
82.TP
83\fB\-\-bind=filename1,filename2
84Mount-bind filename1 on top of filename2. This option is only available when running as root.
85.br
86
87.br
88Example:
89.br
90# firejail \-\-bind=/config/etc/passwd,/etc/passwd
91.TP
92\fB\-\-blacklist=dirname_or_filename
93Blacklist directory or file.
94.br
95
96.br
97Example:
98.br
99$ firejail \-\-blacklist=/sbin \-\-blacklist=/usr/sbin
100.TP
101\fB\-c
102Execute command and exit.
103.TP
104\fB\-\-caps
105Linux capabilities is a kernel feature designed to split up the root privilege into a set of distinct privileges.
106These privileges can be enabled or disabled independently, thus restricting what a process running
107as root can do in the system.
108
109By default root programs run with all capabilities enabled. \-\-caps option disables the following capabilities:
110CAP_SYS_MODULE, CAP_SYS_RAWIO,
111CAP_SYS_BOOT, CAP_SYS_NICE, CAP_SYS_TTY_CONFIG, CAP_SYSLOG, CAP_MKNOD, CAP_SYS_ADMIN.
112The filter is applied to all processes started in the sandbox.
113.br
114
115.br
116Example:
117.br
118$ sudo firejail \-\-caps "/etc/init.d/nginx start && sleep inf"
119
120.TP
121\fB\-\-caps.drop=all
122Drop all capabilities for the processes running in the sandbox. This option is recommended for running GUI programs
123or any other program that doesn't require root privileges. It is a must-have option for sandboxing untrusted programs
124installed from unofficial sources - such as games, Java programs, etc.
125.br
126
127.br
128Example:
129.br
130$ firejail \-\-caps.drop=all warzone2100
131
132.TP
133\fB\-\-caps.drop=capability,capability,capability
134Define a custom blacklist Linux capabilities filter.
135.br
136
137.br
138Example:
139.br
140$ firejail \-\-caps.keep=net_broadcast,net_admin,net_raw
141
142.TP
143\fB\-\-caps.keep=capability,capability,capability
144Define a custom whitelist Linux capabilities filter.
145.br
146
147.br
148Example:
149.br
150$ sudo firejail \-\-caps.keep=chown,net_bind_service,setgid,\\
151setuid "/etc/init.d/nginx start && sleep inf"
152
153.TP
154\fB\-\-caps.print=name
155Print the caps filter for the sandbox identified by name.
156.br
157
158.br
159Example:
160.br
161$ firejail \-\-name=mygame \-\-caps.drop=all warzone2100 &
162.br
163[...]
164.br
165$ firejail \-\-caps.print=mygame
166
167.TP
168\fB\-\-caps.print=pid
169Print the caps filter for a sandbox identified by PID.
170.br
171
172.br
173Example:
174.br
175$ firejail \-\-list
176.br
1773272:netblue:firejail \-\-private firefox
178.br
179$ firejail \-\-caps.print=3272
180
181.TP
182\fB\-\-cgroup=tasks-file
183Place the sandbox in the specified control group. tasks-file is the full path of cgroup tasks file.
184.br
185
186.br
187Example:
188.br
189# firejail \-\-cgroup=/sys/fs/cgroup/g1/tasks
190
191.TP
192\fB\-\-chroot=dirname
193Chroot the sandbox into a root filesystem. If the sandbox is started as a
194regular user, default seccomp and capabilities filters are eanbled.
195.br
196
197.br
198Example:
199.br
200$ firejail \-\-chroot=/media/ubuntu warzone2100
201
202.TP
203\fB\-\-cpu=cpu-number,cpu-number,cpu-number
204Set CPU affinity.
205.br
206
207.br
208Example:
209.br
210$ firejail \-\-cpu=0,1 handbrake
211
212.TP
213\fB\-\-csh
214Use /bin/csh as default user shell.
215.br
216
217.br
218Example:
219.br
220$ firejail \-\-csh
221.TP
222\fB\-\-debug\fR
223Print debug messages.
224.br
225
226.br
227Example:
228.br
229$ firejail \-\-debug firefox
230.TP
231\fB\-\-debug-syscalls
232Print all recognized system calls in the current Firejail software build and exit.
233.br
234
235.br
236Example:
237.br
238$ firejail \-\-debug-syscalls
239.TP
240\fB\-\-debug-caps
241Print all recognized capabilities in the current Firejail software build and exit.
242.br
243
244.br
245Example:
246.br
247$ firejail \-\-debug-caps
248.TP
249\fB\-\-defaultgw=address
250Use this address as default gateway in the new network namespace.
251.br
252
253.br
254Example:
255.br
256$ firejail \-\-net=eth0 \-\-defaultgw=10.10.20.1 firefox
257
258.TP
259\fB\-\-dns=address
260Set a DNS server for the sandbox. Up to three DNS servers can be defined.
261Use this option if you don't trust the DNS setup on your network.
262.br
263
264.br
265Example:
266.br
267$ firejail \-\-dns=8.8.8.8 \-\-dns=8.8.4.4 firefox
268
269.TP
270\fB\-\-dns.print=name
271Print DNS configuration for a sandbox identified by name.
272.br
273
274.br
275Example:
276.br
277$ firejail \-\-name=mygame \-\-caps.drop=all warzone2100 &
278.br
279[...]
280.br
281$ firejail \-\-dns.print=mygame
282
283.TP
284\fB\-\-dns.print=pid
285Print DNS configuration for a sandbox identified by PID.
286.br
287
288.br
289Example:
290.br
291$ firejail \-\-list
292.br
2933272:netblue:firejail \-\-private firefox
294.br
295$ firejail \-\-dns.print=3272
296
297.TP
298\fB\-?\fR, \fB\-\-help\fR
299Print options end exit.
300.TP
301\fB\-\-ip=address
302Assign IP addresses to the last network interface defined by a \-\-net option. A
303default gateway is assigned by default.
304.br
305
306.br
307Example:
308.br
309$ firejail \-\-net=eth0 \-\-ip=10.10.20.56 firefox
310
311.TP
312\fB\-\-ip=none
313No IP address and no default gateway are configured for the last interface
314defined by a \-\-net option. Use this option
315in case you intend to start an external DHCP client in the sandbox.
316.br
317
318.br
319Example:
320.br
321$ firejail \-\-net=eth0 \-\-\ip=none
322
323.TP
324\fB\-\-iprange=address,address
325Assign an IP address in the provided range to the last network interface defined by a \-\-net option. A
326default gateway is assigned by default.
327.br
328
329.br
330Example:
331.br
332$ firejail \-\-net=eth0 \-\-\iprange=192.168.1.100,192.168.1.150
333
334.TP
335\fB\-\-ipc-namespace
336Enable a new IPC namespace if the sandbox was started as a regular user. IPC namespace is enabled by default
337for sandboxes started as root.
338.br
339
340.br
341Example:
342.br
343$ firejail \-\-ipc-namespace firefox
344.TP
345\fB\-\-join=name
346Join the sandbox identified by name. By default a /bin/bash shell is started after joining the sandbox.
347If a program is specified, the program is run in the sandbox.
348.br
349
350.br
351Example:
352.br
353$ firejail \-\-name=mygame \-\-caps.drop=all warzone2100 &
354.br
355[...]
356.br
357$ firejail \-\-join=mygame
358
359
360.TP
361\fB\-\-join=pid
362Join the sandbox identified by PID. By default a /bin/bash shell is started after joining the sandbox.
363If a program is specified, the program is run in the sandbox.
364.br
365
366.br
367Example:
368.br
369$ firejail \-\-list
370.br
3713272:netblue:firejail \-\-private firefox
372.br
373$ firejail \-\-join=3272
374
375.TP
376\fB\-\-list
377List all sandboxes, see MONITORING section for more details.
378.br
379
380.br
381Example:
382.br
383$ firejail \-\-list
384.br
3857015:netblue:firejail firefox
386.br
3877056:netblue:firejail \-\-net=eth0 transmission-gtk
388.br
3897064:netblue:firejail \-\-noroot xterm
390.br
391$
392.TP
393\fB\-\-mac=address
394Assign MAC addresses to the last network interface defined by a \-\-net option.
395.br
396
397.br
398Example:
399.br
400$ firejail \-\-net=eth0 \-\-mac=00:11:22:33:44:55 firefox
401
402.TP
403\fB\-\-name=name
404Set sandbox hostname. Several options, such as \-\-join and \-\-shutdown, can use
405this name to identify a sandbox.
406.br
407
408.br
409Example:
410.br
411$ firejail \-\-name=mybrowser firefox
412
413.TP
414\fB\-\-net=bridge_interface
415Enable a new network namespace and connect it to this bridge interface.
416Unless specified with option \-\-ip and \-\-defaultgw, an IP address and a default gateway will be assigned
417automatically to the sandbox. The IP address is verified using ARP before assignment. The address
418configured as default gateway is the bridge device IP address. Up to four \-\-net
419bridge devices can be defined. Mixing bridge and macvlan devices is allowed.
420.br
421
422.br
423Example:
424.br
425$ sudo brctl addbr br0
426.br
427$ sudo ifconfig br0 10.10.20.1/24
428.br
429$ sudo brctl addbr br1
430.br
431$ sudo ifconfig br1 10.10.30.1/24
432.br
433$ firejail \-\-net=br0 \-\-net=br1
434
435.TP
436\fB\-\-net=ethernet_interface
437Enable a new network namespace and connect it
438to this ethernet interface using the standard Linux macvlan
439driver. Unless specified with option \-\-ip and \-\-defaultgw, an
440IP address and a default gateway will be assigned automatically
441to the sandbox. The IP address is verified using ARP before
442assignment. The address configured as default gateway is the
443default gateway of the host. Up to four \-\-net devices can
444be defined. Mixing bridge and macvlan devices is allowed.
445.br
446
447.br
448Example:
449.br
450$ firejail \-\-net=eth0 \-\-ip=192.168.1.80 \-\-dns=8.8.8.8 firefox
451
452.TP
453\fB\-\-net=none
454Enable a new, unconnected network namespace. The only interface
455available in the new namespace is a new loopback interface (lo).
456Use this option to deny
457network access to programs that don't really need network access.
458.br
459
460.br
461Example:
462.br
463$ firejail \-\-net=none vlc
464
465.TP
466\fB\-\-netfilter
467Enable a default client network filter in the new network namespace.
468New network namespaces are created using \-\-net option. If a new network namespaces is not created,
469\-\-netfilter option does nothing.
470The default filter is as follows:
471.br
472
473.br
474*filter
475.br
476:INPUT DROP [0:0]
477.br
478:FORWARD DROP [0:0]
479.br
480:OUTPUT ACCEPT [0:0]
481.br
482\-A INPUT \-i lo \-j ACCEPT
483.br
484\-A INPUT \-m state \-\-state RELATED,ESTABLISHED \-j ACCEPT
485.br
486\-A INPUT \-p icmp \-\-icmp-type destination-unreachable \-j ACCEPT
487.br
488\-A INPUT \-p icmp \-\-icmp-type time-exceeded \-j ACCEPT
489.br
490\-A INPUT \-p icmp \-\-icmp-type echo-request \-j ACCEPT
491.br
492COMMIT
493.br
494
495.br
496Example:
497.br
498$ firejail \-\-net=eth0 \-\-netfilter firefox
499.TP
500\fB\-\-netfilter=filename
501Enable the network filter specified by filename in the new network namespace. The filter file format
502is the format of iptables-save and iptable-restore commands.
503New network namespaces are created using \-\-net option. If a new network namespaces is not created,
504\-\-netfilter option does nothing.
505.br
506
507.br
508Example:
509.br
510$ firejail \-\-net=eth0 \-\-netfilter=myfile firefox
511.TP
512\fB\-\-netstats
513Monitor network namespace statistics, see MONITORING section for more details.
514.br
515
516.br
517Example:
518.br
519$ firejail \-\-netstats
520.br
521PID User RX(KB/s) TX(KB/s) Command
522.br
5231294 netblue 53.355 1.473 firejail \-\-net=eth0 firefox
524.br
5257383 netblue 9.045 0.112 firejail \-\-net=eth0 transmission
526
527
528.TP
529\fB\-\-nogroups
530Disable supplementary groups. Without this option, supplementary groups are enabled for the user starting the
531sandbox. For root user supplementary groups are always disabled.
532.br
533
534.br
535Example:
536.br
537$ id
538.br
539uid=1000(netblue) gid=1000(netblue) groups=1000(netblue),24(cdrom),25(floppy),27(sudo),29(audio)
540.br
541$ firejail \-\-nogroups
542.br
543Parent pid 8704, child pid 8705
544.br
545Child process initialized
546.br
547$ id
548.br
549uid=1000(netblue) gid=1000(netblue) groups=1000(netblue)
550.br
551$
552
553.TP
554\fB\-\-noroot
555Install a user namespace with a single user - the current user.
556root user does not exist in the new namespace. This option
557requires a Linux kernel version 3.8 or newer. The option
558is not supported for \-\-chroot and \-\-overlay configurations,
559or for sandboxes started as root.
560.br
561
562.br
563Example:
564.br
565$ firejail \-\-noroot
566.br
567Parent pid 8553, child pid 8554
568.br
569Child process initialized
570.br
571$ ping google.com
572.br
573ping: icmp open socket: Operation not permitted
574.br
575$
576.TP
577\fB\-\-output=logfile
578stdout logging and log rotation. Copy stdout to logfile, and keep the size of the file under 500KB using log
579rotation. Five files with prefixes .1 to .5 are used in rotation.
580.br
581
582.br
583Example:
584.br
585$ firejail \-\-output=sandboxlog /bin/bash
586.br
587[...]
588.br
589$ ls -l sandboxlog*
590.br
591-rw-r--r-- 1 netblue netblue 333890 Jun 2 07:48 sadnboxlog
592.br
593-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.1
594.br
595-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.2
596.br
597-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.3
598.br
599-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.4
600.br
601-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.5
602
603.TP
604\fB\-\-overlay
605Mount a filesystem overlay on top of the current filesystem. All filesystem modifications go into the overlay,
606and are discarded when the sandbox is closed.
607.br
608
609.br
610OverlayFS support is required in Linux kernel for this option to work.
611OverlayFS was officially introduced in Linux kernel version 3.18. It was also
612available in earlier kernel versions in some distributions such as Ubuntu and OpenSUSE.
613.br
614
615.br
616Example:
617.br
618$ firejail \-\-overlay firefox
619
620.TP
621\fB\-\-private
622Mount new /root and /home/user directories in temporary
623filesystems. All modifications are discarded when the sandbox is
624closed.
625.br
626
627.br
628Example:
629.br
630$ firejail \-\-private firefox
631.TP
632\fB\-\-private=directory
633Use directory as user home.
634.br
635
636.br
637Example:
638.br
639$ firejail \-\-private=/home/netblue/firefox-home firefox
640
641.TP
642\fB\-\-private.keep=file,directory
643Build a new user home in a temporary
644filesystem, and copy the files and directories in the list in the
645new home. All modifications are discarded when the sandbox is
646closed.
647.br
648
649.br
650Example:
651.br
652$ firejail \-\-private.keep=.mozilla firefox
653.TP
654\fB\-\-private-dev
655Create a new /dev directory. Only null, full, zero, tty, pts, ptmx, random, urandom and shm devices are available.
656.br
657
658.br
659Example:
660.br
661$ firejail \-\-private-dev
662.br
663Parent pid 9887, child pid 9888
664.br
665Child process initialized
666.br
667$ ls /dev
668.br
669full null ptmx pts random shm tty urandom zero
670.br
671$
672.TP
673\fB\-\-profile=filename
674Load a custom profile from filename. For filename use an absolute path or a path relative to the current path.
675For more information, see PROFILES section below.
676.br
677
678.br
679Example:
680.br
681$ firejail \-\-profile=myprofile
682.TP
683\fB\-\-read-only=dirname_or_filename
684Set directory or file read-only.
685.br
686
687.br
688Example:
689.br
690$ firejail \-\-read-only=~/.mozilla firefox
691.TP
692\fB\-\-rlimit-fsize=number
693Set the maximum file size that can be created by a process.
694.TP
695\fB\-\-rlimit-nofile=number
696Set the maximum number of files that can be opened by a process.
697.TP
698\fB\-\-rlimit-nproc=number
699Set the maximum number of processes that can be created for the real user ID of the calling process.
700.TP
701\fB\-\-rlimit-sigpending=number
702Set the maximum number of pending signals for a process.
703.TP
704\fB\-\-scan
705ARP-scan all the networks from inside a network namespace.
706This makes it possible to detect macvlan kernel device drivers running on the current host.
707.br
708
709.br
710Example:
711.br
712$ firejail \-\-net=eth0 \-\-scan
713.TP
714\fB\-\-seccomp
715Enable seccomp filter and blacklist the syscalls in the default list. The default list is as follows:
716mount, umount2, ptrace, kexec_load, open_by_handle_at, init_module, finit_module, delete_module,
717iopl, ioperm, swapon, swapoff, mknode, syslog, process_vm_readv and process_vm_writev,
718sysfs,_sysctl, adjtimex, clock_adjtime, lookup_dcookie, perf_event_open, fanotify_init and kcmp.
719.br
720
721.br
722Example:
723.br
724$ firejail \-\-sccomp
725.TP
726\fB\-\-seccomp=syscall,syscall,syscall
727Enable seccomp filter, blacklist the default list and the syscalls specified by the command.
728.br
729
730.br
731Example:
732.br
733$ firejail \-\-seccomp=utime,utimensat,utimes firefox
734.TP
735\fB\-\-seccomp.drop=syscall,syscall,syscall
736Enable seccomp filter, and blacklist the syscalls specified by the command.
737.br
738
739.br
740Example:
741.br
742$ firejail \-\-seccomp.drop=utime,utimensat,utimes
743.TP
744\fB\-\-seccomp.keep=syscall,syscall,syscall
745Enable seccomp filter, and whitelist the syscalls specified by the command.
746.br
747
748.br
749Example:
750.br
751$ firejail \-\-shell=none \-\-seccomp.keep=poll,select,[...] transmission-gtk
752.TP
753\fB\-\-seccomp.print=name
754Print the seccomp filter for the sandbox started using \-\-name option.
755.br
756
757.br
758Example:
759.br
760$ firejail \-\-name=browser firefox &
761.br
762$ firejail \-\-seccomp.print=browser
763.br
764SECCOMP Filter:
765.br
766 VALIDATE_ARCHITECTURE
767.br
768 EXAMINE_SYSCAL
769.br
770 BLACKLIST 165 mount
771.br
772 BLACKLIST 166 umount2
773.br
774 BLACKLIST 101 ptrace
775.br
776 BLACKLIST 246 kexec_load
777.br
778 BLACKLIST 304 open_by_handle_at
779.br
780 BLACKLIST 175 init_module
781.br
782 BLACKLIST 176 delete_module
783.br
784 BLACKLIST 172 iopl
785.br
786 BLACKLIST 173 ioperm
787.br
788 BLACKLIST 167 swapon
789.br
790 BLACKLIST 168 swapoff
791.br
792 BLACKLIST 103 syslog
793.br
794 BLACKLIST 310 process_vm_readv
795.br
796 BLACKLIST 311 process_vm_writev
797.br
798 BLACKLIST 133 mknod
799.br
800 BLACKLIST 139 sysfs
801.br
802 BLACKLIST 156 _sysctl
803.br
804 BLACKLIST 159 adjtimex
805.br
806 BLACKLIST 305 clock_adjtime
807.br
808 BLACKLIST 212 lookup_dcookie
809.br
810 BLACKLIST 298 perf_event_open
811.br
812 BLACKLIST 300 fanotify_init
813.br
814 RETURN_ALLOW
815.br
816$
817.TP
818\fB\-\-seccomp.print=pid
819Print the seccomp filter for the sandbox specified by process ID. Use \-\-list option to get a list of all active sandboxes.
820.br
821
822.br
823Example:
824.br
825$ firejail \-\-list
826.br
82710786:netblue:firejail \-\-name=browser firefox
828$ firejail \-\-seccomp.print=10786
829.br
830SECCOMP Filter:
831.br
832 VALIDATE_ARCHITECTURE
833.br
834 EXAMINE_SYSCAL
835.br
836 BLACKLIST 165 mount
837.br
838 BLACKLIST 166 umount2
839.br
840 BLACKLIST 101 ptrace
841.br
842 BLACKLIST 246 kexec_load
843.br
844 BLACKLIST 304 open_by_handle_at
845.br
846 BLACKLIST 175 init_module
847.br
848 BLACKLIST 176 delete_module
849.br
850 BLACKLIST 172 iopl
851.br
852 BLACKLIST 173 ioperm
853.br
854 BLACKLIST 167 swapon
855.br
856 BLACKLIST 168 swapoff
857.br
858 BLACKLIST 103 syslog
859.br
860 BLACKLIST 310 process_vm_readv
861.br
862 BLACKLIST 311 process_vm_writev
863.br
864 BLACKLIST 133 mknod
865.br
866 BLACKLIST 139 sysfs
867.br
868 BLACKLIST 156 _sysctl
869.br
870 BLACKLIST 159 adjtimex
871.br
872 BLACKLIST 305 clock_adjtime
873.br
874 BLACKLIST 212 lookup_dcookie
875.br
876 BLACKLIST 298 perf_event_open
877.br
878 BLACKLIST 300 fanotify_init
879.br
880 RETURN_ALLOW
881.br
882$
883.TP
884\fB\-\-shell=none
885Run the program directly, without a user shell.
886.br
887
888.br
889Example:
890.br
891$ firejail \-\-shell=none script.sh
892.TP
893\fB\-\-shell=program
894Set default user shell. Use this shell to run the application using \-c shell option.
895For example "firejail \-\-shell=/bin/dash firefox" will start Mozilla Firefox as "/bin/dash \-c firefox".
896By default Bash shell (/bin/bash) is used. Options such as \-\-zsh and \-\-csh can also set the default
897shell.
898.br
899
900.br
901Example:
902$firejail \-\-shell=/bin/dash script.sh
903.TP
904\fB\-\-shutdown=name
905Shutdown the sandbox started using \-\-name option.
906.br
907
908.br
909Example:
910.br
911$ firejail \-\-name=mygame \-\-caps.drop=all warzone2100 &
912.br
913[...]
914.br
915$ firejail \-\-shutdown=mygame
916.TP
917\fB\-\-shutdown=pid
918Shutdown the sandbox specified by process ID. Use \-\-list option to get a list of all active sandboxes.
919.br
920
921.br
922Example:
923.br
924$ firejail \-\-list
925.br
9263272:netblue:firejail \-\-private firefox
927.br
928$ firejail \-\-shutdown=3272
929.TP
930\fB\-\-tmpfs=dirname
931Mount a tmpfs filesystem on directory dirname.
932.br
933
934.br
935Example:
936.br
937$ firejail \-\-tmpfs=/var
938.TP
939\fB\-\-top
940Monitor the most CPU-intensive sandboxes, see MONITORING section for more details.
941.br
942
943.br
944Example:
945.br
946$ firejail \-\-top
947.TP
948\fB\-\-trace
949Trace open, access and connect system calls.
950.br
951
952.br
953Example:
954.br
955$ firejail \-\-trace wget -q www.debian.org
956.br
957Parent pid 11793, child pid 11794
958.br
959Child process initialized
960.br
9611:bash:open /dev/tty
962.br
9631:wget:fopen64 /etc/wgetrc
964.br
9651:wget:fopen /etc/hosts
966.br
9671:wget:socket AF_INET SOCK_DGRAM IPPROTO_IP
968.br
9691:wget:connect 8.8.8.8:53
970.br
9711:wget:socket AF_INET SOCK_STREAM IPPROTO_IP
972.br
9731:wget:connect 140.211.15.34:80
974.br
9751:wget:fopen64 index.html.1
976.br
977
978.br
979parent is shutting down, bye...
980.TP
981\fB\-\-tree
982Print a tree of all sandboxed processes, see MONITORING section for more details.
983.br
984
985.br
986Example:
987.br
988$ firejail \-\-tree
989.br
99011903:netblue:firejail iceweasel
991.br
992 11904:netblue:iceweasel
993.br
994 11957:netblue:/usr/lib/iceweasel/plugin-container
995.br
99611969:netblue:firejail \-\-net=eth0 transmission-gtk
997.br
998 11970:netblue:transmission-gtk
999.TP
1000\fB\-\-version
1001Print program version and exit.
1002.br
1003
1004.br
1005Example:
1006.br
1007$ firejail \-\-version
1008.br
1009firejail version 0.9.27
1010.TP
1011\fB\-\-zsh
1012Use /usr/bin/zsh as default user shell.
1013.br
1014
1015.br
1016Example:
1017.br
1018$ firejakil \-\-zsh
1019.SH TRAFFIC SHAPING
1020Network bandwidth is an expensive resource shared among all sandboxes running on a system.
1021Traffic shaping allows the user to increase network performance by controlling
1022the amount of data that flows into and out of the sandboxes.
1023
1024Firejail implements a simple rate-limiting shaper based on Linux command tc.
1025The shaper works at sandbox level, and can be used only for sandboxes configured with new network namespaces.
1026
1027Set rate-limits:
1028
1029 firejail --bandwidth={name|pid} set network download upload
1030
1031Clear rate-limits:
1032
1033 firejail --bandwidth={name|pid} clear network
1034
1035Status:
1036
1037 firejail --bandwidth={name|pid} status
1038
1039where:
1040.br
1041 name - sandbox name
1042.br
1043 pid - sandbox pid
1044.br
1045 network - network interface as used by \-\-net option
1046.br
1047 download - download speed in KB/s (kilobyte per second)
1048.br
1049 upload - upload speed in KB/s (kilobyte per second)
1050
1051Example:
1052.br
1053 $ firejail \-\-name=mybrowser \-\-net=eth0 firefox &
1054.br
1055 $ firejail \-\-bandwidth=mybrowser set eth0 80 20
1056.br
1057 $ firejail \-\-bandwidth=mybrowser status
1058.br
1059 $ firejail \-\-bandwidth=mybrowser clear eth0
1060
1061.SH MONITORING
1062Option \-\-list prints a list of all sandboxes. The format
1063for each process entry is as follows:
1064
1065 PID:USER:Command
1066
1067Option \-\-tree prints the tree of processes running in the sandbox. The format
1068for each process entry is as follows:
1069
1070 PID:USER:Command
1071
1072Option \-\-top is similar to the UNIX top command, however it applies only to
1073sandboxes.
1074
1075Option \-\-netstats prints network statistics for active sandboxes installing new network namespaces.
1076
1077
1078Listed below are the available fields (columns) in alphabetical
1079order for \-\-top and \-\-netstat options:
1080
1081.TP
1082Command
1083Command used to start the sandbox.
1084.TP
1085CPU%
1086CPU usage, the sandbox share of the elapsed CPU time since the
1087last screen update
1088.TP
1089PID
1090Unique process ID for the task controlling the sandbox.
1091.TP
1092Prcs
1093Number of processes running in sandbox, including the controlling process.
1094.TP
1095RES
1096Resident Memory Size (KiB), sandbox non-swapped physical memory.
1097It is a sum of the RES values for all processes running in the sandbox.
1098.TP
1099RX(KB/s)
1100Network receive speed.
1101.TP
1102SHR
1103Shared Memory Size (KiB), it reflects memory shared with other
1104processes. It is a sum of the SHR values for all processes running
1105in the sandbox, including the controlling process.
1106.TP
1107TX(KB/s)
1108Network transmit speed.
1109.TP
1110Uptime
1111Sandbox running time in hours:minutes:seconds format.
1112.TP
1113User
1114The owner of the sandbox.
1115
1116.SH PROFILES
1117Several command line configuration options can be passed to the program using
1118profile files. Firejail supports user specified profile files and automatic profile files,
1119as follows:
1120
11211. Load a specific profile file from a full path, or a path relative to the current directory.
1122Example:
1123.PP
1124.RS
1125$ firejail --profile=/home/netblue/icecat.profile icecat
1126.RE
1127
11282. Load a default profile file automatically from ~/.config/firejail or from /etc/firejail, based
1129on the name of the executable started in the sandbox. Example:
1130.PP
1131.RS
1132$ firejail icecat
1133.br
1134Command name #icecat#
1135.br
1136.br
1137Found icecat profile in /home/netblue/.config/firejail directory
1138.br
1139Reading profile /home/netblue/.config/firejail/icecat.profile
1140.br
1141[...]
1142.RE
1143
1144See man 5 firejail-profile for profile file syntax information.
1145
1146.SH RESTRICTED SHELL
1147To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in
1148/etc/password file for each user that needs to be restricted. Alternatively,
1149you can specify /usr/bin/firejail in adduser command:
1150
1151adduser \-\-shell /usr/bin/firejail username
1152
1153Additional arguments passed to firejail executable upon login are declared in /etc/firejail/login.users file.
1154
1155.SH EXAMPLES
1156.TP
1157\f\firejail
1158Start a regular /bin/bash session in sandbox.
1159.TP
1160\f\firejail firefox
1161Start Mozilla Firefox.
1162.TP
1163\f\firejail \-\-seccomp firefox
1164Start Mozilla Firefox in a seccomp sandbox.
1165.TP
1166\f\firejail \-\-caps firefox
1167Start Mozilla Firefox in a Linux capabilities sandbox.
1168.TP
1169\f\firejail \-\-debug firefox
1170Debug Firefox sandbox.
1171.TP
1172\f\firejail \-\-private
1173Start a /bin/bash session with a new tmpfs home directory.
1174.TP
1175\f\firejail \-\-net=br0 ip=10.10.20.10
1176Start a /bin/bash session in a new network namespace. The session is
1177connected to the main network using br0 bridge device. An IP address
1178of 10.10.20.10 is assigned to the sandbox.
1179.TP
1180\f\firejail \-\-net=br0 \-\-net=br1 \-\-net=br2
1181Start a /bin/bash session in a new network namespace and connect it
1182to br0, br1, and br2 host bridge devices.
1183.TP
1184\f\firejail \-\-list
1185List all sandboxed processes.
1186.SH LICENSE
1187This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
1188.PP
1189Homepage: http://firejail.sourceforge.net
1190.SH SEE ALSO
1191\&\flfiremon\fR\|(1),
1192\&\flfirejail-profile\fR\|(5),
1193\&\flfirejail-login\fR\|(5)
1194
1195
1196
diff --git a/src/man/firemon.txt b/src/man/firemon.txt
new file mode 100644
index 000000000..b6010f46e
--- /dev/null
+++ b/src/man/firemon.txt
@@ -0,0 +1,107 @@
1.TH man 1 "MONTH YEAR" "VERSION" "firemon man page"
2.SH NAME
3Firemon \- Monitoring program for processes started in a Firejail sandbox.
4.SH SYNOPSIS
5firemon [OPTIONS] [PID]
6.SH DESCRIPTION
7Firemon monitors programs started in a Firejail sandbox.
8Without a PID specified, all processes started by Firejail are monitored. Descendants of
9these processes are also being monitored.
10.SH OPTIONS
11.TP
12\fB\-\-arp
13Print ARP table for each sandbox.
14.TP
15\fB\-\-caps
16Print capabilities configuration for each sandbox.
17.TP
18\fB\-\-cgroup
19Print control group information for each sandbox.
20.TP
21\fB\-\-cpu
22Print CPU affinity for each sandbox.
23.TP
24\fB\-?\fR, \fB\-\-help\fR
25Print options end exit.
26.TP
27\fB\-\-interface
28Print network interface information for each sandbox.
29.TP
30\fB\-\-list
31List all sandboxes.
32.TP
33\fB\-\-name=name
34Print information only about named sandbox.
35.TP
36\fB\-\-netstats
37Monitor network statistics for sandboxes creating a new network namespace.
38.TP
39\fB\-\-route
40Print route table for each sandbox.
41.TP
42\fB\-\-seccomp
43Print seccomp configuration for each sandbox.
44.TP
45\fB\-\-top
46Monitor the most CPU-intensive sandboxes.
47.TP
48\fB\-\-tree
49Print a tree of all sandboxed processes.
50.TP
51\fB\-\-version
52Print program version and exit.
53
54.PP
55Option \-\-list prints a list of all sandboxes. The format
56for each entry is as follows:
57
58 PID:USER:Command
59
60Option \-\-tree prints the tree of processes running in the sandbox. The format
61for each process entry is as follows:
62
63 PID:USER:Command
64
65Option \-\-top is similar to the UNIX top command, however it applies only to
66sandboxes. Listed below are the available fields (columns) in alphabetical
67order:
68
69.TP
70Command
71Command used to start the sandbox.
72.TP
73CPU%
74CPU usage, the sandbox share of the elapsed CPU time since the
75last screen update
76.TP
77PID
78Unique process ID for the task controlling the sandbox.
79.TP
80Prcs
81Number of processes running in sandbox, including the controlling process.
82.TP
83RES
84Resident Memory Size (KiB), sandbox non-swapped physical memory.
85It is a sum of the RES values for all processes running in the sandbox.
86.TP
87SHR
88Shared Memory Size (KiB), it reflects memory shared with other
89processes. It is a sum of the SHR values for all processes running
90in the sandbox, including the controlling process.
91.TP
92Uptime
93Sandbox running time in hours:minutes:seconds format.
94.TP
95User
96The owner of the sandbox.
97
98.SH LICENSE
99This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
100.PP
101Homepage: http://firejail.sourceforge.net
102.SH SEE ALSO
103\&\flfirejail\fR\|(1),
104\&\flfirejail-profile\fR\|(5),
105\&\flfirejail-login\fR\|(5)
106
107
diff --git a/src/tools/check-caps.sh b/src/tools/check-caps.sh
new file mode 100755
index 000000000..13525677b
--- /dev/null
+++ b/src/tools/check-caps.sh
@@ -0,0 +1,46 @@
1#!/bin/bash
2
3if [ $# -eq 0 ]
4then
5 echo "Usage: check-caps.sh program-and-arguments"
6 echo
7fi
8
9set -x
10
11firejail --caps.drop=chown "$1"
12firejail --caps.drop=dac_override "$1"
13firejail --caps.drop=dac_read_search "$1"
14firejail --caps.drop=fowner "$1"
15firejail --caps.drop=fsetid "$1"
16firejail --caps.drop=kill "$1"
17firejail --caps.drop=setgid "$1"
18firejail --caps.drop=setuid "$1"
19firejail --caps.drop=setpcap "$1"
20firejail --caps.drop=linux_immutable "$1"
21firejail --caps.drop=net_bind_service "$1"
22firejail --caps.drop=net_broadcast "$1"
23firejail --caps.drop=net_admin "$1"
24firejail --caps.drop=net_raw "$1"
25firejail --caps.drop=ipc_lock "$1"
26firejail --caps.drop=ipc_owner "$1"
27firejail --caps.drop=sys_module "$1"
28firejail --caps.drop=sys_rawio "$1"
29firejail --caps.drop=sys_chroot "$1"
30firejail --caps.drop=sys_ptrace "$1"
31firejail --caps.drop=sys_pacct "$1"
32firejail --caps.drop=sys_admin "$1"
33firejail --caps.drop=sys_boot "$1"
34firejail --caps.drop=sys_nice "$1"
35firejail --caps.drop=sys_resource "$1"
36firejail --caps.drop=sys_time "$1"
37firejail --caps.drop=sys_tty_config "$1"
38firejail --caps.drop=mknod "$1"
39firejail --caps.drop=lease "$1"
40firejail --caps.drop=audit_write "$1"
41firejail --caps.drop=audit_control "$1"
42firejail --caps.drop=setfcap "$1"
43firejail --caps.drop=mac_override "$1"
44firejail --caps.drop=mac_admin "$1"
45firejail --caps.drop=syslog "$1"
46firejail --caps.drop=wake_alarm "$1"
diff --git a/src/tools/extract_caps.c b/src/tools/extract_caps.c
new file mode 100644
index 000000000..94a062ccb
--- /dev/null
+++ b/src/tools/extract_caps.c
@@ -0,0 +1,83 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <assert.h>
24
25#define BUFMAX 4096
26
27int main(int argc, char **argv) {
28 if (argc != 2) {
29 printf("usage: %s /usr/include/linux/capability.h\n", argv[0]);
30 return 1;
31 }
32
33 //open file
34 FILE *fp = fopen(argv[1], "r");
35 if (!fp) {
36 fprintf(stderr, "Error: cannot open file\n");
37 return 1;
38 }
39
40 // read file
41 char buf[BUFMAX];
42 while (fgets(buf, BUFMAX, fp)) {
43 // cleanup
44 char *start = buf;
45 while (*start == ' ' || *start == '\t')
46 start++;
47 char *end = strchr(start, '\n');
48 if (end)
49 *end = '\0';
50
51 // parsing
52 if (strncmp(start, "#define CAP_", 12) == 0) {
53 if (strstr(start, "CAP_LAST_CAP"))
54 break;
55
56 char *ptr1 = start + 8;
57 char *ptr2 = ptr1;
58 while (*ptr2 == ' ' || *ptr2 == '\t')
59 ptr2++;
60 while (*ptr2 != ' ' && *ptr2 != '\t')
61 ptr2++;
62 *ptr2 = '\0';
63
64 ptr2 = strdup(ptr1);
65 assert(ptr2);
66 ptr2 += 4;
67 char *ptr3 = ptr2;
68 while (*ptr3 != '\0') {
69 *ptr3 = tolower(*ptr3);
70 ptr3++;
71 }
72
73
74 printf("#ifdef %s\n", ptr1);
75 printf("\t{\"%s\", %s },\n", ptr2, ptr1);
76 printf("#endif\n");
77
78 }
79
80 }
81 fclose(fp);
82 return 0;
83}
diff --git a/src/tools/extract_syscalls.c b/src/tools/extract_syscalls.c
new file mode 100644
index 000000000..0e064a49e
--- /dev/null
+++ b/src/tools/extract_syscalls.c
@@ -0,0 +1,91 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include <stdio.h>
21#include <stdlib.h>6
22#include <string.h>
23
24#define BUFMAX 4096
25
26int main(int argc, char **argv) {
27 if (argc != 2) {
28 printf("usage: %s /media/ubuntu/usr/include/x86_64-linux-gnu/bits/syscall.h\n", argv[0]);
29 return 1;
30 }
31
32 //open file
33 FILE *fp = fopen(argv[1], "r");
34 if (!fp) {
35 fprintf(stderr, "Error: cannot open file\n");
36 return 1;
37 }
38
39 // read file
40 char buf[BUFMAX];
41 while (fgets(buf, BUFMAX, fp)) {
42 // cleanup
43 char *start = buf;
44 while (*start == ' ' || *start == '\t')
45 start++;
46 char *end = strchr(start, '\n');
47 if (end)
48 *end = '\0';
49
50 // parsing
51 if (strncmp(start, "#endif", 6) == 0)
52 printf("%s\n", start);
53 if (strncmp(start, "#endif", 6) == 0)
54 printf("%s\n", start);
55 else if (strncmp(start, "#if", 3) == 0)
56 printf("%s\n", start);
57 else if (strncmp(start, "#define", 7) == 0) {
58 // extract data
59 char *ptr1 = strstr(start, "SYS_");
60 char *ptr2 = strstr(start, "__NR_");
61 if (!ptr1 || !ptr2) {
62 fprintf(stderr, "Error: cannot parse \"%s\"\n", start);
63 fclose(fp);
64 return 1;
65 }
66 *(ptr2 - 1) = '\0';
67
68 char *ptr3 = ptr1;
69 while (*ptr3 != ' ' && *ptr3 != '\t' && *ptr3 != '\0')
70 ptr3++;
71 *ptr3 = '\0';
72 ptr3 = ptr2;
73 while (*ptr3 != ' ' && *ptr3 != '\t' && *ptr3 != '\0')
74 ptr3++;
75 *ptr3 = '\0';
76
77 ptr3 = ptr1;
78 while (*ptr3 != '_')
79 ptr3++;
80 ptr3++;
81
82 printf("#ifdef %s\n", ptr1);
83 printf("#ifdef %s\n", ptr2);
84 printf("\t{\"%s\", %s},\n", ptr3, ptr2);
85 printf("#endif\n");
86 printf("#endif\n");
87 }
88 }
89 fclose(fp);
90 return 0;
91}
diff --git a/src/tools/mkcoverit.sh b/src/tools/mkcoverit.sh
new file mode 100755
index 000000000..4af84a7a1
--- /dev/null
+++ b/src/tools/mkcoverit.sh
@@ -0,0 +1,45 @@
1#!/bin/bash
2
3# unpack firejail archive
4ARCFIREJAIL=`ls *.tar.bz2| grep firejail`
5if [ "$?" -eq 0 ];
6then
7 echo "preparing $ARCFIREJAIL"
8 DIRFIREJAIL=`basename $ARCFIREJAIL .tar.bz2`
9 rm -fr $DIRFIREJAIL
10 tar -xjvf $ARCFIREJAIL
11 cd $DIRFIREJAIL
12 ./configure --prefix=/usr
13 cd ..
14else
15 echo "Error: firejail source archive missing"
16 exit 1
17fi
18
19
20# unpack firetools archive
21ARCFIRETOOLS=`ls *.tar.bz2 | grep firetools`
22if [ "$?" -eq 0 ];
23then
24 echo "preparing $ARCFIRETOOLS"
25 DIRFIRETOOLS=`basename $ARCFIRETOOLS .tar.bz2`
26 rm -fr $DIRFIRETOOLS
27 tar -xjvf $ARCFIRETOOLS
28 cd $DIRFIRETOOLS
29 pwd
30 ./configure --prefix=/usr
31 cd ..
32
33else
34 echo "Error: firetools source archive missing"
35 exit 1
36fi
37
38# move firetools in firejail source tree
39mkdir -p $DIRFIREJAIL/extras
40mv $DIRFIRETOOLS $DIRFIREJAIL/extras/firetools
41
42# build
43cd $DIRFIREJAIL
44cov-build --dir cov-int make -j 4 extras
45tar czvf myproject.tgz cov-int
diff --git a/src/tools/rvtest.c b/src/tools/rvtest.c
new file mode 100644
index 000000000..95050e671
--- /dev/null
+++ b/src/tools/rvtest.c
@@ -0,0 +1,144 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21// run it as "rvtest 2>/dev/null | grep TESTING"
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <string.h>
27#include <sys/types.h>
28#include <signal.h>
29
30#define MAXBUF 1024 // line buffer
31#define TIMEOUT 30 // timeout time in seconds
32
33static pid_t pid;
34static void catch_alarm(int sig) {
35 kill(pid, SIGTERM);
36 sleep(1);
37 kill(pid, SIGKILL);
38 printf("TESTING ERROR: SIGALARM triggered\n");
39 exit(1);
40}
41
42static void usage(void) {
43 printf("Usage: rvtest testfile\n");
44 printf("\n");
45 printf("Testfile format:\n");
46 printf("\tretval command\n");
47 printf("\n");
48 printf("Testfile example:\n");
49 printf("\n");
50 printf("0 firejail --net=none exit\n");
51 printf("1 firejail --private=/etc sleep 1\n");
52 printf("1 firejail --blablabla\n");
53}
54
55int main(int argc, char **argv) {
56 if (argc != 2) {
57 fprintf(stderr, "Error: test file missing\n");
58 usage();
59 return 1;
60 }
61
62 signal (SIGALRM, catch_alarm);
63
64 // open test file
65 char *fname = argv[1];
66 FILE *fp = fopen(fname, "r");
67
68 // read test file
69 char buf[MAXBUF];
70 int line = 0;
71 while (fgets(buf, MAXBUF, fp)) {
72 line++;
73 // skip blanks
74 char *start = buf;
75 while (*start == ' ' || *start == '\t')
76 start++;
77 // remove '\n'
78 char *ptr = strchr(start, '\n');
79 if (ptr)
80 *ptr ='\0';
81 if (*start == '\0')
82 continue;
83
84 // skip comments
85 if (*start == '#')
86 continue;
87 ptr = strchr(start, '#');
88 if (ptr)
89 *ptr = '\0';
90
91 // extract exit status
92 int status;
93 int rv = sscanf(start, "%d\n", &status);
94 if (rv != 1) {
95 fprintf(stderr, "Error: invalid line %d in %s\n", line, fname);
96 exit(1);
97 }
98
99 // extract command
100 char *cmd = strchr(start, ' ');
101 if (!cmd) {
102 fprintf(stderr, "Error: invalid line %d in %s\n", line, fname);
103 exit(1);
104 }
105
106 // execute command
107 printf("TESTING %s\n", cmd);
108 fflush(0);
109 pid = fork();
110 if (pid == -1) {
111 perror("fork");
112 exit(1);
113 }
114
115 // child
116 if (pid == 0) {
117 char *earg[50];
118 earg[0] = "/bin/bash";
119 earg[1] = "-c";
120 earg[2] = cmd;
121 earg[3] = NULL;
122 execvp(earg[0], earg);
123 }
124 // parent
125 else {
126 int exit_status;
127
128 alarm(TIMEOUT);
129 pid = waitpid(pid, &exit_status, 0);
130 if (pid == -1) {
131 perror("waitpid");
132 exit(1);
133 }
134
135 if (WEXITSTATUS(exit_status) != status)
136 printf("ERROR TESTING: %s\n", cmd);
137 }
138
139 fflush(0);
140 }
141 fclose(fp);
142
143 return 0;
144} \ No newline at end of file
diff --git a/src/tools/ttytest.c b/src/tools/ttytest.c
new file mode 100644
index 000000000..a449bf9ba
--- /dev/null
+++ b/src/tools/ttytest.c
@@ -0,0 +1,36 @@
1#define _XOPEN_SOURCE 600
2#include <stdlib.h>
3#include <stdio.h>
4#include <fcntl.h>
5#include <errno.h>
6
7int main(void) {
8 int fdm;
9 int rc;
10
11 // initial
12 system("ls -l /dev/pts");
13
14 fdm = posix_openpt(O_RDWR);
15 if (fdm < 0) {
16 perror("posix_openpt");
17 return 1;
18 }
19
20 rc = grantpt(fdm);
21 if (rc != 0) {
22 perror("grantpt");
23 return 1;
24 }
25
26 rc = unlockpt(fdm);
27 if (rc != 0) {
28 perror("unlockpt");
29 return 1;
30 }
31
32 // final
33 system("ls -l /dev/pts");
34
35 return 0;
36}
diff --git a/test/4bridges_arp.exp b/test/4bridges_arp.exp
new file mode 100755
index 000000000..3004082e6
--- /dev/null
+++ b/test/4bridges_arp.exp
@@ -0,0 +1,175 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check eth0
8send -- "firejail --net=br0 --net=br1 --net=br2 --net=br3\r"
9expect {
10 timeout {puts "TESTING ERROR 0.0\n";exit}
11 "eth0"
12}
13expect {
14 timeout {puts "TESTING ERROR 0.1\n";exit}
15 "10.10.20"
16}
17expect {
18 timeout {puts "TESTING ERROR 0.2\n";exit}
19 "255.255.255.248"
20}
21expect {
22 timeout {puts "TESTING ERROR 0.3\n";exit}
23 "UP"
24}
25expect {
26 timeout {puts "TESTING ERROR 0.4\n";exit}
27 "Child process initialized"
28}
29sleep 2
30send -- "exit\r"
31sleep 2
32
33# check eth1
34send -- "firejail --net=br0 --net=br1 --net=br2 --net=br3\r"
35expect {
36 timeout {puts "TESTING ERROR 1.0\n";exit}
37 "eth1"
38}
39expect {
40 timeout {puts "TESTING ERROR 1.1\n";exit}
41 "10.10.30"
42}
43expect {
44 timeout {puts "TESTING ERROR 1.2\n";exit}
45 "255.255.255.0"
46}
47expect {
48 timeout {puts "TESTING ERROR 1.3\n";exit}
49 "UP"
50}
51expect {
52 timeout {puts "TESTING ERROR 1.4\n";exit}
53 "Child process initialized"
54}
55sleep 2
56send -- "exit\r"
57sleep 2
58
59
60# check eth2
61send -- "firejail --net=br0 --net=br1 --net=br2 --net=br3\r"
62expect {
63 timeout {puts "TESTING ERROR 2.0\n";exit}
64 "eth2"
65}
66expect {
67 timeout {puts "TESTING ERROR 2.1\n";exit}
68 "10.10.40"
69}
70expect {
71 timeout {puts "TESTING ERROR 2.2\n";exit}
72 "255.255.255.0"
73}
74expect {
75 timeout {puts "TESTING ERROR 2.3\n";exit}
76 "UP"
77}
78expect {
79 timeout {puts "TESTING ERROR 2.4\n";exit}
80 "Child process initialized"
81}
82sleep 2
83send -- "exit\r"
84sleep 2
85
86
87
88# check eth3
89send -- "firejail --net=br0 --net=br1 --net=br2 --net=br3\r"
90expect {
91 timeout {puts "TESTING ERROR 3.0\n";exit}
92 "eth3"
93}
94expect {
95 timeout {puts "TESTING ERROR 3.1\n";exit}
96 "10.10.50"
97}
98expect {
99 timeout {puts "TESTING ERROR 3.2\n";exit}
100 "255.255.255.0"
101}
102expect {
103 timeout {puts "TESTING ERROR 3.3\n";exit}
104 "UP"
105}
106expect {
107 timeout {puts "TESTING ERROR 4\n";exit}
108 "Child process initialized"
109}
110sleep 2
111send -- "exit\r"
112sleep 2
113
114
115
116
117# check loopback
118send -- "firejail --net=br0 --net=br1 --net=br2 --net=br3\r"
119expect {
120 timeout {puts "TESTING ERROR 5\n";exit}
121 "lo"
122}
123expect {
124 timeout {puts "TESTING ERROR 6\n";exit}
125 "127.0.0.1"
126}
127expect {
128 timeout {puts "TESTING ERROR 7\n";exit}
129 "255.0.0.0"
130}
131expect {
132 timeout {puts "TESTING ERROR 8\n";exit}
133 "UP"
134}
135expect {
136 timeout {puts "TESTING ERROR 9\n";exit}
137 "Child process initialized"
138}
139
140# check default gateway
141send -- "bash\r"
142sleep 1
143send -- "netstat -rn;pwd\r"
144expect {
145 timeout {puts "TESTING ERROR 10.1\n";exit}
146 "0.0.0.0"
147}
148expect {
149 timeout {puts "TESTING ERROR 10.2\n";exit}
150 "10.10.20.1"
151}
152expect {
153 timeout {puts "TESTING ERROR 10.3\n";exit}
154 "eth0"
155}
156expect {
157 timeout {puts "TESTING ERROR 10.4\n";exit}
158 "10.10.20.0"
159}
160expect {
161 timeout {puts "TESTING ERROR 10.5\n";exit}
162 "0.0.0.0"
163}
164expect {
165 timeout {puts "TESTING ERROR 10.6\n";exit}
166 "eth0"
167}
168expect {
169 timeout {puts "TESTING ERROR 10\n";exit}
170 "home"
171}
172sleep 1
173
174puts "\n"
175
diff --git a/test/4bridges_ip.exp b/test/4bridges_ip.exp
new file mode 100755
index 000000000..9e37b4ff4
--- /dev/null
+++ b/test/4bridges_ip.exp
@@ -0,0 +1,175 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check eth0
8send -- "firejail --net=br0 --net=br1 --ip=10.10.30.50 --net=br2 --ip=10.10.40.100 --net=br3\r"
9expect {
10 timeout {puts "TESTING ERROR 0.0\n";exit}
11 "eth0"
12}
13expect {
14 timeout {puts "TESTING ERROR 0.1\n";exit}
15 "10.10.20"
16}
17expect {
18 timeout {puts "TESTING ERROR 0.2\n";exit}
19 "255.255.255.248"
20}
21expect {
22 timeout {puts "TESTING ERROR 0.3\n";exit}
23 "UP"
24}
25expect {
26 timeout {puts "TESTING ERROR 0.4\n";exit}
27 "Child process initialized"
28}
29sleep 2
30send -- "exit\r"
31sleep 2
32
33# check eth1
34send -- "firejail --net=br0 --net=br1 --ip=10.10.30.50 --net=br2 --ip=10.10.40.100 --net=br3\r"
35expect {
36 timeout {puts "TESTING ERROR 1.0\n";exit}
37 "eth1"
38}
39expect {
40 timeout {puts "TESTING ERROR 1.1\n";exit}
41 "10.10.30.50"
42}
43expect {
44 timeout {puts "TESTING ERROR 1.2\n";exit}
45 "255.255.255.0"
46}
47expect {
48 timeout {puts "TESTING ERROR 1.3\n";exit}
49 "UP"
50}
51expect {
52 timeout {puts "TESTING ERROR 1.4\n";exit}
53 "Child process initialized"
54}
55sleep 2
56send -- "exit\r"
57sleep 2
58
59
60# check eth2
61send -- "firejail --net=br0 --net=br1 --ip=10.10.30.50 --net=br2 --ip=10.10.40.100 --net=br3\r"
62expect {
63 timeout {puts "TESTING ERROR 2.0\n";exit}
64 "eth2"
65}
66expect {
67 timeout {puts "TESTING ERROR 2.1\n";exit}
68 "10.10.40.100"
69}
70expect {
71 timeout {puts "TESTING ERROR 2.2\n";exit}
72 "255.255.255.0"
73}
74expect {
75 timeout {puts "TESTING ERROR 2.3\n";exit}
76 "UP"
77}
78expect {
79 timeout {puts "TESTING ERROR 2.4\n";exit}
80 "Child process initialized"
81}
82sleep 2
83send -- "exit\r"
84sleep 2
85
86
87
88# check eth3
89send -- "firejail --net=br0 --net=br1 --ip=10.10.30.50 --net=br2 --ip=10.10.40.100 --net=br3\r"
90expect {
91 timeout {puts "TESTING ERROR 3.0\n";exit}
92 "eth3"
93}
94expect {
95 timeout {puts "TESTING ERROR 3.1\n";exit}
96 "10.10.50"
97}
98expect {
99 timeout {puts "TESTING ERROR 3.2\n";exit}
100 "255.255.255.0"
101}
102expect {
103 timeout {puts "TESTING ERROR 3.3\n";exit}
104 "UP"
105}
106expect {
107 timeout {puts "TESTING ERROR 4\n";exit}
108 "Child process initialized"
109}
110sleep 2
111send -- "exit\r"
112sleep 2
113
114
115
116
117# check loopback
118send -- "firejail --net=br0 --net=br1 --ip=10.10.30.50 --net=br2 --ip=10.10.40.100 --net=br3\r"
119expect {
120 timeout {puts "TESTING ERROR 5\n";exit}
121 "lo"
122}
123expect {
124 timeout {puts "TESTING ERROR 6\n";exit}
125 "127.0.0.1"
126}
127expect {
128 timeout {puts "TESTING ERROR 7\n";exit}
129 "255.0.0.0"
130}
131expect {
132 timeout {puts "TESTING ERROR 8\n";exit}
133 "UP"
134}
135expect {
136 timeout {puts "TESTING ERROR 9\n";exit}
137 "Child process initialized"
138}
139
140# check default gateway
141send -- "bash\r"
142sleep 1
143send -- "netstat -rn;pwd\r"
144expect {
145 timeout {puts "TESTING ERROR 10.1\n";exit}
146 "0.0.0.0"
147}
148expect {
149 timeout {puts "TESTING ERROR 10.2\n";exit}
150 "10.10.20.1"
151}
152expect {
153 timeout {puts "TESTING ERROR 10.3\n";exit}
154 "eth0"
155}
156expect {
157 timeout {puts "TESTING ERROR 10.4\n";exit}
158 "10.10.20.0"
159}
160expect {
161 timeout {puts "TESTING ERROR 10.5\n";exit}
162 "0.0.0.0"
163}
164expect {
165 timeout {puts "TESTING ERROR 10.6\n";exit}
166 "eth0"
167}
168expect {
169 timeout {puts "TESTING ERROR 10\n";exit}
170 "home"
171}
172sleep 1
173
174puts "\n"
175
diff --git a/test/auto/autotest.sh b/test/auto/autotest.sh
new file mode 100755
index 000000000..0fb7565af
--- /dev/null
+++ b/test/auto/autotest.sh
@@ -0,0 +1,202 @@
1#!/bin/bash
2
3arr[1]="TEST 1: svn and standard compilation"
4arr[2]="TEST 2: cppcheck"
5arr[3]="TEST 3: compile seccomp disabled, chroot disabled, bind disabled"
6arr[4]="TEST 4: rvtest"
7arr[5]="TEST 5: expect test as root, no malloc perturb"
8arr[6]="TEST 6: expect test as user, no malloc perturb"
9arr[7]="TEST 7: expect test as root, malloc perturb"
10arr[8]="TEST 8: expect test as user, malloc perturb"
11
12
13# remove previous reports and output file
14cleanup() {
15 rm -f out-test
16 rm -f output*
17 rm -f report*
18 rm -fr firejail-trunk
19}
20
21print_title() {
22 echo
23 echo
24 echo
25 echo "**************************************************"
26 echo $1
27 echo "**************************************************"
28}
29
30while [ $# -gt 0 ]; do # Until you run out of parameters . . .
31 case "$1" in
32 --clean)
33 cleanup
34 exit
35 ;;
36 --help)
37 echo "./autotest.sh [--clean|--help]"
38 exit
39 ;;
40 esac
41 shift # Check next set of parameters.
42done
43
44cleanup
45# enable sudo
46sudo ls -al
47
48#*****************************************************************
49# TEST 1
50#*****************************************************************
51# - checkout source code
52# - check compilation
53# - install
54#*****************************************************************
55print_title "${arr[1]}"
56svn checkout svn://svn.code.sf.net/p/firejail/code-0/trunk firejail-trunk
57cd firejail-trunk
58./configure --prefix=/usr 2>&1 | tee ../output-configure
59make -j4 2>&1 | tee ../output-make
60sudo make install 2>&1 | tee ../output-install
61cd src/tools
62gcc -o rvtest rvtest.c
63cd ../..
64cd test
65sudo ./configure > /dev/null
66cd ../..
67grep warning output-configure output-make output-install > ./report-test1
68grep error output-configure output-make output-install >> ./report-test1
69cat report-test1 > out-test1
70
71#*****************************************************************
72# TEST 2
73#*****************************************************************
74# - run cppcheck
75#*****************************************************************
76print_title "${arr[2]}"
77cd firejail-trunk
78cp /home/netblue/bin/cfg/std.cfg .
79cppcheck --force . 2>&1 | tee ../output-cppcheck
80cd ..
81grep error output-cppcheck > report-test2
82cat report-test2 > out-test2
83
84#*****************************************************************
85# TEST 3
86#*****************************************************************
87# - disable seccomp configuration
88# - check compilation
89#*****************************************************************
90print_title "${arr[3]}"
91# seccomp
92cd firejail-trunk
93make distclean
94./configure --prefix=/usr --disable-seccomp 2>&1 | tee ../output-configure-noseccomp
95make -j4 2>&1 | tee ../output-make-noseccomp
96cd ..
97grep warning output-configure-noseccomp output-make-noseccomp > ./report-test3
98grep error output-configure-noseccomp output-make-noseccomp >> ./report-test3
99# chroot
100cd firejail-trunk
101make distclean
102./configure --prefix=/usr --disable-chroot 2>&1 | tee ../output-configure-nochroot
103make -j4 2>&1 | tee ../output-make-nochroot
104cd ..
105grep warning output-configure-nochroot output-make-nochroot >> ./report-test3
106grep error output-configure-nochroot output-make-nochroot >> ./report-test3
107# bind
108cd firejail-trunk
109make distclean
110./configure --prefix=/usr --disable-bind 2>&1 | tee ../output-configure-nobind
111make -j4 2>&1 | tee ../output-make-nobind
112cd ..
113grep warning output-configure-nobind output-make-nobind >> ./report-test3
114grep error output-configure-nobind output-make-nobind >> ./report-test3
115# save result
116cat report-test3 > out-test3
117
118#*****************************************************************
119# TEST 4
120#*****************************************************************
121# - rvtest
122#*****************************************************************
123print_title "${arr[4]}"
124cd firejail-trunk
125cd test
126../src/tools/rvtest test.rv 2>/dev/null | tee ../../output-test4 | grep TESTING
127cd ../..
128grep TESTING output-test4 > ./report-test4
129grep ERROR report-test4 > out-test4
130
131
132#*****************************************************************
133# TEST 5
134#*****************************************************************
135# - expect test as root, no malloc perturb
136#*****************************************************************
137print_title "${arr[5]}"
138cd firejail-trunk/test
139sudo ./test-root.sh 2>&1 | tee ../../output-test5 | grep TESTING
140cd ../..
141grep TESTING output-test5 > ./report-test5
142grep ERROR report-test5 > out-test5
143
144#*****************************************************************
145# TEST 6
146#*****************************************************************
147# - expect test as user, no malloc perturb
148#*****************************************************************
149print_title "${arr[6]}"
150cd firejail-trunk/test
151./test.sh 2>&1 | tee ../../output-test6 | grep TESTING
152cd ../..
153grep TESTING output-test6 > ./report-test6
154grep ERROR report-test6 > out-test6
155
156
157
158#*****************************************************************
159# TEST 7
160#*****************************************************************
161# - expect test as root, malloc perturb
162#*****************************************************************
163print_title "${arr[7]}"
164export MALLOC_CHECK_=3
165export MALLOC_PERTURB_=$(($RANDOM % 255 + 1))
166cd firejail-trunk/test
167sudo ./test-root.sh 2>&1 | tee ../../output-test7 | grep TESTING
168cd ../..
169grep TESTING output-test7 > ./report-test7
170grep ERROR report-test7 > out-test7
171
172#*****************************************************************
173# TEST 8
174#*****************************************************************
175# - expect test as user, malloc perturb
176#*****************************************************************
177print_title "${arr[8]}"
178cd firejail-trunk/test
179./test.sh 2>&1 | tee ../../output-test8| grep TESTING
180cd ../..
181grep TESTING output-test8 > ./report-test8
182grep ERROR report-test8 > out-test8
183
184#*****************************************************************
185# PRINT REPORTS
186#*****************************************************************
187echo
188echo
189echo
190echo
191echo "**********************************************************"
192echo "TEST RESULTS"
193echo "**********************************************************"
194
195wc -l out-test*
196rm out-test*
197echo
198
199
200
201
202exit
diff --git a/test/caps1.profile b/test/caps1.profile
new file mode 100644
index 000000000..e14655b2e
--- /dev/null
+++ b/test/caps1.profile
@@ -0,0 +1 @@
caps.drop chown,kill \ No newline at end of file
diff --git a/test/caps2.profile b/test/caps2.profile
new file mode 100644
index 000000000..cb2258c52
--- /dev/null
+++ b/test/caps2.profile
@@ -0,0 +1 @@
caps.keep chown,kill \ No newline at end of file
diff --git a/test/chk_config.exp b/test/chk_config.exp
new file mode 100755
index 000000000..ada59d655
--- /dev/null
+++ b/test/chk_config.exp
@@ -0,0 +1,86 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check br0
8send -- "/sbin/ifconfig;pwd\r"
9expect {
10 timeout {puts "TESTING ERROR 0 - please run ./configure\n";exit}
11 "br0"
12}
13expect {
14 timeout {puts "TESTING ERROR 0 - please run ./configure\n";exit}
15 "10.10.20.1"
16}
17expect {
18 timeout {puts "TESTING ERROR 0 - please run ./configure\n";exit}
19 "home"
20}
21
22# check br1
23send -- "/sbin/ifconfig;pwd\r"
24expect {
25 timeout {puts "TESTING ERROR 1\n";exit}
26 "br1"
27}
28expect {
29 timeout {puts "TESTING ERROR 1\n";exit}
30 "10.10.30.1"
31}
32expect {
33 timeout {puts "TESTING ERROR 1\n";exit}
34 "home"
35}
36
37# check br2
38send -- "/sbin/ifconfig;pwd\r"
39expect {
40 timeout {puts "TESTING ERROR 2\n";exit}
41 "br2"
42}
43expect {
44 timeout {puts "TESTING ERROR 2\n";exit}
45 "10.10.40.1"
46}
47expect {
48 timeout {puts "TESTING ERROR 2\n";exit}
49 "home"
50}
51
52# check br3
53send -- "/sbin/ifconfig;pwd\r"
54expect {
55 timeout {puts "TESTING ERROR 3\n";exit}
56 "br3"
57}
58expect {
59 timeout {puts "TESTING ERROR 3\n";exit}
60 "10.10.50.1"
61}
62expect {
63 timeout {puts "TESTING ERROR 3\n";exit}
64 "home"
65}
66
67# start a sandbox and check MALLOC_PERTURB
68send -- "firejail\r"
69expect {
70 timeout {puts "TESTING ERROR 4\n";exit}
71 "Child process initialized"
72}
73sleep 1
74
75set timeout 2
76send -- "env | grep MALLOC;pwd\r"
77expect {
78 timeout {puts "\nTESTING: MALLOC_PERTURB_ disabled\n"}
79 "MALLOC_PERTURB_" {puts "\nTESTING: MALLOC_PERTURB_ enabled\n"}
80}
81expect {
82 timeout {puts "TESTING ERROR 5\n";exit}
83 "home"
84}
85
86
diff --git a/test/chromium.exp b/test/chromium.exp
new file mode 100755
index 000000000..020826f3d
--- /dev/null
+++ b/test/chromium.exp
@@ -0,0 +1,72 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail chromium-browser www.gentoo.org\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Reading profile /etc/firejail/chromium-browser.profile"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "Child process initialized"
15}
16sleep 10
17
18spawn $env(SHELL)
19send -- "firejail --list\r"
20expect {
21 timeout {puts "TESTING ERROR 3\n";exit}
22 ":firejail"
23}
24expect {
25 timeout {puts "TESTING ERROR 3.1\n";exit}
26 "chromium-browser"
27}
28sleep 1
29
30send -- "firejail --name=blablabla\r"
31expect {
32 timeout {puts "TESTING ERROR 4\n";exit}
33 "Child process initialized"
34}
35sleep 2
36
37spawn $env(SHELL)
38send -- "firemon --seccomp\r"
39expect {
40 timeout {puts "TESTING ERROR 5\n";exit}
41 ":firejail chromium-browser"
42}
43expect {
44 timeout {puts "TESTING ERROR 5.1\n";exit}
45 "Seccomp: 0"
46}
47expect {
48 timeout {puts "TESTING ERROR 5.1\n";exit}
49 "name=blablabla"
50}
51sleep 1
52send -- "firemon --caps\r"
53expect {
54 timeout {puts "TESTING ERROR 6\n";exit}
55 ":firejail chromium-browser"
56}
57expect {
58 timeout {puts "TESTING ERROR 6.1\n";exit}
59 "CapBnd:"
60}
61expect {
62 timeout {puts "TESTING ERROR 6.2\n";exit}
63 "fffffffff"
64}
65expect {
66 timeout {puts "TESTING ERROR 6.3\n";exit}
67 "name=blablabla"
68}
69sleep 1
70
71puts "\n"
72
diff --git a/test/configure b/test/configure
new file mode 100755
index 000000000..17bb22e1b
--- /dev/null
+++ b/test/configure
@@ -0,0 +1,42 @@
1#!/bin/bash
2
3brctl addbr br0
4ifconfig br0 10.10.20.1/29 up
5# NAT masquerade
6iptables -t nat -A POSTROUTING -o eth0 -s 10.10.20.0/29 -j MASQUERADE
7# port forwarding
8# iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 10.10.20.2:80
9
10brctl addbr br1
11ifconfig br1 10.10.30.1/24 up
12brctl addbr br2
13ifconfig br2 10.10.40.1/24 up
14brctl addbr br3
15ifconfig br3 10.10.50.1/24 up
16brctl addbr br4
17ifconfig br4 10.10.60.1/24 up
18
19
20# build a very small chroot
21ROOTDIR="/tmp/chroot" # default chroot directory
22DEFAULT_FILES="/bin/bash /bin/sh " # basic chroot files
23DEFAULT_FILES+="/etc/passwd /etc/nsswitch.conf /etc/group "
24DEFAULT_FILES+=`find /lib -name libnss*` # files required by glibc
25DEFAULT_FILES+=" /bin/ls /bin/cat /bin/ps /usr/bin/id /usr/bin/whoami /usr/bin/wc /usr/bin/wget"
26
27rm -fr $ROOTDIR
28mkdir -p $ROOTDIR/{root,bin,lib,lib64,usr,home,etc,dev/shm,tmp,var/run,var/tmp,var/lock,proc}
29SORTED=`for FILE in $* $DEFAULT_FILES; do echo " $FILE "; ldd $FILE | grep -v dynamic | cut -d " " -f 3; done | sort -u`
30for FILE in $SORTED
31do
32 cp --parents $FILE $ROOTDIR
33done
34cp --parents /lib64/ld-linux-x86-64.so.2 $ROOTDIR
35cp --parents /lib/ld-linux.so.2 $ROOTDIR
36
37cd $ROOTDIR; find .
38mkdir -p usr/lib/firejail/
39cp /usr/lib/firejail/libtrace.so usr/lib/firejail/.
40
41
42echo "To enter the chroot directory run: firejail --chroot=$ROOTDIR"
diff --git a/test/dns.exp b/test/dns.exp
new file mode 100755
index 000000000..96513f278
--- /dev/null
+++ b/test/dns.exp
@@ -0,0 +1,69 @@
1#!/usr/bin/expect -f
2
3set timeout 30
4spawn $env(SHELL)
5match_max 100000
6
7# no chroot
8send -- "firejail --trace --dns=208.67.222.222 wget -q debian.org\r"
9expect {
10 timeout {puts "TESTING ERROR 1.1\n";exit}
11 "Child process initialized"
12}
13expect {
14 timeout {puts "TESTING ERROR 1.2\n";exit}
15 "1:wget:connect 208.67.222.222:53"
16}
17sleep 1
18
19send -- "rm index.html\r"
20sleep 1
21
22# with chroot
23send -- "firejail --chroot=/tmp/chroot --trace --dns=208.67.222.222 wget -q debian.org\r"
24expect {
25 timeout {puts "TESTING ERROR 2.1\n";exit}
26 "Child process initialized"
27}
28expect {
29 timeout {puts "TESTING ERROR 2.2\n";exit}
30 "1:wget:connect 208.67.222.222:53"
31}
32sleep 1
33
34send -- "rm index.html\r"
35sleep 1
36
37# net eth0
38send -- "firejail --net=eth0 --trace --dns=208.67.222.222 wget -q debian.org\r"
39expect {
40 timeout {puts "TESTING ERROR 3.1\n";exit}
41 "Child process initialized"
42}
43expect {
44 timeout {puts "TESTING ERROR 3.2\n";exit}
45 "1:wget:connect 208.67.222.222:53"
46}
47sleep 1
48
49send -- "rm index.html\r"
50sleep 1
51
52# net eth0 and chroot
53send -- "firejail --net=eth0 --chroot=/tmp/chroot --trace --dns=208.67.222.222 wget -q debian.org\r"
54expect {
55 timeout {puts "TESTING ERROR 4.1\n";exit}
56 "Child process initialized"
57}
58expect {
59 timeout {puts "TESTING ERROR 4.2\n";exit}
60 "1:wget:connect 208.67.222.222:53"
61}
62sleep 1
63
64send -- "rm index.html\r"
65sleep 1
66
67
68puts "\n"
69
diff --git a/test/doubledash.exp b/test/doubledash.exp
new file mode 100755
index 000000000..3c8a42471
--- /dev/null
+++ b/test/doubledash.exp
@@ -0,0 +1,60 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail -- ls -- -testdir\r"
8expect {
9 timeout {puts "TESTING ERROR 1\n";exit}
10 "Child process initialized"
11}
12expect {
13 timeout {puts "TESTING ERROR 2\n";exit}
14 "ttt"
15}
16expect {
17 timeout {puts "TESTING ERROR 3\n";exit}
18 "parent is shutting down"
19}
20sleep 1
21
22
23send -- "firejail --name=testing -- -testdir/bash\r"
24expect {
25 timeout {puts "TESTING ERROR 4\n";exit}
26 "Child process initialized"
27}
28sleep 3
29
30spawn $env(SHELL)
31send -- "firejail --join=testing -- -testdir/bash\r"
32expect {
33 timeout {puts "TESTING ERROR 5\n";exit}
34 "the first child process inside the sandbox"
35}
36sleep 3
37
38spawn $env(SHELL)
39send -- "firejail --list;pwd\r"
40expect {
41 timeout {puts "TESTING ERROR 6\n";exit}
42 "name=testing"
43}
44expect {
45 timeout {puts "TESTING ERROR 7\n";exit}
46 "home"
47}
48send -- "firejail --list;pwd\r"
49expect {
50 timeout {puts "TESTING ERROR 8 (join)\n";exit}
51 "join=testing"
52}
53expect {
54 timeout {puts "TESTING ERROR 9\n";exit}
55 "home"
56}
57
58sleep 1
59
60puts "\n"
diff --git a/test/evince.exp b/test/evince.exp
new file mode 100755
index 000000000..7b115144c
--- /dev/null
+++ b/test/evince.exp
@@ -0,0 +1,72 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail evince\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Reading profile /etc/firejail/evince.profile"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "Child process initialized"
15}
16sleep 10
17
18spawn $env(SHELL)
19send -- "firejail --list\r"
20expect {
21 timeout {puts "TESTING ERROR 3\n";exit}
22 ":firejail"
23}
24expect {
25 timeout {puts "TESTING ERROR 3.1\n";exit}
26 "evince"
27}
28sleep 1
29
30send -- "firejail --name=blablabla\r"
31expect {
32 timeout {puts "TESTING ERROR 4\n";exit}
33 "Child process initialized"
34}
35sleep 2
36
37spawn $env(SHELL)
38send -- "firemon --seccomp\r"
39expect {
40 timeout {puts "TESTING ERROR 5\n";exit}
41 ":firejail evince"
42}
43expect {
44 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
45 "Seccomp: 2"
46}
47expect {
48 timeout {puts "TESTING ERROR 5.1\n";exit}
49 "name=blablabla"
50}
51sleep 1
52send -- "firemon --caps\r"
53expect {
54 timeout {puts "TESTING ERROR 6\n";exit}
55 ":firejail evince"
56}
57expect {
58 timeout {puts "TESTING ERROR 6.1\n";exit}
59 "CapBnd:"
60}
61expect {
62 timeout {puts "TESTING ERROR 6.2\n";exit}
63 "0000000000000000"
64}
65expect {
66 timeout {puts "TESTING ERROR 6.3\n";exit}
67 "name=blablabla"
68}
69sleep 1
70
71puts "\n"
72
diff --git a/test/extract_command.exp b/test/extract_command.exp
new file mode 100755
index 000000000..c49614b84
--- /dev/null
+++ b/test/extract_command.exp
@@ -0,0 +1,23 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --debug /usr/bin/firefox www.gentoo.org\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Reading profile /etc/firejail/firefox.profile"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "Starting /usr/bin/firefox"
15}
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "Child process initialized"
19}
20sleep 5
21
22puts "\n"
23
diff --git a/test/firefox.exp b/test/firefox.exp
new file mode 100755
index 000000000..c2e64e04f
--- /dev/null
+++ b/test/firefox.exp
@@ -0,0 +1,74 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail firefox www.gentoo.org\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Reading profile /etc/firejail/firefox.profile"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "Child process initialized"
15}
16sleep 10
17
18spawn $env(SHELL)
19send -- "firejail --list\r"
20expect {
21 timeout {puts "TESTING ERROR 3\n";exit}
22 ":firejail"
23}
24expect {
25 timeout {puts "TESTING ERROR 3.1\n";exit}
26 "firefox" {puts "firefox detected\n";}
27 "iceweasel" {puts "iceweasel detected\n";}
28}
29sleep 1
30send -- "firejail --name=blablabla\r"
31expect {
32 timeout {puts "TESTING ERROR 4\n";exit}
33 "Child process initialized"
34}
35sleep 2
36
37spawn $env(SHELL)
38send -- "firemon --seccomp\r"
39expect {
40 timeout {puts "TESTING ERROR 5\n";exit}
41 " firefox" {puts "firefox detected\n";}
42 " iceweasel" {puts "iceweasel detected\n";}
43}
44expect {
45 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
46 "Seccomp: 2"
47}
48expect {
49 timeout {puts "TESTING ERROR 5.1\n";exit}
50 "name=blablabla"
51}
52sleep 1
53send -- "firemon --caps\r"
54expect {
55 timeout {puts "TESTING ERROR 6\n";exit}
56 " firefox" {puts "firefox detected\n";}
57 " iceweasel" {puts "iceweasel detected\n";}
58}
59expect {
60 timeout {puts "TESTING ERROR 6.1\n";exit}
61 "CapBnd:"
62}
63expect {
64 timeout {puts "TESTING ERROR 6.2\n";exit}
65 "0000000000000000"
66}
67expect {
68 timeout {puts "TESTING ERROR 6.3\n";exit}
69 "name=blablabla"
70}
71sleep 1
72
73puts "\n"
74
diff --git a/test/firejail-in-firejail.exp b/test/firejail-in-firejail.exp
new file mode 100755
index 000000000..404eb03bb
--- /dev/null
+++ b/test/firejail-in-firejail.exp
@@ -0,0 +1,37 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 1\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "firejail\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Child process initialized"
18}
19sleep 1
20
21send -- "firejail\r"
22expect {
23 timeout {puts "TESTING ERROR 1\n";exit}
24 "Child process initialized"
25}
26sleep 1
27puts "\n"
28
29send -- "exit\r"
30sleep 1
31send -- "exit\r"
32sleep 1
33send -- "exit\r"
34sleep 1
35
36
37puts "\n"
diff --git a/test/firemon-arp.exp b/test/firemon-arp.exp
new file mode 100755
index 000000000..3fc8c2aee
--- /dev/null
+++ b/test/firemon-arp.exp
@@ -0,0 +1,34 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "ping -c 3 192.168.1.1\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "3 packets transmitted"
11}
12sleep 1
13
14send -- "firejail\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Child process initialized"
18}
19sleep 1
20
21spawn $env(SHELL)
22send -- "firemon --arp\r"
23expect {
24 timeout {puts "TESTING ERROR 2\n";exit}
25 "192.168.1.1 dev eth0 lladdr" {puts "Debian testing\n";}
26 "192.168.1.1 dev enp0s3 lladdr" {puts "Centos 7 testing\n";}
27}
28expect {
29 timeout {puts "TESTING ERROR 3\n";exit}
30 "REACHABLE"
31}
32sleep 1
33
34puts "\n"
diff --git a/test/firemon-caps.exp b/test/firemon-caps.exp
new file mode 100755
index 000000000..547d04c02
--- /dev/null
+++ b/test/firemon-caps.exp
@@ -0,0 +1,135 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=bingo1 --caps\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14spawn $env(SHELL)
15send -- "firejail --name=bingo2\r"
16expect {
17 timeout {puts "TESTING ERROR 0\n";exit}
18 "Child process initialized"
19}
20sleep 1
21
22spawn $env(SHELL)
23send -- "firejail --name=bingo3 --caps.drop=all\r"
24expect {
25 timeout {puts "TESTING ERROR 0\n";exit}
26 "Child process initialized"
27}
28sleep 1
29
30spawn $env(SHELL)
31send -- "firejail --name=bingo4 --caps.drop=chown,kill\r"
32expect {
33 timeout {puts "TESTING ERROR 0\n";exit}
34 "Child process initialized"
35}
36sleep 1
37
38spawn $env(SHELL)
39send -- "firejail --name=bingo5 --caps.keep=chown,kill\r"
40expect {
41 timeout {puts "TESTING ERROR 0\n";exit}
42 "Child process initialized"
43}
44sleep 1
45
46spawn $env(SHELL)
47send -- "firejail --name=bingo6 --profile=caps1.profile\r"
48expect {
49 timeout {puts "TESTING ERROR 0\n";exit}
50 "Child process initialized"
51}
52sleep 1
53
54spawn $env(SHELL)
55send -- "firejail --name=bingo7 --profile=caps2.profile\r"
56expect {
57 timeout {puts "TESTING ERROR 0\n";exit}
58 "Child process initialized"
59}
60sleep 1
61
62
63
64
65spawn $env(SHELL)
66send -- "firemon --caps\r"
67expect {
68 timeout {puts "TESTING ERROR 1\n";exit}
69 "bingo1"
70}
71expect {
72 timeout {puts "TESTING ERROR 2\n";exit}
73 "31cffff"
74}
75expect {
76 timeout {puts "TESTING ERROR 3\n";exit}
77 "bingo2"
78}
79expect {
80 timeout {puts "TESTING ERROR 4\n";exit}
81 "fffffff"
82}
83expect {
84 timeout {puts "TESTING ERROR 5\n";exit}
85 "bingo3"
86}
87expect {
88 timeout {puts "TESTING ERROR 6\n";exit}
89 "000000000000"
90}
91
92expect {
93 timeout {puts "TESTING ERROR 7\n";exit}
94 "bingo4"
95}
96expect {
97 timeout {puts "TESTING ERROR 8\n";exit}
98 "ffffffde"
99}
100expect {
101 timeout {puts "TESTING ERROR 7\n";exit}
102 "bingo5"
103}
104expect {
105 timeout {puts "TESTING ERROR 9\n";exit}
106 "0000000000000021"
107}
108
109expect {
110 timeout {puts "TESTING ERROR 10\n";exit}
111 "bingo6"
112}
113expect {
114 timeout {puts "TESTING ERROR 11\n";exit}
115 "ffffffde"
116}
117expect {
118 timeout {puts "TESTING ERROR 12\n";exit}
119 "bingo7"
120}
121expect {
122 timeout {puts "TESTING ERROR 13\n";exit}
123 "0000000000000021"
124}
125
126
127
128
129
130
131
132sleep 1
133
134puts "\n"
135
diff --git a/test/firemon-cgroup.exp b/test/firemon-cgroup.exp
new file mode 100755
index 000000000..41a38b3b6
--- /dev/null
+++ b/test/firemon-cgroup.exp
@@ -0,0 +1,40 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=bingo1 --cgroup=/sys/fs/cgroup/g1/tasks\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14spawn $env(SHELL)
15send -- "firejail --name=bingo2\r"
16expect {
17 timeout {puts "TESTING ERROR 0\n";exit}
18 "Child process initialized"
19}
20sleep 1
21
22
23spawn $env(SHELL)
24send -- "firemon --cgroup\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "bingo1"
28}
29expect {
30 timeout {puts "TESTING ERROR 2\n";exit}
31 ":/g1"
32}
33expect {
34 timeout {puts "TESTING ERROR 3\n";exit}
35 "bingo2"
36}
37sleep 1
38
39puts "\n"
40
diff --git a/test/firemon-interface.exp b/test/firemon-interface.exp
new file mode 100755
index 000000000..6a82ae41e
--- /dev/null
+++ b/test/firemon-interface.exp
@@ -0,0 +1,34 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14spawn $env(SHELL)
15send -- "firemon --interface\r"
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "lo UP"
19}
20expect {
21 timeout {puts "TESTING ERROR 2\n";exit}
22 "10.10.20.1/29"
23}
24expect {
25 timeout {puts "TESTING ERROR 3\n";exit}
26 "10.10.50.1/24"
27}
28expect {
29 timeout {puts "TESTING ERROR 3\n";exit}
30 "br3"
31}
32sleep 1
33
34puts "\n"
diff --git a/test/firemon-route.exp b/test/firemon-route.exp
new file mode 100755
index 000000000..76ebd70f6
--- /dev/null
+++ b/test/firemon-route.exp
@@ -0,0 +1,32 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14spawn $env(SHELL)
15send -- "firemon --route\r"
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "0.0.0.0/0 via 192.168.1.1, dev eth0, metric 0" {puts "Debian testing\n";}
19 "0.0.0.0/0 via 192.168.1.1, dev enp0s3, metric 1024" {puts "Centos 7 testing\n";}
20 "0.0.0.0/0 via 192.168.1.1, dev enp0s3, metric 0" {puts "OpenSUSE testing\n";}
21}
22expect {
23 timeout {puts "TESTING ERROR 2\n";exit}
24 "10.10.30.0/24, dev br1, scope link src 10.10.30.1"
25}
26expect {
27 timeout {puts "TESTING ERROR 3\n";exit}
28 "10.10.50.0/24, dev br3, scope link src 10.10.50.1"
29}
30sleep 1
31
32puts "\n"
diff --git a/test/firemon-seccomp.exp b/test/firemon-seccomp.exp
new file mode 100755
index 000000000..0cf53b690
--- /dev/null
+++ b/test/firemon-seccomp.exp
@@ -0,0 +1,45 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=bingo1 --seccomp\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14spawn $env(SHELL)
15send -- "firejail --name=bingo2\r"
16expect {
17 timeout {puts "TESTING ERROR 0\n";exit}
18 "Child process initialized"
19}
20sleep 1
21
22
23
24
25spawn $env(SHELL)
26send -- "firemon --seccomp\r"
27expect {
28 timeout {puts "TESTING ERROR 1\n";exit}
29 "bingo1"
30}
31expect {
32 timeout {puts "TESTING ERROR 2\n";exit}
33 "Seccomp: 2"
34}
35expect {
36 timeout {puts "TESTING ERROR 3\n";exit}
37 "bingo2"
38}
39expect {
40 timeout {puts "TESTING ERROR 3\n";exit}
41 "Seccomp: 0"
42}
43sleep 1
44
45puts "\n"
diff --git a/test/fs_chroot.exp b/test/fs_chroot.exp
new file mode 100755
index 000000000..ba832337b
--- /dev/null
+++ b/test/fs_chroot.exp
@@ -0,0 +1,54 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --chroot=/tmp/chroot\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "cd /home;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 3\n";exit}
17 "home"
18}
19sleep 1
20send -- "bash\r"
21sleep 1
22send -- "ps aux; pwd\r"
23expect {
24 timeout {puts "TESTING ERROR 1\n";exit}
25 "/bin/bash"
26}
27expect {
28 timeout {puts "TESTING ERROR 2\n";exit}
29 "bash"
30}
31expect {
32 timeout {puts "TESTING ERROR 3\n";exit}
33 "ps aux"
34}
35expect {
36 timeout {puts "TESTING ERROR 4\n";exit}
37 "home"
38}
39sleep 1
40
41
42send -- "ps aux |wc -l; pwd\r"
43expect {
44 timeout {puts "TESTING ERROR 5\n";exit}
45 "5"
46}
47expect {
48 timeout {puts "TESTING ERROR 6\n";exit}
49 "home"
50}
51sleep 1
52
53puts "\n"
54
diff --git a/test/fs_dev_shm.exp b/test/fs_dev_shm.exp
new file mode 100755
index 000000000..b54f24eb5
--- /dev/null
+++ b/test/fs_dev_shm.exp
@@ -0,0 +1,87 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# testing read-write /dev/shm
8send -- "firejail\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Child process initialized"
12}
13sleep 1
14
15send -- "echo mytest > /dev/shm/ttt;pwd\r"
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "home"
19}
20
21send -- "cat /dev/shm/ttt;pwd\r"
22expect {
23 timeout {puts "TESTING ERROR 2.1\n";exit}
24 "mytest"
25}
26expect {
27 timeout {puts "TESTING ERROR 2\n";exit}
28 "home"
29}
30
31send -- "rm /dev/shm/ttt;pwd\r"
32expect {
33 timeout {puts "TESTING ERROR 3\n";exit}
34 "home"
35}
36
37send -- "cat /dev/shm/ttt;pwd\r"
38expect {
39 timeout {puts "TESTING ERROR 4\n";exit}
40 "mytest" {puts "TESTING ERROR 4.1\n";exit}
41 "home"
42}
43
44sleep 1
45send -- "exit\r"
46sleep 1
47
48# redo the test with --private
49send -- "firejail\r"
50expect {
51 timeout {puts "TESTING ERROR 10\n";exit}
52 "Child process initialized"
53}
54sleep 1
55
56send -- "echo mytest > /dev/shm/ttt;pwd\r"
57expect {
58 timeout {puts "TESTING ERROR 11\n";exit}
59 "home"
60}
61
62send -- "cat /dev/shm/ttt;pwd\r"
63expect {
64 timeout {puts "TESTING ERROR 12.1\n";exit}
65 "mytest"
66}
67expect {
68 timeout {puts "TESTING ERROR 12\n";exit}
69 "home"
70}
71
72send -- "rm /dev/shm/ttt;pwd\r"
73expect {
74 timeout {puts "TESTING ERROR 13\n";exit}
75 "home"
76}
77
78send -- "cat /dev/shm/ttt;pwd\r"
79expect {
80 timeout {puts "TESTING ERROR 14\n";exit}
81 "mytest" {puts "TESTING ERROR 14.1\n";exit}
82 "home"
83}
84
85sleep 1
86
87puts "\n"
diff --git a/test/fs_home_sanitize.exp b/test/fs_home_sanitize.exp
new file mode 100755
index 000000000..300babd1c
--- /dev/null
+++ b/test/fs_home_sanitize.exp
@@ -0,0 +1,33 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "ls /home;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "bingo"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "home"
22}
23sleep 1
24
25send -- "ls /home/bingo;pwd\r"
26expect {
27 timeout {puts "TESTING ERROR 3\n";exit}
28 "cannot open directory"
29}
30sleep 1
31
32puts "\n"
33
diff --git a/test/fs_overlay.exp b/test/fs_overlay.exp
new file mode 100755
index 000000000..166970a5c
--- /dev/null
+++ b/test/fs_overlay.exp
@@ -0,0 +1,64 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "rm -f /tmp/firejail-overlay-test;pwd\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "home"
11}
12
13send -- "ls > /tmp/firejail-overlay-test;pwd\r"
14expect {
15 timeout {puts "TESTING ERROR 1\n";exit}
16 "home"
17}
18
19send -- "firejail --overlay\r"
20expect {
21 timeout {puts "TESTING ERROR 2\n";exit}
22 "Child process initialized"
23}
24sleep 1
25
26send -- "echo xyzxyzxyz > /tmp/firejail-overlay-test;pwd\r"
27expect {
28 timeout {puts "TESTING ERROR 3\n";exit}
29 "home"
30}
31sleep 1
32
33send -- "cat /tmp/firejail-overlay-test;pwd\r"
34expect {
35 timeout {puts "TESTING ERROR 4\n";exit}
36 "xyzxyzxyz"
37}
38expect {
39 timeout {puts "TESTING ERROR 4.1\n";exit}
40 "home"
41}
42sleep 1
43
44send -- "exit\r"
45sleep 2
46
47send -- "cat /tmp/firejail-overlay-test;pwd\r"
48expect {
49 timeout {puts "TESTING ERROR 5\n";exit}
50 "xyzxyzxyz" {puts "TESTING ERROR 5.1\n";exit}
51 "home"
52}
53
54sleep 1
55send -- "rm -f /tmp/firejail-overlay-test;pwd\r"
56expect {
57 timeout {puts "TESTING ERROR 0\n";exit}
58 "home"
59}
60
61
62sleep 1
63puts "\n"
64
diff --git a/test/fs_sys.exp b/test/fs_sys.exp
new file mode 100755
index 000000000..69f080460
--- /dev/null
+++ b/test/fs_sys.exp
@@ -0,0 +1,34 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --net=br0\r"
8expect {
9 timeout {puts "TESTING ERROR 1\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "find /sys | grep --color=never eth0;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 2\n";exit}
17 "/sys/class/net/eth0"
18}
19expect {
20 timeout {puts "TESTING ERROR 3\n";exit}
21 "home"
22}
23sleep 1
24
25send -- "find /sys | grep --color=never br0;pwd\r"
26expect {
27 timeout {puts "TESTING ERROR 4\n";exit}
28 "/sys/class/net/br0" {puts "TESTING ERROR 5\n";exit}
29 "home"
30}
31sleep 1
32
33puts "\n"
34
diff --git a/test/fs_var_lock.exp b/test/fs_var_lock.exp
new file mode 100755
index 000000000..dfcf571f4
--- /dev/null
+++ b/test/fs_var_lock.exp
@@ -0,0 +1,87 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# testing read-write /var/lock
8send -- "firejail\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Child process initialized"
12}
13sleep 1
14
15send -- "echo mytest > /var/lock/ttt;pwd\r"
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "home"
19}
20
21send -- "cat /var/lock/ttt;pwd\r"
22expect {
23 timeout {puts "TESTING ERROR 2.1\n";exit}
24 "mytest"
25}
26expect {
27 timeout {puts "TESTING ERROR 2\n";exit}
28 "home"
29}
30
31send -- "rm /var/lock/ttt;pwd\r"
32expect {
33 timeout {puts "TESTING ERROR 3\n";exit}
34 "home"
35}
36
37send -- "cat /var/lock/ttt;pwd\r"
38expect {
39 timeout {puts "TESTING ERROR 4\n";exit}
40 "mytest" {puts "TESTING ERROR 4.1\n";exit}
41 "home"
42}
43
44sleep 1
45send -- "exit\r"
46sleep 1
47
48# redo the test with --private
49send -- "firejail\r"
50expect {
51 timeout {puts "TESTING ERROR 10\n";exit}
52 "Child process initialized"
53}
54sleep 1
55
56send -- "echo mytest > /var/lock/ttt;pwd\r"
57expect {
58 timeout {puts "TESTING ERROR 11\n";exit}
59 "home"
60}
61
62send -- "cat /var/lock/ttt;pwd\r"
63expect {
64 timeout {puts "TESTING ERROR 12.1\n";exit}
65 "mytest"
66}
67expect {
68 timeout {puts "TESTING ERROR 12\n";exit}
69 "home"
70}
71
72send -- "rm /var/lock/ttt;pwd\r"
73expect {
74 timeout {puts "TESTING ERROR 13\n";exit}
75 "home"
76}
77
78send -- "cat /var/lock/ttt;pwd\r"
79expect {
80 timeout {puts "TESTING ERROR 14\n";exit}
81 "mytest" {puts "TESTING ERROR 14.1\n";exit}
82 "home"
83}
84
85sleep 1
86
87puts "\n"
diff --git a/test/fs_var_tmp.exp b/test/fs_var_tmp.exp
new file mode 100755
index 000000000..95ceeb2a4
--- /dev/null
+++ b/test/fs_var_tmp.exp
@@ -0,0 +1,87 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# testing read-write /var/tmp
8send -- "firejail\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Child process initialized"
12}
13sleep 1
14
15send -- "echo mytest > /var/tmp/ttt;pwd\r"
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "home"
19}
20
21send -- "cat /var/tmp/ttt;pwd\r"
22expect {
23 timeout {puts "TESTING ERROR 2.1\n";exit}
24 "mytest"
25}
26expect {
27 timeout {puts "TESTING ERROR 2\n";exit}
28 "home"
29}
30
31send -- "rm /var/tmp/ttt;pwd\r"
32expect {
33 timeout {puts "TESTING ERROR 3\n";exit}
34 "home"
35}
36
37send -- "cat /var/tmp/ttt;pwd\r"
38expect {
39 timeout {puts "TESTING ERROR 4\n";exit}
40 "mytest" {puts "TESTING ERROR 4.1\n";exit}
41 "home"
42}
43
44sleep 1
45send -- "exit\r"
46sleep 1
47
48# redo the test with --private
49send -- "firejail\r"
50expect {
51 timeout {puts "TESTING ERROR 10\n";exit}
52 "Child process initialized"
53}
54sleep 1
55
56send -- "echo mytest > /var/tmp/ttt;pwd\r"
57expect {
58 timeout {puts "TESTING ERROR 11\n";exit}
59 "home"
60}
61
62send -- "cat /var/tmp/ttt;pwd\r"
63expect {
64 timeout {puts "TESTING ERROR 12.1\n";exit}
65 "mytest"
66}
67expect {
68 timeout {puts "TESTING ERROR 12\n";exit}
69 "home"
70}
71
72send -- "rm /var/tmp/ttt;pwd\r"
73expect {
74 timeout {puts "TESTING ERROR 13\n";exit}
75 "home"
76}
77
78send -- "cat /var/tmp/ttt;pwd\r"
79expect {
80 timeout {puts "TESTING ERROR 14\n";exit}
81 "mytest" {puts "TESTING ERROR 14.1\n";exit}
82 "home"
83}
84
85sleep 1
86
87puts "\n"
diff --git a/test/fscheck-bindnoroot.exp b/test/fscheck-bindnoroot.exp
new file mode 100755
index 000000000..796a7d975
--- /dev/null
+++ b/test/fscheck-bindnoroot.exp
@@ -0,0 +1,14 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8send -- "firejail --net=br0 --bind=fscheck-dir,/etc\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Error"
12}
13after 100
14
diff --git a/test/fscheck-blacklist.exp b/test/fscheck-blacklist.exp
new file mode 100755
index 000000000..5b6a9623c
--- /dev/null
+++ b/test/fscheck-blacklist.exp
@@ -0,0 +1,14 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8send -- "firejail --net=br0 --blacklist=../test/fscheck-dir\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Error"
12}
13after 100
14
diff --git a/test/fscheck-chroot.exp b/test/fscheck-chroot.exp
new file mode 100755
index 000000000..208ca6a43
--- /dev/null
+++ b/test/fscheck-chroot.exp
@@ -0,0 +1,77 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8#send -- "firejail --net=br0 --chroot=fscheck-dir\r"
9#expect {
10# timeout {puts "TESTING ERROR 0\n";exit}
11# "Error"
12#}
13#after 100
14
15# ..
16send -- "firejail --net=br0 --chroot=../test/fscheck-dir\r"
17expect {
18 timeout {puts "TESTING ERROR 0.1\n";exit}
19 "Error"
20}
21after 100
22
23# dir link
24send -- "firejail --net=br0 --chroot=fscheck-dir-link\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "Error"
28}
29after 100
30
31# ..
32send -- "firejail --net=br0 --chroot=../test/fscheck-dir-link\r"
33expect {
34 timeout {puts "TESTING ERROR 1.1\n";exit}
35 "Error"
36}
37after 100
38
39# file link
40send -- "firejail --net=br0 --chroot=fscheck-file-link\r"
41expect {
42 timeout {puts "TESTING ERROR 2\n";exit}
43 "Error"
44}
45after 100
46
47# file
48send -- "firejail --net=br0 --chroot=fscheck-file\r"
49expect {
50 timeout {puts "TESTING ERROR 2.1\n";exit}
51 "Error"
52}
53after 100
54
55# ..
56send -- "firejail --net=br0 --chroot=../test/fscheck-file\r"
57expect {
58 timeout {puts "TESTING ERROR 2.2\n";exit}
59 "Error"
60}
61after 100
62
63# no file
64send -- "firejail --net=br0 --chroot=../test/nodir\r"
65expect {
66 timeout {puts "TESTING ERROR 3\n";exit}
67 "Error"
68}
69after 100
70
71# same owner
72#send -- "firejail --net=br0 --chroot=/etc\r"
73#expect {
74# timeout {puts "TESTING ERROR 4\n";exit}
75# "Error"
76#}
77#after 100
diff --git a/test/fscheck-netfilter.exp b/test/fscheck-netfilter.exp
new file mode 100755
index 000000000..d2339c8b9
--- /dev/null
+++ b/test/fscheck-netfilter.exp
@@ -0,0 +1,69 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8send -- "firejail --net=br0 --netfilter=fscheck-dir\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Error"
12}
13after 100
14
15# ..
16send -- "firejail --net=br0 --netfilter=../test/fscheck-dir\r"
17expect {
18 timeout {puts "TESTING ERROR 0.1\n";exit}
19 "Error"
20}
21after 100
22
23# dir link
24send -- "firejail --net=br0 --netfilter=fscheck-dir-link\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "Error"
28}
29after 100
30
31# ..
32send -- "firejail --net=br0 --netfilter=../test/fscheck-dir-link\r"
33expect {
34 timeout {puts "TESTING ERROR 1.1\n";exit}
35 "Error"
36}
37after 100
38
39# file link
40send -- "firejail --net=br0 --netfilter=fscheck-file-link\r"
41expect {
42 timeout {puts "TESTING ERROR 2\n";exit}
43 "Error"
44}
45after 100
46
47# ..
48send -- "firejail --net=br0 --netfilter=../test/fscheck-file-link\r"
49expect {
50 timeout {puts "TESTING ERROR 2\n";exit}
51 "Error"
52}
53after 100
54
55# no file
56send -- "firejail --net=br0 --netfilter=../test/nofile\r"
57expect {
58 timeout {puts "TESTING ERROR 3\n";exit}
59 "Error"
60}
61after 100
62
63# real GID/UID
64send -- "firejail --net=br0 --netfilter=/etc/shadow\r"
65expect {
66 timeout {puts "TESTING ERROR 4\n";exit}
67 "Error"
68}
69after 100
diff --git a/test/fscheck-output.exp b/test/fscheck-output.exp
new file mode 100755
index 000000000..0b444d6ba
--- /dev/null
+++ b/test/fscheck-output.exp
@@ -0,0 +1,104 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8send -- "firejail --net=br0 --output=fscheck-dir\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Error"
12}
13after 100
14
15# ..
16send -- "firejail --net=br0 --output=../test/fscheck-dir\r"
17expect {
18 timeout {puts "TESTING ERROR 0.1\n";exit}
19 "Error"
20}
21after 100
22
23# dir link
24send -- "firejail --net=br0 --output=fscheck-dir-link\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "Error"
28}
29after 100
30
31# ..
32send -- "firejail --net=br0 --output=../test/fscheck-dir-link\r"
33expect {
34 timeout {puts "TESTING ERROR 1.1\n";exit}
35 "Error"
36}
37after 100
38
39# file link
40send -- "firejail --net=br0 --output=fscheck-file-link\r"
41expect {
42 timeout {puts "TESTING ERROR 2\n";exit}
43 "Error"
44}
45after 100
46
47# ..
48send -- "firejail --net=br0 --output=../test/fscheck-file-link\r"
49expect {
50 timeout {puts "TESTING ERROR 2.1\n";exit}
51 "Error"
52}
53after 100
54
55# hard link1
56send -- "firejail --net=br0 --output=fscheck-file-hard1\r"
57expect {
58 timeout {puts "TESTING ERROR 2.2\n";exit}
59 "Error"
60}
61after 100
62
63# hard link2
64send -- "firejail --net=br0 --output=fscheck-file-hard2\r"
65expect {
66 timeout {puts "TESTING ERROR 2.3\n";exit}
67 "Error"
68}
69after 100
70
71# ..
72send -- "firejail --net=br0 --output=../test/fscheck-file-hard1\r"
73expect {
74 timeout {puts "TESTING ERROR 2.4\n";exit}
75 "Error"
76}
77after 100
78
79# ..
80send -- "firejail --net=br0 --output=../test/fscheck-file-hard2\r"
81expect {
82 timeout {puts "TESTING ERROR 2.5\n";exit}
83 "Error"
84}
85after 100
86
87
88
89
90# no file
91send -- "firejail --net=br0 --output=../test/nofile\r"
92expect {
93 timeout {puts "TESTING ERROR 3\n";exit}
94 "Error"
95}
96after 100
97
98# real GID/UID
99send -- "firejail --net=br0 --output=/etc/shadow\r"
100expect {
101 timeout {puts "TESTING ERROR 4\n";exit}
102 "Error"
103}
104after 100
diff --git a/test/fscheck-private.exp b/test/fscheck-private.exp
new file mode 100755
index 000000000..4c791423d
--- /dev/null
+++ b/test/fscheck-private.exp
@@ -0,0 +1,77 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8#send -- "firejail --net=br0 --private=fscheck-dir\r"
9#expect {
10# timeout {puts "TESTING ERROR 0\n";exit}
11# "Error"
12#}
13#after 100
14
15# ..
16send -- "firejail --net=br0 --private=../test/fscheck-dir\r"
17expect {
18 timeout {puts "TESTING ERROR 0.1\n";exit}
19 "Error"
20}
21after 100
22
23# dir link
24send -- "firejail --net=br0 --private=fscheck-dir-link\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "Error"
28}
29after 100
30
31# ..
32send -- "firejail --net=br0 --private=../test/fscheck-dir-link\r"
33expect {
34 timeout {puts "TESTING ERROR 1.1\n";exit}
35 "Error"
36}
37after 100
38
39# file link
40send -- "firejail --net=br0 --private=fscheck-file-link\r"
41expect {
42 timeout {puts "TESTING ERROR 2\n";exit}
43 "Error"
44}
45after 100
46
47# file
48send -- "firejail --net=br0 --private=fscheck-file\r"
49expect {
50 timeout {puts "TESTING ERROR 2.1\n";exit}
51 "Error"
52}
53after 100
54
55# ..
56send -- "firejail --net=br0 --private=../test/fscheck-file\r"
57expect {
58 timeout {puts "TESTING ERROR 2.2\n";exit}
59 "Error"
60}
61after 100
62
63# no file
64send -- "firejail --net=br0 --private=../test/nodir\r"
65expect {
66 timeout {puts "TESTING ERROR 3\n";exit}
67 "Error"
68}
69after 100
70
71# same owner
72send -- "firejail --net=br0 --private=/etc\r"
73expect {
74 timeout {puts "TESTING ERROR 4\n";exit}
75 "Error"
76}
77after 100
diff --git a/test/fscheck-privatekeep.exp b/test/fscheck-privatekeep.exp
new file mode 100755
index 000000000..513dcc37a
--- /dev/null
+++ b/test/fscheck-privatekeep.exp
@@ -0,0 +1,93 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8#send -- "firejail --net=br0 --private.keep=fscheck-dir\r"
9#expect {
10# timeout {puts "TESTING ERROR 0\n";exit}
11# "Error"
12#}
13#after 100
14
15# ..
16send -- "firejail --net=br0 --private.keep=../test/fscheck-dir\r"
17expect {
18 timeout {puts "TESTING ERROR 0.1\n";exit}
19 "Error"
20}
21after 100
22
23# dir link
24send -- "firejail --net=br0 --private.keep=fscheck-dir-link\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "Error"
28}
29after 100
30
31# ..
32send -- "firejail --net=br0 --private.keep=../test/fscheck-dir-link\r"
33expect {
34 timeout {puts "TESTING ERROR 1.1\n";exit}
35 "Error"
36}
37after 100
38
39# file link
40send -- "firejail --net=br0 --private.keep=fscheck-file-link\r"
41expect {
42 timeout {puts "TESTING ERROR 2\n";exit}
43 "Error"
44}
45after 100
46
47# file
48#send -- "firejail --net=br0 --private.keep=fscheck-file\r"
49#expect {
50# timeout {puts "TESTING ERROR 2.1\n";exit}
51# "Error"
52#}
53#after 100
54
55# ..
56send -- "firejail --net=br0 --private.keep=../test/fscheck-file\r"
57expect {
58 timeout {puts "TESTING ERROR 2.2\n";exit}
59 "Error"
60}
61after 100
62
63# no dir
64send -- "firejail --net=br0 --private.keep=../test/nodir\r"
65expect {
66 timeout {puts "TESTING ERROR 3\n";exit}
67 "Error"
68}
69after 100
70
71# no file
72send -- "firejail --net=br0 --private.keep=../test/nofile\r"
73expect {
74 timeout {puts "TESTING ERROR 3.1\n";exit}
75 "Error"
76}
77after 100
78
79# same owner
80send -- "firejail --net=br0 --private=/etc\r"
81expect {
82 timeout {puts "TESTING ERROR 4\n";exit}
83 "Error"
84}
85after 100
86
87# same owner
88send -- "firejail --net=br0 --private=/etc/shadow\r"
89expect {
90 timeout {puts "TESTING ERROR 4\n";exit}
91 "Error"
92}
93after 100
diff --git a/test/fscheck-profile.exp b/test/fscheck-profile.exp
new file mode 100755
index 000000000..d7d7c7cd1
--- /dev/null
+++ b/test/fscheck-profile.exp
@@ -0,0 +1,69 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8send -- "firejail --net=br0 --profile=fscheck-dir\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Error"
12}
13after 100
14
15# ..
16send -- "firejail --net=br0 --profile=../test/fscheck-dir\r"
17expect {
18 timeout {puts "TESTING ERROR 0.1\n";exit}
19 "Error"
20}
21after 100
22
23# dir link
24send -- "firejail --net=br0 --profile=fscheck-dir-link\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "Error"
28}
29after 100
30
31# ..
32send -- "firejail --net=br0 --profile=../test/fscheck-dir-link\r"
33expect {
34 timeout {puts "TESTING ERROR 1.1\n";exit}
35 "Error"
36}
37after 100
38
39# file link
40send -- "firejail --net=br0 --profile=fscheck-file-link\r"
41expect {
42 timeout {puts "TESTING ERROR 2\n";exit}
43 "Error"
44}
45after 100
46
47# ..
48send -- "firejail --net=br0 --profile=../test/fscheck-file-link\r"
49expect {
50 timeout {puts "TESTING ERROR 2\n";exit}
51 "Error"
52}
53after 100
54
55# no file
56send -- "firejail --net=br0 --profile=../test/nofile\r"
57expect {
58 timeout {puts "TESTING ERROR 3\n";exit}
59 "Error"
60}
61after 100
62
63# real GID/UID
64send -- "firejail --net=br0 --profile=/etc/shadow\r"
65expect {
66 timeout {puts "TESTING ERROR 4\n";exit}
67 "Error"
68}
69after 100
diff --git a/test/fscheck-readonly.exp b/test/fscheck-readonly.exp
new file mode 100755
index 000000000..e0f0a8a1d
--- /dev/null
+++ b/test/fscheck-readonly.exp
@@ -0,0 +1,14 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8send -- "firejail --net=br0 --read-only=../test/fscheck-dir\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Error"
12}
13after 100
14
diff --git a/test/fscheck-shell.exp b/test/fscheck-shell.exp
new file mode 100755
index 000000000..d2320a4c3
--- /dev/null
+++ b/test/fscheck-shell.exp
@@ -0,0 +1,69 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# dir
8send -- "firejail --net=br0 --shell=fscheck-dir\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Error"
12}
13after 100
14
15# ..
16send -- "firejail --net=br0 --shell=../test/fscheck-dir\r"
17expect {
18 timeout {puts "TESTING ERROR 0.1\n";exit}
19 "Error"
20}
21after 100
22
23# dir link
24send -- "firejail --net=br0 --shell=fscheck-dir-link\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "Error"
28}
29after 100
30
31# ..
32send -- "firejail --net=br0 --shell=../test/fscheck-dir-link\r"
33expect {
34 timeout {puts "TESTING ERROR 1.1\n";exit}
35 "Error"
36}
37after 100
38
39# file link
40send -- "firejail --net=br0 --shell=fscheck-file-link\r"
41expect {
42 timeout {puts "TESTING ERROR 2\n";exit}
43 "Error"
44}
45after 100
46
47# ..
48send -- "firejail --net=br0 --shell=../test/fscheck-file-link\r"
49expect {
50 timeout {puts "TESTING ERROR 2\n";exit}
51 "Error"
52}
53after 100
54
55# no file
56send -- "firejail --net=br0 --shell=../test/nofile\r"
57expect {
58 timeout {puts "TESTING ERROR 3\n";exit}
59 "Error"
60}
61after 100
62
63# real GID/UID
64send -- "firejail --net=br0 --shell=/etc/shadow\r"
65expect {
66 timeout {puts "TESTING ERROR 4\n";exit}
67 "Error"
68}
69after 100
diff --git a/test/fscheck-tmpfs.exp b/test/fscheck-tmpfs.exp
new file mode 100755
index 000000000..d5bbccd96
--- /dev/null
+++ b/test/fscheck-tmpfs.exp
@@ -0,0 +1,14 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# ..
8send -- "firejail --net=br0 --tmpfs=../test/fscheck-dir\r"
9expect {
10 timeout {puts "TESTING ERROR 0.1\n";exit}
11 "Error"
12}
13after 100
14
diff --git a/test/fscheck.sh b/test/fscheck.sh
new file mode 100755
index 000000000..25756d5be
--- /dev/null
+++ b/test/fscheck.sh
@@ -0,0 +1,39 @@
1#!/bin/bash
2
3mkdir fscheck-dir
4ln -s fscheck-dir fscheck-dir-link
5touch fscheck-file
6ln -s fscheck-file fscheck-file-link
7touch fscheck-file-hard1
8ln fscheck-file-hard1 fscheck-file-hard2
9
10echo "TESTING: fscheck netfilter"
11./fscheck-netfilter.exp
12echo "TESTING: fscheck shell"
13./fscheck-shell.exp
14echo "TESTING: fscheck private"
15./fscheck-private.exp
16echo "TESTING: fscheck private keep"
17./fscheck-privatekeep.exp
18echo "TESTING: fscheck profile"
19./fscheck-profile.exp
20echo "TESTING: fscheck chroot"
21./fscheck-chroot.exp
22echo "TESTING: fscheck output"
23./fscheck-output.exp
24echo "TESTING: fscheck bind nonroot"
25./fscheck-bindnoroot.exp
26echo "TESTING: fscheck tmpfs"
27./fscheck-tmpfs.exp
28echo "TESTING: fscheck readonly"
29./fscheck-readonly.exp
30echo "TESTING: fscheck blacklist"
31./fscheck-blacklist.exp
32
33
34rm -fr fscheck-dir
35rm -fr fscheck-dir-link
36rm -fr fscheck-file-link
37rm -fr fscheck-file
38rm -fr fscheck-file-hard1
39rm -fr fscheck-file-hard2
diff --git a/test/login_ssh.exp b/test/login_ssh.exp
new file mode 100755
index 000000000..dff6dc655
--- /dev/null
+++ b/test/login_ssh.exp
@@ -0,0 +1,59 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "ssh bingo@0\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "password:" {
11 puts "\nTESTING: please enter SSH password"
12 set oldmode [stty -echo -raw]
13 expect_user -re "(.*)\n"
14 send_user "\n"
15 eval stty $oldmode
16# stty echo
17 set pass $expect_out(1,string)
18 send -- "$pass\r"
19 puts "TESTING: password sent to the server"
20 }
21 "Child process initialized"
22}
23sleep 1
24
25# test default gw
26send -- "bash\r"
27sleep 1
28send -- "ps aux; pwd\r"
29expect {
30 timeout {puts "TESTING ERROR 1\n";exit}
31 "/bin/bash"
32}
33expect {
34 timeout {puts "TESTING ERROR 2\n";exit}
35 "bash"
36}
37expect {
38 timeout {puts "TESTING ERROR 3\n";exit}
39 "ps aux"
40}
41expect {
42 timeout {puts "TESTING ERROR 4\n";exit}
43 "home"
44}
45sleep 1
46
47
48send -- "ps aux |wc -l; pwd\r"
49expect {
50 timeout {puts "TESTING ERROR 5\n";exit}
51 "5"
52}
53expect {
54 timeout {puts "TESTING ERROR 6\n";exit}
55 "home"
56}
57sleep 1
58
59puts "\n"
diff --git a/test/midori.exp b/test/midori.exp
new file mode 100755
index 000000000..ec33816dd
--- /dev/null
+++ b/test/midori.exp
@@ -0,0 +1,73 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail midori www.gentoo.org\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Reading profile /etc/firejail/midori.profile"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "Child process initialized"
15}
16sleep 10
17
18spawn $env(SHELL)
19send -- "firejail --list\r"
20expect {
21 timeout {puts "TESTING ERROR 3\n";exit}
22 ":firejail"
23}
24expect {
25 timeout {puts "TESTING ERROR 3.1\n";exit}
26 "midori"
27}
28sleep 1
29
30send -- "firejail --name=blablabla\r"
31expect {
32 timeout {puts "TESTING ERROR 4\n";exit}
33 "Child process initialized"
34}
35sleep 2
36
37spawn $env(SHELL)
38send -- "firemon --seccomp\r"
39expect {
40 timeout {puts "TESTING ERROR 5\n";exit}
41 ":firejail midori"
42}
43expect {
44 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
45 "Seccomp: 2"
46}
47expect {
48 timeout {puts "TESTING ERROR 5.1\n";exit}
49 "name=blablabla"
50}
51sleep 1
52send -- "firemon --caps\r"
53expect {
54 timeout {puts "TESTING ERROR 6\n";exit}
55 ":firejail midori"
56}
57expect {
58 timeout {puts "TESTING ERROR 6.1\n";exit}
59 "CapBnd"
60}
61expect {
62 timeout {puts "TESTING ERROR 6.2\n";exit}
63 "0000000000000000"
64}
65expect {
66 timeout {puts "TESTING ERROR 6.3n";exit}
67 "name=blablabla"
68}
69sleep 1
70
71
72puts "\n"
73
diff --git a/test/name.exp b/test/name.exp
new file mode 100755
index 000000000..704b8315e
--- /dev/null
+++ b/test/name.exp
@@ -0,0 +1,25 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=baluba\r"
8expect {
9 timeout {puts "TESTING ERROR 1\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "ping -c 3 baluba;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 2\n";exit}
17 "3 packets transmitted, 3 received"
18}
19expect {
20 timeout {puts "TESTING ERROR 3\n";exit}
21 "home"
22}
23sleep 1
24
25puts "\n"
diff --git a/test/net_arp.exp b/test/net_arp.exp
new file mode 100755
index 000000000..9e07744f3
--- /dev/null
+++ b/test/net_arp.exp
@@ -0,0 +1,71 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --net=br0 sleep 20 &\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12send -- "firejail --net=br0 sleep 20 &\r"
13expect {
14 timeout {puts "TESTING ERROR 1\n";exit}
15 "Child process initialized"
16}
17send -- "firejail --net=br0 sleep 20 &\r"
18expect {
19 timeout {puts "TESTING ERROR 2\n";exit}
20 "Child process initialized"
21}
22send -- "firejail --net=br0 sleep 20 &\r"
23expect {
24 timeout {puts "TESTING ERROR 3\n";exit}
25 "Child process initialized"
26}
27send -- "firejail --net=br0 sleep 20 &\r"
28expect {
29 timeout {puts "TESTING ERROR 4\n";exit}
30 "Child process initialized"
31}
32
33# will fail
34send -- "firejail --net=br0 sleep 20 &\r"
35expect {
36 timeout {puts "TESTING ERROR 5n";exit}
37 "cannot assign an IP address"
38}
39
40send -- "firejail --net=br0 sleep 20 &\r"
41expect {
42 timeout {puts "TESTING ERROR 6\n";exit}
43 "cannot assign an IP address"
44}
45
46# check firejail --list
47send -- "firejail --list\r"
48expect {
49 timeout {puts "TESTING ERROR 7.1\n";exit}
50 "sleep 20"
51}
52expect {
53 timeout {puts "TESTING ERROR 7.2\n";exit}
54 "sleep 20"
55}
56expect {
57 timeout {puts "TESTING ERROR 7.3\n";exit}
58 "sleep 20"
59}
60expect {
61 timeout {puts "TESTING ERROR 7.4\n";exit}
62 "sleep 20"
63}
64expect {
65 timeout {puts "TESTING ERROR 7.5\n";exit}
66 "sleep 20"
67}
68
69# wait for snadboxes to be shutdown
70sleep 30
71puts "\n"
diff --git a/test/net_badip.exp b/test/net_badip.exp
new file mode 100755
index 000000000..71b69e104
--- /dev/null
+++ b/test/net_badip.exp
@@ -0,0 +1,16 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check eth0
8send -- "firejail --net=br0 --net=br1 --ip=10.100.10.47\r"
9expect {
10 timeout {puts "TESTING ERROR 0.0\n";exit}
11 "the IP address is not"
12}
13sleep 1
14
15puts "\n"
16
diff --git a/test/net_defaultgw.exp b/test/net_defaultgw.exp
new file mode 100755
index 000000000..9820660b7
--- /dev/null
+++ b/test/net_defaultgw.exp
@@ -0,0 +1,65 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check ip address
8send -- "firejail --net=br0 --ip=10.10.20.5 --defaultgw=10.10.20.2\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "eth0"
12}
13expect {
14 timeout {puts "TESTING ERROR 1\n";exit}
15 "10.10.20.5"
16}
17expect {
18 timeout {puts "TESTING ERROR 2\n";exit}
19 "255.255.255.248"
20}
21expect {
22 timeout {puts "TESTING ERROR 3\n";exit}
23 "UP"
24}
25expect {
26 timeout {puts "TESTING ERROR 4\n";exit}
27 "Child process initialized"
28}
29
30# check default gateway
31send -- "bash\r"
32sleep 1
33send -- "netstat -rn;pwd\r"
34expect {
35 timeout {puts "TESTING ERROR 10.1\n";exit}
36 "0.0.0.0"
37}
38expect {
39 timeout {puts "TESTING ERROR 10.2\n";exit}
40 "10.10.20.2"
41}
42expect {
43 timeout {puts "TESTING ERROR 10.3\n";exit}
44 "eth0"
45}
46expect {
47 timeout {puts "TESTING ERROR 10.4\n";exit}
48 "10.10.20.0"
49}
50expect {
51 timeout {puts "TESTING ERROR 10.5\n";exit}
52 "0.0.0.0"
53}
54expect {
55 timeout {puts "TESTING ERROR 10.6\n";exit}
56 "eth0"
57}
58expect {
59 timeout {puts "TESTING ERROR 10\n";exit}
60 "home"
61}
62sleep 1
63
64puts "\n"
65
diff --git a/test/net_defaultgw2.exp b/test/net_defaultgw2.exp
new file mode 100755
index 000000000..be9b4882a
--- /dev/null
+++ b/test/net_defaultgw2.exp
@@ -0,0 +1,65 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check ip address
8send -- "firejail --net=br0 --net=br1 --defaultgw=10.10.30.89\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "eth1"
12}
13expect {
14 timeout {puts "TESTING ERROR 4\n";exit}
15 "Child process initialized"
16}
17
18# check default gateway
19send -- "bash\r"
20sleep 1
21send -- "netstat -rn;pwd\r"
22expect {
23 timeout {puts "TESTING ERROR 10.1\n";exit}
24 "0.0.0.0"
25}
26expect {
27 timeout {puts "TESTING ERROR 10.2\n";exit}
28 "10.10.30.89"
29}
30expect {
31 timeout {puts "TESTING ERROR 10.3\n";exit}
32 "eth1"
33}
34expect {
35 timeout {puts "TESTING ERROR 10.4\n";exit}
36 "10.10.20.0"
37}
38expect {
39 timeout {puts "TESTING ERROR 10.5\n";exit}
40 "0.0.0.0"
41}
42expect {
43 timeout {puts "TESTING ERROR 10.6\n";exit}
44 "eth0"
45}
46expect {
47 timeout {puts "TESTING ERROR 10.4\n";exit}
48 "10.10.30.0"
49}
50expect {
51 timeout {puts "TESTING ERROR 10.5\n";exit}
52 "0.0.0.0"
53}
54expect {
55 timeout {puts "TESTING ERROR 10.6\n";exit}
56 "eth1"
57}
58expect {
59 timeout {puts "TESTING ERROR 10\n";exit}
60 "home"
61}
62sleep 1
63
64puts "\n"
65
diff --git a/test/net_defaultgw3.exp b/test/net_defaultgw3.exp
new file mode 100755
index 000000000..64da9dfca
--- /dev/null
+++ b/test/net_defaultgw3.exp
@@ -0,0 +1,17 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check ip address
8send -- "firejail --net=br0 --net=br1 --defaultgw=10.10.95.89\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "default gateway 10.10.95.89 is not in the range of any network"
12}
13
14sleep 1
15
16puts "\n"
17
diff --git a/test/net_ip.exp b/test/net_ip.exp
new file mode 100755
index 000000000..5995296c7
--- /dev/null
+++ b/test/net_ip.exp
@@ -0,0 +1,91 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check ip address
8send -- "firejail --net=br0 --ip=10.10.20.5\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "eth0"
12}
13expect {
14 timeout {puts "TESTING ERROR 1\n";exit}
15 "10.10.20.5"
16}
17expect {
18 timeout {puts "TESTING ERROR 2\n";exit}
19 "255.255.255.248"
20}
21expect {
22 timeout {puts "TESTING ERROR 3\n";exit}
23 "UP"
24}
25expect {
26 timeout {puts "TESTING ERROR 4\n";exit}
27 "Child process initialized"
28}
29sleep 2
30send -- "exit\r"
31sleep 2
32
33# check loopback
34send -- "firejail --net=br0 --ip=10.10.20.5\r"
35expect {
36 timeout {puts "TESTING ERROR 5\n";exit}
37 "lo"
38}
39expect {
40 timeout {puts "TESTING ERROR 6\n";exit}
41 "127.0.0.1"
42}
43expect {
44 timeout {puts "TESTING ERROR 7\n";exit}
45 "255.0.0.0"
46}
47expect {
48 timeout {puts "TESTING ERROR 8\n";exit}
49 "UP"
50}
51expect {
52 timeout {puts "TESTING ERROR 9\n";exit}
53 "Child process initialized"
54}
55
56# check default gateway
57send -- "bash\r"
58sleep 1
59send -- "netstat -rn;pwd\r"
60expect {
61 timeout {puts "TESTING ERROR 10.1\n";exit}
62 "0.0.0.0"
63}
64expect {
65 timeout {puts "TESTING ERROR 10.2\n";exit}
66 "10.10.20.1"
67}
68expect {
69 timeout {puts "TESTING ERROR 10.3\n";exit}
70 "eth0"
71}
72expect {
73 timeout {puts "TESTING ERROR 10.4\n";exit}
74 "10.10.20.0"
75}
76expect {
77 timeout {puts "TESTING ERROR 10.5\n";exit}
78 "0.0.0.0"
79}
80expect {
81 timeout {puts "TESTING ERROR 10.6\n";exit}
82 "eth0"
83}
84expect {
85 timeout {puts "TESTING ERROR 10\n";exit}
86 "home"
87}
88sleep 1
89
90puts "\n"
91
diff --git a/test/net_local.exp b/test/net_local.exp
new file mode 100755
index 000000000..9302ec4ef
--- /dev/null
+++ b/test/net_local.exp
@@ -0,0 +1,49 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check ip address
8send -- "firejail --debug\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Using the local network stack"
12}
13expect {
14 timeout {puts "TESTING ERROR 4\n";exit}
15 "Child process initialized"
16}
17sleep 2
18send -- "exit\r"
19sleep 2
20
21# check loopback
22send -- "firejail\r"
23expect {
24 timeout {puts "TESTING ERROR 9\n";exit}
25 "Child process initialized"
26}
27sleep 1
28
29
30send -- "/sbin/ifconfig\r"
31expect {
32 timeout {puts "TESTING ERROR 5\n";exit}
33 "lo"
34}
35expect {
36 timeout {puts "TESTING ERROR 6\n";exit}
37 "127.0.0.1"
38}
39expect {
40 timeout {puts "TESTING ERROR 7\n";exit}
41 "255.0.0.0"
42}
43expect {
44 timeout {puts "TESTING ERROR 8\n";exit}
45 "UP"
46}
47
48puts "\n"
49
diff --git a/test/net_mac.exp b/test/net_mac.exp
new file mode 100755
index 000000000..555d86b74
--- /dev/null
+++ b/test/net_mac.exp
@@ -0,0 +1,36 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check ip address
8send -- "firejail --net=br0 --ip=10.10.20.5 --mac=00:11:22:33:44:55\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "eth0"
12}
13expect {
14 timeout {puts "TESTING ERROR 0.1\n";exit}
15 "00:11:22:33:44:55"
16}
17expect {
18 timeout {puts "TESTING ERROR 1\n";exit}
19 "10.10.20.5"
20}
21expect {
22 timeout {puts "TESTING ERROR 2\n";exit}
23 "255.255.255.248"
24}
25expect {
26 timeout {puts "TESTING ERROR 3\n";exit}
27 "UP"
28}
29expect {
30 timeout {puts "TESTING ERROR 4\n";exit}
31 "Child process initialized"
32}
33sleep 1
34
35puts "\n"
36
diff --git a/test/net_macvlan.exp b/test/net_macvlan.exp
new file mode 100755
index 000000000..20d022de9
--- /dev/null
+++ b/test/net_macvlan.exp
@@ -0,0 +1,88 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check the existing address
8spawn $env(SHELL)
9send -- "firejail --net=eth0 --ip=192.168.1.60\r"
10expect {
11 timeout {puts "TESTING ERROR 1.1\n";puts "Please open a sandbox on 192.168.1.60\n";exit}
12 "the address 192.168.1.60 is already in use"
13}
14
15
16
17# grab 30 ip addresses
18set MAXi 229
19set i 200
20while { $i <= $MAXi } {
21 spawn $env(SHELL)
22 send -- "firejail --net=eth0 --ip=192.168.1.$i\r"
23 expect {
24 timeout {puts "TESTING ERROR 0\n";exit}
25 "Child process initialized"
26 }
27 incr i
28 after 100
29}
30
31
32# check an existing address
33spawn $env(SHELL)
34send -- "firejail --net=eth0 --ip=192.168.1.200\r"
35expect {
36 timeout {puts "TESTING ERROR 1\n";exit}
37 "the address 192.168.1.200 is already in use"
38}
39
40
41set MAXi 254
42set i 2
43while { $i <= $MAXi } {
44 spawn $env(SHELL)
45 send -- "firejail --net=eth0\r"
46 expect {
47 timeout {puts "TESTING ERROR 2.1\n";exit}
48 "192.168.1.60" {puts "TESTING ERROR 2.2\n";exit}
49 "192.168.1.200" {puts "TESTING ERROR 3\n";exit}
50 "192.168.1.201" {puts "TESTING ERROR 3\n";exit}
51 "192.168.1.202" {puts "TESTING ERROR 3\n";exit}
52 "192.168.1.203" {puts "TESTING ERROR 3\n";exit}
53 "192.168.1.204" {puts "TESTING ERROR 3\n";exit}
54 "192.168.1.205" {puts "TESTING ERROR 3\n";exit}
55 "192.168.1.206" {puts "TESTING ERROR 3\n";exit}
56 "192.168.1.207" {puts "TESTING ERROR 3\n";exit}
57 "192.168.1.208" {puts "TESTING ERROR 3\n";exit}
58 "192.168.1.209" {puts "TESTING ERROR 3\n";exit}
59 "192.168.1.210" {puts "TESTING ERROR 3\n";exit}
60 "192.168.1.211" {puts "TESTING ERROR 3\n";exit}
61 "192.168.1.212" {puts "TESTING ERROR 3\n";exit}
62 "192.168.1.213" {puts "TESTING ERROR 3\n";exit}
63 "192.168.1.214" {puts "TESTING ERROR 3\n";exit}
64 "192.168.1.215" {puts "TESTING ERROR 3\n";exit}
65 "192.168.1.216" {puts "TESTING ERROR 3\n";exit}
66 "192.168.1.217" {puts "TESTING ERROR 3\n";exit}
67 "192.168.1.218" {puts "TESTING ERROR 3\n";exit}
68 "192.168.1.219" {puts "TESTING ERROR 3\n";exit}
69 "192.168.1.220" {puts "TESTING ERROR 3\n";exit}
70 "192.168.1.221" {puts "TESTING ERROR 3\n";exit}
71 "192.168.1.222" {puts "TESTING ERROR 3\n";exit}
72 "192.168.1.223" {puts "TESTING ERROR 3\n";exit}
73 "192.168.1.224" {puts "TESTING ERROR 3\n";exit}
74 "192.168.1.225" {puts "TESTING ERROR 3\n";exit}
75 "192.168.1.226" {puts "TESTING ERROR 3\n";exit}
76 "192.168.1.227" {puts "TESTING ERROR 3\n";exit}
77 "192.168.1.228" {puts "TESTING ERROR 3\n";exit}
78 "192.168.1.229" {puts "TESTING ERROR 3\n";exit}
79 "Child process initialized"
80 }
81 puts "************ $i ******************\n"
82 incr i
83 after 100
84# sleep 1
85}
86
87puts "\n"
88
diff --git a/test/net_netfilter.exp b/test/net_netfilter.exp
new file mode 100755
index 000000000..8583d4625
--- /dev/null
+++ b/test/net_netfilter.exp
@@ -0,0 +1,88 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check default netfilter on br0
8send -- "firejail --debug --net=br0 --ip=10.10.20.5 --netfilter\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Installing network filter"
12}
13expect {
14 timeout {puts "TESTING ERROR 1\n";exit}
15 "Chain INPUT (policy DROP"
16}
17expect {
18 timeout {puts "TESTING ERROR 2\n";exit}
19 "ACCEPT all -- any any anywhere"
20}
21expect {
22 timeout {puts "TESTING ERROR 3\n";exit}
23 "ACCEPT icmp -- any any anywhere"
24}
25expect {
26 timeout {puts "TESTING ERROR 4\n";exit}
27 "Child process initialized"
28}
29sleep 2
30send -- "exit\r"
31sleep 1
32
33# check default netfilter no new network
34send -- "firejail --debug --netfilter\r"
35expect {
36 timeout {puts "TESTING ERROR 5\n";exit}
37 "Installing network filter" {puts "TESTING ERROR 5.1\n";exit}
38 "Chain INPUT (policy DROP" {puts "TESTING ERROR 5.1\n";exit}
39 "ACCEPT all -- any any anywhere" {puts "TESTING ERROR 5.1\n";exit}
40 "ACCEPT icmp -- any any anywhere" {puts "TESTING ERROR 5.1\n";exit}
41 "Child process initialized"
42}
43sleep 2
44send -- "exit\r"
45sleep 1
46
47# check file filter netfilter on br0
48send -- "firejail --debug --net=br0 --ip=10.10.20.5 --netfilter=netfilter.filter\r"
49expect {
50 timeout {puts "TESTING ERROR 6\n";exit}
51 "Installing network filter"
52}
53expect {
54 timeout {puts "TESTING ERROR 6.1\n";exit}
55 "Child process initialized"
56}
57sleep 2
58send -- "ping -c 1 -w 3 10.10.20.1\r"
59expect {
60 timeout {puts "TESTING ERROR 6.2\n";exit}
61 "0 received, 100% packet loss"
62}
63
64send -- "exit\r"
65sleep 1
66
67# check profile netfilter on br0
68send -- "firejail --debug --net=br0 --ip=10.10.20.5 --profile=netfilter.profile\r"
69expect {
70 timeout {puts "TESTING ERROR 7\n";exit}
71 "Installing network filter"
72}
73expect {
74 timeout {puts "TESTING ERROR 7.1\n";exit}
75 "Child process initialized"
76}
77sleep 2
78send -- "ping -c 1 -w 3 10.10.20.1\r"
79expect {
80 timeout {puts "TESTING ERROR 7.2\n";exit}
81 "0 received, 100% packet loss"
82}
83
84send -- "exit\r"
85sleep 1
86
87puts "\n"
88
diff --git a/test/net_noip.exp b/test/net_noip.exp
new file mode 100755
index 000000000..3db67885d
--- /dev/null
+++ b/test/net_noip.exp
@@ -0,0 +1,41 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check ip address
8send -- "firejail --net=br0 --ip=none\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "eth0" {puts "TESTING ERROR 1\n";exit}
12 "Child process initialized"
13}
14sleep 1
15send -- "bash\r"
16sleep 1
17
18# no default gateway configured
19send -- "netstat -rn;pwd\r"
20expect {
21 timeout {puts "TESTING ERROR 2\n";exit}
22 "0.0.0.0" {puts "TESTING ERROR 3\n";exit}
23 "eth0" {puts "TESTING ERROR 4\n";exit}
24 "home"
25}
26sleep 1
27
28# eth0 configured
29send -- "/sbin/ifconfig;pwd\r"
30expect {
31 timeout {puts "TESTING ERROR 5\n";exit}
32 "eth0"
33}
34expect {
35 timeout {puts "TESTING ERROR 6\n";exit}
36 "home"
37}
38sleep 1
39
40puts "\n"
41
diff --git a/test/net_noip2.exp b/test/net_noip2.exp
new file mode 100755
index 000000000..234aec8a8
--- /dev/null
+++ b/test/net_noip2.exp
@@ -0,0 +1,41 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# check ip address
8send -- "firejail --net=br1 --ip=none --defaultgw=10.10.30.78\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "eth0" {puts "TESTING ERROR 1\n";exit}
12 "Child process initialized"
13}
14sleep 1
15send -- "bash\r"
16sleep 1
17
18# no default gateway configured
19send -- "netstat -rn;pwd\r"
20expect {
21 timeout {puts "TESTING ERROR 2\n";exit}
22 "0.0.0.0" {puts "TESTING ERROR 3\n";exit}
23 "eth0" {puts "TESTING ERROR 4\n";exit}
24 "home"
25}
26sleep 1
27
28# eth0 configured
29send -- "/sbin/ifconfig;pwd\r"
30expect {
31 timeout {puts "TESTING ERROR 5\n";exit}
32 "eth0"
33}
34expect {
35 timeout {puts "TESTING ERROR 6\n";exit}
36 "home"
37}
38sleep 1
39
40puts "\n"
41
diff --git a/test/net_none.exp b/test/net_none.exp
new file mode 100755
index 000000000..dfa14a211
--- /dev/null
+++ b/test/net_none.exp
@@ -0,0 +1,36 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --net=none\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "eth0" {puts "TESTING ERROR 0.1\n";exit}
11 "Child process initialized"
12}
13sleep 1
14
15# test default gw
16send -- "bash\r"
17sleep 1
18send -- "netstat -rn; pwd\r"
19expect {
20 timeout {puts "TESTING ERROR 1\n";exit}
21 "0.0.0.0" {puts "TESTING ERROR 1.1\n";exit}
22 "home"
23}
24sleep 1
25
26# check again devices
27send -- "cat /proc/1/net/dev;pwd\r"
28expect {
29 timeout {puts "TESTING ERROR 2\n";exit}
30 "eth0" {puts "TESTING ERROR 2.1\n";exit}
31 "home"
32}
33sleep 1
34
35
36puts "\n"
diff --git a/test/netfilter.filter b/test/netfilter.filter
new file mode 100644
index 000000000..3e232065c
--- /dev/null
+++ b/test/netfilter.filter
@@ -0,0 +1,6 @@
1*filter
2:INPUT DROP [0:0]
3:FORWARD DROP [0:0]
4:OUTPUT ACCEPT [0:0]
5-A INPUT -i lo -j ACCEPT
6COMMIT
diff --git a/test/netfilter.profile b/test/netfilter.profile
new file mode 100644
index 000000000..824c6cd0f
--- /dev/null
+++ b/test/netfilter.profile
@@ -0,0 +1 @@
netfilter netfilter.filter
diff --git a/test/noroot.exp b/test/noroot.exp
new file mode 100755
index 000000000..78991d4a9
--- /dev/null
+++ b/test/noroot.exp
@@ -0,0 +1,124 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --debug --noroot --caps.drop=all --seccomp --cpu=0,1 --name=noroot-sandbox\r"
8expect {
9 timeout {puts "TESTING ERROR 0.1\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "cat /proc/self/status\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "CapBnd:"
18}
19expect {
20 timeout {puts "TESTING ERROR 1.1\n";exit}
21 "0000000000000000"
22}
23
24send -- "cat /proc/self/status\r"
25expect {
26 timeout {puts "TESTING ERROR 2\n";exit}
27 "Cpus_allowed:"
28}
29expect {
30 timeout {puts "TESTING ERROR 2.1\n";exit}
31 "3"
32}
33expect {
34 timeout {puts "TESTING ERROR 2.2\n";exit}
35 "Cpus_allowed_list:"
36}
37puts "\n"
38
39send -- "cat /proc/self/status\r"
40expect {
41 timeout {puts "TESTING ERROR 2\n";exit}
42 "Seccomp:"
43}
44expect {
45 timeout {puts "TESTING ERROR 2.1\n";exit}
46 "2"
47}
48expect {
49 timeout {puts "TESTING ERROR 2.2\n";exit}
50 "Cpus_allowed:"
51}
52puts "\n"
53
54send -- "cat /etc/hostname\r"
55expect {
56 timeout {puts "TESTING ERROR 3\n";exit}
57 "noroot-sandbox"
58}
59puts "\n"
60
61send -- "ping 0\r"
62expect {
63 timeout {puts "TESTING ERROR 4\n";exit}
64 "Operation not permitted"
65}
66puts "\n"
67
68send -- "whoami\r"
69expect {
70 timeout {puts "TESTING ERROR 55\\n";exit}
71 "netblue"
72}
73puts "\n"
74send -- "exit\r"
75sleep 2
76
77
78send -- "firejail --noroot\r"
79expect {
80 timeout {puts "TESTING ERROR 6\n";exit}
81 "Child process initialized"
82}
83sleep 1
84send -- "whoami\r"
85expect {
86 timeout {puts "TESTING ERROR 7\n";exit}
87 "netblue"
88}
89send -- "sudo -s\r"
90expect {
91 timeout {puts "TESTING ERROR 8\n";exit}
92 "effective uid is not 0, is sudo installed setuid root?" { puts "OK\n";}
93 "sudo must be owned by uid 0 and have the setuid bit set" { puts "OK\n";}
94}
95puts "\n"
96send -- "exit\r"
97sleep 2
98
99send -- "firejail --name=test --noroot\r"
100expect {
101 timeout {puts "TESTING ERROR 9\n";exit}
102 "Child process initialized"
103}
104sleep 1
105
106spawn $env(SHELL)
107send -- "firejail --debug --join=test\r"
108expect {
109 timeout {puts "TESTING ERROR 9\n";exit}
110 "User namespace detected"
111}
112expect {
113 timeout {puts "TESTING ERROR 9\n";exit}
114 "Joining user namespace"
115}
116sleep 1
117
118send -- "sudo -s\r"
119expect {
120 timeout {puts "TESTING ERROR 8\n";exit}
121 "effective uid is not 0, is sudo installed setuid root?" { puts "OK\n";}
122 "sudo must be owned by uid 0 and have the setuid bit set" { puts "OK\n";}
123}
124puts "\n"
diff --git a/test/opera.exp b/test/opera.exp
new file mode 100755
index 000000000..f536ae866
--- /dev/null
+++ b/test/opera.exp
@@ -0,0 +1,72 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail opera www.gentoo.org\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Reading profile /etc/firejail/opera.profile"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "Child process initialized"
15}
16sleep 10
17
18spawn $env(SHELL)
19send -- "firejail --list\r"
20expect {
21 timeout {puts "TESTING ERROR 3\n";exit}
22 ":firejail"
23}
24expect {
25 timeout {puts "TESTING ERROR 3.1\n";exit}
26 "opera"
27}
28sleep 1
29
30send -- "firejail --name=blablabla\r"
31expect {
32 timeout {puts "TESTING ERROR 4\n";exit}
33 "Child process initialized"
34}
35sleep 2
36
37spawn $env(SHELL)
38send -- "firemon --seccomp\r"
39expect {
40 timeout {puts "TESTING ERROR 5\n";exit}
41 ":firejail opera"
42}
43expect {
44 timeout {puts "TESTING ERROR 5.1\n";exit}
45 "Seccomp: 0"
46}
47expect {
48 timeout {puts "TESTING ERROR 5.1\n";exit}
49 "name=blablabla"
50}
51sleep 1
52send -- "firemon --caps\r"
53expect {
54 timeout {puts "TESTING ERROR 6\n";exit}
55 ":firejail opera"
56}
57expect {
58 timeout {puts "TESTING ERROR 6.1\n";exit}
59 "CapBnd:"
60}
61expect {
62 timeout {puts "TESTING ERROR 6.2\n";exit}
63 "fffffffff"
64}
65expect {
66 timeout {puts "TESTING ERROR 6.3\n";exit}
67 "name=blablabla"
68}
69sleep 1
70
71puts "\n"
72
diff --git a/test/option-join.exp b/test/option-join.exp
new file mode 100755
index 000000000..ad8ba73e0
--- /dev/null
+++ b/test/option-join.exp
@@ -0,0 +1,43 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=svntesting\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 3
13
14spawn $env(SHELL)
15send -- "firejail --join=svntesting;pwd\r"
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "Switching to pid"
19}
20expect {
21 timeout {puts "TESTING ERROR 2 (join) \n";exit}
22 "@svntesting"
23}
24sleep 1
25
26
27spawn $env(SHELL)
28send -- "firejail --shutdown=svntesting;pwd\r"
29expect {
30 timeout {puts "TESTING ERROR 3\n";exit}
31 "home"
32}
33sleep 1
34
35send -- "firejail --list;pwd\r"
36expect {
37 timeout {puts "TESTING ERROR 4\n";exit}
38 "svntesting" {puts "TESTING ERROR 5\n";exit}
39 "home"
40}
41sleep 1
42
43puts "\n"
diff --git a/test/option-shutdown.exp b/test/option-shutdown.exp
new file mode 100755
index 000000000..260a5b84f
--- /dev/null
+++ b/test/option-shutdown.exp
@@ -0,0 +1,30 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=svntesting\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 3
13
14spawn $env(SHELL)
15send -- "firejail --shutdown=svntesting;pwd\r"
16expect {
17 timeout {puts "TESTING ERROR 4\n";exit}
18 "home"
19}
20sleep 1
21
22send -- "firejail --list;pwd\r"
23expect {
24 timeout {puts "TESTING ERROR 5\n";exit}
25 "svntesting" {puts "TESTING ERROR 6\n";exit}
26 "home"
27}
28sleep 1
29
30puts "\n"
diff --git a/test/option-trace.exp b/test/option-trace.exp
new file mode 100755
index 000000000..b8f723fb8
--- /dev/null
+++ b/test/option-trace.exp
@@ -0,0 +1,31 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --trace firefox --name=testing\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "command not found" {puts "\nTESTING: not tested, firefox not found\n"; exit}
15 "1:firefox:open" {puts "\n"}
16 "1:iceweasel:open"
17}
18expect {
19 timeout {puts "TESTING ERROR 2\n";exit}
20 "1:firefox:access" {puts "\n"}
21 "1:iceweasel:access"
22}
23expect {
24 timeout {puts "TESTING ERROR 3\n";exit}
25 "1:firefox:connect" {puts "\n"}
26 "1:iceweasel:connect"
27}
28
29sleep 1
30
31puts "\n"
diff --git a/test/option_bind_directory.exp b/test/option_bind_directory.exp
new file mode 100755
index 000000000..1c1acc814
--- /dev/null
+++ b/test/option_bind_directory.exp
@@ -0,0 +1,26 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --bind=/tmp/chroot,mntpoint\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "ls mntpoint;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "root"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "home"
22}
23sleep 1
24
25puts "\n"
26
diff --git a/test/option_bind_file.exp b/test/option_bind_file.exp
new file mode 100755
index 000000000..0380b68b5
--- /dev/null
+++ b/test/option_bind_file.exp
@@ -0,0 +1,26 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --bind=tmpfile,/etc/passwd\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "cat /etc/passwd;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "hello"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "home"
22}
23sleep 1
24
25puts "\n"
26
diff --git a/test/option_bind_user.exp b/test/option_bind_user.exp
new file mode 100755
index 000000000..9d2d17d7f
--- /dev/null
+++ b/test/option_bind_user.exp
@@ -0,0 +1,15 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --bind=/tmp/chroot,mntpoint\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "bind option is available only if running as root"
11}
12sleep 1
13
14puts "\n"
15
diff --git a/test/option_blacklist.exp b/test/option_blacklist.exp
new file mode 100755
index 000000000..b80d0cc60
--- /dev/null
+++ b/test/option_blacklist.exp
@@ -0,0 +1,35 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --blacklist=/var\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "ls -l /var;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Permission denied"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "home"
22}
23send -- "cd /var;pwd\r"
24expect {
25 timeout {puts "TESTING ERROR 3\n";exit}
26 "Permission denied"
27}
28expect {
29 timeout {puts "TESTING ERROR 4\n";exit}
30 "home"
31}
32sleep 1
33
34puts "\n"
35
diff --git a/test/option_blacklist_file.exp b/test/option_blacklist_file.exp
new file mode 100755
index 000000000..ecdfe3b82
--- /dev/null
+++ b/test/option_blacklist_file.exp
@@ -0,0 +1,26 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --blacklist=/etc/passwd\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "cat /etc/passwd;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Permission denied"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "home"
22}
23sleep 1
24
25puts "\n"
26
diff --git a/test/option_chroot_overlay.exp b/test/option_chroot_overlay.exp
new file mode 100755
index 000000000..b39bc0c8e
--- /dev/null
+++ b/test/option_chroot_overlay.exp
@@ -0,0 +1,21 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --chroot=/tmp/chroot --overlay\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "mutually exclusive"
11}
12sleep 1
13
14send -- "firejail --overlay --chroot=/tmp/chroot\r"
15expect {
16 timeout {puts "TESTING ERROR 0\n";exit}
17 "mutually exclusive"
18}
19sleep 1
20
21puts "\n"
diff --git a/test/option_help.exp b/test/option_help.exp
new file mode 100755
index 000000000..f4518219c
--- /dev/null
+++ b/test/option_help.exp
@@ -0,0 +1,22 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --help\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "License GPL version 2 or later"
11}
12after 100
13
14send -- "firejail -?\r"
15expect {
16 timeout {puts "TESTING ERROR 0\n";exit}
17 "License GPL version 2 or later"
18}
19after 100
20
21puts "\n"
22
diff --git a/test/option_list.exp b/test/option_list.exp
new file mode 100755
index 000000000..b9c73e52b
--- /dev/null
+++ b/test/option_list.exp
@@ -0,0 +1,48 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12after 100
13
14spawn $env(SHELL)
15send -- "firejail\r"
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "Child process initialized"
19}
20after 100
21
22spawn $env(SHELL)
23send -- "firejail\r"
24expect {
25 timeout {puts "TESTING ERROR 2\n";exit}
26 "Child process initialized"
27}
28sleep 1
29
30spawn $env(SHELL)
31send -- "firejail --list\r"
32expect {
33 timeout {puts "TESTING ERROR 3\n";exit}
34 ":firejail"
35}
36expect {
37 timeout {puts "TESTING ERROR 4\n";exit}
38 ":firejail"
39}
40expect {
41 timeout {puts "TESTING ERROR 5\n";exit}
42 ":firejail"
43}
44after 100
45
46
47puts "\n"
48
diff --git a/test/option_man.exp b/test/option_man.exp
new file mode 100755
index 000000000..d941a2432
--- /dev/null
+++ b/test/option_man.exp
@@ -0,0 +1,17 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "man firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Linux namespaces sandbox program"
11}
12after 100
13
14send -- "q\r"
15after 100
16puts "\n"
17
diff --git a/test/option_readonly.exp b/test/option_readonly.exp
new file mode 100755
index 000000000..4abbef617
--- /dev/null
+++ b/test/option_readonly.exp
@@ -0,0 +1,26 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --read-only=tmpreadonly\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "touch tmpreadonly;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Read-only file system"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "home"
22}
23sleep 1
24
25puts "\n"
26
diff --git a/test/option_rlimit.exp b/test/option_rlimit.exp
new file mode 100755
index 000000000..17d2bd9d1
--- /dev/null
+++ b/test/option_rlimit.exp
@@ -0,0 +1,36 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --rlimit-fsize=1024 --rlimit-nproc=1000 --rlimit-nofile=500 --rlimit-sigpending=200\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "cat /proc/self/limits; pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1.1\n";exit}
17 "Max file size 1024 1024"
18}
19expect {
20 timeout {puts "TESTING ERROR 1.2\n";exit}
21 "Max processes 1000 1000"
22}
23expect {
24 timeout {puts "TESTING ERROR 1.3\n";exit}
25 "Max open files 500 500"
26}
27expect {
28 timeout {puts "TESTING ERROR 1.4\n";exit}
29 "Max pending signals 200 200"
30}
31expect {
32 timeout {puts "TESTING ERROR 1.5\n";exit}
33 "home"
34}
35sleep 1
36puts "\n"
diff --git a/test/option_tmpfs.exp b/test/option_tmpfs.exp
new file mode 100755
index 000000000..1ff47ab13
--- /dev/null
+++ b/test/option_tmpfs.exp
@@ -0,0 +1,26 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --tmpfs=/var\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "ls -l /var;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "total 0"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "home"
22}
23sleep 1
24
25puts "\n"
26
diff --git a/test/option_tree.exp b/test/option_tree.exp
new file mode 100755
index 000000000..1841907d1
--- /dev/null
+++ b/test/option_tree.exp
@@ -0,0 +1,60 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12after 100
13
14spawn $env(SHELL)
15send -- "firejail\r"
16expect {
17 timeout {puts "TESTING ERROR 1\n";exit}
18 "Child process initialized"
19}
20after 100
21
22spawn $env(SHELL)
23send -- "firejail\r"
24expect {
25 timeout {puts "TESTING ERROR 2\n";exit}
26 "Child process initialized"
27}
28sleep 1
29
30spawn $env(SHELL)
31send -- "firejail --tree\r"
32expect {
33 timeout {puts "TESTING ERROR 3\n";exit}
34 ":firejail"
35}
36expect {
37 timeout {puts "TESTING ERROR 3.1\n";exit}
38 ":/bin/bash"
39}
40expect {
41 timeout {puts "TESTING ERROR 4\n";exit}
42 ":firejail"
43}
44expect {
45 timeout {puts "TESTING ERROR 4.1\n";exit}
46 ":/bin/bash"
47}
48expect {
49 timeout {puts "TESTING ERROR 5\n";exit}
50 ":firejail"
51}
52expect {
53 timeout {puts "TESTING ERROR 5.1\n";exit}
54 ":/bin/bash"
55}
56after 100
57
58
59puts "\n"
60
diff --git a/test/option_version.exp b/test/option_version.exp
new file mode 100755
index 000000000..44c0c217f
--- /dev/null
+++ b/test/option_version.exp
@@ -0,0 +1,15 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --version\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "firejail version "
11}
12after 100
13
14puts "\n"
15
diff --git a/test/output.exp b/test/output.exp
new file mode 100755
index 000000000..90a9d64b6
--- /dev/null
+++ b/test/output.exp
@@ -0,0 +1,66 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "rm -f logfile*\r"
8sleep 1
9puts "\n"
10
11send -- "firejail --output=logfile -- ./output.sh\r"
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "20000"
15}
16expect {
17 timeout {puts "TESTING ERROR 1.1\n";exit}
18 "60000"
19}
20expect {
21 timeout {puts "TESTING ERROR 1.2\n";exit}
22 "100000"
23}
24expect {
25 timeout {puts "TESTING ERROR 1.3\n";exit}
26 "120000"
27}
28expect {
29 timeout {puts "TESTING ERROR 1.4\n";exit}
30 "14999"
31}
32sleep 2
33puts "\n"
34
35
36set timeout 2
37send -- "ls -al logfile*\r"
38expect {
39 timeout {puts "TESTING ERROR 2\n";exit}
40 "logfile"
41}
42expect {
43 timeout {puts "TESTING ERROR 3\n";exit}
44 "logfile.1"
45}
46expect {
47 timeout {puts "TESTING ERROR 4\n";exit}
48 "logfile.2"
49}
50expect {
51 timeout {puts "TESTING ERROR 5\n";exit}
52 "logfile.3"
53}
54expect {
55 timeout {puts "TESTING ERROR 6\n";exit}
56 "logfile.4"
57}
58expect {
59 timeout {puts "TESTING ERROR 7\n";exit}
60 "logfile.5"
61}
62sleep 1
63send -- "rm -f logfile*\r"
64sleep 1
65
66puts "\n"
diff --git a/test/output.sh b/test/output.sh
new file mode 100755
index 000000000..2be188e3a
--- /dev/null
+++ b/test/output.sh
@@ -0,0 +1,9 @@
1#!/bin/bash
2
3i="0"
4
5while [ $i -lt 150000 ]
6do
7 echo message number $i
8 i=$[$i+1]
9done
diff --git a/test/pid.exp b/test/pid.exp
new file mode 100755
index 000000000..0baf3af0e
--- /dev/null
+++ b/test/pid.exp
@@ -0,0 +1,48 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14# test processes
15send -- "bash\r"
16sleep 1
17send -- "ps aux; pwd\r"
18expect {
19 timeout {puts "TESTING ERROR 1\n";exit}
20 "/bin/bash"
21}
22expect {
23 timeout {puts "TESTING ERROR 2\n";exit}
24 "bash"
25}
26expect {
27 timeout {puts "TESTING ERROR 3\n";exit}
28 "ps aux"
29}
30expect {
31 timeout {puts "TESTING ERROR 4\n";exit}
32 "home"
33}
34sleep 1
35
36
37send -- "ps aux |wc -l; pwd\r"
38expect {
39 timeout {puts "TESTING ERROR 5\n";exit}
40 "5"
41}
42expect {
43 timeout {puts "TESTING ERROR 6\n";exit}
44 "home"
45}
46sleep 1
47
48puts "\n"
diff --git a/test/private-keep.exp b/test/private-keep.exp
new file mode 100755
index 000000000..cdae12ac3
--- /dev/null
+++ b/test/private-keep.exp
@@ -0,0 +1,66 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --private.keep=.mozilla,.config/firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "ls -al\r"
15expect {
16 timeout {puts "TESTING ERROR 0.1\n";exit}
17 ".config"
18}
19expect {
20 timeout {puts "TESTING ERROR 0.2\n";exit}
21 ".mozilla"
22}
23sleep 1
24
25send -- "find .config\r"
26expect {
27 timeout {puts "TESTING ERROR 0.3\n";exit}
28 ".config"
29}
30expect {
31 timeout {puts "TESTING ERROR 0.4\n";exit}
32 ".config/firejail"
33}
34sleep 1
35puts "\n"
36send -- "exit\r"
37sleep 2
38
39
40send -- "firejail --profile=private-keep.profile\r"
41expect {
42 timeout {puts "TESTING ERROR 1.0\n";exit}
43 "Child process initialized"
44}
45sleep 1
46
47send -- "ls -al\r"
48expect {
49 timeout {puts "TESTING ERROR 1.1\n";exit}
50 ".config"
51}
52expect {
53 timeout {puts "TESTING ERROR 1.2\n";exit}
54 ".mozilla"
55}
56sleep 1
57
58send -- "find .config\r"
59expect {
60 timeout {puts "TESTING ERROR 1.3\n";exit}
61 ".config"
62}
63expect {
64 timeout {puts "TESTING ERROR 1.4\n";exit}
65 ".config/firejail"
66}
diff --git a/test/private-keep.profile b/test/private-keep.profile
new file mode 100644
index 000000000..7f842cc04
--- /dev/null
+++ b/test/private-keep.profile
@@ -0,0 +1 @@
private.keep .mozilla,.config/firejail
diff --git a/test/private.exp b/test/private.exp
new file mode 100755
index 000000000..e2ae80b33
--- /dev/null
+++ b/test/private.exp
@@ -0,0 +1,95 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7if { $argc != 1 } {
8 puts "TESTING ERROR: argument missing"
9 puts "Usage: private.exp username"
10 puts "where username is the name of the current user"
11 exit
12}
13
14# testing profile and private
15send -- "firejail --private --profile=/etc/firejail/firefox.profile\r"
16expect {
17 timeout {puts "TESTING ERROR 0\n";exit}
18 "Child process initialized"
19}
20sleep 1
21send -- "exit\r"
22sleep 1
23
24send -- "firejail --private\r"
25expect {
26 timeout {puts "TESTING ERROR 0\n";exit}
27 "Child process initialized"
28}
29
30sleep 1
31send -- "ls -al; pwd\r"
32expect {
33 timeout {puts "TESTING ERROR 0.1\n";exit}
34 ".bashrc"
35}
36expect {
37 timeout {puts "TESTING ERROR 0.2\n";exit}
38 [lindex $argv 0]
39}
40send -- "ls -al; pwd\r"
41expect {
42 timeout {
43 # OpenSUSE doesn't use .Xauthority from user home directory
44 send -- "env | grep XAUTHORITY\r"
45
46 expect {
47 timeout {puts "TESTING ERROR 0.3\n";exit}
48 "/run/lightdm/netblue/xauthority"
49 }
50 }
51 ".Xauthority"
52}
53expect {
54 timeout {puts "TESTING ERROR 0.4\n";exit}
55 [lindex $argv 0]
56}
57
58
59# testing private only
60send -- "bash\r"
61sleep 1
62# owner /home/netblue
63send -- "ls -l /home;pwd\r"
64expect {
65 timeout {puts "TESTING ERROR 1\n";exit}
66 [lindex $argv 0]
67}
68expect {
69 timeout {puts "TESTING ERROR 1.1\n";exit}
70 [lindex $argv 0]
71}
72expect {
73 timeout {puts "TESTING ERROR 1.2\n";exit}
74 [lindex $argv 0]
75}
76expect {
77 timeout {puts "TESTING ERROR 1.3\n";exit}
78 "home"
79}
80sleep 1
81
82# owner /tmp
83send -- "stat -c %U%a /tmp;pwd\r"
84expect {
85 timeout {puts "TESTING ERROR 2\n";exit}
86 "root777" {puts "version 1\n";}
87 "root1777" {puts "version 2\n";}
88}
89expect {
90 timeout {puts "TESTING ERROR 2.1\n";exit}
91 "home"
92}
93sleep 1
94
95puts "\n"
diff --git a/test/private.profile b/test/private.profile
new file mode 100644
index 000000000..1b947b6f7
--- /dev/null
+++ b/test/private.profile
@@ -0,0 +1 @@
private ./dirprivate
diff --git a/test/private_dir.exp b/test/private_dir.exp
new file mode 100755
index 000000000..95f89362a
--- /dev/null
+++ b/test/private_dir.exp
@@ -0,0 +1,53 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# testing private
8send -- "firejail --private=./dirprivate\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Child process initialized"
12}
13sleep 1
14
15send -- "ls -al;pwd\r"
16expect {
17 timeout {puts "TESTING ERROR 0.1\n";exit}
18 "bashrc"
19}
20expect {
21 timeout {puts "TESTING ERROR 0.2\n";exit}
22 "home"
23}
24send -- "ls -al;pwd\r"
25expect {
26 timeout {
27 # OpenSUSE doesn't use .Xauthority from user home directory
28 send -- "env | grep XAUTHORITY\r"
29
30 expect {
31 timeout {puts "TESTING ERROR 0.3\n";exit}
32 "/run/lightdm/netblue/xauthority"
33 }
34 }
35 ".Xauthority"
36}
37expect {
38 timeout {puts "TESTING ERROR 0.4\n";exit}
39 [lindex $argv 0]
40}
41
42send -- "ls -al | wc -l;pwd\r"
43expect {
44 timeout {puts "TESTING ERROR 1\n";exit}
45 "5" {puts "normal system\n";}
46 "4" {puts "OpenSUSE\n";}
47}
48expect {
49 timeout {puts "TESTING ERROR 2\n";exit}
50 "home"
51}
52
53puts "\n"
diff --git a/test/private_dir_profile.exp b/test/private_dir_profile.exp
new file mode 100755
index 000000000..e6c01798e
--- /dev/null
+++ b/test/private_dir_profile.exp
@@ -0,0 +1,54 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# testing private
8send -- "firejail --profile=private.profile\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Child process initialized"
12}
13sleep 1
14
15send -- "ls -al;pwd\r"
16expect {
17 timeout {puts "TESTING ERROR 0.1\n";exit}
18 "bashrc"
19}
20expect {
21 timeout {puts "TESTING ERROR 0.2\n";exit}
22 "home"
23}
24send -- "ls -al;pwd\r"
25expect {
26 timeout {
27 # OpenSUSE doesn't use .Xauthority from user home directory
28 send -- "env | grep XAUTHORITY\r"
29
30 expect {
31 timeout {puts "TESTING ERROR 0.3\n";exit}
32 "/run/lightdm/netblue/xauthority"
33 }
34 }
35 ".Xauthority"
36}
37expect {
38 timeout {puts "TESTING ERROR 0.4\n";exit}
39 [lindex $argv 0]
40}
41
42send -- "ls -al | wc -l;pwd\r"
43expect {
44 timeout {puts "TESTING ERROR 1\n";exit}
45 "5" {puts "normal system\n";}
46 "4" {puts "OpenSUSE\n";}
47}
48expect {
49 timeout {puts "TESTING ERROR 2\n";exit}
50 "home"
51}
52
53puts "\n"
54
diff --git a/test/profile_apps.exp b/test/profile_apps.exp
new file mode 100755
index 000000000..c57b31489
--- /dev/null
+++ b/test/profile_apps.exp
@@ -0,0 +1,48 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7# firefox
8send -- "firejail --profile=/etc/firejail/firefox.profile\r"
9expect {
10 timeout {puts "TESTING ERROR 0\n";exit}
11 "Child process initialized"
12}
13sleep 1
14send -- "exit\r"
15sleep 1
16
17# iceweasel
18send -- "firejail --profile=/etc/firejail/iceweasel.profile\r"
19expect {
20 timeout {puts "TESTING ERROR 1\n";exit}
21 "Child process initialized"
22}
23sleep 1
24send -- "exit\r"
25sleep 1
26
27# evince
28send -- "firejail --profile=/etc/firejail/evince.profile\r"
29expect {
30 timeout {puts "TESTING ERROR 2\n";exit}
31 "Child process initialized"
32}
33sleep 1
34send -- "exit\r"
35sleep 1
36
37# midori
38send -- "firejail --profile=/etc/firejail/midori.profile\r"
39expect {
40 timeout {puts "TESTING ERROR 3\n";exit}
41 "Child process initialized"
42}
43sleep 1
44send -- "exit\r"
45sleep 1
46
47
48puts "\n"
diff --git a/test/profile_followlnk.exp b/test/profile_followlnk.exp
new file mode 100755
index 000000000..e2ede2865
--- /dev/null
+++ b/test/profile_followlnk.exp
@@ -0,0 +1,68 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "mkdir /tmp/firejailtestdir\r"
8sleep 1
9send -- "ln -s /tmp/firejailtestdir /tmp/firejailtestdirlnk\r"
10sleep 1
11send -- "touch /tmp/firejailtestfile\r"
12sleep 1
13send -- "ln -s /tmp/firejailtestfile /tmp/firejailtestfilelnk\r"
14sleep 1
15
16send -- "firejail --profile=readonly-lnk.profile --debug\r"
17expect {
18 timeout {puts "TESTING ERROR 0\n";exit}
19 "Child process initialized"
20}
21
22# testing private only
23send -- "bash\r"
24sleep 1
25
26
27send -- "ls > /tmp/firejailtestdirlnk/ttt;pwd\r"
28expect {
29 timeout {puts "TESTING ERROR 1\n";exit}
30 "Read-only file system"
31}
32expect {
33 timeout {puts "TESTING ERROR 1.1\n";exit}
34 "home"
35}
36sleep 1
37
38send -- "ls > /tmp/firejailtestfilelnk;pwd\r"
39expect {
40 timeout {puts "TESTING ERROR 2\n";exit}
41 "Read-only file system"
42}
43expect {
44 timeout {puts "TESTING ERROR 2.1\n";exit}
45 "home"
46}
47sleep 1
48
49send -- "exit\r"
50sleep 1
51send -- "pwd\r"
52expect {
53 timeout {puts "TESTING ERROR 3\n";exit}
54 "home"
55}
56sleep 1
57send -- "exit\r"
58sleep 1
59send -- "pwd\r"
60expect {
61 timeout {puts "TESTING ERROR 4\n";exit}
62 "home"
63}
64sleep 2
65send -- "rm -fr /tmp/firejailtest*\r"
66sleep 1
67
68puts "\n"
diff --git a/test/profile_noperm.exp b/test/profile_noperm.exp
new file mode 100755
index 000000000..b3ed558bc
--- /dev/null
+++ b/test/profile_noperm.exp
@@ -0,0 +1,13 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --profile=/etc/shadow\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "cannot access profile"
11}
12sleep 1
13puts "\n"
diff --git a/test/profile_readonly.exp b/test/profile_readonly.exp
new file mode 100755
index 000000000..046b0d738
--- /dev/null
+++ b/test/profile_readonly.exp
@@ -0,0 +1,64 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "mkdir /tmp/firejailtestdir\r"
8sleep 1
9send -- "touch /tmp/firejailtestfile\r"
10sleep 1
11
12send -- "firejail --profile=readonly.profile\r"
13expect {
14 timeout {puts "TESTING ERROR 0\n";exit}
15 "Child process initialized"
16}
17
18# testing private only
19send -- "bash\r"
20sleep 1
21
22
23send -- "ls > /tmp/firejailtestdir/ttt;pwd\r"
24expect {
25 timeout {puts "TESTING ERROR 1\n";exit}
26 "Read-only file system"
27}
28expect {
29 timeout {puts "TESTING ERROR 1.1\n";exit}
30 "home"
31}
32sleep 1
33
34send -- "ls > /tmp/firejailtestfile;pwd\r"
35expect {
36 timeout {puts "TESTING ERROR 2\n";exit}
37 "Read-only file system"
38}
39expect {
40 timeout {puts "TESTING ERROR 2.1\n";exit}
41 "home"
42}
43sleep 1
44
45send -- "exit\r"
46sleep 1
47send -- "pwd\r"
48expect {
49 timeout {puts "TESTING ERROR 3\n";exit}
50 "home"
51}
52sleep 1
53send -- "exit\r"
54sleep 1
55send -- "pwd\r"
56expect {
57 timeout {puts "TESTING ERROR 4\n";exit}
58 "home"
59}
60sleep 2
61send -- "rm -fr /tmp/firejailtest*\r"
62sleep 1
63
64puts "\n"
diff --git a/test/profile_rlimit.exp b/test/profile_rlimit.exp
new file mode 100755
index 000000000..7d2637444
--- /dev/null
+++ b/test/profile_rlimit.exp
@@ -0,0 +1,36 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --profile=rlimit.profile\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "cat /proc/self/limits; pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1.1\n";exit}
17 "Max file size 1024 1024"
18}
19expect {
20 timeout {puts "TESTING ERROR 1.2\n";exit}
21 "Max processes 1000 1000"
22}
23expect {
24 timeout {puts "TESTING ERROR 1.3\n";exit}
25 "Max open files 500 500"
26}
27expect {
28 timeout {puts "TESTING ERROR 1.4\n";exit}
29 "Max pending signals 200 200"
30}
31expect {
32 timeout {puts "TESTING ERROR 1.5\n";exit}
33 "home"
34}
35sleep 1
36puts "\n"
diff --git a/test/profile_syntax.exp b/test/profile_syntax.exp
new file mode 100755
index 000000000..3218177c3
--- /dev/null
+++ b/test/profile_syntax.exp
@@ -0,0 +1,69 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --profile=test.profile\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12
13sleep 2
14send -- "ls /sbin\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "cannot open"
18}
19
20sleep 1
21send -- "ls /usr/sbin\r"
22expect {
23 timeout {puts "TESTING ERROR 2\n";exit}
24 "cannot open"
25}
26
27sleep 1
28send -- "ls -l /etc/shadow\r"
29expect {
30 timeout {puts "TESTING ERROR 3\n";exit}
31 "root root 0"
32}
33
34sleep 1
35send -- "rmdir;pwd\r"
36expect {
37 timeout {puts "TESTING ERROR 4\n";exit}
38 "Permission denied"
39}
40expect {
41 timeout {puts "TESTING ERROR 5\n";exit}
42 "home"
43}
44
45sleep 1
46send -- "mount;pwd\r"
47expect {
48 timeout {puts "TESTING ERROR 6\n";exit}
49 "Permission denied"
50}
51expect {
52 timeout {puts "TESTING ERROR 7\n";exit}
53 "home"
54}
55
56sleep 1
57send -- "umount;pwd\r"
58expect {
59 timeout {puts "TESTING ERROR 8\n";exit}
60 "Permission denied"
61}
62expect {
63 timeout {puts "TESTING ERROR 9\n";exit}
64 "home"
65}
66send -- "exit\r"
67
68sleep 1
69puts "\n"
diff --git a/test/profile_syntax2.exp b/test/profile_syntax2.exp
new file mode 100755
index 000000000..cd514aa0e
--- /dev/null
+++ b/test/profile_syntax2.exp
@@ -0,0 +1,47 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --debug --profile=test2.profile\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Reading profile test2.profile"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "Reading profile test.profile"
15}
16expect {
17 timeout {puts "TESTING ERROR 2\n";exit}
18 "Disable /bin/rmdir" {puts "Most Linux platforms\n"}
19 "Disable /usr/bin/rmdir" { puts "OpenSUSE platform\n"}
20}
21expect {
22 timeout {puts "TESTING ERROR 3\n";exit}
23 "Mounting a new /home directory"
24}
25expect {
26 timeout {puts "TESTING ERROR 4\n";exit}
27 "Drop CAP_SYS_MODULE"
28}
29expect {
30 timeout {puts "TESTING ERROR 5\n";exit}
31 "Initialize seccomp filter"
32}
33expect {
34 timeout {puts "TESTING ERROR 6\n";exit}
35 "Blacklisting syscall"
36}
37expect {
38 timeout {puts "TESTING ERROR 7\n";exit}
39 "mount"
40}
41expect {
42 timeout {puts "TESTING ERROR 8\n";exit}
43 "Child process initialized"
44}
45
46sleep 1
47puts "\n"
diff --git a/test/profile_tmpfs.exp b/test/profile_tmpfs.exp
new file mode 100755
index 000000000..a2faa32f7
--- /dev/null
+++ b/test/profile_tmpfs.exp
@@ -0,0 +1,37 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "mkdir /tmp/firejailtestdir\r"
8sleep 1
9send -- "ls > /tmp/firejailtestdir/tmpfile\r"
10sleep 1
11
12send -- "firejail --profile=tmpfs.profile\r"
13expect {
14 timeout {puts "TESTING ERROR 0\n";exit}
15 "Child process initialized"
16}
17
18# testing private only
19send -- "bash\r"
20sleep 1
21
22send -- "ls -l /tmp/firejailtestdir;pwd\r"
23expect {
24 timeout {puts "TESTING ERROR 1.1\n";exit}
25 "tmpfile" {puts "TESTING ERROR 1\n";exit}
26 "home"
27}
28sleep 1
29send -- "exit\r"
30sleep 1
31send -- "exit\r"
32sleep 1
33send -- "rm -fr /tmp/firejailtestdir\r"
34
35sleep 1
36
37puts "\n"
diff --git a/test/readonly-lnk.profile b/test/readonly-lnk.profile
new file mode 100644
index 000000000..71ffb1a26
--- /dev/null
+++ b/test/readonly-lnk.profile
@@ -0,0 +1,2 @@
1read-only /tmp/firejailtestdirlnk
2read-only /tmp/firejailtestfilelnk
diff --git a/test/readonly.profile b/test/readonly.profile
new file mode 100644
index 000000000..55d89e3d7
--- /dev/null
+++ b/test/readonly.profile
@@ -0,0 +1,2 @@
1read-only /tmp/firejailtestdir
2read-only /tmp/firejailtestfile \ No newline at end of file
diff --git a/test/rlimit.profile b/test/rlimit.profile
new file mode 100644
index 000000000..271891c03
--- /dev/null
+++ b/test/rlimit.profile
@@ -0,0 +1,4 @@
1 rlimit-fsize 1024
2rlimit-nproc 1000
3 rlimit-nofile 500
4rlimit-sigpending 200 \ No newline at end of file
diff --git a/test/seccomp-bad-empty.exp b/test/seccomp-bad-empty.exp
new file mode 100755
index 000000000..53b5c2e21
--- /dev/null
+++ b/test/seccomp-bad-empty.exp
@@ -0,0 +1,38 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --seccomp=\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Error: empty syscall lists are not allowed"
11}
12
13send -- "firejail --seccomp.drop=\r"
14expect {
15 timeout {puts "TESTING ERROR 2\n";exit}
16 "Error: empty syscall lists are not allowed"
17}
18
19send -- "firejail --seccomp.keep=\r"
20expect {
21 timeout {puts "TESTING ERROR 4\n";exit}
22 "Error: empty syscall lists are not allowed"
23}
24
25send -- "firejail --profile=seccomp-bad-empty.profile\r"
26expect {
27 timeout {puts "TESTING ERROR 6\n";exit}
28 "Error: line 1 in the custom profile is invalid"
29}
30
31send -- "firejail --profile=seccomp-bad-empty2.profile\r"
32expect {
33 timeout {puts "TESTING ERROR 7\n";exit}
34 "Error: line 1 in the custom profile is invalid"
35}
36sleep 1
37puts "\n"
38
diff --git a/test/seccomp-bad-empty.profile b/test/seccomp-bad-empty.profile
new file mode 100644
index 000000000..2d4fcde7c
--- /dev/null
+++ b/test/seccomp-bad-empty.profile
@@ -0,0 +1 @@
seccomp.drop
diff --git a/test/seccomp-bad-empty2.profile b/test/seccomp-bad-empty2.profile
new file mode 100644
index 000000000..c4e6c9f74
--- /dev/null
+++ b/test/seccomp-bad-empty2.profile
@@ -0,0 +1 @@
seccomp.keep
diff --git a/test/seccomp-chmod-profile.exp b/test/seccomp-chmod-profile.exp
new file mode 100755
index 000000000..098328cea
--- /dev/null
+++ b/test/seccomp-chmod-profile.exp
@@ -0,0 +1,46 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --profile=seccomp.profile --private\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 2
13
14send -- "touch testfile;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "/root" {puts "running as root"}
18 "/home"
19}
20
21send -- "ls -l testfile;pwd\r"
22expect {
23 timeout {puts "TESTING ERROR 2\n";exit}
24 "testfile"
25}
26expect {
27 timeout {puts "TESTING ERROR 3\n";exit}
28 "/root" {puts "running as root"}
29 "/home"
30}
31
32send -- "chmod +x testfile;pwd\r"
33expect {
34 timeout {puts "TESTING ERROR 2\n";exit}
35 "Bad system call"
36}
37expect {
38 timeout {puts "TESTING ERROR 3\n";exit}
39 "/root" {puts "running as root"}
40 "/home"
41}
42
43
44send -- "exit\r"
45sleep 1
46puts "\n"
diff --git a/test/seccomp-chmod.exp b/test/seccomp-chmod.exp
new file mode 100755
index 000000000..b4a213206
--- /dev/null
+++ b/test/seccomp-chmod.exp
@@ -0,0 +1,46 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --seccomp=chmod,fchmod,fchmodat --private\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 2
13
14send -- "touch testfile;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "/root" {puts "running as root"}
18 "/home"
19}
20
21send -- "ls -l testfile;pwd\r"
22expect {
23 timeout {puts "TESTING ERROR 2\n";exit}
24 "testfile"
25}
26expect {
27 timeout {puts "TESTING ERROR 3\n";exit}
28 "/root" {puts "running as root"}
29 "/home"
30}
31
32send -- "chmod +x testfile;pwd\r"
33expect {
34 timeout {puts "TESTING ERROR 2\n";exit}
35 "Bad system call"
36}
37expect {
38 timeout {puts "TESTING ERROR 3\n";exit}
39 "/root" {puts "running as root"}
40 "/home"
41}
42
43
44send -- "exit\r"
45sleep 1
46puts "\n"
diff --git a/test/seccomp-chown.exp b/test/seccomp-chown.exp
new file mode 100755
index 000000000..69b896700
--- /dev/null
+++ b/test/seccomp-chown.exp
@@ -0,0 +1,46 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --seccomp=chown,fchown,fchownat,lchown --private\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 2
13
14send -- "touch testfile;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "/root" {puts "running as root"}
18 "/home"
19}
20
21send -- "ls -l testfile;pwd\r"
22expect {
23 timeout {puts "TESTING ERROR 2\n";exit}
24 "testfile"
25}
26expect {
27 timeout {puts "TESTING ERROR 3\n";exit}
28 "/root" {puts "running as root"}
29 "/home"
30}
31
32send -- "chown netblue:netblue testfile;pwd\r"
33expect {
34 timeout {puts "TESTING ERROR 2\n";exit}
35 "Bad system call"
36}
37expect {
38 timeout {puts "TESTING ERROR 3\n";exit}
39 "/root" {puts "running as root"}
40 "/home"
41}
42
43
44send -- "exit\r"
45sleep 1
46puts "\n"
diff --git a/test/seccomp-debug.exp b/test/seccomp-debug.exp
new file mode 100755
index 000000000..a7b89912a
--- /dev/null
+++ b/test/seccomp-debug.exp
@@ -0,0 +1,32 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --seccomp --debug\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Blacklisting syscall"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "open_by_handle_at"
15}
16expect {
17 timeout {puts "TESTING ERROR 2\n";exit}
18 "BLACKLIST"
19}
20expect {
21 timeout {puts "TESTING ERROR 3\n";exit}
22 "open_by_handle_at"
23}
24expect {
25 timeout {puts "TESTING ERROR 4\n";exit}
26 "Child process initialized"
27}
28sleep 2
29
30send -- "exit\r"
31sleep 1
32puts "\n"
diff --git a/test/seccomp-empty.exp b/test/seccomp-empty.exp
new file mode 100755
index 000000000..11abf2e00
--- /dev/null
+++ b/test/seccomp-empty.exp
@@ -0,0 +1,145 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --debug --seccomp=chmod,fchmod,fchmodat --private\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "VALIDATE_ARCHITECTURE"
11}
12expect {
13 timeout {puts "TESTING ERROR 0.1\n";exit}
14 "mount"
15}
16expect {
17 timeout {puts "TESTING ERROR 0.2\n";exit}
18 "ptrace"
19}
20expect {
21 timeout {puts "TESTING ERROR 0.3\n";exit}
22 "chmod"
23}
24expect {
25 timeout {puts "TESTING ERROR 0.4\n";exit}
26 "fchmod"
27}
28expect {
29 timeout {puts "TESTING ERROR 0.5\n";exit}
30 "fchmodat"
31}
32expect {
33 timeout {puts "TESTING ERROR 0.6\n";exit}
34 "RETURN_ALLOW"
35}
36expect {
37 timeout {puts "TESTING ERROR 0.7\n";exit}
38 "Child process initialized"
39}
40sleep 2
41send -- "exit\r"
42sleep 3
43puts "\n"
44
45send -- "firejail --debug --seccomp.drop=chmod,fchmod,fchmodat --private\r"
46expect {
47 timeout {puts "TESTING ERROR 1\n";exit}
48 "VALIDATE_ARCHITECTURE"
49}
50expect {
51 timeout {puts "TESTING ERROR 1.1\n";exit}
52 "mount" {puts "TESTING ERROR 1.2\n";exit}
53 "ptrace" {puts "TESTING ERROR 1.3\n";exit}
54 "chmod"
55}
56expect {
57 timeout {puts "TESTING ERROR 1.4\n";exit}
58 "fchmod"
59}
60expect {
61 timeout {puts "TESTING ERROR 1.5\n";exit}
62 "fchmodat"
63}
64expect {
65 timeout {puts "TESTING ERROR 1.6\n";exit}
66 "RETURN_ALLOW"
67}
68expect {
69 timeout {puts "TESTING ERROR 1.7\n";exit}
70 "Child process initialized"
71}
72sleep 2
73send -- "exit\r"
74puts "\n"
75
76sleep 2
77send -- "firejail --debug --profile=seccomp.profile --private\r"
78expect {
79 timeout {puts "TESTING ERROR 2\n";exit}
80 "VALIDATE_ARCHITECTURE"
81}
82expect {
83 timeout {puts "TESTING ERROR 2.1\n";exit}
84 "mount"
85}
86expect {
87 timeout {puts "TESTING ERROR 2.2\n";exit}
88 "ptrace"
89}
90expect {
91 timeout {puts "TESTING ERROR 2.3\n";exit}
92 "chmod"
93}
94expect {
95 timeout {puts "TESTING ERROR 2.4\n";exit}
96 "fchmod"
97}
98expect {
99 timeout {puts "TESTING ERROR 2.5\n";exit}
100 "fchmodat"
101}
102expect {
103 timeout {puts "TESTING ERROR 2.6\n";exit}
104 "RETURN_ALLOW"
105}
106expect {
107 timeout {puts "TESTING ERROR 2.7\n";exit}
108 "Child process initialized"
109}
110sleep 2
111send -- "exit\r"
112sleep 3
113puts "\n"
114
115send -- "firejail --debug --profile=seccomp-empty.profile --private\r"
116expect {
117 timeout {puts "TESTING ERROR 3\n";exit}
118 "VALIDATE_ARCHITECTURE"
119}
120expect {
121 timeout {puts "TESTING ERROR 3.1\n";exit}
122 "mount" {puts "TESTING ERROR 3.2\n";exit}
123 "ptrace" {puts "TESTING ERROR 3.3\n";exit}
124 "chmod"
125}
126expect {
127 timeout {puts "TESTING ERROR 3.4\n";exit}
128 "fchmod"
129}
130expect {
131 timeout {puts "TESTING ERROR 3.5\n";exit}
132 "fchmodat"
133}
134expect {
135 timeout {puts "TESTING ERROR 3.6\n";exit}
136 "RETURN_ALLOW"
137}
138expect {
139 timeout {puts "TESTING ERROR 3.7\n";exit}
140 "Child process initialized"
141}
142sleep 2
143send -- "exit\r"
144puts "\n"
145
diff --git a/test/seccomp-empty.profile b/test/seccomp-empty.profile
new file mode 100644
index 000000000..8f71f55a5
--- /dev/null
+++ b/test/seccomp-empty.profile
@@ -0,0 +1 @@
seccomp.drop chmod,fchmod,fchmodat
diff --git a/test/seccomp-ptrace.exp b/test/seccomp-ptrace.exp
new file mode 100755
index 000000000..c5411c249
--- /dev/null
+++ b/test/seccomp-ptrace.exp
@@ -0,0 +1,23 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --seccomp\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 2
13
14send -- "strace ls\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Bad system call" {puts "version 1\n";}
18 " unexpected signal 31" {puts "version 2\n"}
19}
20
21send -- "exit\r"
22sleep 1
23puts "\n"
diff --git a/test/seccomp-su.exp b/test/seccomp-su.exp
new file mode 100755
index 000000000..dca6f15ee
--- /dev/null
+++ b/test/seccomp-su.exp
@@ -0,0 +1,34 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --seccomp\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 2
13
14send -- "sudo su -\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "effective uid is not 0"
18}
19
20send -- "sudo ls\r"
21expect {
22 timeout {puts "TESTING ERROR 2\n";exit}
23 "effective uid is not 0"
24}
25
26send -- "ping google.com\r"
27expect {
28 timeout {puts "TESTING ERROR 2\n";exit}
29 "Operation not permitted"
30}
31
32send -- "exit\r"
33sleep 1
34puts "\n"
diff --git a/test/seccomp-umount.exp b/test/seccomp-umount.exp
new file mode 100755
index 000000000..e037d3264
--- /dev/null
+++ b/test/seccomp-umount.exp
@@ -0,0 +1,28 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "sudo ls; sudo whoami; sudo pwd\r"
8expect {
9 timeout {puts "TESTING ERROR: you need to root run this test as root\n";exit}
10 "root"
11}
12
13send -- "firejail --net=br0 --ip=10.10.20.5 --seccomp\r"
14expect {
15 timeout {puts "TESTING ERROR 0\n";exit}
16 "Child process initialized"
17}
18sleep 2
19
20send -- "umount /proc\r"
21expect {
22 timeout {puts "TESTING ERROR 1\n";exit}
23 "Bad system call"
24}
25
26send -- "exit\r"
27sleep 1
28puts "\n"
diff --git a/test/seccomp.profile b/test/seccomp.profile
new file mode 100644
index 000000000..cb0b15aee
--- /dev/null
+++ b/test/seccomp.profile
@@ -0,0 +1 @@
seccomp chmod,fchmod,fchmodat
diff --git a/test/servers.exp b/test/servers.exp
new file mode 100755
index 000000000..a36814a69
--- /dev/null
+++ b/test/servers.exp
@@ -0,0 +1,40 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "sudo ls; sudo whoami; sudo pwd\r"
8expect {
9 timeout {puts "TESTING ERROR: you need to root run this test as root\n";exit}
10 "root"
11}
12
13send -- "firejail --net=br0 --ip=10.10.20.5 --seccomp\r"
14expect {
15 timeout {puts "TESTING ERROR 0\n";exit}
16 "Child process initialized"
17}
18sleep 2
19
20
21send -- "/etc/init.d/rsyslog start;sleep 1;/etc/init.d/ssh start;sleep 1;/etc/init.d/nginx start\r"
22sleep 3
23
24send -- "ps aux; pwd\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "rsyslogd"
28}
29expect {
30 timeout {puts "TESTING ERROR 2\n";exit}
31 "sshd"
32}
33expect {
34 timeout {puts "TESTING ERROR 3\n";exit}
35 "nginx"
36}
37
38send -- "exit\r"
39sleep 1
40puts "\n"
diff --git a/test/servers2.exp b/test/servers2.exp
new file mode 100755
index 000000000..28bcae207
--- /dev/null
+++ b/test/servers2.exp
@@ -0,0 +1,31 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "sudo ls; sudo whoami; sudo pwd\r"
8expect {
9 timeout {puts "TESTING ERROR: you need to root run this test as root\n";exit}
10 "root"
11}
12
13send -- "firejail --net=br0 --ip=10.10.20.5--seccomp\r"
14expect {
15 timeout {puts "TESTING ERROR 0\n";exit}
16 "Child process initialized"
17}
18sleep 2
19
20send -- "/etc/init.d/snmpd start"
21sleep 2
22
23send -- "ps aux; pwd\r"
24expect {
25 timeout {puts "TESTING ERROR 1\n";exit}
26 "snmpd"
27}
28
29send -- "exit\r"
30sleep 1
31puts "\n"
diff --git a/test/servers3.exp b/test/servers3.exp
new file mode 100755
index 000000000..f23ffba46
--- /dev/null
+++ b/test/servers3.exp
@@ -0,0 +1,31 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "sudo ls; sudo whoami; sudo pwd\r"
8expect {
9 timeout {puts "TESTING ERROR: you need to root run this test as root\n";exit}
10 "root"
11}
12
13send -- "firejail --net=br0 --ip=10.10.20.5 --seccomp\r"
14expect {
15 timeout {puts "TESTING ERROR 0\n";exit}
16 "Child process initialized"
17}
18sleep 2
19
20send -- "/etc/init.d/apache2 start\r"
21sleep 2
22
23send -- "ps aux; pwd\r"
24expect {
25 timeout {puts "TESTING ERROR 1\n";exit}
26 "apache"
27}
28
29send -- "exit\r"
30sleep 1
31puts "\n"
diff --git a/test/servers4.exp b/test/servers4.exp
new file mode 100755
index 000000000..9feeecf61
--- /dev/null
+++ b/test/servers4.exp
@@ -0,0 +1,32 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "sudo ls; sudo whoami; sudo pwd\r"
8expect {
9 timeout {puts "TESTING ERROR: you need to root run this test as root\n";exit}
10 "root"
11}
12
13send -- "firejail --net=br0 --ip=10.10.20.5 --seccomp\r"
14expect {
15 timeout {puts "TESTING ERROR 0\n";exit}
16 "Child process initialized"
17}
18sleep 2
19
20send -- "/etc/init.d/isc-dhcp-server start\r"
21sleep 5
22
23
24send -- "ps aux; pwd\r"
25expect {
26 timeout {puts "TESTING ERROR 1\n";exit}
27 "dhcpd"
28}
29
30send -- "exit\r"
31sleep 1
32puts "\n"
diff --git a/test/shell_csh.exp b/test/shell_csh.exp
new file mode 100755
index 000000000..8fa1ef166
--- /dev/null
+++ b/test/shell_csh.exp
@@ -0,0 +1,40 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --private --csh\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "ls -al;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 ".cshrc"
18}
19expect {
20 timeout {puts "TESTING ERROR 1.1\n";exit}
21 "home"
22}
23send -- "env | grep SHELL;pwd\r"
24expect {
25 timeout {puts "TESTING ERROR 2\n";exit}
26 "SHELL"
27}
28expect {
29 timeout {puts "TESTING ERROR 2.1\n";exit}
30 "/bin/csh"
31}
32expect {
33 timeout {puts "TESTING ERROR 2.2\n";exit}
34 "home"
35}
36send -- "exit\r"
37sleep 1
38
39puts "\n"
40
diff --git a/test/shell_dash.exp b/test/shell_dash.exp
new file mode 100755
index 000000000..298b65a0d
--- /dev/null
+++ b/test/shell_dash.exp
@@ -0,0 +1,41 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --private --shell=/bin/dash\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14#send -- "ls -al;pwd\r"
15#expect {
16# timeout {puts "TESTING ERROR 1\n";exit}
17# ".zshrc"
18#}
19#expect {
20# timeout {puts "TESTING ERROR 1.1\n";exit}
21# "home"
22#}
23
24send -- "env | grep SHELL;pwd\r"
25expect {
26 timeout {puts "TESTING ERROR 2\n";exit}
27 "SHELL"
28}
29expect {
30 timeout {puts "TESTING ERROR 2.1\n";exit}
31 "/bin/dash"
32}
33expect {
34 timeout {puts "TESTING ERROR 2.2\n";exit}
35 "home"
36}
37send -- "exit\r"
38sleep 1
39
40puts "\n"
41
diff --git a/test/shell_zsh.exp b/test/shell_zsh.exp
new file mode 100755
index 000000000..79cd78a3e
--- /dev/null
+++ b/test/shell_zsh.exp
@@ -0,0 +1,40 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --private --zsh\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "ls -al;pwd\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 ".zshrc"
18}
19expect {
20 timeout {puts "TESTING ERROR 1.1\n";exit}
21 "home"
22}
23send -- "env | grep SHELL;pwd\r"
24expect {
25 timeout {puts "TESTING ERROR 2\n";exit}
26 "SHELL"
27}
28expect {
29 timeout {puts "TESTING ERROR 2.1\n";exit}
30 "/usr/bin/zsh"
31}
32expect {
33 timeout {puts "TESTING ERROR 2.2\n";exit}
34 "home"
35}
36send -- "exit\r"
37sleep 1
38
39puts "\n"
40
diff --git a/test/sysrq-trigger.exp b/test/sysrq-trigger.exp
new file mode 100755
index 000000000..18fb4a01a
--- /dev/null
+++ b/test/sysrq-trigger.exp
@@ -0,0 +1,21 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "echo b > /proc/sysrq-trigger\r"
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Read-only file system"
18}
19sleep 1
20
21puts "\n"
diff --git a/test/test-nonet.sh b/test/test-nonet.sh
new file mode 100755
index 000000000..3df8b2d4e
--- /dev/null
+++ b/test/test-nonet.sh
@@ -0,0 +1,44 @@
1#!/bin/bash
2
3echo "TESTING: version"
4./option_version.exp
5
6echo "TESTING: help"
7./option_help.exp
8
9echo "TESTING: man"
10./option_man.exp
11
12echo "TESTING: list"
13./option_list.exp
14
15echo "TESTING: PID"
16./pid.exp
17
18echo "TESTING: profile no permissions"
19./profile_noperm.exp
20
21echo "TESTING: profile syntax"
22./profile_syntax.exp
23
24echo "TESTING: profile read-only"
25./profile_readonly.exp
26
27echo "TESTING: profile tmpfs"
28./profile_tmpfs.exp
29
30echo "TESTING: private"
31./private.exp `whoami`
32
33echo "TESTING: read/write /var/tmp"
34./fs_var_tmp.exp
35
36echo "TESTING: read/write /var/run"
37./fs_var_run.exp
38
39echo "TESTING: read/write /var/lock"
40./fs_var_lock.exp
41
42echo "TESTING: read/write /dev/shm"
43./fs_dev_shm.exp
44
diff --git a/test/test-root.sh b/test/test-root.sh
new file mode 100755
index 000000000..cd607b75b
--- /dev/null
+++ b/test/test-root.sh
@@ -0,0 +1,56 @@
1#!/bin/bash
2
3./chk_config.exp
4
5echo "TESTING: servers rsyslogd, sshd, nginx"
6./servers.exp
7
8if [ -f /etc/init.d/snmpd ]
9then
10 echo "TESTING: servers snmpd"
11 ./servers2.exp
12fi
13
14if [ -f /etc/init.d/apache2 ]
15then
16 echo "TESTING: servers apache2"
17 ./servers3.exp
18fi
19
20if [ -f /etc/init.d/isc-dhcp-server ]
21then
22 echo "TESTING: servers isc dhcp server"
23 ./servers4.exp
24fi
25
26echo "TESTING: /proc/sysrq-trigger reset disabled"
27./sysrq-trigger.exp
28
29echo "TESTING: seccomp umount"
30./seccomp-umount.exp
31
32echo "TESTING: seccomp chmod (seccomp lists)"
33./seccomp-chmod.exp
34
35echo "TESTING: seccomp chown (seccomp lists)"
36./seccomp-chown.exp
37
38echo "TESTING: bind directory"
39./option_bind_directory.exp
40
41echo "TESTING: bind file"
42echo hello > tmpfile
43./option_bind_file.exp
44rm -f tmpfile
45
46echo "TESTING: chroot"
47./fs_chroot.exp
48
49echo "TESTING: firemon --interface"
50./firemon-interface.exp
51
52if [ -f /sys/fs/cgroup/g1/tasks ]
53then
54 echo "TESTING: firemon --cgroup"
55 ./firemon-cgroup.exp
56fi
diff --git a/test/test.profile b/test/test.profile
new file mode 100644
index 000000000..716419fd0
--- /dev/null
+++ b/test/test.profile
@@ -0,0 +1,6 @@
1 blacklist /sbin
2blacklist /usr/sbin
3blacklist /etc/shadow
4 blacklist /bin/rmdir
5blacklist ${PATH}/umount
6blacklist ${PATH}/mount
diff --git a/test/test.rv b/test/test.rv
new file mode 100644
index 000000000..98a04fba2
--- /dev/null
+++ b/test/test.rv
@@ -0,0 +1,49 @@
1# run it as:
2# ../src/tools/rvtest test.rv 2>/dev/null | grep TESTING
3#
4
5
6# invalid options
71 firejail -blablabla
81 firejail --blablabla
91 firejail --debug --blablabla
10
11# misc options
120 firejail --help
130 firejail --list
14
15# network testing
160 firejail --net=none exit
171 firejail --ip=none --net=none exit # noip requires at least one network
180 firejail --net=br0 exit
191 firejail --net=none --net=br0 exit # --net and --net=none are mutually exclusive
201 firejail --ip=none exit # noip requires at least one network
211 firejail --defaultgw=10.10.20.1 # no bridge configured
220 firejail --net=br0 --ip=10.10.20.6 exit
231 firejail --net=br0 --ip=192.168.5.6 exit # interface range
241 firejail --net=br0 --ip=10.10 # bad ip
251 firejail --net=br0 --ip=asdf #bad ip
261 firejail --ip=asdf # no bridge configured
270 firejail --net=br0 --defaultgw=10.10.20.1 exit
281 firejail --net=br0 --defaultgw=10.10.20 exit # invalid ip address
291 firejail --net=br0 --defaultgw=asdf exit # invalid ip address
300 firejail --net=br0 --ip=10.10.20.2 --defaultgw=10.10.20.1 exit
310 firejail --net=br0 --net=br1 --net=br2 --net=br3 exit
321 firejail --net
331 firejail --net=
341 firejail --net=bingo
351 firejail --net=loopback
361 firejail --net=lo #invalid network device
371 firejail --net=/br0 exit
381 firejail --net=br0 --net=br1 --net=br2 --net=br3 --net=br4 exit # only 4 networks allowed
390 firejail --net=eth0 exit
401 firejail --net=/dev/eth0 exit
411 firejail --net=br0 --net=br1 --net=/dev/eth0 exit
420 firejail --net=br0 --net=br0 exit # same device twice
430 firejail --net=eth0 --net=br2 --net=br3 --net=eth0 exit # same device twice
440 firejail --net=eth0 --net=br0 exit
45
46# private mode
470 firejail --private exit
481 firejail --private=/etc sleep 1
491 firejail --private=bingo sleep 1
diff --git a/test/test.sh b/test/test.sh
new file mode 100755
index 000000000..5fe01eb2a
--- /dev/null
+++ b/test/test.sh
@@ -0,0 +1,329 @@
1#!/bin/bash
2
3./chk_config.exp
4
5./fscheck.sh
6
7echo "TESTING: version"
8./option_version.exp
9
10echo "TESTING: help"
11./option_help.exp
12
13echo "TESTING: man"
14./option_man.exp
15
16echo "TESTING: list"
17./option_list.exp
18
19echo "TESTING: tree"
20./option_tree.exp
21
22if [ -f /proc/self/uid_map ];
23then
24 echo "TESTING: noroot"
25 ./noroot.exp
26else
27 echo "TESTING: user namespaces not available"
28fi
29
30echo "TESTING: doubledash"
31mkdir -- -testdir
32touch -- -testdir/ttt
33cp -- /bin/bash -testdir/.
34./doubledash.exp
35rm -fr -- -testdir
36
37echo "TESTING: trace1"
38./option-trace.exp
39
40echo "TESTING: trace2"
41rm -f index.html*
42./trace.exp
43rm -f index.html*
44
45echo "TESTING: extract command"
46./extract_command.exp
47
48echo "TESTING: rlimit"
49./option_rlimit.exp
50
51echo "TESTING: shutdown"
52./option-shutdown.exp
53
54echo "TESTING: join"
55./option-join.exp
56
57echo "TESTING: firejail in firejail"
58./firejail-in-firejail.exp
59
60echo "TESTING: chroot overlay"
61./option_chroot_overlay.exp
62
63echo "TESTING: tmpfs"
64./option_tmpfs.exp
65
66echo "TESTING: blacklist directory"
67./option_blacklist.exp
68
69echo "TESTING: blacklist file"
70./option_blacklist_file.exp
71
72echo "TESTING: bind as user"
73./option_bind_user.exp
74
75if [ -d /home/bingo ];
76then
77 echo "TESTING: home sanitize"
78 ./option_version.exp
79fi
80
81echo "TESTING: chroot as user"
82./fs_chroot.exp
83
84echo "TESTING: /sys"
85./fs_sys.exp
86
87echo "TESTING: readonly"
88ls -al > tmpreadonly
89./option_readonly.exp
90sleep 5
91rm -f tmpreadonly
92
93echo "TESTING: name"
94./name.exp
95
96echo "TESTING: zsh"
97./shell_zsh.exp
98
99echo "TESTING: csh"
100./shell_csh.exp
101
102which dash
103if [ "$?" -eq 0 ];
104then
105 echo "TESTING: dash"
106 ./shell_dash.exp
107else
108 echo "TESTING: dash not found"
109fi
110
111which firefox
112if [ "$?" -eq 0 ];
113then
114 echo "TESTING: firefox"
115 ./firefox.exp
116else
117 echo "TESTING: firefox not found"
118fi
119
120which midori
121if [ "$?" -eq 0 ];
122then
123 echo "TESTING: midori"
124 ./midori.exp
125else
126 echo "TESTING: midori not found"
127fi
128
129which chromium-browser
130if [ "$?" -eq 0 ];
131then
132 echo "TESTING: chromium"
133 ./chromium.exp
134else
135 echo "TESTING: chromium not found"
136fi
137
138which opera
139if [ "$?" -eq 0 ];
140then
141 echo "TESTING: opera"
142 ./opera.exp
143else
144 echo "TESTING: opera not found"
145fi
146
147which transmission-gtk
148if [ "$?" -eq 0 ];
149then
150 echo "TESTING: transmission-gtk"
151 ./transmission-gtk.exp
152else
153 echo "TESTING: transmission-gtk not found"
154fi
155
156which transmission-qt
157if [ "$?" -eq 0 ];
158then
159 echo "TESTING: transmission-qt"
160 ./transmission-qt.exp
161else
162 echo "TESTING: transmission-qt not found"
163fi
164
165which evince
166if [ "$?" -eq 0 ];
167then
168 echo "TESTING: evince"
169 ./evince.exp
170else
171 echo "TESTING: evince not found"
172fi
173
174echo "TESTING: PID"
175./pid.exp
176
177echo "TESTING: output"
178./output.exp
179
180echo "TESTING: profile no permissions"
181./profile_noperm.exp
182
183echo "TESTING: profile syntax"
184./profile_syntax.exp
185
186echo "TESTING: profile syntax 2"
187./profile_syntax2.exp
188
189echo "TESTING: profile rlimit"
190./profile_rlimit.exp
191
192echo "TESTING: profile read-only"
193./profile_readonly.exp
194
195echo "TESTING: profile tmpfs"
196./profile_tmpfs.exp
197
198echo "TESTING: profile applications"
199./profile_apps.exp
200
201echo "TESTING: private"
202./private.exp `whoami`
203
204echo "TESTING: private directory"
205rm -fr dirprivate
206mkdir dirprivate
207./private_dir.exp
208rm -fr dirprivate
209
210echo "TESTING: private directory profile"
211rm -fr dirprivate
212mkdir dirprivate
213./private_dir_profile.exp
214rm -fr dirprivate
215
216echo "TESTING: private keep"
217./private-keep.exp
218
219uname -r | grep "3.18"
220if [ "$?" -eq 0 ];
221then
222 echo "TESTING: overlayfs on 3.18 kernel"
223 ./fs_overlay.exp
224fi
225
226grep "openSUSE" /etc/os-release
227if [ "$?" -eq 0 ];
228then
229 echo "TESTING: overlayfs"
230 ./fs_overlay.exp
231fi
232
233grep "Ubuntu" /etc/os-release
234if [ "$?" -eq 0 ];
235then
236 echo "TESTING: overlayfs"
237 ./fs_overlay.exp
238fi
239
240echo "TESTING: seccomp debug"
241./seccomp-debug.exp
242
243echo "TESTING: seccomp su"
244./seccomp-su.exp
245
246echo "TESTING: seccomp ptrace"
247./seccomp-ptrace.exp
248
249echo "TESTING: seccomp chmod (seccomp lists)"
250./seccomp-chmod.exp
251
252echo "TESTING: seccomp chmod profile (seccomp lists)"
253./seccomp-chmod-profile.exp
254
255echo "TESTING: seccomp empty"
256./seccomp-empty.exp
257
258echo "TESTING: seccomp bad empty"
259./seccomp-bad-empty.exp
260
261echo "TESTING: read/write /var/tmp"
262./fs_var_tmp.exp
263
264echo "TESTING: read/write /var/lock"
265./fs_var_lock.exp
266
267echo "TESTING: read/write /dev/shm"
268./fs_dev_shm.exp
269
270echo "TESTING: local network"
271./net_local.exp
272
273echo "TESTING: no network"
274./net_none.exp
275
276echo "TESTING: network IP"
277./net_ip.exp
278
279echo "TESTING: network MAC"
280./net_mac.exp
281
282echo "TESTING: network bad IP"
283./net_badip.exp
284
285echo "TESTING: network no IP test 1"
286./net_noip.exp
287
288echo "TESTING: network no IP test 2"
289./net_noip2.exp
290
291echo "TESTING: network default gateway test 1"
292./net_defaultgw.exp
293
294echo "TESTING: network default gateway test 2"
295./net_defaultgw2.exp
296
297echo "TESTING: network default gateway test 3"
298./net_defaultgw3.exp
299
300echo "TESTING: netfilter"
301./net_netfilter.exp
302
303echo "TESTING: 4 bridges ARP"
304./4bridges_arp.exp
305
306echo "TESTING: 4 bridges IP"
307./4bridges_ip.exp
308
309echo "TESTING: login SSH"
310./login_ssh.exp
311
312echo "TESTING: ARP"
313./net_arp.exp
314
315echo "TESTING: DNS"
316./dns.exp
317
318echo "TESTING: firemon --arp"
319./firemon-arp.exp
320
321echo "TESTING: firemon --route"
322./firemon-route.exp
323
324echo "TESTING: firemon --seccomp"
325./firemon-seccomp.exp
326
327echo "TESTING: firemon --caps"
328./firemon-caps.exp
329
diff --git a/test/test2.profile b/test/test2.profile
new file mode 100644
index 000000000..d7e1a1f21
--- /dev/null
+++ b/test/test2.profile
@@ -0,0 +1,4 @@
1caps
2seccomp
3 private
4 include test.profile
diff --git a/test/tmpfs.profile b/test/tmpfs.profile
new file mode 100644
index 000000000..0680f4d69
--- /dev/null
+++ b/test/tmpfs.profile
@@ -0,0 +1 @@
tmpfs /tmp/firejailtestdir \ No newline at end of file
diff --git a/test/trace.exp b/test/trace.exp
new file mode 100755
index 000000000..bca3ac3b3
--- /dev/null
+++ b/test/trace.exp
@@ -0,0 +1,95 @@
1#!/usr/bin/expect -f
2
3set timeout 30
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --trace mkdir ttt\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Child process initialized"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "1:mkdir:mkdir ttt"
15}
16sleep 1
17
18send -- "firejail --trace rmdir ttt\r"
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "Child process initialized"
22}
23expect {
24 timeout {puts "TESTING ERROR 3\n";exit}
25 "1:rmdir:rmdir ttt"
26}
27sleep 1
28
29send -- "firejail --trace touch ttt\r"
30expect {
31 timeout {puts "TESTING ERROR 4\n";exit}
32 "Child process initialized"
33}
34expect {
35 timeout {puts "TESTING ERROR 5\n";exit}
36 "1:touch:open ttt" {puts "OK\n";}
37 "1:touch:open64 ttt" {puts "OK\n";}
38}
39sleep 1
40
41send -- "firejail --trace rm ttt\r"
42expect {
43 timeout {puts "TESTING ERROR 6\n";exit}
44 "Child process initialized"
45}
46expect {
47 timeout {puts "TESTING ERROR 7\n";exit}
48 "1:rm:unlinkat ttt"
49}
50sleep 1
51
52send -- "firejail --trace wget -q debian.org\r"
53expect {
54 timeout {puts "TESTING ERROR 8.1\n";exit}
55 "Child process initialized"
56}
57expect {
58 timeout {puts "TESTING ERROR 8.2\n";exit}
59 "1:bash:open /dev/tty" {puts "OK\n";}
60 "1:bash:open64 /dev/tty" {puts "OK\n";}
61}
62expect {
63 timeout {puts "TESTING ERROR 8.3\n";exit}
64 "1:wget:fopen64 /etc/wgetrc" {puts "OK\n";}
65 "1:wget:fopen /etc/wgetrc" {puts "OK\n";}
66}
67expect {
68 timeout {puts "TESTING ERROR 8.4\n";exit}
69 "1:wget:fopen /etc/hosts"
70}
71expect {
72 timeout {puts "TESTING ERROR 8.5\n";exit}
73 "1:wget:connect"
74}
75expect {
76 timeout {puts "TESTING ERROR 8.6\n";exit}
77 "1:wget:fopen64 index.html" {puts "OK\n";}
78 "1:wget:fopen index.html" {puts "OK\n";}
79}
80sleep 1
81
82send -- "firejail --trace rm index.html\r"
83expect {
84 timeout {puts "TESTING ERROR 9\n";exit}
85 "Child process initialized"
86}
87expect {
88 timeout {puts "TESTING ERROR 10\n";exit}
89 "1:rm:unlinkat index.html"
90}
91sleep 1
92
93
94puts "\n"
95
diff --git a/test/transmission-gtk.exp b/test/transmission-gtk.exp
new file mode 100755
index 000000000..7760ae3ad
--- /dev/null
+++ b/test/transmission-gtk.exp
@@ -0,0 +1,68 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail transmission-gtk\r"
8expect {
9 timeout {puts "TESTING ERROR 1\n";exit}
10 "Child process initialized"
11}
12sleep 10
13
14spawn $env(SHELL)
15send -- "firejail --list\r"
16expect {
17 timeout {puts "TESTING ERROR 3\n";exit}
18 ":firejail"
19}
20expect {
21 timeout {puts "TESTING ERROR 3.1\n";exit}
22 "transmission-gtk"
23}
24sleep 1
25
26send -- "firejail --name=blablabla\r"
27expect {
28 timeout {puts "TESTING ERROR 4\n";exit}
29 "Child process initialized"
30}
31sleep 2
32
33spawn $env(SHELL)
34send -- "firemon --seccomp\r"
35expect {
36 timeout {puts "TESTING ERROR 5\n";exit}
37 ":firejail transmission-gtk"
38}
39expect {
40 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
41 "Seccomp: 2"
42}
43expect {
44 timeout {puts "TESTING ERROR 5.1\n";exit}
45 "name=blablabla"
46}
47sleep 1
48send -- "firemon --caps\r"
49expect {
50 timeout {puts "TESTING ERROR 6\n";exit}
51 ":firejail transmission-gtk"
52}
53expect {
54 timeout {puts "TESTING ERROR 6.1\n";exit}
55 "CapBnd"
56}
57expect {
58 timeout {puts "TESTING ERROR 6.2\n";exit}
59 "0000000000000000"
60}
61expect {
62 timeout {puts "TESTING ERROR 6.3\n";exit}
63 "name=blablabla"
64}
65sleep 1
66
67puts "\n"
68
diff --git a/test/transmission-qt.exp b/test/transmission-qt.exp
new file mode 100755
index 000000000..85457aeb8
--- /dev/null
+++ b/test/transmission-qt.exp
@@ -0,0 +1,72 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail transmission-qt\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Reading profile /etc/firejail/transmission-qt.profile"
11}
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "Child process initialized"
15}
16sleep 10
17
18spawn $env(SHELL)
19send -- "firejail --list\r"
20expect {
21 timeout {puts "TESTING ERROR 3\n";exit}
22 ":firejail"
23}
24expect {
25 timeout {puts "TESTING ERROR 3.1\n";exit}
26 "transmission-qt"
27}
28sleep 1
29
30send -- "firejail --name=blablabla\r"
31expect {
32 timeout {puts "TESTING ERROR 4\n";exit}
33 "Child process initialized"
34}
35sleep 2
36
37spawn $env(SHELL)
38send -- "firemon --seccomp\r"
39expect {
40 timeout {puts "TESTING ERROR 5\n";exit}
41 ":firejail transmission-qt"
42}
43expect {
44 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
45 "Seccomp: 2"
46}
47expect {
48 timeout {puts "TESTING ERROR 5.1\n";exit}
49 "name=blablabla"
50}
51sleep 1
52send -- "firemon --caps\r"
53expect {
54 timeout {puts "TESTING ERROR 6\n";exit}
55 ":firejail transmission-qt"
56}
57expect {
58 timeout {puts "TESTING ERROR 6.1\n";exit}
59 "CapBnd"
60}
61expect {
62 timeout {puts "TESTING ERROR 6.2\n";exit}
63 "0000000000000000"
64}
65expect {
66 timeout {puts "TESTING ERROR 6.3\n";exit}
67 "name=blablabla"
68}
69sleep 1
70
71puts "\n"
72