diff --git a/pkg/rngd/Dockerfile b/pkg/rngd/Dockerfile index e877bda5a..0ff49e675 100644 --- a/pkg/rngd/Dockerfile +++ b/pkg/rngd/Dockerfile @@ -1,46 +1,15 @@ -FROM linuxkit/alpine:9bcf61f605ef0ce36cc94d59b8eac307862de6e1 AS mirror -RUN mkdir -p /out/etc/apk && cp -r /etc/apk/* /out/etc/apk/ -RUN apk add --no-cache --initdb -p /out \ - tini -RUN rm -rf /out/etc/apk /out/lib/apk /out/var/cache -RUN mkdir -p /out/dev /out/proc /out/sys +FROM linuxkit/alpine:c23813875499d85163dc358fc6370c9de650df57 AS mirror -FROM linuxkit/alpine:9bcf61f605ef0ce36cc94d59b8eac307862de6e1 AS build -RUN apk add \ - argp-standalone \ - automake \ - curl \ - gcc \ - linux-headers \ - make \ - musl-dev \ - patch +RUN apk add --no-cache go gcc musl-dev linux-headers +ENV GOPATH=/go PATH=$PATH:/go/bin -COPY . / - -ENV pkgname=rng-tools pkgver=5 - -RUN curl -fSL "http://downloads.sourceforge.net/project/gkernel/$pkgname/$pkgver/$pkgname-$pkgver.tar.gz" -o "$pkgname-$pkgver.tar.gz" -RUN sha256sum -c sha256sums -RUN zcat $pkgname-$pkgver.tar.gz | tar xf - - -RUN cd $pkgname-$pkgver && for p in ../*.patch; do cat $p | patch -p1; done - -RUN cd $pkgname-$pkgver && \ - export LIBS="-largp" && \ - LDFLAGS=-static ./configure \ - --prefix=/usr \ - --libexecdir=/usr/lib/rng-tools \ - --sysconfdir=/etc \ - --disable-silent-rules && \ - make && \ - make DESTDIR=/ install && \ - strip /usr/sbin/rngd +COPY cmd/rngd/*.go /go/src/rngd/ +RUN REQUIRE_CGO=1 go-compile.sh /go/src/rngd FROM scratch ENTRYPOINT [] +CMD [] WORKDIR / -COPY --from=mirror /out/ / -COPY --from=build usr/sbin/rngd usr/sbin/rngd -CMD ["/sbin/tini", "/usr/sbin/rngd", "-f"] +COPY --from=mirror /go/bin/rngd /sbin/rngd +CMD ["/sbin/rngd"] LABEL org.mobyproject.config='{"capabilities": ["CAP_SYS_ADMIN"], "oomScoreAdj": -800, "readonly": true, "net": "new", "ipc": "new"}' diff --git a/pkg/rngd/Makefile b/pkg/rngd/Makefile index c37ede3ef..ed48b44aa 100644 --- a/pkg/rngd/Makefile +++ b/pkg/rngd/Makefile @@ -1,4 +1,4 @@ IMAGE=rngd -NETWORK=1 +DEPS=$(wildcard cmd/rngd/*.go) include ../package.mk diff --git a/pkg/rngd/cmd/rngd/main.go b/pkg/rngd/cmd/rngd/main.go new file mode 100644 index 000000000..31708e261 --- /dev/null +++ b/pkg/rngd/cmd/rngd/main.go @@ -0,0 +1,66 @@ +package main + +import ( + "log" + "os" + "syscall" +) + +func main() { + oneshot := len(os.Args) > 1 && os.Args[1] == "-1" + + timeout := -1 + if oneshot { + timeout = 0 + } + + supported := initRand() + if !supported { + log.Fatalf("No random source available") + } + + random, err := os.Open("/dev/random") + if err != nil { + log.Fatalf("Cannot open /dev/random: %v", err) + } + defer random.Close() + fd := int(random.Fd()) + + epfd, err := syscall.EpollCreate1(0) + if err != nil { + log.Fatalf("epoll create error: %v", err) + } + defer syscall.Close(epfd) + + var event syscall.EpollEvent + var events [1]syscall.EpollEvent + + event.Events = syscall.EPOLLOUT + event.Fd = int32(fd) + if err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil { + log.Fatalf("epoll add error: %v", err) + } + + count := 0 + + for { + // write some entropy + n, err := writeEntropy(random) + if err != nil { + log.Fatalf("write entropy: %v", err) + } + count += n + // sleep until we can write more + nevents, err := syscall.EpollWait(epfd, events[:], timeout) + if err != nil { + log.Fatalf("epoll wait error: %v", err) + } + if nevents == 1 && events[0].Events&syscall.EPOLLOUT == syscall.EPOLLOUT { + continue + } + if oneshot { + log.Printf("Wrote %d bytes of entropy, exiting as oneshot\n", count) + break + } + } +} diff --git a/pkg/rngd/cmd/rngd/rng_amd64.go b/pkg/rngd/cmd/rngd/rng_amd64.go new file mode 100644 index 000000000..eeddc71a3 --- /dev/null +++ b/pkg/rngd/cmd/rngd/rng_amd64.go @@ -0,0 +1,84 @@ +package main + +// #cgo CFLAGS: -mrdrnd -mrdseed +// #include +// #include +// #include +// #include +// #include +// #include +// +// int hasrdrand() { +// unsigned int eax, ebx, ecx, edx; +// __get_cpuid(1, &eax, &ebx, &ecx, &edx); +// +// return ((ecx & bit_RDRND) == bit_RDRND); +// } +// +// int hasrdseed() { +// unsigned int eax, ebx, ecx, edx; +// __get_cpuid(7, &eax, &ebx, &ecx, &edx); +// +// return ((ebx & bit_RDSEED) == bit_RDSEED); +// } +// +// int rdrand(uint64_t *val) { +// return _rdrand64_step((unsigned long long *)val); +// } +// +// int rdseed(uint64_t *val) { +// return _rdseed64_step((unsigned long long *)val); +// } +// +// int rndaddentropy = RNDADDENTROPY; +// +import "C" + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +var hasRdrand, hasRdseed bool + +type randInfo struct { + entropyCount int + size int + buf uint64 +} + +func initRand() bool { + hasRdrand = C.hasrdrand() == 1 + hasRdseed = C.hasrdseed() == 1 + return hasRdrand || hasRdseed +} + +func rand() (uint64, error) { + var x C.uint64_t + // prefer rdseed as that is correct seed + if hasRdseed && C.rdseed(&x) == 1 { + return uint64(x), nil + } + // failed rdseed, rdrand better than nothing + if hasRdrand && C.rdrand(&x) == 1 { + return uint64(x), nil + } + return 0, errors.New("No randomness available") +} + +func writeEntropy(random *os.File) (int, error) { + r, err := rand() + if err != nil { + // assume can fail occasionally + return 0, nil + } + const entropy = 64 // they are good random numbers, Brent + info := randInfo{entropy, 8, r} + ret, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(random.Fd()), uintptr(C.rndaddentropy), uintptr(unsafe.Pointer(&info))) + if ret == 0 { + return 8, nil + } + return 0, err +} diff --git a/pkg/rngd/cmd/rngd/rng_unsupported.go b/pkg/rngd/cmd/rngd/rng_unsupported.go new file mode 100644 index 000000000..e5bbc79d2 --- /dev/null +++ b/pkg/rngd/cmd/rngd/rng_unsupported.go @@ -0,0 +1,13 @@ +// +build !amd64 + +package main + +import "errors" + +func initRand() bool { + return false +} + +func rand() (uint64, error) { + return 0, errors.New("No rng available") +} diff --git a/pkg/rngd/fix-textrels-on-PIC-x86.patch b/pkg/rngd/fix-textrels-on-PIC-x86.patch deleted file mode 100644 index 7ea76d6fd..000000000 --- a/pkg/rngd/fix-textrels-on-PIC-x86.patch +++ /dev/null @@ -1,50 +0,0 @@ ---- rng-tools/rdrand_asm.S -+++ rng-tools/rdrand_asm.S -@@ -49,6 +49,7 @@ - ret - ENDPROC(x86_rdrand_nlong) - -+#define INIT_PIC() - #define SETPTR(var,ptr) leaq var(%rip),ptr - #define PTR0 %rdi - #define PTR1 %rsi -@@ -84,7 +85,16 @@ - ret - ENDPROC(x86_rdrand_nlong) - -+#if defined(__PIC__) -+#undef __i686 /* gcc builtin define gets in our way */ -+#define INIT_PIC() \ -+ call __i686.get_pc_thunk.bx ; \ -+ addl $_GLOBAL_OFFSET_TABLE_, %ebx -+#define SETPTR(var,ptr) leal (var)@GOTOFF(%ebx),ptr -+#else -+#define INIT_PIC() - #define SETPTR(var,ptr) movl $(var),ptr -+#endif - #define PTR0 %eax - #define PTR1 %edx - #define PTR2 %ecx -@@ -101,6 +111,7 @@ - movl 8(%ebp), %eax - movl 12(%ebp), %edx - #endif -+ INIT_PIC() - - SETPTR(aes_round_keys, PTR2) - -@@ -166,6 +177,17 @@ - #endif - ret - ENDPROC(x86_aes_mangle) -+ -+#if defined(__i386__) && defined(__PIC__) -+ .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits -+.globl __i686.get_pc_thunk.bx -+ .hidden __i686.get_pc_thunk.bx -+ .type __i686.get_pc_thunk.bx,@function -+__i686.get_pc_thunk.bx: -+ movl (%esp), %ebx -+ ret -+#endif -+ diff --git a/pkg/rngd/sha256sums b/pkg/rngd/sha256sums deleted file mode 100644 index 8416a085c..000000000 --- a/pkg/rngd/sha256sums +++ /dev/null @@ -1 +0,0 @@ -60a102b6603bbcce2da341470cad42eeaa9564a16b4490e7867026ca11a3078e rng-tools-5.tar.gz