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: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
bcda76524c
commit
65cfc67223
10
fs/open.c
10
fs/open.c
|
@ -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,
|
||||||
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,
|
||||||
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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue