diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/fs/namei.c b/fs/namei.c index 9d4f32700179..c9b7f5b7e92a 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2945,15 +2945,27 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, | |||
2945 | struct dentry *new_dentry; | 2945 | struct dentry *new_dentry; |
2946 | struct nameidata nd; | 2946 | struct nameidata nd; |
2947 | struct path old_path; | 2947 | struct path old_path; |
2948 | int how = 0; | ||
2948 | int error; | 2949 | int error; |
2949 | char *to; | 2950 | char *to; |
2950 | 2951 | ||
2951 | if ((flags & ~AT_SYMLINK_FOLLOW) != 0) | 2952 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) |
2952 | return -EINVAL; | 2953 | return -EINVAL; |
2954 | /* | ||
2955 | * To use null names we require CAP_DAC_READ_SEARCH | ||
2956 | * This ensures that not everyone will be able to create | ||
2957 | * handlink using the passed filedescriptor. | ||
2958 | */ | ||
2959 | if (flags & AT_EMPTY_PATH) { | ||
2960 | if (!capable(CAP_DAC_READ_SEARCH)) | ||
2961 | return -ENOENT; | ||
2962 | how = LOOKUP_EMPTY; | ||
2963 | } | ||
2964 | |||
2965 | if (flags & AT_SYMLINK_FOLLOW) | ||
2966 | how |= LOOKUP_FOLLOW; | ||
2953 | 2967 | ||
2954 | error = user_path_at(olddfd, oldname, | 2968 | error = user_path_at(olddfd, oldname, how, &old_path); |
2955 | flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0, | ||
2956 | &old_path); | ||
2957 | if (error) | 2969 | if (error) |
2958 | return error; | 2970 | return error; |
2959 | 2971 | ||