├── .gitattributes ├── Document ├── Data Integrity │ └── eCryptfs文件完整性校验文档.rar ├── Other │ ├── Figure │ │ ├── 2015.10.30.ddd │ │ ├── Conversions in user layer.png │ │ ├── How to convert FEK into EFEK.png │ │ ├── How to encrypt extents one by one.png │ │ ├── Overview of eCryptfs architecture 1.png │ │ ├── Overview of eCryptfs architecture 2.png │ │ ├── Version1 Salt.png │ │ ├── Version2 Salt.png │ │ └── hybrid.png │ └── Thesis │ │ ├── Chinese Theses(Not Recommend) │ │ ├── CBAC_一种基于密码访问控制机制的研究_马康.caj │ │ ├── Extending_File_Systems_Using_Stackable_Templates.pdf │ │ ├── FiST_A_Language_for_Stackable_File_Systems.pdf │ │ ├── Kernel Support for Stackable File Systems.pdf │ │ ├── Linux加密文件系统_Crypt_FS_丁成.pdf │ │ ├── Optimizing eCryptfs for better performance and security.pdf │ │ ├── Performance_of_Size-Changing_Algorithms_in_Stackable_File_Systems.pdf │ │ ├── StegFS_A_Steganographic_File_System_for_Linux.pdf │ │ ├── TransCrypt A Secure and Transparent Encrypting File System for Enterprises.pdf │ │ ├── eCryptfs An Enterprise-class Cryptographic Filesystem for Linux.pdf │ │ ├── eCryptfs v0.1 Design Document.pdf │ │ ├── linuxsymposium_procv1.pdf │ │ ├── 一个基于Linux的加密文件系统的设计与实现_邢常亮.pdf │ │ ├── 一种基于对称加密和隐写术的反取证方法_王灿.pdf │ │ ├── 一种面向特定应用的内核级文件加密技术_许国春.pdf │ │ ├── 可信计算平台中Linux加密文件系统的设计与实现_罗芳.pdf │ │ ├── 基于Linux的NAND Flash加密文件系统的设计与实现.caj │ │ ├── 基于Merkle树的移动平台文件完整性校验_张晓燕.pdf │ │ ├── 基于Merkle树的远程证明机制_邱罡.pdf │ │ ├── 基于eCryptfs的多用户加密文件系统设计和实现.pdf │ │ ├── 基于可信计算平台的Linux加密文件系统研究与实现_罗芳.caj │ │ ├── 基于可信计算平台的加密文件系统_章勤.pdf │ │ ├── 基于读写优化的内核级加密文件系统_裴灿浩.pdf │ │ └── 面向虚拟化平台的透明加密系统设计与实现_高汉军.pdf │ │ ├── Cryptfs and other versions │ │ ├── Cryptfs_A Stackable Vnode Level Encryption File System.pdf │ │ ├── NCryptfs-Presentation.ppt │ │ ├── Operating System Support for Extensible Secure File Systems.pdf │ │ └── ncryptfs-usenix03.ppt │ │ ├── Data Integrity │ │ ├── CheckSum │ │ │ ├── Adding Security to File Systems.pdf │ │ │ ├── Checksumming RAID.pdf │ │ │ ├── Ensuring data integrity in storage_Techniques and applications.pdf │ │ │ ├── FILE INTEGRITY CHECKERS_STATE OF THE ART.pdf │ │ │ ├── File System Extensibility and Reliability Using an in-Kernel Database.pdf │ │ │ ├── Improving Ext2 Integrity with Checksums.pdf │ │ │ ├── Modern Approaches to File System Integrity Checking.pdf │ │ │ ├── Practical Protection of Kernel Integrity for Commodity OS from Untrusted Extensions.pdf │ │ │ ├── Return-Oriented Rootkits_Bypassing Kernel Code Integrity Protection Mechanisms.pdf │ │ │ └── i3fs an in-kernel integrity checker and intrusion detection file system.pdf │ │ ├── HASH │ │ │ ├── A new hashing package for UNIX.pdf │ │ │ └── RFC 1321_The MD5 Message-Digest Algorithm.pdf │ │ └── HMAC&GCM │ │ │ ├── HMAC_ Keyed-hashing for message authentication. Technical Report RFC 2104.pdf │ │ │ └── aes128加密算法的GCM工作模式详解 .pdf │ │ ├── Old Theses.rar │ │ ├── Stackable │ │ ├── A Stackable File System Interface For Linux.pdf │ │ ├── A Stackable Vnode Level Encryption File System.pdf │ │ └── Stackable Design of File Systems.pdf │ │ ├── eCryptfs │ │ ├── Distributed Encrypting File System for Linux in User-space.pdf │ │ ├── ECFS_AN ENTERPRISE-CLASS CRYPTOGRAPHIC FILE SYSTEM.pdf │ │ ├── EXT4 Encryption Design Document (public version).pdf │ │ ├── Halcrow_EXT4_Encryption.pdf │ │ ├── Transcryptfs.pdf │ │ └── ecryptfs.pdf │ │ └── wrapfs and FiST │ │ └── On Incremental File System Development.pdf ├── VFS │ └── linux内核设计与实现之VFS文件系统.docx └── eCryptfs │ ├── Metadata(aes).png │ ├── Metadata(rsa).png │ ├── eCryptfs v0.1 Design Document中文版.docx │ ├── ecryptfs.h.pdf │ ├── ecryptfs_kernel.h.pdf │ └── 黄老师笔记(未完) │ ├── Keystore.c.docx │ ├── Linux VFS虚拟文件系统-3.3.8.docx │ ├── Messaging.c.docx │ ├── Miscdev.c.docx │ ├── ecryptfs.rar │ ├── ecryptfs内核.docx │ └── read_write.c.docx ├── Miscdev & Message.pdf ├── README.md ├── Source Code ├── README.txt ├── ecryptfs3_3_8 │ ├── Kconfig │ ├── Makefile │ ├── crypto.c │ ├── debug.c │ ├── dentry.c │ ├── ecryptfs_kernel.h │ ├── file.c │ ├── inode.c │ ├── keystore.c │ ├── kthread.c │ ├── main.c │ ├── messaging.c │ ├── miscdev.c │ ├── mmap.c │ ├── read_write.c │ └── super.c └── ecryptfs_2_6_24+hmac_patch │ ├── Makefile │ ├── crypto.c │ ├── debug.c │ ├── dentry.c │ ├── ecryptfs_kernel.h │ ├── file.c │ ├── hmac.c │ ├── inode.c │ ├── keystore.c │ ├── main.c │ ├── messaging.c │ ├── mmap.c │ ├── netlink.c │ ├── read_write.c │ └── super.c ├── ecryptfs-creat调试.docx └── ecryptfs_write_lower()调试.docx /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /Document/Data Integrity/eCryptfs文件完整性校验文档.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Data Integrity/eCryptfs文件完整性校验文档.rar -------------------------------------------------------------------------------- /Document/Other/Figure/2015.10.30.ddd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/2015.10.30.ddd -------------------------------------------------------------------------------- /Document/Other/Figure/Conversions in user layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/Conversions in user layer.png -------------------------------------------------------------------------------- /Document/Other/Figure/How to convert FEK into EFEK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/How to convert FEK into EFEK.png -------------------------------------------------------------------------------- /Document/Other/Figure/How to encrypt extents one by one.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/How to encrypt extents one by one.png -------------------------------------------------------------------------------- /Document/Other/Figure/Overview of eCryptfs architecture 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/Overview of eCryptfs architecture 1.png -------------------------------------------------------------------------------- /Document/Other/Figure/Overview of eCryptfs architecture 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/Overview of eCryptfs architecture 2.png -------------------------------------------------------------------------------- /Document/Other/Figure/Version1 Salt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/Version1 Salt.png -------------------------------------------------------------------------------- /Document/Other/Figure/Version2 Salt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/Version2 Salt.png -------------------------------------------------------------------------------- /Document/Other/Figure/hybrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Figure/hybrid.png -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/CBAC_一种基于密码访问控制机制的研究_马康.caj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/CBAC_一种基于密码访问控制机制的研究_马康.caj -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/Extending_File_Systems_Using_Stackable_Templates.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/Extending_File_Systems_Using_Stackable_Templates.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/FiST_A_Language_for_Stackable_File_Systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/FiST_A_Language_for_Stackable_File_Systems.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/Kernel Support for Stackable File Systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/Kernel Support for Stackable File Systems.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/Linux加密文件系统_Crypt_FS_丁成.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/Linux加密文件系统_Crypt_FS_丁成.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/Optimizing eCryptfs for better performance and security.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/Optimizing eCryptfs for better performance and security.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/Performance_of_Size-Changing_Algorithms_in_Stackable_File_Systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/Performance_of_Size-Changing_Algorithms_in_Stackable_File_Systems.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/StegFS_A_Steganographic_File_System_for_Linux.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/StegFS_A_Steganographic_File_System_for_Linux.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/TransCrypt A Secure and Transparent Encrypting File System for Enterprises.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/TransCrypt A Secure and Transparent Encrypting File System for Enterprises.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/eCryptfs An Enterprise-class Cryptographic Filesystem for Linux.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/eCryptfs An Enterprise-class Cryptographic Filesystem for Linux.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/eCryptfs v0.1 Design Document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/eCryptfs v0.1 Design Document.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/linuxsymposium_procv1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/linuxsymposium_procv1.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/一个基于Linux的加密文件系统的设计与实现_邢常亮.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/一个基于Linux的加密文件系统的设计与实现_邢常亮.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/一种基于对称加密和隐写术的反取证方法_王灿.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/一种基于对称加密和隐写术的反取证方法_王灿.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/一种面向特定应用的内核级文件加密技术_许国春.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/一种面向特定应用的内核级文件加密技术_许国春.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/可信计算平台中Linux加密文件系统的设计与实现_罗芳.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/可信计算平台中Linux加密文件系统的设计与实现_罗芳.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/基于Linux的NAND Flash加密文件系统的设计与实现.caj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/基于Linux的NAND Flash加密文件系统的设计与实现.caj -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/基于Merkle树的移动平台文件完整性校验_张晓燕.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/基于Merkle树的移动平台文件完整性校验_张晓燕.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/基于Merkle树的远程证明机制_邱罡.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/基于Merkle树的远程证明机制_邱罡.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/基于eCryptfs的多用户加密文件系统设计和实现.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/基于eCryptfs的多用户加密文件系统设计和实现.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/基于可信计算平台的Linux加密文件系统研究与实现_罗芳.caj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/基于可信计算平台的Linux加密文件系统研究与实现_罗芳.caj -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/基于可信计算平台的加密文件系统_章勤.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/基于可信计算平台的加密文件系统_章勤.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/基于读写优化的内核级加密文件系统_裴灿浩.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/基于读写优化的内核级加密文件系统_裴灿浩.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Chinese Theses(Not Recommend)/面向虚拟化平台的透明加密系统设计与实现_高汉军.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Chinese Theses(Not Recommend)/面向虚拟化平台的透明加密系统设计与实现_高汉军.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Cryptfs and other versions/Cryptfs_A Stackable Vnode Level Encryption File System.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Cryptfs and other versions/Cryptfs_A Stackable Vnode Level Encryption File System.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Cryptfs and other versions/NCryptfs-Presentation.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Cryptfs and other versions/NCryptfs-Presentation.ppt -------------------------------------------------------------------------------- /Document/Other/Thesis/Cryptfs and other versions/Operating System Support for Extensible Secure File Systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Cryptfs and other versions/Operating System Support for Extensible Secure File Systems.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Cryptfs and other versions/ncryptfs-usenix03.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Cryptfs and other versions/ncryptfs-usenix03.ppt -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/Adding Security to File Systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/Adding Security to File Systems.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/Checksumming RAID.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/Checksumming RAID.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/Ensuring data integrity in storage_Techniques and applications.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/Ensuring data integrity in storage_Techniques and applications.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/FILE INTEGRITY CHECKERS_STATE OF THE ART.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/FILE INTEGRITY CHECKERS_STATE OF THE ART.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/File System Extensibility and Reliability Using an in-Kernel Database.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/File System Extensibility and Reliability Using an in-Kernel Database.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/Improving Ext2 Integrity with Checksums.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/Improving Ext2 Integrity with Checksums.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/Modern Approaches to File System Integrity Checking.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/Modern Approaches to File System Integrity Checking.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/Practical Protection of Kernel Integrity for Commodity OS from Untrusted Extensions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/Practical Protection of Kernel Integrity for Commodity OS from Untrusted Extensions.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/Return-Oriented Rootkits_Bypassing Kernel Code Integrity Protection Mechanisms.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/Return-Oriented Rootkits_Bypassing Kernel Code Integrity Protection Mechanisms.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/CheckSum/i3fs an in-kernel integrity checker and intrusion detection file system.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/CheckSum/i3fs an in-kernel integrity checker and intrusion detection file system.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/HASH/A new hashing package for UNIX.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/HASH/A new hashing package for UNIX.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/HASH/RFC 1321_The MD5 Message-Digest Algorithm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/HASH/RFC 1321_The MD5 Message-Digest Algorithm.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/HMAC&GCM/HMAC_ Keyed-hashing for message authentication. Technical Report RFC 2104.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/HMAC&GCM/HMAC_ Keyed-hashing for message authentication. Technical Report RFC 2104.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Data Integrity/HMAC&GCM/aes128加密算法的GCM工作模式详解 .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Data Integrity/HMAC&GCM/aes128加密算法的GCM工作模式详解 .pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Old Theses.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Old Theses.rar -------------------------------------------------------------------------------- /Document/Other/Thesis/Stackable/A Stackable File System Interface For Linux.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Stackable/A Stackable File System Interface For Linux.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Stackable/A Stackable Vnode Level Encryption File System.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Stackable/A Stackable Vnode Level Encryption File System.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/Stackable/Stackable Design of File Systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/Stackable/Stackable Design of File Systems.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/eCryptfs/Distributed Encrypting File System for Linux in User-space.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/eCryptfs/Distributed Encrypting File System for Linux in User-space.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/eCryptfs/ECFS_AN ENTERPRISE-CLASS CRYPTOGRAPHIC FILE SYSTEM.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/eCryptfs/ECFS_AN ENTERPRISE-CLASS CRYPTOGRAPHIC FILE SYSTEM.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/eCryptfs/EXT4 Encryption Design Document (public version).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/eCryptfs/EXT4 Encryption Design Document (public version).pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/eCryptfs/Halcrow_EXT4_Encryption.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/eCryptfs/Halcrow_EXT4_Encryption.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/eCryptfs/Transcryptfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/eCryptfs/Transcryptfs.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/eCryptfs/ecryptfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/eCryptfs/ecryptfs.pdf -------------------------------------------------------------------------------- /Document/Other/Thesis/wrapfs and FiST/On Incremental File System Development.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/Other/Thesis/wrapfs and FiST/On Incremental File System Development.pdf -------------------------------------------------------------------------------- /Document/VFS/linux内核设计与实现之VFS文件系统.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/VFS/linux内核设计与实现之VFS文件系统.docx -------------------------------------------------------------------------------- /Document/eCryptfs/Metadata(aes).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/Metadata(aes).png -------------------------------------------------------------------------------- /Document/eCryptfs/Metadata(rsa).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/Metadata(rsa).png -------------------------------------------------------------------------------- /Document/eCryptfs/eCryptfs v0.1 Design Document中文版.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/eCryptfs v0.1 Design Document中文版.docx -------------------------------------------------------------------------------- /Document/eCryptfs/ecryptfs.h.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/ecryptfs.h.pdf -------------------------------------------------------------------------------- /Document/eCryptfs/ecryptfs_kernel.h.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/ecryptfs_kernel.h.pdf -------------------------------------------------------------------------------- /Document/eCryptfs/黄老师笔记(未完)/Keystore.c.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/黄老师笔记(未完)/Keystore.c.docx -------------------------------------------------------------------------------- /Document/eCryptfs/黄老师笔记(未完)/Linux VFS虚拟文件系统-3.3.8.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/黄老师笔记(未完)/Linux VFS虚拟文件系统-3.3.8.docx -------------------------------------------------------------------------------- /Document/eCryptfs/黄老师笔记(未完)/Messaging.c.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/黄老师笔记(未完)/Messaging.c.docx -------------------------------------------------------------------------------- /Document/eCryptfs/黄老师笔记(未完)/Miscdev.c.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/黄老师笔记(未完)/Miscdev.c.docx -------------------------------------------------------------------------------- /Document/eCryptfs/黄老师笔记(未完)/ecryptfs.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/黄老师笔记(未完)/ecryptfs.rar -------------------------------------------------------------------------------- /Document/eCryptfs/黄老师笔记(未完)/ecryptfs内核.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/黄老师笔记(未完)/ecryptfs内核.docx -------------------------------------------------------------------------------- /Document/eCryptfs/黄老师笔记(未完)/read_write.c.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Document/eCryptfs/黄老师笔记(未完)/read_write.c.docx -------------------------------------------------------------------------------- /Miscdev & Message.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Miscdev & Message.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eCryptfs 2 | Name: 3 | Wanli Xing 4 | 5 | Email: 6 | wlxing@yahoo.com 7 | 8 | Github: 9 | https://github.com/JasonXing 10 | 11 | University(undergraduate): 12 | Chongqing University of Posts and Telecommunications 13 | 14 | Contents: 15 | 16 | 1. To Fully Understand about Why eCryptfs Is Developed and How eCryptfs Works. 17 | 18 | 2. My Thinking and Other Implementations on eCryptfs. 19 | -------------------------------------------------------------------------------- /Source Code/README.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Source Code/README.txt -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/Kconfig: -------------------------------------------------------------------------------- 1 | config ECRYPT_FS 2 | tristate "eCrypt filesystem layer support (EXPERIMENTAL)" 3 | depends on EXPERIMENTAL && KEYS && CRYPTO && (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n) 4 | select CRYPTO_ECB 5 | select CRYPTO_CBC 6 | select CRYPTO_MD5 7 | help 8 | Encrypted filesystem that operates on the VFS layer. See 9 | to learn more about 10 | eCryptfs. Userspace components are required and can be 11 | obtained from . 12 | 13 | To compile this file system support as a module, choose M here: the 14 | module will be called ecryptfs. 15 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for the Linux 2.6 eCryptfs 3 | # 4 | 5 | obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o 6 | 7 | ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o miscdev.o kthread.o debug.o 8 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/crypto.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/Source Code/ecryptfs3_3_8/crypto.c -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/debug.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * Functions only useful for debugging. 4 | * 5 | * Copyright (C) 2006 International Business Machines Corp. 6 | * Author(s): Michael A. Halcrow 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License as 10 | * published by the Free Software Foundation; either version 2 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, but 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 21 | * 02111-1307, USA. 22 | */ 23 | 24 | #include "ecryptfs_kernel.h" 25 | 26 | /** 27 | * ecryptfs_dump_auth_tok - debug function to print auth toks 28 | * 29 | * This function will print the contents of an ecryptfs authentication 30 | * token. 31 | */ 32 | void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok) 33 | { 34 | char salt[ECRYPTFS_SALT_SIZE * 2 + 1]; 35 | char sig[ECRYPTFS_SIG_SIZE_HEX + 1]; 36 | 37 | ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n", 38 | auth_tok); 39 | if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) { 40 | ecryptfs_printk(KERN_DEBUG, " * private key type\n"); 41 | } else { 42 | ecryptfs_printk(KERN_DEBUG, " * passphrase type\n"); 43 | ecryptfs_to_hex(salt/*dst*/, auth_tok->token.password.salt/*src*/, 44 | ECRYPTFS_SALT_SIZE); 45 | salt[ECRYPTFS_SALT_SIZE * 2] = '\0'; 46 | ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt); 47 | if (auth_tok->token.password.flags & 48 | ECRYPTFS_PERSISTENT_PASSWORD) { 49 | ecryptfs_printk(KERN_DEBUG, " * persistent\n"); 50 | } 51 | memcpy(sig, auth_tok->token.password.signature, 52 | ECRYPTFS_SIG_SIZE_HEX); 53 | sig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; 54 | ecryptfs_printk(KERN_DEBUG, " * signature = [%s]\n", sig); 55 | } 56 | ecryptfs_printk(KERN_DEBUG, " * session_key.flags = [0x%x]\n", 57 | auth_tok->session_key.flags); 58 | if (auth_tok->session_key.flags 59 | & ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT) 60 | ecryptfs_printk(KERN_DEBUG, 61 | " * Userspace decrypt request set\n"); 62 | if (auth_tok->session_key.flags 63 | & ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT) 64 | ecryptfs_printk(KERN_DEBUG, 65 | " * Userspace encrypt request set\n"); 66 | if (auth_tok->session_key.flags & ECRYPTFS_CONTAINS_DECRYPTED_KEY) { 67 | ecryptfs_printk(KERN_DEBUG, " * Contains decrypted key\n"); 68 | ecryptfs_printk(KERN_DEBUG, 69 | " * session_key.decrypted_key_size = [0x%x]\n", 70 | auth_tok->session_key.decrypted_key_size); 71 | ecryptfs_printk(KERN_DEBUG, " * Decrypted session key " 72 | "dump:\n"); 73 | if (ecryptfs_verbosity > 0) 74 | ecryptfs_dump_hex(auth_tok->session_key.decrypted_key, 75 | ECRYPTFS_DEFAULT_KEY_BYTES); 76 | } 77 | if (auth_tok->session_key.flags & ECRYPTFS_CONTAINS_ENCRYPTED_KEY) { 78 | ecryptfs_printk(KERN_DEBUG, " * Contains encrypted key\n"); 79 | ecryptfs_printk(KERN_DEBUG, 80 | " * session_key.encrypted_key_size = [0x%x]\n", 81 | auth_tok->session_key.encrypted_key_size); 82 | ecryptfs_printk(KERN_DEBUG, " * Encrypted session key " 83 | "dump:\n"); 84 | if (ecryptfs_verbosity > 0) 85 | ecryptfs_dump_hex(auth_tok->session_key.encrypted_key, 86 | auth_tok->session_key. 87 | encrypted_key_size); 88 | } 89 | } 90 | 91 | /** 92 | * ecryptfs_dump_hex - debug hex printer 93 | * @data: string of bytes to be printed 94 | * @bytes: number of bytes to print 95 | * 96 | * Dump hexadecimal representation of char array 97 | */ 98 | void ecryptfs_dump_hex(char *data, int bytes) 99 | { 100 | int i = 0; 101 | int add_newline = 1; 102 | 103 | if (ecryptfs_verbosity < 1) 104 | return; 105 | if (bytes != 0) { 106 | printk(KERN_DEBUG "0x%.2x.", (unsigned char)data[i]); 107 | i++; 108 | } 109 | while (i < bytes) { 110 | printk("0x%.2x.", (unsigned char)data[i]); 111 | i++; 112 | if (i % 16 == 0) { 113 | printk("\n"); 114 | add_newline = 0; 115 | } else 116 | add_newline = 1; 117 | } 118 | if (add_newline) 119 | printk("\n"); 120 | } 121 | 122 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/dentry.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 1997-2003 Erez Zadok 5 | * Copyright (C) 2001-2003 Stony Brook University 6 | * Copyright (C) 2004-2006 International Business Machines Corp. 7 | * Author(s): Michael A. Halcrow 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License as 11 | * published by the Free Software Foundation; either version 2 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, but 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 22 | * 02111-1307, USA. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "ecryptfs_kernel.h" 31 | 32 | /** 33 | * ecryptfs_d_revalidate - revalidate an ecryptfs dentry 34 | * @dentry: The ecryptfs dentry 35 | * @nd: The associated nameidata 36 | * 37 | * Called when the VFS needs to revalidate a dentry. This 38 | * is called whenever a name lookup finds a dentry in the 39 | * dcache. Most filesystems leave this as NULL, because all their 40 | * dentries in the dcache are valid. 41 | * 42 | * Returns 1 if valid, 0 otherwise. 43 | * 44 | */ 45 | static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) 46 | { 47 | struct dentry *lower_dentry; 48 | struct vfsmount *lower_mnt; 49 | struct dentry *dentry_save = NULL; 50 | struct vfsmount *vfsmount_save = NULL; 51 | int rc = 1; 52 | 53 | if (nd && nd->flags & LOOKUP_RCU) 54 | return -ECHILD; 55 | 56 | lower_dentry = ecryptfs_dentry_to_lower(dentry); 57 | lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); 58 | if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) 59 | goto out; 60 | if (nd) { 61 | dentry_save = nd->path.dentry; 62 | vfsmount_save = nd->path.mnt; 63 | nd->path.dentry = lower_dentry; 64 | nd->path.mnt = lower_mnt; 65 | } 66 | rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); 67 | if (nd) {/* the operation of @revalidate failed */ 68 | nd->path.dentry = dentry_save; 69 | nd->path.mnt = vfsmount_save; 70 | } 71 | if (dentry->d_inode) { 72 | struct inode *lower_inode = 73 | ecryptfs_inode_to_lower(dentry->d_inode); 74 | 75 | fsstack_copy_attr_all(dentry->d_inode, lower_inode);/* copy all attributes */ 76 | } 77 | out: 78 | return rc; 79 | } 80 | 81 | struct kmem_cache *ecryptfs_dentry_info_cache; 82 | 83 | /** 84 | * ecryptfs_d_release 85 | * @dentry: The ecryptfs dentry 86 | * 87 | * Called when a dentry is really deallocated. 88 | */ 89 | static void ecryptfs_d_release(struct dentry *dentry) 90 | { 91 | if (ecryptfs_dentry_to_private(dentry)) { 92 | if (ecryptfs_dentry_to_lower(dentry)) { 93 | dput(ecryptfs_dentry_to_lower(dentry)); 94 | mntput(ecryptfs_dentry_to_lower_mnt(dentry)); 95 | } 96 | kmem_cache_free(ecryptfs_dentry_info_cache, 97 | ecryptfs_dentry_to_private(dentry)); 98 | } 99 | return; 100 | } 101 | 102 | const struct dentry_operations ecryptfs_dops = { 103 | .d_revalidate = ecryptfs_d_revalidate, 104 | .d_release = ecryptfs_d_release, 105 | }; 106 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/file.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 1997-2004 Erez Zadok 5 | * Copyright (C) 2001-2004 Stony Brook University 6 | * Copyright (C) 2004-2007 International Business Machines Corp. 7 | * Author(s): Michael A. Halcrow 8 | * Michael C. Thompson 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License as 12 | * published by the Free Software Foundation; either version 2 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, but 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | * General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 23 | * 02111-1307, USA. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "ecryptfs_kernel.h" 35 | 36 | /** 37 | * ecryptfs_read_update_atime 38 | * 39 | * generic_file_read updates the atime of upper layer inode. But, it 40 | * doesn't give us a chance to update the atime of the lower layer 41 | * inode. This function is a wrapper to generic_file_read. It 42 | * updates the atime of the lower level inode if generic_file_read 43 | * returns without any errors. This is to be used only for file reads. 44 | * The function to be used for directory reads is ecryptfs_read. 45 | */ 46 | static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb, 47 | const struct iovec *iov, 48 | unsigned long nr_segs, loff_t pos) 49 | { 50 | ssize_t rc; 51 | struct dentry *lower_dentry; 52 | struct vfsmount *lower_vfsmount; 53 | struct file *file = iocb->ki_filp; 54 | 55 | rc = generic_file_aio_read(iocb, iov, nr_segs, pos);/* generic filesystem read routine asynchronously*/ 56 | /* 57 | * Even though this is a async interface, we need to wait 58 | * for IO to finish to update atime 59 | */ 60 | if (-EIOCBQUEUED == rc) 61 | rc = wait_on_sync_kiocb(iocb);/* Waits on the given sync kiocb to complete. */ 62 | if (rc >= 0) { 63 | lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry); 64 | lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry); 65 | touch_atime(lower_vfsmount, lower_dentry); 66 | } 67 | return rc; 68 | } 69 | 70 | struct ecryptfs_getdents_callback { 71 | void *dirent; 72 | struct dentry *dentry; 73 | filldir_t filldir; 74 | int filldir_called; 75 | int entries_written; 76 | }; 77 | 78 | /* Inspired by generic filldir in fs/readdir.c */ 79 | static int 80 | ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen, 81 | loff_t offset, u64 ino, unsigned int d_type) 82 | { 83 | struct ecryptfs_getdents_callback *buf = 84 | (struct ecryptfs_getdents_callback *)dirent; 85 | size_t name_size; 86 | char *name; 87 | int rc; 88 | 89 | buf->filldir_called++; 90 | rc = ecryptfs_decode_and_decrypt_filename(&name, &name_size, 91 | buf->dentry, lower_name, 92 | lower_namelen); 93 | if (rc) { 94 | printk(KERN_ERR "%s: Error attempting to decode and decrypt " 95 | "filename [%s]; rc = [%d]\n", __func__, lower_name, 96 | rc); 97 | goto out; 98 | } 99 | rc = buf->filldir(buf->dirent, name, name_size, offset, ino, d_type); 100 | kfree(name); 101 | if (rc >= 0) 102 | buf->entries_written++; 103 | out: 104 | return rc; 105 | } 106 | 107 | /** 108 | * ecryptfs_readdir 109 | * @file: The eCryptfs directory file 110 | * @dirent: Directory entry handle 111 | * @filldir: The filldir callback function 112 | */ 113 | static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) 114 | { 115 | int rc; 116 | struct file *lower_file; 117 | struct inode *inode; 118 | struct ecryptfs_getdents_callback buf; 119 | 120 | lower_file = ecryptfs_file_to_lower(file); 121 | lower_file->f_pos = file->f_pos; 122 | inode = file->f_path.dentry->d_inode; 123 | memset(&buf, 0, sizeof(buf)); 124 | buf.dirent = dirent; 125 | buf.dentry = file->f_path.dentry; 126 | buf.filldir = filldir; 127 | buf.filldir_called = 0; 128 | buf.entries_written = 0; 129 | rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf); 130 | file->f_pos = lower_file->f_pos; 131 | if (rc < 0) 132 | goto out; 133 | if (buf.filldir_called && !buf.entries_written) 134 | goto out; 135 | if (rc >= 0) 136 | fsstack_copy_attr_atime(inode, 137 | lower_file->f_path.dentry->d_inode); 138 | out: 139 | return rc; 140 | } 141 | 142 | static void ecryptfs_vma_close(struct vm_area_struct *vma) 143 | { 144 | filemap_write_and_wait(vma->vm_file->f_mapping); 145 | } 146 | 147 | static const struct vm_operations_struct ecryptfs_file_vm_ops = { 148 | .close = ecryptfs_vma_close, 149 | .fault = filemap_fault, 150 | }; 151 | 152 | static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma) 153 | { 154 | int rc; 155 | 156 | rc = generic_file_mmap(file, vma); 157 | if (!rc) 158 | vma->vm_ops = &ecryptfs_file_vm_ops; 159 | 160 | return rc; 161 | } 162 | 163 | struct kmem_cache *ecryptfs_file_info_cache; 164 | 165 | /** 166 | * ecryptfs_open 167 | * @inode: inode specifying file to open 168 | * @file: Structure to return filled in 169 | * 170 | * Opens the file specified by inode. 171 | * 172 | * Returns zero on success; non-zero otherwise 173 | */ 174 | static int ecryptfs_open(struct inode *inode, struct file *file/*dst*/) 175 | { 176 | int rc = 0; 177 | struct ecryptfs_crypt_stat *crypt_stat = NULL; 178 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 179 | struct dentry *ecryptfs_dentry = file->f_path/* contains the dentry */.dentry; 180 | /* Private value of ecryptfs_dentry allocated in 181 | * ecryptfs_lookup() */ 182 | struct dentry *lower_dentry; 183 | struct ecryptfs_file_info *file_info; 184 | 185 | mount_crypt_stat = &ecryptfs_superblock_to_private( 186 | ecryptfs_dentry->d_sb)->mount_crypt_stat; 187 | if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) 188 | && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) 189 | || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) 190 | || (file->f_flags & O_APPEND))) { 191 | printk(KERN_WARNING "Mount has encrypted view enabled; " 192 | "files may only be read\n"); 193 | rc = -EPERM; 194 | goto out; 195 | } 196 | /* Released in ecryptfs_release or end of function if failure */ 197 | file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);/* Return zeroed page on success */ 198 | ecryptfs_set_file_private(file/*dst*/, file_info/*src*/);/*file->private_data = file_info*/ 199 | if (!file_info) { 200 | ecryptfs_printk(KERN_ERR, 201 | "Error attempting to allocate memory\n"); 202 | rc = -ENOMEM; 203 | goto out; 204 | } 205 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 206 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; 207 | mutex_lock(&crypt_stat->cs_mutex); 208 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED/*Apply policy*/)) { 209 | ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); 210 | /* Policy code enabled in future release */ 211 | crypt_stat->flags |= (ECRYPTFS_POLICY_APPLIED 212 | | ECRYPTFS_ENCRYPTED/*Encrypt file*/); 213 | } 214 | mutex_unlock(&crypt_stat->cs_mutex); 215 | rc = ecryptfs_get_lower_file(ecryptfs_dentry/*dst*/, inode); 216 | if (rc) { 217 | printk(KERN_ERR "%s: Error attempting to initialize " 218 | "the lower file for the dentry with name " 219 | "[%s]; rc = [%d]\n", __func__, 220 | ecryptfs_dentry->d_name.name, rc); 221 | goto out_free; 222 | } 223 | if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) 224 | == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { 225 | rc = -EPERM; 226 | printk(KERN_WARNING "%s: Lower file is RO; eCryptfs " 227 | "file must hence be opened RO\n", __func__); 228 | goto out_put; 229 | } 230 | ecryptfs_set_file_lower( 231 | file, ecryptfs_inode_to_private(inode)->lower_file); 232 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { 233 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); 234 | mutex_lock(&crypt_stat->cs_mutex); 235 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 236 | mutex_unlock(&crypt_stat->cs_mutex); 237 | rc = 0; 238 | goto out; 239 | } 240 | /* At this point, we know it is not the dir */ 241 | mutex_lock(&crypt_stat->cs_mutex); 242 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) 243 | || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { 244 | rc = ecryptfs_read_metadata(ecryptfs_dentry); 245 | if (rc) { 246 | ecryptfs_printk(KERN_DEBUG, 247 | "Valid headers not found\n"); 248 | if (!(mount_crypt_stat->flags 249 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { 250 | rc = -EIO; 251 | printk(KERN_WARNING "Either the lower file " 252 | "is not in a valid eCryptfs format, " 253 | "or the key could not be retrieved. " 254 | "Plaintext passthrough mode is not " 255 | "enabled; returning -EIO\n"); 256 | mutex_unlock(&crypt_stat->cs_mutex); 257 | goto out_put; 258 | } 259 | rc = 0; 260 | crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED 261 | | ECRYPTFS_ENCRYPTED); 262 | mutex_unlock(&crypt_stat->cs_mutex); 263 | goto out; 264 | } 265 | } 266 | mutex_unlock(&crypt_stat->cs_mutex); 267 | ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = " 268 | "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, 269 | (unsigned long long)i_size_read(inode)); 270 | goto out; 271 | out_put: 272 | ecryptfs_put_lower_file(inode); 273 | out_free: 274 | kmem_cache_free(ecryptfs_file_info_cache, 275 | ecryptfs_file_to_private(file)); 276 | out: 277 | return rc; 278 | } 279 | 280 | static int ecryptfs_flush(struct file *file, fl_owner_t td) 281 | { 282 | return file->f_mode & FMODE_WRITE 283 | ? filemap_write_and_wait(file->f_mapping) : 0; 284 | } 285 | 286 | static int ecryptfs_release(struct inode *inode, struct file *file) 287 | { 288 | ecryptfs_put_lower_file(inode); 289 | kmem_cache_free(ecryptfs_file_info_cache, 290 | ecryptfs_file_to_private(file)); 291 | return 0; 292 | } 293 | 294 | static int 295 | ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) 296 | { 297 | int rc = 0; 298 | 299 | rc = generic_file_fsync(file, start, end, datasync); 300 | if (rc) 301 | goto out; 302 | rc = vfs_fsync_range(ecryptfs_file_to_lower(file), start, end, 303 | datasync); 304 | out: 305 | return rc; 306 | } 307 | 308 | static int ecryptfs_fasync(int fd, struct file *file, int flag) 309 | { 310 | int rc = 0; 311 | struct file *lower_file = NULL; 312 | 313 | lower_file = ecryptfs_file_to_lower(file); 314 | if (lower_file->f_op && lower_file->f_op->fasync) 315 | rc = lower_file->f_op->fasync(fd, lower_file, flag); 316 | return rc; 317 | } 318 | 319 | static long 320 | ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 321 | { 322 | struct file *lower_file = NULL; 323 | long rc = -ENOTTY; 324 | 325 | if (ecryptfs_file_to_private(file)) 326 | lower_file = ecryptfs_file_to_lower(file); 327 | if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl) 328 | rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); 329 | return rc; 330 | } 331 | 332 | #ifdef CONFIG_COMPAT 333 | static long 334 | ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 335 | { 336 | struct file *lower_file = NULL; 337 | long rc = -ENOIOCTLCMD; 338 | 339 | if (ecryptfs_file_to_private(file)) 340 | lower_file = ecryptfs_file_to_lower(file); 341 | if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl) 342 | rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); 343 | return rc; 344 | } 345 | #endif 346 | 347 | const struct file_operations ecryptfs_dir_fops = { 348 | .readdir = ecryptfs_readdir, 349 | .read = generic_read_dir, 350 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, 351 | #ifdef CONFIG_COMPAT 352 | .compat_ioctl = ecryptfs_compat_ioctl, 353 | #endif 354 | .open = ecryptfs_open, 355 | .flush = ecryptfs_flush, 356 | .release = ecryptfs_release, 357 | .fsync = ecryptfs_fsync, 358 | .fasync = ecryptfs_fasync, 359 | .splice_read = generic_file_splice_read, 360 | .llseek = default_llseek, 361 | }; 362 | 363 | const struct file_operations ecryptfs_main_fops = { 364 | .llseek = generic_file_llseek, 365 | .read = do_sync_read, 366 | .aio_read = ecryptfs_read_update_atime, 367 | .write = do_sync_write, 368 | .aio_write = generic_file_aio_write, 369 | .readdir = ecryptfs_readdir, 370 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, 371 | #ifdef CONFIG_COMPAT 372 | .compat_ioctl = ecryptfs_compat_ioctl, 373 | #endif 374 | .mmap = ecryptfs_file_mmap, 375 | .open = ecryptfs_open, 376 | .flush = ecryptfs_flush, 377 | .release = ecryptfs_release, 378 | .fsync = ecryptfs_fsync, 379 | .fasync = ecryptfs_fasync, 380 | .splice_read = generic_file_splice_read, 381 | }; 382 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/kthread.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 2008 International Business Machines Corp. 5 | * Author(s): Michael A. Halcrow 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 | * 02111-1307, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "ecryptfs_kernel.h" 29 | 30 | struct kmem_cache *ecryptfs_open_req_cache; 31 | 32 | #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 33 | static struct ecryptfs_kthread_ctl { 34 | u32 flags; 35 | struct mutex mux; 36 | struct list_head req_list; 37 | wait_queue_head_t wait; 38 | } ecryptfs_kthread_ctl; 39 | 40 | static struct task_struct *ecryptfs_kthread; 41 | 42 | /** 43 | * ecryptfs_threadfn 44 | * @ignored: ignored 45 | * 46 | * The eCryptfs kernel thread that has the responsibility of getting 47 | * the lower file with RW(Read-Write) permissions. 48 | * 49 | * Returns zero on success; non-zero otherwise 50 | */ 51 | static int ecryptfs_threadfn(void *ignored) 52 | { 53 | set_freezable();/* Clear off the flag(PF_NOFREEZE). Mark %current freezable and enter refrigerator if necessary*/ 54 | while (1) { 55 | struct ecryptfs_open_req *req; 56 | 57 | wait_event_freezable( 58 | ecryptfs_kthread_ctl.wait, 59 | (!list_empty(&ecryptfs_kthread_ctl.req_list) 60 | || kthread_should_stop()));/* Sleep until a condition gets true */ 61 | mutex_lock(&ecryptfs_kthread_ctl.mux); 62 | if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { 63 | mutex_unlock(&ecryptfs_kthread_ctl.mux); 64 | goto out; 65 | } 66 | while (!list_empty(&ecryptfs_kthread_ctl.req_list)) {/* Tests whether a list is empty */ 67 | /* It's not empty */ 68 | req = list_first_entry(&ecryptfs_kthread_ctl.req_list, 69 | struct ecryptfs_open_req, 70 | kthread_ctl_list);/* Get the first element from a list */ 71 | mutex_lock(&req->mux); 72 | list_del(&req->kthread_ctl_list);/* Delete a list entry by making the prev/next entries point to each other */ 73 | if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) { 74 | dget(req->lower_dentry); 75 | mntget(req->lower_mnt); 76 | (*req->lower_file) = dentry_open( 77 | req->lower_dentry, req->lower_mnt, 78 | (O_RDWR | O_LARGEFILE), current_cred()); 79 | req->flags |= ECRYPTFS_REQ_PROCESSED; 80 | } 81 | wake_up(&req->wait); 82 | mutex_unlock(&req->mux); 83 | } 84 | mutex_unlock(&ecryptfs_kthread_ctl.mux); 85 | } 86 | out: 87 | return 0; 88 | } 89 | 90 | /* Returns zero on success */ 91 | int __init ecryptfs_init_kthread(void) 92 | { 93 | int rc = 0; 94 | 95 | mutex_init(&ecryptfs_kthread_ctl.mux); 96 | init_waitqueue_head(&ecryptfs_kthread_ctl.wait); 97 | INIT_LIST_HEAD(&ecryptfs_kthread_ctl.req_list); 98 | ecryptfs_kthread = kthread_run(&ecryptfs_threadfn, NULL, 99 | "ecryptfs-kthread");/* Create and wake a thread. */ 100 | if (IS_ERR(ecryptfs_kthread)) { 101 | rc = PTR_ERR(ecryptfs_kthread); 102 | printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]" 103 | "\n", __func__, rc); 104 | } 105 | return rc; 106 | } 107 | 108 | /** 109 | * kthread_run - create and wake a thread. 110 | * @threadfn: the function to run until signal_pending(current). 111 | * @data: data ptr for @threadfn. 112 | * @namefmt: printf-style name for the thread. 113 | * 114 | * Description: Convenient wrapper for kthread_create() followed by 115 | * wake_up_process(). Returns the kthread or ERR_PTR(-ENOMEM). 116 | */ 117 | #define kthread_run(threadfn, data, namefmt, ...) \ 118 | ({ \ 119 | struct task_struct *__k \ 120 | = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \ 121 | if (!IS_ERR(__k)) \ 122 | wake_up_process(__k); \ 123 | __k; \ 124 | }) 125 | 126 | struct task_struct *kthread_create(int (*threadfn)(void *data), 127 | void *data, 128 | const char namefmt[], 129 | ...) 130 | { 131 | struct kthread_create_info create; 132 | 133 | create.threadfn = threadfn; 134 | create.data = data; 135 | init_completion(&create.started); 136 | init_completion(&create.done); 137 | 138 | spin_lock(&kthread_create_lock); 139 | list_add_tail(&create.list, &kthread_create_list); 140 | wake_up_process(kthreadd_task); 141 | spin_unlock(&kthread_create_lock); 142 | 143 | wait_for_completion(&create.done); 144 | 145 | if (!IS_ERR(create.result)) { 146 | va_list args; 147 | va_start(args, namefmt); 148 | vsnprintf(create.result->comm, sizeof(create.result->comm), 149 | namefmt, args); 150 | va_end(args); 151 | } 152 | return create.result; 153 | } 154 | 155 | void ecryptfs_destroy_kthread(void) 156 | { 157 | struct ecryptfs_open_req *req; 158 | 159 | mutex_lock(&ecryptfs_kthread_ctl.mux); 160 | ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE; 161 | list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list, 162 | kthread_ctl_list) { 163 | mutex_lock(&req->mux); 164 | req->flags |= ECRYPTFS_REQ_ZOMBIE; 165 | wake_up(&req->wait); 166 | mutex_unlock(&req->mux); 167 | } 168 | mutex_unlock(&ecryptfs_kthread_ctl.mux); 169 | kthread_stop(ecryptfs_kthread);/* Stop a thread created by kthread_create() */ 170 | wake_up(&ecryptfs_kthread_ctl.wait); 171 | } 172 | 173 | /** 174 | * ecryptfs_privileged_open 175 | * @lower_file: Result of dentry_open by root on lower dentry 176 | * @lower_dentry: Lower dentry for file to open 177 | * @lower_mnt: Lower vfsmount for file to open 178 | * 179 | * This function gets a r/w file opened againt the lower dentry. 180 | * 181 | * Returns zero on success; non-zero otherwise 182 | */ 183 | int ecryptfs_privileged_open(struct file **lower_file, 184 | struct dentry *lower_dentry, 185 | struct vfsmount *lower_mnt, 186 | const struct cred *cred) 187 | { 188 | struct ecryptfs_open_req *req; 189 | int flags = O_LARGEFILE;/* The size of largefile is over 2G */ 190 | int rc = 0; 191 | 192 | /* Corresponding dput() and mntput() are done when the 193 | * lower file is fput() when all eCryptfs files for the inode are 194 | * released. */ 195 | dget(lower_dentry);/* Get a reference to a dentry *//* lower_dentry->d_count++ */ 196 | mntget(lower_mnt);/* lower_mnt->mnt_mount++ */ 197 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; 198 | (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);/* Find an unused file and fill in it with some info*/ 199 | if (!IS_ERR(*lower_file))/* If lower_file is not negative value , that means we go right and IS_ERR returns zero on success */ 200 | goto out;/* Successful */ 201 | if (flags & O_RDONLY) { 202 | rc = PTR_ERR((*lower_file));/* Now, lower_file is a negative value */ 203 | goto out;/* Failure */ 204 | } 205 | req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL); 206 | if (!req) { 207 | rc = -ENOMEM; 208 | goto out;/* Failure */ 209 | } 210 | mutex_init(&req->mux); 211 | req->lower_file = lower_file; 212 | req->lower_dentry = lower_dentry; 213 | req->lower_mnt = lower_mnt; 214 | init_waitqueue_head(&req->wait); 215 | req->flags = 0; 216 | mutex_lock(&ecryptfs_kthread_ctl.mux); 217 | if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { 218 | rc = -EIO; 219 | mutex_unlock(&ecryptfs_kthread_ctl.mux); 220 | printk(KERN_ERR "%s: We are in the middle of shutting down; " 221 | "aborting privileged request to open lower file\n", 222 | __func__); 223 | goto out_free; 224 | } 225 | list_add_tail(&req->kthread_ctl_list/* new */, &ecryptfs_kthread_ctl.req_list/* head */);/* Add a new entry */ 226 | mutex_unlock(&ecryptfs_kthread_ctl.mux); 227 | wake_up(&ecryptfs_kthread_ctl.wait);/* Wake up threads blocked on a waitqueue. */ 228 | /* The process is put to sleep (TASK_UNINTERRUPTIBLE) until the @condition evaluates 229 | * to true. flags != 0 so we needn't sleep the process */ 230 | wait_event(req->wait/*wait queue to wait on*/, (req->flags != 0)/*condition*/); 231 | mutex_lock(&req->mux); 232 | BUG_ON(req->flags == 0); 233 | if (req->flags & ECRYPTFS_REQ_DROPPED 234 | || req->flags & ECRYPTFS_REQ_ZOMBIE) { 235 | rc = -EIO; 236 | printk(KERN_WARNING "%s: Privileged open request dropped\n", 237 | __func__); 238 | goto out_unlock;/* Failure */ 239 | } 240 | if (IS_ERR(*req->lower_file)) 241 | rc = PTR_ERR(*req->lower_file); 242 | out_unlock: 243 | mutex_unlock(&req->mux); 244 | out_free: 245 | kmem_cache_free(ecryptfs_open_req_cache, req); 246 | out: 247 | return rc; 248 | } 249 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/miscdev.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 2008 International Business Machines Corp. 5 | * Author(s): Michael A. Halcrow 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License version 9 | * 2 as published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 | * 02111-1307, USA. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "ecryptfs_kernel.h" 31 | 32 | static atomic_t ecryptfs_num_miscdev_opens; 33 | 34 | /** 35 | * ecryptfs_miscdev_poll 36 | * @file: dev file (ignored) 37 | * @pt: dev poll table (ignored) 38 | * 39 | * Returns the poll mask 40 | */ 41 | static unsigned int 42 | ecryptfs_miscdev_poll(struct file *file, poll_table *pt) 43 | { 44 | struct ecryptfs_daemon *daemon; 45 | unsigned int mask = 0; 46 | uid_t euid = current_euid(); 47 | int rc; 48 | 49 | mutex_lock(&ecryptfs_daemon_hash_mux); 50 | /* TODO: Just use file->private_data? */ 51 | rc = ecryptfs_find_daemon_by_euid(&daemon/*dst*/, euid, current_user_ns()); 52 | BUG_ON(rc || !daemon); 53 | mutex_lock(&daemon->mux); 54 | mutex_unlock(&ecryptfs_daemon_hash_mux); 55 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { 56 | printk(KERN_WARNING "%s: Attempt to poll on zombified " 57 | "daemon\n", __func__); 58 | goto out_unlock_daemon; 59 | } 60 | if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) 61 | goto out_unlock_daemon; 62 | if (daemon->flags & ECRYPTFS_DAEMON_IN_POLL) 63 | goto out_unlock_daemon; 64 | daemon->flags |= ECRYPTFS_DAEMON_IN_POLL; 65 | mutex_unlock(&daemon->mux); 66 | poll_wait(file, &daemon->wait, pt); 67 | mutex_lock(&daemon->mux); 68 | if (!list_empty(&daemon->msg_ctx_out_queue)) 69 | mask |= POLLIN | POLLRDNORM; 70 | out_unlock_daemon: 71 | daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL; 72 | mutex_unlock(&daemon->mux); 73 | return mask; 74 | } 75 | 76 | /** 77 | * ecryptfs_miscdev_open 78 | * @inode: inode of miscdev handle (ignored) 79 | * @file: file for miscdev handle (ignored) 80 | * 81 | * Returns zero on success; non-zero otherwise 82 | */ 83 | static int 84 | ecryptfs_miscdev_open(struct inode *inode, struct file *file) 85 | { 86 | struct ecryptfs_daemon *daemon = NULL; 87 | uid_t euid = current_euid(); 88 | int rc; 89 | 90 | mutex_lock(&ecryptfs_daemon_hash_mux); 91 | rc = try_module_get(THIS_MODULE); 92 | if (rc == 0) { 93 | rc = -EIO; 94 | printk(KERN_ERR "%s: Error attempting to increment module use " 95 | "count; rc = [%d]\n", __func__, rc); 96 | goto out_unlock_daemon_list; 97 | } 98 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); 99 | if (rc || !daemon) { 100 | rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(), 101 | task_pid(current)); 102 | if (rc) { 103 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " 104 | "rc = [%d]\n", __func__, rc); 105 | goto out_module_put_unlock_daemon_list; 106 | } 107 | } 108 | mutex_lock(&daemon->mux); 109 | if (daemon->pid != task_pid(current)) { 110 | rc = -EINVAL; 111 | printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], " 112 | "but pid [0x%p] has attempted to open the handle " 113 | "instead\n", __func__, daemon->pid, daemon->euid, 114 | task_pid(current)); 115 | goto out_unlock_daemon; 116 | } 117 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { 118 | rc = -EBUSY; 119 | printk(KERN_ERR "%s: Miscellaneous device handle may only be " 120 | "opened once per daemon; pid [0x%p] already has this " 121 | "handle open\n", __func__, daemon->pid); 122 | goto out_unlock_daemon; 123 | } 124 | daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; 125 | atomic_inc(&ecryptfs_num_miscdev_opens); 126 | out_unlock_daemon: 127 | mutex_unlock(&daemon->mux); 128 | out_module_put_unlock_daemon_list: 129 | if (rc) 130 | module_put(THIS_MODULE); 131 | out_unlock_daemon_list: 132 | mutex_unlock(&ecryptfs_daemon_hash_mux); 133 | return rc; 134 | } 135 | 136 | /** 137 | * ecryptfs_miscdev_release 138 | * @inode: inode of fs/ecryptfs/euid handle (ignored) 139 | * @file: file for fs/ecryptfs/euid handle (ignored) 140 | * 141 | * This keeps the daemon registered until the daemon sends another 142 | * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. 143 | * 144 | * Returns zero on success; non-zero otherwise 145 | */ 146 | static int 147 | ecryptfs_miscdev_release(struct inode *inode, struct file *file) 148 | { 149 | struct ecryptfs_daemon *daemon = NULL; 150 | uid_t euid = current_euid(); 151 | int rc; 152 | 153 | mutex_lock(&ecryptfs_daemon_hash_mux); 154 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); 155 | BUG_ON(rc || !daemon); 156 | mutex_lock(&daemon->mux); 157 | BUG_ON(daemon->pid != task_pid(current)); 158 | BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); 159 | daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; 160 | atomic_dec(&ecryptfs_num_miscdev_opens); 161 | mutex_unlock(&daemon->mux); 162 | rc = ecryptfs_exorcise_daemon(daemon); 163 | if (rc) { 164 | printk(KERN_CRIT "%s: Fatal error whilst attempting to " 165 | "shut down daemon; rc = [%d]. Please report this " 166 | "bug.\n", __func__, rc); 167 | BUG(); 168 | } 169 | module_put(THIS_MODULE); 170 | mutex_unlock(&ecryptfs_daemon_hash_mux); 171 | return rc; 172 | } 173 | 174 | /** 175 | * ecryptfs_send_miscdev 176 | * @data: Data to send to daemon; may be NULL 177 | * @data_size: Amount of data to send to daemon 178 | * @msg_ctx: Message context, which is used to handle the reply. If 179 | * this is NULL, then we do not expect a reply. 180 | * @msg_type: Type of message 181 | * @msg_flags: Flags for message 182 | * @daemon: eCryptfs daemon object 183 | * 184 | * Add msg_ctx to queue and then, if it exists, notify the blocked 185 | * miscdevess about the data being available. Must be called with 186 | * ecryptfs_daemon_hash_mux held. 187 | * 188 | * Returns zero on success; non-zero otherwise 189 | */ 190 | /* Send message to userspace daemon */ 191 | int ecryptfs_send_miscdev(char *data/*src*/, size_t data_size/*src*/, 192 | struct ecryptfs_msg_ctx *msg_ctx/*dst*/, u8 msg_type/*src*/, 193 | u16 msg_flags/*src*/, struct ecryptfs_daemon *daemon/*dst*/) 194 | { 195 | int rc = 0; 196 | 197 | mutex_lock(&msg_ctx->mux); 198 | msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size), 199 | GFP_KERNEL); 200 | if (!msg_ctx->msg) { 201 | rc = -ENOMEM; 202 | printk(KERN_ERR "%s: Out of memory whilst attempting " 203 | "to kmalloc(%zd, GFP_KERNEL)\n", __func__, 204 | (sizeof(*msg_ctx->msg) + data_size)); 205 | goto out_unlock; 206 | } 207 | msg_ctx->msg->index = msg_ctx->index; 208 | msg_ctx->msg->data_len = data_size; 209 | msg_ctx->type = msg_type; 210 | memcpy(msg_ctx->msg->data, data, data_size); 211 | msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size); 212 | mutex_lock(&daemon->mux); 213 | list_add_tail(&msg_ctx->daemon_out_list/*new*/, &daemon->msg_ctx_out_queue/*head*/); 214 | daemon->num_queued_msg_ctx++; 215 | wake_up_interruptible(&daemon->wait); 216 | mutex_unlock(&daemon->mux); 217 | out_unlock: 218 | mutex_unlock(&msg_ctx->mux); 219 | return rc; 220 | } 221 | 222 | /* 223 | * miscdevfs packet format: 224 | * Octet 0: Type 225 | * Octets 1-4: network byte order msg_ctx->counter 226 | * Octets 5-N0: Size of struct ecryptfs_message to follow 227 | * Octets N0-N1: struct ecryptfs_message (including data) 228 | * 229 | * Octets 5-N1 not written if the packet type does not include a message 230 | */ 231 | #define PKT_TYPE_SIZE 1 232 | #define PKT_CTR_SIZE 4 233 | #define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE) 234 | #define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \ 235 | + ECRYPTFS_MIN_PKT_LEN_SIZE) 236 | /* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */ 237 | #define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \ 238 | + ECRYPTFS_MAX_PKT_LEN_SIZE \ 239 | + sizeof(struct ecryptfs_message) \ 240 | + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) 241 | #define PKT_TYPE_OFFSET 0 242 | #define PKT_CTR_OFFSET PKT_TYPE_SIZE 243 | #define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE) 244 | 245 | /** 246 | * ecryptfs_miscdev_read - format and send message from queue 247 | * @file: fs/ecryptfs/euid miscdevfs handle (ignored) 248 | * @buf: User buffer into which to copy the next message on the daemon queue 249 | * @count: Amount of space available in @buf 250 | * @ppos: Offset in file (ignored) 251 | * 252 | * Pulls the most recent message from the daemon queue, formats it for 253 | * being sent via a miscdevfs handle, and copies it into @buf 254 | * 255 | * Returns the number of bytes copied into the user buffer 256 | */ 257 | static ssize_t 258 | ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, 259 | loff_t *ppos) 260 | { 261 | struct ecryptfs_daemon *daemon; 262 | struct ecryptfs_msg_ctx *msg_ctx; 263 | size_t packet_length_size; 264 | char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; 265 | size_t i; 266 | size_t total_length; 267 | uid_t euid = current_euid(); 268 | int rc; 269 | 270 | mutex_lock(&ecryptfs_daemon_hash_mux); 271 | /* TODO: Just use file->private_data? */ 272 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); 273 | BUG_ON(rc || !daemon); 274 | mutex_lock(&daemon->mux); 275 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { 276 | rc = 0; 277 | mutex_unlock(&ecryptfs_daemon_hash_mux); 278 | printk(KERN_WARNING "%s: Attempt to read from zombified " 279 | "daemon\n", __func__); 280 | goto out_unlock_daemon; 281 | } 282 | if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { 283 | rc = 0; 284 | mutex_unlock(&ecryptfs_daemon_hash_mux); 285 | goto out_unlock_daemon; 286 | } 287 | /* This daemon will not go away so long as this flag is set */ 288 | daemon->flags |= ECRYPTFS_DAEMON_IN_READ; 289 | mutex_unlock(&ecryptfs_daemon_hash_mux); 290 | check_list: 291 | if (list_empty(&daemon->msg_ctx_out_queue)) { 292 | mutex_unlock(&daemon->mux); 293 | rc = wait_event_interruptible( 294 | daemon->wait, !list_empty(&daemon->msg_ctx_out_queue)); 295 | mutex_lock(&daemon->mux); 296 | if (rc < 0) { 297 | rc = 0; 298 | goto out_unlock_daemon; 299 | } 300 | } 301 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { 302 | rc = 0; 303 | goto out_unlock_daemon; 304 | } 305 | if (list_empty(&daemon->msg_ctx_out_queue)) { 306 | /* Something else jumped in since the 307 | * wait_event_interruptable() and removed the 308 | * message from the queue; try again */ 309 | goto check_list; 310 | } 311 | BUG_ON(euid != daemon->euid); 312 | BUG_ON(current_user_ns() != daemon->user_ns); 313 | BUG_ON(task_pid(current) != daemon->pid); 314 | msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue, 315 | struct ecryptfs_msg_ctx, daemon_out_list); 316 | BUG_ON(!msg_ctx); 317 | mutex_lock(&msg_ctx->mux); 318 | if (msg_ctx->msg) { 319 | rc = ecryptfs_write_packet_length(packet_length, 320 | msg_ctx->msg_size, 321 | &packet_length_size); 322 | if (rc) { 323 | rc = 0; 324 | printk(KERN_WARNING "%s: Error writing packet length; " 325 | "rc = [%d]\n", __func__, rc); 326 | goto out_unlock_msg_ctx; 327 | } 328 | } else { 329 | packet_length_size = 0; 330 | msg_ctx->msg_size = 0; 331 | } 332 | total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size 333 | + msg_ctx->msg_size); 334 | if (count < total_length) { 335 | rc = 0; 336 | printk(KERN_WARNING "%s: Only given user buffer of " 337 | "size [%zd], but we need [%zd] to read the " 338 | "pending message\n", __func__, count, total_length); 339 | goto out_unlock_msg_ctx; 340 | } 341 | rc = -EFAULT; 342 | if (put_user(msg_ctx->type, buf)) 343 | goto out_unlock_msg_ctx; 344 | if (put_user(cpu_to_be32(msg_ctx->counter), 345 | (__be32 __user *)(&buf[PKT_CTR_OFFSET]))) 346 | goto out_unlock_msg_ctx; 347 | i = PKT_TYPE_SIZE + PKT_CTR_SIZE; 348 | if (msg_ctx->msg) { 349 | if (copy_to_user(&buf[i], packet_length, packet_length_size)) 350 | goto out_unlock_msg_ctx; 351 | i += packet_length_size; 352 | if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size)) 353 | goto out_unlock_msg_ctx; 354 | i += msg_ctx->msg_size; 355 | } 356 | rc = i; 357 | list_del(&msg_ctx->daemon_out_list); 358 | kfree(msg_ctx->msg); 359 | msg_ctx->msg = NULL; 360 | /* We do not expect a reply from the userspace daemon for any 361 | * message type other than ECRYPTFS_MSG_REQUEST */ 362 | if (msg_ctx->type != ECRYPTFS_MSG_REQUEST) 363 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); 364 | out_unlock_msg_ctx: 365 | mutex_unlock(&msg_ctx->mux); 366 | out_unlock_daemon: 367 | daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ; 368 | mutex_unlock(&daemon->mux); 369 | return rc; 370 | } 371 | 372 | /** 373 | * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon 374 | * @data: Bytes comprising struct ecryptfs_message 375 | * @data_size: sizeof(struct ecryptfs_message) + data len 376 | * @euid: Effective user id of miscdevess sending the miscdev response 377 | * @user_ns: The namespace in which @euid applies 378 | * @pid: Miscdevess id of miscdevess sending the miscdev response 379 | * @seq: Sequence number for miscdev response packet 380 | * 381 | * Returns zero on success; non-zero otherwise 382 | */ 383 | static int ecryptfs_miscdev_response(char *data, size_t data_size, 384 | uid_t euid, struct user_namespace *user_ns, 385 | struct pid *pid, u32 seq) 386 | { 387 | struct ecryptfs_message *msg = (struct ecryptfs_message *)data; 388 | int rc; 389 | 390 | if ((sizeof(*msg) + msg->data_len) != data_size) { 391 | printk(KERN_WARNING "%s: (sizeof(*msg) + msg->data_len) = " 392 | "[%zd]; data_size = [%zd]. Invalid packet.\n", __func__, 393 | (sizeof(*msg) + msg->data_len), data_size); 394 | rc = -EINVAL; 395 | goto out; 396 | } 397 | rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq); 398 | if (rc) 399 | printk(KERN_ERR 400 | "Error processing response message; rc = [%d]\n", rc); 401 | out: 402 | return rc; 403 | } 404 | 405 | /** 406 | * ecryptfs_miscdev_write - handle write to daemon miscdev handle 407 | * @file: File for misc dev handle (ignored) 408 | * @buf: Buffer containing user data 409 | * @count: Amount of data in @buf 410 | * @ppos: Pointer to offset in file (ignored) 411 | * 412 | * Returns the number of bytes read from @buf 413 | */ 414 | static ssize_t 415 | ecryptfs_miscdev_write(struct file *file, const char __user *buf, 416 | size_t count, loff_t *ppos) 417 | { 418 | __be32 counter_nbo; 419 | u32 seq; 420 | size_t packet_size, packet_size_length; 421 | char *data; 422 | uid_t euid = current_euid(); 423 | unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; 424 | ssize_t rc; 425 | 426 | if (count == 0) { 427 | return 0; 428 | } else if (count == MIN_NON_MSG_PKT_SIZE) { 429 | /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */ 430 | goto memdup; 431 | } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) { 432 | printk(KERN_WARNING "%s: Acceptable packet size range is " 433 | "[%d-%zu], but amount of data written is [%zu].", 434 | __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count); 435 | return -EINVAL; 436 | } 437 | 438 | if (copy_from_user(packet_size_peek/*to*/, &buf[PKT_LEN_OFFSET]/*from*/, 439 | sizeof(packet_size_peek))/* Copy a block of data from user space. */) { 440 | printk(KERN_WARNING "%s: Error while inspecting packet size\n", 441 | __func__); 442 | return -EFAULT; 443 | } 444 | 445 | rc = ecryptfs_parse_packet_length(packet_size_peek/*src*/, &packet_size/*dst*/, 446 | &packet_size_length); 447 | if (rc) { 448 | printk(KERN_WARNING "%s: Error parsing packet length; " 449 | "rc = [%zd]\n", __func__, rc); 450 | return rc; 451 | } 452 | 453 | if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size) 454 | != count) { 455 | printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__, 456 | packet_size); 457 | return -EINVAL; 458 | } 459 | 460 | memdup: 461 | data = memdup_user(buf, count); 462 | if (IS_ERR(data)) { 463 | printk(KERN_ERR "%s: memdup_user returned error [%ld]\n", 464 | __func__, PTR_ERR(data)); 465 | return PTR_ERR(data); 466 | } 467 | switch (data[PKT_TYPE_OFFSET]) { 468 | case ECRYPTFS_MSG_RESPONSE: 469 | if (count < (MIN_MSG_PKT_SIZE 470 | + sizeof(struct ecryptfs_message))) { 471 | printk(KERN_WARNING "%s: Minimum acceptable packet " 472 | "size is [%zd], but amount of data written is " 473 | "only [%zd]. Discarding response packet.\n", 474 | __func__, 475 | (MIN_MSG_PKT_SIZE 476 | + sizeof(struct ecryptfs_message)), count); 477 | rc = -EINVAL; 478 | goto out_free; 479 | } 480 | memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); 481 | seq = be32_to_cpu(counter_nbo); 482 | rc = ecryptfs_miscdev_response( 483 | &data[PKT_LEN_OFFSET + packet_size_length], 484 | packet_size, euid, current_user_ns(), 485 | task_pid(current), seq); 486 | if (rc) { 487 | printk(KERN_WARNING "%s: Failed to deliver miscdev " 488 | "response to requesting operation; rc = [%zd]\n", 489 | __func__, rc); 490 | goto out_free; 491 | } 492 | break; 493 | case ECRYPTFS_MSG_HELO: 494 | case ECRYPTFS_MSG_QUIT: 495 | break; 496 | default: 497 | ecryptfs_printk(KERN_WARNING, "Dropping miscdev " 498 | "message of unrecognized type [%d]\n", 499 | data[0]); 500 | rc = -EINVAL; 501 | goto out_free; 502 | } 503 | rc = count; 504 | out_free: 505 | kfree(data); 506 | return rc; 507 | } 508 | 509 | 510 | static const struct file_operations ecryptfs_miscdev_fops = { 511 | .open = ecryptfs_miscdev_open, 512 | .poll = ecryptfs_miscdev_poll, 513 | .read = ecryptfs_miscdev_read, 514 | .write = ecryptfs_miscdev_write, 515 | .release = ecryptfs_miscdev_release, 516 | .llseek = noop_llseek, 517 | }; 518 | 519 | static struct miscdevice ecryptfs_miscdev = { 520 | .minor = MISC_DYNAMIC_MINOR, 521 | .name = "ecryptfs", 522 | .fops = &ecryptfs_miscdev_fops 523 | }; 524 | 525 | /** 526 | * ecryptfs_init_ecryptfs_miscdev 527 | * 528 | * Messages sent to the userspace daemon from the kernel are placed on 529 | * a queue associated with the daemon. The next read against the 530 | * miscdev handle by that daemon will return the oldest message placed 531 | * on the message queue for the daemon. 532 | * 533 | * Returns zero on success; non-zero otherwise 534 | */ 535 | int __init ecryptfs_init_ecryptfs_miscdev(void) 536 | { 537 | int rc; 538 | 539 | atomic_set(&ecryptfs_num_miscdev_opens, 0); 540 | rc = misc_register(&ecryptfs_miscdev);/* Register a miscellaneous device */ 541 | if (rc) 542 | printk(KERN_ERR "%s: Failed to register miscellaneous device " 543 | "for communications with userspace daemons; rc = [%d]\n", 544 | __func__, rc); 545 | return rc; 546 | } 547 | 548 | /** 549 | * ecryptfs_destroy_ecryptfs_miscdev 550 | * 551 | * All of the daemons must be exorcised prior to calling this 552 | * function. 553 | */ 554 | void ecryptfs_destroy_ecryptfs_miscdev(void) 555 | { 556 | BUG_ON(atomic_read(&ecryptfs_num_miscdev_opens) != 0); 557 | misc_deregister(&ecryptfs_miscdev);/* Unregister a miscellaneous device */ 558 | } 559 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/mmap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * This is where eCryptfs coordinates the symmetric encryption and 4 | * decryption of the file data as it passes between the lower 5 | * encrypted file and the upper decrypted file. 6 | * 7 | * Copyright (C) 1997-2003 Erez Zadok 8 | * Copyright (C) 2001-2003 Stony Brook University 9 | * Copyright (C) 2004-2007 International Business Machines Corp. 10 | * Author(s): Michael A. Halcrow 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License as 14 | * published by the Free Software Foundation; either version 2 of the 15 | * License, or (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, but 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | * General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program; if not, write to the Free Software 24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 25 | * 02111-1307, USA. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "ecryptfs_kernel.h" 38 | 39 | /** 40 | * ecryptfs_get_locked_page 41 | * 42 | * Get one page from cache or lower f/s, return error otherwise. 43 | * 44 | * Returns locked and up-to-date page (if ok), with increased 45 | * refcnt. 46 | */ 47 | struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index) 48 | { 49 | struct page *page = read_mapping_page(inode->i_mapping, index, NULL);/* Read into page cache, fill it if needed */ 50 | if (!IS_ERR(page)) 51 | lock_page(page); 52 | return page; 53 | } 54 | 55 | /** 56 | * ecryptfs_writepage 57 | * @page: Page that is locked before this call is made 58 | * 59 | * Returns zero on success; non-zero otherwise 60 | * 61 | * This is where we encrypt the data and pass the encrypted data to 62 | * the lower filesystem. In OpenPGP-compatible mode, we operate on 63 | * entire underlying packets. 64 | */ 65 | static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) 66 | { 67 | int rc; 68 | 69 | /* 70 | * Refuse to write the page out if we are called from reclaim context 71 | * since our writepage() path may potentially allocate memory when 72 | * calling into the lower fs vfs_write() which may in turn invoke 73 | * us again. 74 | */ 75 | if (current->flags & PF_MEMALLOC) {/* Allocating memory */ 76 | redirty_page_for_writepage(wbc, page);/* Redirty the locked page and unlock the page */ 77 | rc = 0; 78 | goto out; 79 | } 80 | 81 | rc = ecryptfs_encrypt_page(page); 82 | if (rc) { 83 | ecryptfs_printk(KERN_WARNING, "Error encrypting " 84 | "page (upper index [0x%.16lx])\n", page->index); 85 | ClearPageUptodate(page); 86 | goto out; 87 | } 88 | SetPageUptodate(page);/* Set certain bit to PG_uptodate(page->flags) */ 89 | out: 90 | unlock_page(page);/* Page that is locked before this call is made */ 91 | return rc; 92 | } 93 | 94 | static void strip_xattr_flag(char *page_virt, 95 | struct ecryptfs_crypt_stat *crypt_stat) 96 | { 97 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { 98 | size_t written; 99 | 100 | crypt_stat->flags &= ~ECRYPTFS_METADATA_IN_XATTR; 101 | ecryptfs_write_crypt_stat_flags(page_virt, crypt_stat, 102 | &written);/* Copy from @flags to dst(@&page_virt) */ 103 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; 104 | } 105 | } 106 | 107 | /** 108 | * Header Extent: 109 | * Octets 0-7: Unencrypted file size (big-endian) 110 | * Octets 8-15: eCryptfs special marker 111 | * Octets 16-19: Flags 112 | * Octet 16: File format version number (between 0 and 255) 113 | * Octets 17-18: Reserved 114 | * Octet 19: Bit 1 (lsb): Reserved 115 | * Bit 2: Encrypted? 116 | * Bits 3-8: Reserved 117 | * 118 | * Octets 20-23: Header extent size (big-endian) 119 | * Octets 24-25: Number of header extents at front of file 120 | * (big-endian) 121 | * Octet 26: Begin RFC 2440 authentication token packet set 122 | */ 123 | 124 | /** 125 | * ecryptfs_copy_up_encrypted_with_header 126 | * @page: Sort of a ''virtual'' representation of the encrypted lower 127 | * file. The actual lower file does not have the metadata in 128 | * the header. This is locked. 129 | * @crypt_stat: The eCryptfs inode's cryptographic context 130 | * 131 | * The ''view'' is the version of the file that userspace winds up 132 | * seeing, with the header information inserted. 133 | */ 134 | /* Copy the encrypted content from the lower file whilst inserting the metadata from the xattr into the header */ 135 | static int 136 | ecryptfs_copy_up_encrypted_with_header(struct page *page, 137 | struct ecryptfs_crypt_stat *crypt_stat) 138 | { 139 | loff_t extent_num_in_page = 0; 140 | loff_t num_extents_per_page = (PAGE_CACHE_SIZE 141 | / crypt_stat->extent_size); 142 | int rc = 0; 143 | 144 | while (extent_num_in_page < num_extents_per_page) { 145 | loff_t view_extent_num = ((((loff_t)page->index/*Our offset within mapping*/) 146 | * num_extents_per_page) 147 | + extent_num_in_page); 148 | size_t num_header_extents_at_front = 149 | (crypt_stat->metadata_size / crypt_stat->extent_size); 150 | 151 | if (view_extent_num < num_header_extents_at_front) { 152 | /* This is a header area */ 153 | char *page_virt; 154 | 155 | page_virt = kmap_atomic(page); 156 | memset(page_virt, 0, PAGE_CACHE_SIZE); 157 | /* TODO: Support more than one header extent */ 158 | if (view_extent_num == 0) { 159 | size_t written; 160 | 161 | rc = ecryptfs_read_xattr_region( 162 | page_virt/*dst*/, page->mapping->host);/*xattr: ?16 octets?*/ 163 | strip_xattr_flag(page_virt + 16/*dst*/, crypt_stat);/*flag: ?4 octets?*/ 164 | ecryptfs_write_header_metadata(page_virt + 20/*dst*/, 165 | crypt_stat, 166 | &written/*6*/);/*header extent size + num_header_extents_at_front: 6 octets*/ 167 | } 168 | kunmap_atomic(page_virt); 169 | flush_dcache_page(page); 170 | if (rc) { 171 | printk(KERN_ERR "%s: Error reading xattr " 172 | "region; rc = [%d]\n", __func__, rc); 173 | goto out; 174 | } 175 | } else { 176 | /* This is an encrypted data area */ 177 | loff_t lower_offset = 178 | ((view_extent_num * crypt_stat->extent_size) 179 | - crypt_stat->metadata_size); 180 | 181 | rc = ecryptfs_read_lower_page_segment( 182 | page/*dst*/, (lower_offset >> PAGE_CACHE_SHIFT), 183 | (lower_offset & ~PAGE_CACHE_MASK), 184 | crypt_stat->extent_size, page->mapping->host); 185 | if (rc) { 186 | printk(KERN_ERR "%s: Error attempting to read " 187 | "extent at offset [%lld] in the lower " 188 | "file; rc = [%d]\n", __func__, 189 | lower_offset, rc); 190 | goto out; 191 | } 192 | } 193 | extent_num_in_page++; 194 | } 195 | out: 196 | return rc; 197 | } 198 | 199 | /** 200 | * ecryptfs_readpage 201 | * @file: An eCryptfs file 202 | * @page: Page from eCryptfs inode mapping into which to stick the read data 203 | * 204 | * Read in a page, decrypting if necessary. 205 | * 206 | * Returns zero on success; non-zero on error. 207 | */ 208 | static int ecryptfs_readpage(struct file *file, struct page *page) 209 | { 210 | struct ecryptfs_crypt_stat *crypt_stat = 211 | &ecryptfs_inode_to_private(page->mapping->host)->crypt_stat; 212 | int rc = 0; 213 | 214 | if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { 215 | /* We can't read any crypto information or flags&ECRYPTFS_ENCRYPED == 9. 216 | * That file is not encrypted, so we can read right now */ 217 | rc = ecryptfs_read_lower_page_segment(page/*dst*/, page->index, 0, 218 | PAGE_CACHE_SIZE, 219 | page->mapping->host); 220 | } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {/* View as encrypted file */ 221 | /* We've encrypted the page */ 222 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { 223 | /* Metadata in xattr */ 224 | rc = ecryptfs_copy_up_encrypted_with_header(page/*dst*/, 225 | crypt_stat);/*Some info about size and encrypted data */ 226 | if (rc) { 227 | printk(KERN_ERR "%s: Error attempting to copy " 228 | "the encrypted content from the lower " 229 | "file whilst inserting the metadata " 230 | "from the xattr into the header; rc = " 231 | "[%d]\n", __func__, rc); 232 | goto out; 233 | } 234 | 235 | } else { 236 | /* Metadata in header */ 237 | rc = ecryptfs_read_lower_page_segment( 238 | page/*dst*/, page->index, 0, PAGE_CACHE_SIZE, 239 | page->mapping->host); 240 | if (rc) { 241 | printk(KERN_ERR "Error reading page; rc = " 242 | "[%d]\n", rc); 243 | goto out; 244 | } 245 | } 246 | } else { 247 | /* Not view as encrypted file */ 248 | rc = ecryptfs_decrypt_page(page); 249 | if (rc) { 250 | ecryptfs_printk(KERN_ERR, "Error decrypting page; " 251 | "rc = [%d]\n", rc); 252 | goto out; 253 | } 254 | } 255 | out: 256 | if (rc) 257 | ClearPageUptodate(page); 258 | else 259 | SetPageUptodate(page); 260 | ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]\n", 261 | page->index); 262 | unlock_page(page); 263 | return rc; 264 | } 265 | 266 | /** 267 | * Called with lower inode mutex held. 268 | */ 269 | static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) 270 | { 271 | struct inode *inode = page->mapping->host; 272 | int end_byte_in_page; 273 | 274 | if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index) 275 | goto out; 276 | end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; 277 | if (to > end_byte_in_page) 278 | end_byte_in_page = to; 279 | zero_user_segment(page, end_byte_in_page, PAGE_CACHE_SIZE);/* Set the virtual address of page from @end_byte_in_page to @PAGE_CACHE_SIZE to zero */ 280 | out: 281 | return 0; 282 | } 283 | 284 | /** 285 | * ecryptfs_write_begin 286 | * @file: The eCryptfs file 287 | * @mapping: The eCryptfs object 288 | * @pos: The file offset at which to start writing 289 | * @len: Length of the write 290 | * @flags: Various flags 291 | * @pagep: Pointer to return the page 292 | * @fsdata: Pointer to return fs data (unused) 293 | * 294 | * This function must zero any hole we create 295 | * 296 | * Returns zero on success; non-zero otherwise 297 | */ 298 | static int ecryptfs_write_begin(struct file *file, 299 | struct address_space *mapping, 300 | loff_t pos, unsigned len, unsigned flags, 301 | struct page **pagep, void **fsdata) 302 | { 303 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; 304 | struct page *page; 305 | loff_t prev_page_end_size; 306 | int rc = 0; 307 | 308 | page = grab_cache_page_write_begin(mapping, index, flags);/* Find or create a page at the given pagecache position */ 309 | if (!page) 310 | return -ENOMEM; 311 | *pagep = page; 312 | 313 | prev_page_end_size = ((loff_t)index << PAGE_CACHE_SHIFT); 314 | if (!PageUptodate(page)) { 315 | struct ecryptfs_crypt_stat *crypt_stat = 316 | &ecryptfs_inode_to_private(mapping->host)->crypt_stat; 317 | 318 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { 319 | rc = ecryptfs_read_lower_page_segment( 320 | page, index, 0, PAGE_CACHE_SIZE, mapping->host);/* Read from @page to @mapping->host */ 321 | if (rc) { 322 | printk(KERN_ERR "%s: Error attemping to read " 323 | "lower page segment; rc = [%d]\n", 324 | __func__, rc); 325 | ClearPageUptodate(page); 326 | goto out; 327 | } else 328 | SetPageUptodate(page); 329 | } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { 330 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { 331 | rc = ecryptfs_copy_up_encrypted_with_header( 332 | page, crypt_stat); 333 | if (rc) { 334 | printk(KERN_ERR "%s: Error attempting " 335 | "to copy the encrypted content " 336 | "from the lower file whilst " 337 | "inserting the metadata from " 338 | "the xattr into the header; rc " 339 | "= [%d]\n", __func__, rc); 340 | ClearPageUptodate(page); 341 | goto out; 342 | } 343 | SetPageUptodate(page); 344 | } else { 345 | rc = ecryptfs_read_lower_page_segment( 346 | page, index, 0, PAGE_CACHE_SIZE, 347 | mapping->host); 348 | if (rc) { 349 | printk(KERN_ERR "%s: Error reading " 350 | "page; rc = [%d]\n", 351 | __func__, rc); 352 | ClearPageUptodate(page); 353 | goto out; 354 | } 355 | SetPageUptodate(page); 356 | } 357 | } else { 358 | if (prev_page_end_size 359 | >= i_size_read(page->mapping->host)) { 360 | zero_user(page, 0, PAGE_CACHE_SIZE); 361 | } else { 362 | rc = ecryptfs_decrypt_page(page); 363 | if (rc) { 364 | printk(KERN_ERR "%s: Error decrypting " 365 | "page at index [%ld]; " 366 | "rc = [%d]\n", 367 | __func__, page->index, rc); 368 | ClearPageUptodate(page); 369 | goto out; 370 | } 371 | } 372 | SetPageUptodate(page); 373 | } 374 | } 375 | /* If creating a page or more of holes, zero them out via truncate. 376 | * Note, this will increase i_size. */ 377 | if (index != 0) { 378 | if (prev_page_end_size > i_size_read(page->mapping->host)) { 379 | rc = ecryptfs_truncate(file->f_path.dentry, 380 | prev_page_end_size); 381 | if (rc) { 382 | printk(KERN_ERR "%s: Error on attempt to " 383 | "truncate to (higher) offset [%lld];" 384 | " rc = [%d]\n", __func__, 385 | prev_page_end_size, rc); 386 | goto out; 387 | } 388 | } 389 | } 390 | /* Writing to a new page, and creating a small hole from start 391 | * of page? Zero it out. */ 392 | if ((i_size_read(mapping->host) == prev_page_end_size) 393 | && (pos != 0)) 394 | zero_user(page, 0, PAGE_CACHE_SIZE); 395 | out: 396 | if (unlikely(rc)) { 397 | unlock_page(page); 398 | page_cache_release(page); 399 | *pagep = NULL; 400 | } 401 | return rc; 402 | } 403 | 404 | /** 405 | * ecryptfs_write_inode_size_to_header 406 | * 407 | * Writes the lower file size to the first 8 bytes of the header. 408 | * 409 | * Returns zero on success; non-zero on error. 410 | */ 411 | static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode) 412 | { 413 | char *file_size_virt; 414 | int rc; 415 | 416 | file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL); 417 | if (!file_size_virt) { 418 | rc = -ENOMEM; 419 | goto out; 420 | } 421 | put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt); 422 | rc = ecryptfs_write_lower(ecryptfs_inode/*dst*/, file_size_virt/*src*/, 0, 423 | sizeof(u64));/* @offset = 0, sizeof(u64) = 8 , 424 | * Write @file_size_virt to the first 8 bytes of the header(@ecryptfs_inode) */ 425 | kfree(file_size_virt); 426 | if (rc < 0) 427 | printk(KERN_ERR "%s: Error writing file size to header; " 428 | "rc = [%d]\n", __func__, rc); 429 | else 430 | rc = 0; 431 | out: 432 | return rc; 433 | } 434 | 435 | struct kmem_cache *ecryptfs_xattr_cache; 436 | 437 | static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode) 438 | { 439 | ssize_t size; 440 | void *xattr_virt; 441 | struct dentry *lower_dentry = 442 | ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry; 443 | struct inode *lower_inode = lower_dentry->d_inode; 444 | int rc; 445 | 446 | if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) { 447 | printk(KERN_WARNING 448 | "No support for setting xattr in lower filesystem\n"); 449 | rc = -ENOSYS; 450 | goto out; 451 | } 452 | xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL); 453 | if (!xattr_virt) { 454 | printk(KERN_ERR "Out of memory whilst attempting to write " 455 | "inode size to xattr\n"); 456 | rc = -ENOMEM; 457 | goto out; 458 | } 459 | mutex_lock(&lower_inode->i_mutex); 460 | /* Used by the VFS to copy into @value(xattr_virt) the value of the extended attribute name for the specified file. */ 461 | size = lower_inode->i_op->getxattr(lower_dentry, ECRYPTFS_XATTR_NAME, 462 | xattr_virt/*dst*/, PAGE_CACHE_SIZE); 463 | if (size < 0) 464 | size = 8; 465 | put_unaligned_be64(i_size_read(ecryptfs_inode)/*src*/, xattr_virt/*dst*/); 466 | rc = lower_inode->i_op->setxattr(lower_dentry/*dst*/, ECRYPTFS_XATTR_NAME/*src*/, 467 | xattr_virt/*src*/, size, 0); 468 | mutex_unlock(&lower_inode->i_mutex); 469 | if (rc) 470 | printk(KERN_ERR "Error whilst attempting to write inode size " 471 | "to lower file xattr; rc = [%d]\n", rc); 472 | kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); 473 | out: 474 | return rc; 475 | } 476 | 477 | int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode) 478 | { 479 | struct ecryptfs_crypt_stat *crypt_stat; 480 | 481 | crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 482 | BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); 483 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) 484 | return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode); 485 | else 486 | return ecryptfs_write_inode_size_to_header(ecryptfs_inode); 487 | } 488 | 489 | /** 490 | * ecryptfs_write_end 491 | * @file: The eCryptfs file object 492 | * @mapping: The eCryptfs object 493 | * @pos: The file position 494 | * @len: The length of the data (unused) 495 | * @copied: The amount of data copied 496 | * @page: The eCryptfs page 497 | * @fsdata: The fsdata (unused) 498 | */ 499 | /* Returns the amount of data copied on success */ 500 | static int ecryptfs_write_end(struct file *file, 501 | struct address_space *mapping, 502 | loff_t pos, unsigned len, unsigned copied, 503 | struct page *page, void *fsdata) 504 | { 505 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; 506 | unsigned from = pos & (PAGE_CACHE_SIZE - 1); 507 | unsigned to = from + copied; 508 | struct inode *ecryptfs_inode = mapping->host; 509 | struct ecryptfs_crypt_stat *crypt_stat = 510 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 511 | int rc; 512 | int need_unlock_page = 1; 513 | 514 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" 515 | "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); 516 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { 517 | /* We do not encrypt the file */ 518 | rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0, 519 | to); 520 | if (!rc) { 521 | /* Successful(rc==0) */ 522 | rc = copied; 523 | fsstack_copy_inode_size(ecryptfs_inode, 524 | ecryptfs_inode_to_lower(ecryptfs_inode));/* Copy from @ecryptfs_inode_to_lower(ecryptfs_inode) to @ecryptfs_inode */ 525 | } 526 | goto out; 527 | } 528 | /* We do encrypt the file */ 529 | /* Fills in zeros if 'to' goes beyond inode size */ 530 | rc = fill_zeros_to_end_of_page(page, to); 531 | if (rc) { 532 | ecryptfs_printk(KERN_WARNING, "Error attempting to fill " 533 | "zeros in page with index = [0x%.16lx]\n", index); 534 | goto out; 535 | } 536 | set_page_dirty(page);/* Dirty a page */ 537 | unlock_page(page); 538 | need_unlock_page = 0; 539 | if (pos + copied > i_size_read(ecryptfs_inode)) { 540 | i_size_write(ecryptfs_inode, pos + copied);/* ecryptfs_inode->i_size = pos + copied */ 541 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " 542 | "[0x%.16llx]\n", 543 | (unsigned long long)i_size_read(ecryptfs_inode)); 544 | balance_dirty_pages_ratelimited(mapping);/* Check the system's dirty state and will initiate writeback if needed */ 545 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); 546 | if (rc) { 547 | printk(KERN_ERR "Error writing inode size to metadata; " 548 | "rc = [%d]\n", rc); 549 | goto out; 550 | } 551 | } 552 | rc = copied; 553 | out: 554 | if (need_unlock_page) 555 | unlock_page(page); 556 | page_cache_release(page); 557 | return rc; 558 | } 559 | 560 | static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block) 561 | { 562 | int rc = 0; 563 | struct inode *inode; 564 | struct inode *lower_inode; 565 | 566 | inode = (struct inode *)mapping->host; 567 | lower_inode = ecryptfs_inode_to_lower(inode); 568 | if (lower_inode->i_mapping->a_ops->bmap) 569 | rc = lower_inode->i_mapping->a_ops->bmap(lower_inode->i_mapping, 570 | block); 571 | return rc; 572 | } 573 | 574 | const struct address_space_operations ecryptfs_aops = { 575 | .writepage = ecryptfs_writepage, 576 | .readpage = ecryptfs_readpage, 577 | .write_begin = ecryptfs_write_begin, 578 | .write_end = ecryptfs_write_end, 579 | .bmap = ecryptfs_bmap, 580 | }; 581 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/read_write.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 2007 International Business Machines Corp. 5 | * Author(s): Michael A. Halcrow 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 | * 02111-1307, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include "ecryptfs_kernel.h" 26 | 27 | /** 28 | * ecryptfs_write_lower 29 | * @ecryptfs_inode: The eCryptfs inode 30 | * @data: Data to write 31 | * @offset: Byte offset in the lower file to which to write the data 32 | * @size: Number of bytes from @data to write at @offset in the lower 33 | * file 34 | * 35 | * Write data to the lower file. 36 | * 37 | * Returns bytes written on success; less than zero on error 38 | */ 39 | int ecryptfs_write_lower(struct inode *ecryptfs_inode/*dst*/, char *data/*src*/, 40 | loff_t offset, size_t size) 41 | { 42 | struct file *lower_file; 43 | mm_segment_t fs_save; 44 | ssize_t rc; 45 | 46 | lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file; 47 | if (!lower_file) 48 | return -EIO; 49 | fs_save = get_fs(); /* Get the current process mode of kernel for memory address check * 50 | * Get the thread information (thread address space) */ 51 | set_fs(get_ds());/* Set the current process mode of kernel KERNEL_DS */ 52 | rc = vfs_write(lower_file/*dst*/, data/*src*/, size, &offset);/* Write from @data to @lower_file */ 53 | set_fs(fs_save);/* Change the process mode of kernel for memory address check */ 54 | mark_inode_dirty_sync(ecryptfs_inode);/* Put the inode on the super block's dirty list */ 55 | return rc; 56 | } 57 | 58 | /** 59 | * ecryptfs_write_lower_page_segment 60 | * @ecryptfs_inode: The eCryptfs inode 61 | * @page_for_lower: The page containing the data to be written to the 62 | * lower file 63 | * @offset_in_page: The offset in the @page_for_lower from which to 64 | * start writing the data 65 | * @size: The amount of data from @page_for_lower to write to the 66 | * lower file 67 | * 68 | * Determines the byte offset in the file for the given page and 69 | * offset within the page, maps the page, and makes the call to write 70 | * the contents of @page_for_lower to the lower inode. 71 | * 72 | * Returns zero on success; non-zero otherwise 73 | */ 74 | int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode/*dst*/, 75 | struct page *page_for_lower/*virt: src*/, 76 | size_t offset_in_page, size_t size) 77 | { 78 | char *virt; 79 | loff_t offset; 80 | int rc; 81 | 82 | offset = ((((loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT) 83 | + offset_in_page); 84 | virt = kmap(page_for_lower);/* Return the virtual address of the specified page corresponding to the kernel space */ 85 | rc = ecryptfs_write_lower(ecryptfs_inode/*dst*/, virt/*src*/, offset, size); 86 | if (rc > 0) 87 | rc = 0; 88 | kunmap(page_for_lower);/* Clear off kmap() */ 89 | return rc; 90 | } 91 | 92 | /** 93 | * ecryptfs_write 94 | * @ecryptfs_inode: The eCryptfs file into which to write 95 | * @data: Virtual address where data to write is located 96 | * @offset: Offset in the eCryptfs file at which to begin writing the 97 | * data from @data 98 | * @size: The number of bytes to write from @data 99 | * 100 | * Write an arbitrary amount of data to an arbitrary location in the 101 | * eCryptfs inode page cache. This is done on a page-by-page, and then 102 | * by an extent-by-extent, basis; individual extents are encrypted and 103 | * written to the lower page cache (via VFS writes). This function 104 | * takes care of all the address translation to locations in the lower 105 | * filesystem; it also handles truncate events, writing out zeros 106 | * where necessary. 107 | * 108 | * Returns zero on success; non-zero otherwise 109 | */ 110 | int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, 111 | size_t size) 112 | { 113 | struct page *ecryptfs_page; 114 | struct ecryptfs_crypt_stat *crypt_stat; 115 | char *ecryptfs_page_virt; 116 | loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode); 117 | loff_t data_offset = 0; 118 | loff_t pos; 119 | int rc = 0; 120 | 121 | crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 122 | /* 123 | * if we are writing beyond current size, then start pos 124 | * at the current size - we'll fill in zeros from there. 125 | */ 126 | if (offset/*Current size*/ > ecryptfs_file_size/*Original size*/) 127 | /* We're growing larger */ 128 | pos = ecryptfs_file_size; 129 | else 130 | /* We're shrinking */ 131 | pos = offset; 132 | while (pos < (offset + size)) { 133 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);/* Top 20 bits is index in page table */ 134 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);/* Lower 12 bits is offset in page */ 135 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); 136 | loff_t total_remaining_bytes = ((offset + size) - pos); 137 | 138 | if (fatal_signal_pending(current)) { 139 | /* the current process has SIGKILL pending (9) signal */ 140 | rc = -EINTR; 141 | break; 142 | } 143 | 144 | if (num_bytes > total_remaining_bytes) 145 | num_bytes = total_remaining_bytes; 146 | if (pos < offset) {/* We're growing larger */ 147 | /* Remaining zeros to write, up to destination offset */ 148 | loff_t total_remaining_zeros = (offset - pos); 149 | 150 | if (num_bytes > total_remaining_zeros) 151 | num_bytes = total_remaining_zeros; 152 | } 153 | ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode, 154 | ecryptfs_page_idx);/* Get one page from cache or lower f/s 155 | * Get locked and up-to-date page (if ok), with increased refcnt. */ 156 | if (IS_ERR(ecryptfs_page)) { 157 | rc = PTR_ERR(ecryptfs_page); 158 | printk(KERN_ERR "%s: Error getting page at " 159 | "index [%ld] from eCryptfs inode " 160 | "mapping; rc = [%d]\n", __func__, 161 | ecryptfs_page_idx, rc); 162 | goto out; 163 | } 164 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page); 165 | 166 | /* 167 | * pos: where we're now writing, offset: where the request was 168 | * If current pos is before request, we are filling zeros 169 | * If we are at or beyond request, we are writing the *data* 170 | * If we're in a fresh page beyond eof, zero it in either case 171 | */ 172 | if (pos < offset || !start_offset_in_page) { 173 | /* We are extending past the previous end of the file. 174 | * Fill in zero values to the end of the page */ 175 | memset(((char *)ecryptfs_page_virt 176 | + start_offset_in_page), 0, 177 | PAGE_CACHE_SIZE - start_offset_in_page); 178 | } 179 | 180 | /* pos >= offset, we are now writing the data request */ 181 | if (pos >= offset) { 182 | memcpy(((char *)ecryptfs_page_virt 183 | + start_offset_in_page), 184 | (data + data_offset), num_bytes); 185 | data_offset += num_bytes; 186 | } 187 | kunmap_atomic(ecryptfs_page_virt); 188 | flush_dcache_page(ecryptfs_page); 189 | SetPageUptodate(ecryptfs_page); 190 | unlock_page(ecryptfs_page); 191 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) 192 | rc = ecryptfs_encrypt_page(ecryptfs_page); 193 | else 194 | rc = ecryptfs_write_lower_page_segment(ecryptfs_inode/*dst*/, 195 | ecryptfs_page/*virt: src*/, 196 | start_offset_in_page, 197 | data_offset);/* Write the contents of @ecryptfs_page(page for lower) to the lower inodes */ 198 | page_cache_release(ecryptfs_page); 199 | if (rc) { 200 | printk(KERN_ERR "%s: Error encrypting " 201 | "page; rc = [%d]\n", __func__, rc); 202 | goto out; 203 | } 204 | pos += num_bytes; 205 | } 206 | if (pos > ecryptfs_file_size) { 207 | i_size_write(ecryptfs_inode/*dst*/, pos/*src*/); 208 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { 209 | int rc2; 210 | 211 | rc2 = ecryptfs_write_inode_size_to_metadata( 212 | ecryptfs_inode);/* Write into header or xattr */ 213 | if (rc2) { 214 | printk(KERN_ERR "Problem with " 215 | "ecryptfs_write_inode_size_to_metadata; " 216 | "rc = [%d]\n", rc2); 217 | if (!rc) 218 | rc = rc2; 219 | goto out; 220 | } 221 | } 222 | } 223 | out: 224 | return rc; 225 | } 226 | 227 | /** 228 | * ecryptfs_read_lower 229 | * @data: The read data is stored here by this function 230 | * @offset: Byte offset in the lower file from which to read the data 231 | * @size: Number of bytes to read from @offset of the lower file and 232 | * store into @data 233 | * @ecryptfs_inode: The eCryptfs inode 234 | * 235 | * Read @size bytes of data at byte offset @offset from the lower 236 | * inode into memory location @data. 237 | * 238 | * Returns bytes(@rc) read on success; 0 on EOF; less than zero on error 239 | */ 240 | int ecryptfs_read_lower(char *data/*dst*/, loff_t offset, size_t size, 241 | struct inode *ecryptfs_inode/*src*/) 242 | { 243 | struct file *lower_file; 244 | mm_segment_t fs_save; 245 | ssize_t rc; 246 | 247 | lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file; 248 | if (!lower_file) 249 | return -EIO; 250 | fs_save = get_fs(); 251 | set_fs(get_ds()); 252 | rc = vfs_read(lower_file/*src*/, data/*dst*/, size, &offset);/* Read @lower_file into @data */ 253 | set_fs(fs_save); 254 | return rc; 255 | } 256 | 257 | /** 258 | * ecryptfs_read_lower_page_segment 259 | * @page_for_ecryptfs: The page into which data for eCryptfs will be 260 | * written 261 | * @page_index: Offset in file for the given page 262 | * @offset_in_page: Offset in @page_for_ecryptfs from which to start 263 | * writing 264 | * @size: The number of bytes to write into @page_for_ecryptfs 265 | * @ecryptfs_inode: The eCryptfs inode 266 | * 267 | * Determines the byte offset in the file for the given page and 268 | * offset within the page, maps the page, and makes the call to read 269 | * the contents of @page_for_ecryptfs from the lower inode. 270 | * 271 | * Returns zero on success; non-zero otherwise 272 | */ 273 | int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs/*dst*/, 274 | pgoff_t page_index, 275 | size_t offset_in_page, size_t size, 276 | struct inode *ecryptfs_inode/*src*/) 277 | { 278 | char *virt; 279 | loff_t offset; 280 | int rc; 281 | 282 | offset = ((((loff_t)page_index) << PAGE_CACHE_SHIFT/*PAGE_SHIFT*/) + offset_in_page); 283 | virt = kmap(page_for_ecryptfs);/* Obtain the virtual page */ 284 | rc = ecryptfs_read_lower(virt/*dst*/, offset, size, ecryptfs_inode/*src*/); 285 | if (rc > 0) 286 | rc = 0; 287 | kunmap(page_for_ecryptfs); 288 | flush_dcache_page(page_for_ecryptfs); 289 | return rc; 290 | } 291 | -------------------------------------------------------------------------------- /Source Code/ecryptfs3_3_8/super.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 1997-2003 Erez Zadok 5 | * Copyright (C) 2001-2003 Stony Brook University 6 | * Copyright (C) 2004-2006 International Business Machines Corp. 7 | * Author(s): Michael A. Halcrow 8 | * Michael C. Thompson 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License as 12 | * published by the Free Software Foundation; either version 2 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, but 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | * General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 23 | * 02111-1307, USA. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "ecryptfs_kernel.h" 36 | 37 | struct kmem_cache *ecryptfs_inode_info_cache; 38 | 39 | /** 40 | * ecryptfs_alloc_inode - allocate an ecryptfs inode 41 | * @sb: Pointer to the ecryptfs super block 42 | * 43 | * Called to bring an inode into existence. 44 | * 45 | * Only handle allocation, setting up structures should be done in 46 | * ecryptfs_read_inode. This is because the kernel, between now and 47 | * then, will 0 out the private data pointer. 48 | * 49 | * Returns a pointer to a newly allocated inode, NULL otherwise 50 | */ 51 | static struct inode *ecryptfs_alloc_inode(struct super_block *sb) 52 | { 53 | struct ecryptfs_inode_info *inode_info; 54 | struct inode *inode = NULL; 55 | 56 | inode_info = kmem_cache_alloc(ecryptfs_inode_info_cache, GFP_KERNEL); 57 | if (unlikely(!inode_info)) 58 | goto out; 59 | ecryptfs_init_crypt_stat(&inode_info->crypt_stat);/* Initialize the crypt_stat structure */ 60 | mutex_init(&inode_info->lower_file_mutex); 61 | atomic_set(&inode_info->lower_file_count, 0);/* lower_file_count->counter=0 */ 62 | inode_info->lower_file = NULL; 63 | inode = &inode_info->vfs_inode; 64 | out: 65 | return inode; 66 | } 67 | 68 | static void ecryptfs_i_callback(struct rcu_head *head) 69 | { 70 | struct inode *inode = container_of(head, struct inode, i_rcu); 71 | struct ecryptfs_inode_info *inode_info; 72 | inode_info = ecryptfs_inode_to_private(inode); 73 | 74 | kmem_cache_free(ecryptfs_inode_info_cache, inode_info); 75 | } 76 | 77 | /** 78 | * ecryptfs_destroy_inode 79 | * @inode: The ecryptfs inode 80 | * 81 | * This is used during the final destruction of the inode. All 82 | * allocation of memory related to the inode, including allocated 83 | * memory in the crypt_stat struct, will be released here. 84 | * There should be no chance that this deallocation will be missed. 85 | */ 86 | static void ecryptfs_destroy_inode(struct inode *inode) 87 | { 88 | struct ecryptfs_inode_info *inode_info; 89 | 90 | inode_info = ecryptfs_inode_to_private(inode); 91 | BUG_ON(inode_info->lower_file); 92 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); 93 | call_rcu(&inode->i_rcu, ecryptfs_i_callback);/* Queue a preemptible -RCU callback for invocation after a grace period */ 94 | } 95 | 96 | /** 97 | * ecryptfs_statfs 98 | * @sb: The ecryptfs super block 99 | * @buf: The struct kstatfs to fill in with stats 100 | * 101 | * Get the filesystem statistics. Currently, we let this pass right through 102 | * to the lower filesystem and take no action ourselves. 103 | */ 104 | static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) 105 | { 106 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 107 | int rc; 108 | 109 | if (!lower_dentry->d_sb->s_op->statfs) 110 | return -ENOSYS; 111 | 112 | rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf); 113 | if (rc) 114 | return rc; 115 | 116 | buf->f_type = ECRYPTFS_SUPER_MAGIC; 117 | rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen, 118 | &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat); 119 | 120 | return rc; 121 | } 122 | 123 | /** 124 | * ecryptfs_evict_inode 125 | * @inode - The ecryptfs inode 126 | * 127 | * Called by iput() when the inode reference count reached zero 128 | * and the inode is not hashed anywhere. Used to clear anything 129 | * that needs to be, before the inode is completely destroyed and put 130 | * on the inode free list. We use this to drop out reference to the 131 | * lower inode. 132 | */ 133 | static void ecryptfs_evict_inode(struct inode *inode) 134 | { 135 | truncate_inode_pages(&inode->i_data, 0);/* truncate *all* the pages from an offset(offset==0) */ 136 | end_writeback(inode); 137 | iput(ecryptfs_inode_to_lower(inode));/* put an inode */ 138 | } 139 | 140 | /** 141 | * ecryptfs_show_options 142 | * 143 | * Prints the mount options for a given superblock. 144 | * Returns zero; does not fail. 145 | */ 146 | static int ecryptfs_show_options(struct seq_file *m, struct dentry *root) 147 | { 148 | struct super_block *sb = root->d_sb; 149 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = 150 | &ecryptfs_superblock_to_private(sb)->mount_crypt_stat; 151 | struct ecryptfs_global_auth_tok *walker; 152 | 153 | mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); 154 | list_for_each_entry(walker, 155 | &mount_crypt_stat->global_auth_tok_list, 156 | mount_crypt_stat_list) { 157 | if (walker->flags & ECRYPTFS_AUTH_TOK_FNEK) 158 | seq_printf(m, ",ecryptfs_fnek_sig=%s", walker->sig); 159 | else 160 | seq_printf(m, ",ecryptfs_sig=%s", walker->sig); 161 | } 162 | mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); 163 | 164 | seq_printf(m, ",ecryptfs_cipher=%s", 165 | mount_crypt_stat->global_default_cipher_name); 166 | 167 | if (mount_crypt_stat->global_default_cipher_key_size) 168 | seq_printf(m, ",ecryptfs_key_bytes=%zd", 169 | mount_crypt_stat->global_default_cipher_key_size); 170 | if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) 171 | seq_printf(m, ",ecryptfs_passthrough"); 172 | if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) 173 | seq_printf(m, ",ecryptfs_xattr_metadata"); 174 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) 175 | seq_printf(m, ",ecryptfs_encrypted_view"); 176 | if (mount_crypt_stat->flags & ECRYPTFS_UNLINK_SIGS) 177 | seq_printf(m, ",ecryptfs_unlink_sigs"); 178 | if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY) 179 | seq_printf(m, ",ecryptfs_mount_auth_tok_only"); 180 | 181 | return 0; 182 | } 183 | 184 | const struct super_operations ecryptfs_sops = { 185 | .alloc_inode = ecryptfs_alloc_inode, 186 | .destroy_inode = ecryptfs_destroy_inode, 187 | .drop_inode = generic_drop_inode, 188 | .statfs = ecryptfs_statfs, 189 | .remount_fs = NULL, 190 | .evict_inode = ecryptfs_evict_inode, 191 | .show_options = ecryptfs_show_options 192 | }; 193 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for the Linux 2.6 eCryptfs 3 | # 4 | 5 | obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o 6 | 7 | //ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o debug.o 8 | ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o debug.o hmac.o -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/debug.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * Functions only useful for debugging. 4 | * 5 | * Copyright (C) 2006 International Business Machines Corp. 6 | * Author(s): Michael A. Halcrow 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License as 10 | * published by the Free Software Foundation; either version 2 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, but 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 21 | * 02111-1307, USA. 22 | */ 23 | 24 | #include "ecryptfs_kernel.h" 25 | 26 | /** 27 | * ecryptfs_dump_auth_tok - debug function to print auth toks 28 | * 29 | * This function will print the contents of an ecryptfs authentication 30 | * token. 31 | */ 32 | void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok) 33 | { 34 | char salt[ECRYPTFS_SALT_SIZE * 2 + 1]; 35 | char sig[ECRYPTFS_SIG_SIZE_HEX + 1]; 36 | 37 | ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n", 38 | auth_tok); 39 | if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) { 40 | ecryptfs_printk(KERN_DEBUG, " * private key type\n"); 41 | } else { 42 | ecryptfs_printk(KERN_DEBUG, " * passphrase type\n"); 43 | ecryptfs_to_hex(salt, auth_tok->token.password.salt, 44 | ECRYPTFS_SALT_SIZE); 45 | salt[ECRYPTFS_SALT_SIZE * 2] = '\0'; 46 | ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt); 47 | if (auth_tok->token.password.flags & 48 | ECRYPTFS_PERSISTENT_PASSWORD) { 49 | ecryptfs_printk(KERN_DEBUG, " * persistent\n"); 50 | } 51 | memcpy(sig, auth_tok->token.password.signature, 52 | ECRYPTFS_SIG_SIZE_HEX); 53 | sig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; 54 | ecryptfs_printk(KERN_DEBUG, " * signature = [%s]\n", sig); 55 | } 56 | ecryptfs_printk(KERN_DEBUG, " * session_key.flags = [0x%x]\n", 57 | auth_tok->session_key.flags); 58 | if (auth_tok->session_key.flags 59 | & ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT) 60 | ecryptfs_printk(KERN_DEBUG, 61 | " * Userspace decrypt request set\n"); 62 | if (auth_tok->session_key.flags 63 | & ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT) 64 | ecryptfs_printk(KERN_DEBUG, 65 | " * Userspace encrypt request set\n"); 66 | if (auth_tok->session_key.flags & ECRYPTFS_CONTAINS_DECRYPTED_KEY) { 67 | ecryptfs_printk(KERN_DEBUG, " * Contains decrypted key\n"); 68 | ecryptfs_printk(KERN_DEBUG, 69 | " * session_key.decrypted_key_size = [0x%x]\n", 70 | auth_tok->session_key.decrypted_key_size); 71 | ecryptfs_printk(KERN_DEBUG, " * Decrypted session key " 72 | "dump:\n"); 73 | if (ecryptfs_verbosity > 0) 74 | ecryptfs_dump_hex(auth_tok->session_key.decrypted_key, 75 | ECRYPTFS_DEFAULT_KEY_BYTES); 76 | } 77 | if (auth_tok->session_key.flags & ECRYPTFS_CONTAINS_ENCRYPTED_KEY) { 78 | ecryptfs_printk(KERN_DEBUG, " * Contains encrypted key\n"); 79 | ecryptfs_printk(KERN_DEBUG, 80 | " * session_key.encrypted_key_size = [0x%x]\n", 81 | auth_tok->session_key.encrypted_key_size); 82 | ecryptfs_printk(KERN_DEBUG, " * Encrypted session key " 83 | "dump:\n"); 84 | if (ecryptfs_verbosity > 0) 85 | ecryptfs_dump_hex(auth_tok->session_key.encrypted_key, 86 | auth_tok->session_key. 87 | encrypted_key_size); 88 | } 89 | } 90 | 91 | /** 92 | * ecryptfs_dump_hex - debug hex printer 93 | * @data: string of bytes to be printed 94 | * @bytes: number of bytes to print 95 | * 96 | * Dump hexadecimal representation of char array 97 | */ 98 | void ecryptfs_dump_hex(char *data, int bytes) 99 | { 100 | int i = 0; 101 | int add_newline = 1; 102 | 103 | if (ecryptfs_verbosity < 1) 104 | return; 105 | if (bytes != 0) { 106 | printk(KERN_DEBUG "0x%.2x.", (unsigned char)data[i]); 107 | i++; 108 | } 109 | while (i < bytes) { 110 | printk("0x%.2x.", (unsigned char)data[i]); 111 | i++; 112 | if (i % 16 == 0) { 113 | printk("\n"); 114 | add_newline = 0; 115 | } else 116 | add_newline = 1; 117 | } 118 | if (add_newline) 119 | printk("\n"); 120 | } 121 | 122 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/dentry.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 1997-2003 Erez Zadok 5 | * Copyright (C) 2001-2003 Stony Brook University 6 | * Copyright (C) 2004-2006 International Business Machines Corp. 7 | * Author(s): Michael A. Halcrow 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License as 11 | * published by the Free Software Foundation; either version 2 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, but 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 22 | * 02111-1307, USA. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "ecryptfs_kernel.h" 30 | 31 | /** 32 | * ecryptfs_d_revalidate - revalidate an ecryptfs dentry 33 | * @dentry: The ecryptfs dentry 34 | * @nd: The associated nameidata 35 | * 36 | * Called when the VFS needs to revalidate a dentry. This 37 | * is called whenever a name lookup finds a dentry in the 38 | * dcache. Most filesystems leave this as NULL, because all their 39 | * dentries in the dcache are valid. 40 | * 41 | * Returns 1 if valid, 0 otherwise. 42 | * 43 | */ 44 | static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) 45 | { 46 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 47 | struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); 48 | struct dentry *dentry_save; 49 | struct vfsmount *vfsmount_save; 50 | int rc = 1; 51 | 52 | if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) 53 | goto out; 54 | dentry_save = nd->dentry; 55 | vfsmount_save = nd->mnt; 56 | nd->dentry = lower_dentry; 57 | nd->mnt = lower_mnt; 58 | rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); 59 | nd->dentry = dentry_save; 60 | nd->mnt = vfsmount_save; 61 | if (dentry->d_inode) { 62 | struct inode *lower_inode = 63 | ecryptfs_inode_to_lower(dentry->d_inode); 64 | 65 | fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL); 66 | } 67 | out: 68 | return rc; 69 | } 70 | 71 | struct kmem_cache *ecryptfs_dentry_info_cache; 72 | 73 | /** 74 | * ecryptfs_d_release 75 | * @dentry: The ecryptfs dentry 76 | * 77 | * Called when a dentry is really deallocated. 78 | */ 79 | static void ecryptfs_d_release(struct dentry *dentry) 80 | { 81 | if (ecryptfs_dentry_to_private(dentry)) { 82 | if (ecryptfs_dentry_to_lower(dentry)) { 83 | mntput(ecryptfs_dentry_to_lower_mnt(dentry)); 84 | dput(ecryptfs_dentry_to_lower(dentry)); 85 | } 86 | kmem_cache_free(ecryptfs_dentry_info_cache, 87 | ecryptfs_dentry_to_private(dentry)); 88 | } 89 | return; 90 | } 91 | 92 | struct dentry_operations ecryptfs_dops = { 93 | .d_revalidate = ecryptfs_d_revalidate, 94 | .d_release = ecryptfs_d_release, 95 | }; 96 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/file.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 1997-2004 Erez Zadok 5 | * Copyright (C) 2001-2004 Stony Brook University 6 | * Copyright (C) 2004-2007 International Business Machines Corp. 7 | * Author(s): Michael A. Halcrow 8 | * Michael C. Thompson 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License as 12 | * published by the Free Software Foundation; either version 2 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, but 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | * General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 23 | * 02111-1307, USA. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "ecryptfs_kernel.h" 34 | 35 | /** 36 | * ecryptfs_read_update_atime 37 | * 38 | * generic_file_read updates the atime of upper layer inode. But, it 39 | * doesn't give us a chance to update the atime of the lower layer 40 | * inode. This function is a wrapper to generic_file_read. It 41 | * updates the atime of the lower level inode if generic_file_read 42 | * returns without any errors. This is to be used only for file reads. 43 | * The function to be used for directory reads is ecryptfs_read. 44 | */ 45 | static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb, 46 | const struct iovec *iov, 47 | unsigned long nr_segs, loff_t pos) 48 | { 49 | int rc; 50 | struct dentry *lower_dentry; 51 | struct vfsmount *lower_vfsmount; 52 | struct file *file = iocb->ki_filp; 53 | 54 | rc = generic_file_aio_read(iocb, iov, nr_segs, pos); 55 | /* 56 | * Even though this is a async interface, we need to wait 57 | * for IO to finish to update atime 58 | */ 59 | if (-EIOCBQUEUED == rc) 60 | rc = wait_on_sync_kiocb(iocb); 61 | if (rc >= 0) { 62 | lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry); 63 | lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry); 64 | touch_atime(lower_vfsmount, lower_dentry); 65 | } 66 | return rc; 67 | } 68 | 69 | struct ecryptfs_getdents_callback { 70 | void *dirent; 71 | struct dentry *dentry; 72 | filldir_t filldir; 73 | int err; 74 | int filldir_called; 75 | int entries_written; 76 | }; 77 | 78 | /* Inspired by generic filldir in fs/readir.c */ 79 | static int 80 | ecryptfs_filldir(void *dirent, const char *name, int namelen, loff_t offset, 81 | u64 ino, unsigned int d_type) 82 | { 83 | struct ecryptfs_crypt_stat *crypt_stat; 84 | struct ecryptfs_getdents_callback *buf = 85 | (struct ecryptfs_getdents_callback *)dirent; 86 | int rc; 87 | int decoded_length; 88 | char *decoded_name; 89 | 90 | crypt_stat = ecryptfs_dentry_to_private(buf->dentry)->crypt_stat; 91 | buf->filldir_called++; 92 | decoded_length = ecryptfs_decode_filename(crypt_stat, name, namelen, 93 | &decoded_name); 94 | if (decoded_length < 0) { 95 | rc = decoded_length; 96 | goto out; 97 | } 98 | rc = buf->filldir(buf->dirent, decoded_name, decoded_length, offset, 99 | ino, d_type); 100 | kfree(decoded_name); 101 | if (rc >= 0) 102 | buf->entries_written++; 103 | out: 104 | return rc; 105 | } 106 | 107 | /** 108 | * ecryptfs_readdir 109 | * @file: The ecryptfs file struct 110 | * @dirent: Directory entry 111 | * @filldir: The filldir callback function 112 | */ 113 | static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) 114 | { 115 | int rc; 116 | struct file *lower_file; 117 | struct inode *inode; 118 | struct ecryptfs_getdents_callback buf; 119 | 120 | lower_file = ecryptfs_file_to_lower(file); 121 | lower_file->f_pos = file->f_pos; 122 | inode = file->f_path.dentry->d_inode; 123 | memset(&buf, 0, sizeof(buf)); 124 | buf.dirent = dirent; 125 | buf.dentry = file->f_path.dentry; 126 | buf.filldir = filldir; 127 | retry: 128 | buf.filldir_called = 0; 129 | buf.entries_written = 0; 130 | buf.err = 0; 131 | rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf); 132 | if (buf.err) 133 | rc = buf.err; 134 | if (buf.filldir_called && !buf.entries_written) 135 | goto retry; 136 | file->f_pos = lower_file->f_pos; 137 | if (rc >= 0) 138 | fsstack_copy_attr_atime(inode, lower_file->f_path.dentry->d_inode); 139 | return rc; 140 | } 141 | 142 | struct kmem_cache *ecryptfs_file_info_cache; 143 | 144 | /** 145 | * ecryptfs_open 146 | * @inode: inode speciying file to open 147 | * @file: Structure to return filled in 148 | * 149 | * Opens the file specified by inode. 150 | * 151 | * Returns zero on success; non-zero otherwise 152 | */ 153 | static int ecryptfs_open(struct inode *inode, struct file *file) 154 | { 155 | int rc = 0; 156 | struct ecryptfs_crypt_stat *crypt_stat = NULL; 157 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 158 | struct dentry *ecryptfs_dentry = file->f_path.dentry; 159 | /* Private value of ecryptfs_dentry allocated in 160 | * ecryptfs_lookup() */ 161 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 162 | struct ecryptfs_file_info *file_info; 163 | 164 | mount_crypt_stat = &ecryptfs_superblock_to_private( 165 | ecryptfs_dentry->d_sb)->mount_crypt_stat; 166 | if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) 167 | && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) 168 | || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) 169 | || (file->f_flags & O_APPEND))) { 170 | printk(KERN_WARNING "Mount has encrypted view enabled; " 171 | "files may only be read\n"); 172 | rc = -EPERM; 173 | goto out; 174 | } 175 | /* Released in ecryptfs_release or end of function if failure */ 176 | file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); 177 | ecryptfs_set_file_private(file, file_info); 178 | if (!file_info) { 179 | ecryptfs_printk(KERN_ERR, 180 | "Error attempting to allocate memory\n"); 181 | rc = -ENOMEM; 182 | goto out; 183 | } 184 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 185 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; 186 | mutex_lock(&crypt_stat->cs_mutex); 187 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) { 188 | ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); 189 | /* Policy code enabled in future release */ 190 | crypt_stat->flags |= (ECRYPTFS_POLICY_APPLIED 191 | | ECRYPTFS_ENCRYPTED); 192 | } 193 | mutex_unlock(&crypt_stat->cs_mutex); 194 | ecryptfs_set_file_lower( 195 | file, ecryptfs_inode_to_private(inode)->lower_file); 196 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { 197 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); 198 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 199 | rc = 0; 200 | goto out; 201 | } 202 | mutex_lock(&crypt_stat->cs_mutex); 203 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) 204 | || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { 205 | rc = ecryptfs_read_metadata(ecryptfs_dentry); 206 | if (rc) { 207 | ecryptfs_printk(KERN_DEBUG, 208 | "Valid headers not found\n"); 209 | if (!(mount_crypt_stat->flags 210 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { 211 | rc = -EIO; 212 | printk(KERN_WARNING "Attempt to read file that " 213 | "is not in a valid eCryptfs format, " 214 | "and plaintext passthrough mode is not " 215 | "enabled; returning -EIO\n"); 216 | mutex_unlock(&crypt_stat->cs_mutex); 217 | goto out_free; 218 | } 219 | rc = 0; 220 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 221 | mutex_unlock(&crypt_stat->cs_mutex); 222 | goto out; 223 | } 224 | } 225 | /*************************HMAC PATCH********************/ 226 | /* 227 | * TODO: How should HMAC be handled with passthrough? 228 | * Currently HMAC is not included in passthrough, but it might 229 | * be a nice feature in the future. 230 | */ 231 | if(crypt_stat->flags & ECRYPTFS_ENABLE_HMAC) { 232 | rc = ecryptfs_verify_root_hmac(crypt_stat, inode); 233 | if (rc) { 234 | rc = -EIO; 235 | printk(KERN_WARNING "Unable to initialize " 236 | "hmac data structure; returning -EIO\n"); 237 | mutex_unlock(&crypt_stat->cs_mutex); 238 | goto out_free; 239 | } 240 | } 241 | /*************************HMAC PATCH********************/ 242 | mutex_unlock(&crypt_stat->cs_mutex); 243 | ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = [0x%.16x] " 244 | "size: [0x%.16x]\n", inode, inode->i_ino, 245 | i_size_read(inode)); 246 | goto out; 247 | out_free: 248 | kmem_cache_free(ecryptfs_file_info_cache, 249 | ecryptfs_file_to_private(file)); 250 | out: 251 | return rc; 252 | } 253 | 254 | static int ecryptfs_flush(struct file *file, fl_owner_t td) 255 | { 256 | int rc = 0; 257 | struct file *lower_file = NULL; 258 | 259 | lower_file = ecryptfs_file_to_lower(file); 260 | if (lower_file->f_op && lower_file->f_op->flush) 261 | rc = lower_file->f_op->flush(lower_file, td); 262 | return rc; 263 | } 264 | 265 | static int ecryptfs_release(struct inode *inode, struct file *file) 266 | { 267 | /*************************HMAC PATCH********************/ 268 | struct ecryptfs_crypt_stat *crypt_stat; 269 | int rc = 0; 270 | 271 | crypt_stat = (&ecryptfs_inode_to_private(inode)->crypt_stat); 272 | if (crypt_stat->flags & ECRYPTFS_ENABLE_HMAC) { 273 | rc = ecryptfs_hmac_close(inode); 274 | if (rc) { 275 | printk(KERN_ERR "Error writing hmac extents to file\n"); 276 | goto out; 277 | } 278 | } 279 | /*************************HMAC PATCH********************/ 280 | kmem_cache_free(ecryptfs_file_info_cache, 281 | ecryptfs_file_to_private(file)); 282 | // return 0; 283 | out: /* HMAC PATCH */ 284 | return rc; /* HMAC PATCH */ 285 | } 286 | 287 | static int 288 | ecryptfs_fsync(struct file *file, struct dentry *dentry, int datasync) 289 | { 290 | struct file *lower_file = ecryptfs_file_to_lower(file); 291 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 292 | struct inode *lower_inode = lower_dentry->d_inode; 293 | int rc = -EINVAL; 294 | 295 | if (lower_inode->i_fop->fsync) { 296 | mutex_lock(&lower_inode->i_mutex); 297 | rc = lower_inode->i_fop->fsync(lower_file, lower_dentry, 298 | datasync); 299 | mutex_unlock(&lower_inode->i_mutex); 300 | } 301 | return rc; 302 | } 303 | 304 | static int ecryptfs_fasync(int fd, struct file *file, int flag) 305 | { 306 | int rc = 0; 307 | struct file *lower_file = NULL; 308 | 309 | lower_file = ecryptfs_file_to_lower(file); 310 | if (lower_file->f_op && lower_file->f_op->fasync) 311 | rc = lower_file->f_op->fasync(fd, lower_file, flag); 312 | return rc; 313 | } 314 | 315 | static int ecryptfs_ioctl(struct inode *inode, struct file *file, 316 | unsigned int cmd, unsigned long arg); 317 | 318 | const struct file_operations ecryptfs_dir_fops = { 319 | .readdir = ecryptfs_readdir, 320 | .ioctl = ecryptfs_ioctl, 321 | .mmap = generic_file_mmap, 322 | .open = ecryptfs_open, 323 | .flush = ecryptfs_flush, 324 | .release = ecryptfs_release, 325 | .fsync = ecryptfs_fsync, 326 | .fasync = ecryptfs_fasync, 327 | .splice_read = generic_file_splice_read, 328 | }; 329 | 330 | const struct file_operations ecryptfs_main_fops = { 331 | .llseek = generic_file_llseek, 332 | .read = do_sync_read, 333 | .aio_read = ecryptfs_read_update_atime, 334 | .write = do_sync_write, 335 | .aio_write = generic_file_aio_write, 336 | .readdir = ecryptfs_readdir, 337 | .ioctl = ecryptfs_ioctl, 338 | .mmap = generic_file_mmap, 339 | .open = ecryptfs_open, 340 | .flush = ecryptfs_flush, 341 | .release = ecryptfs_release, 342 | .fsync = ecryptfs_fsync, 343 | .fasync = ecryptfs_fasync, 344 | .splice_read = generic_file_splice_read, 345 | }; 346 | 347 | static int 348 | ecryptfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 349 | unsigned long arg) 350 | { 351 | int rc = 0; 352 | struct file *lower_file = NULL; 353 | 354 | if (ecryptfs_file_to_private(file)) 355 | lower_file = ecryptfs_file_to_lower(file); 356 | if (lower_file && lower_file->f_op && lower_file->f_op->ioctl) 357 | rc = lower_file->f_op->ioctl(ecryptfs_inode_to_lower(inode), 358 | lower_file, cmd, arg); 359 | else 360 | rc = -ENOTTY; 361 | return rc; 362 | } 363 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/hmac.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 2007 Trevor Highland 5 | * Author(s): Trevor S. Highland 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 | * 02111-1307, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "ecryptfs_kernel.h" 34 | 35 | struct kmem_cache *ecryptfs_extent_cache; 36 | 37 | #define HEADER_EXTENTS ( (crypt_stat->num_header_bytes_at_front) \ 38 | / (crypt_stat->extent_size)) 39 | #define FL_HMAC(extent) (((extent) & 0x1fc000) >> 14)/*(1111111) 111111100000000000000>>14*/ 40 | #define SL_HMAC(extent) (((extent) & 0x3f80) >> 7)/*(1111111) 11111110000000>>7*/ 41 | #define TL_HMAC(extent) ((extent) & 0x7f)/*1111111*/ 42 | #define FL_OFFSET (HMAC_PER_EXTENT * (HMAC_PER_EXTENT + 1) + 1)/*First level(16513): 128*(128+1)+1)*/ 43 | #define SL_OFFSET (HMAC_PER_EXTENT + 1)/*Second level(129): 128+1*/ 44 | int ecryptfs_init_hmac(struct ecryptfs_crypt_stat *crypt_stat) 45 | { 46 | int rc = 0; 47 | 48 | mutex_init(&crypt_stat->cs_hmac_tfm_mutex); 49 | mutex_init(&crypt_stat->cs_hmac_mutex); 50 | crypt_stat->root = kzalloc(sizeof(struct ecryptfs_hmac_table), 51 | GFP_KERNEL); 52 | if (!(crypt_stat->root)) { 53 | rc = -ENOMEM; 54 | goto out; 55 | } 56 | crypt_stat->root->extent = 57 | kmem_cache_zalloc(ecryptfs_extent_cache, GFP_KERNEL);/*4096*/ 58 | if (!(crypt_stat->root)) { 59 | rc = -ENOMEM; 60 | goto out; 61 | } 62 | crypt_stat->hmac_bytes = ECRYPTFS_HMAC_BYTES/* 32 */; 63 | if (strlen(ECRYPTFS_DEFAULT_HMAC) <= ECRYPTFS_MAX_CIPHER_NAME_SIZE) { 64 | strcpy(crypt_stat->hmac, ECRYPTFS_DEFAULT_HMAC); 65 | } 66 | out: 67 | return rc; 68 | } 69 | 70 | static int ecryptfs_read_hmac_root(struct inode *ecryptfs_inode/*src*/, 71 | struct ecryptfs_crypt_stat *crypt_stat/*dst*/) 72 | { 73 | int rc; 74 | char *extent; 75 | 76 | extent = kmalloc(crypt_stat->extent_size, GFP_KERNEL); 77 | rc = ecryptfs_read_lower(extent, 0, crypt_stat->extent_size, 78 | ecryptfs_inode); 79 | if (rc) 80 | goto out; 81 | memcpy(crypt_stat->root->extent, 82 | &extent[crypt_stat->root_hmac_header_offset], 83 | 2 * crypt_stat->hmac_bytes/*32*/); 84 | 85 | kfree(extent); 86 | 87 | out: 88 | return rc; 89 | } 90 | 91 | static int ecryptfs_write_hmac_root_to_header(struct inode *ecryptfs_inode, 92 | struct ecryptfs_crypt_stat *crypt_stat) 93 | { 94 | int rc; 95 | loff_t offset = crypt_stat->root_hmac_header_offset; 96 | struct ecryptfs_hmac_table *root; 97 | 98 | root = crypt_stat->root; 99 | if (crypt_stat->flags & ECRYPTFS_ROOT_HMAC) 100 | offset += crypt_stat->hmac_bytes; 101 | rc = ecryptfs_write_lower(ecryptfs_inode, root->extent, offset, 102 | crypt_stat->hmac_bytes/*32*/); 103 | crypt_stat->flags ^= ECRYPTFS_ROOT_HMAC; 104 | return rc; 105 | } 106 | 107 | /* 108 | * For performance reasons, hmac extents reside in memory until the file is 109 | * closed. This functions flushes each of the hmac extents to disk. 110 | */ 111 | int ecryptfs_hmac_close(struct inode *ecryptfs_inode) 112 | { 113 | int rc = 0; 114 | size_t i; 115 | size_t j; 116 | loff_t offset; 117 | struct ecryptfs_crypt_stat *crypt_stat; 118 | struct ecryptfs_hmac_table *root; 119 | 120 | crypt_stat = (&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); 121 | 122 | mutex_lock(&crypt_stat->cs_hmac_mutex); 123 | root = crypt_stat->root; 124 | if(!root) { 125 | rc = -EIO; 126 | goto out; 127 | } 128 | for (i = 0; i < HMAC_PER_EXTENT; i++) { 129 | if (!root->children[i]) 130 | break; 131 | if (!(root->children[i]->flags & ECRYPTFS_HMAC_EXTENT_DIRTY)) { 132 | continue; 133 | } 134 | for (j = 0; j < HMAC_PER_EXTENT; j++) { 135 | if (!root->children[i]->children[j]) 136 | break; 137 | if (!(root->children[i]->children[j]->flags 138 | & ECRYPTFS_HMAC_EXTENT_DIRTY)) { 139 | continue; 140 | } 141 | offset = root->children[i]->children[j]->lwr_extent 142 | * crypt_stat->extent_size; 143 | rc = ecryptfs_write_lower(ecryptfs_inode/*dst*/, 144 | root->children[i]->children[j]->extent/*data*/, 145 | offset, crypt_stat->extent_size); 146 | if (rc) { 147 | ecryptfs_printk(KERN_ERR, "Error, writing hmac " 148 | "extent. returning EIO\n"); 149 | rc = -EIO; 150 | goto out; 151 | } 152 | } 153 | offset = root->children[i]->lwr_extent 154 | * crypt_stat->extent_size; 155 | rc = ecryptfs_write_lower(ecryptfs_inode, 156 | root->children[i]->extent, 157 | offset, crypt_stat->extent_size); 158 | if (rc) { 159 | ecryptfs_printk(KERN_ERR, "Error, writing hmac extent. " 160 | "returning EIO\n"); 161 | rc = -EIO; 162 | goto out; 163 | } 164 | } 165 | out: 166 | mutex_unlock(&crypt_stat->cs_hmac_mutex); 167 | return rc; 168 | } 169 | 170 | static int ecryptfs_calculate_root_hmac(struct ecryptfs_crypt_stat *crypt_stat, 171 | char *dst) 172 | { 173 | struct hash_desc desc = { 174 | .tfm = crypt_stat->hmac_tfm, 175 | .flags = CRYPTO_TFM_REQ_MAY_SLEEP, 176 | }; 177 | struct ecryptfs_hmac_table *root; 178 | struct scatterlist sg; 179 | size_t i; 180 | int rc; 181 | 182 | mutex_lock(&crypt_stat->cs_hmac_tfm_mutex); 183 | root = crypt_stat->root; 184 | if(!root) { 185 | rc = -EIO; 186 | goto out; 187 | } 188 | if (!desc.tfm) { 189 | desc.tfm = crypto_alloc_hash(crypt_stat->hmac, 0, 190 | CRYPTO_ALG_ASYNC); 191 | if (IS_ERR(desc.tfm)) { 192 | rc = PTR_ERR(desc.tfm); 193 | ecryptfs_printk(KERN_ERR, "Error attempting to " 194 | "allocate crypto context; rc = [%d]\n", 195 | rc); 196 | goto out; 197 | } 198 | rc = crypto_hash_setkey(desc.tfm, crypt_stat->key, 199 | crypt_stat->key_size); 200 | if (rc) { 201 | ecryptfs_printk(KERN_ERR, "Error setting hmac key [%d]", 202 | rc); 203 | goto out; 204 | } 205 | crypt_stat->hmac_tfm = desc.tfm; 206 | } 207 | 208 | crypto_hash_init(&desc); 209 | for (i=0; i < HMAC_PER_EXTENT/*128*/; i++) { 210 | if (!root->children[i]) 211 | break; 212 | sg_init_one(&sg, root->children[i]->extent, 213 | crypt_stat->extent_size); 214 | crypto_hash_update(&desc, &sg, crypt_stat->extent_size); 215 | } 216 | crypto_hash_final(&desc, dst); 217 | out: 218 | mutex_unlock(&crypt_stat->cs_hmac_tfm_mutex); 219 | return rc; 220 | } 221 | 222 | static int ecryptfs_init_hmac_node(struct ecryptfs_hmac_table **hmac_node, 223 | size_t lwr_extent) 224 | { 225 | int rc = 0; 226 | *hmac_node = kzalloc(sizeof(struct ecryptfs_hmac_table),GFP_KERNEL); 227 | if (!(*hmac_node)) { 228 | rc = -ENOMEM; 229 | goto out; 230 | } 231 | (*hmac_node)->lwr_extent = lwr_extent; 232 | (*hmac_node)->extent = 233 | kmem_cache_zalloc(ecryptfs_extent_cache, GFP_KERNEL);/*4096*/ 234 | if (!((*hmac_node)->extent)) { 235 | rc = -ENOMEM; 236 | goto out; 237 | } 238 | out: 239 | return rc; 240 | } 241 | 242 | int ecryptfs_verify_root_hmac(struct ecryptfs_crypt_stat *crypt_stat, 243 | struct inode *ecryptfs_inode) 244 | { 245 | int rc = 0; 246 | size_t i; 247 | size_t lwr_extent; 248 | u64 file_size; 249 | struct ecryptfs_hmac_table *root; 250 | char *root_hmac; 251 | 252 | 253 | root_hmac = kzalloc(ECRYPTFS_HMAC_BYTES/*32*/, GFP_KERNEL); 254 | if (!root_hmac) { 255 | ecryptfs_printk(KERN_ERR, "Error allocating root_hmac\n"); 256 | return -ENOMEM; 257 | } 258 | 259 | mutex_lock(&crypt_stat->cs_hmac_mutex); 260 | root = crypt_stat->root; 261 | if (!root) { 262 | rc = -EIO; 263 | goto out; 264 | } 265 | ecryptfs_read_hmac_root(ecryptfs_inode/*src*/, crypt_stat/*dst*/); 266 | 267 | /* 268 | * Allocate first level HMAC nodes that have not been 269 | * prviously initialized 270 | */ 271 | file_size = (u64)i_size_read(ecryptfs_inode); 272 | for (i=0; ichildren[i]) 274 | continue; 275 | if (file_size <= crypt_stat->extent_size * HMAC_PER_EXTENT 276 | * HMAC_PER_EXTENT * i) 277 | break; 278 | lwr_extent = HEADER_EXTENTS + (i * FL_OFFSET); 279 | rc = ecryptfs_init_hmac_node(&(root->children[i]), lwr_extent); 280 | if (rc) 281 | goto out; 282 | rc = ecryptfs_read_lower(root->children[i]->extent, 283 | lwr_extent * crypt_stat->extent_size, 284 | crypt_stat->extent_size, 285 | ecryptfs_inode); 286 | if (rc) 287 | goto out; 288 | } 289 | ecryptfs_calculate_root_hmac(crypt_stat, root_hmac/*32*/); 290 | if (!memcmp(root_hmac, crypt_stat->root->extent, ECRYPTFS_HMAC_BYTES)) { 291 | crypt_stat->flags |= ECRYPTFS_ROOT_HMAC; 292 | goto out; 293 | } 294 | if (!memcmp(root_hmac, crypt_stat->root->extent + ECRYPTFS_HMAC_BYTES, 295 | ECRYPTFS_HMAC_BYTES)) { 296 | crypt_stat->flags &= ~ECRYPTFS_ROOT_HMAC; 297 | goto out; 298 | } 299 | ecryptfs_printk(KERN_ERR, "HMAC incorrect; return -EIO \n"); 300 | rc = -EIO; 301 | out: 302 | mutex_unlock(&crypt_stat->cs_hmac_mutex); 303 | kfree(root_hmac); 304 | return rc; 305 | } 306 | 307 | static int load_hmac_extents(struct ecryptfs_crypt_stat *crypt_stat, int extent, 308 | struct inode *ecryptfs_inode) 309 | { 310 | int rc = 0; 311 | size_t lwr_extent; 312 | u64 file_size; 313 | char *hmac_addr; 314 | char *hmac_value; 315 | struct scatterlist sg; 316 | struct ecryptfs_hmac_table *level1_node; 317 | struct ecryptfs_hmac_table *level2_node; 318 | struct ecryptfs_hmac_table *root; 319 | 320 | hmac_value = kmalloc(ECRYPTFS_HMAC_BYTES, GFP_KERNEL);/*32*/ 321 | if (!hmac_value) { 322 | ecryptfs_printk(KERN_ERR, "Error allocating hmac_value\n"); 323 | return -ENOMEM; 324 | } 325 | 326 | root = crypt_stat->root; 327 | if (!root) { 328 | ecryptfs_printk(KERN_ERR, "Error returning EIO\n"); 329 | rc = -EIO; 330 | goto out; 331 | } 332 | /* 333 | * Allocate first level HMAC node if it has not been 334 | * prviously initialized 335 | */ 336 | if (!(root->children[FL_HMAC(extent)])) { 337 | lwr_extent = HEADER_EXTENTS + (FL_HMAC(extent) * FL_OFFSET); 338 | rc = ecryptfs_init_hmac_node(&(root->children[FL_HMAC(extent)]), 339 | lwr_extent); 340 | if (rc) 341 | goto out; 342 | level1_node = root->children[FL_HMAC(extent)]; 343 | } else { 344 | level1_node = root->children[FL_HMAC(extent)]; 345 | } 346 | 347 | /* 348 | * Allocate second level HMAC node if it has not been 349 | * previously initialized 350 | */ 351 | if (!(level1_node->children[SL_HMAC(extent)])) { 352 | lwr_extent = (level1_node->lwr_extent + 1) 353 | + (SL_HMAC(extent) * SL_OFFSET); 354 | rc = ecryptfs_init_hmac_node( 355 | &(level1_node->children[SL_HMAC(extent)]), 356 | lwr_extent); 357 | if (rc) 358 | goto out; 359 | level2_node = level1_node->children[SL_HMAC(extent)]; 360 | file_size = (u64)i_size_read(ecryptfs_inode);/*inode->i_size*/ 361 | if (file_size <= crypt_stat->extent_size * (extent & ~0x7f)) { 362 | goto out; 363 | } 364 | rc = ecryptfs_read_lower(level2_node->extent/*dst: data*/, 365 | lwr_extent * crypt_stat->extent_size/*offset*/, 366 | crypt_stat->extent_size/*size*/, 367 | ecryptfs_inode); 368 | if (rc) 369 | goto out; 370 | 371 | /* Below: To verify two value @hmac_value(1st level hmac) and @hmac_addr, use different ways to compute and check */ 372 | sg_init_one(&sg, level2_node->extent, crypt_stat->extent_size); 373 | rc = ecryptfs_calculate_hmac(hmac_value/*dst: 32octets*/, crypt_stat, &sg, 374 | crypt_stat->extent_size);/* Calculate tha value of second level extent hmac */ 375 | if (rc) 376 | goto out; 377 | hmac_addr = level1_node->extent 378 | + (SL_HMAC(extent) * ECRYPTFS_HMAC_BYTES);/* first level HMAC value */ 379 | if (memcmp(hmac_value, hmac_addr, ECRYPTFS_HMAC_BYTES)) { 380 | ecryptfs_printk(KERN_ERR, "Error returning EIO\n"); 381 | rc = -EIO; 382 | goto out; 383 | } 384 | } 385 | out: 386 | kfree(hmac_value); 387 | return rc; 388 | } 389 | 390 | int ecryptfs_update_hmac(struct ecryptfs_crypt_stat *crypt_stat, 391 | struct inode *ecryptfs_inode, struct page *page, 392 | int page_offset/*offset in that page*/, int extent/*extent offset*/) 393 | { 394 | int rc; 395 | struct ecryptfs_hmac_table *level1_node; 396 | struct ecryptfs_hmac_table *level2_node; 397 | struct scatterlist sg; 398 | char *hmac_addr; 399 | 400 | 401 | mutex_lock(&crypt_stat->cs_hmac_mutex); 402 | if (!crypt_stat->root) { 403 | ecryptfs_printk(KERN_ERR, "Error returning EIO\n"); 404 | rc = -EIO; 405 | goto out; 406 | } 407 | rc = load_hmac_extents(crypt_stat, extent, ecryptfs_inode);/*verify the hmac value*/ 408 | if (rc) 409 | goto out; 410 | if (!(crypt_stat->root->children[FL_HMAC(extent)])) { 411 | ecryptfs_printk(KERN_ERR, "Error returning EIO\n"); 412 | rc = -EIO; 413 | goto out; 414 | } 415 | level1_node = crypt_stat->root->children[FL_HMAC(extent)]; 416 | 417 | if (!(level1_node->children[SL_HMAC(extent)])) { 418 | ecryptfs_printk(KERN_ERR, "Error returning EIO\n"); 419 | rc = -EIO; 420 | } 421 | level2_node = level1_node->children[SL_HMAC(extent)]; 422 | 423 | /* 424 | * Update the Second level HMAC 425 | */ 426 | hmac_addr = level2_node->extent 427 | + (TL_HMAC(extent) * ECRYPTFS_HMAC_BYTES); 428 | sg_init_table(&sg, 1); 429 | sg_set_page(&sg, page, crypt_stat->extent_size, page_offset); 430 | rc = ecryptfs_calculate_hmac(hmac_addr/*dst*/, crypt_stat, &sg, 431 | crypt_stat->extent_size); 432 | level2_node->flags |= ECRYPTFS_HMAC_EXTENT_DIRTY; 433 | 434 | /* 435 | * Update the first level HMAC 436 | */ 437 | hmac_addr = level1_node->extent 438 | + (SL_HMAC(extent) * ECRYPTFS_HMAC_BYTES); 439 | sg_init_one(&sg, level2_node->extent, crypt_stat->extent_size); 440 | rc = ecryptfs_calculate_hmac(hmac_addr/*dst*/, crypt_stat, &sg, 441 | crypt_stat->extent_size); 442 | if (rc) 443 | goto out; 444 | level1_node->flags |= ECRYPTFS_HMAC_EXTENT_DIRTY; 445 | ecryptfs_calculate_root_hmac(crypt_stat, crypt_stat->root->extent/*dst*/); 446 | ecryptfs_write_hmac_root_to_header(ecryptfs_inode, crypt_stat); 447 | out: 448 | mutex_unlock(&crypt_stat->cs_hmac_mutex); 449 | if (rc) { 450 | ecryptfs_printk(KERN_ERR, "Error returning EIO\n"); 451 | rc = -EIO; 452 | } 453 | return rc; 454 | } 455 | 456 | int ecryptfs_verify_hmac(struct ecryptfs_crypt_stat *crypt_stat, 457 | struct inode *ecryptfs_inode, struct page *page, 458 | int page_offset, int extent) 459 | { 460 | int rc; 461 | struct ecryptfs_hmac_table *root; 462 | struct ecryptfs_hmac_table *node; 463 | struct scatterlist sg; 464 | char *hmac_value; 465 | char *hmac_addr; 466 | 467 | hmac_value = kmalloc(ECRYPTFS_HMAC_BYTES, GFP_KERNEL);/*32*/ 468 | if (!hmac_value) { 469 | ecryptfs_printk(KERN_ERR, "Error allocating hmac_value\n"); 470 | return -ENOMEM; 471 | } 472 | 473 | mutex_lock(&crypt_stat->cs_hmac_mutex); 474 | root = crypt_stat->root; 475 | if (!root) { 476 | rc = -EIO; 477 | goto out; 478 | } 479 | rc = load_hmac_extents(crypt_stat, extent, ecryptfs_inode); 480 | if (rc) { 481 | goto out; 482 | } 483 | if (!(crypt_stat->root->children[FL_HMAC(extent)])) { 484 | rc = -EINVAL; 485 | goto out; 486 | } 487 | 488 | if (!(root->children[FL_HMAC(extent)]->children[SL_HMAC(extent)])) { 489 | rc = -EINVAL; 490 | goto out; 491 | } 492 | node = root->children[FL_HMAC(extent)]->children[SL_HMAC(extent)]; 493 | 494 | sg_init_table(&sg, 1); 495 | sg_set_page(&sg, page, crypt_stat->extent_size, page_offset); 496 | rc = ecryptfs_calculate_hmac(hmac_value/*dst*/, crypt_stat, &sg, 497 | crypt_stat->extent_size); 498 | if (rc) 499 | goto out; 500 | hmac_addr = node->extent + (TL_HMAC(extent) * ECRYPTFS_HMAC_BYTES); 501 | if (memcmp(hmac_value, hmac_addr, ECRYPTFS_HMAC_BYTES)) {/* Compare 3rd level hmac value */ 502 | rc = -EINVAL; 503 | goto out; 504 | } 505 | out: 506 | mutex_unlock(&crypt_stat->cs_hmac_mutex); 507 | if (rc) { 508 | ecryptfs_printk(KERN_ERR, "Error returning EIO\n"); 509 | return -EIO; 510 | } 511 | return rc; 512 | } 513 | 514 | void ecryptfs_truncate_hmac(struct ecryptfs_crypt_stat *crypt_stat, 515 | struct inode *ecryptfs_inode) 516 | { 517 | struct ecryptfs_hmac_table *root; 518 | struct ecryptfs_hmac_table *first_level_node; 519 | size_t size; 520 | size_t num_extents; 521 | size_t i; 522 | size_t j; 523 | 524 | size = i_size_read(ecryptfs_inode); 525 | num_extents = size / crypt_stat->extent_size; 526 | i = FL_HMAC((num_extents + 1)); 527 | j = SL_HMAC((num_extents + 1)); 528 | mutex_lock(&crypt_stat->cs_hmac_mutex); 529 | root = crypt_stat->root; 530 | if (!root) { 531 | goto out; 532 | } 533 | if (j != 0) { 534 | first_level_node = root->children[i]; 535 | if (!first_level_node) { 536 | goto out; 537 | } 538 | for (; j < HMAC_PER_EXTENT; j++) { 539 | if (!first_level_node->children[j]) 540 | goto out; 541 | kmem_cache_free(ecryptfs_extent_cache, 542 | first_level_node->children[j]->extent);/*4096*/ 543 | kfree(first_level_node->children[j]); 544 | memset(&(first_level_node->children[j]), 0, 545 | sizeof(struct ecryptfs_hmac_table *)); 546 | } 547 | i++; 548 | } 549 | for (; i < HMAC_PER_EXTENT; i++) { 550 | first_level_node = root->children[i]; 551 | if (!first_level_node) 552 | goto out; 553 | for (j = 0; j < HMAC_PER_EXTENT; j++) { 554 | if (!first_level_node->children[j]) 555 | goto out; 556 | kmem_cache_free(ecryptfs_extent_cache, 557 | first_level_node->children[j]->extent); 558 | kfree(first_level_node->children[j]); 559 | memset(&(first_level_node->children[j]), 0, 560 | sizeof(struct ecryptfs_hmac_table *)); 561 | } 562 | kmem_cache_free(ecryptfs_extent_cache, 563 | first_level_node->extent); 564 | kfree(first_level_node); 565 | memset(&(root->children[i]), 0, 566 | sizeof(struct ecryptfs_hmac_table *)); 567 | } 568 | ecryptfs_calculate_root_hmac(crypt_stat, crypt_stat->root->extent/*dst*/); 569 | ecryptfs_write_hmac_root_to_header(ecryptfs_inode, crypt_stat); 570 | out: 571 | mutex_unlock(&crypt_stat->cs_hmac_mutex); 572 | } 573 | 574 | 575 | /** 576 | * ecryptfs_free_hmac_table 577 | * @crypt_stat: Pointer to crypt_stat struct hmac table for the current inode 578 | * 579 | * Free all hmac extents and nodes for the hmac table 580 | * 581 | * This function should always succeed 582 | */ 583 | void ecryptfs_free_hmac_table(struct ecryptfs_hmac_table *root) 584 | { 585 | struct ecryptfs_hmac_table *first_level_node; 586 | size_t i = 0; 587 | size_t j; 588 | 589 | if(!root) 590 | return; 591 | for (i = 0; i < HMAC_PER_EXTENT; i++) { 592 | first_level_node = root->children[i]; 593 | if (!first_level_node) 594 | continue; 595 | for (j = 0; j < HMAC_PER_EXTENT; j++) { 596 | if (!first_level_node->children[j]) 597 | continue; 598 | kmem_cache_free(ecryptfs_extent_cache, 599 | first_level_node->children[j]->extent); 600 | kfree(first_level_node->children[j]); 601 | } 602 | kmem_cache_free(ecryptfs_extent_cache, 603 | first_level_node->extent); 604 | kfree(first_level_node); 605 | } 606 | if (root->extent) 607 | kmem_cache_free(ecryptfs_extent_cache,root->extent); 608 | kfree(root); 609 | } 610 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/messaging.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 2004-2006 International Business Machines Corp. 5 | * Author(s): Michael A. Halcrow 6 | * Tyler Hicks 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License version 10 | * 2 as published by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 | * 02111-1307, USA. 21 | */ 22 | #include 23 | #include "ecryptfs_kernel.h" 24 | 25 | static LIST_HEAD(ecryptfs_msg_ctx_free_list); 26 | static LIST_HEAD(ecryptfs_msg_ctx_alloc_list); 27 | static struct mutex ecryptfs_msg_ctx_lists_mux; 28 | 29 | static struct hlist_head *ecryptfs_daemon_id_hash; 30 | static struct mutex ecryptfs_daemon_id_hash_mux; 31 | static int ecryptfs_hash_buckets; 32 | #define ecryptfs_uid_hash(uid) \ 33 | hash_long((unsigned long)uid, ecryptfs_hash_buckets) 34 | 35 | static unsigned int ecryptfs_msg_counter; 36 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; 37 | 38 | /** 39 | * ecryptfs_acquire_free_msg_ctx 40 | * @msg_ctx: The context that was acquired from the free list 41 | * 42 | * Acquires a context element from the free list and locks the mutex 43 | * on the context. Returns zero on success; non-zero on error or upon 44 | * failure to acquire a free context element. Be sure to lock the 45 | * list mutex before calling. 46 | */ 47 | static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx) 48 | { 49 | struct list_head *p; 50 | int rc; 51 | 52 | if (list_empty(&ecryptfs_msg_ctx_free_list)) { 53 | ecryptfs_printk(KERN_WARNING, "The eCryptfs free " 54 | "context list is empty. It may be helpful to " 55 | "specify the ecryptfs_message_buf_len " 56 | "parameter to be greater than the current " 57 | "value of [%d]\n", ecryptfs_message_buf_len); 58 | rc = -ENOMEM; 59 | goto out; 60 | } 61 | list_for_each(p, &ecryptfs_msg_ctx_free_list) { 62 | *msg_ctx = list_entry(p, struct ecryptfs_msg_ctx, node); 63 | if (mutex_trylock(&(*msg_ctx)->mux)) { 64 | (*msg_ctx)->task = current; 65 | rc = 0; 66 | goto out; 67 | } 68 | } 69 | rc = -ENOMEM; 70 | out: 71 | return rc; 72 | } 73 | 74 | /** 75 | * ecryptfs_msg_ctx_free_to_alloc 76 | * @msg_ctx: The context to move from the free list to the alloc list 77 | * 78 | * Be sure to lock the list mutex and the context mutex before 79 | * calling. 80 | */ 81 | static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx) 82 | { 83 | list_move(&msg_ctx->node, &ecryptfs_msg_ctx_alloc_list); 84 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_PENDING; 85 | msg_ctx->counter = ++ecryptfs_msg_counter; 86 | } 87 | 88 | /** 89 | * ecryptfs_msg_ctx_alloc_to_free 90 | * @msg_ctx: The context to move from the alloc list to the free list 91 | * 92 | * Be sure to lock the list mutex and the context mutex before 93 | * calling. 94 | */ 95 | static void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) 96 | { 97 | list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list); 98 | if (msg_ctx->msg) 99 | kfree(msg_ctx->msg); 100 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE; 101 | } 102 | 103 | /** 104 | * ecryptfs_find_daemon_id 105 | * @uid: The user id which maps to the desired daemon id 106 | * @id: If return value is zero, points to the desired daemon id 107 | * pointer 108 | * 109 | * Search the hash list for the given user id. Returns zero if the 110 | * user id exists in the list; non-zero otherwise. The daemon id hash 111 | * mutex should be held before calling this function. 112 | */ 113 | static int ecryptfs_find_daemon_id(uid_t uid, struct ecryptfs_daemon_id **id) 114 | { 115 | struct hlist_node *elem; 116 | int rc; 117 | 118 | hlist_for_each_entry(*id, elem, 119 | &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)], 120 | id_chain) { 121 | if ((*id)->uid == uid) { 122 | rc = 0; 123 | goto out; 124 | } 125 | } 126 | rc = -EINVAL; 127 | out: 128 | return rc; 129 | } 130 | 131 | static int ecryptfs_send_raw_message(unsigned int transport, u16 msg_type, 132 | pid_t pid) 133 | { 134 | int rc; 135 | 136 | switch(transport) { 137 | case ECRYPTFS_TRANSPORT_NETLINK: 138 | rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0, pid); 139 | break; 140 | case ECRYPTFS_TRANSPORT_CONNECTOR: 141 | case ECRYPTFS_TRANSPORT_RELAYFS: 142 | default: 143 | rc = -ENOSYS; 144 | } 145 | return rc; 146 | } 147 | 148 | /** 149 | * ecryptfs_process_helo 150 | * @transport: The underlying transport (netlink, etc.) 151 | * @uid: The user ID owner of the message 152 | * @pid: The process ID for the userspace program that sent the 153 | * message 154 | * 155 | * Adds the uid and pid values to the daemon id hash. If a uid 156 | * already has a daemon pid registered, the daemon will be 157 | * unregistered before the new daemon id is put into the hash list. 158 | * Returns zero after adding a new daemon id to the hash list; 159 | * non-zero otherwise. 160 | */ 161 | int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid) 162 | { 163 | struct ecryptfs_daemon_id *new_id; 164 | struct ecryptfs_daemon_id *old_id; 165 | int rc; 166 | 167 | mutex_lock(&ecryptfs_daemon_id_hash_mux); 168 | new_id = kmalloc(sizeof(*new_id), GFP_KERNEL); 169 | if (!new_id) { 170 | rc = -ENOMEM; 171 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable " 172 | "to register daemon [%d] for user [%d]\n", 173 | pid, uid); 174 | goto unlock; 175 | } 176 | if (!ecryptfs_find_daemon_id(uid, &old_id)) { 177 | printk(KERN_WARNING "Received request from user [%d] " 178 | "to register daemon [%d]; unregistering daemon " 179 | "[%d]\n", uid, pid, old_id->pid); 180 | hlist_del(&old_id->id_chain); 181 | rc = ecryptfs_send_raw_message(transport, ECRYPTFS_NLMSG_QUIT, 182 | old_id->pid); 183 | if (rc) 184 | printk(KERN_WARNING "Failed to send QUIT " 185 | "message to daemon [%d]; rc = [%d]\n", 186 | old_id->pid, rc); 187 | kfree(old_id); 188 | } 189 | new_id->uid = uid; 190 | new_id->pid = pid; 191 | hlist_add_head(&new_id->id_chain, 192 | &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)]); 193 | rc = 0; 194 | unlock: 195 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); 196 | return rc; 197 | } 198 | 199 | /** 200 | * ecryptfs_process_quit 201 | * @uid: The user ID owner of the message 202 | * @pid: The process ID for the userspace program that sent the 203 | * message 204 | * 205 | * Deletes the corresponding daemon id for the given uid and pid, if 206 | * it is the registered that is requesting the deletion. Returns zero 207 | * after deleting the desired daemon id; non-zero otherwise. 208 | */ 209 | int ecryptfs_process_quit(uid_t uid, pid_t pid) 210 | { 211 | struct ecryptfs_daemon_id *id; 212 | int rc; 213 | 214 | mutex_lock(&ecryptfs_daemon_id_hash_mux); 215 | if (ecryptfs_find_daemon_id(uid, &id)) { 216 | rc = -EINVAL; 217 | ecryptfs_printk(KERN_ERR, "Received request from user [%d] to " 218 | "unregister unrecognized daemon [%d]\n", uid, 219 | pid); 220 | goto unlock; 221 | } 222 | if (id->pid != pid) { 223 | rc = -EINVAL; 224 | ecryptfs_printk(KERN_WARNING, "Received request from user [%d] " 225 | "with pid [%d] to unregister daemon [%d]\n", 226 | uid, pid, id->pid); 227 | goto unlock; 228 | } 229 | hlist_del(&id->id_chain); 230 | kfree(id); 231 | rc = 0; 232 | unlock: 233 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); 234 | return rc; 235 | } 236 | 237 | /** 238 | * ecryptfs_process_reponse 239 | * @msg: The ecryptfs message received; the caller should sanity check 240 | * msg->data_len 241 | * @pid: The process ID of the userspace application that sent the 242 | * message 243 | * @seq: The sequence number of the message 244 | * 245 | * Processes a response message after sending a operation request to 246 | * userspace. Returns zero upon delivery to desired context element; 247 | * non-zero upon delivery failure or error. 248 | */ 249 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid, 250 | pid_t pid, u32 seq) 251 | { 252 | struct ecryptfs_daemon_id *id; 253 | struct ecryptfs_msg_ctx *msg_ctx; 254 | int msg_size; 255 | int rc; 256 | 257 | if (msg->index >= ecryptfs_message_buf_len) { 258 | rc = -EINVAL; 259 | ecryptfs_printk(KERN_ERR, "Attempt to reference " 260 | "context buffer at index [%d]; maximum " 261 | "allowable is [%d]\n", msg->index, 262 | (ecryptfs_message_buf_len - 1)); 263 | goto out; 264 | } 265 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; 266 | mutex_lock(&msg_ctx->mux); 267 | if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) { 268 | rc = -EBADMSG; 269 | ecryptfs_printk(KERN_WARNING, "User [%d] received a " 270 | "message response from process [%d] but does " 271 | "not have a registered daemon\n", 272 | msg_ctx->task->euid, pid); 273 | goto wake_up; 274 | } 275 | if (msg_ctx->task->euid != uid) { 276 | rc = -EBADMSG; 277 | ecryptfs_printk(KERN_WARNING, "Received message from user " 278 | "[%d]; expected message from user [%d]\n", 279 | uid, msg_ctx->task->euid); 280 | goto unlock; 281 | } 282 | if (id->pid != pid) { 283 | rc = -EBADMSG; 284 | ecryptfs_printk(KERN_ERR, "User [%d] received a " 285 | "message response from an unrecognized " 286 | "process [%d]\n", msg_ctx->task->euid, pid); 287 | goto unlock; 288 | } 289 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { 290 | rc = -EINVAL; 291 | ecryptfs_printk(KERN_WARNING, "Desired context element is not " 292 | "pending a response\n"); 293 | goto unlock; 294 | } else if (msg_ctx->counter != seq) { 295 | rc = -EINVAL; 296 | ecryptfs_printk(KERN_WARNING, "Invalid message sequence; " 297 | "expected [%d]; received [%d]\n", 298 | msg_ctx->counter, seq); 299 | goto unlock; 300 | } 301 | msg_size = sizeof(*msg) + msg->data_len; 302 | msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL); 303 | if (!msg_ctx->msg) { 304 | rc = -ENOMEM; 305 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); 306 | goto unlock; 307 | } 308 | memcpy(msg_ctx->msg, msg, msg_size); 309 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; 310 | rc = 0; 311 | wake_up: 312 | wake_up_process(msg_ctx->task); 313 | unlock: 314 | mutex_unlock(&msg_ctx->mux); 315 | out: 316 | return rc; 317 | } 318 | 319 | /** 320 | * ecryptfs_send_message 321 | * @transport: The transport over which to send the message (i.e., 322 | * netlink) 323 | * @data: The data to send 324 | * @data_len: The length of data 325 | * @msg_ctx: The message context allocated for the send 326 | */ 327 | int ecryptfs_send_message(unsigned int transport, char *data, int data_len, 328 | struct ecryptfs_msg_ctx **msg_ctx) 329 | { 330 | struct ecryptfs_daemon_id *id; 331 | int rc; 332 | 333 | mutex_lock(&ecryptfs_daemon_id_hash_mux); 334 | if (ecryptfs_find_daemon_id(current->euid, &id)) { 335 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); 336 | rc = -ENOTCONN; 337 | ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon " 338 | "registered\n", current->euid); 339 | goto out; 340 | } 341 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); 342 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); 343 | rc = ecryptfs_acquire_free_msg_ctx(msg_ctx); 344 | if (rc) { 345 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); 346 | ecryptfs_printk(KERN_WARNING, "Could not claim a free " 347 | "context element\n"); 348 | goto out; 349 | } 350 | ecryptfs_msg_ctx_free_to_alloc(*msg_ctx); 351 | mutex_unlock(&(*msg_ctx)->mux); 352 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); 353 | switch (transport) { 354 | case ECRYPTFS_TRANSPORT_NETLINK: 355 | rc = ecryptfs_send_netlink(data, data_len, *msg_ctx, 356 | ECRYPTFS_NLMSG_REQUEST, 0, id->pid); 357 | break; 358 | case ECRYPTFS_TRANSPORT_CONNECTOR: 359 | case ECRYPTFS_TRANSPORT_RELAYFS: 360 | default: 361 | rc = -ENOSYS; 362 | } 363 | if (rc) { 364 | printk(KERN_ERR "Error attempting to send message to userspace " 365 | "daemon; rc = [%d]\n", rc); 366 | } 367 | out: 368 | return rc; 369 | } 370 | 371 | /** 372 | * ecryptfs_wait_for_response 373 | * @msg_ctx: The context that was assigned when sending a message 374 | * @msg: The incoming message from userspace; not set if rc != 0 375 | * 376 | * Sleeps until awaken by ecryptfs_receive_message or until the amount 377 | * of time exceeds ecryptfs_message_wait_timeout. If zero is 378 | * returned, msg will point to a valid message from userspace; a 379 | * non-zero value is returned upon failure to receive a message or an 380 | * error occurs. 381 | */ 382 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, 383 | struct ecryptfs_message **msg) 384 | { 385 | signed long timeout = ecryptfs_message_wait_timeout * HZ; 386 | int rc = 0; 387 | 388 | sleep: 389 | timeout = schedule_timeout_interruptible(timeout); 390 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); 391 | mutex_lock(&msg_ctx->mux); 392 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_DONE) { 393 | if (timeout) { 394 | mutex_unlock(&msg_ctx->mux); 395 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); 396 | goto sleep; 397 | } 398 | rc = -ENOMSG; 399 | } else { 400 | *msg = msg_ctx->msg; 401 | msg_ctx->msg = NULL; 402 | } 403 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); 404 | mutex_unlock(&msg_ctx->mux); 405 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); 406 | return rc; 407 | } 408 | 409 | int ecryptfs_init_messaging(unsigned int transport) 410 | { 411 | int i; 412 | int rc = 0; 413 | 414 | if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) { 415 | ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS; 416 | ecryptfs_printk(KERN_WARNING, "Specified number of users is " 417 | "too large, defaulting to [%d] users\n", 418 | ecryptfs_number_of_users); 419 | } 420 | mutex_init(&ecryptfs_daemon_id_hash_mux); 421 | mutex_lock(&ecryptfs_daemon_id_hash_mux); 422 | ecryptfs_hash_buckets = 1; 423 | while (ecryptfs_number_of_users >> ecryptfs_hash_buckets) 424 | ecryptfs_hash_buckets++; 425 | ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head) 426 | * ecryptfs_hash_buckets, GFP_KERNEL); 427 | if (!ecryptfs_daemon_id_hash) { 428 | rc = -ENOMEM; 429 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); 430 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); 431 | goto out; 432 | } 433 | for (i = 0; i < ecryptfs_hash_buckets; i++) 434 | INIT_HLIST_HEAD(&ecryptfs_daemon_id_hash[i]); 435 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); 436 | 437 | ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx) 438 | * ecryptfs_message_buf_len), GFP_KERNEL); 439 | if (!ecryptfs_msg_ctx_arr) { 440 | rc = -ENOMEM; 441 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); 442 | goto out; 443 | } 444 | mutex_init(&ecryptfs_msg_ctx_lists_mux); 445 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); 446 | ecryptfs_msg_counter = 0; 447 | for (i = 0; i < ecryptfs_message_buf_len; i++) { 448 | INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node); 449 | mutex_init(&ecryptfs_msg_ctx_arr[i].mux); 450 | mutex_lock(&ecryptfs_msg_ctx_arr[i].mux); 451 | ecryptfs_msg_ctx_arr[i].index = i; 452 | ecryptfs_msg_ctx_arr[i].state = ECRYPTFS_MSG_CTX_STATE_FREE; 453 | ecryptfs_msg_ctx_arr[i].counter = 0; 454 | ecryptfs_msg_ctx_arr[i].task = NULL; 455 | ecryptfs_msg_ctx_arr[i].msg = NULL; 456 | list_add_tail(&ecryptfs_msg_ctx_arr[i].node, 457 | &ecryptfs_msg_ctx_free_list); 458 | mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux); 459 | } 460 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); 461 | switch(transport) { 462 | case ECRYPTFS_TRANSPORT_NETLINK: 463 | rc = ecryptfs_init_netlink(); 464 | if (rc) 465 | ecryptfs_release_messaging(transport); 466 | break; 467 | case ECRYPTFS_TRANSPORT_CONNECTOR: 468 | case ECRYPTFS_TRANSPORT_RELAYFS: 469 | default: 470 | rc = -ENOSYS; 471 | } 472 | out: 473 | return rc; 474 | } 475 | 476 | void ecryptfs_release_messaging(unsigned int transport) 477 | { 478 | if (ecryptfs_msg_ctx_arr) { 479 | int i; 480 | 481 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); 482 | for (i = 0; i < ecryptfs_message_buf_len; i++) { 483 | mutex_lock(&ecryptfs_msg_ctx_arr[i].mux); 484 | if (ecryptfs_msg_ctx_arr[i].msg) 485 | kfree(ecryptfs_msg_ctx_arr[i].msg); 486 | mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux); 487 | } 488 | kfree(ecryptfs_msg_ctx_arr); 489 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); 490 | } 491 | if (ecryptfs_daemon_id_hash) { 492 | struct hlist_node *elem; 493 | struct ecryptfs_daemon_id *id; 494 | int i; 495 | 496 | mutex_lock(&ecryptfs_daemon_id_hash_mux); 497 | for (i = 0; i < ecryptfs_hash_buckets; i++) { 498 | hlist_for_each_entry(id, elem, 499 | &ecryptfs_daemon_id_hash[i], 500 | id_chain) { 501 | hlist_del(elem); 502 | kfree(id); 503 | } 504 | } 505 | kfree(ecryptfs_daemon_id_hash); 506 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); 507 | } 508 | switch(transport) { 509 | case ECRYPTFS_TRANSPORT_NETLINK: 510 | ecryptfs_release_netlink(); 511 | break; 512 | case ECRYPTFS_TRANSPORT_CONNECTOR: 513 | case ECRYPTFS_TRANSPORT_RELAYFS: 514 | default: 515 | break; 516 | } 517 | return; 518 | } 519 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/mmap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * This is where eCryptfs coordinates the symmetric encryption and 4 | * decryption of the file data as it passes between the lower 5 | * encrypted file and the upper decrypted file. 6 | * 7 | * Copyright (C) 1997-2003 Erez Zadok 8 | * Copyright (C) 2001-2003 Stony Brook University 9 | * Copyright (C) 2004-2007 International Business Machines Corp. 10 | * Author(s): Michael A. Halcrow 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License as 14 | * published by the Free Software Foundation; either version 2 of the 15 | * License, or (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, but 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | * General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program; if not, write to the Free Software 24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 25 | * 02111-1307, USA. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "ecryptfs_kernel.h" 36 | 37 | struct kmem_cache *ecryptfs_lower_page_cache; 38 | 39 | /** 40 | * ecryptfs_get_locked_page 41 | * 42 | * Get one page from cache or lower f/s, return error otherwise. 43 | * 44 | * Returns locked and up-to-date page (if ok), with increased 45 | * refcnt. 46 | */ 47 | struct page *ecryptfs_get_locked_page(struct file *file, loff_t index) 48 | { 49 | struct dentry *dentry; 50 | struct inode *inode; 51 | struct address_space *mapping; 52 | struct page *page; 53 | 54 | dentry = file->f_path.dentry; 55 | inode = dentry->d_inode; 56 | mapping = inode->i_mapping; 57 | page = read_mapping_page(mapping, index, (void *)file); 58 | if (!IS_ERR(page)) 59 | lock_page(page); 60 | return page; 61 | } 62 | 63 | /** 64 | * ecryptfs_writepage 65 | * @page: Page that is locked before this call is made 66 | * 67 | * Returns zero on success; non-zero otherwise 68 | */ 69 | static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) 70 | { 71 | int rc; 72 | 73 | rc = ecryptfs_encrypt_page(page); 74 | if (rc) { 75 | ecryptfs_printk(KERN_WARNING, "Error encrypting " 76 | "page (upper index [0x%.16x])\n", page->index); 77 | ClearPageUptodate(page); 78 | goto out; 79 | } 80 | SetPageUptodate(page); 81 | unlock_page(page); 82 | out: 83 | return rc; 84 | } 85 | 86 | /** 87 | * Header Extent: 88 | * Octets 0-7: Unencrypted file size (big-endian) 89 | * Octets 8-15: eCryptfs special marker 90 | * Octets 16-19: Flags 91 | * Octet 16: File format version number (between 0 and 255) 92 | * Octets 17-18: Reserved 93 | * Octet 19: Bit 1 (lsb): Reserved 94 | * Bit 2: Encrypted? 95 | * Bits 3-8: Reserved 96 | * Octets 20-23: Header extent size (big-endian) 97 | * Octets 24-25: Number of header extents at front of file 98 | * (big-endian) 99 | * Octet 26: Begin RFC 2440 authentication token packet set 100 | */ 101 | static void set_header_info(char *page_virt, 102 | struct ecryptfs_crypt_stat *crypt_stat) 103 | { 104 | size_t written; 105 | int save_num_header_extents_at_front = 106 | crypt_stat->num_header_extents_at_front; 107 | 108 | crypt_stat->num_header_extents_at_front = 1; 109 | ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written); 110 | crypt_stat->num_header_extents_at_front = 111 | save_num_header_extents_at_front; 112 | } 113 | 114 | /** 115 | * ecryptfs_copy_up_encrypted_with_header 116 | * @page: Sort of a ``virtual'' representation of the encrypted lower 117 | * file. The actual lower file does not have the metadata in 118 | * the header. This is locked. 119 | * @crypt_stat: The eCryptfs inode's cryptographic context 120 | * 121 | * The ``view'' is the version of the file that userspace winds up 122 | * seeing, with the header information inserted. 123 | */ 124 | static int 125 | ecryptfs_copy_up_encrypted_with_header(struct page *page, 126 | struct ecryptfs_crypt_stat *crypt_stat) 127 | { 128 | loff_t extent_num_in_page = 0; 129 | loff_t num_extents_per_page = (PAGE_CACHE_SIZE 130 | / crypt_stat->extent_size); 131 | int rc = 0; 132 | 133 | while (extent_num_in_page < num_extents_per_page) { 134 | loff_t view_extent_num = ((((loff_t)page->index) 135 | * num_extents_per_page) 136 | + extent_num_in_page); 137 | 138 | if (view_extent_num < crypt_stat->num_header_extents_at_front) { 139 | /* This is a header extent */ 140 | char *page_virt; 141 | 142 | page_virt = kmap_atomic(page, KM_USER0); 143 | memset(page_virt, 0, PAGE_CACHE_SIZE); 144 | /* TODO: Support more than one header extent */ 145 | if (view_extent_num == 0) { 146 | rc = ecryptfs_read_xattr_region( 147 | page_virt, page->mapping->host); 148 | set_header_info(page_virt, crypt_stat); 149 | } 150 | kunmap_atomic(page_virt, KM_USER0); 151 | flush_dcache_page(page); 152 | if (rc) { 153 | printk(KERN_ERR "%s: Error reading xattr " 154 | "region; rc = [%d]\n", __FUNCTION__, rc); 155 | goto out; 156 | } 157 | } else { 158 | /* This is an encrypted data extent */ 159 | loff_t lower_offset = 160 | ((view_extent_num - 161 | crypt_stat->num_header_extents_at_front) 162 | * crypt_stat->extent_size); 163 | 164 | rc = ecryptfs_read_lower_page_segment( 165 | page, (lower_offset >> PAGE_CACHE_SHIFT), 166 | (lower_offset & ~PAGE_CACHE_MASK), 167 | crypt_stat->extent_size, page->mapping->host); 168 | if (rc) { 169 | printk(KERN_ERR "%s: Error attempting to read " 170 | "extent at offset [%lld] in the lower " 171 | "file; rc = [%d]\n", __FUNCTION__, 172 | lower_offset, rc); 173 | goto out; 174 | } 175 | } 176 | extent_num_in_page++; 177 | } 178 | out: 179 | return rc; 180 | } 181 | 182 | /** 183 | * ecryptfs_readpage 184 | * @file: An eCryptfs file 185 | * @page: Page from eCryptfs inode mapping into which to stick the read data 186 | * 187 | * Read in a page, decrypting if necessary. 188 | * 189 | * Returns zero on success; non-zero on error. 190 | */ 191 | static int ecryptfs_readpage(struct file *file, struct page *page) 192 | { 193 | struct ecryptfs_crypt_stat *crypt_stat = 194 | &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat; 195 | int rc = 0; 196 | 197 | if (!crypt_stat 198 | || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED) 199 | || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { 200 | ecryptfs_printk(KERN_DEBUG, 201 | "Passing through unencrypted page\n"); 202 | rc = ecryptfs_read_lower_page_segment(page, page->index, 0, 203 | PAGE_CACHE_SIZE, 204 | page->mapping->host); 205 | } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { 206 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { 207 | rc = ecryptfs_copy_up_encrypted_with_header(page, 208 | crypt_stat); 209 | if (rc) { 210 | printk(KERN_ERR "%s: Error attempting to copy " 211 | "the encrypted content from the lower " 212 | "file whilst inserting the metadata " 213 | "from the xattr into the header; rc = " 214 | "[%d]\n", __FUNCTION__, rc); 215 | goto out; 216 | } 217 | 218 | } else { 219 | rc = ecryptfs_read_lower_page_segment( 220 | page, page->index, 0, PAGE_CACHE_SIZE, 221 | page->mapping->host); 222 | if (rc) { 223 | printk(KERN_ERR "Error reading page; rc = " 224 | "[%d]\n", rc); 225 | goto out; 226 | } 227 | } 228 | } else { 229 | rc = ecryptfs_decrypt_page(page); 230 | if (rc) { 231 | ecryptfs_printk(KERN_ERR, "Error decrypting page; " 232 | "rc = [%d]\n", rc); 233 | goto out; 234 | } 235 | } 236 | out: 237 | if (rc) 238 | ClearPageUptodate(page); 239 | else 240 | SetPageUptodate(page); 241 | ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]\n", 242 | page->index); 243 | unlock_page(page); 244 | return rc; 245 | } 246 | 247 | /** 248 | * Called with lower inode mutex held. 249 | */ 250 | static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) 251 | { 252 | struct inode *inode = page->mapping->host; 253 | int end_byte_in_page; 254 | 255 | if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index) 256 | goto out; 257 | end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; 258 | if (to > end_byte_in_page) 259 | end_byte_in_page = to; 260 | zero_user_page(page, end_byte_in_page, 261 | PAGE_CACHE_SIZE - end_byte_in_page, KM_USER0); 262 | out: 263 | return 0; 264 | } 265 | 266 | /* This function must zero any hole we create */ 267 | static int ecryptfs_prepare_write(struct file *file, struct page *page, 268 | unsigned from, unsigned to) 269 | { 270 | int rc = 0; 271 | loff_t prev_page_end_size; 272 | 273 | if (!PageUptodate(page)) { 274 | rc = ecryptfs_read_lower_page_segment(page, page->index, 0, 275 | PAGE_CACHE_SIZE, 276 | page->mapping->host); 277 | if (rc) { 278 | printk(KERN_ERR "%s: Error attemping to read lower " 279 | "page segment; rc = [%d]\n", __FUNCTION__, rc); 280 | ClearPageUptodate(page); 281 | goto out; 282 | } else 283 | SetPageUptodate(page); 284 | } 285 | 286 | prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT); 287 | 288 | /* 289 | * If creating a page or more of holes, zero them out via truncate. 290 | * Note, this will increase i_size. 291 | */ 292 | if (page->index != 0) { 293 | if (prev_page_end_size > i_size_read(page->mapping->host)) { 294 | rc = ecryptfs_truncate(file->f_path.dentry, 295 | prev_page_end_size); 296 | if (rc) { 297 | printk(KERN_ERR "Error on attempt to " 298 | "truncate to (higher) offset [%lld];" 299 | " rc = [%d]\n", prev_page_end_size, rc); 300 | goto out; 301 | } 302 | } 303 | } 304 | /* 305 | * Writing to a new page, and creating a small hole from start of page? 306 | * Zero it out. 307 | */ 308 | if ((i_size_read(page->mapping->host) == prev_page_end_size) && 309 | (from != 0)) { 310 | zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); 311 | } 312 | out: 313 | return rc; 314 | } 315 | 316 | /** 317 | * ecryptfs_write_inode_size_to_header 318 | * 319 | * Writes the lower file size to the first 8 bytes of the header. 320 | * 321 | * Returns zero on success; non-zero on error. 322 | */ 323 | static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode) 324 | { 325 | u64 file_size; 326 | char *file_size_virt; 327 | int rc; 328 | 329 | file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL); 330 | if (!file_size_virt) { 331 | rc = -ENOMEM; 332 | goto out; 333 | } 334 | file_size = (u64)i_size_read(ecryptfs_inode); 335 | file_size = cpu_to_be64(file_size); 336 | memcpy(file_size_virt, &file_size, sizeof(u64)); 337 | rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0, 338 | sizeof(u64)); 339 | kfree(file_size_virt); 340 | if (rc) 341 | printk(KERN_ERR "%s: Error writing file size to header; " 342 | "rc = [%d]\n", __FUNCTION__, rc); 343 | out: 344 | return rc; 345 | } 346 | 347 | struct kmem_cache *ecryptfs_xattr_cache; 348 | 349 | static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode) 350 | { 351 | ssize_t size; 352 | void *xattr_virt; 353 | struct dentry *lower_dentry = 354 | ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry; 355 | struct inode *lower_inode = lower_dentry->d_inode; 356 | u64 file_size; 357 | int rc; 358 | 359 | if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) { 360 | printk(KERN_WARNING 361 | "No support for setting xattr in lower filesystem\n"); 362 | rc = -ENOSYS; 363 | goto out; 364 | } 365 | xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL); 366 | if (!xattr_virt) { 367 | printk(KERN_ERR "Out of memory whilst attempting to write " 368 | "inode size to xattr\n"); 369 | rc = -ENOMEM; 370 | goto out; 371 | } 372 | mutex_lock(&lower_inode->i_mutex); 373 | size = lower_inode->i_op->getxattr(lower_dentry, ECRYPTFS_XATTR_NAME, 374 | xattr_virt, PAGE_CACHE_SIZE); 375 | if (size < 0) 376 | size = 8; 377 | file_size = (u64)i_size_read(ecryptfs_inode); 378 | file_size = cpu_to_be64(file_size); 379 | memcpy(xattr_virt, &file_size, sizeof(u64)); 380 | rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME, 381 | xattr_virt, size, 0); 382 | mutex_unlock(&lower_inode->i_mutex); 383 | if (rc) 384 | printk(KERN_ERR "Error whilst attempting to write inode size " 385 | "to lower file xattr; rc = [%d]\n", rc); 386 | kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); 387 | out: 388 | return rc; 389 | } 390 | 391 | int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode) 392 | { 393 | struct ecryptfs_crypt_stat *crypt_stat; 394 | 395 | crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 396 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) 397 | return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode); 398 | else 399 | return ecryptfs_write_inode_size_to_header(ecryptfs_inode); 400 | } 401 | 402 | /** 403 | * ecryptfs_commit_write 404 | * @file: The eCryptfs file object 405 | * @page: The eCryptfs page 406 | * @from: Ignored (we rotate the page IV on each write) 407 | * @to: Ignored 408 | * 409 | * This is where we encrypt the data and pass the encrypted data to 410 | * the lower filesystem. In OpenPGP-compatible mode, we operate on 411 | * entire underlying packets. 412 | */ 413 | static int ecryptfs_commit_write(struct file *file, struct page *page, 414 | unsigned from, unsigned to) 415 | { 416 | loff_t pos; 417 | struct inode *ecryptfs_inode = page->mapping->host; 418 | struct ecryptfs_crypt_stat *crypt_stat = 419 | &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat; 420 | int rc; 421 | 422 | if (crypt_stat->flags & ECRYPTFS_NEW_FILE) { 423 | ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " 424 | "crypt_stat at memory location [%p]\n", crypt_stat); 425 | crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE); 426 | } else 427 | ecryptfs_printk(KERN_DEBUG, "Not a new file\n"); 428 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" 429 | "(page w/ index = [0x%.16x], to = [%d])\n", page->index, 430 | to); 431 | /* Fills in zeros if 'to' goes beyond inode size */ 432 | rc = fill_zeros_to_end_of_page(page, to); 433 | if (rc) { 434 | ecryptfs_printk(KERN_WARNING, "Error attempting to fill " 435 | "zeros in page with index = [0x%.16x]\n", 436 | page->index); 437 | goto out; 438 | } 439 | rc = ecryptfs_encrypt_page(page); 440 | if (rc) { 441 | ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " 442 | "index [0x%.16x])\n", page->index); 443 | goto out; 444 | } 445 | pos = (((loff_t)page->index) << PAGE_CACHE_SHIFT) + to; 446 | if (pos > i_size_read(ecryptfs_inode)) { 447 | i_size_write(ecryptfs_inode, pos); 448 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " 449 | "[0x%.16x]\n", i_size_read(ecryptfs_inode)); 450 | } 451 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); 452 | if (rc) 453 | printk(KERN_ERR "Error writing inode size to metadata; " 454 | "rc = [%d]\n", rc); 455 | out: 456 | return rc; 457 | } 458 | 459 | static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block) 460 | { 461 | int rc = 0; 462 | struct inode *inode; 463 | struct inode *lower_inode; 464 | 465 | inode = (struct inode *)mapping->host; 466 | lower_inode = ecryptfs_inode_to_lower(inode); 467 | if (lower_inode->i_mapping->a_ops->bmap) 468 | rc = lower_inode->i_mapping->a_ops->bmap(lower_inode->i_mapping, 469 | block); 470 | return rc; 471 | } 472 | 473 | struct address_space_operations ecryptfs_aops = { 474 | .writepage = ecryptfs_writepage, 475 | .readpage = ecryptfs_readpage, 476 | .prepare_write = ecryptfs_prepare_write, 477 | .commit_write = ecryptfs_commit_write, 478 | .bmap = ecryptfs_bmap, 479 | }; 480 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/netlink.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 2004-2006 International Business Machines Corp. 5 | * Author(s): Michael A. Halcrow 6 | * Tyler Hicks 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License version 10 | * 2 as published by the Free Software Foundation. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 | * 02111-1307, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include "ecryptfs_kernel.h" 27 | 28 | static struct sock *ecryptfs_nl_sock; 29 | 30 | /** 31 | * ecryptfs_send_netlink 32 | * @data: The data to include as the payload 33 | * @data_len: The byte count of the data 34 | * @msg_ctx: The netlink context that will be used to handle the 35 | * response message 36 | * @msg_type: The type of netlink message to send 37 | * @msg_flags: The flags to include in the netlink header 38 | * @daemon_pid: The process id of the daemon to send the message to 39 | * 40 | * Sends the data to the specified daemon pid and uses the netlink 41 | * context element to store the data needed for validation upon 42 | * receiving the response. The data and the netlink context can be 43 | * null if just sending a netlink header is sufficient. Returns zero 44 | * upon sending the message; non-zero upon error. 45 | */ 46 | int ecryptfs_send_netlink(char *data, int data_len, 47 | struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type, 48 | u16 msg_flags, pid_t daemon_pid) 49 | { 50 | struct sk_buff *skb; 51 | struct nlmsghdr *nlh; 52 | struct ecryptfs_message *msg; 53 | size_t payload_len; 54 | int rc; 55 | 56 | payload_len = ((data && data_len) ? (sizeof(*msg) + data_len) : 0); 57 | skb = alloc_skb(NLMSG_SPACE(payload_len), GFP_KERNEL); 58 | if (!skb) { 59 | rc = -ENOMEM; 60 | ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n"); 61 | goto out; 62 | } 63 | nlh = NLMSG_PUT(skb, daemon_pid, msg_ctx ? msg_ctx->counter : 0, 64 | msg_type, payload_len); 65 | nlh->nlmsg_flags = msg_flags; 66 | if (msg_ctx && payload_len) { 67 | msg = (struct ecryptfs_message *)NLMSG_DATA(nlh); 68 | msg->index = msg_ctx->index; 69 | msg->data_len = data_len; 70 | memcpy(msg->data, data, data_len); 71 | } 72 | rc = netlink_unicast(ecryptfs_nl_sock, skb, daemon_pid, 0); 73 | if (rc < 0) { 74 | ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink " 75 | "message; rc = [%d]\n", rc); 76 | goto out; 77 | } 78 | rc = 0; 79 | goto out; 80 | nlmsg_failure: 81 | rc = -EMSGSIZE; 82 | kfree_skb(skb); 83 | out: 84 | return rc; 85 | } 86 | 87 | /** 88 | * ecryptfs_process_nl_reponse 89 | * @skb: The socket buffer containing the netlink message of state 90 | * RESPONSE 91 | * 92 | * Processes a response message after sending a operation request to 93 | * userspace. Attempts to assign the msg to a netlink context element 94 | * at the index specified in the msg. The sk_buff and nlmsghdr must 95 | * be validated before this function. Returns zero upon delivery to 96 | * desired context element; non-zero upon delivery failure or error. 97 | */ 98 | static int ecryptfs_process_nl_response(struct sk_buff *skb) 99 | { 100 | struct nlmsghdr *nlh = nlmsg_hdr(skb); 101 | struct ecryptfs_message *msg = NLMSG_DATA(nlh); 102 | int rc; 103 | 104 | if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) { 105 | rc = -EINVAL; 106 | ecryptfs_printk(KERN_ERR, "Received netlink message with " 107 | "incorrectly specified data length\n"); 108 | goto out; 109 | } 110 | rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid, 111 | NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq); 112 | if (rc) 113 | printk(KERN_ERR 114 | "Error processing response message; rc = [%d]\n", rc); 115 | out: 116 | return rc; 117 | } 118 | 119 | /** 120 | * ecryptfs_process_nl_helo 121 | * @skb: The socket buffer containing the nlmsghdr in HELO state 122 | * 123 | * Gets uid and pid of the skb and adds the values to the daemon id 124 | * hash. Returns zero after adding a new daemon id to the hash list; 125 | * non-zero otherwise. 126 | */ 127 | static int ecryptfs_process_nl_helo(struct sk_buff *skb) 128 | { 129 | int rc; 130 | 131 | rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK, 132 | NETLINK_CREDS(skb)->uid, 133 | NETLINK_CREDS(skb)->pid); 134 | if (rc) 135 | printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc); 136 | return rc; 137 | } 138 | 139 | /** 140 | * ecryptfs_process_nl_quit 141 | * @skb: The socket buffer containing the nlmsghdr in QUIT state 142 | * 143 | * Gets uid and pid of the skb and deletes the corresponding daemon 144 | * id, if it is the registered that is requesting the 145 | * deletion. Returns zero after deleting the desired daemon id; 146 | * non-zero otherwise. 147 | */ 148 | static int ecryptfs_process_nl_quit(struct sk_buff *skb) 149 | { 150 | int rc; 151 | 152 | rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid, 153 | NETLINK_CREDS(skb)->pid); 154 | if (rc) 155 | printk(KERN_WARNING 156 | "Error processing QUIT message; rc = [%d]\n", rc); 157 | return rc; 158 | } 159 | 160 | /** 161 | * ecryptfs_receive_nl_message 162 | * 163 | * Callback function called by netlink system when a message arrives. 164 | * If the message looks to be valid, then an attempt is made to assign 165 | * it to its desired netlink context element and wake up the process 166 | * that is waiting for a response. 167 | */ 168 | static void ecryptfs_receive_nl_message(struct sk_buff *skb) 169 | { 170 | struct nlmsghdr *nlh; 171 | 172 | nlh = nlmsg_hdr(skb); 173 | if (!NLMSG_OK(nlh, skb->len)) { 174 | ecryptfs_printk(KERN_ERR, "Received corrupt netlink " 175 | "message\n"); 176 | goto free; 177 | } 178 | switch (nlh->nlmsg_type) { 179 | case ECRYPTFS_NLMSG_RESPONSE: 180 | if (ecryptfs_process_nl_response(skb)) { 181 | ecryptfs_printk(KERN_WARNING, "Failed to " 182 | "deliver netlink response to " 183 | "requesting operation\n"); 184 | } 185 | break; 186 | case ECRYPTFS_NLMSG_HELO: 187 | if (ecryptfs_process_nl_helo(skb)) { 188 | ecryptfs_printk(KERN_WARNING, "Failed to " 189 | "fulfill HELO request\n"); 190 | } 191 | break; 192 | case ECRYPTFS_NLMSG_QUIT: 193 | if (ecryptfs_process_nl_quit(skb)) { 194 | ecryptfs_printk(KERN_WARNING, "Failed to " 195 | "fulfill QUIT request\n"); 196 | } 197 | break; 198 | default: 199 | ecryptfs_printk(KERN_WARNING, "Dropping netlink " 200 | "message of unrecognized type [%d]\n", 201 | nlh->nlmsg_type); 202 | break; 203 | } 204 | free: 205 | kfree_skb(skb); 206 | } 207 | 208 | /** 209 | * ecryptfs_init_netlink 210 | * 211 | * Initializes the daemon id hash list, netlink context array, and 212 | * necessary locks. Returns zero upon success; non-zero upon error. 213 | */ 214 | int ecryptfs_init_netlink(void) 215 | { 216 | int rc; 217 | 218 | ecryptfs_nl_sock = netlink_kernel_create(&init_net, NETLINK_ECRYPTFS, 0, 219 | ecryptfs_receive_nl_message, 220 | NULL, THIS_MODULE); 221 | if (!ecryptfs_nl_sock) { 222 | rc = -EIO; 223 | ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n"); 224 | goto out; 225 | } 226 | ecryptfs_nl_sock->sk_sndtimeo = ECRYPTFS_DEFAULT_SEND_TIMEOUT; 227 | rc = 0; 228 | out: 229 | return rc; 230 | } 231 | 232 | /** 233 | * ecryptfs_release_netlink 234 | * 235 | * Frees all memory used by the netlink context array and releases the 236 | * netlink socket. 237 | */ 238 | void ecryptfs_release_netlink(void) 239 | { 240 | if (ecryptfs_nl_sock && ecryptfs_nl_sock->sk_socket) 241 | sock_release(ecryptfs_nl_sock->sk_socket); 242 | ecryptfs_nl_sock = NULL; 243 | } 244 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/read_write.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 2007 International Business Machines Corp. 5 | * Author(s): Michael A. Halcrow 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 | * 02111-1307, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include "ecryptfs_kernel.h" 26 | 27 | /** 28 | * ecryptfs_write_lower 29 | * @ecryptfs_inode: The eCryptfs inode 30 | * @data: Data to write 31 | * @offset: Byte offset in the lower file to which to write the data 32 | * @size: Number of bytes from @data to write at @offset in the lower 33 | * file 34 | * 35 | * Write data to the lower file. 36 | * 37 | * Returns zero on success; non-zero on error 38 | */ 39 | int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, 40 | loff_t offset, size_t size) 41 | { 42 | struct ecryptfs_inode_info *inode_info; 43 | ssize_t octets_written; 44 | mm_segment_t fs_save; 45 | int rc = 0; 46 | 47 | inode_info = ecryptfs_inode_to_private(ecryptfs_inode); 48 | mutex_lock(&inode_info->lower_file_mutex); 49 | BUG_ON(!inode_info->lower_file); 50 | inode_info->lower_file->f_pos = offset; 51 | fs_save = get_fs(); 52 | set_fs(get_ds()); 53 | octets_written = vfs_write(inode_info->lower_file, data, size, 54 | &inode_info->lower_file->f_pos); 55 | set_fs(fs_save); 56 | if (octets_written < 0) { 57 | printk(KERN_ERR "%s: octets_written = [%td]; " 58 | "expected [%td]\n", __FUNCTION__, octets_written, size); 59 | rc = -EINVAL; 60 | } 61 | mutex_unlock(&inode_info->lower_file_mutex); 62 | mark_inode_dirty_sync(ecryptfs_inode); 63 | return rc; 64 | } 65 | 66 | /** 67 | * ecryptfs_write_lower_page_segment 68 | * @ecryptfs_inode: The eCryptfs inode 69 | * @page_for_lower: The page containing the data to be written to the 70 | * lower file 71 | * @offset_in_page: The offset in the @page_for_lower from which to 72 | * start writing the data 73 | * @size: The amount of data from @page_for_lower to write to the 74 | * lower file 75 | * 76 | * Determines the byte offset in the file for the given page and 77 | * offset within the page, maps the page, and makes the call to write 78 | * the contents of @page_for_lower to the lower inode. 79 | * 80 | * Returns zero on success; non-zero otherwise 81 | */ 82 | int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode, 83 | struct page *page_for_lower, 84 | size_t offset_in_page, size_t size) 85 | { 86 | char *virt; 87 | loff_t offset; 88 | int rc; 89 | 90 | offset = ((((loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT) 91 | + offset_in_page); 92 | virt = kmap(page_for_lower); 93 | rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size); 94 | kunmap(page_for_lower); 95 | return rc; 96 | } 97 | 98 | /** 99 | * ecryptfs_write 100 | * @ecryptfs_file: The eCryptfs file into which to write 101 | * @data: Virtual address where data to write is located 102 | * @offset: Offset in the eCryptfs file at which to begin writing the 103 | * data from @data 104 | * @size: The number of bytes to write from @data 105 | * 106 | * Write an arbitrary amount of data to an arbitrary location in the 107 | * eCryptfs inode page cache. This is done on a page-by-page, and then 108 | * by an extent-by-extent, basis; individual extents are encrypted and 109 | * written to the lower page cache (via VFS writes). This function 110 | * takes care of all the address translation to locations in the lower 111 | * filesystem; it also handles truncate events, writing out zeros 112 | * where necessary. 113 | * 114 | * Returns zero on success; non-zero otherwise 115 | */ 116 | int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset, 117 | size_t size) 118 | { 119 | struct page *ecryptfs_page; 120 | char *ecryptfs_page_virt; 121 | loff_t ecryptfs_file_size = 122 | i_size_read(ecryptfs_file->f_dentry->d_inode); 123 | loff_t data_offset = 0; 124 | loff_t pos; 125 | int rc = 0; 126 | 127 | /* 128 | * if we are writing beyond current size, then start pos 129 | * at the current size - we'll fill in zeros from there. 130 | */ 131 | if (offset > ecryptfs_file_size) 132 | pos = ecryptfs_file_size; 133 | else 134 | pos = offset; 135 | while (pos < (offset + size)) { 136 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); 137 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); 138 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); 139 | size_t total_remaining_bytes = ((offset + size) - pos); 140 | 141 | if (num_bytes > total_remaining_bytes) 142 | num_bytes = total_remaining_bytes; 143 | if (pos < offset) { 144 | /* remaining zeros to write, up to destination offset */ 145 | size_t total_remaining_zeros = (offset - pos); 146 | 147 | if (num_bytes > total_remaining_zeros) 148 | num_bytes = total_remaining_zeros; 149 | } 150 | ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_file, 151 | ecryptfs_page_idx); 152 | if (IS_ERR(ecryptfs_page)) { 153 | rc = PTR_ERR(ecryptfs_page); 154 | printk(KERN_ERR "%s: Error getting page at " 155 | "index [%ld] from eCryptfs inode " 156 | "mapping; rc = [%d]\n", __FUNCTION__, 157 | ecryptfs_page_idx, rc); 158 | goto out; 159 | } 160 | if (start_offset_in_page) { 161 | /* Read in the page from the lower 162 | * into the eCryptfs inode page cache, 163 | * decrypting */ 164 | rc = ecryptfs_decrypt_page(ecryptfs_page); 165 | if (rc) { 166 | printk(KERN_ERR "%s: Error decrypting " 167 | "page; rc = [%d]\n", 168 | __FUNCTION__, rc); 169 | ClearPageUptodate(ecryptfs_page); 170 | page_cache_release(ecryptfs_page); 171 | goto out; 172 | } 173 | } 174 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); 175 | 176 | /* 177 | * pos: where we're now writing, offset: where the request was 178 | * If current pos is before request, we are filling zeros 179 | * If we are at or beyond request, we are writing the *data* 180 | * If we're in a fresh page beyond eof, zero it in either case 181 | */ 182 | if (pos < offset || !start_offset_in_page) { 183 | /* We are extending past the previous end of the file. 184 | * Fill in zero values to the end of the page */ 185 | memset(((char *)ecryptfs_page_virt 186 | + start_offset_in_page), 0, 187 | PAGE_CACHE_SIZE - start_offset_in_page); 188 | } 189 | 190 | /* pos >= offset, we are now writing the data request */ 191 | if (pos >= offset) { 192 | memcpy(((char *)ecryptfs_page_virt 193 | + start_offset_in_page), 194 | (data + data_offset), num_bytes); 195 | data_offset += num_bytes; 196 | } 197 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); 198 | flush_dcache_page(ecryptfs_page); 199 | SetPageUptodate(ecryptfs_page); 200 | unlock_page(ecryptfs_page); 201 | rc = ecryptfs_encrypt_page(ecryptfs_page); 202 | page_cache_release(ecryptfs_page); 203 | if (rc) { 204 | printk(KERN_ERR "%s: Error encrypting " 205 | "page; rc = [%d]\n", __FUNCTION__, rc); 206 | goto out; 207 | } 208 | pos += num_bytes; 209 | } 210 | if ((offset + size) > ecryptfs_file_size) { 211 | i_size_write(ecryptfs_file->f_dentry->d_inode, (offset + size)); 212 | rc = ecryptfs_write_inode_size_to_metadata( 213 | ecryptfs_file->f_dentry->d_inode); 214 | if (rc) { 215 | printk(KERN_ERR "Problem with " 216 | "ecryptfs_write_inode_size_to_metadata; " 217 | "rc = [%d]\n", rc); 218 | goto out; 219 | } 220 | } 221 | out: 222 | return rc; 223 | } 224 | 225 | /** 226 | * ecryptfs_read_lower 227 | * @data: The read data is stored here by this function 228 | * @offset: Byte offset in the lower file from which to read the data 229 | * @size: Number of bytes to read from @offset of the lower file and 230 | * store into @data 231 | * @ecryptfs_inode: The eCryptfs inode 232 | * 233 | * Read @size bytes of data at byte offset @offset from the lower 234 | * inode into memory location @data. 235 | * 236 | * Returns zero on success; non-zero on error 237 | */ 238 | int ecryptfs_read_lower(char *data, loff_t offset, size_t size, 239 | struct inode *ecryptfs_inode) 240 | { 241 | struct ecryptfs_inode_info *inode_info = 242 | ecryptfs_inode_to_private(ecryptfs_inode); 243 | ssize_t octets_read; 244 | mm_segment_t fs_save; 245 | int rc = 0; 246 | 247 | mutex_lock(&inode_info->lower_file_mutex); 248 | BUG_ON(!inode_info->lower_file); 249 | inode_info->lower_file->f_pos = offset; 250 | fs_save = get_fs(); 251 | set_fs(get_ds()); 252 | octets_read = vfs_read(inode_info->lower_file, data, size, 253 | &inode_info->lower_file->f_pos); 254 | set_fs(fs_save); 255 | if (octets_read < 0) { 256 | printk(KERN_ERR "%s: octets_read = [%td]; " 257 | "expected [%td]\n", __FUNCTION__, octets_read, size); 258 | rc = -EINVAL; 259 | } 260 | mutex_unlock(&inode_info->lower_file_mutex); 261 | return rc; 262 | } 263 | 264 | /** 265 | * ecryptfs_read_lower_page_segment 266 | * @page_for_ecryptfs: The page into which data for eCryptfs will be 267 | * written 268 | * @offset_in_page: Offset in @page_for_ecryptfs from which to start 269 | * writing 270 | * @size: The number of bytes to write into @page_for_ecryptfs 271 | * @ecryptfs_inode: The eCryptfs inode 272 | * 273 | * Determines the byte offset in the file for the given page and 274 | * offset within the page, maps the page, and makes the call to read 275 | * the contents of @page_for_ecryptfs from the lower inode. 276 | * 277 | * Returns zero on success; non-zero otherwise 278 | */ 279 | int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, 280 | pgoff_t page_index, 281 | size_t offset_in_page, size_t size, 282 | struct inode *ecryptfs_inode) 283 | { 284 | char *virt; 285 | loff_t offset; 286 | int rc; 287 | 288 | offset = ((((loff_t)page_index) << PAGE_CACHE_SHIFT) + offset_in_page); 289 | virt = kmap(page_for_ecryptfs); 290 | rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode); 291 | kunmap(page_for_ecryptfs); 292 | flush_dcache_page(page_for_ecryptfs); 293 | return rc; 294 | } 295 | 296 | /** 297 | * ecryptfs_read 298 | * @data: The virtual address into which to write the data read (and 299 | * possibly decrypted) from the lower file 300 | * @offset: The offset in the decrypted view of the file from which to 301 | * read into @data 302 | * @size: The number of bytes to read into @data 303 | * @ecryptfs_file: The eCryptfs file from which to read 304 | * 305 | * Read an arbitrary amount of data from an arbitrary location in the 306 | * eCryptfs page cache. This is done on an extent-by-extent basis; 307 | * individual extents are decrypted and read from the lower page 308 | * cache (via VFS reads). This function takes care of all the 309 | * address translation to locations in the lower filesystem. 310 | * 311 | * Returns zero on success; non-zero otherwise 312 | */ 313 | int ecryptfs_read(char *data, loff_t offset, size_t size, 314 | struct file *ecryptfs_file) 315 | { 316 | struct page *ecryptfs_page; 317 | char *ecryptfs_page_virt; 318 | loff_t ecryptfs_file_size = 319 | i_size_read(ecryptfs_file->f_dentry->d_inode); 320 | loff_t data_offset = 0; 321 | loff_t pos; 322 | int rc = 0; 323 | 324 | if ((offset + size) > ecryptfs_file_size) { 325 | rc = -EINVAL; 326 | printk(KERN_ERR "%s: Attempt to read data past the end of the " 327 | "file; offset = [%lld]; size = [%td]; " 328 | "ecryptfs_file_size = [%lld]\n", 329 | __FUNCTION__, offset, size, ecryptfs_file_size); 330 | goto out; 331 | } 332 | pos = offset; 333 | while (pos < (offset + size)) { 334 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); 335 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); 336 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); 337 | size_t total_remaining_bytes = ((offset + size) - pos); 338 | 339 | if (num_bytes > total_remaining_bytes) 340 | num_bytes = total_remaining_bytes; 341 | ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_file, 342 | ecryptfs_page_idx); 343 | if (IS_ERR(ecryptfs_page)) { 344 | rc = PTR_ERR(ecryptfs_page); 345 | printk(KERN_ERR "%s: Error getting page at " 346 | "index [%ld] from eCryptfs inode " 347 | "mapping; rc = [%d]\n", __FUNCTION__, 348 | ecryptfs_page_idx, rc); 349 | goto out; 350 | } 351 | rc = ecryptfs_decrypt_page(ecryptfs_page); 352 | if (rc) { 353 | printk(KERN_ERR "%s: Error decrypting " 354 | "page; rc = [%d]\n", __FUNCTION__, rc); 355 | ClearPageUptodate(ecryptfs_page); 356 | page_cache_release(ecryptfs_page); 357 | goto out; 358 | } 359 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); 360 | memcpy((data + data_offset), 361 | ((char *)ecryptfs_page_virt + start_offset_in_page), 362 | num_bytes); 363 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); 364 | flush_dcache_page(ecryptfs_page); 365 | SetPageUptodate(ecryptfs_page); 366 | unlock_page(ecryptfs_page); 367 | page_cache_release(ecryptfs_page); 368 | pos += num_bytes; 369 | data_offset += num_bytes; 370 | } 371 | out: 372 | return rc; 373 | } 374 | -------------------------------------------------------------------------------- /Source Code/ecryptfs_2_6_24+hmac_patch/super.c: -------------------------------------------------------------------------------- 1 | /** 2 | * eCryptfs: Linux filesystem encryption layer 3 | * 4 | * Copyright (C) 1997-2003 Erez Zadok 5 | * Copyright (C) 2001-2003 Stony Brook University 6 | * Copyright (C) 2004-2006 International Business Machines Corp. 7 | * Author(s): Michael A. Halcrow 8 | * Michael C. Thompson 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License as 12 | * published by the Free Software Foundation; either version 2 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, but 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | * General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 23 | * 02111-1307, USA. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "ecryptfs_kernel.h" 33 | 34 | struct kmem_cache *ecryptfs_inode_info_cache; 35 | 36 | /** 37 | * ecryptfs_alloc_inode - allocate an ecryptfs inode 38 | * @sb: Pointer to the ecryptfs super block 39 | * 40 | * Called to bring an inode into existence. 41 | * 42 | * Only handle allocation, setting up structures should be done in 43 | * ecryptfs_read_inode. This is because the kernel, between now and 44 | * then, will 0 out the private data pointer. 45 | * 46 | * Returns a pointer to a newly allocated inode, NULL otherwise 47 | */ 48 | static struct inode *ecryptfs_alloc_inode(struct super_block *sb) 49 | { 50 | struct ecryptfs_inode_info *inode_info; 51 | struct inode *inode = NULL; 52 | 53 | inode_info = kmem_cache_alloc(ecryptfs_inode_info_cache, GFP_KERNEL); 54 | if (unlikely(!inode_info)) 55 | goto out; 56 | ecryptfs_init_crypt_stat(&inode_info->crypt_stat); 57 | mutex_init(&inode_info->lower_file_mutex); 58 | inode_info->lower_file = NULL; 59 | inode = &inode_info->vfs_inode; 60 | out: 61 | return inode; 62 | } 63 | 64 | /** 65 | * ecryptfs_destroy_inode 66 | * @inode: The ecryptfs inode 67 | * 68 | * This is used during the final destruction of the inode. All 69 | * allocation of memory related to the inode, including allocated 70 | * memory in the crypt_stat struct, will be released here. This 71 | * function also fput()'s the persistent file for the lower inode. 72 | * There should be no chance that this deallocation will be missed. 73 | */ 74 | static void ecryptfs_destroy_inode(struct inode *inode) 75 | { 76 | struct ecryptfs_inode_info *inode_info; 77 | 78 | inode_info = ecryptfs_inode_to_private(inode); 79 | mutex_lock(&inode_info->lower_file_mutex); 80 | if (inode_info->lower_file) { 81 | struct dentry *lower_dentry = 82 | inode_info->lower_file->f_dentry; 83 | 84 | BUG_ON(!lower_dentry); 85 | if (lower_dentry->d_inode) { 86 | fput(inode_info->lower_file); 87 | inode_info->lower_file = NULL; 88 | d_drop(lower_dentry); 89 | } 90 | } 91 | mutex_unlock(&inode_info->lower_file_mutex); 92 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); 93 | kmem_cache_free(ecryptfs_inode_info_cache, inode_info); 94 | } 95 | 96 | /** 97 | * ecryptfs_init_inode 98 | * @inode: The ecryptfs inode 99 | * 100 | * Set up the ecryptfs inode. 101 | */ 102 | void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode) 103 | { 104 | ecryptfs_set_inode_lower(inode, lower_inode); 105 | inode->i_ino = lower_inode->i_ino; 106 | inode->i_version++; 107 | inode->i_op = &ecryptfs_main_iops; 108 | inode->i_fop = &ecryptfs_main_fops; 109 | inode->i_mapping->a_ops = &ecryptfs_aops; 110 | } 111 | 112 | /** 113 | * ecryptfs_put_super 114 | * @sb: Pointer to the ecryptfs super block 115 | * 116 | * Final actions when unmounting a file system. 117 | * This will handle deallocation and release of our private data. 118 | */ 119 | static void ecryptfs_put_super(struct super_block *sb) 120 | { 121 | struct ecryptfs_sb_info *sb_info = ecryptfs_superblock_to_private(sb); 122 | 123 | ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat); 124 | kmem_cache_free(ecryptfs_sb_info_cache, sb_info); 125 | ecryptfs_set_superblock_private(sb, NULL); 126 | } 127 | 128 | /** 129 | * ecryptfs_statfs 130 | * @sb: The ecryptfs super block 131 | * @buf: The struct kstatfs to fill in with stats 132 | * 133 | * Get the filesystem statistics. Currently, we let this pass right through 134 | * to the lower filesystem and take no action ourselves. 135 | */ 136 | static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) 137 | { 138 | return vfs_statfs(ecryptfs_dentry_to_lower(dentry), buf); 139 | } 140 | 141 | /** 142 | * ecryptfs_clear_inode 143 | * @inode - The ecryptfs inode 144 | * 145 | * Called by iput() when the inode reference count reached zero 146 | * and the inode is not hashed anywhere. Used to clear anything 147 | * that needs to be, before the inode is completely destroyed and put 148 | * on the inode free list. We use this to drop out reference to the 149 | * lower inode. 150 | */ 151 | static void ecryptfs_clear_inode(struct inode *inode) 152 | { 153 | iput(ecryptfs_inode_to_lower(inode)); 154 | } 155 | 156 | /** 157 | * ecryptfs_show_options 158 | * 159 | * Prints the directory we are currently mounted over. 160 | * Returns zero on success; non-zero otherwise 161 | */ 162 | static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt) 163 | { 164 | struct super_block *sb = mnt->mnt_sb; 165 | struct dentry *lower_root_dentry = ecryptfs_dentry_to_lower(sb->s_root); 166 | struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(sb->s_root); 167 | char *tmp_page; 168 | char *path; 169 | int rc = 0; 170 | 171 | tmp_page = (char *)__get_free_page(GFP_KERNEL); 172 | if (!tmp_page) { 173 | rc = -ENOMEM; 174 | goto out; 175 | } 176 | path = d_path(lower_root_dentry, lower_mnt, tmp_page, PAGE_SIZE); 177 | if (IS_ERR(path)) { 178 | rc = PTR_ERR(path); 179 | goto out; 180 | } 181 | seq_printf(m, ",dir=%s", path); 182 | free_page((unsigned long)tmp_page); 183 | out: 184 | return rc; 185 | } 186 | 187 | const struct super_operations ecryptfs_sops = { 188 | .alloc_inode = ecryptfs_alloc_inode, 189 | .destroy_inode = ecryptfs_destroy_inode, 190 | .drop_inode = generic_delete_inode, 191 | .put_super = ecryptfs_put_super, 192 | .statfs = ecryptfs_statfs, 193 | .remount_fs = NULL, 194 | .clear_inode = ecryptfs_clear_inode, 195 | .show_options = ecryptfs_show_options 196 | }; 197 | -------------------------------------------------------------------------------- /ecryptfs-creat调试.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/ecryptfs-creat调试.docx -------------------------------------------------------------------------------- /ecryptfs_write_lower()调试.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonXing/eCryptfs/cbbe09801e680d2684c2c41ceec5787c8fee600a/ecryptfs_write_lower()调试.docx --------------------------------------------------------------------------------