martes, 19 de mayo de 2015

Building ecryptfs on Red Hat 7




Ecryptfs is NO LONGER SUPPORTED at Redhat 7.X

Anyway you can try this for fun!


Previous steps of this blog are described at this other blog:  Build a Red Hat 7 custom kernel

1. rhel7 has ecryptfs disabled in the config file, although the ecryptfs source code still in the kernel source directories structure.

# cat /boot/config-3.10.0-229.el7.x86_64 | grep ECRYPT
# CONFIG_ECRYPT_FS is not set
[root@localhost linux-3.10.0-229.1.2.el7]# md5sum fs/ecryptfs/*
b0b2198fb0d9a5b63203d014e436c12a fs/ecryptfs/crypto.c
10b5b2afb477d645a976ed5a425db6e5 fs/ecryptfs/debug.c
d93cc9c2bebf8d365c3295e410c8cc28 fs/ecryptfs/dentry.c
42ec82030d5e6688f55d961a3eaab962 fs/ecryptfs/ecryptfs_kernel.h
58614e45ce41110a15293eb7281a6825 fs/ecryptfs/file.c
96c2f720c685370e428c2cf0c6ef9956 fs/ecryptfs/inode.c
b491875a59037880dbb3869d73414902 fs/ecryptfs/Kconfig
583a15f5c15e51d59f3c9e6075144dcc fs/ecryptfs/keystore.c
720d1880946744a22f4661afc558a58f fs/ecryptfs/kthread.c
7d02e53411da2344f32d2cbaef87f38f fs/ecryptfs/main.c
f6306e09d0870d78453baeaf06192dd3 fs/ecryptfs/Makefile
7014db803b5b251fef4ff8b0a5b1231f fs/ecryptfs/messaging.c
9199e6035ca61f5b49920215a9c71e78 fs/ecryptfs/miscdev.c
96690eaf5e6e04c88bcb20537fe2b7bf fs/ecryptfs/mmap.c
4d17c980ac64d11ce54cba87c63843d2 fs/ecryptfs/read_write.c
3dda1f0792415e03f9031387fd5b6b66 fs/ecryptfs/super.c

[root@localhost linux-3.10.0-229.1.2.el7]# cat /etc/redhat-release 
Red Hat Enterprise Linux Server release 7.1 (Maipo)

[root@localhost linux-3.10.0-229.1.2.el7]# uname -r
3.10.0-229.el7.x86_64

[root@localhost linux-3.10.0-229.1.2.el7]# pwd
/root/rpmbuild/SOURCES/linux/linux-3.10.0-229.1.2.el7


2. Rhel7 has ecryptfs disabled by default

r7_ecrypt.png

3. After enabling ecryptfs using "#make menuconfig" and trying to compile the kernel follow error is received:

[root@localhost linux-3.10.0-229.1.2.el7]# make
scripts/kconfig/conf --silentoldconfig Kconfig
make[1]: Nothing to be done for `all'.
make[1]: Nothing to be done for `relocs'.
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `arch/x86/purgatory/kexec-purgatory.c' is up to date.
CALL scripts/checksyscalls.sh
CC scripts/mod/devicetable-offsets.s
GEN scripts/mod/devicetable-offsets.h
HOSTCC scripts/mod/file2alias.o
HOSTLD scripts/mod/modpost
CHK include/generated/compile.h
make[3]: `arch/x86/realmode/rm/realmode.bin' is up to date.
CERTS kernel/x509_certificate_list
- Including cert /root/rpmbuild/SOURCES/linux/linux-3.10.0-229.1.2.el7/signing_key.x509
AS kernel/system_certificates.o
LD kernel/built-in.o
LD fs/ecryptfs/built-in.o
CC [M] fs/ecryptfs/dentry.o
CC [M] fs/ecryptfs/file.o
CC [M] fs/ecryptfs/inode.o
CC [M] fs/ecryptfs/main.o
fs/ecryptfs/main.c: In function ‘ecryptfs_mount’:
fs/ecryptfs/main.c:570:3: error: ‘struct super_block’ has no member named ‘s_stack_depth’
s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
^
fs/ecryptfs/main.c:570:38: error: ‘struct super_block’ has no member named ‘s_stack_depth’
s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
^
fs/ecryptfs/main.c:573:7: error: ‘struct super_block’ has no member named ‘s_stack_depth’
if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
^
make[2]: *** [fs/ecryptfs/main.o] Error 1
make[1]: *** [fs/ecryptfs] Error 2
make: *** [fs] Error 2
[root@localhost linux-3.10.0-229.1.2.el7]#



