[bug report] btrfs: hold a ref on the root in btrfs_search_path_in_tree_user

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[ It's weird that I haven't reported before...  - dan ]

Hello Josef Bacik,

The patch d8359e551d00: "btrfs: hold a ref on the root in
btrfs_search_path_in_tree_user" from Jan 24, 2020, leads to the
following static checker warning:

	fs/btrfs/ioctl.c:2534 btrfs_search_path_in_tree_user()
	error: uninitialized symbol 'root'.

fs/btrfs/ioctl.c
  2374  static int btrfs_search_path_in_tree_user(struct inode *inode,
  2375                                  struct btrfs_ioctl_ino_lookup_user_args *args)
  2376  {
  2377          struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
  2378          struct super_block *sb = inode->i_sb;
  2379          struct btrfs_key upper_limit = BTRFS_I(inode)->location;
  2380          u64 treeid = BTRFS_I(inode)->root->root_key.objectid;
  2381          u64 dirid = args->dirid;
  2382          unsigned long item_off;
  2383          unsigned long item_len;
  2384          struct btrfs_inode_ref *iref;
  2385          struct btrfs_root_ref *rref;
  2386          struct btrfs_root *root;
                                   ^^^^

  2387          struct btrfs_path *path;
  2388          struct btrfs_key key, key2;
  2389          struct extent_buffer *leaf;
  2390          struct inode *temp_inode;
  2391          char *ptr;
  2392          int slot;
  2393          int len;
  2394          int total_len = 0;
  2395          int ret;
  2396  
  2397          path = btrfs_alloc_path();
  2398          if (!path)
  2399                  return -ENOMEM;
  2400  
  2401          /*
  2402           * If the bottom subvolume does not exist directly under upper_limit,
  2403           * construct the path in from the bottom up.
  2404           */
  2405          if (dirid != upper_limit.objectid) {
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
root isn't initialized on the else path.

  2406                  ptr = &args->path[BTRFS_INO_LOOKUP_USER_PATH_MAX - 1];
  2407  
  2408                  key.objectid = treeid;
  2409                  key.type = BTRFS_ROOT_ITEM_KEY;
  2410                  key.offset = (u64)-1;
  2411                  root = btrfs_get_fs_root(fs_info, &key, true);
  2412                  if (IS_ERR(root)) {
  2413                          ret = PTR_ERR(root);
  2414                          goto out;
  2415                  }
  2416  
  2417                  key.objectid = dirid;
  2418                  key.type = BTRFS_INODE_REF_KEY;
  2419                  key.offset = (u64)-1;
  2420                  while (1) {
  2421                          ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  2422                          if (ret < 0) {
  2423                                  goto out_put;
  2424                          } else if (ret > 0) {
  2425                                  ret = btrfs_previous_item(root, path, dirid,
  2426                                                            BTRFS_INODE_REF_KEY);
  2427                                  if (ret < 0) {
  2428                                          goto out_put;
  2429                                  } else if (ret > 0) {
  2430                                          ret = -ENOENT;
  2431                                          goto out_put;
  2432                                  }
  2433                          }
  2434  
  2435                          leaf = path->nodes[0];
  2436                          slot = path->slots[0];
  2437                          btrfs_item_key_to_cpu(leaf, &key, slot);
  2438  
  2439                          iref = btrfs_item_ptr(leaf, slot, struct btrfs_inode_ref);
  2440                          len = btrfs_inode_ref_name_len(leaf, iref);
  2441                          ptr -= len + 1;
  2442                          total_len += len + 1;
  2443                          if (ptr < args->path) {
  2444                                  ret = -ENAMETOOLONG;
  2445                                  goto out_put;
  2446                          }
  2447  
  2448                          *(ptr + len) = '/';
  2449                          read_extent_buffer(leaf, ptr,
  2450                                          (unsigned long)(iref + 1), len);
  2451  
  2452                          /* Check the read+exec permission of this directory */
  2453                          ret = btrfs_previous_item(root, path, dirid,
  2454                                                    BTRFS_INODE_ITEM_KEY);
  2455                          if (ret < 0) {
  2456                                  goto out_put;
  2457                          } else if (ret > 0) {
  2458                                  ret = -ENOENT;
  2459                                  goto out_put;
  2460                          }
  2461  
  2462                          leaf = path->nodes[0];
  2463                          slot = path->slots[0];
  2464                          btrfs_item_key_to_cpu(leaf, &key2, slot);
  2465                          if (key2.objectid != dirid) {
  2466                                  ret = -ENOENT;
  2467                                  goto out_put;
  2468                          }
  2469  
  2470                          temp_inode = btrfs_iget(sb, &key2, root);
  2471                          if (IS_ERR(temp_inode)) {
  2472                                  ret = PTR_ERR(temp_inode);
  2473                                  goto out_put;
  2474                          }
  2475                          ret = inode_permission(temp_inode, MAY_READ | MAY_EXEC);
  2476                          iput(temp_inode);
  2477                          if (ret) {
  2478                                  ret = -EACCES;
  2479                                  goto out_put;
  2480                          }
  2481  
  2482                          if (key.offset == upper_limit.objectid)
  2483                                  break;
  2484                          if (key.objectid == BTRFS_FIRST_FREE_OBJECTID) {
  2485                                  ret = -EACCES;
  2486                                  goto out_put;
  2487                          }
  2488  
  2489                          btrfs_release_path(path);
  2490                          key.objectid = key.offset;
  2491                          key.offset = (u64)-1;
  2492                          dirid = key.objectid;
  2493                  }
  2494  
  2495                  memmove(args->path, ptr, total_len);
  2496                  args->path[total_len] = '\0';
  2497                  btrfs_put_root(root);
  2498                  root = NULL;
  2499                  btrfs_release_path(path);
  2500          }
  2501  
  2502          /* Get the bottom subvolume's name from ROOT_REF */
  2503          key.objectid = treeid;
  2504          key.type = BTRFS_ROOT_REF_KEY;
  2505          key.offset = args->treeid;
  2506          ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, path, 0, 0);
  2507          if (ret < 0) {
  2508                  goto out;
  2509          } else if (ret > 0) {
  2510                  ret = -ENOENT;
  2511                  goto out;
  2512          }
  2513  
  2514          leaf = path->nodes[0];
  2515          slot = path->slots[0];
  2516          btrfs_item_key_to_cpu(leaf, &key, slot);
  2517  
  2518          item_off = btrfs_item_ptr_offset(leaf, slot);
  2519          item_len = btrfs_item_size_nr(leaf, slot);
  2520          /* Check if dirid in ROOT_REF corresponds to passed dirid */
  2521          rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref);
  2522          if (args->dirid != btrfs_root_ref_dirid(leaf, rref)) {
  2523                  ret = -EINVAL;
  2524                  goto out;
  2525          }
  2526  
  2527          /* Copy subvolume's name */
  2528          item_off += sizeof(struct btrfs_root_ref);
  2529          item_len -= sizeof(struct btrfs_root_ref);
  2530          read_extent_buffer(leaf, args->name, item_off, item_len);
  2531          args->name[item_len] = 0;

root isn't initialized on the success path.

  2532  
  2533  out_put:
  2534          btrfs_put_root(root);
  2535  out:
  2536          btrfs_free_path(path);
  2537          return ret;
  2538  }

regards,
dan carpenter



[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux