Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -573,13 +573,15 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
{
	struct path path;
	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;

	follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
	error = user_path_at(dfd, filename, follow, &path);
	lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
	if (flag & AT_EMPTY_PATH)
		lookup_flags |= LOOKUP_EMPTY;
	error = user_path_at(dfd, filename, lookup_flags, &path);
	if (error)
		goto out;
	error = mnt_want_write(path.mnt);
+5 −2
Original line number Diff line number Diff line
@@ -75,13 +75,16 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
	int error = -EINVAL;
	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;

	if (!(flag & AT_SYMLINK_NOFOLLOW))
		lookup_flags |= LOOKUP_FOLLOW;
	if (flag & AT_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);
	if (error)
@@ -297,7 +300,7 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
	if (bufsiz <= 0)
		return -EINVAL;

	error = user_path_at(dfd, pathname, 0, &path);
	error = user_path_at(dfd, pathname, LOOKUP_EMPTY, &path);
	if (!error) {
		struct inode *inode = path.dentry->d_inode;