]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to ae6f512de8 bcachefs: Fix out of bounds read in fs usage...
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 15 May 2021 18:43:26 +0000 (14:43 -0400)
committerKent Overstreet <kent.overstreet@gmail.com>
Sat, 15 May 2021 18:43:26 +0000 (14:43 -0400)
.bcachefs_revision
libbcachefs/btree_gc.c
libbcachefs/chardev.c
libbcachefs/fs.c
libbcachefs/fsck.c
libbcachefs/opts.c
libbcachefs/super.c

index 80991d76ef07d84bcfb7462670750281eb6ecf2c..20572444402cd4bfbdae1064a2a977f472aed472 100644 (file)
@@ -1 +1 @@
-b6d54265513ceb7532e3983163338c1ad28a0284
+ae6f512de8cdd129ce873e14eab84b8e0746daed
index ec6eb106e5e626bbb353e2ac5ea3c797198b2dbe..b02624992ab6c0a599b22f973e60cd5d6e1b21ad 100644 (file)
@@ -436,7 +436,7 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id,
                                p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
                                bch2_data_types[ptr_data_type(k->k, &p.ptr)],
                                p.ptr.gen)) {
-                       if (p.ptr.cached) {
+                       if (!p.ptr.cached) {
                                g2->_mark.gen   = g->_mark.gen          = p.ptr.gen;
                                g2->gen_valid   = g->gen_valid          = true;
                                set_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags);
@@ -450,7 +450,7 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id,
                                p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
                                bch2_data_types[ptr_data_type(k->k, &p.ptr)],
                                p.ptr.gen, g->mark.gen)) {
-                       if (p.ptr.cached) {
+                       if (!p.ptr.cached) {
                                g2->_mark.gen   = g->_mark.gen  = p.ptr.gen;
                                g2->gen_valid   = g->gen_valid  = true;
                                g2->_mark.data_type             = 0;
index c61601476c0d168a180cad686c6fc788aefaa518..c29f8272e682a4fb9d698c392d2ea04ac694e223 100644 (file)
@@ -414,7 +414,8 @@ static long bch2_ioctl_fs_usage(struct bch_fs *c,
                struct bch_replicas_entry *src_e =
                        cpu_replicas_entry(&c->replicas, i);
 
-               if (replicas_usage_next(dst_e) > dst_end) {
+               /* check that we have enough space for one replicas entry */
+               if (dst_e + 1 > dst_end) {
                        ret = -ERANGE;
                        break;
                }
@@ -523,7 +524,7 @@ static long bch2_ioctl_read_super(struct bch_fs *c,
        ret = copy_to_user((void __user *)(unsigned long)arg.sb,
                           sb, vstruct_bytes(sb));
 err:
-       if (ca)
+       if (!IS_ERR_OR_NULL(ca))
                percpu_ref_put(&ca->ref);
        mutex_unlock(&c->sb_lock);
        return ret;
index b1bbec3f96bd3c5360b8b3b7eb9bddab10857736..4c6568e04a67d4f76bf71ef6626f858e183d3b74 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/posix_acl.h>
 #include <linux/random.h>
 #include <linux/statfs.h>
+#include <linux/string.h>
 #include <linux/xattr.h>
 
 static struct kmem_cache *bch2_inode_cache;
@@ -1311,6 +1312,9 @@ static char **split_devs(const char *_dev_name, unsigned *nr)
        char *dev_name = NULL, **devs = NULL, *s;
        size_t i, nr_devs = 0;
 
+       if (strlen(_dev_name) == 0)
+               return NULL;
+
        dev_name = kstrdup(_dev_name, GFP_KERNEL);
        if (!dev_name)
                return NULL;
index 338d50bec7e5ebdfbd9cf2719ac75754487f7a80..d2697864f5cc185586a2e27a11afbcbf9ab91fe9 100644 (file)
@@ -512,7 +512,9 @@ static int check_inodes(struct bch_fs *c, bool full)
 
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
 
-       for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN, 0, k, ret) {
+       for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN,
+                          BTREE_ITER_INTENT|
+                          BTREE_ITER_PREFETCH, k, ret) {
                if (k.k->type != KEY_TYPE_inode)
                        continue;
 
@@ -621,7 +623,8 @@ static int check_extents(struct bch_fs *c)
 
        iter = bch2_trans_get_iter(&trans, BTREE_ID_extents,
                                   POS(BCACHEFS_ROOT_INO, 0),
-                                  BTREE_ITER_INTENT);
+                                  BTREE_ITER_INTENT|
+                                  BTREE_ITER_PREFETCH);
 retry:
        while ((k = bch2_btree_iter_peek(iter)).k &&
               !(ret = bkey_err(k))) {
@@ -719,7 +722,9 @@ static int check_dirents(struct bch_fs *c)
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
 
        iter = bch2_trans_get_iter(&trans, BTREE_ID_dirents,
-                                  POS(BCACHEFS_ROOT_INO, 0), 0);
+                                  POS(BCACHEFS_ROOT_INO, 0),
+                                  BTREE_ITER_INTENT|
+                                  BTREE_ITER_PREFETCH);
 retry:
        while ((k = bch2_btree_iter_peek(iter)).k &&
               !(ret = bkey_err(k))) {
@@ -920,7 +925,9 @@ static int check_xattrs(struct bch_fs *c)
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
 
        iter = bch2_trans_get_iter(&trans, BTREE_ID_xattrs,
-                                  POS(BCACHEFS_ROOT_INO, 0), 0);
+                                  POS(BCACHEFS_ROOT_INO, 0),
+                                  BTREE_ITER_INTENT|
+                                  BTREE_ITER_PREFETCH);
 retry:
        while ((k = bch2_btree_iter_peek(iter)).k &&
               !(ret = bkey_err(k))) {
@@ -1108,7 +1115,9 @@ static int check_directory_structure(struct bch_fs *c)
 
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
 
-       for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN, 0, k, ret) {
+       for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN,
+                          BTREE_ITER_INTENT|
+                          BTREE_ITER_PREFETCH, k, ret) {
                if (k.k->type != KEY_TYPE_inode)
                        continue;
 
@@ -1207,7 +1216,9 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c,
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
 
        for_each_btree_key(&trans, iter, BTREE_ID_inodes,
-                          POS(0, start), 0, k, ret) {
+                          POS(0, start),
+                          BTREE_ITER_INTENT|
+                          BTREE_ITER_PREFETCH, k, ret) {
                if (k.k->type != KEY_TYPE_inode)
                        continue;
 
@@ -1255,7 +1266,9 @@ static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links
 
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
 
-       for_each_btree_key(&trans, iter, BTREE_ID_dirents, POS_MIN, 0, k, ret) {
+       for_each_btree_key(&trans, iter, BTREE_ID_dirents, POS_MIN,
+                          BTREE_ITER_INTENT|
+                          BTREE_ITER_PREFETCH, k, ret) {
                switch (k.k->type) {
                case KEY_TYPE_dirent:
                        d = bkey_s_c_to_dirent(k);
@@ -1293,7 +1306,9 @@ static int check_nlinks_update_hardlinks(struct bch_fs *c,
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
 
        for_each_btree_key(&trans, iter, BTREE_ID_inodes,
-                          POS(0, range_start), 0, k, ret) {
+                          POS(0, range_start),
+                          BTREE_ITER_INTENT|
+                          BTREE_ITER_PREFETCH, k, ret) {
                if (k.k->p.offset >= range_end)
                        break;
 
index 0cfbb56a57c103211c2761603747f65f17fb41a2..64bf5a382d63574da713321185f626a413c7932f 100644 (file)
@@ -315,11 +315,20 @@ int bch2_opts_check_may_set(struct bch_fs *c)
 int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
                          char *options)
 {
+       char *copied_opts, *copied_opts_start;
        char *opt, *name, *val;
        int ret, id;
        u64 v;
 
-       while ((opt = strsep(&options, ",")) != NULL) {
+       if (!options)
+               return 0;
+
+       copied_opts = kstrdup(options, GFP_KERNEL);
+       if (!copied_opts)
+               return -1;
+       copied_opts_start = copied_opts;
+
+       while ((opt = strsep(&copied_opts, ",")) != NULL) {
                name    = strsep(&opt, "=");
                val     = opt;
 
@@ -363,16 +372,24 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
                bch2_opt_set_by_id(opts, id, v);
        }
 
-       return 0;
+       ret = 0;
+       goto out;
+
 bad_opt:
        pr_err("Bad mount option %s", name);
-       return -1;
+       ret = -1;
+       goto out;
 bad_val:
        pr_err("Invalid value %s for mount option %s", val, name);
-       return -1;
+       ret = -1;
+       goto out;
 no_val:
        pr_err("Mount option %s requires a value", name);
-       return -1;
+       ret = -1;
+       goto out;
+out:
+       kfree(copied_opts_start);
+       return ret;
 }
 
 /* io opts: */
index e5936041b9e2442e7b9d21ba10b998a9c67a4cde..3b1e9203bfcc32a4a623387d4356c9fd56fd05d7 100644 (file)
@@ -110,7 +110,7 @@ struct bch_fs *bch2_dev_to_fs(dev_t dev)
 
        list_for_each_entry(c, &bch_fs_list, list)
                for_each_member_device_rcu(ca, c, i, NULL)
-                       if (ca->disk_sb.bdev->bd_dev == dev) {
+                       if (ca->disk_sb.bdev && ca->disk_sb.bdev->bd_dev == dev) {
                                closure_get(&c->cl);
                                goto found;
                        }