Commit 65cfc672 authored by Al Viro's avatar Al Viro

readlinkat(), fchownat() and fstatat() with empty relative pathnames

For readlinkat() we simply allow empty pathname; it will fail unless
we have dfd equal to O_PATH-opened symlink, so we are outside of
POSIX scope here.  For fchownat() and fstatat() we allow AT_EMPTY_PATH;
let the caller explicitly ask for such behaviour.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent bcda7652
...@@ -573,13 +573,15 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, ...@@ -573,13 +573,15 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
{ {
struct path path; struct path path;
int error = -EINVAL; int error = -EINVAL;
int follow; int lookup_flags;
if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
goto out; goto out;
follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
error = user_path_at(dfd, filename, follow, &path); if (flag & AT_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error) if (error)
goto out; goto out;
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
......
...@@ -75,13 +75,16 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, ...@@ -75,13 +75,16 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
int error = -EINVAL; int error = -EINVAL;
int lookup_flags = 0; int lookup_flags = 0;
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
AT_EMPTY_PATH)) != 0)
goto out; goto out;
if (!(flag & AT_SYMLINK_NOFOLLOW)) if (!(flag & AT_SYMLINK_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW; lookup_flags |= LOOKUP_FOLLOW;
if (flag & AT_NO_AUTOMOUNT) if (flag & AT_NO_AUTOMOUNT)
lookup_flags |= LOOKUP_NO_AUTOMOUNT; lookup_flags |= LOOKUP_NO_AUTOMOUNT;
if (flag & AT_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
error = user_path_at(dfd, filename, lookup_flags, &path); error = user_path_at(dfd, filename, lookup_flags, &path);
if (error) if (error)
...@@ -297,7 +300,7 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname, ...@@ -297,7 +300,7 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
if (bufsiz <= 0) if (bufsiz <= 0)
return -EINVAL; return -EINVAL;
error = user_path_at(dfd, pathname, 0, &path); error = user_path_at(dfd, pathname, LOOKUP_EMPTY, &path);
if (!error) { if (!error) {
struct inode *inode = path.dentry->d_inode; struct inode *inode = path.dentry->d_inode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment