[bug report] afs: Locally edit directory data for mkdir/create/unlink/...

Dan Carpenter dan.carpenter at oracle.com
Fri Apr 20 04:14:39 PDT 2018


[ This warning is slightly complicated and often has false positives.
  - dan ]

Hello David Howells,

The patch 63a4681ff39c: "afs: Locally edit directory data for
mkdir/create/unlink/..." from Apr 6, 2018, leads to the following
static checker warning:

	fs/afs/dir.c:1392 afs_create()
	warn: 'dentry->d_name.len' is out of bounds '255' vs '15'

fs/afs/dir_edit.c
   311  new_directory:
   312          afs_edit_init_block(meta, meta, 0);
   313          i_size = AFS_DIR_BLOCK_SIZE;
   314          i_size_write(&vnode->vfs_inode, i_size);
   315          slot = AFS_DIR_RESV_BLOCKS0;
   316          page = page0;
   317          block = meta;
   318          nr_blocks = 1;
   319          b = 0;
   320  
   321  found_space:
   322          /* Set the dirent slot. */
   323          trace_afs_edit_dir(vnode, why, afs_edit_dir_create, b, slot,
   324                             new_fid->vnode, new_fid->unique, name->name);
   325          de = &block->dirents[slot];
   326          de->u.valid     = 1;
   327          de->u.unused[0] = 0;
   328          de->u.hash_next = 0; // TODO: Really need to maintain this
   329          de->u.vnode     = htonl(new_fid->vnode);
   330          de->u.unique    = htonl(new_fid->unique);
   331          memcpy(de->u.name, name->name, name->len + 1);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   332          de->u.name[name->len] = 0;
                ^^^^^^^^^^^^^^^^^^^^^^^^
de->u.name is a 16 character buffer.

   333  
   334          /* Adjust the bitmap. */
   335          afs_set_contig_bits(block, slot, need_slots);
   336          if (page != page0) {
   337                  unlock_page(page);
   338                  kunmap(page);
   339                  put_page(page);
   340          }
   341  
   342          /* Adjust the allocation counter. */
   343          if (b < AFS_DIR_BLOCKS_WITH_CTR)
   344                  meta->meta.alloc_ctrs[b] -= need_slots;
   345  
   346          inode_inc_iversion_raw(&vnode->vfs_inode);
   347          afs_stat_v(vnode, n_dir_cr);
   348          _debug("Insert %s in %u[%u]", name->name, b, slot);
   349  
   350  out_unmap:

fs/afs/dir.c
  1346  static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  1347                        bool excl)
  1348  {
  1349          struct afs_fs_cursor fc;
  1350          struct afs_file_status newstatus;
  1351          struct afs_callback newcb;
  1352          struct afs_vnode *dvnode = AFS_FS_I(dir);
  1353          struct afs_fid newfid;
  1354          struct key *key;
  1355          u64 data_version = dvnode->status.data_version;
  1356          int ret;
  1357  
  1358          mode |= S_IFREG;
  1359  
  1360          _enter("{%x:%u},{%pd},%ho,",
  1361                 dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
  1362  
  1363          ret = -ENAMETOOLONG;
  1364          if (dentry->d_name.len >= AFSNAMEMAX)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here we ensure that d_name.len is 255 or less.
  1365                  goto error;
  1366  
  1367          key = afs_request_key(dvnode->volume->cell);
  1368          if (IS_ERR(key)) {
  1369                  ret = PTR_ERR(key);
  1370                  goto error;
  1371          }
  1372  
  1373          ret = -ERESTARTSYS;
  1374          if (afs_begin_vnode_operation(&fc, dvnode, key)) {
  1375                  while (afs_select_fileserver(&fc)) {
  1376                          fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
  1377                          afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
  1378                                        &newfid, &newstatus, &newcb);
  1379                  }
  1380  
  1381                  afs_check_for_remote_deletion(&fc, fc.vnode);
  1382                  afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
  1383                  afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, &newcb);
  1384                  ret = afs_end_vnode_operation(&fc);
  1385                  if (ret < 0)
  1386                          goto error_key;
  1387          } else {
  1388                  goto error_key;
  1389          }
  1390  
  1391          if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
  1392                  afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
                                                  ^^^^^^^^^^^^^^
This is where the warning gets generated because 255 is more than 15.

  1393                                   afs_edit_dir_for_create);
  1394  
  1395          key_put(key);
  1396          _leave(" = 0");
  1397          return 0;
  1398  
  1399  error_key:
  1400          key_put(key);
  1401  error:
  1402          d_drop(dentry);
  1403          _leave(" = %d", ret);
  1404          return ret;
  1405  }

See also:
fs/afs/dir.c:1465 afs_link() warn: 'dentry->d_name.len' is out of bounds '255' vs '15'
fs/afs/dir.c:1532 afs_symlink() warn: 'dentry->d_name.len' is out of bounds '255' vs '15'

regards,
dan carpenter



More information about the linux-afs mailing list