Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'xfs-for-linux-4.10-rc5-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:
"I have a few more patches this week -- one to make the behavior of a
quota id ioctl consistent with the other filesystems, and the rest
improve validation of i_mode & i_size values coming into xfs so that
we don't read off the ends of arrays or crash when handed garbage disk
data.

Summary:
- inode i_mode sanitization
- prevent overflows in getnextquota
- minor build fixes"

* tag 'xfs-for-linux-4.10-rc5-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: fix xfs_mode_to_ftype() prototype
xfs: don't wrap ID in xfs_dq_get_next_id
xfs: sanity check inode di_mode
xfs: sanity check inode mode when creating new dentry
xfs: replace xfs_mode_to_ftype table with switch statement
xfs: add missing include dependencies to xfs_dir2.h
xfs: sanity check directory inode di_size
xfs: make the ASSERT() condition likely

+84 -33
+24 -15
fs/xfs/libxfs/xfs_dir2.c
··· 36 36 struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR }; 37 37 38 38 /* 39 - * @mode, if set, indicates that the type field needs to be set up. 40 - * This uses the transformation from file mode to DT_* as defined in linux/fs.h 41 - * for file type specification. This will be propagated into the directory 42 - * structure if appropriate for the given operation and filesystem config. 39 + * Convert inode mode to directory entry filetype 43 40 */ 44 - const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = { 45 - [0] = XFS_DIR3_FT_UNKNOWN, 46 - [S_IFREG >> S_SHIFT] = XFS_DIR3_FT_REG_FILE, 47 - [S_IFDIR >> S_SHIFT] = XFS_DIR3_FT_DIR, 48 - [S_IFCHR >> S_SHIFT] = XFS_DIR3_FT_CHRDEV, 49 - [S_IFBLK >> S_SHIFT] = XFS_DIR3_FT_BLKDEV, 50 - [S_IFIFO >> S_SHIFT] = XFS_DIR3_FT_FIFO, 51 - [S_IFSOCK >> S_SHIFT] = XFS_DIR3_FT_SOCK, 52 - [S_IFLNK >> S_SHIFT] = XFS_DIR3_FT_SYMLINK, 53 - }; 41 + unsigned char xfs_mode_to_ftype(int mode) 42 + { 43 + switch (mode & S_IFMT) { 44 + case S_IFREG: 45 + return XFS_DIR3_FT_REG_FILE; 46 + case S_IFDIR: 47 + return XFS_DIR3_FT_DIR; 48 + case S_IFCHR: 49 + return XFS_DIR3_FT_CHRDEV; 50 + case S_IFBLK: 51 + return XFS_DIR3_FT_BLKDEV; 52 + case S_IFIFO: 53 + return XFS_DIR3_FT_FIFO; 54 + case S_IFSOCK: 55 + return XFS_DIR3_FT_SOCK; 56 + case S_IFLNK: 57 + return XFS_DIR3_FT_SYMLINK; 58 + default: 59 + return XFS_DIR3_FT_UNKNOWN; 60 + } 61 + } 54 62 55 63 /* 56 64 * ASCII case-insensitive (ie. A-Z) support for directories that was ··· 639 631 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) 640 632 return rval; 641 633 rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; 642 - ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize); 634 + if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) 635 + return -EFSCORRUPTED; 643 636 *vp = rval; 644 637 return 0; 645 638 }
+5 -3
fs/xfs/libxfs/xfs_dir2.h
··· 18 18 #ifndef __XFS_DIR2_H__ 19 19 #define __XFS_DIR2_H__ 20 20 21 + #include "xfs_da_format.h" 22 + #include "xfs_da_btree.h" 23 + 21 24 struct xfs_defer_ops; 22 25 struct xfs_da_args; 23 26 struct xfs_inode; ··· 35 32 extern struct xfs_name xfs_name_dotdot; 36 33 37 34 /* 38 - * directory filetype conversion tables. 35 + * Convert inode mode to directory entry filetype 39 36 */ 40 - #define S_SHIFT 12 41 - extern const unsigned char xfs_mode_to_ftype[]; 37 + extern unsigned char xfs_mode_to_ftype(int mode); 42 38 43 39 /* 44 40 * directory operations vector for encode/decode routines
+8 -2
fs/xfs/libxfs/xfs_inode_buf.c
··· 29 29 #include "xfs_icache.h" 30 30 #include "xfs_trans.h" 31 31 #include "xfs_ialloc.h" 32 + #include "xfs_dir2.h" 32 33 33 34 /* 34 35 * Check that none of the inode's in the buffer have a next ··· 387 386 xfs_ino_t ino, 388 387 struct xfs_dinode *dip) 389 388 { 389 + uint16_t mode; 390 390 uint16_t flags; 391 391 uint64_t flags2; 392 392 ··· 398 396 if (be64_to_cpu(dip->di_size) & (1ULL << 63)) 399 397 return false; 400 398 401 - /* No zero-length symlinks. */ 402 - if (S_ISLNK(be16_to_cpu(dip->di_mode)) && dip->di_size == 0) 399 + mode = be16_to_cpu(dip->di_mode); 400 + if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN) 401 + return false; 402 + 403 + /* No zero-length symlinks/dirs. */ 404 + if ((S_ISLNK(mode) || S_ISDIR(mode)) && dip->di_size == 0) 403 405 return false; 404 406 405 407 /* only version 3 or greater inodes are extensively verified here */
+4
fs/xfs/xfs_dquot.c
··· 710 710 /* Simple advance */ 711 711 next_id = *id + 1; 712 712 713 + /* If we'd wrap past the max ID, stop */ 714 + if (next_id < *id) 715 + return -ENOENT; 716 + 713 717 /* If new ID is within the current chunk, advancing it sufficed */ 714 718 if (next_id % mp->m_quotainfo->qi_dqperchunk) { 715 719 *id = next_id;
+40 -10
fs/xfs/xfs_iops.c
··· 98 98 static void 99 99 xfs_dentry_to_name( 100 100 struct xfs_name *namep, 101 + struct dentry *dentry) 102 + { 103 + namep->name = dentry->d_name.name; 104 + namep->len = dentry->d_name.len; 105 + namep->type = XFS_DIR3_FT_UNKNOWN; 106 + } 107 + 108 + static int 109 + xfs_dentry_mode_to_name( 110 + struct xfs_name *namep, 101 111 struct dentry *dentry, 102 112 int mode) 103 113 { 104 114 namep->name = dentry->d_name.name; 105 115 namep->len = dentry->d_name.len; 106 - namep->type = xfs_mode_to_ftype[(mode & S_IFMT) >> S_SHIFT]; 116 + namep->type = xfs_mode_to_ftype(mode); 117 + 118 + if (unlikely(namep->type == XFS_DIR3_FT_UNKNOWN)) 119 + return -EFSCORRUPTED; 120 + 121 + return 0; 107 122 } 108 123 109 124 STATIC void ··· 134 119 * xfs_init_security we must back out. 135 120 * ENOSPC can hit here, among other things. 136 121 */ 137 - xfs_dentry_to_name(&teardown, dentry, 0); 122 + xfs_dentry_to_name(&teardown, dentry); 138 123 139 124 xfs_remove(XFS_I(dir), &teardown, XFS_I(inode)); 140 125 } ··· 169 154 if (error) 170 155 return error; 171 156 157 + /* Verify mode is valid also for tmpfile case */ 158 + error = xfs_dentry_mode_to_name(&name, dentry, mode); 159 + if (unlikely(error)) 160 + goto out_free_acl; 161 + 172 162 if (!tmpfile) { 173 - xfs_dentry_to_name(&name, dentry, mode); 174 163 error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip); 175 164 } else { 176 165 error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip); ··· 267 248 if (dentry->d_name.len >= MAXNAMELEN) 268 249 return ERR_PTR(-ENAMETOOLONG); 269 250 270 - xfs_dentry_to_name(&name, dentry, 0); 251 + xfs_dentry_to_name(&name, dentry); 271 252 error = xfs_lookup(XFS_I(dir), &name, &cip, NULL); 272 253 if (unlikely(error)) { 273 254 if (unlikely(error != -ENOENT)) ··· 294 275 if (dentry->d_name.len >= MAXNAMELEN) 295 276 return ERR_PTR(-ENAMETOOLONG); 296 277 297 - xfs_dentry_to_name(&xname, dentry, 0); 278 + xfs_dentry_to_name(&xname, dentry); 298 279 error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name); 299 280 if (unlikely(error)) { 300 281 if (unlikely(error != -ENOENT)) ··· 329 310 struct xfs_name name; 330 311 int error; 331 312 332 - xfs_dentry_to_name(&name, dentry, inode->i_mode); 313 + error = xfs_dentry_mode_to_name(&name, dentry, inode->i_mode); 314 + if (unlikely(error)) 315 + return error; 333 316 334 317 error = xfs_link(XFS_I(dir), XFS_I(inode), &name); 335 318 if (unlikely(error)) ··· 350 329 struct xfs_name name; 351 330 int error; 352 331 353 - xfs_dentry_to_name(&name, dentry, 0); 332 + xfs_dentry_to_name(&name, dentry); 354 333 355 334 error = xfs_remove(XFS_I(dir), &name, XFS_I(d_inode(dentry))); 356 335 if (error) ··· 380 359 381 360 mode = S_IFLNK | 382 361 (irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO); 383 - xfs_dentry_to_name(&name, dentry, mode); 362 + error = xfs_dentry_mode_to_name(&name, dentry, mode); 363 + if (unlikely(error)) 364 + goto out; 384 365 385 366 error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip); 386 367 if (unlikely(error)) ··· 418 395 { 419 396 struct inode *new_inode = d_inode(ndentry); 420 397 int omode = 0; 398 + int error; 421 399 struct xfs_name oname; 422 400 struct xfs_name nname; 423 401 ··· 429 405 if (flags & RENAME_EXCHANGE) 430 406 omode = d_inode(ndentry)->i_mode; 431 407 432 - xfs_dentry_to_name(&oname, odentry, omode); 433 - xfs_dentry_to_name(&nname, ndentry, d_inode(odentry)->i_mode); 408 + error = xfs_dentry_mode_to_name(&oname, odentry, omode); 409 + if (omode && unlikely(error)) 410 + return error; 411 + 412 + error = xfs_dentry_mode_to_name(&nname, ndentry, 413 + d_inode(odentry)->i_mode); 414 + if (unlikely(error)) 415 + return error; 434 416 435 417 return xfs_rename(XFS_I(odir), &oname, XFS_I(d_inode(odentry)), 436 418 XFS_I(ndir), &nname,
+3 -3
fs/xfs/xfs_linux.h
··· 331 331 } 332 332 333 333 #define ASSERT_ALWAYS(expr) \ 334 - (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) 334 + (likely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) 335 335 336 336 #ifdef DEBUG 337 337 #define ASSERT(expr) \ 338 - (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) 338 + (likely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) 339 339 340 340 #ifndef STATIC 341 341 # define STATIC noinline ··· 346 346 #ifdef XFS_WARN 347 347 348 348 #define ASSERT(expr) \ 349 - (unlikely(expr) ? (void)0 : asswarn(#expr, __FILE__, __LINE__)) 349 + (likely(expr) ? (void)0 : asswarn(#expr, __FILE__, __LINE__)) 350 350 351 351 #ifndef STATIC 352 352 # define STATIC static noinline