4. s_stack_depth is handled differently at redhat 7 and it is part of a new structure called super_block_wrapper

struct super_block {s_stack_depth
struct list_head s_list; /* Keep this first */
dev_t s_dev; /* search index; _not_ kdev_t */
unsigned char s_blocksize_bits;
unsigned long s_blocksize;
loff_t s_maxbytes; /* Max file size */
struct file_system_type *s_type;
const struct super_operations *s_op;
const struct dquot_operations *dq_op;
const struct quotactl_ops *s_qcop;
const struct export_operations *s_export_op;
unsigned long s_flags;
unsigned long s_magic;
struct dentry *s_root;
struct rw_semaphore s_umount;
int s_count;
atomic_t s_active;
#ifdef CONFIG_SECURITY
void *s_security;
#endif
const struct xattr_handler **s_xattr;
struct list_head s_inodes; /* all inodes */
struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */
#ifdef __GENKSYMS__
#ifdef CONFIG_SMP
struct list_head __percpu *s_files;
#else
struct list_head s_files;
#endif
#else
#ifdef CONFIG_SMP
struct list_head __percpu *s_files_deprecated;
#else
struct list_head s_files_deprecated;
#endif
#endif
struct list_head s_mounts; /* list of mounts; _not_ for fs use */
/* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */
struct list_head s_dentry_lru; /* unused dentry lru */
int s_nr_dentry_unused; /* # of dentry on lru */
/* s_inode_lru_lock protects s_inode_lru and s_nr_inodes_unused */
spinlock_t s_inode_lru_lock ____cacheline_aligned_in_smp;
struct list_head s_inode_lru; /* unused inode lru */
int s_nr_inodes_unused; /* # of inodes on lru */
struct block_device *s_bdev;
struct backing_dev_info *s_bdi;
struct mtd_info *s_mtd;
struct hlist_node s_instances;
struct quota_info s_dquot; /* Diskquota specific options */
struct sb_writers s_writers;
char s_id[32]; /* Informational name */
u8 s_uuid[16]; /* UUID */
void *s_fs_info; /* Filesystem private info */
unsigned int s_max_links;
fmode_t s_mode;
/* Granularity of c/m/atime in ns.
Cannot be worse than a second */
u32 s_time_gran;
/*
* The next field is for VFS *only*. No filesystems have any business
* even looking at it. You had been warned.
*/
struct mutex s_vfs_rename_mutex; /* Kludge */
/*
* Filesystem subtype. If non-empty the filesystem type field
* in /proc/mounts will be "type.subtype"
*/
/*
* Saved mount options for lazy filesystems using
* generic_show_options()
*/
char __rcu *s_options;
const struct dentry_operations *s_d_op; /* default d_op for dentries */
/*
* Saved pool identifier for cleancache (-1 means none)
*/
int cleancache_poolid;
struct shrinker s_shrink; /* per-sb shrinker handle */
/* Number of inodes with nlink == 0 but still referenced */
atomic_long_t s_remove_count;
/* Being remounted read-only */
int s_readonly_remount;
};

