From 011062967ab28b8c1cd9903570d67e04f67e4a45 Mon Sep 17 00:00:00 2001 From: WenMing Date: Fri, 18 Jan 2019 00:21:25 +0800 Subject: [PATCH 1/3] bugfix: fixed duplicated seeds. ngx.time() + ngx.worker.pid() maybe get duplicated seeds. get from /dev/urandom first. --- rootfs/etc/nginx/lua/lua_ingress.lua | 31 +++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/rootfs/etc/nginx/lua/lua_ingress.lua b/rootfs/etc/nginx/lua/lua_ingress.lua index f0d33db81..b751b2214 100644 --- a/rootfs/etc/nginx/lua/lua_ingress.lua +++ b/rootfs/etc/nginx/lua/lua_ingress.lua @@ -2,25 +2,40 @@ local _M = {} local seeds = {} local original_randomseed = math.randomseed -math.randomseed = function(seed) - local pid = ngx.worker.pid() - if seeds[pid] then +local function get_seed_from_urandom() + local seed + local frandom = io.open("/dev/urandom", "rb") + if frandom then + local str = frandom:read(4) + frandom:close() + seed = 0 + for i = 1, 4 do + seed = 256 * seed + str:byte(i) + end + end + return seed +end + +math.randomseed = function() + local pid = ngx.worker.pid() + local seed = seeds[pid] + if seed then ngx.log(ngx.WARN, string.format("ignoring math.randomseed(%d) since PRNG is already seeded for worker %d", seed, pid)) return end + seed = get_seed_from_urandom() + if not seed then + seed = ngx.now() * 1000 + pid + end original_randomseed(seed) seeds[pid] = seed end -local function randomseed() - math.randomseed(ngx.time() + ngx.worker.pid()) -end - function _M.init_worker() - randomseed() + math.randomseed() end return _M From c782f22c5d8c7e6c1ded62f704dfd523f9e5e2e1 Mon Sep 17 00:00:00 2001 From: WenMing Date: Fri, 18 Jan 2019 10:08:33 +0800 Subject: [PATCH 2/3] fixed test case for math.randomseed. --- rootfs/etc/nginx/lua/lua_ingress.lua | 2 +- rootfs/etc/nginx/lua/test/lua_ingress_test.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rootfs/etc/nginx/lua/lua_ingress.lua b/rootfs/etc/nginx/lua/lua_ingress.lua index b751b2214..0dab84226 100644 --- a/rootfs/etc/nginx/lua/lua_ingress.lua +++ b/rootfs/etc/nginx/lua/lua_ingress.lua @@ -22,7 +22,7 @@ math.randomseed = function() local seed = seeds[pid] if seed then ngx.log(ngx.WARN, - string.format("ignoring math.randomseed(%d) since PRNG is already seeded for worker %d", seed, pid)) + string.format("ignoring math.randomseed() since PRNG is already seeded for worker %d", pid)) return end diff --git a/rootfs/etc/nginx/lua/test/lua_ingress_test.lua b/rootfs/etc/nginx/lua/test/lua_ingress_test.lua index 89d3150ef..fc983a872 100644 --- a/rootfs/etc/nginx/lua/test/lua_ingress_test.lua +++ b/rootfs/etc/nginx/lua/test/lua_ingress_test.lua @@ -2,8 +2,8 @@ describe("lua_ingress", function() it("patches math.randomseed to not be called more than once per worker", function() local s = spy.on(ngx, "log") - math.randomseed(100) + math.randomseed() assert.spy(s).was_called_with(ngx.WARN, - string.format("ignoring math.randomseed(%d) since PRNG is already seeded for worker %d", 100, ngx.worker.pid())) + string.format("ignoring math.randomseed() since PRNG is already seeded for worker %d", ngx.worker.pid())) end) end) From 8ea7501d8b4f14b748ef2c8d00e617ca16c43b9a Mon Sep 17 00:00:00 2001 From: WenMing Date: Mon, 21 Jan 2019 17:26:52 +0800 Subject: [PATCH 3/3] added more error info and keep test cases. --- rootfs/etc/nginx/lua/lua_ingress.lua | 47 ++++++++++++------- .../etc/nginx/lua/test/lua_ingress_test.lua | 4 +- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/rootfs/etc/nginx/lua/lua_ingress.lua b/rootfs/etc/nginx/lua/lua_ingress.lua index 0dab84226..35077f9d8 100644 --- a/rootfs/etc/nginx/lua/lua_ingress.lua +++ b/rootfs/etc/nginx/lua/lua_ingress.lua @@ -5,37 +5,50 @@ local original_randomseed = math.randomseed local function get_seed_from_urandom() local seed - local frandom = io.open("/dev/urandom", "rb") - if frandom then - local str = frandom:read(4) - frandom:close() - seed = 0 - for i = 1, 4 do - seed = 256 * seed + str:byte(i) - end + local frandom, err = io.open("/dev/urandom", "rb") + if not frandom then + ngx.log(ngx.WARN, 'failed to open /dev/urandom: ', err) + return nil end + + local str = frandom:read(4) + frandom:close() + if not str then + ngx.log(ngx.WARN, 'failed to read data from /dev/urandom') + return nil + end + + seed = 0 + for i = 1, 4 do + seed = 256 * seed + str:byte(i) + end + return seed end -math.randomseed = function() +math.randomseed = function(seed) local pid = ngx.worker.pid() - local seed = seeds[pid] - if seed then + if seeds[pid] then ngx.log(ngx.WARN, - string.format("ignoring math.randomseed() since PRNG is already seeded for worker %d", pid)) + string.format("ignoring math.randomseed(%d) since PRNG is already seeded for worker %d", seed, pid)) return end - seed = get_seed_from_urandom() - if not seed then - seed = ngx.now() * 1000 + pid - end original_randomseed(seed) seeds[pid] = seed end +local function randomseed() + local seed = get_seed_from_urandom() + if not seed then + ngx.log(ngx.WARN, 'failed to get seed from urandom') + seed = ngx.now() * 1000 + ngx.worker.pid() + end + math.randomseed(seed) +end + function _M.init_worker() - math.randomseed() + randomseed() end return _M diff --git a/rootfs/etc/nginx/lua/test/lua_ingress_test.lua b/rootfs/etc/nginx/lua/test/lua_ingress_test.lua index fc983a872..89d3150ef 100644 --- a/rootfs/etc/nginx/lua/test/lua_ingress_test.lua +++ b/rootfs/etc/nginx/lua/test/lua_ingress_test.lua @@ -2,8 +2,8 @@ describe("lua_ingress", function() it("patches math.randomseed to not be called more than once per worker", function() local s = spy.on(ngx, "log") - math.randomseed() + math.randomseed(100) assert.spy(s).was_called_with(ngx.WARN, - string.format("ignoring math.randomseed() since PRNG is already seeded for worker %d", ngx.worker.pid())) + string.format("ignoring math.randomseed(%d) since PRNG is already seeded for worker %d", 100, ngx.worker.pid())) end) end)