無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

ファイル参照チェック


chdir/open等のファイル参照時、do_inode_permission()で、inodeのpermissionから、参照内容に応じたチェックが行われます。

inodeオペレーションコールバックの.permissionが定義されていなければ、generic_permission()がコールされます。sysfs/procfs等では.permissionは定義されてますが、ext等のファイルシステムでは、定義されていません。

inode->i_opflags |= IOP_FASTPERMは、二回目以降のdo_inode_permission()コール時、inodeキャッシュのpermissionコールバックがNULLかのチェックでなく、inode->i_opflagsをビット演算によるチェックでの効率化故かと思いますが、他の箇所でIOP_FASTPERMを使用されておらず、permission()その物の負荷を考慮すると、意味の無い効率化かと思います。
static inline int do_inode_permission(struct inode *inode, int mask)
{
       if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) {
               if (likely(inode->i_op->permission))
                       return inode->i_op->permission(inode, mask);

               spin_lock(&inode->i_lock);
               inode->i_opflags |= IOP_FASTPERM;
               spin_unlock(&inode->i_lock);
       }
       return generic_permission(inode, mask);
}
acl_permission_check()でinode->i_modeおよびACLに掛かる参照チェックを行い、参照不可ならケーパビリティに掛かる参照チェックを行います。

inode_userns(inode)は、inodeの属するnamespaceで、プロセスnamespaceに関係なく、作成されるinodeは、root_userプロセスのnamespaceに属する事になります。ns_capable()は、カレントプロセスが指定されるケーパビリティを有しているかチェックします。

ディレクトリの時、inode/ACLの参照条件に関係なく、ケーパビリティがCAP_DAC_OVERRIDEなら読書き(ls/rm/)OK。CAP_DAC_READ_SEARCHなら読込み(ls)OKです。

ファイルでは、CAP_DAC_OVERRIDEなら読書き可能。実行でU/G/OのどれかがOKなら実行可能となります。(userチェックでuserのEXEがセットされてなく、otherのEXEがセットされているなら、実行できるという事です。)

CAP_DAC_READ_SEARCHなら、読込みのみOKです。

rootは、これ等のケーパビリティは設定されており、inode->i_modeで読み書き不可としても、読み書きできるのは、ケーパビリティ所以です。
int generic_permission(struct inode *inode, int mask)
{
       int ret;

       ret = acl_permission_check(inode, mask);
       if (ret != -EACCES)
               return ret;

       if (S_ISDIR(inode->i_mode)) {
               if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
                       return 0;
               if (!(mask & MAY_WRITE))
                       if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
                               return 0;
               return -EACCES;
       }

       if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
               if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
                       return 0;

       mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
       if (mask == MAY_READ)
               if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
                       return 0;

       return -EACCES;
}
inode->i_modeは、上位9ビットから3ビット単位で、u/g/oです。プロセスのnamespaceは、新規にnamespaceを設定しないかぎり、初期プロセスのそれを継承します。プロセスnamespaceがinodeのネームスペース(初期プロセスのnamespace)と異なる時、Other(mode >>= 0)でチェックします。

current->cred->fsuidがinode->i_uid(ファイルを作成したユーザID)なら、User(mode >>= 6)でチェックします。

それ以外、ACLのチェックをし、in_group_p()で、setgroupsシステムコールで設定されるcred->group_info->blocks[]のプロセスが属するグループにinode->i_gidを有しているなら、Group(mode >>= 3)でチェックします。
#define MAY_EXEC                0x00000001
#define MAY_WRITE               0x00000002
#define MAY_READ                0x00000004

static int acl_permission_check(struct inode *inode, int mask)
{
       unsigned int mode = inode->i_mode;

       if (current_user_ns() != inode_userns(inode))
               goto other_perms;

       if (likely(current_fsuid() == inode->i_uid))
               mode >>= 6;
       else {
               if (IS_POSIXACL(inode) && (mode & S_IRWXG)) {
                       int error = check_acl(inode, mask);
                       if (error != -EAGAIN)
                               return error;
               }

               if (in_group_p(inode->i_gid))
                       mode >>= 3;
       }

other_perms:
       if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
               return 0;
       return -EACCES;
}

#define inode_userns(inode) (&init_user_ns)

#define current_user_ns()       (current_cred_xxx(user_ns))

#define current_cred_xxx(xxx)                   \
({                                              \
       current_cred()->xxx;                    \
})
#define current_cred() \
       rcu_dereference_protected(current->cred, 1)

struct user_namespace init_user_ns = {
       .kref = {
               .refcount       = ATOMIC_INIT(3),
       },
       .creator = &root_user,
};

最終更新 2015/07/18 17:59:56 - north
(2015/07/18 17:59:56 作成)