Ejemplo n.º 1
0
/*
 * Object creation/destruction.
 */
LinuxSystemRoot* newLinuxSystemRoot(void)
{
    LinuxSystemRoot* object;
    unsigned m_seq = 0;


    object = talpa_alloc(sizeof(template_LinuxSystemRoot));
    if ( object )
    {
        struct task_struct* inittask;


        memcpy(object, &template_LinuxSystemRoot, sizeof(template_LinuxSystemRoot));
        object->i_ISystemRoot.object = object;

        talpa_tasklist_lock();
        inittask = talpa_find_task_by_pid(1);
        talpa_tasklist_unlock();

        if ( inittask )
        {
            struct fs_struct *init_fs;
            struct vfsmount *rootmnt;

            task_lock(inittask);
            init_fs = inittask->fs;
            if ( init_fs )
            {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
                spin_lock(&init_fs->lock);
  #else
                write_lock(&init_fs->lock);
  #endif
                init_fs->users++;
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
                spin_unlock(&init_fs->lock);
  #else
                write_unlock(&init_fs->lock);
  #endif
#else
                atomic_inc(&init_fs->count);
#endif
            }
            task_unlock(inittask);

            if ( init_fs )
            {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
                spin_lock(&init_fs->lock);
#else
                write_lock(&init_fs->lock);
#endif


restart_mnt:
                talpa_vfsmount_lock(&m_seq); // locks dcache_lock on 2.4
                for (rootmnt = talpa_fs_mnt(init_fs); rootmnt != getParent(rootmnt); rootmnt = getParent(rootmnt));
                object->mMnt = mntget(rootmnt);
                object->mDentry = dget(rootmnt->mnt_root);
                if (talpa_vfsmount_unlock(&m_seq)) // unlocks dcache_lock on 2.4
                {
                    goto restart_mnt;
                }
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
                init_fs->users--;
  #else
                atomic_dec(&init_fs->count);
  #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
                spin_unlock(&init_fs->lock);
#else
                write_unlock(&init_fs->lock);
#endif
            }
        }

        if ( !object->mMnt || !object->mDentry )
        {
            if ( object->mMnt )
            {
                mntput(object->mMnt);
            }

            if ( object->mDentry )
            {
                dput(object->mDentry);
            }

            talpa_free(object);

            return NULL;
        }
    }

    return object;
}
Ejemplo n.º 2
0
Archivo: glue.c Proyecto: sophos/talpa
/**
 * d_path - return the path of a dentry
 * @dentry: dentry to report
 * @vfsmnt: vfsmnt to which the dentry belongs
 * @root: root dentry
 * @rootmnt: vfsmnt to which the root dentry belongs
 * @buffer: buffer to return value in
 * @buflen: 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.
 *
 * Returns the buffer or an error code if the path was too long.
 *
 * "buflen" should be positive. Caller holds the dcache_lock.
 */
static char * __talpa_d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
            struct dentry *root, struct vfsmount *rootmnt,
            char *buffer, int buflen)
{
    char * end = buffer+buflen;
    char * retval;
    int namelen;
    unsigned m_seq = 1;

    *--end = '\0';
    buflen--;
    if (!IS_ROOT(dentry) && d_unhashed(dentry))
    {
        buflen -= 10;
        end -= 10;
        if (buflen < 0)
            goto Elong;
        memcpy(end, " (deleted)", 10);
    }

    if (buflen < 1)
        goto Elong;
    /* Get '/' right */
    retval = end-1;
    *retval = '/';

    for (;;) {
        struct dentry * parent;

        if (dentry == root && vfsmnt == rootmnt)
            break;
        if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry))
        {
            /* Global root? */
            talpa_vfsmount_lock(&m_seq);
            if (vfsmnt->mnt_parent == vfsmnt) {
                talpa_vfsmount_unlock(&m_seq);
                goto global_root;
            }
            dentry = vfsmnt->mnt_mountpoint;
            vfsmnt = vfsmnt->mnt_parent;
            talpa_vfsmount_unlock(&m_seq);
            continue;
        }
        parent = dentry->d_parent;
        prefetch(parent);
        namelen = dentry->d_name.len;
        buflen -= namelen + 1;
        if (buflen < 0)
            goto Elong;
        end -= namelen;
        memcpy(end, dentry->d_name.name, namelen);
        *--end = '/';
        retval = end;
        dentry = parent;
    }

    return retval;

