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

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

追加属性でファイルの削除


[root@localhost tmp]# mkdir hoge
[root@localhost tmp]# chattr +a hoge
[root@localhost tmp]# touch hoge/test
[root@localhost tmp]# rm hoge/test
rm: 通常の空ファイル `hoge/test' を削除しますか? y
rm: `hoge/test' を削除できません: 許可されていない操作です
[root@localhost tmp]# chattr -a hoge/
[root@localhost tmp]# rm hoge/test
rm: 通常の空ファイル `hoge/test' を削除しますか? y
[root@localhost tmp]#
削除できない追加属性。と言う事で、結論は明々白々ですが、とりあえず以下その実装です。

chmodで設定する属性はinode->i_modeに、chattrで設定する属性はinode->i_flagsに設定され、この設定値により削除可能かどうかのチェックが行われます。

ファイル削除はunlinkシステムコールからvfs_unlink()とコールされ、isdir=0でmay_delete()で削除していいかのチェックします。dirは削除ファイルの属するディレクトリで、victimは削除ファイルのdentryです。

inode_permission()で親ディレクトリがWRITE/EXECでなく、if (IS_APPEND(dir))で追加属性なら削除できません。また、親ディレクトリが削除可能でも、削除ファイルがIS_APPEND(victim->d_inode)でも削除できません。
static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
{
       int error;

       if (!victim->d_inode)
               return -ENOENT;

       BUG_ON(victim->d_parent->d_inode != dir);
       audit_inode_child(victim, dir);

       error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
       if (error)
               return error;
       if (IS_APPEND(dir))
               return -EPERM;
       if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
           IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
               return -EPERM;
       if (isdir) {
               if (!S_ISDIR(victim->d_inode->i_mode))
                       return -ENOTDIR;
               if (IS_ROOT(victim))
                       return -EBUSY;
       } else if (S_ISDIR(victim->d_inode->i_mode))
               return -EISDIR;
       if (IS_DEADDIR(dir))
               return -ENOENT;
       if (victim->d_flags & DCACHE_NFSFS_RENAMED)
               return -EBUSY;
       return 0;
}

補足

BUG_ON(victim->d_parent->d_inode != dir)は、victimがdirディレクトリ下のファイルでないと言うことで、これはカーネルのバグか、may_delete()引数の誤使用と言うことです。

IS_IMMUTABLE(victim->d_inode)はchattr -iで設定するフラグで、当然削除できません。親ディレクトリについては、inode_permission(dir, MAY_WRITE | MAY_EXEC)で-iならエラーと返します。


最終更新 2014/03/22 00:39:46 - north
(2014/03/22 00:38:54 作成)