All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
To: hch@infradead.org, viro@zeniv.linux.org.uk, adilger@sun.com,
	corbet@lwn.net, neilb@suse.de, npiggin@kernel.dk,
	hooanon05@yahoo.co.jp, bfields@fieldses.org, miklos@szeredi.hu
Cc: linux-fsdevel@vger.kernel.org, sfrench@us.ibm.com,
	philippe.deniel@CEA.FR, linux-kernel@vger.kernel.org,
	"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Subject: [PATCH -V26 13/16] fs: Support "" relative pathnames
Date: Sun, 30 Jan 2011 00:38:16 +0530	[thread overview]
Message-ID: <1296328099-23263-14-git-send-email-aneesh.kumar@linux.vnet.ibm.com> (raw)
In-Reply-To: <1296328099-23263-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

Support "" relative pathnames relative to file descriptor opened
with O_PATH flag. This is needed so that we can make *_at variant
syscall operate on the dirfd passed.

Primary motivation is to enable readlinkat and linkat syscall
to work on symlink file descriptor. This also enables us to
do path lookup in userspace which can be useful for implementing
file servers in userspace.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/namei.c         |  104 +++++++++++++++++++++++++++++++++++++++-------------
 include/linux/fs.h |   10 ++++-
 2 files changed, 87 insertions(+), 27 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index b9a500c..990b155 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -115,7 +115,8 @@
  * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
  * PATH_MAX includes the nul terminator --RR.
  */
-static int do_getname(const char __user *filename, char *page)
+static int __do_getname(const char __user *filename,
+			char *page, int allow_null_name)
 {
 	int retval;
 	unsigned long len = PATH_MAX;
@@ -132,19 +133,20 @@ static int do_getname(const char __user *filename, char *page)
 		if (retval < len)
 			return 0;
 		return -ENAMETOOLONG;
-	} else if (!retval)
+	} else if (!retval && !allow_null_name)
 		retval = -ENOENT;
+
 	return retval;
 }
 
