diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 123 |
1 files changed, 86 insertions, 37 deletions
diff --git a/fs/namei.c b/fs/namei.c index 9ed9361223c0..89a612e392eb 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1352,7 +1352,7 @@ static int lookup_fast(struct nameidata *nd, | |||
1352 | */ | 1352 | */ |
1353 | if (nd->flags & LOOKUP_RCU) { | 1353 | if (nd->flags & LOOKUP_RCU) { |
1354 | unsigned seq; | 1354 | unsigned seq; |
1355 | dentry = __d_lookup_rcu(parent, &nd->last, &seq, nd->inode); | 1355 | dentry = __d_lookup_rcu(parent, &nd->last, &seq); |
1356 | if (!dentry) | 1356 | if (!dentry) |
1357 | goto unlazy; | 1357 | goto unlazy; |
1358 | 1358 | ||
@@ -1787,8 +1787,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1787 | struct dentry *parent = nd->path.dentry; | 1787 | struct dentry *parent = nd->path.dentry; |
1788 | nd->flags &= ~LOOKUP_JUMPED; | 1788 | nd->flags &= ~LOOKUP_JUMPED; |
1789 | if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { | 1789 | if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { |
1790 | err = parent->d_op->d_hash(parent, nd->inode, | 1790 | err = parent->d_op->d_hash(parent, &this); |
1791 | &this); | ||
1792 | if (err < 0) | 1791 | if (err < 0) |
1793 | break; | 1792 | break; |
1794 | } | 1793 | } |
@@ -2121,7 +2120,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | |||
2121 | * to use its own hash.. | 2120 | * to use its own hash.. |
2122 | */ | 2121 | */ |
2123 | if (base->d_flags & DCACHE_OP_HASH) { | 2122 | if (base->d_flags & DCACHE_OP_HASH) { |
2124 | int err = base->d_op->d_hash(base, base->d_inode, &this); | 2123 | int err = base->d_op->d_hash(base, &this); |
2125 | if (err < 0) | 2124 | if (err < 0) |
2126 | return ERR_PTR(err); | 2125 | return ERR_PTR(err); |
2127 | } | 2126 | } |
@@ -2690,28 +2689,10 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2690 | nd->flags &= ~LOOKUP_PARENT; | 2689 | nd->flags &= ~LOOKUP_PARENT; |
2691 | nd->flags |= op->intent; | 2690 | nd->flags |= op->intent; |
2692 | 2691 | ||
2693 | switch (nd->last_type) { | 2692 | if (nd->last_type != LAST_NORM) { |
2694 | case LAST_DOTDOT: | ||
2695 | case LAST_DOT: | ||
2696 | error = handle_dots(nd, nd->last_type); | 2693 | error = handle_dots(nd, nd->last_type); |
2697 | if (error) | 2694 | if (error) |
2698 | return error; | 2695 | 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; | 2696 | goto finish_open; |
2716 | } | 2697 | } |
2717 | 2698 | ||
@@ -2841,19 +2822,19 @@ finish_lookup: | |||
2841 | } | 2822 | } |
2842 | nd->inode = inode; | 2823 | nd->inode = inode; |
2843 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ | 2824 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ |
2825 | finish_open: | ||
2844 | error = complete_walk(nd); | 2826 | error = complete_walk(nd); |
2845 | if (error) { | 2827 | if (error) { |
2846 | path_put(&save_parent); | 2828 | path_put(&save_parent); |
2847 | return error; | 2829 | return error; |
2848 | } | 2830 | } |
2831 | audit_inode(name, nd->path.dentry, 0); | ||
2849 | error = -EISDIR; | 2832 | error = -EISDIR; |
2850 | if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) | 2833 | if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) |
2851 | goto out; | 2834 | goto out; |
2852 | error = -ENOTDIR; | 2835 | error = -ENOTDIR; |
2853 | if ((nd->flags & LOOKUP_DIRECTORY) && !can_lookup(nd->inode)) | 2836 | if ((nd->flags & LOOKUP_DIRECTORY) && !can_lookup(nd->inode)) |
2854 | goto out; | 2837 | goto out; |
2855 | audit_inode(name, nd->path.dentry, 0); | ||
2856 | finish_open: | ||
2857 | if (!S_ISREG(nd->inode->i_mode)) | 2838 | if (!S_ISREG(nd->inode->i_mode)) |
2858 | will_truncate = false; | 2839 | will_truncate = false; |
2859 | 2840 | ||
@@ -2920,6 +2901,67 @@ stale_open: | |||
2920 | goto retry_lookup; | 2901 | goto retry_lookup; |
2921 | } | 2902 | } |
2922 | 2903 | ||
2904 | static int do_tmpfile(int dfd, struct filename *pathname, | ||
2905 | struct nameidata *nd, int flags, | ||
2906 | const struct open_flags *op, | ||
2907 | struct file *file, int *opened) | ||
2908 | { | ||
2909 | static const struct qstr name = QSTR_INIT("/", 1); | ||
2910 | struct dentry *dentry, *child; | ||
2911 | struct inode *dir; | ||
2912 | int error = path_lookupat(dfd, pathname->name, | ||
2913 | flags | LOOKUP_DIRECTORY, nd); | ||
2914 | if (unlikely(error)) | ||
2915 | return error; | ||
2916 | error = mnt_want_write(nd->path.mnt); | ||
2917 | if (unlikely(error)) | ||
2918 | goto out; | ||
2919 | /* we want directory to be writable */ | ||
2920 | error = inode_permission(nd->inode, MAY_WRITE | MAY_EXEC); | ||
2921 | if (error) | ||
2922 | goto out2; | ||
2923 | dentry = nd->path.dentry; | ||
2924 | dir = dentry->d_inode; | ||
2925 | if (!dir->i_op->tmpfile) { | ||
2926 | error = -EOPNOTSUPP; | ||
2927 | goto out2; | ||
2928 | } | ||
2929 | child = d_alloc(dentry, &name); | ||
2930 | if (unlikely(!child)) { | ||
2931 | error = -ENOMEM; | ||
2932 | goto out2; | ||
2933 | } | ||
2934 | nd->flags &= ~LOOKUP_DIRECTORY; | ||
2935 | nd->flags |= op->intent; | ||
2936 | dput(nd->path.dentry); | ||
2937 | nd->path.dentry = child; | ||
2938 | error = dir->i_op->tmpfile(dir, nd->path.dentry, op->mode); | ||
2939 | if (error) | ||
2940 | goto out2; | ||
2941 | audit_inode(pathname, nd->path.dentry, 0); | ||
2942 | error = may_open(&nd->path, op->acc_mode, op->open_flag); | ||
2943 | if (error) | ||
2944 | goto out2; | ||
2945 | file->f_path.mnt = nd->path.mnt; | ||
2946 | error = finish_open(file, nd->path.dentry, NULL, opened); | ||
2947 | if (error) | ||
2948 | goto out2; | ||
2949 | error = open_check_o_direct(file); | ||
2950 | if (error) { | ||
2951 | fput(file); | ||
2952 | } else if (!(op->open_flag & O_EXCL)) { | ||
2953 | struct inode *inode = file_inode(file); | ||
2954 | spin_lock(&inode->i_lock); | ||
2955 | inode->i_state |= I_LINKABLE; | ||
2956 | spin_unlock(&inode->i_lock); | ||
2957 | } | ||
2958 | out2: | ||
2959 | mnt_drop_write(nd->path.mnt); | ||
2960 | out: | ||
2961 | path_put(&nd->path); | ||
2962 | return error; | ||
2963 | } | ||
2964 | |||
2923 | static struct file *path_openat(int dfd, struct filename *pathname, | 2965 | static struct file *path_openat(int dfd, struct filename *pathname, |
2924 | struct nameidata *nd, const struct open_flags *op, int flags) | 2966 | struct nameidata *nd, const struct open_flags *op, int flags) |
2925 | { | 2967 | { |
@@ -2935,6 +2977,11 @@ static struct file *path_openat(int dfd, struct filename *pathname, | |||
2935 | 2977 | ||
2936 | file->f_flags = op->open_flag; | 2978 | file->f_flags = op->open_flag; |
2937 | 2979 | ||
2980 | if (unlikely(file->f_flags & __O_TMPFILE)) { | ||
2981 | error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened); | ||
2982 | goto out; | ||
2983 | } | ||
2984 | |||
2938 | error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); | 2985 | error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); |
2939 | if (unlikely(error)) | 2986 | if (unlikely(error)) |
2940 | goto out; | 2987 | goto out; |
@@ -2987,9 +3034,10 @@ out: | |||
2987 | } | 3034 | } |
2988 | 3035 | ||
2989 | struct file *do_filp_open(int dfd, struct filename *pathname, | 3036 | struct file *do_filp_open(int dfd, struct filename *pathname, |
2990 | const struct open_flags *op, int flags) | 3037 | const struct open_flags *op) |
2991 | { | 3038 | { |
2992 | struct nameidata nd; | 3039 | struct nameidata nd; |
3040 | int flags = op->lookup_flags; | ||
2993 | struct file *filp; | 3041 | struct file *filp; |
2994 | 3042 | ||
2995 | filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU); | 3043 | filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU); |
@@ -3001,17 +3049,16 @@ struct file *do_filp_open(int dfd, struct filename *pathname, | |||
3001 | } | 3049 | } |
3002 | 3050 | ||
3003 | struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | 3051 | struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, |
3004 | const char *name, const struct open_flags *op, int flags) | 3052 | const char *name, const struct open_flags *op) |
3005 | { | 3053 | { |
3006 | struct nameidata nd; | 3054 | struct nameidata nd; |
3007 | struct file *file; | 3055 | struct file *file; |
3008 | struct filename filename = { .name = name }; | 3056 | struct filename filename = { .name = name }; |
3057 | int flags = op->lookup_flags | LOOKUP_ROOT; | ||
3009 | 3058 | ||
3010 | nd.root.mnt = mnt; | 3059 | nd.root.mnt = mnt; |
3011 | nd.root.dentry = dentry; | 3060 | nd.root.dentry = dentry; |
3012 | 3061 | ||
3013 | flags |= LOOKUP_ROOT; | ||
3014 | |||
3015 | if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) | 3062 | if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) |
3016 | return ERR_PTR(-ELOOP); | 3063 | return ERR_PTR(-ELOOP); |
3017 | 3064 | ||
@@ -3586,12 +3633,18 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
3586 | 3633 | ||
3587 | mutex_lock(&inode->i_mutex); | 3634 | mutex_lock(&inode->i_mutex); |
3588 | /* Make sure we don't allow creating hardlink to an unlinked file */ | 3635 | /* Make sure we don't allow creating hardlink to an unlinked file */ |
3589 | if (inode->i_nlink == 0) | 3636 | if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE)) |
3590 | error = -ENOENT; | 3637 | error = -ENOENT; |
3591 | else if (max_links && inode->i_nlink >= max_links) | 3638 | else if (max_links && inode->i_nlink >= max_links) |
3592 | error = -EMLINK; | 3639 | error = -EMLINK; |
3593 | else | 3640 | else |
3594 | error = dir->i_op->link(old_dentry, dir, new_dentry); | 3641 | error = dir->i_op->link(old_dentry, dir, new_dentry); |
3642 | |||
3643 | if (!error && (inode->i_state & I_LINKABLE)) { | ||
3644 | spin_lock(&inode->i_lock); | ||
3645 | inode->i_state &= ~I_LINKABLE; | ||
3646 | spin_unlock(&inode->i_lock); | ||
3647 | } | ||
3595 | mutex_unlock(&inode->i_mutex); | 3648 | mutex_unlock(&inode->i_mutex); |
3596 | if (!error) | 3649 | if (!error) |
3597 | fsnotify_link(dir, inode, new_dentry); | 3650 | fsnotify_link(dir, inode, new_dentry); |
@@ -3618,15 +3671,11 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, | |||
3618 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) | 3671 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) |
3619 | return -EINVAL; | 3672 | return -EINVAL; |
3620 | /* | 3673 | /* |
3621 | * To use null names we require CAP_DAC_READ_SEARCH | 3674 | * Using empty names is equivalent to using AT_SYMLINK_FOLLOW |
3622 | * This ensures that not everyone will be able to create | 3675 | * on /proc/self/fd/<fd>. |
3623 | * handlink using the passed filedescriptor. | ||
3624 | */ | 3676 | */ |
3625 | if (flags & AT_EMPTY_PATH) { | 3677 | if (flags & AT_EMPTY_PATH) |
3626 | if (!capable(CAP_DAC_READ_SEARCH)) | ||
3627 | return -ENOENT; | ||
3628 | how = LOOKUP_EMPTY; | 3678 | how = LOOKUP_EMPTY; |
3629 | } | ||
3630 | 3679 | ||
3631 | if (flags & AT_SYMLINK_FOLLOW) | 3680 | if (flags & AT_SYMLINK_FOLLOW) |
3632 | how |= LOOKUP_FOLLOW; | 3681 | how |= LOOKUP_FOLLOW; |