* [PATCH 2/2] vfs: show unreachable paths in getcwd and proc
2010-05-27 10:29 Miklos Szeredi
@ 2010-05-27 10:30 ` Miklos Szeredi
0 siblings, 0 replies; 6+ messages in thread
From: Miklos Szeredi @ 2010-05-27 10:30 UTC (permalink / raw)
To: Al Viro; +Cc: John Johansen, Tetsuo Handa, linux-fsdevel, linux-kernel
From: Miklos Szeredi <mszeredi@suse.cz>
Prepend "(unreachable)" to path strings if the path is not reachable
from the current root.
Two places updated are
- the return string from getcwd()
- and symlinks under /proc/$PID.
Other uses of d_path() are left unchanged (we know that some old
software crashes if /proc/mounts is changed).
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/dcache.c | 82 +++++++++++++++++++++++++++++++++++++++++--------
fs/proc/base.c | 2 -
include/linux/dcache.h | 1
3 files changed, 72 insertions(+), 13 deletions(-)
Index: linux-2.6/fs/dcache.c
===================================================================
--- linux-2.6.orig/fs/dcache.c 2010-05-27 12:22:21.000000000 +0200
+++ linux-2.6/fs/dcache.c 2010-05-27 12:22:24.000000000 +0200
@@ -1957,6 +1957,33 @@ int __d_path(const struct path *path, st
return error;
}
+static void current_root(struct path *root)
+{
+ read_lock(¤t->fs->lock);
+ *root = current->fs->root;
+ path_get(root);
+ read_unlock(¤t->fs->lock);
+}
+
+static int __d_path_with_deleted(const struct path *path, struct path *root,
+ char **buffer, int *buflen)
+{
+ int error;
+
+ prepend(buffer, buflen, "\0", 1);
+ if (d_unlinked(path->dentry)) {
+ error = prepend(buffer, buflen, " (deleted)", 10);
+ if (error)
+ return error;
+ }
+ return __d_path(path, root, buffer, buflen);
+}
+
+static int prepend_unreachable(char **buffer, int *buflen)
+{
+ return prepend(buffer, buflen, "(unreachable)", 13);
+}
+
/**
* d_path - return the path of a dentry
* @path: path to report
@@ -1990,27 +2017,51 @@ char *d_path(const struct path *path, ch
if (path->dentry->d_op && path->dentry->d_op->d_dname)
return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
- read_lock(¤t->fs->lock);
- root = current->fs->root;
- path_get(&root);
- read_unlock(¤t->fs->lock);
+ current_root(&root);
spin_lock(&dcache_lock);
ptr = buf + buflen;
- prepend(&ptr, &buflen, "\0", 1);
- if (d_unlinked(path->dentry)) {
- error = prepend(&ptr, &buflen, " (deleted)", 10);
- if (error)
- goto out;
- }
tmp = root;
- error = __d_path(path, &tmp, &ptr, &buflen);
-out:
+ error = __d_path_with_deleted(path, &tmp, &ptr, &buflen);
spin_unlock(&dcache_lock);
path_put(&root);
return error ? ERR_PTR(error) : ptr;
}
EXPORT_SYMBOL(d_path);
+/**
+ * d_path_with_unreachable - return the path of a dentry
+ * @path: path to report
+ * @buf: buffer to return value in
+ * @buflen: buffer length
+ *
+ * The difference from d_path() is that this prepends "(unreachable)"
+ * to paths which are unreachable from the current process' root.
+ */
+char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
+{
+ char *ptr;
+ struct path root;
+ struct path tmp;
+ int error;
+
+ if (path->dentry->d_op && path->dentry->d_op->d_dname)
+ return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
+
+ current_root(&root);
+ spin_lock(&dcache_lock);
+ ptr = buf + buflen;
+ tmp = root;
+ error = __d_path_with_deleted(path, &tmp, &ptr, &buflen);
+ if (!error) {
+ if (tmp.dentry != root.dentry || tmp.mnt != root.mnt)
+ error = prepend_unreachable(&ptr, &buflen);
+ }
+
+ spin_unlock(&dcache_lock);
+ path_put(&root);
+ return error ? ERR_PTR(error) : ptr;
+}
+
/*
* Helper function for dentry_operations.d_dname() members
*/
@@ -2118,6 +2169,13 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
if (error)
goto out;
+ /* Unreachable from current root */
+ if (tmp.dentry != root.dentry || tmp.mnt != root.mnt) {
+ error = prepend_unreachable(&cwd, &buflen);
+ if (error)
+ goto out;
+ }
+
error = -ERANGE;
len = PAGE_SIZE + page - cwd;
if (len <= size) {
Index: linux-2.6/include/linux/dcache.h
===================================================================
--- linux-2.6.orig/include/linux/dcache.h 2010-05-27 12:13:48.000000000 +0200
+++ linux-2.6/include/linux/dcache.h 2010-05-27 12:22:24.000000000 +0200
@@ -315,6 +315,7 @@ extern char *dynamic_dname(struct dentry
extern int __d_path(const struct path *path, struct path *root, char **, int *);
extern char *d_path(const struct path *, char *, int);
+extern char *d_path_with_unreachable(const struct path *, char *, int);
extern char *dentry_path(struct dentry *, char *, int);
/* Allocation counts.. */
Index: linux-2.6/fs/proc/base.c
===================================================================
--- linux-2.6.orig/fs/proc/base.c 2010-05-27 11:53:55.000000000 +0200
+++ linux-2.6/fs/proc/base.c 2010-05-27 12:22:24.000000000 +0200
@@ -1438,7 +1438,7 @@ static int do_proc_readlink(struct path
if (!tmp)
return -ENOMEM;
- pathname = d_path(path, tmp, PAGE_SIZE);
+ pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE);
len = PTR_ERR(pathname);
if (IS_ERR(pathname))
goto out;
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] vfs: sanitize __d_path()
@ 2010-06-04 11:52 Miklos Szeredi
2010-06-04 11:53 ` [PATCH 2/2] vfs: show unreachable paths in getcwd and proc Miklos Szeredi
2010-06-04 14:10 ` [PATCH 1/2] vfs: sanitize __d_path() Tetsuo Handa
0 siblings, 2 replies; 6+ messages in thread
From: Miklos Szeredi @ 2010-06-04 11:52 UTC (permalink / raw)
To: Al Viro, Andrew Morton
Cc: John Johansen, Tetsuo Handa, linux-fsdevel, linux-kernel
From: Miklos Szeredi <mszeredi@suse.cz>
__d_path() no longer appends " (deleted)" to unlinked paths. This is
moved into d_path() which is the only caller that cares.
If a global root is reached then __d_path() no longer prepends the
name of the root dentry. This was needed by pseudo filesystems, but
the d_dname() method has superseded it.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/dcache.c | 99 ++++++++++++++++++++-------------------------
fs/seq_file.c | 12 +++--
include/linux/dcache.h | 2
security/tomoyo/realpath.c | 17 ++++---
4 files changed, 62 insertions(+), 68 deletions(-)
Index: linux-2.6/fs/dcache.c
===================================================================
--- linux-2.6.orig/fs/dcache.c 2010-05-27 12:13:46.000000000 +0200
+++ linux-2.6/fs/dcache.c 2010-05-27 12:22:21.000000000 +0200
@@ -1904,78 +1904,57 @@ static int prepend_name(char **buffer, i
* __d_path - return the path of a dentry
* @path: the dentry/vfsmount to report
* @root: root vfsmnt/dentry (may be modified by this function)
- * @buffer: buffer to return value in
- * @buflen: buffer length
+ * @buffer: end of free buffer, will point to the result on return
+ * @buflen: pointer to buffer length
*
- * Convert a dentry into an ASCII path name. If the entry has been deleted
- * the string " (deleted)" is appended. Note that this is ambiguous.
+ * Convert a vfsmount+dentry into an ASCII path name.
*
- * Returns a pointer into the buffer or an error code if the
- * path was too long.
+ * Returns an error code if the path was too long.
*
* "buflen" should be positive. Caller holds the dcache_lock.
*
* If path is not reachable from the supplied root, then the value of
* root is changed (without modifying refcounts).
*/
-char *__d_path(const struct path *path, struct path *root,
- char *buffer, int buflen)
+int __d_path(const struct path *path, struct path *root,
+ char **buffer, int *buflen)
{
struct dentry *dentry = path->dentry;
struct vfsmount *vfsmnt = path->mnt;
- char *end = buffer + buflen;
- char *retval;
+ bool slash = false;
+ int error = 0;
spin_lock(&vfsmount_lock);
- prepend(&end, &buflen, "\0", 1);
- if (d_unlinked(dentry) &&
- (prepend(&end, &buflen, " (deleted)", 10) != 0))
- goto Elong;
-
- if (buflen < 1)
- goto Elong;
- /* Get '/' right */
- retval = end-1;
- *retval = '/';
-
- for (;;) {
- struct dentry * parent;
-
- if (dentry == root->dentry && vfsmnt == root->mnt)
- break;
+ while (dentry != root->dentry || vfsmnt != root->mnt) {
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
/* Global root? */
if (vfsmnt->mnt_parent == vfsmnt) {
- goto global_root;
+ root->mnt = vfsmnt;
+ root->dentry = dentry;
+ break;
}
dentry = vfsmnt->mnt_mountpoint;
vfsmnt = vfsmnt->mnt_parent;
- continue;
+ } else {
+ struct dentry *parent = dentry->d_parent;
+
+ prefetch(parent);
+ error = prepend_name(buffer, buflen, &dentry->d_name);
+ if (!error)
+ error = prepend(buffer, buflen, "/", 1);
+ if (error)
+ break;
+
+ slash = true;
+ dentry = parent;
}
- parent = dentry->d_parent;
- prefetch(parent);
- if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
- (prepend(&end, &buflen, "/", 1) != 0))
- goto Elong;
- retval = end;
- dentry = parent;
}
-
-out:
spin_unlock(&vfsmount_lock);
- return retval;
-global_root:
- retval += 1; /* hit the slash */
- if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
- goto Elong;
- root->mnt = vfsmnt;
- root->dentry = dentry;
- goto out;
+ if (!error && !slash)
+ error = prepend(buffer, buflen, "/", 1);
-Elong:
- retval = ERR_PTR(-ENAMETOOLONG);
- goto out;
+ return error;
}
/**
@@ -1996,9 +1975,10 @@ Elong:
*/
char *d_path(const struct path *path, char *buf, int buflen)
{
- char *res;
+ char *ptr;
struct path root;
struct path tmp;
+ int error;
/*
* We have various synthetic filesystems that never get mounted. On
@@ -2015,11 +1995,19 @@ char *d_path(const struct path *path, ch
path_get(&root);
read_unlock(¤t->fs->lock);
spin_lock(&dcache_lock);
+ ptr = buf + buflen;
+ prepend(&ptr, &buflen, "\0", 1);
+ if (d_unlinked(path->dentry)) {
+ error = prepend(&ptr, &buflen, " (deleted)", 10);
+ if (error)
+ goto out;
+ }
tmp = root;
- res = __d_path(path, &tmp, buf, buflen);
+ error = __d_path(path, &tmp, &ptr, &buflen);
+out:
spin_unlock(&dcache_lock);
path_put(&root);
- return res;
+ return error ? ERR_PTR(error) : ptr;
}
EXPORT_SYMBOL(d_path);
@@ -2120,13 +2108,14 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
if (!d_unlinked(pwd.dentry)) {
unsigned long len;
struct path tmp = root;
- char * cwd;
+ int buflen = PAGE_SIZE;
+ char *cwd = page + buflen;
- cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
+ prepend(&cwd, &buflen, "\0", 1);
+ error = __d_path(&pwd, &tmp, &cwd, &buflen);
spin_unlock(&dcache_lock);
- error = PTR_ERR(cwd);
- if (IS_ERR(cwd))
+ if (error)
goto out;
error = -ERANGE;
Index: linux-2.6/fs/seq_file.c
===================================================================
--- linux-2.6.orig/fs/seq_file.c 2010-05-27 12:13:46.000000000 +0200
+++ linux-2.6/fs/seq_file.c 2010-05-27 12:13:48.000000000 +0200
@@ -448,7 +448,8 @@ int seq_path(struct seq_file *m, struct
EXPORT_SYMBOL(seq_path);
/*
- * Same as seq_path, but relative to supplied root.
+ * Same as seq_path, but relative to supplied root and doesn't append
+ * " (deleted)" for unlinked dentries.
*
* root may be changed, see __d_path().
*/
@@ -460,13 +461,14 @@ int seq_path_root(struct seq_file *m, st
int res = -ENAMETOOLONG;
if (size) {
- char *p;
+ int buflen = size - 1;
+ char *p = buf + buflen;
+ *p = '\0';
spin_lock(&dcache_lock);
- p = __d_path(path, root, buf, size);
+ res = __d_path(path, root, &p, &buflen);
spin_unlock(&dcache_lock);
- res = PTR_ERR(p);
- if (!IS_ERR(p)) {
+ if (!res) {
char *end = mangle_path(buf, p, esc);
if (end)
res = end - buf;
Index: linux-2.6/include/linux/dcache.h
===================================================================
--- linux-2.6.orig/include/linux/dcache.h 2010-05-27 12:13:46.000000000 +0200
+++ linux-2.6/include/linux/dcache.h 2010-05-27 12:13:48.000000000 +0200
@@ -313,7 +313,7 @@ extern int d_validate(struct dentry *, s
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
-extern char *__d_path(const struct path *path, struct path *root, char *, int);
+extern int __d_path(const struct path *path, struct path *root, char **, int *);
extern char *d_path(const struct path *, char *, int);
extern char *dentry_path(struct dentry *, char *, int);
Index: linux-2.6/security/tomoyo/realpath.c
===================================================================
--- linux-2.6.orig/security/tomoyo/realpath.c 2010-05-27 12:13:46.000000000 +0200
+++ linux-2.6/security/tomoyo/realpath.c 2010-05-27 12:13:48.000000000 +0200
@@ -77,7 +77,7 @@ int tomoyo_encode(char *buffer, int bufl
int tomoyo_realpath_from_path2(struct path *path, char *newname,
int newname_len)
{
- int error = -ENOMEM;
+ int error = 0;
struct dentry *dentry = path->dentry;
char *sp;
@@ -88,26 +88,29 @@ int tomoyo_realpath_from_path2(struct pa
static const int offset = 1536;
sp = dentry->d_op->d_dname(dentry, newname + offset,
newname_len - offset);
+ if (IS_ERR(sp))
+ error = PTR_ERR(sp);
} else {
struct path ns_root = {.mnt = NULL, .dentry = NULL};
+ int buflen = newname_len - 1;
+ sp = newname + buflen;
+ *sp = '\0';
spin_lock(&dcache_lock);
/* go to whatever namespace root we are under */
- sp = __d_path(path, &ns_root, newname, newname_len);
+ error = __d_path(path, &ns_root, &sp, &buflen);
spin_unlock(&dcache_lock);
/* Prepend "/proc" prefix if using internal proc vfs mount. */
- if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
+ if (!error && (path->mnt->mnt_flags & MNT_INTERNAL) &&
(path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
sp -= 5;
if (sp >= newname)
memcpy(sp, "/proc", 5);
else
- sp = ERR_PTR(-ENOMEM);
+ error = -ENOMEM;
}
}
- if (IS_ERR(sp))
- error = PTR_ERR(sp);
- else
+ if (!error)
error = tomoyo_encode(newname, sp - newname, sp);
/* Append trailing '/' if dentry is a directory. */
if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] vfs: show unreachable paths in getcwd and proc
2010-06-04 11:52 [PATCH 1/2] vfs: sanitize __d_path() Miklos Szeredi
@ 2010-06-04 11:53 ` Miklos Szeredi
2010-06-15 7:31 ` Miklos Szeredi
2010-06-15 8:18 ` Nick Piggin
2010-06-04 14:10 ` [PATCH 1/2] vfs: sanitize __d_path() Tetsuo Handa
1 sibling, 2 replies; 6+ messages in thread
From: Miklos Szeredi @ 2010-06-04 11:53 UTC (permalink / raw)
To: Al Viro, Andrew Morton
Cc: John Johansen, Tetsuo Handa, linux-fsdevel, linux-kernel
From: Miklos Szeredi <mszeredi@suse.cz>
Prepend "(unreachable)" to path strings if the path is not reachable
from the current root.
Two places updated are
- the return string from getcwd()
- and symlinks under /proc/$PID.
Other uses of d_path() are left unchanged (we know that some old
software crashes if /proc/mounts is changed).
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/dcache.c | 82 +++++++++++++++++++++++++++++++++++++++++--------
fs/proc/base.c | 2 -
include/linux/dcache.h | 1
3 files changed, 72 insertions(+), 13 deletions(-)
Index: linux-2.6/fs/dcache.c
===================================================================
--- linux-2.6.orig/fs/dcache.c 2010-05-27 12:22:21.000000000 +0200
+++ linux-2.6/fs/dcache.c 2010-05-27 12:22:24.000000000 +0200
@@ -1957,6 +1957,33 @@ int __d_path(const struct path *path, st
return error;
}
+static void current_root(struct path *root)
+{
+ read_lock(¤t->fs->lock);
+ *root = current->fs->root;
+ path_get(root);
+ read_unlock(¤t->fs->lock);
+}
+
+static int __d_path_with_deleted(const struct path *path, struct path *root,
+ char **buffer, int *buflen)
+{
+ int error;
+
+ prepend(buffer, buflen, "\0", 1);
+ if (d_unlinked(path->dentry)) {
+ error = prepend(buffer, buflen, " (deleted)", 10);
+ if (error)
+ return error;
+ }
+ return __d_path(path, root, buffer, buflen);
+}
+
+static int prepend_unreachable(char **buffer, int *buflen)
+{
+ return prepend(buffer, buflen, "(unreachable)", 13);
+}
+
/**
* d_path - return the path of a dentry
* @path: path to report
@@ -1990,27 +2017,51 @@ char *d_path(const struct path *path, ch
if (path->dentry->d_op && path->dentry->d_op->d_dname)
return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
- read_lock(¤t->fs->lock);
- root = current->fs->root;
- path_get(&root);
- read_unlock(¤t->fs->lock);
+ current_root(&root);
spin_lock(&dcache_lock);
ptr = buf + buflen;
- prepend(&ptr, &buflen, "\0", 1);
- if (d_unlinked(path->dentry)) {
- error = prepend(&ptr, &buflen, " (deleted)", 10);
- if (error)
- goto out;
- }
tmp = root;
- error = __d_path(path, &tmp, &ptr, &buflen);
-out:
+ error = __d_path_with_deleted(path, &tmp, &ptr, &buflen);
spin_unlock(&dcache_lock);
path_put(&root);
return error ? ERR_PTR(error) : ptr;
}
EXPORT_SYMBOL(d_path);
+/**
+ * d_path_with_unreachable - return the path of a dentry
+ * @path: path to report
+ * @buf: buffer to return value in
+ * @buflen: buffer length
+ *
+ * The difference from d_path() is that this prepends "(unreachable)"
+ * to paths which are unreachable from the current process' root.
+ */
+char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
+{
+ char *ptr;
+ struct path root;
+ struct path tmp;
+ int error;
+
+ if (path->dentry->d_op && path->dentry->d_op->d_dname)
+ return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
+
+ current_root(&root);
+ spin_lock(&dcache_lock);
+ ptr = buf + buflen;
+ tmp = root;
+ error = __d_path_with_deleted(path, &tmp, &ptr, &buflen);
+ if (!error) {
+ if (tmp.dentry != root.dentry || tmp.mnt != root.mnt)
+ error = prepend_unreachable(&ptr, &buflen);
+ }
+
+ spin_unlock(&dcache_lock);
+ path_put(&root);
+ return error ? ERR_PTR(error) : ptr;
+}
+
/*
* Helper function for dentry_operations.d_dname() members
*/
@@ -2118,6 +2169,13 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
if (error)
goto out;
+ /* Unreachable from current root */
+ if (tmp.dentry != root.dentry || tmp.mnt != root.mnt) {
+ error = prepend_unreachable(&cwd, &buflen);
+ if (error)
+ goto out;
+ }
+
error = -ERANGE;
len = PAGE_SIZE + page - cwd;
if (len <= size) {
Index: linux-2.6/include/linux/dcache.h
===================================================================
--- linux-2.6.orig/include/linux/dcache.h 2010-05-27 12:13:48.000000000 +0200
+++ linux-2.6/include/linux/dcache.h 2010-05-27 12:22:24.000000000 +0200
@@ -315,6 +315,7 @@ extern char *dynamic_dname(struct dentry
extern int __d_path(const struct path *path, struct path *root, char **, int *);
extern char *d_path(const struct path *, char *, int);
+extern char *d_path_with_unreachable(const struct path *, char *, int);
extern char *dentry_path(struct dentry *, char *, int);
/* Allocation counts.. */
Index: linux-2.6/fs/proc/base.c
===================================================================
--- linux-2.6.orig/fs/proc/base.c 2010-05-27 11:53:55.000000000 +0200
+++ linux-2.6/fs/proc/base.c 2010-05-27 12:22:24.000000000 +0200
@@ -1438,7 +1438,7 @@ static int do_proc_readlink(struct path
if (!tmp)
return -ENOMEM;
- pathname = d_path(path, tmp, PAGE_SIZE);
+ pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE);
len = PTR_ERR(pathname);
if (IS_ERR(pathname))
goto out;
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] vfs: sanitize __d_path()
2010-06-04 11:52 [PATCH 1/2] vfs: sanitize __d_path() Miklos Szeredi
2010-06-04 11:53 ` [PATCH 2/2] vfs: show unreachable paths in getcwd and proc Miklos Szeredi
@ 2010-06-04 14:10 ` Tetsuo Handa
1 sibling, 0 replies; 6+ messages in thread
From: Tetsuo Handa @ 2010-06-04 14:10 UTC (permalink / raw)
To: miklos; +Cc: viro, akpm, john.johansen, linux-fsdevel, linux-kernel
Miklos Szeredi wrote:
> -extern char *__d_path(const struct path *path, struct path *root, char *, int);
> +extern int __d_path(const struct path *path, struct path *root, char **, int *);
Does somebody use buflen after returning from __d_path()?
If nobody uses, we can pass it as "int" rather than "int *".
> --- linux-2.6.orig/security/tomoyo/realpath.c 2010-05-27 12:13:46.000000000 +0200
> +++ linux-2.6/security/tomoyo/realpath.c 2010-05-27 12:13:48.000000000 +0200
Sorry. This hunk will not apply because I modified this part
in order to support longer pathnames.
http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=blob;f=security/tomoyo/realpath.c;h=153fa23a05ccd90a9ff3b90c02cefbd9e0cb9126;hb=006dacc8a64e91f6d47c52aec6a9d894e5f93eba
New hunk will look like below.
---
security/tomoyo/realpath.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
--- security-testing-2.6.orig/security/tomoyo/realpath.c
+++ security-testing-2.6/security/tomoyo/realpath.c
@@ -94,6 +94,8 @@ char *tomoyo_realpath_from_path(struct p
return NULL;
is_dir = dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode);
while (1) {
+ int error;
+ int len;
struct path ns_root = { .mnt = NULL, .dentry = NULL };
char *pos;
buf_len <<= 1;
@@ -127,21 +129,24 @@ char *tomoyo_realpath_from_path(struct p
/* If we don't have a vfsmount, we can't calculate. */
if (!path->mnt)
break;
+ len = buflen - 1;
+ pos = buf + len;
+ *pos = '\0';
spin_lock(&dcache_lock);
/* go to whatever namespace root we are under */
- pos = __d_path(path, &ns_root, buf, buf_len);
+ error = __d_path(path, &ns_root, &pos, &len);
spin_unlock(&dcache_lock);
+ if (error)
+ continue;
/* Prepend "/proc" prefix if using internal proc vfs mount. */
- if (!IS_ERR(pos) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
+ if ((path->mnt->mnt_flags & MNT_INTERNAL) &&
(path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
pos -= 5;
if (pos >= buf)
memcpy(pos, "/proc", 5);
else
- pos = ERR_PTR(-ENOMEM);
+ continue;
}
- if (IS_ERR(pos))
- continue;
name = tomoyo_encode(pos);
break;
}
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] vfs: show unreachable paths in getcwd and proc
2010-06-04 11:53 ` [PATCH 2/2] vfs: show unreachable paths in getcwd and proc Miklos Szeredi
@ 2010-06-15 7:31 ` Miklos Szeredi
2010-06-15 8:18 ` Nick Piggin
1 sibling, 0 replies; 6+ messages in thread
From: Miklos Szeredi @ 2010-06-15 7:31 UTC (permalink / raw)
To: viro; +Cc: akpm, john.johansen, penguin-kernel, linux-fsdevel, linux-kernel
Hi Al,
Could you please consider these patches for 2.6.36?
Thanks,
Miklos
On Fri, 04 Jun 2010, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
>
> Prepend "(unreachable)" to path strings if the path is not reachable
> from the current root.
>
> Two places updated are
> - the return string from getcwd()
> - and symlinks under /proc/$PID.
>
> Other uses of d_path() are left unchanged (we know that some old
> software crashes if /proc/mounts is changed).
>
> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
> ---
> fs/dcache.c | 82 +++++++++++++++++++++++++++++++++++++++++--------
> fs/proc/base.c | 2 -
> include/linux/dcache.h | 1
> 3 files changed, 72 insertions(+), 13 deletions(-)
>
> Index: linux-2.6/fs/dcache.c
> ===================================================================
> --- linux-2.6.orig/fs/dcache.c 2010-05-27 12:22:21.000000000 +0200
> +++ linux-2.6/fs/dcache.c 2010-05-27 12:22:24.000000000 +0200
> @@ -1957,6 +1957,33 @@ int __d_path(const struct path *path, st
> return error;
> }
>
> +static void current_root(struct path *root)
> +{
> + read_lock(¤t->fs->lock);
> + *root = current->fs->root;
> + path_get(root);
> + read_unlock(¤t->fs->lock);
> +}
> +
> +static int __d_path_with_deleted(const struct path *path, struct path *root,
> + char **buffer, int *buflen)
> +{
> + int error;
> +
> + prepend(buffer, buflen, "\0", 1);
> + if (d_unlinked(path->dentry)) {
> + error = prepend(buffer, buflen, " (deleted)", 10);
> + if (error)
> + return error;
> + }
> + return __d_path(path, root, buffer, buflen);
> +}
> +
> +static int prepend_unreachable(char **buffer, int *buflen)
> +{
> + return prepend(buffer, buflen, "(unreachable)", 13);
> +}
> +
> /**
> * d_path - return the path of a dentry
> * @path: path to report
> @@ -1990,27 +2017,51 @@ char *d_path(const struct path *path, ch
> if (path->dentry->d_op && path->dentry->d_op->d_dname)
> return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
>
> - read_lock(¤t->fs->lock);
> - root = current->fs->root;
> - path_get(&root);
> - read_unlock(¤t->fs->lock);
> + current_root(&root);
> spin_lock(&dcache_lock);
> ptr = buf + buflen;
> - prepend(&ptr, &buflen, "\0", 1);
> - if (d_unlinked(path->dentry)) {
> - error = prepend(&ptr, &buflen, " (deleted)", 10);
> - if (error)
> - goto out;
> - }
> tmp = root;
> - error = __d_path(path, &tmp, &ptr, &buflen);
> -out:
> + error = __d_path_with_deleted(path, &tmp, &ptr, &buflen);
> spin_unlock(&dcache_lock);
> path_put(&root);
> return error ? ERR_PTR(error) : ptr;
> }
> EXPORT_SYMBOL(d_path);
>
> +/**
> + * d_path_with_unreachable - return the path of a dentry
> + * @path: path to report
> + * @buf: buffer to return value in
> + * @buflen: buffer length
> + *
> + * The difference from d_path() is that this prepends "(unreachable)"
> + * to paths which are unreachable from the current process' root.
> + */
> +char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
> +{
> + char *ptr;
> + struct path root;
> + struct path tmp;
> + int error;
> +
> + if (path->dentry->d_op && path->dentry->d_op->d_dname)
> + return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
> +
> + current_root(&root);
> + spin_lock(&dcache_lock);
> + ptr = buf + buflen;
> + tmp = root;
> + error = __d_path_with_deleted(path, &tmp, &ptr, &buflen);
> + if (!error) {
> + if (tmp.dentry != root.dentry || tmp.mnt != root.mnt)
> + error = prepend_unreachable(&ptr, &buflen);
> + }
> +
> + spin_unlock(&dcache_lock);
> + path_put(&root);
> + return error ? ERR_PTR(error) : ptr;
> +}
> +
> /*
> * Helper function for dentry_operations.d_dname() members
> */
> @@ -2118,6 +2169,13 @@ SYSCALL_DEFINE2(getcwd, char __user *, b
> if (error)
> goto out;
>
> + /* Unreachable from current root */
> + if (tmp.dentry != root.dentry || tmp.mnt != root.mnt) {
> + error = prepend_unreachable(&cwd, &buflen);
> + if (error)
> + goto out;
> + }
> +
> error = -ERANGE;
> len = PAGE_SIZE + page - cwd;
> if (len <= size) {
> Index: linux-2.6/include/linux/dcache.h
> ===================================================================
> --- linux-2.6.orig/include/linux/dcache.h 2010-05-27 12:13:48.000000000 +0200
> +++ linux-2.6/include/linux/dcache.h 2010-05-27 12:22:24.000000000 +0200
> @@ -315,6 +315,7 @@ extern char *dynamic_dname(struct dentry
>
> extern int __d_path(const struct path *path, struct path *root, char **, int *);
> extern char *d_path(const struct path *, char *, int);
> +extern char *d_path_with_unreachable(const struct path *, char *, int);
> extern char *dentry_path(struct dentry *, char *, int);
>
> /* Allocation counts.. */
> Index: linux-2.6/fs/proc/base.c
> ===================================================================
> --- linux-2.6.orig/fs/proc/base.c 2010-05-27 11:53:55.000000000 +0200
> +++ linux-2.6/fs/proc/base.c 2010-05-27 12:22:24.000000000 +0200
> @@ -1438,7 +1438,7 @@ static int do_proc_readlink(struct path
> if (!tmp)
> return -ENOMEM;
>
> - pathname = d_path(path, tmp, PAGE_SIZE);
> + pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE);
> len = PTR_ERR(pathname);
> if (IS_ERR(pathname))
> goto out;
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] vfs: show unreachable paths in getcwd and proc
2010-06-04 11:53 ` [PATCH 2/2] vfs: show unreachable paths in getcwd and proc Miklos Szeredi
2010-06-15 7:31 ` Miklos Szeredi
@ 2010-06-15 8:18 ` Nick Piggin
1 sibling, 0 replies; 6+ messages in thread
From: Nick Piggin @ 2010-06-15 8:18 UTC (permalink / raw)
To: Miklos Szeredi
Cc: Al Viro, Andrew Morton, John Johansen, Tetsuo Handa,
linux-fsdevel, linux-kernel
On Fri, Jun 04, 2010 at 01:53:42PM +0200, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
>
> Prepend "(unreachable)" to path strings if the path is not reachable
> from the current root.
>
> Two places updated are
> - the return string from getcwd()
> - and symlinks under /proc/$PID.
>
> Other uses of d_path() are left unchanged (we know that some old
> software crashes if /proc/mounts is changed).
>
> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
> ---
> fs/dcache.c | 82 +++++++++++++++++++++++++++++++++++++++++--------
> fs/proc/base.c | 2 -
> include/linux/dcache.h | 1
> 3 files changed, 72 insertions(+), 13 deletions(-)
>
> Index: linux-2.6/fs/dcache.c
> ===================================================================
> --- linux-2.6.orig/fs/dcache.c 2010-05-27 12:22:21.000000000 +0200
> +++ linux-2.6/fs/dcache.c 2010-05-27 12:22:24.000000000 +0200
> @@ -1957,6 +1957,33 @@ int __d_path(const struct path *path, st
> return error;
> }
>
> +static void current_root(struct path *root)
> +{
> + read_lock(¤t->fs->lock);
> + *root = current->fs->root;
> + path_get(root);
> + read_unlock(¤t->fs->lock);
> +}
Does this really need a helper? If yes, then please put matching
get_fs_{root,pwd,both} helpers into fs_struct.c and use them throughout
the tree.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-06-15 8:18 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-04 11:52 [PATCH 1/2] vfs: sanitize __d_path() Miklos Szeredi
2010-06-04 11:53 ` [PATCH 2/2] vfs: show unreachable paths in getcwd and proc Miklos Szeredi
2010-06-15 7:31 ` Miklos Szeredi
2010-06-15 8:18 ` Nick Piggin
2010-06-04 14:10 ` [PATCH 1/2] vfs: sanitize __d_path() Tetsuo Handa
-- strict thread matches above, loose matches on Subject: below --
2010-05-27 10:29 Miklos Szeredi
2010-05-27 10:30 ` [PATCH 2/2] vfs: show unreachable paths in getcwd and proc Miklos Szeredi
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.