-char * getname(const char __user * filename)
+char *do_getname(const char __user *filename, int allow_null_name)
 {
 	char *tmp, *result;
 
 	result = ERR_PTR(-ENOMEM);
 	tmp = __getname();
 	if (tmp)  {
-		int retval = do_getname(filename, tmp);
+		int retval = __do_getname(filename, tmp, allow_null_name);
 
 		result = tmp;
 		if (retval < 0) {
@@ -155,6 +157,7 @@ char * getname(const char __user * filename)
 	audit_getname(result);
 	return result;
 }
+EXPORT_SYMBOL(do_getname);
 
 #ifdef CONFIG_AUDITSYSCALL
 void putname(const char *name)
@@ -1605,6 +1608,14 @@ static int path_init_rcu(int dfd, const char *name, unsigned int flags, struct n
 		struct fs_struct *fs = current->fs;
 		unsigned seq;
 
+		/*
+		 * If relative name is "" the descriptor should
+		 * be O_PATH descriptor.
+		 */
+		if (*name == 0) {
+			retval = -ENOENT;
+			goto out_fail;
+		}
 		br_read_lock(vfsmount_lock);
 		rcu_read_lock();
 
@@ -1617,21 +1628,38 @@ static int path_init_rcu(int dfd, const char *name, unsigned int flags, struct n
 	} else {
 		struct dentry *dentry;
 
-		file = fget_light(dfd, &fput_needed);
+		file = fget_light_lenient(dfd, &fput_needed);
 		retval = -EBADF;
 		if (!file)
 			goto out_fail;
 
 		dentry = file->f_path.dentry;
-
-		retval = -ENOTDIR;
-		if (!S_ISDIR(dentry->d_inode->i_mode))
-			goto fput_fail;
-
-		retval = file_permission(file, MAY_EXEC);
-		if (retval)
-			goto fput_fail;
-
+		/*
+		 * We allow O_PATH fd to be used relative
+		 * to "" name. This indicate operate on
+		 * dfd itself.
+		 */
+		if (!S_ISDIR(dentry->d_inode->i_mode)) {
+			if (!(file->f_flags & O_PATH) || (*name != 0)) {
+				retval = -ENOTDIR;
+				goto fput_fail;
+			}
+		} else {
+			/*
+			 * if directory and relative name is not ""
+			 * then we need to check for EXEC permission.
+			 * If relative name is "" the descriptor should
+			 * be O_PATH descriptor.
+			 */
+			if (*name != 0) {
+				retval = file_permission(file, MAY_EXEC);
+				if (retval)
+					goto fput_fail;
+			} else if (!(file->f_flags & O_PATH)) {
+				retval = -ENOENT;
+				goto fput_fail;
+			}
+		}
 		nd->path = file->f_path;
 		if (fput_needed)
 			nd->file = file;
@@ -1665,25 +1693,50 @@ static int path_init(int dfd, const char *name, unsigned int flags, struct namei
 		nd->path = nd->root;
 		path_get(&nd->root);
 	} else if (dfd == AT_FDCWD) {
+		/*
+		 * If relative name is "" the descriptor should
+		 * be O_PATH descriptor.
+		 */
+		if (*name == 0) {
+			retval = -ENOENT;
+			goto out_fail;
+		}
 		get_fs_pwd(current->fs, &nd->path);
 	} else {
 		struct dentry *dentry;
 
-		file = fget_light(dfd, &fput_needed);
+		file = fget_light_lenient(dfd, &fput_needed);
 		retval = -EBADF;
 		if (!file)
 			goto out_fail;
 
 		dentry = file->f_path.dentry;
-
-		retval = -ENOTDIR;
-		if (!S_ISDIR(dentry->d_inode->i_mode))
-			goto fput_fail;
-
-		retval = file_permission(file, MAY_EXEC);
-		if (retval)
-			goto fput_fail;
-
+		/*
+		 * We allow O_PATH fd to be used relative
+		 * to "" name. This indicate operate on
+		 * dfd itself.
+		 */
+		if (!S_ISDIR(dentry->d_inode->i_mode)) {
+			if (!(file->f_flags & O_PATH) || (*name != 0)) {
+				retval = -ENOTDIR;
+				goto fput_fail;
+			}
+		} else {
+			/*
+			 * if directory and relative name is not ""
+			 * then we need to check for EXEC permission.
+			 * If relative name is "" the descriptor should
+			 * be O_PATH descriptor.
+			 */
+			if (*name != 0) {
+				retval = file_permission(file, MAY_EXEC);
+				if (retval)
+					goto fput_fail;
+			} else if (!(file->f_flags & O_PATH)) {
+				retval = -ENOENT;
+				goto fput_fail;
+			}
+		}
 		nd->path = file->f_path;
 		path_get(&file->f_path);
 
@@ -1926,7 +1979,7 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
 		 struct path *path)
 {
 	struct nameidata nd;
-	char *tmp = getname(name);
+	char *tmp = getname_null(name);
 	int err = PTR_ERR(tmp);
 	if (!IS_ERR(tmp)) {
 
@@ -3806,7 +3859,6 @@ EXPORT_SYMBOL(follow_down_one);
 EXPORT_SYMBOL(follow_down);
 EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
-EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(lock_rename);
 EXPORT_SYMBOL(lookup_one_len);
 EXPORT_SYMBOL(page_follow_link_light);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ac6e899..3f1e7fc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2004,7 +2004,15 @@ struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
 extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
 				 const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
-extern char * getname(const char __user *);
+extern char *do_getname(const char __user *, int allow_null_name);
+static inline char *getname(const char __user *name)
+{
+	return do_getname(name, 0);
+}
+static inline char *getname_null(const char __user *name)
+{
+	return do_getname(name, 1);
+}
 
 /* fs/ioctl.c */
 
-- 
1.7.1


  parent reply	other threads:[~2011-01-29 19:09 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-29 19:08 [PATCH -V26 00/16] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 01/16] exportfs: Return the minimum required handle size Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 02/16] vfs: Add name to file handle conversion support Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 03/16] vfs: Add open by file handle support Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 04/16] fs: Don't allow to create hardlink for deleted file Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 05/16] fs: Remove i_nlink check from file system link callback Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 06/16] x86: Add new syscalls for x86_32 Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 07/16] x86: Add new syscalls for x86_64 Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 08/16] unistd.h: Add new syscalls numbers to asm-generic Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 09/16] vfs: Export file system uuid via /proc/<pid>/mountinfo Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 10/16] ext3: Copy fs UUID to superblock Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 11/16] ext4: " Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 12/16] vfs: Add O_PATH open flag Aneesh Kumar K.V
2011-01-29 19:08 ` Aneesh Kumar K.V [this message]
2011-01-29 19:08 ` [PATCH -V26 14/16] fs: limit linkat syscall with null relative name to CAP_DAC_READ_SEARCH Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 15/16] vfs: enable O_PATH descriptor for few syscalls Aneesh Kumar K.V
2011-01-29 19:08 ` [PATCH -V26 16/16] vfs: enable "" pathname in openat syscall Aneesh Kumar K.V

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=1296328099-23263-14-git-send-email-aneesh.kumar@linux.vnet.ibm.com \
    --to=aneesh.kumar@linux.vnet.ibm.com \
    --cc=adilger@sun.com \
    --cc=bfields@fieldses.org \
    --cc=corbet@lwn.net \
    --cc=hch@infradead.org \
    --cc=hooanon05@yahoo.co.jp \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=neilb@suse.de \
    --cc=npiggin@kernel.dk \
    --cc=philippe.deniel@CEA.FR \
    --cc=sfrench@us.ibm.com \
    --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.