diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-06 09:12:33 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:57:07 -0400 |
commit | bc77daa783afcc56004d4ed3582983b234e01872 (patch) | |
tree | 9bd21739d43b5193eebaff2ed04de5113844a0f8 /fs/namei.c | |
parent | 0888c321de70d93f8e15614073af6c3ef56088b1 (diff) |
do_last(): fix missing checks for LAST_BIND case
/proc/self/cwd with O_CREAT should fail with EISDIR. /proc/self/exe, OTOH,
should fail with ENOTDIR when opened with O_DIRECTORY.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 24 |
1 files changed, 3 insertions, 21 deletions
diff --git a/fs/namei.c b/fs/namei.c index 9ed9361223c0..1bc7b7582a66 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2690,28 +2690,10 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2690 | nd->flags &= ~LOOKUP_PARENT; | 2690 | nd->flags &= ~LOOKUP_PARENT; |
2691 | nd->flags |= op->intent; | 2691 | nd->flags |= op->intent; |
2692 | 2692 | ||
2693 | switch (nd->last_type) { | 2693 | if (nd->last_type != LAST_NORM) { |
2694 | case LAST_DOTDOT: | ||
2695 | case LAST_DOT: | ||
2696 | error = handle_dots(nd, nd->last_type); | 2694 | error = handle_dots(nd, nd->last_type); |
2697 | if (error) | 2695 | if (error) |
2698 | return error; | 2696 | return error; |
2699 | /* fallthrough */ | ||
2700 | case LAST_ROOT: | ||
2701 | error = complete_walk(nd); | ||
2702 | if (error) | ||
2703 | return error; | ||
2704 | audit_inode(name, nd->path.dentry, 0); | ||
2705 | if (open_flag & O_CREAT) { | ||
2706 | error = -EISDIR; | ||
2707 | goto out; | ||
2708 | } | ||
2709 | goto finish_open; | ||
2710 | case LAST_BIND: | ||
2711 | error = complete_walk(nd); | ||
2712 | if (error) | ||
2713 | return error; | ||
2714 | audit_inode(name, dir, 0); | ||
2715 | goto finish_open; | 2697 | goto finish_open; |
2716 | } | 2698 | } |
2717 | 2699 | ||
@@ -2841,19 +2823,19 @@ finish_lookup: | |||
2841 | } | 2823 | } |
2842 | nd->inode = inode; | 2824 | nd->inode = inode; |
2843 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ | 2825 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ |
2826 | finish_open: | ||
2844 | error = complete_walk(nd); | 2827 | error = complete_walk(nd); |
2845 | if (error) { | 2828 | if (error) { |
2846 | path_put(&save_parent); | 2829 | path_put(&save_parent); |
2847 | return error; | 2830 | return error; |
2848 | } | 2831 | } |
2832 | audit_inode(name, nd->path.dentry, 0); | ||
2849 | error = -EISDIR; | 2833 | error = -EISDIR; |
2850 | if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) | 2834 | if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) |
2851 | goto out; | 2835 | goto out; |
2852 | error = -ENOTDIR; | 2836 | error = -ENOTDIR; |
2853 | if ((nd->flags & LOOKUP_DIRECTORY) && !can_lookup(nd->inode)) | 2837 | if ((nd->flags & LOOKUP_DIRECTORY) && !can_lookup(nd->inode)) |
2854 | goto out; | 2838 | goto out; |
2855 | audit_inode(name, nd->path.dentry, 0); | ||
2856 | finish_open: | ||
2857 | if (!S_ISREG(nd->inode->i_mode)) | 2839 | if (!S_ISREG(nd->inode->i_mode)) |
2858 | will_truncate = false; | 2840 | will_truncate = false; |
2859 | 2841 | ||