global_root:
    namelen = dentry->d_name.len;
    buflen -= namelen;
    if (buflen < 0)
        goto Elong;
    retval -= namelen-1;    /* hit the slash */
    memcpy(retval, dentry->d_name.name, namelen);
    return retval;
Elong:
    return ERR_PTR(-ENAMETOOLONG);
}
Ejemplo n.º 3
0
/**
 * We iterate all the possible parents of our mount point,
 * and see if they also have a mount on the same mount point.
 */
int countPropagationPoints(struct vfsmount* vmnt)
{
#ifdef TALPA_SHARED_MOUNTS

    talpa_mount_struct *mnt = real_mount(vmnt);
    talpa_mount_struct *parent = mnt->mnt_parent;
    talpa_mount_struct *child = NULL;
    talpa_mount_struct *m;
    int ret = 1;

    unsigned m_seq = 1;

#ifdef DEBUG_PROPAGATION_POINTS
    talpa_mnt_namespace_t* ns;
    size_t path_size = 0;
    char* path = talpa_alloc_path_atomic(&path_size);
    const char* p = absolutePath(mnt->mnt_mountpoint,vfs_mount(parent), path, path_size);

    if (unlikely( path == NULL ))
    {
        warn("talpa_alloc_path failed");
        return 0;
    }

    ns = mnt->mnt_ns;
    dbg("PATH START: %s ns=%p ns.ns.inum=%u",p,ns,PROC_INUM_FROM_MNT_NAMESPACE(ns));

    ns = parent->mnt_ns;
    p = absolutePath(parent->mnt_mountpoint,vfs_mount(parent->mnt_parent), path, path_size);
    dbg("PARENT: %s ns=%p ns.ns.inum=%u",p,ns,PROC_INUM_FROM_MNT_NAMESPACE(ns));
#endif /* DEBUG_PROPAGATION_POINTS */

    talpa_vfsmount_lock(&m_seq); /* locks dcache_lock on 2.4 */

    /**
     * Iterate all possible shared/slave destination parents for copies of vmnt
     */
    for (m = propagation_next(parent, parent); m;
            m = propagation_next(m, parent))
    {
        child = talpa_lookup_mnt_last(vfs_mount(m), mnt->mnt_mountpoint);
        if (child)
        {
#ifdef DEBUG_PROPAGATION_POINTS
            /* absolutePath() locks up in d_path() if vfsmount_lock is already held */
            p = child->mnt_mountpoint->d_name.name;
            ns = child->mnt_ns;
            dbg("CHILD: %s ns=%p ns.ns.inum=%u",p,ns,PROC_INUM_FROM_MNT_NAMESPACE(ns));
#endif /* DEBUG_PROPAGATION_POINTS */
            if (list_empty(&child->mnt_mounts))
            {
                ret += 1;
            }
        }
    }
    talpa_vfsmount_unlock(&m_seq); /* unlocks dcache_lock on 2.4 */

#ifdef DEBUG_PROPAGATION_POINTS
    talpa_free_path(path);
#endif
    return ret;
#else /* ! TALPA_SHARED_MOUNTS */
    return 1;
#endif /* TALPA_SHARED_MOUNTS */
}
Ejemplo n.º 4
0
Archivo: glue.c Proyecto: sophos/talpa
char* talpa__d_namespace_path( struct dentry *dentry, struct vfsmount *vfsmnt,
            struct dentry *root, struct vfsmount *rootmnt,
            char *buffer, int buflen, bool* nonRootNamespaceOut, bool* inProcessNamespaceOut)
{
    char* path;

#ifdef TALPA_MNT_NAMESPACE
    struct vfsmount *ns_root_mnt = NULL;
    struct dentry *ns_root_dentry;
    unsigned m_seq = 1;
    struct vfsmount *process_root_mnt;
    struct dentry *process_root_dentry;
    struct task_struct* proc;

    proc = current;
    if ( likely(proc->fs != NULL) )
    {
        talpa_proc_fs_lock(&proc->fs->lock);
        process_root_mnt = mntget(talpa_task_root_mnt(proc));
        process_root_dentry = dget(talpa_task_root_dentry(proc));
        talpa_proc_fs_unlock(&proc->fs->lock);

        if (inProcessNamespaceOut)
        {
            if ( likely( proc->nsproxy != NULL ) )
            {
                *inProcessNamespaceOut = (getNamespaceInfo(vfsmnt) == proc->nsproxy->mnt_ns);
            }
            else
            {
                *inProcessNamespaceOut = false;
            }
        }

        talpa_vfsmount_lock(&m_seq);
        if (getNamespaceInfo(process_root_mnt))
        {
            ns_root_mnt = mntget(getNamespaceRoot(process_root_mnt));
        }
        talpa_vfsmount_unlock(&m_seq);

        dbg("root dentry %s dentry=%p vfsmnt=%p",process_root_dentry->d_name.name,process_root_dentry,process_root_mnt);

        if(ns_root_mnt)
        {
            ns_root_dentry = dget(ns_root_mnt->mnt_root);
            dbg("ns_root_dentry %s dentry=%p vfsmnt=%p",ns_root_dentry->d_name.name,ns_root_dentry,ns_root_mnt);

            path = talpa__d_path(dentry, vfsmnt, ns_root_dentry, ns_root_mnt,
                buffer, buflen, NULL);
            dbg("talpa__d_namespace_path: found d_namespace_path: %s", path);

            if (nonRootNamespaceOut)
            {
                *nonRootNamespaceOut = (ns_root_mnt != rootmnt);
            }
            dput(ns_root_dentry);

            mntput(ns_root_mnt);

        }
        else
        {
            path = talpa__d_path(dentry, vfsmnt, process_root_dentry, process_root_mnt,
                buffer, buflen, nonRootNamespaceOut);
            dbg("talpa__d_namespace_path: found non namespace path: %s", path);

        }
        dput(process_root_dentry);
        mntput(process_root_mnt);

    }
    else
    {
        dbg("proc->fs == NULL, cannot get namespace path");

        if (inProcessNamespaceOut)
        {
            *inProcessNamespaceOut = false;
        }
#else /* !TALPA_MNT_NAMESPACE */
    {
        if (inProcessNamespaceOut)
        {
            *inProcessNamespaceOut = true;
        }
#endif

        path = talpa__d_path(dentry, vfsmnt, root, rootmnt,
                buffer, buflen, nonRootNamespaceOut);
        dbg("talpa__d_namespace_path: found non namespace path: %s", path);
    }

    return path;
}

#ifdef TALPA_MNT_NAMESPACE
static void debugPathWalk( struct dentry *dentry, struct vfsmount *vfsmnt,
            struct dentry *root, struct vfsmount *rootmnt)
{
    /* Debug - try and evaluate roots */
    int count = 50;
    struct dentry *td = dentry;
    struct vfsmount *temp_vfsmnt = vfsmnt;

    err("DEBUG: expected root node %s dentry=%p vfsmnt=%p",root->d_name.name,root,rootmnt);
    while (td != root || temp_vfsmnt != rootmnt)
    {
        count--;
        if (count == 0)
        {
            err("DEBUG: reached count limit!");
            break;
        }
        err("DEBUG: examining %s %p",td->d_name.name,td);
        if (td == temp_vfsmnt->mnt_root || IS_ROOT(td))
        {
            struct vfsmount *temp2_vfsmnt = getParent(temp_vfsmnt);
            if (td == temp_vfsmnt->mnt_root)
            {
                err("DEBUG: found root dentry td == temp_vfsmnt->mnt_root %p",td);
            }
            if (IS_ROOT(td))
            {
                err("DEBUG: found root dentry IS_ROOT(td) %p",td);
            }
            err("DEBUG: going to parent: %p -> %p",temp_vfsmnt,temp2_vfsmnt);
            if (temp_vfsmnt != temp2_vfsmnt)
            {
                td = getVfsMountPoint(temp_vfsmnt);
                err("DEBUG: going to mountpoint %s dentry=%p", td->d_name.name, td);
                temp_vfsmnt = temp2_vfsmnt;
            }
            else
            {
                err("DEBUG: Got to temp_vfsmnt = temp2_vfsmnt!");
            }
        }
        if (td == td->d_parent)
        {
            err("DEBUG: td == td->d_parent");
            break;
        }
        else if (td->d_parent == NULL)
        {
            err("DEBUG: td->d_parent == NULL");
            break;
        }
        td = td->d_parent;
    }
    err("DEBUG: actual root node %s dentry=%p vfsmnt=%p",td->d_name.name,td,temp_vfsmnt);
    if (td == root && temp_vfsmnt == rootmnt)
    {
        err("DEBUG: Found the correct root");
    }
    else
    {
        err("DEBUG: Found wrong root td=%p (name=%s) vfsmnt=%p",
            td,
            td->d_name.name,
            temp_vfsmnt);
        err("DEBUG: Expected       root=%p (name=%s) vfsmnt=%p",
            root,
            root->d_name.name,
            rootmnt);
    }
}
Ejemplo n.º 5
0
int iterateFilesystems(struct vfsmount* root, int (*callback) (struct vfsmount* mnt, unsigned long flags, bool fromMount))
{
    talpa_mount_struct *mnt, *nextmnt, *prevmnt;
    struct list_head *nexthead = NULL;
    int ret;
    unsigned m_seq = 1;

    mnt = real_mount(root);
    talpa_mntget(mnt); /* Take extra reference count for the loop */
    do
    {
        struct vfsmount* vfsmnt = vfs_mount(mnt);
        dbg("VFSMNT: 0x%p (at 0x%p), sb: 0x%p, dev: %s, flags: 0x%lx, fs: %s", mnt, mnt->mnt_parent,
                vfsmnt->mnt_sb, mnt->mnt_devname, vfsmnt->mnt_sb->s_flags, vfsmnt->mnt_sb->s_type->name);

        ret = callback(vfsmnt, vfsmnt->mnt_sb->s_flags, false);
        if (ret)
        {
            break;
        }

        talpa_vfsmount_lock(&m_seq); /* locks dcache_lock on 2.4 */

        /* Go down the tree for a child if there is one */
        if ( !list_empty(&mnt->mnt_mounts) )
        {
            nextmnt = list_entry(mnt->mnt_mounts.next, talpa_mount_struct, mnt_child);
        }
        else
        {
            nextmnt = mnt;
            /* If no children, go up until we found some. Abort on root. */
            while ( nextmnt != nextmnt->mnt_parent )
            {
                nexthead = nextmnt->mnt_child.next;
                /* Take next child if available */
                if ( nexthead != &nextmnt->mnt_parent->mnt_mounts )
                {
                    break;
                }
                /* Otherwise go up the tree */
                nextmnt = nextmnt->mnt_parent;
            }

            /* Abort if we are at the root */
            if ( nextmnt == nextmnt->mnt_parent )
            {
                talpa_vfsmount_unlock(&m_seq); /* unlocks dcache_lock on 2.4 */
                talpa_mntput(mnt);
                break;
            }

            /* Take next mount from the list */
            nextmnt = list_entry(nexthead, talpa_mount_struct, mnt_child);
        }

        talpa_mntget(nextmnt);
        prevmnt = mnt;
        mnt = nextmnt;
        talpa_vfsmount_unlock(&m_seq); /* unlocks dcache_lock on 2.4 */
        talpa_mntput(prevmnt);
    } while (mnt);

    /* Don't mntput root as we didn't take a reference for ourselves */

    return ret;
}