Loading fs/namei.c +24 −31 Original line number Diff line number Diff line Loading @@ -498,8 +498,6 @@ static int link_path_walk(const char *, struct nameidata *); static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) { int res = 0; char *name; if (IS_ERR(link)) goto fail; Loading @@ -510,22 +508,7 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l path_get(&nd->root); } res = link_path_walk(link, nd); if (nd->depth || res || nd->last_type!=LAST_NORM) return res; /* * If it is an iterative symlinks resolution in open_namei() we * have to copy the last component. And all that crap because of * bloody create() on broken symlinks. Furrfu... */ name = __getname(); if (unlikely(!name)) { path_put(&nd->path); return -ENOMEM; } strcpy(name, nd->last.name); nd->last.name = name; return 0; return link_path_walk(link, nd); fail: path_put(&nd->path); return PTR_ERR(link); Loading @@ -547,10 +530,10 @@ static inline void path_to_nameidata(struct path *path, struct nameidata *nd) nd->path.dentry = path->dentry; } static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd, void **p) { int error; void *cookie; struct dentry *dentry = path->dentry; touch_atime(path->mnt, dentry); Loading @@ -562,9 +545,9 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata } mntget(path->mnt); nd->last_type = LAST_BIND; cookie = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(cookie); if (!IS_ERR(cookie)) { *p = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(*p); if (!IS_ERR(*p)) { char *s = nd_get_link(nd); error = 0; if (s) Loading @@ -574,8 +557,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata if (error) path_put(&nd->path); } if (dentry->d_inode->i_op->put_link) dentry->d_inode->i_op->put_link(dentry, nd, cookie); } return error; } Loading @@ -589,6 +570,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata */ static inline int do_follow_link(struct path *path, struct nameidata *nd) { void *cookie; int err = -ELOOP; if (current->link_count >= MAX_NESTED_LINKS) goto loop; Loading @@ -602,7 +584,9 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd) current->link_count++; current->total_link_count++; nd->depth++; err = __do_follow_link(path, nd); err = __do_follow_link(path, nd, &cookie); if (!IS_ERR(cookie) && path->dentry->d_inode->i_op->put_link) path->dentry->d_inode->i_op->put_link(path->dentry, nd, cookie); path_put(path); current->link_count--; nd->depth--; Loading Loading @@ -1847,6 +1831,9 @@ reval: nd.flags |= LOOKUP_EXCL; filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); while (unlikely(!filp)) { /* trailing symlink */ struct path holder; struct inode *inode; void *cookie; error = -ELOOP; if ((open_flag & O_NOFOLLOW) || count++ == 32) goto exit_dput; Loading @@ -1865,18 +1852,24 @@ reval: error = security_inode_follow_link(path.dentry, &nd); if (error) goto exit_dput; error = __do_follow_link(&path, &nd); path_put(&path); if (error) { error = __do_follow_link(&path, &nd, &cookie); if (unlikely(error)) { /* nd.path had been dropped */ inode = path.dentry->d_inode; if (!IS_ERR(cookie) && inode->i_op->put_link) inode->i_op->put_link(path.dentry, &nd, cookie); path_put(&path); release_open_intent(&nd); filp = ERR_PTR(error); goto out; } holder = path; nd.flags &= ~LOOKUP_PARENT; filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); if (nd.last_type == LAST_NORM) __putname(nd.last.name); inode = holder.dentry->d_inode; if (inode->i_op->put_link) inode->i_op->put_link(holder.dentry, &nd, cookie); path_put(&holder); } out: if (nd.root.mnt) Loading Loading
fs/namei.c +24 −31 Original line number Diff line number Diff line Loading @@ -498,8 +498,6 @@ static int link_path_walk(const char *, struct nameidata *); static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) { int res = 0; char *name; if (IS_ERR(link)) goto fail; Loading @@ -510,22 +508,7 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l path_get(&nd->root); } res = link_path_walk(link, nd); if (nd->depth || res || nd->last_type!=LAST_NORM) return res; /* * If it is an iterative symlinks resolution in open_namei() we * have to copy the last component. And all that crap because of * bloody create() on broken symlinks. Furrfu... */ name = __getname(); if (unlikely(!name)) { path_put(&nd->path); return -ENOMEM; } strcpy(name, nd->last.name); nd->last.name = name; return 0; return link_path_walk(link, nd); fail: path_put(&nd->path); return PTR_ERR(link); Loading @@ -547,10 +530,10 @@ static inline void path_to_nameidata(struct path *path, struct nameidata *nd) nd->path.dentry = path->dentry; } static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd, void **p) { int error; void *cookie; struct dentry *dentry = path->dentry; touch_atime(path->mnt, dentry); Loading @@ -562,9 +545,9 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata } mntget(path->mnt); nd->last_type = LAST_BIND; cookie = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(cookie); if (!IS_ERR(cookie)) { *p = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(*p); if (!IS_ERR(*p)) { char *s = nd_get_link(nd); error = 0; if (s) Loading @@ -574,8 +557,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata if (error) path_put(&nd->path); } if (dentry->d_inode->i_op->put_link) dentry->d_inode->i_op->put_link(dentry, nd, cookie); } return error; } Loading @@ -589,6 +570,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata */ static inline int do_follow_link(struct path *path, struct nameidata *nd) { void *cookie; int err = -ELOOP; if (current->link_count >= MAX_NESTED_LINKS) goto loop; Loading @@ -602,7 +584,9 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd) current->link_count++; current->total_link_count++; nd->depth++; err = __do_follow_link(path, nd); err = __do_follow_link(path, nd, &cookie); if (!IS_ERR(cookie) && path->dentry->d_inode->i_op->put_link) path->dentry->d_inode->i_op->put_link(path->dentry, nd, cookie); path_put(path); current->link_count--; nd->depth--; Loading Loading @@ -1847,6 +1831,9 @@ reval: nd.flags |= LOOKUP_EXCL; filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); while (unlikely(!filp)) { /* trailing symlink */ struct path holder; struct inode *inode; void *cookie; error = -ELOOP; if ((open_flag & O_NOFOLLOW) || count++ == 32) goto exit_dput; Loading @@ -1865,18 +1852,24 @@ reval: error = security_inode_follow_link(path.dentry, &nd); if (error) goto exit_dput; error = __do_follow_link(&path, &nd); path_put(&path); if (error) { error = __do_follow_link(&path, &nd, &cookie); if (unlikely(error)) { /* nd.path had been dropped */ inode = path.dentry->d_inode; if (!IS_ERR(cookie) && inode->i_op->put_link) inode->i_op->put_link(path.dentry, &nd, cookie); path_put(&path); release_open_intent(&nd); filp = ERR_PTR(error); goto out; } holder = path; nd.flags &= ~LOOKUP_PARENT; filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); if (nd.last_type == LAST_NORM) __putname(nd.last.name); inode = holder.dentry->d_inode; if (inode->i_op->put_link) inode->i_op->put_link(holder.dentry, &nd, cookie); path_put(&holder); } out: if (nd.root.mnt) Loading