From: Gerrit Renker Date: Sun, 3 Dec 2006 16:52:26 +0000 (-0200) Subject: [DCCP] tfrc: Add protection against invalid parameters to TFRC routines X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=8d0086adac0041de66b5f41b77eec0d8d239e16c;p=openwrt%2Fstaging%2Fblogic.git [DCCP] tfrc: Add protection against invalid parameters to TFRC routines 1) For the forward X_calc lookup, it * protects effectively against RTT=0 (this case is possible), by returning the maximal lookup value instead of just setting it to 1 * reformulates the array-bounds exceeded condition: this only happens if p is greater than 1E6 (due to the scaling) * the case of negative indices can now with certainty be excluded, since documentation shows that the formulas are within bounds * additional protection against p = 0 (would give divide-by-zero) 2) For the reverse lookup, it warns against * protects against exceeding array bounds * now returns 0 if f(p) = 0, due to function definition * warns about minimal resolution error and returns the smallest table value instead of p=0 [this would mask congestion conditions] Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index 78bdf3489162..ef3233d45a61 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c @@ -608,22 +608,19 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) u32 f; u64 tmp1, tmp2; + /* check against invalid parameters and divide-by-zero */ + BUG_ON(p > 1000000); /* p must not exceed 100% */ + BUG_ON(p == 0); /* f(0) = 0, divide by zero */ + if (R == 0) { /* possible divide by zero */ + DCCP_CRIT("WARNING: RTT is 0, returning maximum X_calc."); + return ~0U; + } + if (p < TFRC_CALC_X_SPLIT) /* 0 <= p < 0.05 */ index = (p / (TFRC_CALC_X_SPLIT / TFRC_CALC_X_ARRSIZE)) - 1; else /* 0.05 <= p <= 1.00 */ index = (p / (1000000 / TFRC_CALC_X_ARRSIZE)) - 1; - if (index < 0) - /* p should be 0 unless there is a bug in my code */ - index = 0; - - if (R == 0) { - DCCP_WARN("RTT==0, setting to 1\n"); - R = 1; /* RTT can't be zero or else divide by zero */ - } - - BUG_ON(index >= TFRC_CALC_X_ARRSIZE); - if (p >= TFRC_CALC_X_SPLIT) f = tfrc_calc_x_lookup[index][0]; else @@ -653,13 +650,21 @@ u32 tfrc_calc_x_reverse_lookup(u32 fvalue) int ctr = 0; int small; - if (fvalue < tfrc_calc_x_lookup[0][1]) + if (fvalue == 0) /* f(p) = 0 whenever p = 0 */ return 0; + /* Error cases. */ + if (fvalue < tfrc_calc_x_lookup[0][1]) { + DCCP_WARN("fvalue %d smaller than resolution\n", fvalue); + return tfrc_calc_x_lookup[0][1]; + } + if (fvalue > tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][0]) { + DCCP_WARN("fvalue %d exceeds bounds!\n", fvalue); + return 1000000; + } + if (fvalue <= tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][1]) small = 1; - else if (fvalue > tfrc_calc_x_lookup[TFRC_CALC_X_ARRSIZE - 1][0]) - return 1000000; else small = 0;