aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2021-03-10 16:20:54 +0100
committerMartin Schanzenbach <mschanzenbach@posteo.de>2021-03-10 16:20:54 +0100
commitc3bf63a41d68549b769d465205050c1a271dfb67 (patch)
treec268b5709f3d964641f28d097d21f0a3367968cc
parent3ea16c9f3a9d945c5d60cac95dc9b01664bc0c96 (diff)
downloadwww-c3bf63a41d68549b769d465205050c1a271dfb67.tar.gz
www-c3bf63a41d68549b769d465205050c1a271dfb67.zip
import some old news posts
-rw-r--r--news/2011-11-24-archived-vfork.html.j262
-rw-r--r--news/2013-12-28-archived-typos-pkeys.html.j216
l---------news/oldnews-2011.html.j21
l---------news/oldnews-2013.html.j21
4 files changed, 80 insertions, 0 deletions
diff --git a/news/2011-11-24-archived-vfork.html.j2 b/news/2011-11-24-archived-vfork.html.j2
new file mode 100644
index 00000000..61249c38
--- /dev/null
+++ b/news/2011-11-24-archived-vfork.html.j2
@@ -0,0 +1,62 @@
1{% extends "common/news.j2" %}
2{% block body_content %}
3 <h1>vfork and the signal race</h1>
4<p>
5 <b>This is an imported news item from the old Drupal GNUnet homepage.</b>
6</p>
7<p>
8Many articles uniformly claim that using vfork should be
9<a href="https://web.archive.org/web/20150924082249/http://tldp.org/HOWTO/Secure-Programs-HOWTO/avoid-vfork.html">avoided</a>
10and that the only difference between vfork and fork is (or used-to-be)
11<a href="https://web.archive.org/web/20150924082249/http://www.unixguide.net/unix/programming/1.1.2.shtml">performance</a>
12and that thus vfork is
13<a href="https://web.archive.org/web/20150924082249/http://stackoverflow.com/questions/4856255/the-difference-between-fork-vfork-exec-and-clone">obsolete</a>.
14Here, I wanted to document a technical case where vfork is actually required and where using fork instead of vfork (or operating system implementors implementing vfork as an alias for fork) causes a hard-to-find data race.
15</p>
16<p>
17GNUnet uses a hypervisor process (gnunet-service-arm) to control the peer's service processes. Services are started (vfork+exec) on-demand. The hypervisor is also responsible for stopping the services and sends a SIGTERM signal to the services to stop them. SIGTERM must be used to allow the services to shutdown gracefully. Naturally, after shutting down a service with a signal, the hypervisor waits for SIGCHILD and then cleans up with waitpid. Once all services processes have completed, the hypervisor can exit as well. It should also be noted that the hypervisor handles SIGTERM (by shutting down all services), so a signal handler is installed for that signal.
18</p>
19<p>
20The reason why we must use vfork is the following. After the hypervisor has started the service, it might be asked to stop the service at any time. We've actually managed (by scripting it) to reliably trigger a case where the hypervisor would start a service (fork) and then receive a request to terminate the service and issues the SIGTERM signal to the child before the child process had a chance to call exec. As a result, the SIGTERM would go to the (existing) handler of the hypervisor's code, then the child process would be exec'ed and essentially the signal was thereby lost in the race between kill and exec:
21</p>
22<p>
23If exec wins, the signal either kills the process hard during the service startup phase, which is fine, or the service process might handle it normally and terminate --- also fine).
24</p>
25<p>
26If kill wins the race, the signal would be lost and the hypervisor would wait 'forever' for the child to terminate.
27</p>
28<p>
29The solution with vfork is elegant and simple: by blocking the parent, vexec guarantees that the parent's signal handler is no longer active (and replaced by default handlers or the child's custom handlers) by the time the parent is able to issue a 'kill'.
30</p>
31<p>
32In conclusion, with parents that issue 'kill' on child processes, the use of vfork can make an important semantic difference and not only (possibly) offer performance advantages. The situation above cannot be easily fixed by other means and thus vfork is an important POSIX call that should be supported properly by all quality implementations. A possible hack to work around a lack of vfork would be to create a pipe in the parent, set it to close-on-exec, fork the child, close the write end and then do a blocking read from the read end. Once you get a read error, the child has exec'ed. Rather ugly in my opinion.
33</p>
34<p>
35Currently, gnunet-service-arm can hang indefinitely on systems that do not provide a correct implementation of vfork (however, in practice normal users should never encounter this).
36</p>
37<p>
38<b>better suggestion from Thomas Bushnell</b>
39<br>
40I just got an alternative suggestion to using either a pipe and vfork from Thomas Bushnell, which I like and will use:
41
42"The hypervisor at start creates a global variable hypervisor_pid, initialized from getpid().
43
44The signal handler in the hypervisor then does this:
45<br>
46<code class="block">
47if getpid() == hypervisor_pid<br>
48 kill_all_children_and_exit();<br>
49else<br>
50 exit();<br>
51</code>
52
53In this way, if the child is between fork and exec when the parent gets its kill, and then it tries to kill the child, and the kill happens before the child execs (the problematic case you describe), then the child simply enters the hypervisor's signal handler, notices that it's not the hypervisor, and exits.
54<br>
55Thomas"
56<br>
57Thanks for the suggestion!
58</p>
59<p>
60Thomas's suggestion is all fine and well, except that it doesn't work on OS X. As the attached simple program "killing-child-kills-parent.c" demonstrates, OS X manages to sometimes either deliver the signal to the wrong process (?) or not update getpid() between fork+exec or is otherwise generally broken. The program simply installs a signal handler in the parent with the guard suggested by Thomas, then forks + exec's "sleep" and then immediately kills the child. So we expect the signal to either reach our signal handler (child between fork+exec), causing the child to 'exit', or to reach 'sleep' which should also die. Somehow instead the "Should NEVER get this signal!" message is printed. Well, OS X is known to be a pile of crap, so no surprise. Using 'vfork' instead of fork gets us the desired behavor -- howver, this is clearly just a hack. So vfork is back (on OS X) as of SVN 25495.
61</p>
62{% endblock body_content %}
diff --git a/news/2013-12-28-archived-typos-pkeys.html.j2 b/news/2013-12-28-archived-typos-pkeys.html.j2
new file mode 100644
index 00000000..a541ef94
--- /dev/null
+++ b/news/2013-12-28-archived-typos-pkeys.html.j2
@@ -0,0 +1,16 @@
1{% extends "common/news.j2" %}
2{% block body_content %}
3 <h1>Typo-Protected Public Keys</h1>
4<p>
5 <b>This is an imported news item from the old Drupal GNUnet homepage.</b>
6</p>
7<p>
8When users type in public keys (such as the 53-characters of a GNS zone), they might make typos. The usual way to fix typos is to add a checksum, further increasing the length of the sequence that has to be typed in.
9<br>
10We can fix this by including the checksum of the public key in the public key itself, simply by trying new private keys until the corresponding public key happens to have a checksum (over the other bits) in the bits designated for the checksum. If a checksum is 16 bits, we would only need to try 216 keys. The basic idea of brute-forcing keys to match a particular pattern <a href="https://web.archive.org/web/20141008173738/https://bitcointalk.org/index.php?topic=84569.0">was proposed before</a> for creating "vanity" public keys, but this might be another practical variant.
11</p>
12<p>
13<b>Acknowledgements</b><br/>
14The idea popped up in a discussion on the need for short public keys for GNS with Dan Bernstein and Tanja Lange at 30c3.
15</p>
16{% endblock body_content %}
diff --git a/news/oldnews-2011.html.j2 b/news/oldnews-2011.html.j2
new file mode 120000
index 00000000..ef5fcbee
--- /dev/null
+++ b/news/oldnews-2011.html.j2
@@ -0,0 +1 @@
oldnews-2018.html.j2 \ No newline at end of file
diff --git a/news/oldnews-2013.html.j2 b/news/oldnews-2013.html.j2
new file mode 120000
index 00000000..ef5fcbee
--- /dev/null
+++ b/news/oldnews-2013.html.j2
@@ -0,0 +1 @@
oldnews-2018.html.j2 \ No newline at end of file