Re: [PATCH 5.14 018/334] nbd: add the check to prevent overflow in __nbd_ioctl()

From: libaokun (A)
Date: Mon Sep 13 2021 - 22:13:31 EST


在 2021/9/14 7:23, Nick Desaulniers 写道:
On Mon, Sep 13, 2021 at 4:00 PM Linus Torvalds
<torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
On Mon, Sep 13, 2021 at 2:15 PM Nick Desaulniers
<ndesaulniers@xxxxxxxxxx> wrote:
Sorry wrong diff:
Well, this second diff was seriously whitespace-damaged and hard to
read, but while it seems to be the same number of lines, it sure looks
a lot more readable in this format.

Except I think that

default: dividend / divisor);

should really have parentheses around both of those macro arguments.

That's a preexisting problem, but it should be fixed while at it.
Ok, I'll send a revised v2 based on _Generic; Rasmus can help review
when he's awake.

I'm also not sure why that (again, preexisting) BUILD_BUG_ON_MSG()
only checks the size of the dividend, not the divisor. Very strange.
But probably not worth worrying about.
I sent a not-yet-applied diff of my not-yet-applied diff. I was
playing with this last week, and IIRC we had divisors that were less
than 32b being promoted to int. But I'll test it some more.

How about deleting the check_mul_overflow in the __nbd_ioctl as follows?

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 5170a630778d..f404e0540476 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1393,7 +1393,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                       unsigned int cmd, unsigned long arg)
 {
        struct nbd_config *config = nbd->config;
-       loff_t bytesize;

        switch (cmd) {
        case NBD_DISCONNECT:
@@ -1408,9 +1407,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
        case NBD_SET_SIZE:
                return nbd_set_size(nbd, arg, config->blksize);
        case NBD_SET_SIZE_BLOCKS:
-               if (check_mul_overflow((loff_t)arg, config->blksize, &bytesize))
+               if (arg && (LLONG_MAX / arg <= config->blksize))
                        return -EINVAL;
-               return nbd_set_size(nbd, bytesize, config->blksize);
+               return nbd_set_size(nbd, arg * config->blksize,
+                                   config->blksize);
        case NBD_SET_TIMEOUT:
                nbd_set_cmd_timeout(nbd, arg);
                return 0;
--
2.31.1

--
With Best Regards,
Baokun Li