extern const unsigned super_block_wrapper_version;
struct super_block_wrapper {
struct super_block sb;
/* -- Wrapper version 0 -- */s_stack_depth is handled differently at redhat 7 and it is part of a new structure called super_block_wrapper
struct super_block {s_stack_depth
struct list_head s_list; /* Keep this first */
dev_t s_dev; /* search index; _not_ kdev_t */
unsigned char s_blocksize_bits;
unsigned long s_blocksize;
loff_t s_maxbytes; /* Max file size */
struct file_system_type *s_type;
const struct super_operations *s_op;
const struct dquot_operations *dq_op;
const struct quotactl_ops *s_qcop;
const struct export_operations *s_export_op;
unsigned long s_flags;
unsigned long s_magic;
struct dentry *s_root;
struct rw_semaphore s_umount;
int s_count;
atomic_t s_active;
#ifdef CONFIG_SECURITY
void *s_security;
#endif
const struct xattr_handler **s_xattr;
struct list_head s_inodes; /* all inodes */
struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */
#ifdef __GENKSYMS__
#ifdef CONFIG_SMP
struct list_head __percpu *s_files;
#else
struct list_head s_files;
#endif
#else

/*
* Indicates how deep in a filesystem stack this SB is
*/
int s_stack_depth;regressoin
/* -- Wrapper version 1 -- */
};
static inline struct super_block_wrapper *get_sb_wrapper(struct super_block *sb,
unsigned version)
{
/* Make sure we get a link failure if this function is used against an
* older kernel that doesn't have the superblock wrapper.
*/
if (super_block_wrapper_version < version)
return NULL;
return container_of(sb, struct super_block_wrapper, sb);
}
static inline int *get_s_stack_depth(struct super_block *sb)
{
struct super_block_wrapper *wrapper = get_sb_wrapper(sb, 0);
return wrapper ? &wrapper->s_stack_depth : NULL;
}


5. To fix ecryptfs and build it in the kernel follow is the partial fix:
This is a fix that will not be proposed to upstream cause it is not compatible with other kernels; instead it is a patch to make ecryptfs work on Rhel7 only.

See the commented lines and the next one to it with the fix:
First declare an int pointer at the beginning of the function
static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data)
int *s_stack_depth;

s->s_magic = ECRYPTFS_SUPER_MAGIC;
//s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
s_stack_depth = get_s_stack_depth(path.dentry->d_sb);
rc = -EINVAL;
//if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
if ( *s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
pr_err("eCryptfs: maximum fs stacking depth exceeded\n");
goto out_free;
}

