| From: Gokturk Yuksek <gokturk@binghamton.edu> |
| Subject: [PATCH] Fix rngd to open the entropy source with 'O_NOCTTY' flag |
| |
| When start-stop-daemon starts a rngd instance configured to use a tty |
| device as its entropy source, the application crashes due to not being |
| able to read from the entropy device. This is caused by |
| start-stop-daemon calling setsid() before executing rngd, which |
| disassociates the controlling terminal. When rngd attempts to open a |
| hardware entropy source that's a tty device, per POSIX rules, the |
| device becomes the controlling terminal for the process. Then rngd |
| calls daemon(), which internally calls setsid(), and consequently |
| disassociates the controlling terminal for the child. Meanwhile the |
| parent rngd process exits. This results in tty device hanging up. By |
| looking at the strace logs attached to the bug, it can be observed |
| that although the parent rngd process is able to read() from the |
| entropy source successfully, further attempts to read() by the child |
| rngd process return 0. This complies with the POSIX, which states that |
| read() calls on a hung up terminal shall return 0. |
| |
| Note that when rngd is started without start-stop-daemon, this problem |
| does not happen because at the time of opening the entropy source rngd |
| already has a controlling terminal. |
| |
| Prevent the entropy source from becoming the controlling terminal by |
| passing 'O_NOCTTY' flag to open() when opening an entropy source. This |
| flag prevents a tty device from becoming the controlling terminal for |
| a process without a controlling terminal at the time of open(). |
| |
| Thanks to John Bowler <jbowler@acm.org> for debugging the problem and |
| pinpointing the issue as well as confirming the fix. |
| |
| Gentoo-Bug-URL: https://bugs.gentoo.org/556456 |
| Reported-By: John Bowler <jbowler@acm.org> |
| |
| --- rngd_entsource.c |
| +++ rngd_entsource.c |
| @@ -175,7 +175,7 @@ |
| */ |
| int init_entropy_source(struct rng *ent_src) |
| { |
| - ent_src->rng_fd = open(ent_src->rng_name, O_RDONLY); |
| + ent_src->rng_fd = open(ent_src->rng_name, O_RDONLY | O_NOCTTY); |
| if (ent_src->rng_fd == -1) { |
| return 1; |
| } |