libceph: set -EINVAL in one place in crush_decode()
authorIlya Dryomov <idryomov@gmail.com>
Thu, 13 Jul 2017 13:57:26 +0000 (15:57 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 17 Jul 2017 12:54:58 +0000 (14:54 +0200)
No sooner than Dan had fixed this issue in commit 293dffaad8d5
("libceph: NULL deref on crush_decode() error path"), I brought it
back.  Add a new label and set -EINVAL once, right before failing.

Fixes: 278b1d709c6a ("libceph: ceph_decode_skip_* helpers")
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
net/ceph/osdmap.c

index 3ffc7a1fd8b1585ab6bec549490e9d89185e0825..48e0ff82bde2236910d7eea2a99d8041b1590937 100644 (file)
@@ -338,7 +338,7 @@ static void crush_finalize(struct crush_map *c)
 static struct crush_map *crush_decode(void *pbyval, void *end)
 {
        struct crush_map *c;
-       int err = -EINVAL;
+       int err;
        int i, j;
        void **p = &pbyval;
        void *start = pbyval;
@@ -407,7 +407,6 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
                        size = sizeof(struct crush_bucket_straw2);
                        break;
                default:
-                       err = -EINVAL;
                        goto bad;
                }
                BUG_ON(size == 0);
@@ -439,31 +438,31 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
                        err = crush_decode_uniform_bucket(p, end,
                                  (struct crush_bucket_uniform *)b);
                        if (err < 0)
-                               goto bad;
+                               goto fail;
                        break;
                case CRUSH_BUCKET_LIST:
                        err = crush_decode_list_bucket(p, end,
                               (struct crush_bucket_list *)b);
                        if (err < 0)
-                               goto bad;
+                               goto fail;
                        break;
                case CRUSH_BUCKET_TREE:
                        err = crush_decode_tree_bucket(p, end,
                                (struct crush_bucket_tree *)b);
                        if (err < 0)
-                               goto bad;
+                               goto fail;
                        break;
                case CRUSH_BUCKET_STRAW:
                        err = crush_decode_straw_bucket(p, end,
                                (struct crush_bucket_straw *)b);
                        if (err < 0)
-                               goto bad;
+                               goto fail;
                        break;
                case CRUSH_BUCKET_STRAW2:
                        err = crush_decode_straw2_bucket(p, end,
                                (struct crush_bucket_straw2 *)b);
                        if (err < 0)
-                               goto bad;
+                               goto fail;
                        break;
                }
        }
@@ -474,7 +473,6 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
                u32 yes;
                struct crush_rule *r;
 
-               err = -EINVAL;
                ceph_decode_32_safe(p, end, yes, bad);
                if (!yes) {
                        dout("crush_decode NO rule %d off %x %p to %p\n",
@@ -489,7 +487,6 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
                /* len */
                ceph_decode_32_safe(p, end, yes, bad);
 #if BITS_PER_LONG == 32
-               err = -EINVAL;
                if (yes > (ULONG_MAX - sizeof(*r))
                          / sizeof(struct crush_rule_step))
                        goto bad;
@@ -557,7 +554,7 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
        if (*p != end) {
                err = decode_choose_args(p, end, c);
                if (err)
-                       goto bad;
+                       goto fail;
        }
 
 done:
@@ -567,10 +564,14 @@ done:
 
 badmem:
        err = -ENOMEM;
-bad:
+fail:
        dout("crush_decode fail %d\n", err);
        crush_destroy(c);
        return ERR_PTR(err);
+
+bad:
+       err = -EINVAL;
+       goto fail;
 }
 
 int ceph_pg_compare(const struct ceph_pg *lhs, const struct ceph_pg *rhs)