linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kentaro Takeda <takedakn@nttdata.co.jp>
To: viro@ZenIV.linux.org.uk
Cc: linux-fsdevel@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org, miklos@szeredi.hu,
	hch@infradead.org, akpm@linux-foundation.org,
	Toshiharu Harada <haradats@nttdata.co.jp>
Subject: Confirmation of methods for calculating requested pathname.
Date: Tue, 19 Aug 2008 13:19:42 +0900	[thread overview]
Message-ID: <48AA49DE.6000006@nttdata.co.jp> (raw)

The current Linux kernel is not designed to pass vfsmount parameter
that is crucial for pathname-based security including AppArmor and
TOMOYO Linux, to LSM. Though both projects have been proposing
patches to calculate pathname, none of them have been accepted as
you know.

To find the reason for NACK, we examined past proposals and the
threads. And we came to understand that you oppose accessing vfsmount
inside vfs helper functions. Is our understanding correct?

If our understanding is correct, we would like to propose a new
method that does not require modifications to vfs helper functions.
Attached patch is a trial of this method.

vfs helper functions are surrounded by mnt_want_write() and
mnt_drop_write() pairs which receive "struct vfsmount" parameter
since 2.6.26. So, by remembering the absolute pathname of "struct
vfsmount" of the moment, LSM module can calculate an absolute
pathname of the given "struct dentry" parameter inside vfs_*
functions, without passing "struct vfsmount" parameter to vfs_*
functions.

This approach doesn't access vfsmount inside vfs helper functions,
and modification of existing kernel is only in task_struct and
mnt_want/drop_write().

We would like to hear your comments as fs maintainer.

Regards,

---
Subject: Remembering previously referenced vfsmount's pathname.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 fs/Kconfig                |   18 ++++++++++++++++++
 fs/namespace.c            |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/init_task.h |    7 +++++++
 include/linux/sched.h     |    3 +++
 kernel/fork.c             |    8 ++++++++
 5 files changed, 82 insertions(+)

--- linux-2.6.27-rc3.orig/fs/Kconfig
+++ linux-2.6.27-rc3/fs/Kconfig
@@ -2094,4 +2094,22 @@ endif
 source "fs/nls/Kconfig"
 source "fs/dlm/Kconfig"
 
+config REMEMBER_VFSMOUNT_PATH
+	bool "Remember previously referenced vfsmount's pathname."
+	help
+	  The vfs_* functions (e.g. vfs_mkdir) don't receive "struct vfsmount"
+	  parameter, making it impossible to calculate an absolute pathname of
+	  the given "struct dentry" parameter inside vfs_* functions.
+	
+	  If someone wants to get an absolute pathname of the given
+	  "struct dentry" parameter, he/she must calculate it outside
+	  vfs_* functions.
+	
+	  However, vfs_* functions are surrounded by mnt_want_write() and
+	  mnt_drop_write() pairs which receive "struct vfsmount" parameter.
+	  So, by remembering the absolute pathname of "struct vfsmount" of
+	  the moment, he/she can calculate an absolute pathname of the given
+	  "struct dentry" parameter inside vfs_* functions, without passing
+	  "struct vfsmount" parameter to vfs_* functions.
+
 endmenu
--- linux-2.6.27-rc3.orig/fs/namespace.c
+++ linux-2.6.27-rc3/fs/namespace.c
@@ -231,6 +231,41 @@ static inline void use_cpu_writer_for_mo
 	cpu_writer->mnt = mnt;
 }
 
+#ifdef CONFIG_REMEMBER_VFSMOUNT_PATH
+static void forget_vfsmount_path(void)
+{
+	struct task_struct *task = current;
+	kfree(task->current_vfsmount_path);
+	task->current_vfsmount_path = NULL;
+}
+
+static bool remember_vfsmount_path(struct vfsmount *mnt)
+{
+	struct task_struct *task = current;
+	struct path path = { mnt, mnt->mnt_root };
+	char *page;
+	char *ret;
+	if (task->current_vfsmount_path)
+		forget_vfsmount_path();
+	page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!page)
+		goto out;
+	ret = d_path(&path, page, PAGE_SIZE);
+	if (IS_ERR(ret))
+		goto out_free;
+	ret = kstrdup(ret, GFP_KERNEL);
+	if (!ret)
+		goto out_free;
+	kfree(page);
+	task->current_vfsmount_path = ret;
+	return 1;
+ out_free:
+	kfree(page);
+ out:
+	return 0;
+}
+#endif
+
 /*
  * Most r/o checks on a fs are for operations that take
  * discrete amounts of time, like a write() or unlink().
@@ -253,6 +288,10 @@ int mnt_want_write(struct vfsmount *mnt)
 {
 	int ret = 0;
 	struct mnt_writer *cpu_writer;
+#ifdef CONFIG_REMEMBER_VFSMOUNT_PATH
+	if (!remember_vfsmount_path(mnt))
+		return -ENOMEM;
+#endif
 
 	cpu_writer = &get_cpu_var(mnt_writers);
 	spin_lock(&cpu_writer->lock);
@@ -265,6 +304,10 @@ int mnt_want_write(struct vfsmount *mnt)
 out:
 	spin_unlock(&cpu_writer->lock);
 	put_cpu_var(mnt_writers);
+#ifdef CONFIG_REMEMBER_VFSMOUNT_PATH
+	if (ret)
+		forget_vfsmount_path();
+#endif
 	return ret;
 }
 EXPORT_SYMBOL_GPL(mnt_want_write);
@@ -362,6 +405,9 @@ void mnt_drop_write(struct vfsmount *mnt
 	 * we could theoretically wrap __mnt_writers.
 	 */
 	put_cpu_var(mnt_writers);
+#ifdef CONFIG_REMEMBER_VFSMOUNT_PATH
+	forget_vfsmount_path();
+#endif
 }
 EXPORT_SYMBOL_GPL(mnt_drop_write);
 
--- linux-2.6.27-rc3.orig/include/linux/init_task.h
+++ linux-2.6.27-rc3/include/linux/init_task.h
@@ -113,6 +113,12 @@ extern struct group_info init_groups;
 # define CAP_INIT_BSET  CAP_INIT_EFF_SET
 #endif
 
+#ifdef CONFIG_REMEMBER_VFSMOUNT_PATH
+#define INIT_VFSMOUNT_PATH .current_vfsmount_path = NULL,
+#else
+#define INIT_VFSMOUNT_PATH
+#endif
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -179,6 +185,7 @@ extern struct group_info init_groups;
 	INIT_IDS							\
 	INIT_TRACE_IRQFLAGS						\
 	INIT_LOCKDEP							\
+	INIT_VFSMOUNT_PATH                                              \
 }
 
 
--- linux-2.6.27-rc3.orig/include/linux/sched.h
+++ linux-2.6.27-rc3/include/linux/sched.h
@@ -1300,6 +1300,9 @@ struct task_struct {
 	int latency_record_count;
 	struct latency_record latency_record[LT_SAVECOUNT];
 #endif
+#ifdef CONFIG_REMEMBER_VFSMOUNT_PATH
+	const char *current_vfsmount_path;
+#endif
 };
 
 /*
--- linux-2.6.27-rc3.orig/kernel/fork.c
+++ linux-2.6.27-rc3/kernel/fork.c
@@ -1051,6 +1051,14 @@ static struct task_struct *copy_process(
 	p->blocked_on = NULL; /* not blocked yet */
 #endif
 
+#ifdef CONFIG_REMEMBER_VFSMOUNT_PATH
+	/*
+	 * It seems to me that this function is called between mnt_want_write()
+	 * and mnt_drop_write(). I don't know why.
+	 */
+	p->current_vfsmount_path = NULL;
+#endif
+
 	/* Perform scheduler related setup. Assign this task to a CPU. */
 	sched_fork(p, clone_flags);
 



             reply	other threads:[~2008-08-19  4:19 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-19  4:19 Kentaro Takeda [this message]
2008-09-02  4:31 ` (repost) Confirmation of methods for calculating requested pathname Kentaro Takeda
2008-09-02  5:06   ` Alexey Dobriyan
2008-09-02 10:12     ` Kentaro Takeda
2008-09-02  6:42   ` Jamie Lokier
2008-09-02 13:11   ` Serge E. Hallyn
2008-09-02 13:35     ` Tetsuo Handa
2008-09-02 13:37     ` Stephen Smalley
2008-09-02 14:06       ` Miklos Szeredi

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=48AA49DE.6000006@nttdata.co.jp \
    --to=takedakn@nttdata.co.jp \
    --cc=akpm@linux-foundation.org \
    --cc=haradats@nttdata.co.jp \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).