[RFC][PATCH 10/11] security: AppArmor - Add flags to d_path

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds a new function d_path_flags which takes an additional flags
parameter.   Adding a new function rather than ammending the existing d_path
was done to avoid impact on the current users.

It is not essential for inclusion with AppArmor (the apparmor_mediation.patch
can easily be revised to use plain d_path) but it enables cleaner code 
["(delete)" handling] and closes a loophole with pathname generation for 
chrooted tasks. 

It currently adds two flags:

DPATH_SYSROOT:
	d_path should generate a path from the system root rather than the
	task's current root. 

	For AppArmor this enables generation of absolute pathnames in all
	cases.  Currently when a task is chrooted, file access is reported
	relative to the chroot.  Because it is currently not possible to 
	obtain the absolute path in an SMP safe way, without this patch 
	AppArmor will have to report chroot-relative pathnames.
	
DPATH_NODELETED:
	d_path should not append "(deleted)" to unhashed entries. Sometimes
	this information is not useful for the caller and the string can
	exist as the suffix of a valid pathname.

Signed-off-by: Tony Jones <[email protected]>

---
 fs/dcache.c            |   48 ++++++++++++++++++++++++++++++++----------------
 include/linux/dcache.h |    7 +++++++
 2 files changed, 39 insertions(+), 16 deletions(-)

--- linux-2.6.17-rc1.orig/fs/dcache.c
+++ linux-2.6.17-rc1/fs/dcache.c
@@ -1381,9 +1381,11 @@
  * @rootmnt: vfsmnt to which the root dentry belongs
  * @buffer: buffer to return value in
  * @buflen: buffer length
+ * @flags: control flags
  *
  * Convert a dentry into an ASCII path name. If the entry has been deleted
- * the string " (deleted)" is appended. Note that this is ambiguous.
+ * and DPATH_NODELETED is not specified in flags then the string " (deleted)"
+ * is appended. Note that this is ambiguous.
  *
  * Returns the buffer or an error code if the path was too long.
  *
@@ -1391,7 +1393,7 @@
  */
 static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
 			struct dentry *root, struct vfsmount *rootmnt,
-			char *buffer, int buflen)
+			char *buffer, int buflen, unsigned int flags)
 {
 	char * end = buffer+buflen;
 	char * retval;
@@ -1399,7 +1401,8 @@
 
 	*--end = '\0';
 	buflen--;
-	if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
+	if (!(flags & DPATH_NODELETED) &&
+	    !IS_ROOT(dentry) && d_unhashed(dentry)) {
 		buflen -= 10;
 		end -= 10;
 		if (buflen < 0)
@@ -1416,7 +1419,8 @@
 	for (;;) {
 		struct dentry * parent;
 
-		if (dentry == root && vfsmnt == rootmnt)
+		if (!(flags & DPATH_SYSROOT) &&
+		    dentry == root && vfsmnt == rootmnt)
 			break;
 		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
 			/* Global root? */
@@ -1458,25 +1462,36 @@
 }
 
 /* write full pathname into buffer and return start of pathname */
-char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-				char *buf, int buflen)
+char * d_path_flags(struct dentry *dentry, struct vfsmount *vfsmnt,
+		    char *buf, int buflen, unsigned int flags)
 {
 	char *res;
-	struct vfsmount *rootmnt;
-	struct dentry *root;
+	struct vfsmount *rootmnt = NULL;
+	struct dentry *root = NULL;
 
-	read_lock(&current->fs->lock);
-	rootmnt = mntget(current->fs->rootmnt);
-	root = dget(current->fs->root);
-	read_unlock(&current->fs->lock);
+	if (!(flags & DPATH_SYSROOT)){
+		read_lock(&current->fs->lock);
+		rootmnt = mntget(current->fs->rootmnt);
+		root = dget(current->fs->root);
+		read_unlock(&current->fs->lock);
+	}
 	spin_lock(&dcache_lock);
-	res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
+	res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, flags);
 	spin_unlock(&dcache_lock);
-	dput(root);
-	mntput(rootmnt);
+	if (!(flags & DPATH_SYSROOT)){
+		dput(root);
+		mntput(rootmnt);
+	}
 	return res;
 }
 
+/* original d_path without support for flags */
+char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+	      char *buf, int buflen)
+{
+	return d_path_flags(dentry, vfsmnt, buf, buflen, 0);
+}
+
 /*
  * NOTE! The user-level library version returns a
  * character pointer. The kernel system call just
@@ -1519,7 +1534,7 @@
 		unsigned long len;
 		char * cwd;
 
-		cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
+		cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 0);
 		spin_unlock(&dcache_lock);
 
 		error = PTR_ERR(cwd);
@@ -1771,6 +1786,7 @@
 EXPORT_SYMBOL(d_invalidate);
 EXPORT_SYMBOL(d_lookup);
 EXPORT_SYMBOL(d_move);
+EXPORT_SYMBOL(d_path_flags);
 EXPORT_SYMBOL(d_path);
 EXPORT_SYMBOL(d_prune_aliases);
 EXPORT_SYMBOL(d_rehash);
--- linux-2.6.17-rc1.orig/include/linux/dcache.h
+++ linux-2.6.17-rc1/include/linux/dcache.h
@@ -164,6 +164,10 @@
 
 #define DCACHE_INOTIFY_PARENT_WATCHED	0x0020 /* Parent inode is watched */
 
+/* dpath flags */
+#define DPATH_SYSROOT		0x0001	/* continue past fsroot (chroot) */
+#define DPATH_NODELETED		0x0002	/* do not append " (deleted)" */
+
 extern spinlock_t dcache_lock;
 
 /**
@@ -281,6 +285,9 @@
 extern int d_validate(struct dentry *, struct dentry *);
 
 extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
+
+extern char * d_path_flags(struct dentry *, struct vfsmount *, char *, int,
+		     unsigned int);
   
 /* Allocation counts.. */
 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux