eCryptfs - mount系统调用

eCryptfs - mount系统调用

README

  • 作者:邢万里
  • 学校:重庆邮电大学
  • email:wlxing@yahoo.com

入口(系统调用include/linux/syscall.h)

由于安全上的一些问题,2.6和3.x系类的系统调用改动幅度有些偏大。系统调用均经过如下代码进行“过滤”:

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)

这里的mount系统调用对应的是SYSCALL_DEFINE5,而SYSCALL_DEFINEx实现如下:

#define __SYSCALL_DEFINEx(x, name, ...)                 \
    asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__));       \
    static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__));   \
    asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__))        \
    {                               \
        __SC_TEST##x(__VA_ARGS__);              \
        return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__));    \
    }                               \
    SYSCALL_ALIAS(sys##name, SyS##name);                \
    static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__))

上述源码对应到mount后如下:

asmlinkage long sys_mount(const char __user * filename, int flags, umode_t mode);
static inline long SYSC_mount(const char __user * filename, int flags, umode_t mode);
asmlinkage long SyS_mount((long)filename, (long)flags, (long)mode)
{
  __SC_TEST3(const, char __user * filename, int, flags, umode_t, mode); 
  return (long)SYSC_mount(const char __user * filename, int flags, umode_t mode);
}
SYSCALL_ALIAS(sys_mount, SyS_mount);
static inline long SYSC_mount(const char __user * filename, int flags, umode_t mode)

这样,很轻易的发现依然存在sys_mount()函数,此函数在源码的include/linux/syscall.h中,但只有声明没有定义。

VFS层(系统调用fs/namespace.c)

如下是mount系统调用对应的具体函数,我这里略去了异常处理和一些其他细节代码,剩余的代码是核心部分。可以很清楚的看到mount系统调用先获得mount参数,并将其传入到do_mount中进行处理。

SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
        char __user *, type, unsigned long, flags, void __user *, data)
{
    ret = copy_mount_options(data, &data_page);

    ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
        (void *) data_page);
}

下述代码依然只保留了核心部分代码。do_mount()函数先获得挂载点,继而根据flags判断具体的情景:同一个挂载点重复挂载等。最常用的是do_new_mount()函数。

long do_mount(char *dev_name, char *dir_name, char *type_page,
          unsigned long flags, void *data_page)
{
    /* ... and get the mountpoint */
    retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);

    if (flags & MS_REMOUNT)
        retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
                    data_page);
    else if (flags & MS_BIND)
        retval = do_loopback(&path, dev_name, flags & MS_REC);
    else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
        retval = do_change_type(&path, flags);
    else if (flags & MS_MOVE)
        retval = do_move_mount(&path, dev_name);
    else
        retval = do_new_mount(&path, type_page, flags, mnt_flags,
                      dev_name, data_page);
}

下述代码依然只保留了核心部分代码。分别进入代码中两个关键函数看看mount如何实现。

static int do_new_mount(struct path *path, char *type, int flags,
            int mnt_flags, char *name, void *data)
{
    mnt = do_kern_mount(type, flags, name, data);

    err = do_add_mount(real_mount(mnt), path, mnt_flags);
}

下述代码依然只保留了核心部分代码。如下do_kern_mount函数:

do_kern_mount(const char *fstype, int flags, const char *name, void *data)
{
    /* Get the file-system type according to the parameters by parsing the file-system type. Because the file-system-type is
     linked, it's effortless to obtain specific type through searching th e list. IF we don't find the file-system, we try
      to load kernel module and then search the list again. That is to say, if we do not modprobe fs, but we mount fs, linux can 
      help us modprobe ecryptfs,then execute mount-operations */
    struct file_system_type *type = get_fs_type(fstype);

    mnt = vfs_kern_mount(type, flags, name, data);
}

下述代码依然只保留了核心部分代码。以下代码为vfs_kern_mount()具体实现过程,分为三部分,分配、初始化和mount完成操作。

struct vfsmount *
vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
    /* Allocate struct mount for fs-type*/
    mnt = alloc_vfsmnt(name);

    root = mount_fs(type, flags, name, data);

    mnt->mnt.mnt_root = root;
    mnt->mnt.mnt_sb = root->d_sb;
    mnt->mnt_mountpoint = mnt->mnt.mnt_root;
    mnt->mnt_parent = mnt;
}

下述代码依然只保留了核心部分代码。以下代码为mount_fs()函数具体实现,这里可以非常清晰的看到我们要找到的东西已经找到了:type->mount(),此mount即通过VFS机制具体对应到具体的文件系统,如eCryptfs,从而完成mount真正的、本质上的操作。

struct dentry *
mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
{
    root = type->mount(type, flags, name, data);

    error = security_sb_kern_mount(sb, flags, secdata);
}

eCryptfs层(fs/ecryptfs/main.c)

如下部分的数据结构即为前文说到的VFS机制到具体的文件系统。由.mountecryptfs_mount,即由VFS到eCryptfs。

static struct file_system_type ecryptfs_fs_type = {
    .owner = THIS_MODULE,
    .name = "ecryptfs",
    .mount = ecryptfs_mount,
    .kill_sb = ecryptfs_kill_block_super,
    .fs_flags = 0
};

此时只需查询eCryptfs中的ecryptfs_mount()函数是如何完成具体的挂载操作了。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值