aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-09 15:48:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-09 15:48:05 -0400
commitfd3b36d275660c905da9900b078eea341847d5e4 (patch)
tree687872bfb4e3dce727d6bab3e8799cd67d4d5108
parent8ea4a5d84e6c44b3508599fe114ea806e63985a4 (diff)
parent30ce4d1903e1d8a7ccd110860a5eef3c638ed8be (diff)
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
-rw-r--r--fs/namei.c124
1 files changed, 57 insertions, 67 deletions
diff --git a/fs/namei.c b/fs/namei.c
index a66ed5a1622a..186bd2464fd5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -224,9 +224,10 @@ getname_kernel(const char * filename)
224 if (len <= EMBEDDED_NAME_MAX) { 224 if (len <= EMBEDDED_NAME_MAX) {
225 result->name = (char *)result->iname; 225 result->name = (char *)result->iname;
226 } else if (len <= PATH_MAX) { 226 } else if (len <= PATH_MAX) {
227 const size_t size = offsetof(struct filename, iname[1]);
227 struct filename *tmp; 228 struct filename *tmp;
228 229
229 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); 230 tmp = kmalloc(size, GFP_KERNEL);
230 if (unlikely(!tmp)) { 231 if (unlikely(!tmp)) {
231 __putname(result); 232 __putname(result);
232 return ERR_PTR(-ENOMEM); 233 return ERR_PTR(-ENOMEM);
@@ -1597,22 +1598,21 @@ static int lookup_fast(struct nameidata *nd,
1597} 1598}
1598 1599
1599/* Fast lookup failed, do it the slow way */ 1600/* Fast lookup failed, do it the slow way */
1600static struct dentry *lookup_slow(const struct qstr *name, 1601static struct dentry *__lookup_slow(const struct qstr *name,
1601 struct dentry *dir, 1602 struct dentry *dir,
1602 unsigned int flags) 1603 unsigned int flags)
1603{ 1604{
1604 struct dentry *dentry = ERR_PTR(-ENOENT), *old; 1605 struct dentry *dentry, *old;
1605 struct inode *inode = dir->d_inode; 1606 struct inode *inode = dir->d_inode;
1606 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); 1607 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
1607 1608
1608 inode_lock_shared(inode);
1609 /* Don't go there if it's already dead */ 1609 /* Don't go there if it's already dead */
1610 if (unlikely(IS_DEADDIR(inode))) 1610 if (unlikely(IS_DEADDIR(inode)))
1611 goto out; 1611 return ERR_PTR(-ENOENT);
1612again: 1612again:
1613 dentry = d_alloc_parallel(dir, name, &wq); 1613 dentry = d_alloc_parallel(dir, name, &wq);
1614 if (IS_ERR(dentry)) 1614 if (IS_ERR(dentry))
1615 goto out; 1615 return dentry;
1616 if (unlikely(!d_in_lookup(dentry))) { 1616 if (unlikely(!d_in_lookup(dentry))) {
1617 if (!(flags & LOOKUP_NO_REVAL)) { 1617 if (!(flags & LOOKUP_NO_REVAL)) {
1618 int error = d_revalidate(dentry, flags); 1618 int error = d_revalidate(dentry, flags);
@@ -1634,11 +1634,21 @@ again:
1634 dentry = old; 1634 dentry = old;
1635 } 1635 }
1636 } 1636 }
1637out:
1638 inode_unlock_shared(inode);
1639 return dentry; 1637 return dentry;
1640} 1638}
1641 1639
1640static 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;
1650}
1651
1642static inline int may_lookup(struct nameidata *nd) 1652static inline int may_lookup(struct nameidata *nd)
1643{ 1653{
1644 if (nd->flags & LOOKUP_RCU) { 1654 if (nd->flags & LOOKUP_RCU) {
@@ -2421,56 +2431,63 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
2421} 2431}
2422EXPORT_SYMBOL(vfs_path_lookup); 2432EXPORT_SYMBOL(vfs_path_lookup);
2423 2433
2424/** 2434static int lookup_one_len_common(const char *name, struct dentry *base,
2425 * lookup_one_len - filesystem helper to lookup single pathname component 2435 int len, struct qstr *this)
2426 * @name: pathname component to lookup
2427 * @base: base directory to lookup from
2428 * @len: maximum length @len should be interpreted to
2429 *
2430 * Note that this routine is purely a helper for filesystem usage and should
2431 * not be called by generic code.
2432 *
2433 * The caller must hold base->i_mutex.
2434 */
2435struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
2436{ 2436{
2437 struct qstr this; 2437 this->name = name;
2438 unsigned int c; 2438 this->len = len;
2439 int err; 2439 this->hash = full_name_hash(base, name, len);
2440
2441 WARN_ON_ONCE(!inode_is_locked(base->d_inode));
2442
2443 this.name = name;
2444 this.len = len;
2445 this.hash = full_name_hash(base, name, len);
2446 if (!len) 2440 if (!len)
2447 return ERR_PTR(-EACCES); 2441 return -EACCES;
2448 2442
2449 if (unlikely(name[0] == '.')) { 2443 if (unlikely(name[0] == '.')) {
2450 if (len < 2 || (len == 2 && name[1] == '.')) 2444 if (len < 2 || (len == 2 && name[1] == '.'))
2451 return ERR_PTR(-EACCES); 2445 return -EACCES;
2452 } 2446 }
2453 2447
2454 while (len--) { 2448 while (len--) {
2455 c = *(const unsigned char *)name++; 2449 unsigned int c = *(const unsigned char *)name++;
2456 if (c == '/' || c == '\0') 2450 if (c == '/' || c == '\0')
2457 return ERR_PTR(-EACCES); 2451 return -EACCES;
2458 } 2452 }
2459 /* 2453 /*
2460 * See if the low-level filesystem might want 2454 * See if the low-level filesystem might want
2461 * to use its own hash.. 2455 * to use its own hash..
2462 */ 2456 */
2463 if (base->d_flags & DCACHE_OP_HASH) { 2457 if (base->d_flags & DCACHE_OP_HASH) {
2464 int err = base->d_op->d_hash(base, &this); 2458 int err = base->d_op->d_hash(base, this);
2465 if (err < 0) 2459 if (err < 0)
2466 return ERR_PTR(err); 2460 return err;
2467 } 2461 }
2468 2462
2469 err = inode_permission(base->d_inode, MAY_EXEC); 2463 return inode_permission(base->d_inode, MAY_EXEC);
2464}
2465
2466/**
2467 * lookup_one_len - filesystem helper to lookup single pathname component
2468 * @name: pathname component to lookup
2469 * @base: base directory to lookup from
2470 * @len: maximum length @len should be interpreted to
2471 *
2472 * Note that this routine is purely a helper for filesystem usage and should
2473 * not be called by generic code.
2474 *
2475 * The caller must hold base->i_mutex.
2476 */
2477struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
2478{
2479 struct dentry *dentry;
2480 struct qstr this;
2481 int err;
2482
2483 WARN_ON_ONCE(!inode_is_locked(base->d_inode));
2484
2485 err = lookup_one_len_common(name, base, len, &this);
2470 if (err) 2486 if (err)
2471 return ERR_PTR(err); 2487 return ERR_PTR(err);
2472 2488
2473 return __lookup_hash(&this, base, 0); 2489 dentry = lookup_dcache(&this, base, 0);
2490 return dentry ? dentry : __lookup_slow(&this, base, 0);
2474} 2491}
2475EXPORT_SYMBOL(lookup_one_len); 2492EXPORT_SYMBOL(lookup_one_len);
2476 2493
@@ -2490,37 +2507,10 @@ struct dentry *lookup_one_len_unlocked(const char *name,
2490 struct dentry *base, int len) 2507 struct dentry *base, int len)
2491{ 2508{
2492 struct qstr this; 2509 struct qstr this;
2493 unsigned int c;
2494 int err; 2510 int err;
2495 struct dentry *ret; 2511 struct dentry *ret;
2496 2512
2497 this.name = name; 2513 err = lookup_one_len_common(name, base, len, &this);
2498 this.len = len;
2499 this.hash = full_name_hash(base, name, len);
2500 if (!len)
2501 return ERR_PTR(-EACCES);
2502
2503 if (unlikely(name[0] == '.')) {
2504 if (len < 2 || (len == 2 && name[1] == '.'))
2505 return ERR_PTR(-EACCES);
2506 }
2507
2508 while (len--) {
2509 c = *(const unsigned char *)name++;
2510 if (c == '/' || c == '\0')
2511 return ERR_PTR(-EACCES);
2512 }
2513 /*
2514 * See if the low-level filesystem might want
2515 * to use its own hash..
2516 */
2517 if (base->d_flags & DCACHE_OP_HASH) {
2518 int err = base->d_op->d_hash(base, &this);
2519 if (err < 0)
2520 return ERR_PTR(err);
2521 }
2522
2523 err = inode_permission(base->d_inode, MAY_EXEC);
2524 if (err) 2514 if (err)
2525 return ERR_PTR(err); 2515 return ERR_PTR(err);
2526 2516