public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* do_div() silently truncates "base" to 32bit
@ 2013-08-30 17:21 Anatol Pomozov
  2013-08-30 21:23 ` Randy Dunlap
  2013-10-08 16:10 ` [PATCH] core: Catch overflows in do_div() function Anatol Pomozov
  0 siblings, 2 replies; 15+ messages in thread
From: Anatol Pomozov @ 2013-08-30 17:21 UTC (permalink / raw)
  To: LKML, Tejun Heo, bernie

Hi,


I was debugging weird "zero divide" problem in CFQ code below


static u64 cfqg_prfill_avg_queue_size(struct seq_file *sf,
      struct blkg_policy_data *pd, int off)
{
    struct cfq_group *cfqg = pd_to_cfqg(pd);
    u64 samples = blkg_stat_read(&cfqg->stats.avg_queue_size_samples);
    u64 v = 0;

    if (samples) {
        v = blkg_stat_read(&cfqg->stats.avg_queue_size_sum);
        do_div(v, samples);
    }
    __blkg_prfill_u64(sf, pd, v);
    return 0;
}


do_div() crashes says "zero divide". It is weird because just a few
lines above we check divider for zero.


The problem comes from include/asm-generic/div64.h file that
implements do_div() as macros:

# define do_div(n,base) ({ \
    uint32_t __base = (base); \
    uint32_t __rem; \
    __rem = ((uint64_t)(n)) % __base; \
    (n) = ((uint64_t)(n)) / __base; \
    __rem; \
 })


Do you see the problem?

The problem here is that "base" argument is truncated to 32bit, but in
the function above "sample" is 64bit variable. If sample's 32 low bits
are zero - we have a crash. in fact we have incorrect behavior any
time when high 32bits are non-zero.


My question is why the base is 32bit? Why not to use 64bit arguments?

Ideally if this macros is converted to a function so compiler will
warn us about unexpected truncation like this. But in this case it
will be hard to do as "n" parameter both input and output.

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2013-10-08 17:40 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-30 17:21 do_div() silently truncates "base" to 32bit Anatol Pomozov
2013-08-30 21:23 ` Randy Dunlap
2013-08-30 22:14   ` Anatol Pomozov
2013-08-30 22:48     ` Randy Dunlap
2013-08-30 23:28       ` Joe Perches
2013-08-31  0:50         ` Anatol Pomozov
2013-09-04 15:32           ` Anatol Pomozov
2013-09-04 17:20             ` Randy Dunlap
2013-10-08 16:10 ` [PATCH] core: Catch overflows in do_div() function Anatol Pomozov
2013-10-08 16:18   ` Joe Perches
2013-10-08 16:45     ` Richard Weinberger
2013-10-08 16:51       ` Joe Perches
2013-10-08 17:28       ` Anatol Pomozov
2013-10-08 17:40         ` Anatol Pomozov
2013-10-08 17:15   ` Eric Dumazet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox