All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kurz <groug@kaod.org>
To: viro@zeniv.linux.org.uk
Cc: linux-fsdevel@vger.kernel.org, Eric Blake <eblake@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 1/2] vfs: implement fchmodat2() syscall
Date: Tue, 28 Feb 2017 18:03:42 +0100	[thread overview]
Message-ID: <148830142269.7103.7429913851447595016.stgit@bahia> (raw)

According to the POSIX.1-2008 manual page [1], the fchmodat() function has
a flag argument which may be passed the following value:

AT_SYMLINK_NOFOLLOW
    If path names a symbolic link, then the mode of the symbolic link is
    changed.

and the following error may be returned:

[EOPNOTSUPP]
    The AT_SYMLINK_NOFOLLOW bit is set in the flag argument, path names a
    symbolic link, and the system does not support changing the mode of a
    symbolic link.

The linux kernel doesn't support changing the mode of a symbolic link, but
the current implementation doesn't even have a flag argument. It is then
up to userspace to deal with that. Unfortunately, it is impossible to
implement the POSIX behavior in a race-free manner.

This patch introduces a new fchmodat2() syscall with a flag argument to
address the issue.

[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/chmod.html

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 fs/open.c                         |   23 +++++++++++++++++++----
 include/linux/syscalls.h          |    2 ++
 include/uapi/asm-generic/unistd.h |    4 +++-
 scripts/checksyscalls.sh          |    3 ++-
 4 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/fs/open.c b/fs/open.c
index 9921f70bc5ca..66a8c19f72ca 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -558,24 +558,39 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
 	return err;
 }
 
-SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode)
+SYSCALL_DEFINE4(fchmodat2, int, dfd, const char __user *, filename, umode_t,
+		mode, int, flag)
 {
 	struct path path;
-	int error;
-	unsigned int lookup_flags = LOOKUP_FOLLOW;
+	int error = -EINVAL;
+	unsigned int lookup_flags;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
 retry:
 	error = user_path_at(dfd, filename, lookup_flags, &path);
 	if (!error) {
-		error = chmod_common(&path, mode);
+		error = -EOPNOTSUPP;
+		if (!d_is_symlink(path.dentry))
+			error = chmod_common(&path, mode);
 		path_put(&path);
 		if (retry_estale(error, lookup_flags)) {
 			lookup_flags |= LOOKUP_REVAL;
 			goto retry;
 		}
 	}
+out:
 	return error;
 }
 
+SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, umode_t,
+		mode)
+{
+	return sys_fchmodat2(dfd, filename, mode, 0);
+}
+
 SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
 {
 	return sys_fchmodat(AT_FDCWD, filename, mode);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 91a740f6b884..982089d55b31 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -775,6 +775,8 @@ asmlinkage long sys_futimesat(int dfd, const char __user *filename,
 asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode);
 asmlinkage long sys_fchmodat(int dfd, const char __user * filename,
 			     umode_t mode);
+asmlinkage long sys_fchmodat2(int dfd, const char __user *filename,
+			      umode_t mode, int flag);
 asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
 			     gid_t group, int flag);
 asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 9b1462e38b82..e8b0a00908b1 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -730,9 +730,11 @@ __SYSCALL(__NR_pkey_mprotect, sys_pkey_mprotect)
 __SYSCALL(__NR_pkey_alloc,    sys_pkey_alloc)
 #define __NR_pkey_free 290
 __SYSCALL(__NR_pkey_free,     sys_pkey_free)
+#define __NR_fchmodat2 291
+__SYSCALL(__NR_fchmodat2,     sys_fchmodat2)
 
 #undef __NR_syscalls
-#define __NR_syscalls 291
+#define __NR_syscalls 292
 
 /*
  * All syscalls below here should go away really,
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index 2c9082ba6137..2e7471a1d308 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -19,7 +19,7 @@ cat << EOF
 #define __IGNORE_link		/* linkat */
 #define __IGNORE_unlink		/* unlinkat */
 #define __IGNORE_mknod		/* mknodat */
-#define __IGNORE_chmod		/* fchmodat */
+#define __IGNORE_chmod		/* fchmodat2 */
 #define __IGNORE_chown		/* fchownat */
 #define __IGNORE_mkdir		/* mkdirat */
 #define __IGNORE_rmdir		/* unlinkat */
@@ -39,6 +39,7 @@ cat << EOF
 
 /* Missing flags argument */
 #define __IGNORE_renameat	/* renameat2 */
+#define __IGNORE_fchmodat	/* fchmodat2 */
 
 /* CLOEXEC flag */
 #define __IGNORE_pipe		/* pipe2 */

             reply	other threads:[~2017-02-28 17:04 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-28 17:03 Greg Kurz [this message]
2017-02-28 17:03 ` [PATCH 2/2] x86: wire up fchmodat2() syscall Greg Kurz
2017-03-01  9:00   ` kbuild test robot
2017-02-28 18:23 ` [PATCH 1/2] vfs: implement " Eric Blake
2017-02-28 18:41   ` Greg Kurz
2017-02-28 18:59     ` Eric Blake
2017-04-11 17:52   ` Colin Walters
2017-04-11 17:55     ` Eric Blake
2017-04-11 18:07       ` Eric Blake
2017-04-11 18:08         ` Eric Blake
2017-04-11 19:09         ` Colin Walters
2017-04-19 12:45           ` Greg Kurz
2017-03-01  9:01 ` Michael Kerrisk
2017-04-11 11:39   ` Greg Kurz
2017-04-11 12:04     ` Greg Kurz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=148830142269.7103.7429913851447595016.stgit@bahia \
    --to=groug@kaod.org \
    --cc=eblake@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.