lkml.org 
[lkml]   [2009]   [Jan]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [TOMOYO #14 (mmotm 2008-12-30-16-05) 03/10] Introduce d_realpath().
    On Thu, 1 Jan 2009, Tetsuo Handa wrote:

    > To remove factors that make pathname based access control difficult
    > (e.g. symbolic links, "..", "//", chroot() etc.), a variant of d_path()
    > which traverses up to the root of the namespace is needed.
    >
    > This patch introduces d_realpath(), a variant of d_path().
    > While d_path() stops traversing at current->fs->root,
    > d_realpath() doesn't stop traversiong at current->fs->root.
    >
    > Three differences compared to d_path().
    > (1) Ignores current process's root directory.
    > (2) Trailing '/' is added if the pathname refers to a directory.
    > (3) /proc/PID/ is represented as /proc/self/ if PID equals current->tgid.
    >

    This needs an ack from Al and/or Christoph.

    > Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
    > Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
    > Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
    > ---
    > fs/dcache.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
    > include/linux/dcache.h | 1
    > 2 files changed, 85 insertions(+)
    >
    > --- linux-2.6.28-mm1.orig/fs/dcache.c
    > +++ linux-2.6.28-mm1/fs/dcache.c
    > @@ -32,6 +32,7 @@
    > #include <linux/seqlock.h>
    > #include <linux/swap.h>
    > #include <linux/bootmem.h>
    > +#include <linux/magic.h>
    > #include "internal.h"
    >
    >
    > @@ -1978,6 +1979,89 @@ Elong:
    > }
    >
    > /**
    > + * d_realpath - Get the realpath of a dentry.
    > + *
    > + * @path: Pointer to "struct path".
    > + * @buffer: Pointer to buffer to return value in.
    > + * @buflen: Sizeof @buffer.
    > + *
    > + * Returns pointer to the realpath on success, an error code othersize.
    > + *
    > + * If @dentry is a directory, trailing '/' is appended.
    > + * /proc/PID/ is replaced by /proc/self/ if PID == task_tgid_nr_ns(current).
    > + */
    > +char *d_realpath(struct path *path, char *buffer, int buflen)
    > +{
    > + struct dentry *dentry = path->dentry;
    > + struct vfsmount *vfsmnt = path->mnt;
    > + char *end = buffer + buflen;
    > +
    > + spin_lock(&dcache_lock);
    > + spin_lock(&vfsmount_lock);
    > + if (buflen < 1 || prepend(&end, &buflen, "", 1))
    > + goto Elong;
    > + /*
    > + * Exception: Add trailing '/' for directory.
    > + */
    > + if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode) &&
    > + prepend(&end, &buflen, "/", 1))
    > + goto Elong;
    > + for (;;) {
    > + struct dentry *parent;
    > + const char *name;
    > + int name_len;
    > + unsigned long pid;
    > +
    > + if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
    > + /* Global root? */
    > + if (vfsmnt->mnt_parent == vfsmnt)
    > + break;
    > + dentry = vfsmnt->mnt_mountpoint;
    > + vfsmnt = vfsmnt->mnt_parent;
    > + continue;
    > + }
    > + parent = dentry->d_parent;
    > + prefetch(parent);
    > + /*
    > + * Exception: Use /proc/self/ rather than /proc/\$/
    > + * for current process.
    > + */
    > + name = dentry->d_name.name;
    > + name_len = dentry->d_name.len;
    > + if (IS_ROOT(parent) &&
    > + parent->d_sb->s_magic == PROC_SUPER_MAGIC &&
    > + !strict_strtoul(name, 10, &pid)) {
    > + const pid_t tgid
    > + = task_tgid_nr_ns(current,
    > + dentry->d_sb->s_fs_info);
    > + if (tgid && (pid_t) pid == tgid) {
    > + name = "self";
    > + name_len = 4;
    > + }
    > + }
    > + if (prepend(&end, &buflen, name, name_len))
    > + goto Elong;
    > + if (prepend(&end, &buflen, "/", 1))
    > + goto Elong;
    > + dentry = parent;
    > + }
    > + if (*end == '/') {
    > + /* hit the slash */
    > + buflen++;
    > + end++;
    > + }
    > + if (prepend_name(&end, &buflen, &dentry->d_name))
    > + goto Elong;
    > + out:
    > + spin_unlock(&vfsmount_lock);
    > + spin_unlock(&dcache_lock);
    > + return end;
    > + Elong:
    > + end = ERR_PTR(-ENAMETOOLONG);
    > + goto out;
    > +}
    > +
    > +/**
    > * d_path - return the path of a dentry
    > * @path: path to report
    > * @buf: buffer to return value in
    > --- linux-2.6.28-mm1.orig/include/linux/dcache.h
    > +++ linux-2.6.28-mm1/include/linux/dcache.h
    > @@ -305,6 +305,7 @@ extern char *dynamic_dname(struct dentry
    > extern char *__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);
    > +extern char *d_realpath(struct path *, char *, int);
    >
    > /* Allocation counts.. */
    >
    >
    > --
    > --
    > To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
    > the body of a message to majordomo@vger.kernel.org
    > More majordomo info at http://vger.kernel.org/majordomo-info.html
    >

    --
    James Morris
    <jmorris@namei.org>


    \
     
     \ /
      Last update: 2009-01-05 10:13    [W:2.336 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site