then you can execute the #make
[root@localhost linux-3.10.0-229.1.2.el7]# make
make[1]: Nothing to be done for `all'.
make[1]: Nothing to be done for `relocs'.
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `arch/x86/purgatory/kexec-purgatory.c' is up to date.
CALL scripts/checksyscalls.sh
CC scripts/mod/devicetable-offsets.s
GEN scripts/mod/devicetable-offsets.h
HOSTCC scripts/mod/file2alias.o
HOSTLD scripts/mod/modpost
CHK include/generated/compile.h
make[3]: `arch/x86/realmode/rm/realmode.bin' is up to date.
CC [M] fs/ecryptfs/main.o
LD [M] fs/ecryptfs/ecryptfs.o
CHK include/generated/uapi/linux/version.h
make[2]: Nothing to be done for `all'.
make[2]: Nothing to be done for `relocs'.
TEST posttest
Succeed: decoded and checked 1636136 instructions
TEST posttest
arch/x86/tools/insn_sanity: Success: decoded and checked 1000000 random instructions with 0 errors (seed:0x734ad41f)
Kernel: arch/x86/boot/bzImage is ready (#2)
Building modules, stage 2.
MODPOST 2186 modules
CC fs/ecryptfs/ecryptfs.mod.o
LD [M] fs/ecryptfs/ecryptfs.ko
[root@localhost linux-3.10.0-229.1.2.el7]# make modules
make[1]: Nothing to be done for `all'.
make[1]: Nothing to be done for `relocs'.
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `arch/x86/purgatory/kexec-purgatory.c' is up to date.
CALL scripts/checksyscalls.sh
CC scripts/mod/devicetable-offsets.s
GEN scripts/mod/devicetable-offsets.h
HOSTCC scripts/mod/file2alias.o
HOSTLD scripts/mod/modpost
Building modules, stage 2. 
MODPOST 2183 modules
[root@localhost linux-3.10.0-229.1.2.el7]#


6. After reviewing the modinfo and loading the module with insmod, there are some error messags on the dmesg:

# modinfo /root/rpmbuild/SOURCES/linux-3.10.0-229.1.2.el7/fs/ecryptfs/ecryptfs.ko
filename: /root/rpmbuild/SOURCES/linux-3.10.0-229.1.2.el7/fs/ecryptfs/ecryptfs.ko
license: GPL
description: eCryptfs
author: Michael A. Halcrow <mhalcrow@us.ibm.com>
alias: fs-ecryptfs
rhelversion: 7.1
srcversion: EE0A8CEA8D02FDE3FB63A2B
depends: 
intree: Y
vermagic: 3.10.0 SMP mod_unload modversions 
parm: ecryptfs_verbosity:Initial verbosity level (0 or 1; defaults to 0, which is Quiet) (int)
parm: ecryptfs_message_buf_len:Number of message buffer elements (uint)
parm: ecryptfs_message_wait_timeout:Maximum number of seconds that an operation will sleep while waiting for a message response from userspace (long)
parm: ecryptfs_number_of_users:An estimate of the number of concurrent users of eCryptfs (uint)

# insmod /root/rpmbuild/SOURCES/linux-3.10.0-229.1.2.el7/fs/ecryptfs/ecryptfs.ko
# lsmod | grep ecr
ecryptfs 85424 0

dmesg:
[61759.528990] ecryptfs: no symbol version for module_layout
[65012.599355] ecryptfs: module verification failed: signature and/or required key missing - tainting kernel

# mount -t ecryptfs /mnt/t1 /mnt/t1
mount: wrong fs type, bad option, bad superblock on /mnt/t1,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so.
The mount fails with a -22 error. wrong parameters:

[65575.109585] Error parsing options; rc = [-22]

7. Now we need to install ecryptfs utils and its dependencies:

# wget http://sourceforge.net/projects/ecryptfs/files/latest/download?source=files
# mv download\?source\=files ecryptfs-utils-61.tar.gz
# tar -xvf ecryptfs-utils-61.tar.gz 
# cd ecryptfs-utils-61
# yum install libgcrypt -y
# yum install libgcrypt-devel -y
# yum install keyutils -y
# yum install keyutils-devel -y
# yum install keyutils-libs -y
# yum install keyutils-libs-devel -y
# yum install pam
# yum install pam-devel -y
# ./configure 
# ./configure --prefix=/usr
# make
# make install
#ldconfig
# setenforce 0

then try:

[root@localhost ecryptfs-utils-61]# mount -t ecryptfs /mnt/t1 /mnt/t1
Passphrase: 
Select cipher: regressoin
1) aes: blocksize = 16; min keysize = 16; max keysize = 32 (loaded)
2) des3_ede: blocksize = 8; min keysize = 24; max keysize = 24 (not loaded)
Selection [aes]: 
Select key bytes: 
1) 16
2) 32
3) 24
Selection [16]: 
Enable plaintext passthrough (y/n) [n]: 
Enable filename encryption (y/n) [n]: 
Attempting to mount with the following options:
ecryptfs_key_bytes=16
ecryptfs_cipher=aes
Error mounting eCryptfs; rc = [-22]; strerr = [Invalid argument]. Check your system logs; visit <http://ecryptfs.sourceforge.net/ecryptfs-faq.html>.
ecryptfs_sig=5143317d91ad1a8f

Although there is an error, ecryptfs can be mounted and a basic regression test works.

[root@localhost ecryptfs-utils-61]# mount
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=499292k,nr_inodes=124823,mode=755)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,seclabel)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,seclabel,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,seclabel,mode=755)
tmpfs on /sys/fs/cgroup type tmpfs (rw,nosuid,nodev,noexec,seclabel,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
configfs on /sys/kernel/config type configfs (rw,relatime)
/dev/mapper/rhel-root on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
selinuxfs on /sys/fs/selinux type selinuxfs (rw,relatime)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=33,pgrp=1,timeout=300,minproto=5,maxproto=5,direct)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,seclabel)
mqueue on /dev/mqueue type mqueue (rw,relatime,seclabel)
/dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
/mnt/t1 on /mnt/t1 type ecryptfs (rw,relatime,ecryptfs_sig=5143317d91ad1a8f,ecryptfs_cipher=aes,ecryptfs_key_bytes=16)

[root@localhost ecryptfs-utils-61]# vi /mnt/t1/file.txt

[root@localhost ecryptfs-utils-61]# cat /mnt/t1/file.txt 
This is the content file

[root@localhost ecryptfs-utils-61]# umount /mnt/t1

[root@localhost ecryptfs-utils-61]# cat /mnt/t1/file.txt
��A�)���"3DUfw`����e�� ���

8. warnings on the dmesg:
[260412.494550] Mount on filesystem of type eCryptfs explicitly disallowed due to known incompatibilities
[260412.508406] Reading sb failed; rc = [-22]
[root@localhost ~]#


There are still some warnings that need to be fixed, however a quick ecryptfs regression test works as described in step7.


Enjoy!
P.S.  This should be the official ecryptfs flag

1 comentario: