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

Merge branch 'work.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs namei updates from Al Viro:

- make lookup_one_len() safe with parent locked only shared(incoming
afs series wants that)

- fix of getname_kernel() regression from 2015 (-stable fodder, that
one).

* 'work.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
getname_kernel() needs to make sure that ->name != ->iname in long case
make lookup_one_len() safe to use with directory locked shared
new helper: __lookup_slow()
merge common parts of lookup_one_len{,_unlocked} into common helper

+57 -67
+57 -67
fs/namei.c
··· 224 224 if (len <= EMBEDDED_NAME_MAX) { 225 225 result->name = (char *)result->iname; 226 226 } else if (len <= PATH_MAX) { 227 + const size_t size = offsetof(struct filename, iname[1]); 227 228 struct filename *tmp; 228 229 229 - tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); 230 + tmp = kmalloc(size, GFP_KERNEL); 230 231 if (unlikely(!tmp)) { 231 232 __putname(result); 232 233 return ERR_PTR(-ENOMEM); ··· 1598 1597 } 1599 1598 1600 1599 /* Fast lookup failed, do it the slow way */ 1601 - static struct dentry *lookup_slow(const struct qstr *name, 1602 - struct dentry *dir, 1603 - unsigned int flags) 1600 + static struct dentry *__lookup_slow(const struct qstr *name, 1601 + struct dentry *dir, 1602 + unsigned int flags) 1604 1603 { 1605 - struct dentry *dentry = ERR_PTR(-ENOENT), *old; 1604 + struct dentry *dentry, *old; 1606 1605 struct inode *inode = dir->d_inode; 1607 1606 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); 1608 1607 1609 - inode_lock_shared(inode); 1610 1608 /* Don't go there if it's already dead */ 1611 1609 if (unlikely(IS_DEADDIR(inode))) 1612 - goto out; 1610 + return ERR_PTR(-ENOENT); 1613 1611 again: 1614 1612 dentry = d_alloc_parallel(dir, name, &wq); 1615 1613 if (IS_ERR(dentry)) 1616 - goto out; 1614 + return dentry; 1617 1615 if (unlikely(!d_in_lookup(dentry))) { 1618 1616 if (!(flags & LOOKUP_NO_REVAL)) { 1619 1617 int error = d_revalidate(dentry, flags); ··· 1634 1634 dentry = old; 1635 1635 } 1636 1636 } 1637 - out: 1638 - inode_unlock_shared(inode); 1639 1637 return dentry; 1638 + } 1639 + 1640 + static struct dentry *lookup_slow(const struct qstr *name, 1641 + struct dentry *dir, 1642 + unsigned int flags) 1643 + { 1644 + struct inode *inode = dir->d_inode; 1645 + struct dentry *res; 1646 + inode_lock_shared(inode); 1647 + res = __lookup_slow(name, dir, flags); 1648 + inode_unlock_shared(inode); 1649 + return res; 1640 1650 } 1641 1651 1642 1652 static inline int may_lookup(struct nameidata *nd) ··· 2431 2421 } 2432 2422 EXPORT_SYMBOL(vfs_path_lookup); 2433 2423 2424 + static int lookup_one_len_common(const char *name, struct dentry *base, 2425 + int len, struct qstr *this) 2426 + { 2427 + this->name = name; 2428 + this->len = len; 2429 + this->hash = full_name_hash(base, name, len); 2430 + if (!len) 2431 + return -EACCES; 2432 + 2433 + if (unlikely(name[0] == '.')) { 2434 + if (len < 2 || (len == 2 && name[1] == '.')) 2435 + return -EACCES; 2436 + } 2437 + 2438 + while (len--) { 2439 + unsigned int c = *(const unsigned char *)name++; 2440 + if (c == '/' || c == '\0') 2441 + return -EACCES; 2442 + } 2443 + /* 2444 + * See if the low-level filesystem might want 2445 + * to use its own hash.. 2446 + */ 2447 + if (base->d_flags & DCACHE_OP_HASH) { 2448 + int err = base->d_op->d_hash(base, this); 2449 + if (err < 0) 2450 + return err; 2451 + } 2452 + 2453 + return inode_permission(base->d_inode, MAY_EXEC); 2454 + } 2455 + 2434 2456 /** 2435 2457 * lookup_one_len - filesystem helper to lookup single pathname component 2436 2458 * @name: pathname component to lookup ··· 2476 2434 */ 2477 2435 struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) 2478 2436 { 2437 + struct dentry *dentry; 2479 2438 struct qstr this; 2480 - unsigned int c; 2481 2439 int err; 2482 2440 2483 2441 WARN_ON_ONCE(!inode_is_locked(base->d_inode)); 2484 2442 2485 - this.name = name; 2486 - this.len = len; 2487 - this.hash = full_name_hash(base, name, len); 2488 - if (!len) 2489 - return ERR_PTR(-EACCES); 2490 - 2491 - if (unlikely(name[0] == '.')) { 2492 - if (len < 2 || (len == 2 && name[1] == '.')) 2493 - return ERR_PTR(-EACCES); 2494 - } 2495 - 2496 - while (len--) { 2497 - c = *(const unsigned char *)name++; 2498 - if (c == '/' || c == '\0') 2499 - return ERR_PTR(-EACCES); 2500 - } 2501 - /* 2502 - * See if the low-level filesystem might want 2503 - * to use its own hash.. 2504 - */ 2505 - if (base->d_flags & DCACHE_OP_HASH) { 2506 - int err = base->d_op->d_hash(base, &this); 2507 - if (err < 0) 2508 - return ERR_PTR(err); 2509 - } 2510 - 2511 - err = inode_permission(base->d_inode, MAY_EXEC); 2443 + err = lookup_one_len_common(name, base, len, &this); 2512 2444 if (err) 2513 2445 return ERR_PTR(err); 2514 2446 2515 - return __lookup_hash(&this, base, 0); 2447 + dentry = lookup_dcache(&this, base, 0); 2448 + return dentry ? dentry : __lookup_slow(&this, base, 0); 2516 2449 } 2517 2450 EXPORT_SYMBOL(lookup_one_len); 2518 2451 ··· 2507 2490 struct dentry *base, int len) 2508 2491 { 2509 2492 struct qstr this; 2510 - unsigned int c; 2511 2493 int err; 2512 2494 struct dentry *ret; 2513 2495 2514 - this.name = name; 2515 - this.len = len; 2516 - this.hash = full_name_hash(base, name, len); 2517 - if (!len) 2518 - return ERR_PTR(-EACCES); 2519 - 2520 - if (unlikely(name[0] == '.')) { 2521 - if (len < 2 || (len == 2 && name[1] == '.')) 2522 - return ERR_PTR(-EACCES); 2523 - } 2524 - 2525 - while (len--) { 2526 - c = *(const unsigned char *)name++; 2527 - if (c == '/' || c == '\0') 2528 - return ERR_PTR(-EACCES); 2529 - } 2530 - /* 2531 - * See if the low-level filesystem might want 2532 - * to use its own hash.. 2533 - */ 2534 - if (base->d_flags & DCACHE_OP_HASH) { 2535 - int err = base->d_op->d_hash(base, &this); 2536 - if (err < 0) 2537 - return ERR_PTR(err); 2538 - } 2539 - 2540 - err = inode_permission(base->d_inode, MAY_EXEC); 2496 + err = lookup_one_len_common(name, base, len, &this); 2541 2497 if (err) 2542 2498 return ERR_PTR(err); 2543 2499