diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 71d79f7df..efeccf1c3 100755 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1637,68 +1637,6 @@ config SYSVIPC_COMPAT def_bool y depends on COMPAT && SYSVIPC -menu "Hypervisor" -config UH - bool "Enable micro hypervisor feature" - depends on !SEC_FACTORY - default n - help - enables a micro hypervisor. - It's samsung's hypervisor. - RKP and etc can be loaded on it. - please check a memory map for it. - -config RKP - bool "Enable RKP(Realtime Kernel Protection) feature" - depends on UH - default n - help - protects a kernel text and etc. - -config KDP - bool "Enable KDP(Kernel Data Protection) feature" - depends on !SEC_VTS_TEST - depends on UH - select KDP_CRED - select KDP_NS - default n - help - Prevents unauthorized cred modification, - namespace modification, mapping for page table. - -config KDP_CRED - bool "Enable KDP(Kernel Data Protection) cred feature" - depends on !SEC_VTS_TEST - depends on KDP - default n - help - Prevents unauthorized cred modification. - -config KDP_NS - bool "Enable KDP(Kernel Data Protection) namespace feature" - depends on !SEC_VTS_TEST - depends on KDP - default n - help - Prevents unauthorized namespace modification, mapping for page table. - -config RKP_TEST - bool "Enable RKP test" - depends on !SAMSUNG_PRODUCT_SHIP && RKP - default n - help - enables RKP test. - -config KDP_TEST - bool "Enable KDP test" - depends on !SAMSUNG_PRODUCT_SHIP && KDP - depends on KDP - default n - help - enables KDP test. - -endmenu - menu "Power management options" source "kernel/power/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index adb762d8a..eb550499b 100755 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -196,9 +196,6 @@ obj-$(CONFIG_SENSORS_SSC) += sensors/ obj-$(CONFIG_ADSP_FACTORY) += adsp_factory/ obj-y += switch/ -# FastuH -obj-$(CONFIG_UH) += uh/ - # SPU signature verify obj-$(CONFIG_SPU_VERIFY) += spu_verify/ diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 0ed0cc2a2..d2ddef5b9 100755 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -74,18 +74,6 @@ #include #include #include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { -#include -#include -#include -#include -#include - -#define META_MARK_BASE_LOWER 100 -#define META_MARK_BASE_UPPER 500 - -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } - #include #include #include @@ -143,28 +131,6 @@ do { \ #define GOODCOPY_LEN 128 -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { -/* The KNOX framework marks packets intended to a VPN client for special processing differently. - * The marked packets hit special IP table rules and are routed back to user space using the TUN driver - * for policy based treatment by the VPN client. - * Some VPN clients can make more intelligent decisions based on the UID/PID information. - * For such clients, we mark packets to be in the range >= META_MARK_BASE_LOWER and < META_MARK_BASE_UPPER. - * When such packets are seen, we update the IP headers to carry UID/PID information - * in the IP options - all other packets are ignored. - * Also, see the comments above the individual steps taken in the code for details - */ - -/* Metadata header structure */ - -struct knox_meta_param { - uid_t uid; - pid_t pid; -}; - -#define TUN_META_HDR_SZ sizeof(struct knox_meta_param) -#define TUN_META_MARK_OFFSET offsetof(struct knox_meta_param, uid) -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } - #define FLT_EXACT_COUNT 8 struct tap_filter { unsigned int count; /* Number of addrs. Zero means disabled */ @@ -2037,41 +2003,6 @@ static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from) return result; } -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { -static int get_meta_param_values(struct sk_buff *skb, struct knox_meta_param *metalocal) { - - struct skb_shared_info *knox_shinfo = NULL; - - if (skb != NULL) - knox_shinfo = skb_shinfo(skb); - else { -#ifdef TUN_DEBUG - pr_err("KNOX: NULL SKB in knoxvpn_process_uidpid"); -#endif - return 1; - } - - if (knox_shinfo == NULL) { -#ifdef TUN_DEBUG - pr_err("KNOX: knox_shinfo value is null"); -#endif - return 1; - } - - if (knox_shinfo->knox_mark >= META_MARK_BASE_LOWER && knox_shinfo->knox_mark <= META_MARK_BASE_UPPER) { - metalocal->uid = knox_shinfo->uid; - metalocal->pid = knox_shinfo->pid; - } - - if (knox_shinfo != NULL) { - knox_shinfo->uid = knox_shinfo->pid = 0; - knox_shinfo->knox_mark = 0; - } - - return 0; -} -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } - static ssize_t tun_put_user_xdp(struct tun_struct *tun, struct tun_file *tfile, struct xdp_frame *xdp_frame, @@ -2113,10 +2044,6 @@ static ssize_t tun_put_user(struct tun_struct *tun, struct iov_iter *iter) { struct tun_pi pi = { 0, skb->protocol }; -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - struct knox_meta_param metalocal = { 0, 0 }; - int meta_param_get_status = 0; -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } struct tun_pcpu_stats *stats; ssize_t total; int vlan_offset = 0; @@ -2145,29 +2072,6 @@ static ssize_t tun_put_user(struct tun_struct *tun, return -EFAULT; } -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - meta_param_get_status = get_meta_param_values(skb, &metalocal); - if (meta_param_get_status == 1) { -#ifdef TUN_DEBUG - pr_err("KNOX: Error obtaining meta param values"); -#endif - } else { - - if (tun->flags & TUN_META_HDR) { -#ifdef TUN_DEBUG - pr_err("KNOX: Appending uid: %d and pid: %d", metalocal.uid, - metalocal.pid); -#endif - if (iov_iter_count(iter) < sizeof(struct knox_meta_param)) { - return -EINVAL; - } - - total += sizeof(struct knox_meta_param); - if (copy_to_iter(&metalocal, sizeof(struct knox_meta_param), iter) != sizeof(struct knox_meta_param)) - return -EFAULT; - } - } -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } if (vnet_hdr_sz) { struct virtio_net_hdr gso; @@ -2578,9 +2482,7 @@ static struct proto tun_proto = { static int tun_flags(struct tun_struct *tun) { - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - return tun->flags & (TUN_FEATURES | IFF_PERSIST | IFF_TUN | IFF_TAP | IFF_META_HDR); - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } + return tun->flags & (TUN_FEATURES | IFF_PERSIST | IFF_TUN | IFF_TAP); } static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr, @@ -2782,13 +2684,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) netif_carrier_on(tun->dev); tun_debug(KERN_INFO, tun, "tun_set_iff\n"); - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - if (ifr->ifr_flags & IFF_META_HDR) { - tun->flags |= TUN_META_HDR; - } else { - tun->flags &= ~TUN_META_HDR; - } - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } /* Make sure persistent devices do not get stuck in * xoff state. @@ -2980,11 +2875,6 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, unsigned int ifindex; int le; int ret; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - int knox_flag = 0; - int tun_meta_param; - int tun_meta_value; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } bool do_notify = false; #ifdef CONFIG_ANDROID_PARANOID_NETWORK @@ -3005,11 +2895,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, * This is needed because we never checked for invalid flags on * TUNSETIFF. */ - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - knox_flag |= IFF_META_HDR; - return put_user(IFF_TUN | IFF_TAP | TUN_FEATURES | knox_flag, + return put_user(IFF_TUN | IFF_TAP | TUN_FEATURES, (unsigned int __user*)argp); - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } } else if (cmd == TUNSETQUEUE) { return tun_set_queue(file, &ifr); } else if (cmd == SIOCGSKNS) { @@ -3198,37 +3085,6 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; break; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - case TUNGETMETAPARAM: - - if (copy_from_user(&tun_meta_param, argp, - sizeof(tun_meta_param))) { - ret = -EFAULT; - break; - } - - ret = 0; - switch (tun_meta_param) { - case TUN_GET_META_HDR_SZ: - tun_meta_value = TUN_META_HDR_SZ; - break; - - case TUN_GET_META_MARK_OFFSET: - tun_meta_value = TUN_META_MARK_OFFSET; - break; - - default: - ret = -EINVAL; - break; - } - - if (!ret) { - if (copy_to_user(argp, &tun_meta_value, - sizeof(tun_meta_value))) - ret = -EFAULT; - } - break; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } case TUNSETVNETHDRSZ: if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) { ret = -EFAULT; diff --git a/drivers/uh/Makefile b/drivers/uh/Makefile deleted file mode 100755 index cc21615d7..000000000 --- a/drivers/uh/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -obj-$(CONFIG_UH) += uh_debug_log.o - -# app -obj-$(CONFIG_RKP) += rkp.o -obj-$(CONFIG_KDP) += kdp.o -obj-$(CONFIG_RKP_TEST) += rkp_test.o -obj-$(CONFIG_KDP_TEST) += kdp_test.o diff --git a/drivers/uh/kdp.c b/drivers/uh/kdp.c deleted file mode 100755 index f426826a2..000000000 --- a/drivers/uh/kdp.c +++ /dev/null @@ -1,685 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include <../../fs/mount.h> - -/* security/selinux/include/objsec.h */ -struct task_security_struct { - u32 osid; /* SID prior to last execve */ - u32 sid; /* current SID */ - u32 exec_sid; /* exec SID */ - u32 create_sid; /* fscreate SID */ - u32 keycreate_sid; /* keycreate SID */ - u32 sockcreate_sid; /* fscreate SID */ - void *bp_cred; -}; -/* security/selinux/hooks.c */ -struct task_security_struct init_sec __kdp_ro; - -int kdp_enable __kdp_ro = 0; -static int __check_verifiedboot __kdp_ro = 0; -static int __is_kdp_recovery __kdp_ro = 0; - -#define VERITY_PARAM_LENGTH 20 -static char verifiedbootstate[VERITY_PARAM_LENGTH]; - -#ifdef CONFIG_SAMSUNG_PRODUCT_SHIP -extern int selinux_enforcing __kdp_ro_aligned; -extern int ss_initialized __kdp_ro_aligned; -#endif - -void __init kdp_init(void) -{ - struct kdp_init cred; - memset((void *)&cred, 0, sizeof(kdp_init)); - cred._srodata = (u64)__start_rodata; - cred._erodata = (u64)__end_rodata; -#ifdef CONFIG_KDP - cred.init_mm_pgd = (u64)swapper_pg_dir; -#endif - - cred.credSize = sizeof(struct cred); - cred.sp_size = sizeof(struct task_security_struct); - cred.pgd_mm = offsetof(struct mm_struct,pgd); - cred.uid_cred = offsetof(struct cred,uid); - cred.euid_cred = offsetof(struct cred,euid); - cred.gid_cred = offsetof(struct cred,gid); - cred.egid_cred = offsetof(struct cred,egid); - - cred.bp_pgd_cred = offsetof(struct cred,bp_pgd); - cred.bp_task_cred = offsetof(struct cred,bp_task); - cred.type_cred = offsetof(struct cred,type); - - cred.security_cred = offsetof(struct cred,security); - cred.usage_cred = offsetof(struct cred,use_cnt); - cred.cred_task = offsetof(struct task_struct,cred); - cred.mm_task = offsetof(struct task_struct,mm); - - cred.pid_task = offsetof(struct task_struct,pid); - cred.rp_task = offsetof(struct task_struct,real_parent); - cred.comm_task = offsetof(struct task_struct,comm); - cred.bp_cred_secptr = offsetof(struct task_security_struct,bp_cred); -#ifndef CONFIG_KDP - cred.verifiedbootstate = (u64)verifiedbootstate; -#endif -#ifdef CONFIG_SAMSUNG_PRODUCT_SHIP - cred.selinux.selinux_enforcing_va = (u64)&selinux_enforcing; - cred.selinux.ss_initialized_va = (u64)&ss_initialized; -#else - cred.selinux.selinux_enforcing_va = 0; - cred.selinux.ss_initialized_va = 0; -#endif - uh_call(UH_APP_KDP, KDP_INIT, (u64)&cred, 0, 0, 0); -} - -static int __init verifiedboot_state_setup(char *str) -{ - strlcpy(verifiedbootstate, str, sizeof(verifiedbootstate)); - - if(!strncmp(verifiedbootstate, "orange", sizeof("orange"))) - __check_verifiedboot = 1; - return 0; -} -__setup("androidboot.verifiedbootstate=", verifiedboot_state_setup); - -static int __init boot_recovery(char *str) -{ - int temp = 0; - - if (get_option(&str, &temp)) { - __is_kdp_recovery = temp; - return 0; - } - return -EINVAL; -} -early_param("androidboot.boot_recovery", boot_recovery); - -inline bool is_kdp_kmem_cache(struct kmem_cache *s) -{ - if (s->name && - (!strncmp(s->name, CRED_JAR_RO, strlen(CRED_JAR_RO)) || - !strncmp(s->name, TSEC_JAR, strlen(TSEC_JAR)) || - !strncmp(s->name, VFSMNT_JAR, strlen(VFSMNT_JAR)))) - return true; - else - return false; -} - -#ifdef CONFIG_KDP_CRED -/*------------------------------------------------ - * CRED - *------------------------------------------------*/ -struct kdp_usecnt init_cred_use_cnt = { - .kdp_use_cnt = ATOMIC_INIT(4), - .kdp_rcu_head.non_rcu = 0, - .kdp_rcu_head.bp_cred = (void *)0, - .kdp_rcu_head.reflected_cred = (void *)0, -}; -static struct kmem_cache *cred_jar_ro; -static struct kmem_cache *tsec_jar; -static struct kmem_cache *usecnt_jar; - -/* Dummy constructor to make sure we have separate slabs caches. */ -static void cred_ctor(void *data){} -static void sec_ctor(void *data){} -static void usecnt_ctor(void *data){} - -void __init kdp_cred_init(void) -{ - cred_jar_ro = kmem_cache_create("cred_jar_ro", sizeof(struct cred), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, cred_ctor); - if (!cred_jar_ro) - panic("Unable to create RO Cred cache\n"); - - tsec_jar = kmem_cache_create("tsec_jar", sizeof(struct task_security_struct), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, sec_ctor); - if (!tsec_jar) - panic("Unable to create RO security cache\n"); - - usecnt_jar = kmem_cache_create("usecnt_jar", sizeof(struct kdp_usecnt), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, usecnt_ctor); - if (!usecnt_jar) - panic("Unable to create use count jar\n"); - - uh_call(UH_APP_KDP, JARRO_TSEC_SIZE, (u64)cred_jar_ro->size, (u64)tsec_jar->size, 0, 0); -} - -unsigned int kdp_get_usecount(struct cred *cred) -{ - if (is_kdp_protect_addr((unsigned long )cred)) - return (unsigned int)ROCRED_UC_READ(cred); - else - return atomic_read(&cred->usage); -} - -inline struct cred *get_new_cred(struct cred *cred) -{ - if (is_kdp_protect_addr((unsigned long)cred)) - ROCRED_UC_INC(cred); - else - atomic_inc(&cred->usage); - return cred; -} - -inline void put_cred(const struct cred *_cred) -{ - struct cred *cred = (struct cred *) _cred; - - validate_creds(cred); - - if (is_kdp_protect_addr((unsigned long)cred)) { - if (ROCRED_UC_DEC_AND_TEST(cred)) - __put_cred(cred); - } else { - if (atomic_dec_and_test(&(cred)->usage)) - __put_cred(cred); - } -} - -/* match for kernel/cred.c function */ -inline void set_cred_subscribers(struct cred *cred, int n) -{ -#ifdef CONFIG_DEBUG_CREDENTIALS - atomic_set(&cred->subscribers, n); -#endif -} - -/* Check whether the address belong to Cred Area */ -bool is_kdp_protect_addr(unsigned long addr) -{ - struct kmem_cache *s; - struct page *page; - void *objp = (void *)addr; - - if (!objp) - return false; - - if (!kdp_enable) - return false; - - if ((addr == ((unsigned long)&init_cred)) || - (addr == ((unsigned long)&init_sec))) - return true; - - page = virt_to_head_page(objp); - s = page->slab_cache; - if (s && (s == cred_jar_ro || s == tsec_jar)) - return true; - - return false; -} - -/* We use another function to free protected creds. */ -void put_rocred_rcu(struct rcu_head *rcu) -{ - struct cred *cred = container_of(rcu, struct ro_rcu_head, rcu)->bp_cred; - if (ROCRED_UC_READ(cred) != 0) - panic("RO_CRED: put_rocred_rcu() sees %p with usage %d\n", - cred, ROCRED_UC_READ(cred)); - - security_cred_free(cred); - key_put(cred->session_keyring); - key_put(cred->process_keyring); - key_put(cred->thread_keyring); - key_put(cred->request_key_auth); - if (cred->group_info) - put_group_info(cred->group_info); - free_uid(cred->user); - put_user_ns(cred->user_ns); - if(cred->use_cnt) - kmem_cache_free(usecnt_jar,(void *)cred->use_cnt); - kmem_cache_free(cred_jar_ro, cred); -} - -/* prepare_ro_creds - Prepare a new set of credentials which is protected by KDP */ -struct cred *prepare_ro_creds(struct cred *old, int kdp_cmd, u64 p) -{ - u64 pgd = (u64)(current->mm? current->mm->pgd: swapper_pg_dir); - struct cred *new_ro = NULL; - struct cred_param param_data; - void *use_cnt_ptr = NULL; - void *rcu_ptr = NULL; - void *tsec = NULL; - - new_ro = kmem_cache_alloc(cred_jar_ro, GFP_KERNEL); - if (!new_ro) - panic("[%d] : kmem_cache_alloc() failed", kdp_cmd); - - use_cnt_ptr = kmem_cache_alloc(usecnt_jar, GFP_KERNEL); - if (!use_cnt_ptr) - panic("[%d] : Unable to allocate usage pointer\n", kdp_cmd); - - // get_usecnt_rcu - rcu_ptr = &(((struct kdp_usecnt *)use_cnt_ptr)->kdp_rcu_head); - ((struct ro_rcu_head*)rcu_ptr)->bp_cred = (void *)new_ro; - - tsec = kmem_cache_alloc(tsec_jar, GFP_KERNEL); - if (!tsec) - panic("[%d] : Unable to allocate security pointer\n", kdp_cmd); - - // init - memset((void *)¶m_data, 0, sizeof(struct cred_param)); - param_data.cred = old; - param_data.cred_ro = new_ro; - param_data.use_cnt_ptr = use_cnt_ptr; - param_data.sec_ptr = tsec; - param_data.type = kdp_cmd; - param_data.use_cnt = (u64)p; - - uh_call(UH_APP_KDP, PREPARE_RO_CRED, (u64)¶m_data, (u64)current, 0, 0); - if (kdp_cmd == CMD_COPY_CREDS) { - if ((new_ro->bp_task != (void *)p) || - new_ro->security != tsec || - new_ro->use_cnt != use_cnt_ptr) { - panic("[%d]: KDP Call failed task=0x%lx:0x%lx, sec=0x%lx:0x%lx, usecnt=0x%lx:0x%lx", - kdp_cmd, new_ro->bp_task, (void *)p, - new_ro->security, tsec, new_ro->use_cnt, use_cnt_ptr); - } - } else { - if ((new_ro->bp_task != current) || - (current->mm && new_ro->bp_pgd != (void *)pgd) || - (new_ro->security != tsec) || - (new_ro->use_cnt != use_cnt_ptr)) { - panic("[%d]: KDP Call failed task=0x%lx:0x%lx, sec=0x%lx:0x%lx, usecnt=0x%lx:0x%lx, pgd=0x%lx:0x%lx", - kdp_cmd, new_ro->bp_task, current, new_ro->security, tsec, - new_ro->use_cnt, use_cnt_ptr, new_ro->bp_pgd, (void *)pgd); - } - } - - GET_ROCRED_RCU(new_ro)->non_rcu = old->non_rcu; - GET_ROCRED_RCU(new_ro)->reflected_cred = 0; - ROCRED_UC_SET(new_ro, 2); - - set_cred_subscribers(new_ro, 0); - get_group_info(new_ro->group_info); - get_uid(new_ro->user); - get_user_ns(new_ro->user_ns); - -#ifdef CONFIG_KEYS - key_get(new_ro->session_keyring); - key_get(new_ro->process_keyring); - key_get(new_ro->thread_keyring); - key_get(new_ro->request_key_auth); -#endif - - validate_creds(new_ro); - return new_ro; -} - -/* security/selinux/hooks.c */ -static bool is_kdp_tsec_jar(unsigned long addr) -{ - struct kmem_cache *s; - struct page *page; - void *objp = (void *)addr; - - if (!objp) - return false; - - page = virt_to_head_page(objp); - s = page->slab_cache; - if (s && s == tsec_jar) - return true; - return false; -} - -static inline int chk_invalid_kern_ptr(u64 tsec) -{ - return (((u64)tsec >> 36) != (u64)0xFFFFFFC); -} -void kdp_free_security(unsigned long tsec) -{ - if (!tsec || chk_invalid_kern_ptr(tsec)) - return; - - if (is_kdp_tsec_jar(tsec)) - kmem_cache_free(tsec_jar, (void *)tsec); - else - kfree((void *)tsec); -} - -void kdp_assign_pgd(struct task_struct *p) -{ - u64 pgd = (u64)(p->mm? p->mm->pgd: swapper_pg_dir); - - uh_call(UH_APP_KDP, SET_CRED_PGD, (u64)p->cred, (u64)pgd, 0, 0); -} - -struct task_security_struct init_sec __kdp_ro; -static inline unsigned int cmp_sec_integrity(const struct cred *cred, struct mm_struct *mm) -{ - if (cred->bp_task != current) - printk(KERN_ERR "[KDP] cred->bp_task: 0x%lx, current: 0x%lx\n", - cred->bp_task, current); - - if (mm && (cred->bp_pgd != swapper_pg_dir) && (cred->bp_pgd != mm->pgd )) - printk(KERN_ERR "[KDP] mm: 0x%lx, cred->bp_pgd: 0x%lx, swapper_pg_dir: %p, mm->pgd: 0x%lx\n", - mm, cred->bp_pgd, swapper_pg_dir, mm->pgd, cred->bp_pgd); - - return ((cred->bp_task != current) || - (mm && (!( in_interrupt() || in_softirq())) && - (cred->bp_pgd != swapper_pg_dir) && - (cred->bp_pgd != mm->pgd))); -} - -static inline bool is_kdp_invalid_cred_sp(u64 cred, u64 sec_ptr) -{ - struct task_security_struct *tsec = (struct task_security_struct *)sec_ptr; - u64 cred_size = sizeof(struct cred); - u64 tsec_size = sizeof(struct task_security_struct); - - if((cred == (u64)&init_cred) && (sec_ptr == (u64)&init_sec)) - return false; - - if (!is_kdp_protect_addr(cred) || - !is_kdp_protect_addr(cred + cred_size) || - !is_kdp_protect_addr(sec_ptr) || - !is_kdp_protect_addr(sec_ptr + tsec_size)) { - printk(KERN_ERR, "[KDP] cred: %d, cred + sizeof(cred): %d, sp: %d, sp + sizeof(tsec): %d", - is_kdp_protect_addr(cred), - is_kdp_protect_addr(cred + cred_size), - is_kdp_protect_addr(sec_ptr), - is_kdp_protect_addr(sec_ptr + tsec_size)); - return true; - } - - if ((u64)tsec->bp_cred != cred) { - printk(KERN_ERR, "[KDP] %s: tesc->bp_cred: %lx, cred: %lx\n", - __func__, (u64)tsec->bp_cred, cred); - return true; - } - - return false; -} - -inline int kdp_restrict_fork(struct filename *path) -{ - struct cred *shellcred; - - if (!strcmp(path->name, "/system/bin/patchoat") || - !strcmp(path->name, "/system/bin/idmap2")) { - return 0; - } - - if(KDP_IS_NONROOT(current)) { - shellcred = prepare_creds(); - if (!shellcred) - return 1; - - shellcred->uid.val = 2000; - shellcred->gid.val = 2000; - shellcred->euid.val = 2000; - shellcred->egid.val = 2000; - - commit_creds(shellcred); - } - return 0; -} - -/* This function is related Namespace */ -#ifdef CONFIG_KDP_NS -static unsigned int cmp_ns_integrity(void) -{ - struct mount *root = NULL; - struct nsproxy *nsp = NULL; - - if (in_interrupt() || in_softirq()) - return 0; - - nsp = current->nsproxy; - if (!ns_protect || !nsp || !nsp->mnt_ns) - return 0; - - root = current->nsproxy->mnt_ns->root; - if (root != root->mnt->bp_mount) { - printk(KERN_ERR "[KDP] NameSpace Mismatch %lx != %lx\n nsp: 0x%lx, mnt_ns: 0x%lx\n", - root, root->mnt->bp_mount, nsp, nsp->mnt_ns); - return 1; - } - - return 0; -} -#endif // end CONFIG_KDP_NS - -/* Main function to verify cred security context of a process */ -int security_integrity_current(void) -{ - const struct cred *cur_cred = current_cred(); - rcu_read_lock(); - if (kdp_enable && - (is_kdp_invalid_cred_sp((u64)cur_cred, (u64)cur_cred->security) - || cmp_sec_integrity(cur_cred, current->mm) -#ifdef CONFIG_KDP_NS - || cmp_ns_integrity())) { -#else - )) { -#endif - rcu_read_unlock(); - panic("KDP CRED PROTECTION VIOLATION\n"); - } - rcu_read_unlock(); - return 0; -} -#endif - -#ifdef CONFIG_KDP_NS -/*------------------------------------------------ - * Namespace - *------------------------------------------------*/ -unsigned int ns_protect __kdp_ro = 0; -static int dex2oat_count = 0; -static DEFINE_SPINLOCK(mnt_vfsmnt_lock); - -static struct super_block *rootfs_sb __kdp_ro = NULL; -static struct super_block *sys_sb __kdp_ro = NULL; -static struct super_block *odm_sb __kdp_ro = NULL; -static struct super_block *vendor_sb __kdp_ro = NULL; -static struct super_block *art_sb __kdp_ro = NULL; -static struct super_block *crypt_sb __kdp_ro = NULL; -static struct super_block *dex2oat_sb __kdp_ro = NULL; -static struct super_block *adbd_sb __kdp_ro = NULL; -static struct kmem_cache *vfsmnt_cache __read_mostly; - -void cred_ctor_vfsmount(void *data) -{ - /* Dummy constructor to make sure we have separate slabs caches. */ -} -void __init kdp_mnt_init(void) -{ - struct ns_param nsparam; - - vfsmnt_cache = kmem_cache_create("vfsmnt_cache", sizeof(struct vfsmount), - 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, cred_ctor_vfsmount); - - if (!vfsmnt_cache) - panic("Failed to allocate vfsmnt_cache \n"); - - memset((void *)&nsparam, 0, sizeof(struct ns_param)); - nsparam.ns_buff_size = (u64)vfsmnt_cache->size; - nsparam.ns_size = (u64)sizeof(struct vfsmount); - nsparam.bp_offset = (u64)offsetof(struct vfsmount, bp_mount); - nsparam.sb_offset = (u64)offsetof(struct vfsmount, mnt_sb); - nsparam.flag_offset = (u64)offsetof(struct vfsmount, mnt_flags); - nsparam.data_offset = (u64)offsetof(struct vfsmount, data); - - uh_call(UH_APP_KDP, NS_INIT, (u64)&nsparam, 0, 0, 0); -} - -void __init kdp_init_mount_tree(struct vfsmount *mnt) -{ - if (!rootfs_sb) - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&rootfs_sb, (u64)mnt, KDP_SB_ROOTFS, 0); -} - -bool is_kdp_vfsmnt_cache(unsigned long addr) -{ - static void *objp; - static struct kmem_cache *s; - static struct page *page; - - objp = (void *)addr; - - if (!objp) - return false; - - page = virt_to_head_page(objp); - s = page->slab_cache; - if (s && s == vfsmnt_cache) - return true; - return false; -} - -static int kdp_check_sb_mismatch(struct super_block *sb) -{ - if (__is_kdp_recovery || __check_verifiedboot) - return 0; - - if ((sb != rootfs_sb) && (sb != sys_sb) && (sb != odm_sb) - && (sb != vendor_sb) && (sb != art_sb) && (sb != crypt_sb) - && (sb != dex2oat_sb) && (sb != adbd_sb)) - return 1; - - return 0; -} - -int invalid_drive(struct linux_binprm * bprm) -{ - struct super_block *sb = NULL; - struct vfsmount *vfsmnt = NULL; - - vfsmnt = bprm->file->f_path.mnt; - if (!vfsmnt || !is_kdp_vfsmnt_cache((unsigned long)vfsmnt)) { - printk(KERN_ERR "[KDP] Invalid Drive : %s, vfsmnt: 0x%lx\n", - bprm->filename, (unsigned long)vfsmnt); - return 1; - } - - sb = vfsmnt->mnt_sb; - - if (kdp_check_sb_mismatch(sb)) { - printk(KERN_ERR "[KDP] Superblock Mismatch -> %s vfsmnt: 0x%lx, mnt_sb: 0x%lx", - bprm->filename, (unsigned long)vfsmnt, (unsigned long)sb); - printk(KERN_ERR "[KDP] Superblock list : 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx\n", - (unsigned long)rootfs_sb, (unsigned long)sys_sb, (unsigned long)odm_sb, - (unsigned long)vendor_sb, (unsigned long)art_sb, (unsigned long)crypt_sb, - (unsigned long)dex2oat_sb, (unsigned long)adbd_sb); - return 1; - } - - return 0; -} - -#define KDP_CRED_SYS_ID 1000 -int is_kdp_priv_task(void) -{ - struct cred *cred = (struct cred *)current_cred(); - - if (cred->uid.val <= (uid_t)KDP_CRED_SYS_ID || - cred->euid.val <= (uid_t)KDP_CRED_SYS_ID || - cred->gid.val <= (gid_t)KDP_CRED_SYS_ID || - cred->egid.val <= (gid_t)KDP_CRED_SYS_ID ) { - return 1; - } - - return 0; -} - -inline void kdp_set_mnt_root_sb(struct vfsmount *mnt, struct dentry *mnt_root, struct super_block *mnt_sb) -{ - uh_call(UH_APP_KDP, SET_NS_ROOT_SB, (u64)mnt, (u64)mnt_root, (u64)mnt_sb, 0); -} - -inline void kdp_assign_mnt_flags(struct vfsmount *mnt, int flags) -{ - uh_call(UH_APP_KDP, SET_NS_FLAGS, (u64)mnt, (u64)flags, 0, 0); -} - -inline void kdp_clear_mnt_flags(struct vfsmount *mnt, int flags) -{ - int f = mnt->mnt_flags; - f &= ~flags; - kdp_assign_mnt_flags(mnt, f); -} - -inline void kdp_set_mnt_flags(struct vfsmount *mnt, int flags) -{ - int f = mnt->mnt_flags; - f |= flags; - kdp_assign_mnt_flags(mnt, f); -} - -void kdp_set_ns_data(struct vfsmount *mnt, void *data) -{ - uh_call(UH_APP_KDP, SET_NS_DATA, (u64)mnt, (u64)data, 0, 0); -} - -int kdp_mnt_alloc_vfsmount(struct mount *mnt) -{ - struct vfsmount *vfsmnt = NULL; - - vfsmnt = kmem_cache_alloc(vfsmnt_cache, GFP_KERNEL); - if (!vfsmnt) - return 1; - - spin_lock(&mnt_vfsmnt_lock); - uh_call(UH_APP_KDP, SET_NS_BP, (u64)vfsmnt, (u64)mnt, 0, 0); - mnt->mnt = vfsmnt; - spin_unlock(&mnt_vfsmnt_lock); - - return 0; -} - -void kdp_free_vfsmount(void *objp) -{ - kmem_cache_free(vfsmnt_cache, objp); -} - -static void kdp_populate_sb(char *mount_point, struct vfsmount *mnt) -{ - if (!mount_point || !mnt) - return; - - if (!odm_sb && !strncmp(mount_point, KDP_MOUNT_PRODUCT, KDP_MOUNT_PRODUCT_LEN)) - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&odm_sb, (u64)mnt, KDP_SB_ODM, 0); - else if (!sys_sb && !strncmp(mount_point, KDP_MOUNT_SYSTEM, KDP_MOUNT_SYSTEM_LEN)) - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&sys_sb, (u64)mnt, KDP_SB_SYS, 0); - else if (!vendor_sb && !strncmp(mount_point, KDP_MOUNT_VENDOR, KDP_MOUNT_VENDOR_LEN)) - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&vendor_sb, (u64)mnt, KDP_SB_VENDOR, 0); - else if (!art_sb && !strncmp(mount_point, KDP_MOUNT_ART, KDP_MOUNT_ART_LEN - 1)) - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&art_sb, (u64)mnt, KDP_SB_ART, 0); - else if (!crypt_sb && !strncmp(mount_point, KDP_MOUNT_CRYPT, KDP_MOUNT_CRYPT_LEN - 1)) - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&crypt_sb, (u64)mnt, KDP_SB_CRYPT, 0); - else if (!dex2oat_sb && !strncmp(mount_point, KDP_MOUNT_DEX2OAT, KDP_MOUNT_DEX2OAT_LEN - 1)) - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&dex2oat_sb, (u64)mnt, KDP_SB_DEX2OAT, 0); - else if (!dex2oat_count && !strncmp(mount_point, KDP_MOUNT_DEX2OAT, KDP_MOUNT_DEX2OAT_LEN)) { - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&dex2oat_sb, (u64)mnt, KDP_SB_DEX2OAT, 0); - dex2oat_count++; - } - else if (!adbd_sb && !strncmp(mount_point, KDP_MOUNT_ADBD, KDP_MOUNT_ADBD_LEN - 1)) - uh_call(UH_APP_KDP, SET_NS_SB_VFSMOUNT, (u64)&adbd_sb, (u64)mnt, KDP_SB_ADBD, 0); -} - -int kdp_do_new_mount(struct vfsmount *mnt, struct path *path) -{ - char *buf = NULL; - char *dir_name; - - buf = kzalloc(PATH_MAX, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - dir_name = dentry_path_raw(path->dentry, buf, PATH_MAX); - if (!sys_sb || !odm_sb || !vendor_sb || !art_sb || !crypt_sb || !dex2oat_sb || !dex2oat_count || !adbd_sb) - kdp_populate_sb(dir_name, mnt); - - kfree(buf); - - return 0; -} -#endif diff --git a/drivers/uh/kdp_test.c b/drivers/uh/kdp_test.c deleted file mode 100755 index ce852e69b..000000000 --- a/drivers/uh/kdp_test.c +++ /dev/null @@ -1,387 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include <../../fs/mount.h> -#include - -#include - -/* Never enable this flag*/ -//#define CONFIG_KDP_SEC_TEST - -struct task_security_struct { - u32 osid; /* SID prior to last execve */ - u32 sid; /* current SID */ - u32 exec_sid; /* exec SID */ - u32 create_sid; /* fscreate SID */ - u32 keycreate_sid; /* keycreate SID */ - u32 sockcreate_sid; /* fscreate SID */ - void *bp_cred; -}; - -enum __KDP_TEST { - CMD_ID_CRED = 0, - CMD_ID_SEC_CONTEXT, - CMD_ID_NS, -}; - -#define KDP_PA_READ 0 -#define KDP_PA_WRITE 1 - -/* BUF define */ -#define KDP_BUF_SIZE 8192 -#define KDP_LINE_MAX 80 -static char kdp_test_buf[KDP_BUF_SIZE]; -static unsigned long kdp_test_len = 0; - -static DEFINE_RAW_SPINLOCK(par_lock); -static u64 *ha1; - -static void kdp_print(const char *fmt, ...) -{ - va_list aptr; - - if (kdp_test_len > KDP_BUF_SIZE - KDP_LINE_MAX) - return; - - va_start(aptr, fmt); - kdp_test_len += vsprintf(kdp_test_buf + kdp_test_len, fmt, aptr); - va_end(aptr); -} - -static struct vfsmount *get_vfsmnt(struct task_struct *p) -{ - if(!p || !(p->nsproxy) || - !(p->nsproxy->mnt_ns) || - !(p->nsproxy->mnt_ns->root)) - return NULL; - - return p->nsproxy->mnt_ns->root->mnt; -} - -static bool hyp_check_page_ro(u64 va) -{ - unsigned long flags; - u64 par = 0; - - raw_spin_lock_irqsave(&par_lock, flags); - uh_call(UH_APP_KDP, TEST_GET_PAR, (unsigned long)va, KDP_PA_WRITE, 0, 0); - par = *ha1; - raw_spin_unlock_irqrestore(&par_lock, flags); - - return (par & 0x1)? true: false; -} - -static int test_case_kdp_ro(int cmd_id) -{ - struct task_struct *p = NULL; - u64 ro = 0, rw = 0, dst; - - for_each_process(p) { - switch(cmd_id) { - case CMD_ID_CRED: - /* Here dst points to struct cred */ - dst = (u64)__task_cred(p); - break; - case CMD_ID_SEC_CONTEXT: - /* Here dst points to process security context */ - dst = (u64)__task_cred(p)->security; - break; - case CMD_ID_NS: - /* Here dst points to process security context */ - dst = (u64)get_vfsmnt(p); - break; - } - - if(!dst) - continue; - - if (hyp_check_page_ro(dst)) - ro++; - else - rw++; - } - - kdp_print("ro: %llu, rw: %llu\n", ro, rw); - return rw? 1: 0; -} - -static int cred_match(struct task_struct *p, const struct cred *cred) -{ - struct mm_struct *mm = p->mm; - pgd_t *tgt = NULL; - - if(cred->bp_task != p) { - kdp_print("KDP_WARN task: #%s# cred: %p, task: %p bp_task: %p\n", - p->comm,cred, p,cred->bp_task); - return 0; - } - - if(!(in_interrupt() || in_softirq())) - return 1; - - tgt = mm? mm->pgd: init_mm.pgd; - if(cred->bp_pgd != tgt) { - kdp_print("KDP_WARN task: #%s# cred: %p, mm: %p, init_mm: %p, pgd: %p bp_pgd: %p \n", - p->comm,cred,mm,init_mm.pgd,tgt,cred->bp_pgd); - return 0; - } - - return 1; -} - -static int sec_context_match(const struct cred *cred) -{ - struct task_security_struct *tsec = (struct task_security_struct *)cred->security; - - if((u64)tsec->bp_cred != (u64)cred) - return 0; - - return 1; -} - -static int test_case_match_bp(int cmd_id) -{ - struct task_struct *p = NULL; - u64 match = 0, mismatch = 0 , ret = 0; - - for_each_process(p) { - switch(cmd_id) { - case CMD_ID_CRED: - /*Here dst points to struct cred*/ - ret = cred_match(p,__task_cred(p)); - break; - case CMD_ID_SEC_CONTEXT: - /*Here dst points to process security context*/ - ret = sec_context_match(__task_cred(p)); - break; - } - ret? match++: mismatch++; - } - kdp_print("match: %llu, mismatch: %llu\n", match, mismatch); - return mismatch? 1: 0; -} - -static int test_case_cred_ro(void) -{ - kdp_print("CRED PROTECTION "); - return test_case_kdp_ro(CMD_ID_CRED); -} - -static int test_case_sec_context_ro(void) -{ - kdp_print("SECURITY CONTEXT PROTECTION "); - return test_case_kdp_ro(CMD_ID_SEC_CONTEXT); -} - -static int test_case_cred_match_bp(void) -{ - kdp_print("CRED Back Poiner check "); - return test_case_match_bp(CMD_ID_CRED); -} - -static int test_case_sec_context_match_bp(void) -{ - kdp_print("Security Context Back Poiner check "); - return test_case_match_bp(CMD_ID_SEC_CONTEXT); -} - -static int test_case_ns_ro(void) -{ - kdp_print("NAMESPACE PROTECTION "); - return test_case_kdp_ro(CMD_ID_NS); -} - -#ifdef CONFIG_KDP_SEC_TEST -enum { - CMD_ID_COMMIT_CRED, - CMD_ID_OVERRIDE_CRED, - CMD_ID_REVERT_CRED, -}; - -enum { - CMD_ID_SEC_WRITE_CRED, - CMD_ID_SEC_WRITE_SP, - CMD_ID_SEC_DIRECT_PE, - CMD_ID_SEC_INDIRECT_PE_COMMIT, - CMD_ID_SEC_INDIRECT_PE_OVERRIDE, - CMD_ID_SEC_INDIRECT_PE_REVERT, -}; - -#define PROCFS_MAX_SIZE 64 -void write_ro(u64 *p) -{ - memcpy(p,"c",1); -} -static void sec_test_cred(void) -{ - write_ro((u64 *)current_cred()); -} -static void sec_test_sp(void) -{ - write_ro((u64 *)current_cred()->security); -} - -struct cred *get_root_cred(void) -{ - struct cred *cred; - - cred = prepare_creds(); - cred->uid.val = 0; - cred->gid.val = 0; - cred->euid.val = 0; - cred->egid.val = 0; - - return cred; -} -static void sec_test_cred_direct_pe(void) -{ - struct cred *rcred; - - rcred = get_root_cred(); - current->cred = rcred; -} - -static void sec_test_cred_indirect_pe(int cmd_id) -{ - struct cred *rcred; - - rcred = get_root_cred(); - printk("RKP_SEC_TEST #%d# BEFORE current cred uid = %llx euid = %llx gid = %llx egid = %llx Root Cred%llx\n", - cmd_id,current->cred->uid.val,current->cred->euid.val,current->cred->gid.val,current->cred->egid.val,(u64)rcred); - - switch(cmd_id) { - case CMD_ID_COMMIT_CRED: - commit_creds(rcred); - break; - case CMD_ID_OVERRIDE_CRED: - override_creds(rcred); - break; - case CMD_ID_REVERT_CRED: - revert_creds(rcred); - break; - } - - printk("RKP_SEC_TEST#%d# AFTER current cred uid = %llx euid = %llx gid = %llx egid = %llx Root Cred %llx\n", - cmd_id,current->cred->uid.val,current->cred->euid.val,current->cred->gid.val,current->cred->egid.val,(u64)rcred); -} - -ssize_t kdp_write(struct file *filep, const char __user *buffer, size_t len, loff_t *offset) -{ - char procfs_buffer[PROCFS_MAX_SIZE]; - int buff_size; - int tcase; - - buff_size = (len > PROCFS_MAX_SIZE)?PROCFS_MAX_SIZE:len; - - if ( copy_from_user(procfs_buffer, buffer, buff_size) ) { - return -EFAULT; - } - sscanf(procfs_buffer,"%d",&tcase); - switch(tcase) { - case CMD_ID_SEC_WRITE_CRED: - sec_test_cred(); - break; - case CMD_ID_SEC_WRITE_SP: - sec_test_sp(); - break; - case CMD_ID_SEC_DIRECT_PE: - sec_test_cred_direct_pe(); - break; - case CMD_ID_SEC_INDIRECT_PE_COMMIT: - sec_test_cred_indirect_pe(CMD_ID_COMMIT_CRED); - break; - case CMD_ID_SEC_INDIRECT_PE_OVERRIDE: - sec_test_cred_indirect_pe(CMD_ID_OVERRIDE_CRED); - break; - case CMD_ID_SEC_INDIRECT_PE_REVERT: - sec_test_cred_indirect_pe(CMD_ID_REVERT_CRED); - break; - } - return len; -} -#endif /* CONFIG_KDP_SEC_TEST*/ - -ssize_t kdp_read(struct file *filep, char __user *buffer, size_t count, loff_t *ppos) -{ - int ret = 0, temp_ret = 0, i = 0; - struct test_case tc_funcs[] = { - {test_case_cred_ro, "TEST TASK_CRED_RO"}, - {test_case_sec_context_ro, "TEST TASK_SECURITY_CONTEXT_RO"}, - {test_case_cred_match_bp, "TEST CRED_MATCH_BACKPOINTERS"}, - {test_case_sec_context_match_bp,"TEST TASK_SEC_CONTEXT_BACKPOINTER"}, - {test_case_ns_ro, "TEST NAMESPACE_RO"}, - }; - int tc_num = sizeof(tc_funcs)/sizeof(struct test_case); - - static bool done = false; - if (done) - return 0; - done = true; - - for (i = 0; i < tc_num; i++) { - kdp_print( "KDP_TEST_CASE %d ===========> RUNNING %s\n", i, tc_funcs[i].describe); - temp_ret = tc_funcs[i].fn(); - - if (temp_ret) { - kdp_print("KDP_TEST_CASE %d ===========> %s FAILED WITH %d ERRORS\n", - i, tc_funcs[i].describe, temp_ret); - } else { - kdp_print("KDP_TEST_CASE %d ===========> %s PASSED\n", i, tc_funcs[i].describe); - } - - ret += temp_ret; - } - - if (ret) - kdp_print("KDP_TEST SUMMARY: FAILED WITH %d ERRORS\n", ret); - else - kdp_print("KDP_TEST SUMMARY: PASSED\n"); - - return simple_read_from_buffer(buffer, count, ppos, kdp_test_buf, kdp_test_len); -} - -static const struct file_operations kdp_proc_fops = { - .read = kdp_read, -#ifdef CONFIG_KDP_SEC_TEST - .write = kdp_write, -#endif -}; - -static int __init kdp_test_init(void) -{ - u64 va; - -#ifndef CONFIG_KDP_SEC_TEST - if (proc_create("kdp_test", 0444, NULL, &kdp_proc_fops) == NULL) { -#else - if (proc_create("kdp_test", 0777, NULL, &kdp_proc_fops) == NULL) { -#endif - printk(KERN_ERR "KDP_TEST: Error creating proc entry"); - return -1; - } - - va = __get_free_page(GFP_KERNEL | __GFP_ZERO); - if (!va) - return -1; - - uh_call(UH_APP_KDP, TEST_INIT, va, 0, 0, 0); - - ha1 = (u64 *)va; - - return 0; -} - -static void __exit kdp_test_exit(void) -{ - uh_call(UH_APP_KDP, TEST_EXIT, (u64)ha1, 0, 0, 0); - free_page((unsigned long)ha1); - - remove_proc_entry("kdp_test", NULL); -} - -module_init(kdp_test_init); -module_exit(kdp_test_exit); diff --git a/drivers/uh/rkp.c b/drivers/uh/rkp.c deleted file mode 100755 index 59c9a416b..000000000 --- a/drivers/uh/rkp.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include - -#include -bool rkp_started __rkp_ro = false; -static u64 robuffer_base __rkp_ro = 0; -static u64 robuffer_size __rkp_ro = 0; - -/* init/main.c */ -void __init rkp_init(void) -{ - struct rkp_init init_data; - memset((void *)&init_data, 0, sizeof(struct rkp_init)); - /* initialized rkp_init struct */ - init_data.magic = RKP_INIT_MAGIC; - init_data.vmalloc_start = VMALLOC_START; - init_data.no_fimc_verify = 1; - init_data.fimc_phys_addr = 0; - init_data._text = (u64)_text; - init_data._etext = (u64)_etext; - init_data._srodata = (u64)__start_rodata; - init_data._erodata = (u64)__end_rodata; - init_data.large_memory = 0; - - init_data.vmalloc_end = (u64)high_memory; - init_data.init_mm_pgd = (u64)__pa(swapper_pg_dir); - init_data.id_map_pgd = (u64)__pa(idmap_pg_dir); - init_data.zero_pg_addr = (u64)__pa(empty_zero_page); - - uh_call(UH_APP_RKP, RKP_START, (u64)&init_data, (u64)kimage_voffset, 0, 0); - rkp_started = true; -} - -/* init/main.c */ -void rkp_deferred_init(void) -{ - uh_call(UH_APP_RKP, RKP_DEFERRED_START, 0, 0, 0, 0); -} - -/* RO BUFFER */ -void rkp_robuffer_init(void) -{ - uh_call(UH_APP_RKP, RKP_GET_RO_INFO, (u64)&robuffer_base, (u64)&robuffer_size, 0, 0); -} - -/* allocation */ -inline phys_addr_t rkp_ro_alloc_phys(void) -{ - phys_addr_t alloc_addr = 0; - - uh_call(UH_APP_RKP, RKP_ROBUFFER_ALLOC, (u64)&alloc_addr, 1, 0, 0); - - return alloc_addr; -} - -inline void *rkp_ro_alloc(void) -{ - void *addr = NULL; - - uh_call(UH_APP_RKP, RKP_ROBUFFER_ALLOC, (u64)&addr, 1, 0, 0); - if (!addr) - return 0; - - return (void *)__phys_to_virt(addr); -} - -inline void rkp_ro_free(void *addr) -{ - uh_call(UH_APP_RKP, RKP_ROBUFFER_FREE, (u64)addr, 0, 0, 0); -} - -inline bool is_rkp_ro_buffer(u64 addr) -{ - u64 pa = (u64)virt_to_phys((void *)addr); - - if ((robuffer_base <= pa) && (pa < robuffer_base + robuffer_size)) - return true; - else - return false; -} diff --git a/drivers/uh/rkp_test.c b/drivers/uh/rkp_test.c deleted file mode 100755 index ed5b48e1c..000000000 --- a/drivers/uh/rkp_test.c +++ /dev/null @@ -1,517 +0,0 @@ -#include -#include -#include -#include -#include - -/* - * BIT[0:1] TYPE PXN BIT - * 01 BLOCK 53 For LEVEL 0, 1, 2 //defined by L012_BLOCK_PXN - * 11 TABLE 59 For LEVEL 0, 1, 2 //defined by L012_TABLE_PXN - * 11 PAGE 53 For LEVEL 3 //defined by L3_PAGE_PXN - */ -#define L012_BLOCK_PXN (_AT(pmdval_t, 1) << 53) -#define L012_TABLE_PXN (_AT(pmdval_t, 1) << 59) -#define L3_PAGE_PXN (_AT(pmdval_t, 1) << 53) - -#define MEM_END 0xfffffffffffff000 /* 4K aligned */ -#define DESC_MASK 0xFFFFFFFFF000 - -#define RKP_PA_READ 0 -#define RKP_PA_WRITE 1 - -/* BUF define */ -#define RKP_BUF_SIZE 8192 -#define RKP_LINE_MAX 80 -static char rkp_test_buf[RKP_BUF_SIZE]; -static unsigned long rkp_test_len = 0; -static unsigned long prot_user_l2 = 1; - -static DEFINE_RAW_SPINLOCK(par_lock); -static u64 *ha1; - -struct test_data { - u64 iter; - u64 pxn; - u64 no_pxn; - u64 read; - u64 write; - u64 cred_bkptr_match; - u64 cred_bkptr_mismatch; -}; - -static void buf_print(const char *fmt, ...) -{ - va_list aptr; - - if (rkp_test_len > RKP_BUF_SIZE - RKP_LINE_MAX) { - printk(KERN_ERR "RKP_TEST: Error Maximum buf"); - return; - } - va_start(aptr, fmt); - rkp_test_len += vsprintf(rkp_test_buf+rkp_test_len, fmt, aptr); - va_end(aptr); -} - -//if RO, return true; RW return false -static bool hyp_check_page_ro(u64 va) -{ - unsigned long flags; - u64 par = 0; - - raw_spin_lock_irqsave(&par_lock, flags); - uh_call(UH_APP_RKP, RKP_TEST_GET_PAR, (unsigned long)va, RKP_PA_WRITE, 0, 0); - par = *ha1; - raw_spin_unlock_irqrestore(&par_lock, flags); - - return (par & 0x1) ? true : false; -} - -static void hyp_check_l23pgt_rw(u64 *pg_l, unsigned int level, struct test_data *test) -{ - unsigned int i; - - // Level is 1 2 - if (level >= 3) - return; - - for (i = 0; i < 512; i++) { - if ((pg_l[i] & 3) == 3) { - test[level].iter++; - if (hyp_check_page_ro((u64)phys_to_virt(pg_l[i] & DESC_MASK))) - test[level].read++; - else - test[level].write++; - - hyp_check_l23pgt_rw((u64 *) (phys_to_virt(pg_l[i] & DESC_MASK)), level + 1, test); - } - } -} - -static pmd_t *get_addr_pmd(struct mm_struct *mm, unsigned long addr) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - - pgd = pgd_offset(mm, addr); - if (pgd_none(*pgd)) - return NULL; - - pud = pud_offset(pgd, addr); - if (pud_none(*pud)) - return NULL; - - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) - return NULL; - - return pmd; -} - -static int test_case_user_pgtable_ro(void) -{ - struct task_struct *task; - struct test_data test[3] = {{0}, {0}, {0} }; - struct mm_struct *mm = NULL; - int i; - - for_each_process(task) { - mm = task->active_mm; - if (!(mm) || !(mm->context.id.counter) || !(mm->pgd)) { - continue; - } - - if (hyp_check_page_ro((u64)(mm->pgd))) - test[0].read++; - else - test[0].write++; - - test[0].iter++; - hyp_check_l23pgt_rw(((u64 *) (mm->pgd)), 1, test); - } - - for (i = 0; i < 3; i++) { - buf_print("\t\tL%d TOTAL PAGES %6llu | READ ONLY %6llu | WRITABLE %6llu\n", - i+1, test[i].iter, test[i].read, test[i].write); - } - - //L1 and L2 pgtable should be RO - if ((!prot_user_l2) && (test[0].write == 0)) - return 0; - - if ((test[0].write == 0) && (test[1].write == 0)) - return 0; //pass - else - return 1; //fail -} - -static int test_case_kernel_pgtable_ro(void) -{ - struct test_data test[3] = {{0}, {0}, {0} }; - int i = 0; - // Check for swapper_pg_dir - test[0].iter++; - if (hyp_check_page_ro((u64)swapper_pg_dir)) - test[0].read++; - else - test[0].write++; - - hyp_check_l23pgt_rw((u64 *)swapper_pg_dir, 1, test); - - for (i = 0; i < 3; i++) - buf_print("\t\tL%d TOTAL PAGE TABLES %6llu | READ ONLY %6llu |WRITABLE %6llu\n", - i+1, test[i].iter, test[i].read, test[i].write); - - if ((test[0].write == 0) && (test[1].write == 0)) - return 0; - else - return 1; -} - -static int test_case_kernel_l3pgt_ro(void) -{ - int rw = 0, ro = 0, i = 0; - u64 addrs[] = { - (u64)_text, - (u64)_etext - }; - int len = sizeof(addrs)/sizeof(u64); - - pmd_t * pmd; - u64 pgt_addr; - - for (i = 0; i < len; i++) { - pmd = get_addr_pmd(&init_mm, addrs[i]); - - pgt_addr = (u64)phys_to_virt(((u64)(pmd_val(*pmd))) & DESC_MASK); - if (hyp_check_page_ro(pgt_addr)) - ro++; - else - rw++; - } - - buf_print("\t\tKERNEL TEXT HEAD TAIL L3PGT | RO %6u | RW %6u\n", ro, rw); - return (rw == 0) ? 0 : 1; -} - -// return true if addr mapped, otherwise return false -static bool page_pxn_set(unsigned long addr, u64 *xn, u64 *x) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - - pgd = pgd_offset_k(addr); - if (pgd_none(*pgd)) - return false; - - pud = pud_offset(pgd, addr); - if (pud_none(*pud)) - return false; - - if (pud_sect(*pud)) { - if ((pud_val(*pud) & L012_BLOCK_PXN) > 0) - *xn += 1; - else - *x += 1; - return true; - } - - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) - return false; - - if (pmd_sect(*pmd)) { - if ((pmd_val(*pmd) & L012_BLOCK_PXN) > 0) - *xn += 1; - else - *x += 1; - return true; - } else { - if ((pmd_val(*pmd) & L012_TABLE_PXN) > 0) { - *xn += 1; - return true; - } - } - - // If pmd is table, such as kernel text head and tail, need to check L3 - pte = pte_offset_kernel(pmd, addr); - if (pte_none(*pte)) - return false; - - if ((pte_val(*pte) & L3_PAGE_PXN) > 0) - *xn += 1; - else - *x += 1; - return true; -} - -static void count_pxn(unsigned long pxn, int level, struct test_data *test) -{ - test[level].iter++; - if (pxn) - test[level].pxn++; - else - test[level].no_pxn++; -} - -static void walk_pte(pmd_t *pmd, int level, struct test_data *test) -{ - pte_t *pte = pte_offset_kernel(pmd, 0UL); - unsigned i; - unsigned long prot; - - for (i = 0; i < PTRS_PER_PTE; i++, pte++) { - if (pte_none(*pte)) { - continue; - } else { - prot = pte_val(*pte) & L3_PAGE_PXN; - count_pxn(prot, level, test); - } - } -} - -static void walk_pmd(pud_t *pud, int level, struct test_data *test) -{ - pmd_t *pmd = pmd_offset(pud, 0UL); - unsigned i; - unsigned long prot; - - for (i = 0; i < PTRS_PER_PMD; i++, pmd++) { - if (pmd_none(*pmd)) { - continue; - } else if (pmd_sect(*pmd)) { - prot = pmd_val(*pmd) & L012_BLOCK_PXN; - count_pxn(prot, level, test); - } else { - /* - * For user space, all L2 should have PXN, including block and - * table. Only kernel text head and tail L2 table can have no - * pxn, and kernel text middle L2 blocks can have no pxn - */ - BUG_ON(pmd_bad(*pmd)); - prot = pmd_val(*pmd) & L012_TABLE_PXN; - count_pxn(prot, level, test); - walk_pte(pmd, level+1, test); - } - } -} - -static void walk_pud(pgd_t *pgd, int level, struct test_data *test) -{ - pud_t *pud = pud_offset(pgd, 0UL); - unsigned i; - - for (i = 0; i < PTRS_PER_PUD; i++, pud++) { - if (pud_none(*pud) || pud_sect(*pud)) { - continue; - } else { - BUG_ON(pud_bad(*pud)); - walk_pmd(pud, level, test); - } - } -} - -#define rkp_pgd_table (_AT(pgdval_t, 1) << 1) -#define rkp_pgd_bad(pgd) (!(pgd_val(pgd) & rkp_pgd_table)) -static void walk_pgd(struct mm_struct *mm, int level, struct test_data *test) -{ - pgd_t *pgd = pgd_offset(mm, 0UL); - unsigned i; - unsigned long prot; - - for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { - if (rkp_pgd_bad(*pgd)) { - continue; - } else { //table - prot = pgd_val(*pgd) & L012_TABLE_PXN; - count_pxn(prot, level, test); - walk_pud(pgd, level+1, test); - } - } -} - -static int test_case_user_pxn(void) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct test_data test[3] = {{0}, {0}, {0} }; - int i = 0; - - for_each_process(task) { - mm = task->active_mm; - if (!(mm) || !(mm->context.id.counter) || !(mm->pgd)) { - continue; - } - - /* Check if PXN bit is set */ - walk_pgd(mm, 0, test); - } - - for (i = 0; i < 3; i++) { - buf_print("\t\tL%d TOTAL ENTRIES %6llu | PXN %6llu | NO_PXN %6llu\n", - i+1, test[i].iter, test[i].pxn, test[i].no_pxn); - } - - //all 2nd level entries should be PXN - if (test[0].no_pxn == 0) { - prot_user_l2 = 0; - return 0; - } else if (test[1].no_pxn == 0) { - prot_user_l2 = 1; - return 0; - } else { - return 1; - } -} - -struct mem_range { - u64 start_va; - u64 size; //in bytes - char *info; - bool no_rw; - bool no_x; -}; - -static int test_case_kernel_range_rwx(void) -{ - int ret = 0; - u64 ro = 0, rw = 0; - u64 xn = 0, x = 0; - int i; - u64 j; - bool mapped = false; - u64 va_temp; - - struct mem_range test_ranges[] = { - {(u64)VMALLOC_START, ((u64)_text) - ((u64)VMALLOC_START), "VMALLOC - STEXT", false, true}, - {((u64)_text), ((u64)_etext) - ((u64)_text), "STEXT - ETEXT ", true, false}, - {((u64)__start_rodata), ((u64) __end_rodata) - ((u64)__start_rodata), "SRODATA - ERODATA ", true, true}, - {((u64)__end_rodata), MEM_END - ((u64) __end_rodata), "ERODATA -MEM_END", false, true}, - }; - - int len = sizeof(test_ranges)/sizeof(struct mem_range); - buf_print("\t\t| MEMORY RANGES | %16s - %16s | %8s %8s %8s %8s\n", - "START", "END", "RO", "RW", "PXN", "PX"); - for (i = 0; i < len; i++) { - for (j = 0; j < test_ranges[i].size/PAGE_SIZE; j++) { - va_temp = test_ranges[i].start_va + j*PAGE_SIZE; - mapped = page_pxn_set(va_temp, &xn, &x); - if (!mapped) - continue; - // only for mapped pages - if (hyp_check_page_ro(va_temp)) - ro += 1; - else - rw += 1; - } - - buf_print("\t\t|%s| %016llx - %016llx | %8llu %8llu %8llu %8llu\n", - test_ranges[i].info, test_ranges[i].start_va, - test_ranges[i].start_va + test_ranges[i].size, - ro, rw, xn, x); - - if (test_ranges[i].no_rw && (rw != 0)) { - buf_print("RKP_TEST FAILED, NO RW PAGE ALLOWED, rw=%llu\n", rw); - ret++; - } - - if (test_ranges[i].no_x && (x != 0)) { - buf_print("RKP_TEST FAILED, NO X PAGE ALLOWED, x=%llu\n", x); - ret++; - } - - if ((rw != 0) && (x != 0)) { - buf_print("RKP_TEST FAILED, NO RWX PAGE ALLOWED, rw=%llu, x=%llu\n", rw, x); - ret++; - } - - ro = 0; rw = 0; - xn = 0; x = 0; - } - - return ret; -} - -ssize_t rkp_read(struct file *filep, char __user *buffer, size_t count, loff_t *ppos) -{ - int ret = 0, temp_ret = 0, i = 0; - struct test_case tc_funcs[] = { - {test_case_user_pxn, "TEST USER_PXN"}, - {test_case_user_pgtable_ro, "TEST USER_PGTABLE_RO"}, - {test_case_kernel_pgtable_ro, "TEST KERNEL_PGTABLE_RO"}, - {test_case_kernel_l3pgt_ro, "TEST KERNEL TEXT HEAD TAIL L3PGT RO"}, - {test_case_kernel_range_rwx, "TEST KERNEL_RANGE_RWX"}, - }; - int tc_num = sizeof(tc_funcs)/sizeof(struct test_case); - - static bool done = false; - if (done) - return 0; - done = true; - - if (!ha1) { - buf_print("ERROR RKP_TEST ha1 is NULL\n"); - goto error; - } - - for (i = 0; i < tc_num; i++) { - buf_print( "RKP_TEST_CASE %d ===========> RUNNING %s\n", i, tc_funcs[i].describe); - temp_ret = tc_funcs[i].fn(); - - if (temp_ret) { - buf_print("RKP_TEST_CASE %d ===========> %s FAILED WITH %d ERRORS\n", - i, tc_funcs[i].describe, temp_ret); - } else { - buf_print("RKP_TEST_CASE %d ===========> %s PASSED\n", i, tc_funcs[i].describe); - } - - ret += temp_ret; - } - - if (ret) - buf_print("RKP_TEST SUMMARY: FAILED WITH %d ERRORS\n", ret); - else - buf_print("RKP_TEST SUMMARY: PASSED\n"); - -error: - return simple_read_from_buffer(buffer, count, ppos, rkp_test_buf, rkp_test_len); -} - -static const struct file_operations rkp_proc_fops = { - .read = rkp_read, -}; - -static int __init rkp_test_init(void) -{ - u64 va; - - if (proc_create("rkp_test", 0444, NULL, &rkp_proc_fops) == NULL) { - printk(KERN_ERR "RKP_TEST: Error creating proc entry"); - return -1; - } - - va = __get_free_page(GFP_KERNEL | __GFP_ZERO); - if (!va) - return -1; - - uh_call(UH_APP_RKP, RKP_TEST_INIT, va, 0,0, 0); - - ha1 = (u64 *)va; - - return 0; -} - -static void __exit rkp_test_exit(void) -{ - uh_call(UH_APP_RKP, RKP_TEST_EXIT, (u64)ha1, 0, 0, 0); - free_page((unsigned long)ha1); - - remove_proc_entry("rkp_test", NULL); -} - -module_init(rkp_test_init); -module_exit(rkp_test_exit); - diff --git a/drivers/uh/uh_debug_log.c b/drivers/uh/uh_debug_log.c deleted file mode 100755 index 73536fe07..000000000 --- a/drivers/uh/uh_debug_log.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include -#include -#include - -ssize_t uh_log_read(struct file *filep, char __user *buf, size_t size, loff_t *offset) -{ - static size_t log_buf_size; - unsigned long *log_addr = 0; - - if (!strcmp(filep->f_path.dentry->d_iname, "uh_log")) - log_addr = (unsigned long *)phys_to_virt(UH_LOG_START); - else - return -EINVAL; - - if(!*offset) { - log_buf_size = 0; - while(log_buf_size < UH_LOG_SIZE && ((char *)log_addr)[log_buf_size] != 0) - log_buf_size++; - } - - if (*offset >= log_buf_size) - return 0; - - if (*offset + size > log_buf_size) - size = log_buf_size - *offset; - - if (copy_to_user(buf, (const char *)log_addr + (*offset), size)) - return -EFAULT; - - *offset += size; - return size; -} - -static const struct file_operations uh_proc_fops = { - .owner = THIS_MODULE, - .read = uh_log_read, -}; - -static int __init uh_log_init(void) -{ - struct proc_dir_entry *entry; - - entry = proc_create("uh_log", 0644, NULL, &uh_proc_fops); - if (!entry) { - pr_err("uh_log: Error creating proc entry\n"); - return -ENOMEM; - } - - pr_info("uh_log : create /proc/uh_log\n"); - return 0; -} - -static void __exit uh_log_exit(void) -{ - remove_proc_entry("uh_log", NULL); -} - -module_init(uh_log_init); -module_exit(uh_log_exit); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 37dc2b0bb..184ffd40c 100755 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -511,12 +511,6 @@ struct skb_shared_info { * remains valid until skb destructor */ void * destructor_arg; -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - uid_t uid; - pid_t pid; - u_int32_t knox_mark; -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } - /* must be last field, see pskb_expand_head() */ skb_frag_t frags[MAX_SKB_FRAGS]; }; diff --git a/include/net/ncm.h b/include/net/ncm.h deleted file mode 100755 index fb8559c61..000000000 --- a/include/net/ncm.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Network Context Metadata Module[NCM]:Implementation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// KNOX NPA - START - -#ifndef NCM_COMMON_H__ -#define NCM_COMMON_H__ - -#define NCM_VERSION 11 - -#define INIT_UID_NAP 0 -#define INIT_PID_NAP 1 -#define DNS_PORT_NAP 53 -#define IPV4_FAMILY_NAP 2 -#define IPV6_FAMILY_NAP 10 -#define INET6_ADDRSTRLEN_NAP 48 - -#define NCM_FLOW_TYPE_DEFAULT -1 -#define NCM_FLOW_TYPE_ALL 0 -#define NCM_FLOW_TYPE_OPEN 1 -#define NCM_FLOW_TYPE_CLOSE 2 -#define NCM_FLOW_TYPE_INTERMEDIATE 3 - -#include -#include -#include -#include -#include - -#define isIpv4AddressEqualsNull(srcaddr, dstaddr) ((((strcmp(srcaddr, "0.0.0.0")) || (strcmp(dstaddr, "0.0.0.0"))) == 0) ? 1 : 0) -#define isIpv6AddressEqualsNull(srcaddr, dstaddr) ((((strcmp(srcaddr, "0000:0000:0000:0000:0000:0000:0000:0000")) || (strcmp(dstaddr, "0000:0000:0000:0000:0000:0000:0000:0000"))) == 0) ? 1 : 0) - -/* Struct Socket definition */ -struct knox_socket_metadata { -/* The source port of the socket */ - __u16 srcport; -/* The destination port of the socket */ - __u16 dstport; -/* The Transport layer protocol of the socket*/ - __u16 trans_proto; -/* The number of application layer bytes sent by the socket */ - __u64 knox_sent; -/* The number of application layer bytes recieved by the socket */ - __u64 knox_recv; -/* The uid which created the socket */ - uid_t knox_uid; -/* The pid under which the socket was created */ - pid_t knox_pid; -/* The parent user id under which the socket was created */ - uid_t knox_puid; -/* The epoch time at which the socket was opened */ - __u64 open_time; -/* The epoch time at which the socket was closed */ - __u64 close_time; -/* The source address of the socket */ - char srcaddr[INET6_ADDRSTRLEN_NAP]; -/* The destination address of the socket */ - char dstaddr[INET6_ADDRSTRLEN_NAP]; -/* The name of the process which created the socket */ - char process_name[PROCESS_NAME_LEN_NAP]; -/* The name of the parent process which created the socket */ - char parent_process_name[PROCESS_NAME_LEN_NAP]; -/* The Domain name associated with the ip address of the socket. The size needs to be in sync with the userspace implementation */ - char domain_name[DOMAIN_NAME_LEN_NAP]; -/* The uid which originated the dns request */ - uid_t knox_uid_dns; -/* The parent process id under which the socket was created */ - pid_t knox_ppid; -/* The interface used by the flow to transmit packet */ - char interface_name[IFNAMSIZ]; -/* The flow type is used identify the current state of the network flow*/ - int flow_type; -/* The struct defined is responsible for inserting the socket meta-data into kfifo */ - struct work_struct work_kfifo; -}; - -/* Struct Socket definition */ -struct knox_user_socket_metadata { -/* The source port of the socket */ - __u16 srcport; -/* The destination port of the socket */ - __u16 dstport; -/* The Transport layer protocol of the socket*/ - __u16 trans_proto; -/* The number of application layer bytes sent by the socket */ - __u64 knox_sent; -/* The number of application layer bytes recieved by the socket */ - __u64 knox_recv; -/* The uid which created the socket */ - uid_t knox_uid; -/* The pid under which the socket was created */ - pid_t knox_pid; -/* The parent user id under which the socket was created */ - uid_t knox_puid; -/* The epoch time at which the socket was opened */ - __u64 open_time; -/* The epoch time at which the socket was closed */ - __u64 close_time; -/* The source address of the socket */ - char srcaddr[INET6_ADDRSTRLEN_NAP]; -/* The destination address of the socket */ - char dstaddr[INET6_ADDRSTRLEN_NAP]; -/* The name of the process which created the socket */ - char process_name[PROCESS_NAME_LEN_NAP]; -/* The name of the parent process which created the socket */ - char parent_process_name[PROCESS_NAME_LEN_NAP]; -/* The Domain name associated with the ip address of the socket. The size needs to be in sync with the userspace implementation */ - char domain_name[DOMAIN_NAME_LEN_NAP]; -/* The uid which originated the dns request */ - uid_t knox_uid_dns; -/* The parent process id under which the socket was created */ - pid_t knox_ppid; -/* The interface used by the flow to transmit packet */ - char interface_name[IFNAMSIZ]; -/* The flow type is used identify the current state of the network flow*/ - int flow_type; -}; - -/* The list of function which is being referenced */ -extern unsigned int check_ncm_flag(void); -extern void knox_collect_conntrack_data(struct nf_conn *ct, int startStop, int where); -extern bool kfifo_status(void); -extern void insert_data_kfifo_kthread(struct knox_socket_metadata* knox_socket_metadata); -extern unsigned int check_intermediate_flag(void); -extern unsigned int get_intermediate_timeout(void); - -/* Debug */ -#define NCM_DEBUG 1 -#if NCM_DEBUG -#define NCM_LOGD(...) printk("ncm: "__VA_ARGS__) -#else -#define NCM_LOGD(...) -#endif /* NCM_DEBUG */ -#define NCM_LOGE(...) printk("ncm: "__VA_ARGS__) - -/* IOCTL definitions*/ -#define __NCMIOC 0x120 -#define NCM_ACTIVATED_OPEN _IO(__NCMIOC, 2) -#define NCM_DEACTIVATED _IO(__NCMIOC, 4) -#define NCM_ACTIVATED_CLOSE _IO(__NCMIOC, 8) -#define NCM_ACTIVATED_ALL _IO(__NCMIOC, 16) -#define NCM_GETVERSION _IO(__NCMIOC, 32) -#define NCM_MATCH_VERSION _IO(__NCMIOC, 64) - -#endif - -// KNOX NPA - END diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 746e9e237..ac4d70aee 100755 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -26,10 +26,6 @@ #include #include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -#define PROCESS_NAME_LEN_NAP 128 -#define DOMAIN_NAME_LEN_NAP 255 -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } /* per conntrack: protocol private data */ union nf_conntrack_proto { @@ -107,39 +103,6 @@ struct nf_conn { /* Storage reserved for other modules, must be the last member */ union nf_conntrack_proto proto; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - /* The number of application layer bytes sent by the socket */ - __u64 knox_sent; - /* The number of application layer bytes recieved by the socket */ - __u64 knox_recv; - /* The uid which created the socket */ - uid_t knox_uid; - /* The pid under which the socket was created */ - pid_t knox_pid; - /* The parent user id under which the socket was created */ - uid_t knox_puid; - /* The epoch time at which the socket was opened */ - __u64 open_time; - /* The name of the process which created the socket */ - char process_name[PROCESS_NAME_LEN_NAP]; - /* The name of the parent process which created the socket */ - char parent_process_name[PROCESS_NAME_LEN_NAP]; - /* The Domain name associated with the ip address of the socket. The size needs to be in sync with the userspace implementation */ - char domain_name[DOMAIN_NAME_LEN_NAP]; - /* The parent process id under which the socket was created */ - pid_t knox_ppid; - /* The interface used by the flow to transmit packet */ - char interface_name[IFNAMSIZ]; - /* Atomic variable indicating start of flow */ - atomic_t startFlow; - /* The value at which this ct is considered timed-out for intermediate flows */ - /* Use 'u32 npa_timeout' if struct nf_conn->timeout is of type u32; Use 'struct timer_list npa_timeout' if struct nf_conn->timeout is of type struct timer_list;*/ - u32 npa_timeout; - /* Atomic variable indicating end of intermediate flow */ - atomic_t intermediateFlow; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } - - }; static inline struct nf_conn * diff --git a/include/net/sock.h b/include/net/sock.h index ecd101fce..688256d34 100755 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -74,10 +74,6 @@ #include #include #include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -#define NAP_PROCESS_NAME_LEN 128 -#define NAP_DOMAIN_NAME_LEN 255 -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } /* * This structure really needs to be cleaned up. @@ -500,18 +496,6 @@ struct sock { #endif struct sock_cgroup_data sk_cgrp_data; struct mem_cgroup *sk_memcg; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - uid_t knox_uid; - pid_t knox_pid; - uid_t knox_dns_uid; - char domain_name[NAP_DOMAIN_NAME_LEN]; - char process_name[NAP_PROCESS_NAME_LEN]; - uid_t knox_puid; - pid_t knox_ppid; - char parent_process_name[NAP_PROCESS_NAME_LEN]; - pid_t knox_dns_pid; - char dns_process_name[NAP_PROCESS_NAME_LEN]; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } void (*sk_state_change)(struct sock *sk); void (*sk_data_ready)(struct sock *sk); void (*sk_write_space)(struct sock *sk); diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index 06614fbca..a12692e5f 100755 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -106,11 +106,6 @@ #define SO_PEERGROUPS 59 #define SO_ZEROCOPY 60 -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -#define SO_SET_DOMAIN_NAME 1000 -#define SO_SET_DNS_UID 1001 -#define SO_SET_DNS_PID 1002 -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } #define SO_TXTIME 61 #define SCM_TXTIME SO_TXTIME diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h index 467691e4d..ee432cd30 100755 --- a/include/uapi/linux/if_tun.h +++ b/include/uapi/linux/if_tun.h @@ -87,15 +87,6 @@ #define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ #define TUN_F_UFO 0x10 /* I can handle UFO packets */ -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { -#define TUN_META_HDR 0x0020 -#define TUNGETMETAPARAM _IOR('T', 218, int) -#define IFF_META_HDR 0x0004 -#define TUN_GET_META_HDR_SZ 0 -#define TUN_GET_META_MARK_OFFSET 1 -#define DEFAULT_IHL 5 -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } - /* Protocol info prepended to the packets (when IFF_NO_PI is not set) */ #define TUN_PKT_STRIP 0x0001 struct tun_pi { diff --git a/net/Kconfig b/net/Kconfig index ce5d49574..6870f6c83 100755 --- a/net/Kconfig +++ b/net/Kconfig @@ -242,9 +242,6 @@ source "net/switchdev/Kconfig" source "net/l3mdev/Kconfig" source "net/qrtr/Kconfig" source "net/ncsi/Kconfig" -# SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -source "net/ncm/Kconfig" -# SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } config RPS bool diff --git a/net/Makefile b/net/Makefile index 9b76e55da..449fc0b22 100755 --- a/net/Makefile +++ b/net/Makefile @@ -87,6 +87,3 @@ endif obj-$(CONFIG_QRTR) += qrtr/ obj-$(CONFIG_NET_NCSI) += ncsi/ obj-$(CONFIG_XDP_SOCKETS) += xdp/ -# SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -obj-$(CONFIG_KNOX_NCM) += ncm/ -# SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } diff --git a/net/core/sock.c b/net/core/sock.c index ee694f085..47d5bcb92 100755 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -142,11 +142,6 @@ #include #include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -#include -#include -#include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); @@ -622,94 +617,6 @@ out: return ret; } -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -/** The function sets the domain name associated with the socket. **/ -static int sock_set_domain_name(struct sock *sk, char __user *optval, - int optlen) -{ - int ret = -EADDRNOTAVAIL; - char domain[DOMAIN_NAME_LEN_NAP]; - - ret = -EINVAL; - if (optlen < 0) - goto out; - - if (optlen > DOMAIN_NAME_LEN_NAP - 1) - optlen = DOMAIN_NAME_LEN_NAP - 1; - - memset(domain, 0, sizeof(domain)); - - ret = -EFAULT; - if (copy_from_user(domain, optval, optlen)) - goto out; - memcpy(sk->domain_name,domain, sizeof(sk->domain_name)-1); - ret = 0; - -out: - return ret; -} - -/** The function sets the uid associated with the dns socket. **/ -static int sock_set_dns_uid(struct sock *sk, char __user *optval, int optlen) -{ - int ret = -EADDRNOTAVAIL; - - if (optlen < 0) - goto out; - - if (optlen == sizeof(uid_t)) { - uid_t dns_uid; - ret = -EFAULT; - if (copy_from_user(&dns_uid, optval, sizeof(dns_uid))) - goto out; - memcpy(&sk->knox_dns_uid, &dns_uid, sizeof(sk->knox_dns_uid)); - ret = 0; - } - -out: - return ret; -} - -/** The function sets the pid and the process name associated with the dns socket. **/ -static int sock_set_dns_pid(struct sock *sk, char __user *optval, int optlen) -{ - int ret = -EADDRNOTAVAIL; - struct pid *pid_struct = NULL; - struct task_struct *task = NULL; - int process_returnValue = -1; - char full_process_name[PROCESS_NAME_LEN_NAP] = {0}; - - if (optlen < 0) - goto out; - - if (optlen == sizeof(pid_t)) { - pid_t dns_pid; - ret = -EFAULT; - if (copy_from_user(&dns_pid, optval, sizeof(dns_pid))) - goto out; - memcpy(&sk->knox_dns_pid, &dns_pid, sizeof(sk->knox_dns_pid)); - if(check_ncm_flag()) { - pid_struct = find_get_pid(dns_pid); - if (pid_struct != NULL) { - task = pid_task(pid_struct,PIDTYPE_PID); - if (task != NULL) { - process_returnValue = get_cmdline(task, full_process_name, sizeof(full_process_name)-1); - if (process_returnValue > 0) { - memcpy(sk->dns_process_name, full_process_name, sizeof(sk->dns_process_name)-1); - } else { - memcpy(sk->dns_process_name, task->comm, sizeof(task->comm)-1); - } - } - } - } - ret = 0; - } - -out: - return ret; -} - -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) { @@ -759,14 +666,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname, if (optname == SO_BINDTODEVICE) return sock_setbindtodevice(sk, optval, optlen); - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - if (optname == SO_SET_DOMAIN_NAME) - return sock_set_domain_name(sk, optval, optlen); - if (optname == SO_SET_DNS_UID) - return sock_set_dns_uid(sk, optval, optlen); - if (optname == SO_SET_DNS_PID) - return sock_set_dns_pid(sk, optval, optlen); - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } if (optlen < sizeof(int)) return -EINVAL; @@ -1617,63 +1516,10 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot, int kern) { struct sock *sk; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - struct pid *pid_struct = NULL; - struct task_struct *task = NULL; - int process_returnValue = -1; - char full_process_name[PROCESS_NAME_LEN_NAP] = {0}; - struct pid *parent_pid_struct = NULL; - struct task_struct *parent_task = NULL; - int parent_returnValue = -1; - char full_parent_process_name[PROCESS_NAME_LEN_NAP] = {0}; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } sk = sk_prot_alloc(prot, priority | __GFP_ZERO, family); if (sk) { sk->sk_family = family; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - /* assign values to members of sock structure when npa flag is present */ - sk->knox_uid = current->cred->uid.val; - sk->knox_pid = current->tgid; - sk->knox_puid = 0; - sk->knox_ppid = 0; - sk->knox_dns_uid = 0; - sk->knox_dns_pid = 0; - memset(sk->process_name,'\0',sizeof(sk->process_name)); - memset(sk->parent_process_name,'\0',sizeof(sk->parent_process_name)); - memset(sk->dns_process_name,'\0',sizeof(sk->dns_process_name)); - memset(sk->domain_name,'\0',sizeof(sk->domain_name)); - if (check_ncm_flag()) { - pid_struct = find_get_pid(current->tgid); - if (pid_struct != NULL) { - task = pid_task(pid_struct, PIDTYPE_PID); - if (task != NULL) { - process_returnValue = get_cmdline(task, full_process_name, sizeof(full_process_name)-1); - if (process_returnValue > 0) { - memcpy(sk->process_name, full_process_name, sizeof(sk->process_name)-1); - } else { - memcpy(sk->process_name, task->comm, sizeof(task->comm)-1); - } - if (task->parent != NULL) { - parent_pid_struct = find_get_pid(task->parent->tgid); - if (parent_pid_struct != NULL) { - parent_task = pid_task(parent_pid_struct, PIDTYPE_PID); - if (parent_task != NULL) { - parent_returnValue = get_cmdline(parent_task, full_parent_process_name, sizeof(full_parent_process_name)-1); - if (parent_returnValue > 0) { - memcpy(sk->parent_process_name, full_parent_process_name, sizeof(sk->parent_process_name)-1); - } else { - memcpy(sk->parent_process_name, parent_task->comm, sizeof(parent_task->comm)-1); - } - sk->knox_puid = parent_task->cred->uid.val; - sk->knox_ppid = parent_task->tgid; - } - } - } - } - } - } - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } /* * See comment in struct sock definition to understand * why we need sk_prot_creator -acme diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 821b91fc2..c59a2deee 100755 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -116,9 +116,6 @@ #include #include #include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -#include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } struct udp_table udp_table __read_mostly; EXPORT_SYMBOL(udp_table); @@ -2275,64 +2272,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (sk) { struct dst_entry *dst = skb_dst(skb); int ret; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - struct nf_conn *ct = NULL; - enum ip_conntrack_info ctinfo; - struct nf_conntrack_tuple *tuple = NULL; - char srcaddr[INET6_ADDRSTRLEN_NAP]; - char dstaddr[INET6_ADDRSTRLEN_NAP]; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } if (unlikely(sk->sk_rx_dst != dst)) udp_sk_rx_dst_set(sk, dst); - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - /* function to handle open flows with incoming udp packets */ - if (check_ncm_flag()) { - if ( (sk) && (sk->sk_protocol == IPPROTO_UDP) ) { - ct = nf_ct_get(skb, &ctinfo); - if ( (ct) && (!atomic_read(&ct->startFlow)) && (!nf_ct_is_dying(ct)) ) { - tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - if (tuple) { - sprintf(srcaddr,"%pI4",(void *)&tuple->src.u3.ip); - sprintf(dstaddr,"%pI4",(void *)&tuple->dst.u3.ip); - if ( !isIpv4AddressEqualsNull(srcaddr, dstaddr) ) { - atomic_set(&ct->startFlow, 1); - if ( check_intermediate_flag() ) { - /* Use 'atomic_set(&ct->intermediateFlow, 1); ct->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ);' if struct nf_conn->timeout is of type u32; */ - ct->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ); - atomic_set(&ct->intermediateFlow, 1); - /* Use 'unsigned long timeout = ct->timeout.expires - jiffies; - if ( (timeout > 0) && ((timeout/HZ) > 5) ) { - atomic_set(&ct->intermediateFlow, 1); - ct->npa_timeout.expires = (jiffies) + (get_intermediate_timeout() * HZ); - add_timer(&ct->npa_timeout); - }' - if struct nf_conn->timeout is of type struct timer_list; */ - } - ct->knox_uid = sk->knox_uid; - ct->knox_pid = sk->knox_pid; - memcpy(ct->process_name,sk->process_name,sizeof(ct->process_name)-1); - ct->knox_puid = sk->knox_puid; - ct->knox_ppid = sk->knox_ppid; - memcpy(ct->parent_process_name,sk->parent_process_name,sizeof(ct->parent_process_name)-1); - memcpy(ct->domain_name,sk->domain_name,sizeof(ct->domain_name)-1); - if ( (skb->dev) ) { - memcpy(ct->interface_name,skb->dev->name,sizeof(ct->interface_name)-1); - } else { - sprintf(ct->interface_name,"%s","null"); - } - if ( (tuple != NULL) && (ntohs(tuple->dst.u.udp.port) == DNS_PORT_NAP) && (ct->knox_uid == INIT_UID_NAP) && (sk->knox_dns_uid > INIT_UID_NAP) ) { - ct->knox_puid = sk->knox_dns_uid; - ct->knox_ppid = sk->knox_dns_pid; - memcpy(ct->parent_process_name,sk->dns_process_name,sizeof(ct->parent_process_name)-1); - } - knox_collect_conntrack_data(ct, NCM_FLOW_TYPE_OPEN, 3); - } - } - } - } - } - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } ret = udp_unicast_rcv_skb(sk, skb, uh); sock_put(sk); @@ -2344,62 +2286,8 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, saddr, daddr, udptable, proto); sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable); - if (sk) { - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - struct nf_conn *ct = NULL; - enum ip_conntrack_info ctinfo; - struct nf_conntrack_tuple *tuple = NULL; - char srcaddr[INET6_ADDRSTRLEN_NAP]; - char dstaddr[INET6_ADDRSTRLEN_NAP]; - /* function to handle open flows with incoming udp packets */ - if (check_ncm_flag()) { - if ( (sk) && (sk->sk_protocol == IPPROTO_UDP) ) { - ct = nf_ct_get(skb, &ctinfo); - if ( (ct) && (!atomic_read(&ct->startFlow)) && (!nf_ct_is_dying(ct)) ) { - tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - if (tuple) { - sprintf(srcaddr,"%pI4",(void *)&tuple->src.u3.ip); - sprintf(dstaddr,"%pI4",(void *)&tuple->dst.u3.ip); - if ( !isIpv4AddressEqualsNull(srcaddr, dstaddr) ) { - atomic_set(&ct->startFlow, 1); - if ( check_intermediate_flag() ) { - /* Use 'atomic_set(&ct->intermediateFlow, 1); ct->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ);' if struct nf_conn->timeout is of type u32; */ - ct->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ); - atomic_set(&ct->intermediateFlow, 1); - /* Use 'unsigned long timeout = ct->timeout.expires - jiffies; - if ( (timeout > 0) && ((timeout/HZ) > 5) ) { - atomic_set(&ct->intermediateFlow, 1); - ct->npa_timeout.expires = (jiffies) + (get_intermediate_timeout() * HZ); - add_timer(&ct->npa_timeout); - }' - if struct nf_conn->timeout is of type struct timer_list; */ - } - ct->knox_uid = sk->knox_uid; - ct->knox_pid = sk->knox_pid; - memcpy(ct->process_name,sk->process_name,sizeof(ct->process_name)-1); - ct->knox_puid = sk->knox_puid; - ct->knox_ppid = sk->knox_ppid; - memcpy(ct->parent_process_name,sk->parent_process_name,sizeof(ct->parent_process_name)-1); - memcpy(ct->domain_name,sk->domain_name,sizeof(ct->domain_name)-1); - if ( (skb->dev) ) { - memcpy(ct->interface_name,skb->dev->name,sizeof(ct->interface_name)-1); - } else { - sprintf(ct->interface_name,"%s","null"); - } - if ( (tuple != NULL) && (ntohs(tuple->dst.u.udp.port) == DNS_PORT_NAP) && (ct->knox_uid == INIT_UID_NAP) && (sk->knox_dns_uid > INIT_UID_NAP) ) { - ct->knox_puid = sk->knox_dns_uid; - ct->knox_ppid = sk->knox_dns_pid; - memcpy(ct->parent_process_name,sk->dns_process_name,sizeof(ct->parent_process_name)-1); - } - knox_collect_conntrack_data(ct, NCM_FLOW_TYPE_OPEN, 4); - } - } - } - } - } - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } + if (sk) return udp_unicast_rcv_skb(sk, skb, uh); - } if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) goto drop; diff --git a/net/ncm/Kconfig b/net/ncm/Kconfig deleted file mode 100755 index 3968fdffa..000000000 --- a/net/ncm/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -# -# Network Context Module Configuration -# - -config KNOX_NCM - tristate "Network Context Module Support" - depends on NET - default y diff --git a/net/ncm/Makefile b/net/ncm/Makefile deleted file mode 100755 index 91826351c..000000000 --- a/net/ncm/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_KNOX_NCM) := ncm.o \ No newline at end of file diff --git a/net/ncm/ncm.c b/net/ncm/ncm.c deleted file mode 100755 index 9cff07d42..000000000 --- a/net/ncm/ncm.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Network Context Metadata Module[NCM]:Implementation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// KNOX NPA - START - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#define SUCCESS 0 - -#define FAILURE 1 -/* fifo size in elements (bytes) */ -#define FIFO_SIZE 1024 -#define WAIT_TIMEOUT 10000 /*milliseconds */ -/* Lock to maintain orderly insertion of elements into kfifo */ -static DEFINE_MUTEX(ncm_lock); - -static unsigned int ncm_activated_flag = 1; - -static unsigned int ncm_deactivated_flag; // default = 0 - -static unsigned int intermediate_activated_flag = 1; - -static unsigned int intermediate_deactivated_flag; // default = 0 - -static unsigned int device_open_count; // default = 0 - -static int ncm_activated_type = NCM_FLOW_TYPE_DEFAULT; - -static struct nf_hook_ops nfho_ipv4_pr_conntrack; - -static struct nf_hook_ops nfho_ipv6_pr_conntrack; - -static struct nf_hook_ops nfho_ipv4_li_conntrack; - -static struct nf_hook_ops nfho_ipv6_li_conntrack; - -static struct workqueue_struct *eWq; // default = 0 - -wait_queue_head_t ncm_wq; - -static atomic_t isNCMEnabled = ATOMIC_INIT(0); - -static atomic_t isIntermediateFlowEnabled = ATOMIC_INIT(0); - -static unsigned int intermediate_flow_timeout; // default = 0 - -extern struct knox_socket_metadata knox_socket_metadata; - -DECLARE_KFIFO(knox_sock_info, struct knox_socket_metadata, FIFO_SIZE); - -/* The function is used to check if ncm feature has been enabled or not; The default value is disabled */ -unsigned int check_ncm_flag(void) { - return atomic_read(&isNCMEnabled); -} -EXPORT_SYMBOL(check_ncm_flag); - -/* This function is used to check if ncm feature has been enabled with intermediate flow feature */ -unsigned int check_intermediate_flag(void) { - return atomic_read(&isIntermediateFlowEnabled); -} -EXPORT_SYMBOL(check_intermediate_flag); - -/** The funcation is used to chedk if the kfifo is active or not; - * If the kfifo is active, then the socket metadata would be inserted into the queue which will be read by the user-space; - * By default the kfifo is inactive; - */ -bool kfifo_status(void) { - bool isKfifoActive = false; - if (kfifo_initialized(&knox_sock_info)) { - NCM_LOGD("The fifo queue for ncm was already intialized \n"); - isKfifoActive = true; - } else { - NCM_LOGE("The fifo queue for ncm is not intialized \n"); - isKfifoActive = false; - } - return isKfifoActive; -} -EXPORT_SYMBOL(kfifo_status); - -/** The function is used to insert the socket meta-data into the fifo queue; insertion of data will happen in a seperate kernel thread; - * The meta data information will be collected from the context of the process which originates it; - * If the kfifo is full, then the kfifo is freed before inserting new meta-data; - */ -void insert_data_kfifo(struct work_struct *pwork) { - struct knox_socket_metadata *knox_socket_metadata; - - knox_socket_metadata = container_of(pwork, struct knox_socket_metadata, work_kfifo); - if (IS_ERR(knox_socket_metadata)) { - NCM_LOGE("inserting data into the kfifo failed due to unknown error \n"); - goto err; - } - - if (mutex_lock_interruptible(&ncm_lock)) { - NCM_LOGE("inserting data into the kfifo failed due to an interuppt \n"); - goto err; - } - - if (kfifo_initialized(&knox_sock_info)) { - if (kfifo_is_full(&knox_sock_info)) { - NCM_LOGD("The kfifo is full and need to free it \n"); - kfree(knox_socket_metadata); - } else { - kfifo_in(&knox_sock_info, knox_socket_metadata, 1); - kfree(knox_socket_metadata); - } - } else { - kfree(knox_socket_metadata); - } - mutex_unlock(&ncm_lock); - return; - - err: - if (knox_socket_metadata != NULL) - kfree(knox_socket_metadata); - return; -} - -/** The function is used to insert the socket meta-data into the kfifo in a seperate kernel thread; - * The kernel threads which handles the responsibility of inserting the meta-data into the kfifo is manintained by the workqueue function; - */ -void insert_data_kfifo_kthread(struct knox_socket_metadata* knox_socket_metadata) { - if (knox_socket_metadata != NULL) - { - INIT_WORK(&(knox_socket_metadata->work_kfifo), insert_data_kfifo); - if (!eWq) { - NCM_LOGD("ewq ncmworkqueue not initialized. Data not collected\r\n"); - kfree(knox_socket_metadata); - } - if (eWq) { - queue_work(eWq, &(knox_socket_metadata->work_kfifo)); - } - } -} -EXPORT_SYMBOL(insert_data_kfifo_kthread); - - -/* The function is used to check if the caller is system server or not; */ -static int is_system_server(void) { - uid_t uid = current_uid().val; - switch (uid) { - case 1000: - return 1; - case 0: - return 1; - default: - break; - } - return 0; -} - -/* The function is used to intialize the kfifo */ -static void initialize_kfifo(void) { - INIT_KFIFO(knox_sock_info); - if (kfifo_initialized(&knox_sock_info)) { - NCM_LOGD("The kfifo for knox ncm has been initialized \n"); - init_waitqueue_head(&ncm_wq); - } -} - -/* The function is used to create work queue */ -static void initialize_ncmworkqueue(void) { - if (!eWq) { - NCM_LOGD("ewq..Single Thread created\r\n"); - eWq = create_workqueue("ncmworkqueue"); - } -} - -/* The function is ued to free the kfifo */ -static void free_kfifo(void) { - if (kfifo_status()) { - NCM_LOGD("The kfifo for knox ncm which was intialized is freed \n"); - kfifo_free(&knox_sock_info); - } -} - -/* The function is used to update the flag indicating whether the feature has been enabled or not */ -static void update_ncm_flag(unsigned int ncmFlag) { - if (ncmFlag == ncm_activated_flag) - atomic_set(&isNCMEnabled, ncm_activated_flag); - else - atomic_set(&isNCMEnabled, ncm_deactivated_flag); -} - -/* The function is used to update the flag indicating whether the intermediate flow feature has been enabled or not */ -static void update_intermediate_flag(unsigned int ncmIntermediateFlag) { - if (ncmIntermediateFlag == intermediate_activated_flag) - atomic_set(&isIntermediateFlowEnabled, intermediate_activated_flag); - else - atomic_set(&isIntermediateFlowEnabled, intermediate_deactivated_flag); -} - -/* The function is used to update the flag indicating start or stop flow */ -static void update_ncm_flow_type(int ncmFlowType) { - ncm_activated_type = ncmFlowType; -} - -/* This function is used to update the intermediate flow timeout value */ -static void update_intermediate_timeout(unsigned int timeout) { - intermediate_flow_timeout = timeout; -} - -/* This function is used to get the intermediate flow timeout value */ -unsigned int get_intermediate_timeout(void) { - return intermediate_flow_timeout; -} -EXPORT_SYMBOL(get_intermediate_timeout); - -/* IPv4 hook function to copy information from struct socket into struct nf_conn during first packet of the network flow */ -static unsigned int hook_func_ipv4_out_conntrack(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - - struct iphdr *ip_header = NULL; - struct tcphdr *tcp_header = NULL; - struct udphdr *udp_header = NULL; - struct nf_conn *ct = NULL; - enum ip_conntrack_info ctinfo; - struct nf_conntrack_tuple *tuple = NULL; - char srcaddr[INET6_ADDRSTRLEN_NAP]; - char dstaddr[INET6_ADDRSTRLEN_NAP]; - - if ( (skb) && (skb->sk) ) { - if ( (skb->sk->knox_pid == INIT_PID_NAP) && (skb->sk->knox_uid == INIT_UID_NAP) && (skb->sk->sk_protocol == IPPROTO_TCP) ) { - return NF_ACCEPT; - } - if ( (skb->sk->sk_protocol == IPPROTO_UDP) || (skb->sk->sk_protocol == IPPROTO_TCP) || (skb->sk->sk_protocol == IPPROTO_ICMP) || (skb->sk->sk_protocol == IPPROTO_SCTP) || (skb->sk->sk_protocol == IPPROTO_ICMPV6) ) { - ct = nf_ct_get(skb, &ctinfo); - if ( (ct) && (!atomic_read(&ct->startFlow)) && (!nf_ct_is_dying(ct)) ) { - tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - if (tuple) { - sprintf(srcaddr,"%pI4",(void *)&tuple->src.u3.ip); - sprintf(dstaddr,"%pI4",(void *)&tuple->dst.u3.ip); - if ( isIpv4AddressEqualsNull(srcaddr, dstaddr) ) { - return NF_ACCEPT; - } - } else { - return NF_ACCEPT; - } - atomic_set(&ct->startFlow, 1); - if ( check_intermediate_flag() ) { - /* Use 'atomic_set(&ct->intermediateFlow, 1); ct->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ);' if struct nf_conn->timeout is of type u32; */ - ct->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ); - atomic_set(&ct->intermediateFlow, 1); - /* Use 'unsigned long timeout = ct->timeout.expires - jiffies; - if ( (timeout > 0) && ((timeout/HZ) > 5) ) { - atomic_set(&ct->intermediateFlow, 1); - ct->npa_timeout.expires = (jiffies) + (get_intermediate_timeout() * HZ); - add_timer(&ct->npa_timeout); - }' - if struct nf_conn->timeout is of type struct timer_list; */ - } - ct->knox_uid = skb->sk->knox_uid; - ct->knox_pid = skb->sk->knox_pid; - memcpy(ct->process_name,skb->sk->process_name,sizeof(ct->process_name)-1); - ct->knox_puid = skb->sk->knox_puid; - ct->knox_ppid = skb->sk->knox_ppid; - memcpy(ct->parent_process_name,skb->sk->parent_process_name,sizeof(ct->parent_process_name)-1); - memcpy(ct->domain_name,skb->sk->domain_name,sizeof(ct->domain_name)-1); - if ( (skb->dev) ) { - memcpy(ct->interface_name,skb->dev->name,sizeof(ct->interface_name)-1); - } else { - sprintf(ct->interface_name,"%s","null"); - } - ip_header = (struct iphdr *)skb_network_header(skb); - if ( (ip_header) && (ip_header->protocol == IPPROTO_UDP) ) { - udp_header = (struct udphdr *)skb_transport_header(skb); - if (udp_header) { - int udp_payload_size = (ntohs(udp_header->len)) - sizeof(struct udphdr); - if ( (ct->knox_sent + udp_payload_size) > ULLONG_MAX ) - ct->knox_sent = ULLONG_MAX; - else - ct->knox_sent = ct->knox_sent + udp_payload_size; - if ( (ntohs(udp_header->dest) == DNS_PORT_NAP) && (ct->knox_uid == INIT_UID_NAP) && (skb->sk->knox_dns_uid > INIT_UID_NAP) ) { - ct->knox_puid = skb->sk->knox_dns_uid; - ct->knox_ppid = skb->sk->knox_dns_pid; - memcpy(ct->parent_process_name,skb->sk->dns_process_name,sizeof(ct->parent_process_name)-1); - } - } - } else if ( (ip_header) && (ip_header->protocol == IPPROTO_TCP) ) { - tcp_header = (struct tcphdr *)skb_transport_header(skb); - if (tcp_header) { - int tcp_payload_size = (ntohs(ip_header->tot_len)) - (ip_header->ihl * 4) - (tcp_header->doff * 4); - if ( (ct->knox_sent + tcp_payload_size) > ULLONG_MAX ) - ct->knox_sent = ULLONG_MAX; - else - ct->knox_sent = ct->knox_sent + tcp_payload_size; - if ( (ntohs(tcp_header->dest) == DNS_PORT_NAP) && (ct->knox_uid == INIT_UID_NAP) && (skb->sk->knox_dns_uid > INIT_UID_NAP) ) { - ct->knox_puid = skb->sk->knox_dns_uid; - ct->knox_ppid = skb->sk->knox_dns_pid; - memcpy(ct->parent_process_name,skb->sk->dns_process_name,sizeof(ct->parent_process_name)-1); - } - } - } else { - ct->knox_sent = 0; - } - knox_collect_conntrack_data(ct, NCM_FLOW_TYPE_OPEN, 1); - } else if ( (ct) && (!nf_ct_is_dying(ct)) ) { - ip_header = (struct iphdr *)skb_network_header(skb); - if ( (ip_header) && (ip_header->protocol == IPPROTO_UDP) ) { - udp_header = (struct udphdr *)skb_transport_header(skb); - if (udp_header) { - int udp_payload_size = (ntohs(udp_header->len)) - sizeof(struct udphdr); - if ( (ct->knox_sent + udp_payload_size) > ULLONG_MAX ) - ct->knox_sent = ULLONG_MAX; - else - ct->knox_sent = ct->knox_sent + udp_payload_size; - } - } else if ( (ip_header) && (ip_header->protocol == IPPROTO_TCP) ) { - tcp_header = (struct tcphdr *)skb_transport_header(skb); - if (tcp_header) { - int tcp_payload_size = (ntohs(ip_header->tot_len)) - (ip_header->ihl * 4) - (tcp_header->doff * 4); - if ( (ct->knox_sent + tcp_payload_size) > ULLONG_MAX ) - ct->knox_sent = ULLONG_MAX; - else - ct->knox_sent = ct->knox_sent + tcp_payload_size; - } - } else { - ct->knox_sent = 0; - } - } - } - } - - return NF_ACCEPT; -} - -/* IPv6 hook function to copy information from struct socket into struct nf_conn during first packet of the network flow */ -static unsigned int hook_func_ipv6_out_conntrack(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - struct ipv6hdr *ipv6_header = NULL; - struct tcphdr *tcp_header = NULL; - struct udphdr *udp_header = NULL; - struct nf_conn *ct = NULL; - enum ip_conntrack_info ctinfo; - struct nf_conntrack_tuple *tuple = NULL; - char srcaddr[INET6_ADDRSTRLEN_NAP]; - char dstaddr[INET6_ADDRSTRLEN_NAP]; - - if ( (skb) && (skb->sk) ) { - if ( (skb->sk->knox_pid == INIT_PID_NAP) && (skb->sk->knox_uid == INIT_UID_NAP) && (skb->sk->sk_protocol == IPPROTO_TCP) ) { - return NF_ACCEPT; - } - if ( (skb->sk->sk_protocol == IPPROTO_UDP) || (skb->sk->sk_protocol == IPPROTO_TCP) || (skb->sk->sk_protocol == IPPROTO_ICMP) || (skb->sk->sk_protocol == IPPROTO_SCTP) || (skb->sk->sk_protocol == IPPROTO_ICMPV6) ) { - ct = nf_ct_get(skb, &ctinfo); - if ( (ct) && (!atomic_read(&ct->startFlow)) && (!nf_ct_is_dying(ct)) ) { - tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - if (tuple) { - sprintf(srcaddr,"%pI6",(void *)&tuple->src.u3.ip6); - sprintf(dstaddr,"%pI6",(void *)&tuple->dst.u3.ip6); - if ( isIpv6AddressEqualsNull(srcaddr, dstaddr) ) { - return NF_ACCEPT; - } - } else { - return NF_ACCEPT; - } - atomic_set(&ct->startFlow, 1); - if ( check_intermediate_flag() ) { - /* Use 'atomic_set(&ct->intermediateFlow, 1); ct->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ);' if struct nf_conn->timeout is of type u32; */ - ct->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ); - atomic_set(&ct->intermediateFlow, 1); - /* Use 'unsigned long timeout = ct->timeout.expires - jiffies; - if ( (timeout > 0) && ((timeout/HZ) > 5) ) { - atomic_set(&ct->intermediateFlow, 1); - ct->npa_timeout.expires = (jiffies) + (get_intermediate_timeout() * HZ); - add_timer(&ct->npa_timeout); - }' - if struct nf_conn->timeout is of type struct timer_list; */ - } - ct->knox_uid = skb->sk->knox_uid; - ct->knox_pid = skb->sk->knox_pid; - memcpy(ct->process_name,skb->sk->process_name,sizeof(ct->process_name)-1); - ct->knox_puid = skb->sk->knox_puid; - ct->knox_ppid = skb->sk->knox_ppid; - memcpy(ct->parent_process_name,skb->sk->parent_process_name,sizeof(ct->parent_process_name)-1); - memcpy(ct->domain_name,skb->sk->domain_name,sizeof(ct->domain_name)-1); - if ( (skb->dev) ) { - memcpy(ct->interface_name,skb->dev->name,sizeof(ct->interface_name)-1); - } else { - sprintf(ct->interface_name,"%s","null"); - } - ipv6_header = (struct ipv6hdr *)skb_network_header(skb); - if ( (ipv6_header) && (ipv6_header->nexthdr == IPPROTO_UDP) ) { - udp_header = (struct udphdr *)skb_transport_header(skb); - if (udp_header) { - int udp_payload_size = (ntohs(udp_header->len)) - sizeof(struct udphdr); - if ( (ct->knox_sent + udp_payload_size) > ULLONG_MAX ) - ct->knox_sent = ULLONG_MAX; - else - ct->knox_sent = ct->knox_sent + udp_payload_size; - if ( (ntohs(udp_header->dest) == DNS_PORT_NAP) && (ct->knox_uid == INIT_UID_NAP) && (skb->sk->knox_dns_uid > INIT_UID_NAP) ) { - ct->knox_puid = skb->sk->knox_dns_uid; - ct->knox_ppid = skb->sk->knox_dns_pid; - memcpy(ct->parent_process_name,skb->sk->dns_process_name,sizeof(ct->parent_process_name)-1); - } - } - } else if ( (ipv6_header) && (ipv6_header->nexthdr == IPPROTO_TCP) ) { - tcp_header = (struct tcphdr *)skb_transport_header(skb); - if (tcp_header) { - int tcp_payload_size = (ntohs(ipv6_header->payload_len)) - (tcp_header->doff * 4); - if ( (ct->knox_sent + tcp_payload_size) > ULLONG_MAX ) - ct->knox_sent = ULLONG_MAX; - else - ct->knox_sent = ct->knox_sent + tcp_payload_size; - if ( (ntohs(tcp_header->dest) == DNS_PORT_NAP) && (ct->knox_uid == INIT_UID_NAP) && (skb->sk->knox_dns_uid > INIT_UID_NAP) ) { - ct->knox_puid = skb->sk->knox_dns_uid; - ct->knox_ppid = skb->sk->knox_dns_pid; - memcpy(ct->parent_process_name,skb->sk->dns_process_name,sizeof(ct->parent_process_name)-1); - } - } - } else { - ct->knox_sent = 0; - } - knox_collect_conntrack_data(ct, NCM_FLOW_TYPE_OPEN, 2); - } else if ( (ct) && (!nf_ct_is_dying(ct)) ) { - ipv6_header = (struct ipv6hdr *)skb_network_header(skb); - if ( (ipv6_header) && (ipv6_header->nexthdr == IPPROTO_UDP) ) { - udp_header = (struct udphdr *)skb_transport_header(skb); - if (udp_header) { - int udp_payload_size = (ntohs(udp_header->len)) - sizeof(struct udphdr); - if ( (ct->knox_sent + udp_payload_size) > ULLONG_MAX ) - ct->knox_sent = ULLONG_MAX; - else - ct->knox_sent = ct->knox_sent + udp_payload_size; - } - } else if ( (ipv6_header) && (ipv6_header->nexthdr == IPPROTO_TCP) ) { - tcp_header = (struct tcphdr *)skb_transport_header(skb); - if (tcp_header) { - int tcp_payload_size = (ntohs(ipv6_header->payload_len)) - (tcp_header->doff * 4); - if ( (ct->knox_sent + tcp_payload_size) > ULLONG_MAX ) - ct->knox_sent = ULLONG_MAX; - else - ct->knox_sent = ct->knox_sent + tcp_payload_size; - } - } else { - ct->knox_sent = 0; - } - } - } - } - - return NF_ACCEPT; -} - -static unsigned int hook_func_ipv4_in_conntrack(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - struct iphdr *ip_header = NULL; - struct tcphdr *tcp_header = NULL; - struct udphdr *udp_header = NULL; - struct nf_conn *ct = NULL; - enum ip_conntrack_info ctinfo; - - if (skb){ - ip_header = (struct iphdr *)skb_network_header(skb); - if ( (ip_header) && (ip_header->protocol == IPPROTO_TCP || ip_header->protocol == IPPROTO_UDP || ip_header->protocol == IPPROTO_SCTP || ip_header->protocol == IPPROTO_ICMP || ip_header->protocol == IPPROTO_ICMPV6) ) { - ct = nf_ct_get(skb, &ctinfo); - if ( (ct) && (!nf_ct_is_dying(ct)) ) { - if (ip_header->protocol == IPPROTO_TCP) { - tcp_header = (struct tcphdr *)skb_transport_header(skb); - if (tcp_header) { - int tcp_payload_size = (ntohs(ip_header->tot_len)) - (ip_header->ihl * 4) - (tcp_header->doff * 4); - if ( (ct->knox_recv + tcp_payload_size) > ULLONG_MAX ) - ct->knox_recv = ULLONG_MAX; - else - ct->knox_recv = ct->knox_recv + tcp_payload_size; - } - } else if (ip_header->protocol == IPPROTO_UDP) { - udp_header = (struct udphdr *)skb_transport_header(skb); - if (udp_header) { - int udp_payload_size = (ntohs(udp_header->len)) - sizeof(struct udphdr); - if ( (ct->knox_recv + udp_payload_size) > ULLONG_MAX ) - ct->knox_recv = ULLONG_MAX; - else - ct->knox_recv = ct->knox_recv + udp_payload_size; - } - } else { - ct->knox_recv = 0; - } - } - } - } - - return NF_ACCEPT; -} - -static unsigned int hook_func_ipv6_in_conntrack(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - struct ipv6hdr *ipv6_header = NULL; - struct tcphdr *tcp_header = NULL; - struct udphdr *udp_header = NULL; - struct nf_conn *ct = NULL; - enum ip_conntrack_info ctinfo; - - if (skb){ - ipv6_header = (struct ipv6hdr *)skb_network_header(skb); - if ( (ipv6_header) && (ipv6_header->nexthdr == IPPROTO_TCP || ipv6_header->nexthdr == IPPROTO_UDP || ipv6_header->nexthdr == IPPROTO_SCTP || ipv6_header->nexthdr == IPPROTO_ICMP || ipv6_header->nexthdr == IPPROTO_ICMPV6) ) { - ct = nf_ct_get(skb, &ctinfo); - if ( (ct) && (!nf_ct_is_dying(ct)) ) { - if (ipv6_header->nexthdr == IPPROTO_TCP) { - tcp_header = (struct tcphdr *)skb_transport_header(skb); - if (tcp_header) { - int tcp_payload_size = (ntohs(ipv6_header->payload_len)) - (tcp_header->doff * 4); - if ( (ct->knox_recv + tcp_payload_size) > ULLONG_MAX ) - ct->knox_recv = ULLONG_MAX; - else - ct->knox_recv = ct->knox_recv + tcp_payload_size; - } - } else if (ipv6_header->nexthdr == IPPROTO_UDP) { - udp_header = (struct udphdr *)skb_transport_header(skb); - if (udp_header) { - int udp_payload_size = (ntohs(udp_header->len)) - sizeof(struct udphdr); - if ( (ct->knox_recv + udp_payload_size) > ULLONG_MAX ) - ct->knox_recv = ULLONG_MAX; - else - ct->knox_recv = ct->knox_recv + udp_payload_size; - } - } else { - ct->knox_recv = 0; - } - } - } - } - - return NF_ACCEPT; -} - -/* The fuction registers to listen for packets in the post-routing chain to collect detail; */ -static void registerNetfilterHooks(void) { - nfho_ipv4_pr_conntrack.hook = hook_func_ipv4_out_conntrack; - nfho_ipv4_pr_conntrack.hooknum = NF_INET_POST_ROUTING; - nfho_ipv4_pr_conntrack.pf = PF_INET; - nfho_ipv4_pr_conntrack.priority = NF_IP_PRI_LAST; - - nfho_ipv6_pr_conntrack.hook = hook_func_ipv6_out_conntrack; - nfho_ipv6_pr_conntrack.hooknum = NF_INET_POST_ROUTING; - nfho_ipv6_pr_conntrack.pf = PF_INET6; - nfho_ipv6_pr_conntrack.priority = NF_IP6_PRI_LAST; - - nfho_ipv4_li_conntrack.hook = hook_func_ipv4_in_conntrack; - nfho_ipv4_li_conntrack.hooknum = NF_INET_LOCAL_IN; - nfho_ipv4_li_conntrack.pf = PF_INET; - nfho_ipv4_li_conntrack.priority = NF_IP_PRI_LAST; - - nfho_ipv6_li_conntrack.hook = hook_func_ipv6_in_conntrack; - nfho_ipv6_li_conntrack.hooknum = NF_INET_LOCAL_IN; - nfho_ipv6_li_conntrack.pf = PF_INET6; - nfho_ipv6_li_conntrack.priority = NF_IP6_PRI_LAST; - - /* For kernel versin below 4.13 - nf_register_hook(&nfho_ipv4_pr_conntrack); nf_register_hook(&nfho_ipv6_pr_conntrack); nf_register_hook(&nfho_ipv4_li_conntrack); nf_register_hook(&nfho_ipv6_li_conntrack); */ - - /* For kernel version above 4.13 */ - nf_register_net_hook(&init_net,&nfho_ipv4_pr_conntrack); - nf_register_net_hook(&init_net,&nfho_ipv6_pr_conntrack); - nf_register_net_hook(&init_net,&nfho_ipv4_li_conntrack); - nf_register_net_hook(&init_net,&nfho_ipv6_li_conntrack); -} - -/* The function un-registers the netfilter hook */ -static void unregisterNetFilterHooks(void) { - /* For kernel version below 4.13 - nf_unregister_hook(&nfho_ipv4_pr_conntrack); nf_unregister_hook(&nfho_ipv6_pr_conntrack); nf_unregister_hook(&nfho_ipv4_li_conntrack); nf_unregister_hook(&nfho_ipv6_li_conntrack); */ - - /* For kernel version above 4.13 */ - nf_unregister_net_hook(&init_net,&nfho_ipv4_pr_conntrack); - nf_unregister_net_hook(&init_net,&nfho_ipv6_pr_conntrack); - nf_unregister_net_hook(&init_net,&nfho_ipv4_li_conntrack); - nf_unregister_net_hook(&init_net,&nfho_ipv6_li_conntrack); -} - -/* Function to collect the conntrack meta-data information. This function is called from ncm.c during the flows first send data and nf_conntrack_core.c when flow is removed. */ -void knox_collect_conntrack_data(struct nf_conn *ct, int startStop, int where) { - if ( check_ncm_flag() && (ncm_activated_type == startStop || ncm_activated_type == NCM_FLOW_TYPE_ALL) ) { - struct knox_socket_metadata *ksm = kzalloc(sizeof(struct knox_socket_metadata), GFP_ATOMIC); - struct nf_conntrack_tuple *tuple = NULL; - struct timespec close_timespec; - - if (ksm == NULL) { - printk("kzalloc atomic memory allocation failed\n"); - return; - } - - ksm->knox_uid = ct->knox_uid; - ksm->knox_pid = ct->knox_pid; - memcpy(ksm->process_name, ct->process_name, sizeof(ksm->process_name)-1); - ksm->trans_proto = nf_ct_protonum(ct); - tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - if (tuple != NULL) { - if (nf_ct_l3num(ct) == IPV4_FAMILY_NAP) { - sprintf(ksm->srcaddr,"%pI4",(void *)&tuple->src.u3.ip); - sprintf(ksm->dstaddr,"%pI4",(void *)&tuple->dst.u3.ip); - } else if (nf_ct_l3num(ct) == IPV6_FAMILY_NAP) { - sprintf(ksm->srcaddr,"%pI6",(void *)&tuple->src.u3.ip6); - sprintf(ksm->dstaddr,"%pI6",(void *)&tuple->dst.u3.ip6); - } - if (nf_ct_protonum(ct) == IPPROTO_UDP) { - ksm->srcport = ntohs(tuple->src.u.udp.port); - ksm->dstport = ntohs(tuple->dst.u.udp.port); - } else if (nf_ct_protonum(ct) == IPPROTO_TCP) { - ksm->srcport = ntohs(tuple->src.u.tcp.port); - ksm->dstport = ntohs(tuple->dst.u.tcp.port); - } else if (nf_ct_protonum(ct) == IPPROTO_SCTP) { - ksm->srcport = ntohs(tuple->src.u.sctp.port); - ksm->dstport = ntohs(tuple->dst.u.sctp.port); - } else { - ksm->srcport = 0; - ksm->dstport = 0; - } - } - memcpy(ksm->domain_name, ct->domain_name, sizeof(ksm->domain_name)-1); - ksm->open_time = ct->open_time; - if (startStop == NCM_FLOW_TYPE_OPEN) { - ksm->close_time = 0; - } else if (startStop == NCM_FLOW_TYPE_CLOSE) { - close_timespec = current_kernel_time(); - ksm->close_time = close_timespec.tv_sec; - } else if (startStop == NCM_FLOW_TYPE_INTERMEDIATE) { - close_timespec = current_kernel_time(); - ksm->close_time = close_timespec.tv_sec; - } - ksm->knox_puid = ct->knox_puid; - ksm->knox_ppid = ct->knox_ppid; - memcpy(ksm->parent_process_name, ct->parent_process_name, sizeof(ksm->parent_process_name)-1); - if ( (nf_ct_protonum(ct) == IPPROTO_UDP) || (nf_ct_protonum(ct) == IPPROTO_TCP) || (nf_ct_protonum(ct) == IPPROTO_SCTP) ) { - ksm->knox_sent = ct->knox_sent; - ksm->knox_recv = ct->knox_recv; - } else { - ksm->knox_sent = 0; - ksm->knox_recv = 0; - } - if (ksm->dstport == DNS_PORT_NAP && ksm->knox_uid > INIT_UID_NAP) { - ksm->knox_uid_dns = ksm->knox_uid; - } else { - ksm->knox_uid_dns = ksm->knox_puid; - } - memcpy(ksm->interface_name, ct->interface_name, sizeof(ksm->interface_name)-1); - if (startStop == NCM_FLOW_TYPE_OPEN) { - ksm->flow_type = 1; - } else if (startStop == NCM_FLOW_TYPE_CLOSE) { - ksm->flow_type = 2; - } else if (startStop == NCM_FLOW_TYPE_INTERMEDIATE) { - ksm->flow_type = 3; - } else { - ksm->flow_type = 0; - } - - insert_data_kfifo_kthread(ksm); - } -} -EXPORT_SYMBOL(knox_collect_conntrack_data); - -/* The function opens the char device through which the userspace reads the socket meta-data information */ -static int ncm_open(struct inode *inode, struct file *file) { - NCM_LOGD("ncm_open is being called. \n"); - - if ( !(IS_ENABLED(CONFIG_NF_CONNTRACK)) ) { - NCM_LOGE("ncm_open failed:Trying to open in device conntrack module is not enabled \n"); - return -EACCES; - } - - if (!is_system_server()) { - NCM_LOGE("ncm_open failed:Caller is a non system process with uid %u \n", (current_uid().val)); - return -EACCES; - } - - if (device_open_count) { - NCM_LOGE("ncm_open failed:The device is already in open state \n"); - return -EBUSY; - } - - device_open_count++; - - try_module_get(THIS_MODULE); - - return SUCCESS; -} - -#ifdef CONFIG_64BIT -static ssize_t ncm_copy_data_user_64(char __user *buf, size_t count) -{ - struct knox_socket_metadata kcm = {0}; - struct knox_user_socket_metadata user_copy = {0}; - - unsigned long copied; - int read = 0; - - if (mutex_lock_interruptible(&ncm_lock)) { - NCM_LOGE("ncm_copy_data_user failed:Signal interuption \n"); - return 0; - } - read = kfifo_out(&knox_sock_info, &kcm, 1); - mutex_unlock(&ncm_lock); - if (read == 0) { - return 0; - } - - user_copy.srcport = kcm.srcport; - user_copy.dstport = kcm.dstport; - user_copy.trans_proto = kcm.trans_proto; - user_copy.knox_sent = kcm.knox_sent; - user_copy.knox_recv = kcm.knox_recv; - user_copy.knox_uid = kcm.knox_uid; - user_copy.knox_pid = kcm.knox_pid; - user_copy.knox_puid = kcm.knox_puid; - user_copy.open_time = kcm.open_time; - user_copy.close_time = kcm.close_time; - user_copy.knox_uid_dns = kcm.knox_uid_dns; - user_copy.knox_ppid = kcm.knox_ppid; - user_copy.flow_type = kcm.flow_type; - - memcpy(user_copy.srcaddr, kcm.srcaddr, sizeof(user_copy.srcaddr)); - memcpy(user_copy.dstaddr, kcm.dstaddr, sizeof(user_copy.dstaddr)); - - memcpy(user_copy.process_name, kcm.process_name, sizeof(user_copy.process_name)); - memcpy(user_copy.parent_process_name, kcm.parent_process_name, sizeof(user_copy.parent_process_name)); - - memcpy(user_copy.domain_name, kcm.domain_name, sizeof(user_copy.domain_name)-1); - - memcpy(user_copy.interface_name, kcm.interface_name, sizeof(user_copy.interface_name)-1); - - copied = copy_to_user(buf, &user_copy, sizeof(struct knox_user_socket_metadata)); - return count; -} -#else -static ssize_t ncm_copy_data_user(char __user *buf, size_t count) -{ - struct knox_socket_metadata *kcm = NULL; - struct knox_user_socket_metadata user_copy = {0}; - - unsigned long copied; - int read = 0; - - if (mutex_lock_interruptible(&ncm_lock)) { - NCM_LOGE("ncm_copy_data_user failed:Signal interuption \n"); - return 0; - } - - kcm = kzalloc(sizeof (struct knox_socket_metadata), GFP_KERNEL); - if (kcm == NULL) { - mutex_unlock(&ncm_lock); - return 0; - } - - read = kfifo_out(&knox_sock_info, kcm, 1); - mutex_unlock(&ncm_lock); - if (read == 0) { - kfree(kcm); - return 0; - } - - user_copy.srcport = kcm->srcport; - user_copy.dstport = kcm->dstport; - user_copy.trans_proto = kcm->trans_proto; - user_copy.knox_sent = kcm->knox_sent; - user_copy.knox_recv = kcm->knox_recv; - user_copy.knox_uid = kcm->knox_uid; - user_copy.knox_pid = kcm->knox_pid; - user_copy.knox_puid = kcm->knox_puid; - user_copy.open_time = kcm->open_time; - user_copy.close_time = kcm->close_time; - user_copy.knox_uid_dns = kcm->knox_uid_dns; - user_copy.knox_ppid = kcm->knox_ppid; - user_copy.flow_type = kcm->flow_type; - - memcpy(user_copy.srcaddr, kcm->srcaddr, sizeof(user_copy.srcaddr)); - memcpy(user_copy.dstaddr, kcm->dstaddr, sizeof(user_copy.dstaddr)); - - memcpy(user_copy.process_name, kcm->process_name, sizeof(user_copy.process_name)); - memcpy(user_copy.parent_process_name, kcm->parent_process_name, sizeof(user_copy.parent_process_name)); - - memcpy(user_copy.domain_name, kcm->domain_name, sizeof(user_copy.domain_name)-1); - - memcpy(user_copy.interface_name, kcm->interface_name, sizeof(user_copy.interface_name)-1); - - copied = copy_to_user(buf, &user_copy, sizeof(struct knox_user_socket_metadata)); - - kfree(kcm); - - return count; -} -#endif - -/* The function writes the socket meta-data to the user-space */ -static ssize_t ncm_read(struct file *file, char __user *buf, size_t count, loff_t *off) { - if (!is_system_server()) { - NCM_LOGE("ncm_read failed:Caller is a non system process with uid %u \n", (current_uid().val)); - return -EACCES; - } - - if (!eWq) { - NCM_LOGD("ewq..Single Thread created\r\n"); - eWq = create_workqueue("ncmworkqueue"); - } - - #ifdef CONFIG_64BIT - return ncm_copy_data_user_64(buf, count); - #else - return ncm_copy_data_user(buf, count); - #endif - - return 0; -} - -static ssize_t ncm_write(struct file *file, const char __user *buf, size_t count, loff_t *off) { - char intermediate_string[6]; - int intermediate_value = 0; - if (!is_system_server()) { - NCM_LOGE("ncm_write failed:Caller is a non system process with uid %u \n", (current_uid().val)); - return -EACCES; - } - memset(intermediate_string,'\0',sizeof(intermediate_string)); - copy_from_user(intermediate_string,buf,sizeof(intermediate_string)-1); - intermediate_value = simple_strtol(intermediate_string, NULL, 10); - if (intermediate_value > 0) { - update_intermediate_timeout(intermediate_value); - update_intermediate_flag(intermediate_activated_flag); - return strlen(intermediate_string); - } - return intermediate_value; -} - -/* The function closes the char device */ -static int ncm_close(struct inode *inode, struct file *file) { - NCM_LOGD("ncm_close is being called \n"); - if (!is_system_server()) { - NCM_LOGE("ncm_close failed:Caller is a non system process with uid %u \n", (current_uid().val)); - return -EACCES; - } - device_open_count--; - module_put(THIS_MODULE); - if (!check_ncm_flag()) { - NCM_LOGD("ncm_close success: The device was already in closed state \n"); - return SUCCESS; - } - update_ncm_flag(ncm_deactivated_flag); - free_kfifo(); - unregisterNetFilterHooks(); - return SUCCESS; -} - -/* The function sets the flag which indicates whether the ncm feature needs to be enabled or disabled */ -static long ncm_ioctl_evt(struct file *file, unsigned int cmd, unsigned long arg) { - if (!is_system_server()) { - NCM_LOGE("ncm_ioctl_evt failed:Caller is a non system process with uid %u \n", (current_uid().val)); - return -EACCES; - } - switch (cmd) { - case NCM_ACTIVATED_ALL: { - NCM_LOGD("ncm_ioctl_evt is being NCM_ACTIVATED with the ioctl command %u \n", cmd); - if (check_ncm_flag()) - return SUCCESS; - registerNetfilterHooks(); - initialize_kfifo(); - initialize_ncmworkqueue(); - update_ncm_flag(ncm_activated_flag); - update_ncm_flow_type(NCM_FLOW_TYPE_ALL); - break; - } - case NCM_ACTIVATED_OPEN: { - NCM_LOGD("ncm_ioctl_evt is being NCM_ACTIVATED with the ioctl command %u \n", cmd); - if (check_ncm_flag()) - return SUCCESS; - update_intermediate_timeout(0); - update_intermediate_flag(intermediate_deactivated_flag); - registerNetfilterHooks(); - initialize_kfifo(); - initialize_ncmworkqueue(); - update_ncm_flag(ncm_activated_flag); - update_ncm_flow_type(NCM_FLOW_TYPE_OPEN); - break; - } - case NCM_ACTIVATED_CLOSE: { - NCM_LOGD("ncm_ioctl_evt is being NCM_ACTIVATED with the ioctl command %u \n", cmd); - if (check_ncm_flag()) - return SUCCESS; - update_intermediate_timeout(0); - update_intermediate_flag(intermediate_deactivated_flag); - registerNetfilterHooks(); - initialize_kfifo(); - initialize_ncmworkqueue(); - update_ncm_flag(ncm_activated_flag); - update_ncm_flow_type(NCM_FLOW_TYPE_CLOSE); - break; - } - case NCM_DEACTIVATED: { - NCM_LOGD("ncm_ioctl_evt is being NCM_DEACTIVATED with the ioctl command %u \n", cmd); - if (!check_ncm_flag()) - return SUCCESS; - update_intermediate_flag(intermediate_deactivated_flag); - update_ncm_flow_type(NCM_FLOW_TYPE_DEFAULT); - update_ncm_flag(ncm_deactivated_flag); - free_kfifo(); - unregisterNetFilterHooks(); - update_intermediate_timeout(0); - break; - } - case NCM_GETVERSION: { - NCM_LOGD("ncm_ioctl_evt is being NCM_GETVERSION with the ioctl command %u \n", cmd); - return NCM_VERSION; - break; - } - case NCM_MATCH_VERSION: { - NCM_LOGD("ncm_ioctl_evt is being NCM_MATCH_VERSION with the ioctl command %u \n", cmd); - return sizeof(struct knox_user_socket_metadata); - break; - } - default: - break; - } - return SUCCESS; -} - -static unsigned int ncm_poll(struct file *file, poll_table *pt) { - int mask = 0; - int ret = 0; - if (kfifo_is_empty(&knox_sock_info)) { - ret = wait_event_interruptible_timeout(ncm_wq, !kfifo_is_empty(&knox_sock_info), msecs_to_jiffies(WAIT_TIMEOUT)); - switch (ret) { - case -ERESTARTSYS: - mask = -EINTR; - break; - case 0: - mask = 0; - break; - case 1: - mask |= POLLIN | POLLRDNORM; - break; - default: - mask |= POLLIN | POLLRDNORM; - break; - } - return mask; - } else { - mask |= POLLIN | POLLRDNORM; - } - return mask; -} - -static const struct file_operations ncm_fops = { - .owner = THIS_MODULE, - .open = ncm_open, - .read = ncm_read, - .write = ncm_write, - .release = ncm_close, - .unlocked_ioctl = ncm_ioctl_evt, - .compat_ioctl = ncm_ioctl_evt, - .poll = ncm_poll, -}; - -struct miscdevice ncm_misc_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = "ncm_dev", - .fops = &ncm_fops, -}; - -static int __init ncm_init(void) { - int ret; - ret = misc_register(&ncm_misc_device); - if (unlikely(ret)) { - NCM_LOGE("failed to register ncm misc device!\n"); - return ret; - } - NCM_LOGD("Network Context Metadata Module: initialized\n"); - return SUCCESS; -} - -static void __exit ncm_exit(void) { - misc_deregister(&ncm_misc_device); - NCM_LOGD("Network Context Metadata Module: unloaded\n"); -} - -module_init(ncm_init) -module_exit(ncm_exit) - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Network Context Metadata Module:"); - -// KNOX NPA - END diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 72ce5b43b..ad603cda7 100755 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -205,7 +205,6 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o -obj-y += xt_domainfilter.o # ipset obj-$(CONFIG_IP_SET) += ipset/ diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index e564997b7..27b1ad43e 100755 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -58,9 +58,6 @@ #include #include "nf_internals.h" -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { -#include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } __cacheline_aligned_in_smp spinlock_t nf_conntrack_locks[CONNTRACK_LOCKS]; EXPORT_SYMBOL_GPL(nf_conntrack_locks); @@ -472,13 +469,6 @@ clean_from_lists(struct nf_conn *ct) static void nf_ct_add_to_dying_list(struct nf_conn *ct) { struct ct_pcpu *pcpu; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - /* Add 'del_timer(&ct->npa_timeout)' if struct nf_conn->timeout is of type struct timer_list; */ - /* send dying conntrack entry to collect data */ - if ( (check_ncm_flag()) && (ct != NULL) && (atomic_read(&ct->startFlow)) ) { - knox_collect_conntrack_data(ct, NCM_FLOW_TYPE_CLOSE, 10); - } - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } /* add this conntrack to the (per cpu) dying list */ ct->cpu = smp_processor_id(); @@ -1240,15 +1230,7 @@ static void gc_worker(struct work_struct *work) if (nf_ct_is_expired(tmp)) { nf_ct_gc_expired(tmp); continue; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - } else if ( (tmp != NULL) && (check_ncm_flag()) && (check_intermediate_flag()) && (atomic_read(&tmp->startFlow)) && (atomic_read(&tmp->intermediateFlow)) ) { - s32 npa_timeout = tmp->npa_timeout - ((u32)(jiffies)); - if (npa_timeout <= 0) { - tmp->npa_timeout = ((u32)(jiffies)) + (get_intermediate_timeout() * HZ); - knox_collect_conntrack_data(tmp, NCM_FLOW_TYPE_INTERMEDIATE, 20); - } } - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } if (nf_conntrack_max95 == 0 || gc_worker_skip_ct(tmp)) continue; @@ -1318,9 +1300,6 @@ __nf_conntrack_alloc(struct net *net, gfp_t gfp, u32 hash) { struct nf_conn *ct; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - struct timespec open_timespec; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } /* We don't want any race condition at early drop stage */ atomic_inc(&net->ct.count); @@ -1345,28 +1324,6 @@ __nf_conntrack_alloc(struct net *net, goto out; spin_lock_init(&ct->lock); - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA { - /* initialize the conntrack structure members when memory is allocated */ - if (ct != NULL) { - open_timespec = current_kernel_time(); - ct->open_time = open_timespec.tv_sec; - ct->knox_uid = 0; - ct->knox_pid = 0; - memset(ct->process_name,'\0',sizeof(ct->process_name)); - memset(ct->domain_name,'\0',sizeof(ct->domain_name)); - ct->knox_puid = 0; - ct->knox_ppid = 0; - memset(ct->parent_process_name,'\0',sizeof(ct->parent_process_name)); - ct->knox_sent = 0; - ct->knox_recv = 0; - memset(ct->interface_name,'\0',sizeof(ct->interface_name)); - atomic_set(&ct->startFlow, 0); - /* Use 'ct->npa_timeout = 0' if struct nf_conn->timeout is of type u32; - Use 'setup_timer(&ct->npa_timeout, death_by_timeout_npa, (unsigned long)ct)' if struct nf_conn->timeout is of type struct timer_list; */ - ct->npa_timeout = 0; - atomic_set(&ct->intermediateFlow, 0); - } - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_NPA } ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL; ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index 5f13794e8..29c38aa7f 100755 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c @@ -27,13 +27,6 @@ #include #include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { -#include -#include -#include -#include -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } - MODULE_AUTHOR("Henrik Nordstrom "); MODULE_DESCRIPTION("Xtables: connection mark operations"); MODULE_LICENSE("GPL"); @@ -42,64 +35,6 @@ MODULE_ALIAS("ip6t_CONNMARK"); MODULE_ALIAS("ipt_connmark"); MODULE_ALIAS("ip6t_connmark"); -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { -/* KNOX framework uses mark value 100 to 500 - * when the special meta data is added - * This will indicate to the kernel code that - * it needs to append meta data to the packets - */ - -#define META_MARK_BASE_LOWER 100 -#define META_MARK_BASE_UPPER 500 - -/* Structure to hold metadata values - * intended for VPN clients to make - * more intelligent decisions - * when the KNOX meta mark - * feature is enabled - */ - -struct knox_meta_param { - uid_t uid; - pid_t pid; -}; - -static unsigned int knoxvpn_uidpid(struct sk_buff *skb, u_int32_t newmark) -{ - int szMetaData; - struct skb_shared_info *knox_shinfo = NULL; - - szMetaData = sizeof(struct knox_meta_param); - if (skb != NULL) { - knox_shinfo = skb_shinfo(skb); - } else { - pr_err("KNOX: NULL SKB - no KNOX processing"); - return -1; - } - - if (skb->sk == NULL) { - pr_err("KNOX: skb->sk value is null"); - return -1; - } - - if (knox_shinfo == NULL) { - pr_err("KNOX: knox_shinfo is null"); - return -1; - } - - if (newmark < META_MARK_BASE_LOWER || newmark > META_MARK_BASE_UPPER) { - pr_err("KNOX: The mark is out of range"); - return -1; - } else { - knox_shinfo->uid = skb->sk->knox_uid; - knox_shinfo->pid = skb->sk->knox_pid; - knox_shinfo->knox_mark = newmark; - } - - return 0; -} -// SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } - static unsigned int connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) { @@ -149,9 +84,6 @@ connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) newmark = (skb->mark & ~info->nfmask) ^ new_targetmark; skb->mark = newmark; - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN { - knoxvpn_uidpid(skb, newmark); - // SEC_PRODUCT_FEATURE_KNOX_SUPPORT_VPN } break; } return XT_CONTINUE; diff --git a/net/netfilter/xt_domainfilter.c b/net/netfilter/xt_domainfilter.c deleted file mode 100755 index baa3322b4..000000000 --- a/net/netfilter/xt_domainfilter.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. - * - * Domain Filter Module:Implementation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include - -/* - * Check if a given string is the ending substring of another. - */ -bool endsWith(const char *host, const char *rule) { - size_t hostLen = strlen(host); - size_t ruleLen = strlen(rule); - if (hostLen >= ruleLen) { - unsigned int offSet = hostLen - ruleLen; - return strncmp(host + offSet , rule, ruleLen) == 0; - } else { - return false; - } -} - -/* - * Check if a given string is the beginning substring of another. - */ -bool beginsWith(const char *host, const char *rule) { - size_t hostLen = strlen(host); - size_t ruleLen = strlen(rule); - if (hostLen >= ruleLen) { - return strncmp(host, rule, ruleLen) == 0; - } else { - return false; - } -} - -/* - * Check if the given host matches the provided white/black list rules. - */ -bool matchHost(const char *rule, const char *host) { - size_t ruleLen = strlen(rule); - if (ruleLen == 1 && rule[0] == WILDCARD) { // rule is *, means all hosts - return true; - } - if (rule[0] == WILDCARD) { // starts with * - if (rule[ruleLen -1] == WILDCARD) { // also ends with * - // get the substring between the '*'s - char substrRule[XT_DOMAINFILTER_NAME_LEN]; - strncpy(substrRule, rule+1, ruleLen-2); - substrRule[ruleLen-2] = '\0'; - if(strstr(host, substrRule) != NULL) { - return true; - } - } else { // only starts with * - // remove * from beginning, so host must end if rule - char substrRule[XT_DOMAINFILTER_NAME_LEN]; - strncpy(substrRule, rule+1, ruleLen-1); - substrRule[ruleLen-1] = '\0'; - if (endsWith(host, substrRule)) - return true; - } - } else if (rule[ruleLen -1] == WILDCARD) { // only ends with '*' - char substrRule[XT_DOMAINFILTER_NAME_LEN]; - strncpy(substrRule, rule, ruleLen-1); - substrRule[ruleLen-1] = '\0'; - if (beginsWith(host, substrRule)) - return true; - } else if (strlen(host) == ruleLen && - strcmp(host, rule) == 0) { // exact match - return true; - } - return false; -} - -static int domainfilter_check(const struct xt_mtchk_param *par) -{ - struct xt_domainfilter_match_info *info = par->matchinfo; - if (!(info->flags & (XT_DOMAINFILTER_WHITE|XT_DOMAINFILTER_BLACK))) { - return -EINVAL; - } - return 0; -} - -static bool -domainfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) -{ - const struct xt_domainfilter_match_info *info = par->matchinfo; - struct sock *sk = skb_to_full_sk(skb); - - if (sk == NULL) { - return false; - } - - // check domain name match - if (sk->domain_name[0] != '\0') { - return matchHost(info->domain_name, sk->domain_name); - } - - // didn't match - return false; -} - -static struct xt_match domainfilter_mt_reg __read_mostly = { - .name = "domainfilter", - .revision = 1, - .family = NFPROTO_UNSPEC, - .checkentry = domainfilter_check, - .match = domainfilter_mt, - .matchsize = sizeof(struct xt_domainfilter_match_info), - .hooks = (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_LOCAL_IN), - .me = THIS_MODULE, -}; - -static int __init domainfilter_mt_init(void) -{ - return xt_register_match(&domainfilter_mt_reg); -} - -static void __exit domainfilter_mt_exit(void) -{ - xt_unregister_match(&domainfilter_mt_reg); -} - -module_init(domainfilter_mt_init); -module_exit(domainfilter_mt_exit); -MODULE_AUTHOR("Antonio Junqueira "); -MODULE_DESCRIPTION("Xtables: domain name matching"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_domainfilter"); -MODULE_ALIAS("ip6t_domainfilter"); diff --git a/security/Kconfig b/security/Kconfig index ebc40c779..bfb530278 100755 --- a/security/Kconfig +++ b/security/Kconfig @@ -231,7 +231,6 @@ config STATIC_USERMODEHELPER_PATH specify an empty string here (i.e. ""). source security/selinux/Kconfig -source security/samsung/defex_lsm/Kconfig source security/smack/Kconfig source security/tomoyo/Kconfig source security/apparmor/Kconfig @@ -239,7 +238,6 @@ source security/loadpin/Kconfig source security/yama/Kconfig source security/integrity/Kconfig -source "security/hdm/Kconfig" choice prompt "Default security module" @@ -280,9 +278,5 @@ config DEFAULT_SECURITY source "security/Kconfig.hardening" -source "security/samsung/defex_lsm/Kconfig" # ADDED BY LEGO AUTOMATICALLY: DO NOT SUBMIT -source "security/samsung/proca/Kconfig" # ADDED BY LEGO AUTOMATICALLY: DO NOT SUBMIT -source "security/samsung/proca/gaf/Kconfig" # ADDED BY LEGO AUTOMATICALLY: DO NOT SUBMIT -source "security/samsung/five/Kconfig" # ADDED BY LEGO AUTOMATICALLY: DO NOT SUBMIT endmenu diff --git a/security/Makefile b/security/Makefile index 34ed49138..312d3085a 100755 --- a/security/Makefile +++ b/security/Makefile @@ -10,7 +10,6 @@ subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor subdir-$(CONFIG_SECURITY_YAMA) += yama subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin -subdir-$(CONFIG_SECURITY_DEFEX) += samsung/defex_lsm # always enable default capabilities obj-y += commoncap.o @@ -26,16 +25,8 @@ obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ obj-$(CONFIG_SECURITY_YAMA) += yama/ obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ -obj-$(CONFIG_SECURITY_DEFEX) += samsung/defex_lsm/built-in.a obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o # Object integrity file lists subdir-$(CONFIG_INTEGRITY) += integrity -obj-$(CONFIG_INTEGRITY) += integrity/ - -# HDM driver -obj-$(CONFIG_HDM) += hdm/ -obj-y += samsung/defex_lsm/ # ADDED BY LEGO AUTOMATICALLY: DO NOT SUBMIT -obj-y += samsung/proca/ # ADDED BY LEGO AUTOMATICALLY: DO NOT SUBMIT -obj-y += samsung/proca/gaf/ # ADDED BY LEGO AUTOMATICALLY: DO NOT SUBMIT -obj-y += samsung/five/ # ADDED BY LEGO AUTOMATICALLY: DO NOT SUBMIT +obj-$(CONFIG_INTEGRITY) += integrity/ \ No newline at end of file diff --git a/security/hdm/Kconfig b/security/hdm/Kconfig deleted file mode 100755 index 2a9364e62..000000000 --- a/security/hdm/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -# @file Kconfig -# @brief Kconfig for HDM driver -# Copyright (c) 2019, Samsung Electronics Corporation. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 and -# only version 2 as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -config HDM - bool "HDM feature enable" - depends on !SEC_FACTORY - default n - help - This enables hdm driver - diff --git a/security/hdm/Makefile b/security/hdm/Makefile deleted file mode 100755 index 82cd31c72..000000000 --- a/security/hdm/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -#@file Makefile -#@brief Makefile for HDM driver -#Copyright (c) 2019, Samsung Electronics Corporation. All rights reserved. -# -#This program is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License version 2 and -#only version 2 as published by the Free Software Foundation. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -obj-$(CONFIG_HDM) += hdm.o diff --git a/security/hdm/hdm.c b/security/hdm/hdm.c deleted file mode 100755 index bec85985a..000000000 --- a/security/hdm/hdm.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * @file hdm.c - * @brief HDM Support - * Copyright (c) 2020, Samsung Electronics Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#if defined(CONFIG_ARCH_QCOM) -#include -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#if defined(CONFIG_ARCH_QCOM) -#include -#include -#include -#endif - -#include "hdm_log.h" - -int hdm_log_level = HDM_LOG_LEVEL; -void hdm_printk(int level, const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - if (hdm_log_level < level) - return; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - printk(KERN_INFO "%s %pV", TAG, &vaf); - - va_end(args); -} - -static ssize_t store_hdm_policy(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long mode = HDM_CMD_MAX; - int c, p; - - if (count == 0) { - hdm_err("%s count = 0\n", __func__); - goto error; - } - - if (kstrtoul(buf, 0, &mode)) { - goto error; - }; - - if (mode > HDM_CMD_MAX) { - hdm_err("%s command size max fail. %d\n", __func__, mode); - goto error; - } - hdm_info("%s: command id: 0x%x\n", __func__, (int)mode); - - c = (int)(mode & HDM_C_BITMASK); - p = (int)(mode & HDM_P_BITMASK); - - hdm_info("%s m:0x%x c:0x%x p:0x%x\n", __func__, (int)mode, c, p); - switch (c) { -#if defined(CONFIG_ARCH_QCOM) - case HDM_HYP_CALL: - hdm_info("%s HDM_HYP_CALL\n", __func__); - uh_call(UH_APP_HDM, 9, 0, p, 0, 0); - break; - case HDM_HYP_CALLP: - hdm_info("%s HDM_HYP_CALLP\n", __func__); - uh_call(UH_APP_HDM, 2, 0, p, 0, 0); - break; -#endif - default: - goto error; - } -error: - return count; -} -static DEVICE_ATTR(hdm_policy, 0220, NULL, store_hdm_policy); - -#if defined(CONFIG_ARCH_QCOM) -static uint64_t qseelog_shmbridge_handle; -static int __init __hdm_init_of(void) -{ - struct device_node *node; - struct resource r; - int ret; - phys_addr_t addr; - u64 size; - - uint32_t ns_vmids[] = {VMID_HLOS}; - uint32_t ns_vm_perms[] = {PERM_READ | PERM_WRITE}; - uint32_t ns_vm_nums = 1; - - int src_vmids[1] = {VMID_HLOS}; - int dest_vmids[1] = {VMID_CP_BITSTREAM}; - int dest_perms[1] = {PERM_READ | PERM_WRITE}; - - hdm_info("%s start\n", __func__); - - node = of_find_node_by_name(NULL, "samsung,sec_hdm"); - if (!node) { - hdm_err("failed of_find_node_by_name\n"); - return -ENODEV; - } - - node = of_parse_phandle(node, "memory-region", 0); - if (!node) { - hdm_err("no memory-region specified\n"); - return -EINVAL; - } - - - ret = of_address_to_resource(node, 0, &r); - if (ret) { - hdm_err("failed of_address_to_resource\n"); - return ret; - } - - addr = r.start; - size = resource_size(&r); - - ret = qtee_shmbridge_register(addr, size, ns_vmids, ns_vm_perms, - ns_vm_nums, PERM_READ | PERM_WRITE, &qseelog_shmbridge_handle); - if (ret) - hdm_err("failed to create bridge for qsee_log buffer\n"); - - ret = hyp_assign_phys(addr, size, src_vmids, 1, dest_vmids, dest_perms, 1); - if (ret) { - hdm_err("%s: failed for %pa address of size %zx rc:%d\n", - __func__, &addr, size, ret); - } - - hdm_info("%s done\n", __func__); - return 0; -} -#endif - -static int __init hdm_test_init(void) -{ - struct device *dev; -#if defined(CONFIG_ARCH_QCOM) - int err; -#endif - dev = sec_device_create(NULL, "hdm"); - WARN_ON(!dev); - if (IS_ERR(dev)) - hdm_err("%s Failed to create devce\n", __func__); - - if (device_create_file(dev, &dev_attr_hdm_policy) < 0) - hdm_err("%s Failed to create device file\n", __func__); - -#if defined(CONFIG_ARCH_QCOM) - err = __hdm_init_of(); - if (err) - return err; -#endif - - hdm_info("%s end\n", __func__); - return 0; -} - -module_init(hdm_test_init); diff --git a/security/hdm/hdm_log.h b/security/hdm/hdm_log.h deleted file mode 100755 index a6ba39db8..000000000 --- a/security/hdm/hdm_log.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * @file hdm_log.h - * @brief Header file for HDM log - * Copyright (c) 2019, Samsung Electronics Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __HDM_LOG_H__ -#define __HDM_LOG_H__ - -#include - -#define TAG "[sec_hdm]" - -void hdm_printk(int level, const char *fmt, ...); - -#define DEV_ERR (1) -#define DEV_WARN (2) -#define DEV_NOTI (3) -#define DEV_INFO (4) -#define DEV_DEBUG (5) -#define HDM_LOG_LEVEL DEV_INFO - -#define hdm_err(fmt, ...) hdm_printk(DEV_ERR, fmt, ## __VA_ARGS__) -#define hdm_warn(fmt, ...) hdm_printk(DEV_WARN, fmt, ## __VA_ARGS__) -#define hdm_noti(fmt, ...) hdm_printk(DEV_NOTI, fmt, ## __VA_ARGS__) -#define hdm_info(fmt, ...) hdm_printk(DEV_INFO, fmt, ## __VA_ARGS__) -#define hdm_debug(fmt, ...) hdm_printk(DEV_DEBUG, fmt, ## __VA_ARGS__) - -#endif //__HDM_LOG_H__ diff --git a/security/samsung/defex_lsm/Kconfig b/security/samsung/defex_lsm/Kconfig deleted file mode 100755 index a4e3221f0..000000000 --- a/security/samsung/defex_lsm/Kconfig +++ /dev/null @@ -1,31 +0,0 @@ -config SECURITY_DEFEX - bool "Defex Support" - depends on SECURITY && (!KCOV || SAMSUNG_PRODUCT_SHIP) - select CRYPTO - select CRYPTO_RSA - select CRYPTO_SHA1 - select CRYPTO_SHA256 - select CRYPTO_HASH_INFO - select INTEGRITY_SIGNATURE - select INTEGRITY_ASYMMETRIC_KEYS - default n - help - This selects the Defex support. - If you are unsure how to answer this question, answer N. - -config DEFEX_KERNEL_ONLY - bool "Defex Kernel Only" - depends on SECURITY_DEFEX - default n - help - This lets defex know whether kernel-only build or not. - Default value will be set to "y" if the build is kernel-only. - And it will be changed to "n" by build.py at platform-build. - -config SECURITY_DEFEX_USER - bool "Defex USER build" - depends on SECURITY_DEFEX - default n - help - This lets defex to know whether USER build performed or not - in case of TARGET_BUILD_VARIANT variable is empty. diff --git a/security/samsung/defex_lsm/Makefile b/security/samsung/defex_lsm/Makefile deleted file mode 100755 index 93d2fcbf4..000000000 --- a/security/samsung/defex_lsm/Makefile +++ /dev/null @@ -1,237 +0,0 @@ -# -# Makefile for the Defex -# - -# Features to Enable -PED_ENABLE=true -SAFEPLACE_ENABLE=true -IMMUTABLE_ENABLE=true -LP_ENABLE=true -UMH_RESTRICTION_ENABLE=true -TRUSTED_MAP_ENABLE=false -USER_BUILD=false - -# Additional debug -LOG_BUFFER_ENABLE=false -SHOW_RULES_ENABLE=false - -ifeq (,$(TARGET_BUILD_VARIANT)) - ifeq ($(CONFIG_SECURITY_DEFEX_USER),y) - USER_BUILD := true - endif -else - ifeq ($(TARGET_BUILD_VARIANT),user) - USER_BUILD := true - endif -endif - -ifneq ($(wildcard $(srctree)/include/crypto/internal/rsa.h),) - $(warning [DEFEX] INTEGRITY_ENABLE) - INTEGRITY_ENABLE=true -endif - -# caches to enable -CACHES_ENABLE=true - -# OEM Unlock dependency -OEM_UNLOCK_DEPENDENCY=true - -# use the ramdisk or system_root to store rules file -RAMDISK_ENABLE=true - -# do signing for rules -SIGN_ENABLE=true - -defex-y := core/defex_common.o -defex-y += core/defex_lsm.o -defex-y += core/defex_main.o -defex-y += core/defex_get_mode.o -defex-y += core/defex_rules_proc.o -defex-y += core/defex_tailer.o -defex-y += catch_engine/defex_catch_list.o -defex-y += catch_engine/defex_ht.o -defex-y += defex_rules.o -defex-$(CONFIG_COMPAT) += catch_engine/defex_catch_list_compat.o - -# Immutable Feature is applied with permissive mode first. -DEFEX_DEFINES := -DDEFEX_PERMISSIVE_IM - -# Integrity Feature is applied with permissive mode first. -DEFEX_DEFINES += -DDEFEX_PERMISSIVE_INT - -ifeq ($(CONFIG_DEFEX_KERNEL_ONLY), y) - DEFEX_DEFINES += -DDEFEX_KERNEL_ONLY - ifeq ($(CONFIG_SAMSUNG_PRODUCT_SHIP), y) - $(warning [DEFEX] Kernel_only & Ship) - else - $(warning [DEFEX] Kernel_only & Noship) - defex-y += debug/defex_debug.o - defex-y += core/defex_sysfs.o - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_INT - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_SP - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_TM - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_IM - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_LP - DEFEX_DEFINES += -DDEFEX_DEBUG_ENABLE - ifeq ($(LOG_BUFFER_ENABLE), true) - DEFEX_DEFINES += -DDEFEX_LOG_BUFFER_ENABLE - endif - ifeq ($(SHOW_RULES_ENABLE), true) - defex-y += debug/defex_rules_show.o - DEFEX_DEFINES += -DDEFEX_SHOW_RULES_ENABLE - endif - endif -endif - -ifeq ($(CONFIG_SEC_FACTORY), y) - DEFEX_DEFINES += -DDEFEX_FACTORY_ENABLE - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_LP -endif - -ifeq ($(PED_ENABLE), true) - defex-y += feature_privilege_escalation_detection/defex_priv.o - DEFEX_DEFINES += -DDEFEX_PED_ENABLE -endif - -ifeq ($(SAFEPLACE_ENABLE), true) - defex-y += feature_safeplace/defex_safeplace.o - DEFEX_DEFINES += -DDEFEX_SAFEPLACE_ENABLE -endif - -ifeq ($(INTEGRITY_ENABLE), true) - defex-y += feature_safeplace/defex_integrity.o - DEFEX_DEFINES += -DDEFEX_INTEGRITY_ENABLE -endif - -ifeq ($(IMMUTABLE_ENABLE), true) - defex-y += feature_immutable/defex_immutable.o - DEFEX_DEFINES += -DDEFEX_IMMUTABLE_ENABLE -endif - -ifeq ($(LP_ENABLE), true) - DEFEX_DEFINES += -DDEFEX_LP_ENABLE -endif - -ifeq ($(UMH_RESTRICTION_ENABLE), true) - DEFEX_DEFINES += -DDEFEX_UMH_RESTRICTION_ENABLE -endif - -ifeq ($(CACHES_ENABLE), true) - defex-y += catch_engine/defex_caches.o - DEFEX_DEFINES += -DDEFEX_CACHES_ENABLE -endif - -ifeq ($(OEM_UNLOCK_DEPENDENCY), true) - DEFEX_DEFINES += -DDEFEX_DEPENDING_ON_OEMUNLOCK -endif - -ifeq ($(RAMDISK_ENABLE), true) - DEFEX_DEFINES += -DDEFEX_RAMDISK_ENABLE -ifeq ($(SIGN_ENABLE), true) - defex-y += cert/defex_cert.o - defex-y += cert/defex_sign.o - DEFEX_DEFINES += -DDEFEX_SIGN_ENABLE -endif -endif - -ifeq ($(TRUSTED_MAP_ENABLE), true) - DEFEX_DEFINES += -DDEFEX_TRUSTED_MAP_ENABLE - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_TM - #DEFEX_DEFINES += -DDEFEX_TM_DEFAULT_POLICY_ENABLE - defex-y += feature_trusted_map/defex_trusted_map.o - defex-y += feature_trusted_map/dtm.o - defex-y += feature_trusted_map/dtm_engine.o - defex-y += feature_trusted_map/dtm_log.o - defex-y += feature_trusted_map/dtm_utils.o - defex-y += feature_trusted_map/ptree.o -endif - -ifeq ($(USER_BUILD), true) - $(warning [DEFEX] DEBUG_DISABLE) - ifeq ($(CONFIG_SECURITY_DSMS), y) - DEFEX_DEFINES += -DDEFEX_DSMS_ENABLE - endif -else - $(warning [DEFEX] DEBUG_ENABLE) - defex-y += debug/defex_debug.o - defex-y += core/defex_sysfs.o - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_INT - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_SP - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_TM - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_IM - DEFEX_DEFINES += -DDEFEX_PERMISSIVE_LP - DEFEX_DEFINES += -DDEFEX_DEBUG_ENABLE - ifeq ($(LOG_BUFFER_ENABLE), true) - DEFEX_DEFINES += -DDEFEX_LOG_BUFFER_ENABLE - endif - ifeq ($(SHOW_RULES_ENABLE), true) - defex-y += debug/defex_rules_show.o - DEFEX_DEFINES += -DDEFEX_SHOW_RULES_ENABLE - endif -endif - -# kunit tests options: -ifeq ($(CONFIG_SEC_KUNIT), y) - GCOV_PROFILE := y - DEFEX_DEFINES += -DDEFEX_KUNIT_ENABLED -else - DEFEX_DEFINES += -D__visible_for_testing=static -endif - -ccflags-y := -Wformat - -EXTRA_CFLAGS += -I$(srctree)/$(src) -EXTRA_AFLAGS += -Isecurity/samsung/defex_lsm -EXTRA_CFLAGS += -I$(srctree)/$(src)/cert -EXTRA_AFLAGS += -Isecurity/samsung/defex_lsm/cert - -ifneq ($(wildcard $(srctree)/$(src)/pack_rules.c),) - EXTRA_CFLAGS += $(DEFEX_DEFINES) - EXTRA_AFLAGS += $(DEFEX_DEFINES) - hostprogs := pack_rules - hostprogs-y := pack_rules - HOST_EXTRACFLAGS += $(DEFEX_DEFINES) - clean-files := $(obj)/defex_packed_rules.inc - DEPEND_LIST := $(obj)/pack_rules - - quiet_cmd_pack = PACK $< - cmd_pack = $(obj)/pack_rules -p $< $@ $(srctree)/$(src)/defex_packed_rules.bin - - quiet_cmd_mkey = MAKEKEY $< - cmd_mkey = cp -n $< $@ 2>/dev/null || true - - $(obj)/core/defex_rules_proc.o: $(obj)/pack_rules $(obj)/defex_packed_rules.inc - - $(obj)/cert/defex_cert.o: $(obj)/cert/pubkey_eng.der $(obj)/cert/pubkey_user.der - - $(obj)/cert/pubkey_eng.der: $(srctree)/$(src)/cert/x509_five_eng.der - $(call cmd,mkey) - - $(obj)/cert/pubkey_user.der: $(srctree)/$(src)/cert/x509_five_user.der - $(call cmd,mkey) - - SOURCE_RULES := $(srctree)/$(src)/defex_rules.c - ifneq ($(wildcard $(srctree)/$(src)/file_list),) - $(warning '[DEFEX] file_list found') - SOURCE_RULES := $(srctree)/$(src)/defex_rules_reduced.c - DEPEND_LIST += $(SOURCE_RULES) - DEPEND_LIST += $(srctree)/$(src)/file_list - clean-files += $(DEPEND_LIST) - - quiet_cmd_reduce = REDUCE $< - cmd_reduce = $(obj)/pack_rules -r $< $@ $(srctree)/$(src)/file_list - - $(srctree)/$(src)/defex_rules_reduced.c: $(srctree)/$(src)/defex_rules.c $(obj)/pack_rules - $(call cmd,reduce) - endif - - $(obj)/defex_packed_rules.inc: $(SOURCE_RULES) $(DEPEND_LIST) - $(call cmd,pack) - @cp -n $(obj)/pack_rules $(srctree)/$(src)/pack_rules 2>/dev/null || true - -else - EXTRA_CFLAGS += $(DEFEX_DEFINES) - EXTRA_AFLAGS += $(DEFEX_DEFINES) -endif - -obj-$(CONFIG_SECURITY_DEFEX) := $(defex-y) diff --git a/security/samsung/defex_lsm/catch_engine/defex_caches.c b/security/samsung/defex_lsm/catch_engine/defex_caches.c deleted file mode 100755 index a0123c42a..000000000 --- a/security/samsung/defex_lsm/catch_engine/defex_caches.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include "include/defex_caches.h" - -__visible_for_testing struct defex_file_cache_list file_cache; - -DEFINE_SPINLOCK(defex_caches_lock); - -void defex_file_cache_init(void) -{ - int i; - struct defex_file_cache_entry *current_entry; - unsigned long flags; - - spin_lock_irqsave(&defex_caches_lock, flags); - for (i = 0; i < FILE_CACHE_SIZE; i++) { - current_entry = &file_cache.entry[i]; - current_entry->next_entry = i + 1; - current_entry->prev_entry = i - 1; - current_entry->pid = -1; - current_entry->file_addr = NULL; - } - - file_cache.first_entry = 0; - file_cache.last_entry = FILE_CACHE_SIZE - 1; - - file_cache.entry[file_cache.first_entry].prev_entry = file_cache.last_entry; - file_cache.entry[file_cache.last_entry].next_entry = file_cache.first_entry; - spin_unlock_irqrestore(&defex_caches_lock, flags); -} - -void defex_file_cache_add(int pid, struct file *file_addr) -{ - struct defex_file_cache_entry *current_entry; - struct file *old_file_addr; - unsigned long flags; - - spin_lock_irqsave(&defex_caches_lock, flags); - - current_entry = &file_cache.entry[file_cache.last_entry]; - - current_entry->pid = pid; - - old_file_addr = current_entry->file_addr; - - current_entry->file_addr = file_addr; - current_entry->next_entry = file_cache.first_entry; - - file_cache.first_entry = file_cache.last_entry; - file_cache.last_entry = current_entry->prev_entry; - - spin_unlock_irqrestore(&defex_caches_lock, flags); - if (old_file_addr) { - fput(old_file_addr); - } -} - -void defex_file_cache_update(struct file *file_addr) -{ - struct defex_file_cache_entry *current_entry; - struct file *old_file_addr; - unsigned long flags; - - spin_lock_irqsave(&defex_caches_lock, flags); - current_entry = &file_cache.entry[file_cache.first_entry]; - old_file_addr = current_entry->file_addr; - current_entry->file_addr = file_addr; - spin_unlock_irqrestore(&defex_caches_lock, flags); - if (old_file_addr) - fput(old_file_addr); -} - -void defex_file_cache_delete(int pid) -{ - int current_index, cache_found = 0; - struct defex_file_cache_entry *current_entry; - struct file *old_file_addr = NULL; - unsigned long flags; - - spin_lock_irqsave(&defex_caches_lock, flags); - - current_index = file_cache.first_entry; - do { - current_entry = &file_cache.entry[current_index]; - if (current_entry->pid == pid) { - - if (current_index == file_cache.first_entry) { - file_cache.first_entry = current_entry->next_entry; - file_cache.last_entry = current_index; - cache_found = 1; - break; - } - if (current_index == file_cache.last_entry) { - cache_found = 1; - break; - } - file_cache.entry[current_entry->prev_entry].next_entry = current_entry->next_entry; - file_cache.entry[current_entry->next_entry].prev_entry = current_entry->prev_entry; - file_cache.entry[file_cache.first_entry].prev_entry = current_index; - file_cache.entry[file_cache.last_entry].next_entry = current_index; - - current_entry->next_entry = file_cache.first_entry; - current_entry->prev_entry = file_cache.last_entry; - - file_cache.last_entry = current_index; - - cache_found = 1; - break; - } - current_index = current_entry->next_entry; - } while (current_index != file_cache.first_entry); - - if (cache_found) { - old_file_addr = current_entry->file_addr; - current_entry->pid = -1; - current_entry->file_addr = NULL; - } - - spin_unlock_irqrestore(&defex_caches_lock, flags); - if (old_file_addr) - fput(old_file_addr); - return; -} - -struct file *defex_file_cache_find(int pid) -{ - int current_index, cache_found = 0; - struct defex_file_cache_entry *current_entry; - unsigned long flags; - - spin_lock_irqsave(&defex_caches_lock, flags); - - current_index = file_cache.first_entry; - do { - current_entry = &file_cache.entry[current_index]; - if (current_entry->pid == pid) { - if (current_index == file_cache.first_entry) { - cache_found = 1; - break; - } - if (current_index == file_cache.last_entry) { - current_entry->next_entry = file_cache.first_entry; - file_cache.first_entry = file_cache.last_entry; - file_cache.last_entry = current_entry->prev_entry; - cache_found = 1; - break; - } - file_cache.entry[current_entry->prev_entry].next_entry = current_entry->next_entry; - file_cache.entry[current_entry->next_entry].prev_entry = current_entry->prev_entry; - file_cache.entry[file_cache.first_entry].prev_entry = current_index; - file_cache.entry[file_cache.last_entry].next_entry = current_index; - - current_entry->next_entry = file_cache.first_entry; - current_entry->prev_entry = file_cache.last_entry; - - file_cache.first_entry = current_index; - - cache_found = 1; - break; - } - current_index = current_entry->next_entry; - } while (current_index != file_cache.first_entry); - - spin_unlock_irqrestore(&defex_caches_lock, flags); - - return (!cache_found)?NULL:current_entry->file_addr; -} diff --git a/security/samsung/defex_lsm/catch_engine/defex_catch_list.c b/security/samsung/defex_lsm/catch_engine/defex_catch_list.c deleted file mode 100755 index 935374761..000000000 --- a/security/samsung/defex_lsm/catch_engine/defex_catch_list.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "include/defex_catch_list.h" - -#ifdef DEFEX_KUNIT_ENABLED -#ifndef __NR_syscalls -#define __NR_syscalls 436 -#endif -#endif - -#define DEFEX_CATCH_COUNT __NR_syscalls -const int defex_nr_syscalls = DEFEX_CATCH_COUNT; - -#include "defex_catch_list.inc" - -const struct local_syscall_struct *get_local_syscall(int syscall_no) -{ - if ((unsigned int)syscall_no >= __NR_syscalls) - return NULL; - - if (!syscall_catch_arr[syscall_no].local_syscall && !syscall_catch_arr[syscall_no].err_code && syscall_no) { - return &syscall_catch_arr[0]; - } - - return &syscall_catch_arr[syscall_no]; -} - -int syscall_local2global(int syscall_no) -{ - int i; - for (i = 0; i < __NR_syscalls; i++) { - if (syscall_catch_arr[i].local_syscall == syscall_no) - return i; - } - return 0; -} diff --git a/security/samsung/defex_lsm/catch_engine/defex_catch_list.inc b/security/samsung/defex_lsm/catch_engine/defex_catch_list.inc deleted file mode 100755 index 34ff61126..000000000 --- a/security/samsung/defex_lsm/catch_engine/defex_catch_list.inc +++ /dev/null @@ -1,575 +0,0 @@ -static const struct local_syscall_struct syscall_catch_arr[DEFEX_CATCH_COUNT] = { - /* */ - [0] = { - .local_syscall = 0, - .err_code = -EPERM - }, - -#ifdef __NR_rmdir - SYSCALL_CATCH(rmdir, -EPERM), -#endif -#ifdef __NR_utimes - SYSCALL_CATCH(utimes, -EPERM), -#endif -#ifdef __NR_stat - SYSCALL_CATCH(stat, -EACCES), -#endif -#ifdef __NR_lstat - SYSCALL_CATCH(lstat, -EACCES), -#endif -#ifdef __NR_umount - SYSCALL_CATCH(umount, -EPERM), -#endif -#ifdef __NR_utime - SYSCALL_CATCH(utime, -EPERM), -#endif -#ifdef __NR_futimesat - SYSCALL_CATCH(futimesat, -EPERM), -#endif -#ifdef __NR_uselib - SYSCALL_CATCH(uselib, -EACCES), -#endif -#ifdef __NR_send - SYSCALL_CATCH(send, -EACCES), -#endif -#ifdef __NR_ustat - SYSCALL_CATCH(ustat, -EFAULT), -#endif -#ifdef __NR_getdents - SYSCALL_CATCH(getdents, -EFAULT), -#endif -#ifdef __NR_recv - SYSCALL_CATCH(recv, -EFAULT), -#endif -#ifdef __NR_fork - SYSCALL_CATCH(fork, -EINVAL), -#endif -#ifdef __NR_vfork - SYSCALL_CATCH(vfork, -EINVAL), -#endif -#ifdef __NR_sigprocmask - SYSCALL_CATCH(sigprocmask, -EFAULT), -#endif -#ifdef __NR_sigpending - SYSCALL_CATCH(sigpending, -EFAULT), -#endif -#ifdef __NR_sigaction - SYSCALL_CATCH(sigaction, -EFAULT), -#endif -#ifdef __NR_sigaltstack - SYSCALL_CATCH(sigaltstack, -EFAULT), -#endif -#ifdef __NR_sigsuspend - SYSCALL_CATCH(sigsuspend, -EFAULT), -#endif -#ifdef __NR_truncate64 - SYSCALL_CATCH(truncate64, -EPERM), -#endif -#ifdef __NR_ftruncate64 - SYSCALL_CATCH(ftruncate64, -EPERM), -#endif -#ifdef __NR_fstat64 - SYSCALL_CATCH(fstat64, -EACCES), -#endif -#ifdef __NR_fstatat64 - SYSCALL_CATCH(fstatat64, -EACCES), -#endif -#ifdef __NR_statfs64 - SYSCALL_CATCH(statfs64, -EACCES), -#endif -#ifdef __NR_stat64 - SYSCALL_CATCH(stat64, -EACCES), -#endif -#ifdef __NR_lstat64 - SYSCALL_CATCH(lstat64, -EACCES), -#endif -#ifdef __NR_eventfd - SYSCALL_CATCH(eventfd, -EINVAL), -#endif -#ifdef __NR_epoll_create - SYSCALL_CATCH(epoll_create, -EINVAL), -#endif -#ifdef __NR_shmget - SYSCALL_CATCH(shmget, -EPERM), -#endif -#ifdef __NR_shmctl - SYSCALL_CATCH(shmctl, -EPERM), -#endif -#ifdef __NR_semctl - SYSCALL_CATCH(semctl, -EPERM), -#endif -#ifdef __NR_move_pages - SYSCALL_CATCH(move_pages, -EPERM), -#endif -#ifdef __NR_lookup_dcookie - SYSCALL_CATCH(lookup_dcookie, -EPERM), -#endif -#ifdef __NR_truncate - SYSCALL_CATCH(truncate, -EPERM), -#endif -#ifdef __NR_ftruncate - SYSCALL_CATCH(ftruncate, -EPERM), -#endif -#ifdef __NR_chdir - SYSCALL_CATCH(chdir, -EPERM), -#endif -#ifdef __NR_chroot - SYSCALL_CATCH(chroot, -EPERM), -#endif -#ifdef __NR_fchmod - SYSCALL_CATCH(fchmod, -EPERM), -#endif -#ifdef __NR_fchmodat - SYSCALL_CATCH(fchmodat, -EPERM), -#endif -#ifdef __NR_fchownat - SYSCALL_CATCH(fchownat, -EPERM), -#endif -#ifdef __NR_fchown - SYSCALL_CATCH(fchown, -EPERM), -#endif -#ifdef __NR_mknodat - SYSCALL_CATCH(mknodat, -EPERM), -#endif -#ifdef __NR_mkdirat - SYSCALL_CATCH(mkdirat, -EPERM), -#endif -#ifdef __NR_unlinkat - SYSCALL_CATCH(unlinkat, -EPERM), -#endif -#ifdef __NR_symlinkat - SYSCALL_CATCH(symlinkat, -EPERM), -#endif -#ifdef __NR_linkat - SYSCALL_CATCH(linkat, -EPERM), -#endif -#ifdef __NR_renameat - SYSCALL_CATCH(renameat, -EPERM), -#endif -#ifdef __NR_umount2 - SYSCALL_CATCH(umount2, -EPERM), -#endif -#ifdef __NR_mount - SYSCALL_CATCH(mount, -EPERM), -#endif -#ifdef __NR_pivot_root - SYSCALL_CATCH(pivot_root, -EPERM), -#endif -#ifdef __NR_utimensat - SYSCALL_CATCH(utimensat, -EPERM), -#endif -#ifdef __NR_fcntl - SYSCALL_CATCH(fcntl, -EPERM), -#endif -#ifdef __NR_kexec_load - SYSCALL_CATCH(kexec_load, -EPERM), -#endif -#ifdef __NR_ptrace - SYSCALL_CATCH(ptrace, -EPERM), -#endif -#ifdef __NR_setgroups - SYSCALL_CATCH(setgroups, -EPERM), -#endif -#ifdef __NR_settimeofday - SYSCALL_CATCH(settimeofday, -EPERM), -#endif -#ifdef __NR_delete_module - SYSCALL_CATCH(delete_module, -EPERM), -#endif -#ifdef __NR_init_module - SYSCALL_CATCH(init_module, -EPERM), -#endif -#ifdef __NR_capset - SYSCALL_CATCH(capset, -EPERM), -#endif -#ifdef __NR_setpriority - SYSCALL_CATCH(setpriority, -EPERM), -#endif -#ifdef __NR_setregid - SYSCALL_CATCH(setregid, -EPERM), -#endif -#ifdef __NR_setfsuid - SYSCALL_CATCH(setfsuid, 0), //-EPERM -#endif -#ifdef __NR_setfsgid - SYSCALL_CATCH(setfsgid, 0), //-EPERM -#endif -#ifdef __NR_umask - SYSCALL_CATCH(umask, 0), //-EPERM -#endif -#ifdef __NR_setgid - SYSCALL_CATCH(setgid, -EPERM), -#endif -#ifdef __NR_setreuid - SYSCALL_CATCH(setreuid, -EPERM), -#endif -#ifdef __NR_setuid - SYSCALL_CATCH(setuid, -EPERM), -#endif -#ifdef __NR_setresuid - SYSCALL_CATCH(setresuid, -EPERM), -#endif -#ifdef __NR_setresgid - SYSCALL_CATCH(setresgid, -EPERM), -#endif -#ifdef __NR_setpgid - SYSCALL_CATCH(setpgid, -EPERM), -#endif -#ifdef __NR_getsid - SYSCALL_CATCH(getsid, -EPERM), -#endif -#ifdef __NR_setsid - SYSCALL_CATCH(setsid, -EPERM), -#endif -#ifdef __NR_sethostname - SYSCALL_CATCH(sethostname, -EPERM), -#endif -#ifdef __NR_setdomainname - SYSCALL_CATCH(setdomainname, -EPERM), -#endif -#ifdef __NR_setrlimit - SYSCALL_CATCH(setrlimit, -EPERM), -#endif -#ifdef __NR_prctl - SYSCALL_CATCH(prctl, -EPERM), -#endif -#ifdef __NR_getcpu - SYSCALL_CATCH(getcpu, -EPERM), -#endif -#ifdef __NR_kill - SYSCALL_CATCH(kill, -EPERM), -#endif -#ifdef __NR_tgkill - SYSCALL_CATCH(tgkill, -EPERM), -#endif -#ifdef __NR_tkill - SYSCALL_CATCH(tkill, -EPERM), -#endif -#ifdef __NR_rt_tgsigqueueinfo - SYSCALL_CATCH(rt_tgsigqueueinfo, -EPERM), -#endif -#ifdef __NR_rt_sigqueueinfo - SYSCALL_CATCH(rt_sigqueueinfo, -EPERM), -#endif -#ifdef __NR_listen - SYSCALL_CATCH(listen, -EPERM), -#endif -#ifdef __NR_accept - SYSCALL_CATCH(accept, -EPERM), -#endif -#ifdef __NR_open - SYSCALL_CATCH(open, 0), //-EPERM -#endif -#ifdef __NR_openat - SYSCALL_CATCH(openat, 0), //-EPERM -#endif -#ifdef __NR_shutdown - SYSCALL_CATCH(shutdown, -EBADF), -#endif -#ifdef __NR_shmat - SYSCALL_CATCH(shmat, -EACCES), -#endif -#ifdef __NR_shmdt - SYSCALL_CATCH(shmdt, -EACCES), -#endif -#ifdef __NR_semget - SYSCALL_CATCH(semget, -EACCES), -#endif -#ifdef __NR_semop - SYSCALL_CATCH(semop, -EACCES), -#endif -#ifdef __NR_faccessat - SYSCALL_CATCH(faccessat, -EACCES), -#endif -#ifdef __NR_fchdir - SYSCALL_CATCH(fchdir, -EACCES), -#endif -#ifdef __NR_fstat - SYSCALL_CATCH(fstat, -EACCES), -#endif -#ifdef __NR_readlinkat - SYSCALL_CATCH(readlinkat, -EACCES), -#endif -#ifdef __NR_statfs - SYSCALL_CATCH(statfs, -EACCES), -#endif -#ifdef __NR_fstatfs - SYSCALL_CATCH(fstatfs, -EACCES), -#endif -#ifdef __NR_getcwd - SYSCALL_CATCH(getcwd, -EACCES), -#endif -#ifdef __NR_futex - SYSCALL_CATCH(futex, -EACCES), -#endif -#ifdef __NR_perf_event_open - SYSCALL_CATCH(perf_event_open, -EACCES), -#endif -#ifdef __NR_socket - SYSCALL_CATCH(socket, -EACCES), -#endif -#ifdef __NR_bind - SYSCALL_CATCH(bind, -EACCES), -#endif -#ifdef __NR_connect - SYSCALL_CATCH(connect, -EACCES), -#endif -#ifdef __NR_sendto - SYSCALL_CATCH(sendto, -EACCES), -#endif -#ifdef __NR_mprotect - SYSCALL_CATCH(mprotect, -EACCES), -#endif -#ifdef __NR_mremap - SYSCALL_CATCH(mremap, -EFAULT), -#endif -#ifdef __NR_pselect6 - SYSCALL_CATCH(pselect6, -EFAULT), -#endif -#ifdef __NR_ioctl - SYSCALL_CATCH(ioctl, -EFAULT), -#endif -#ifdef __NR_ioprio_set - SYSCALL_CATCH(ioprio_set, -EFAULT), -#endif -#ifdef __NR_pipe2 - SYSCALL_CATCH(pipe2, -EFAULT), -#endif -#ifdef __NR_getdents64 - SYSCALL_CATCH(getdents64, -EFAULT), -#endif -#ifdef __NR_setitimer - SYSCALL_CATCH(setitimer, -EFAULT), -#endif -#ifdef __NR_capget - SYSCALL_CATCH(capget, -EFAULT), -#endif -#ifdef __NR_getresuid - SYSCALL_CATCH(getresuid, -EFAULT), -#endif -#ifdef __NR_getresgid - SYSCALL_CATCH(getresgid, -EFAULT), -#endif -#ifdef __NR_rt_sigprocmask - SYSCALL_CATCH(rt_sigprocmask, 0), //-EFAULT, Skip this syscall due to HTML5 score of Geekbench5.4 -#endif -#ifdef __NR_socketpair - SYSCALL_CATCH(socketpair, -EFAULT), -#endif -#ifdef __NR_getsockname - SYSCALL_CATCH(getsockname, -EFAULT), -#endif -#ifdef __NR_getpeername - SYSCALL_CATCH(getpeername, -EFAULT), -#endif -#ifdef __NR_recvfrom - SYSCALL_CATCH(recvfrom, -EFAULT), -#endif -#ifdef __NR_setsockopt - SYSCALL_CATCH(setsockopt, -EFAULT), -#endif -#ifdef __NR_sendmsg - SYSCALL_CATCH(sendmsg, -EFAULT), -#endif -#ifdef __NR_recvmsg - SYSCALL_CATCH(recvmsg, -EFAULT), -#endif -#ifdef __NR_rt_sigsuspend - SYSCALL_CATCH(rt_sigsuspend, -EFAULT), -#endif -#ifdef __NR_rt_sigpending - SYSCALL_CATCH(rt_sigpending, -EFAULT), -#endif -#ifdef __NR_rt_sigaction - SYSCALL_CATCH(rt_sigaction, -EFAULT), -#endif -#ifdef __NR_remap_file_pages - SYSCALL_CATCH(remap_file_pages, -EINVAL), -#endif -#ifdef __NR_ppoll - SYSCALL_CATCH(ppoll, -EINVAL), -#endif -#ifdef __NR_dup - SYSCALL_CATCH(dup, -EINVAL), -#endif -#ifdef __NR_dup3 - SYSCALL_CATCH(dup3, -EINVAL), -#endif -#ifdef __NR_eventfd2 - SYSCALL_CATCH(eventfd2, -EINVAL), -#endif -#ifdef __NR_timerfd_create - SYSCALL_CATCH(timerfd_create, -EINVAL), -#endif -#ifdef __NR_timerfd_gettime - SYSCALL_CATCH(timerfd_gettime, -EINVAL), -#endif -#ifdef __NR_timerfd_settime - SYSCALL_CATCH(timerfd_settime, -EINVAL), -#endif -#ifdef __NR_epoll_create1 - SYSCALL_CATCH(epoll_create1, -EINVAL), -#endif -#ifdef __NR_rt_sigtimedwait - SYSCALL_CATCH(rt_sigtimedwait, -EINVAL), -#endif -#ifdef __NR_setxattr - SYSCALL_CATCH(setxattr, -EEXIST), -#endif -#ifdef __NR_lsetxattr - SYSCALL_CATCH(lsetxattr, -EEXIST), -#endif -#ifdef __NR_fsetxattr - SYSCALL_CATCH(fsetxattr, -EEXIST), -#endif -#ifdef __NR_removexattr - SYSCALL_CATCH(removexattr, -EEXIST), -#endif -#ifdef __NR_lremovexattr - SYSCALL_CATCH(lremovexattr, -EEXIST), -#endif -#ifdef __NR_fremovexattr - SYSCALL_CATCH(fremovexattr, -EEXIST), -#endif -#ifdef __NR_inotify_init1 - SYSCALL_CATCH(inotify_init1, -EMFILE), -#endif -#ifdef __NR_clone - SYSCALL_CATCH(clone, -EINVAL), -#endif -#ifdef __NR_execve - SYSCALL_CATCH(execve, 0), //-EPERM -#endif -#ifdef __NR_write - SYSCALL_CATCH(write, 0), //-EPERM -#endif -#ifdef __NR_writev - SYSCALL_CATCH(writev, -EPERM), -#endif -#ifdef __NR_pwrite64 - SYSCALL_CATCH(pwrite64, -EPERM), -#endif -#ifdef __NR_pwritev - SYSCALL_CATCH(pwritev, -EPERM), -#endif -#ifdef __NR_epoll_ctl - SYSCALL_CATCH(epoll_ctl, -EINVAL), -#endif -#ifdef __NR_epoll_pwait - SYSCALL_CATCH(epoll_pwait, -EINVAL), -#endif -#ifdef __NR_sendfile - SYSCALL_CATCH(sendfile, -EFAULT), -#endif -#ifdef __NR_signalfd4 - SYSCALL_CATCH(signalfd4, -EFAULT), -#endif -#ifdef __NR_vmsplice - SYSCALL_CATCH(vmsplice, -EINVAL), -#endif -#ifdef __NR_splice - SYSCALL_CATCH(splice, -EINVAL), -#endif -#ifdef __NR_tee - SYSCALL_CATCH(tee, -EINVAL), -#endif -#ifdef __NR_fsync - SYSCALL_CATCH(fsync, -EINVAL), -#endif -#ifdef __NR_fdatasync - SYSCALL_CATCH(fdatasync, -EINVAL), -#endif -#ifdef __NR_sync_file_range - SYSCALL_CATCH(sync_file_range, -EINVAL), -#endif -#ifdef __NR_acct - SYSCALL_CATCH(acct, -EPERM), -#endif -#ifdef __NR_sched_setparam - SYSCALL_CATCH(sched_setparam, -EINVAL), -#endif -#ifdef __NR_sched_setscheduler - SYSCALL_CATCH(sched_setscheduler, -EINVAL), -#endif -#ifdef __NR_sched_setaffinity - SYSCALL_CATCH(sched_setaffinity, -EINVAL), -#endif -#ifdef __NR_reboot - SYSCALL_CATCH(reboot, -EPERM), -#endif -#ifdef __NR_mq_timedsend - SYSCALL_CATCH(mq_timedsend, -EINVAL), -#endif -#ifdef __NR_mq_timedreceive - SYSCALL_CATCH(mq_timedreceive, -EBADF), -#endif -#ifdef __NR_msgrcv - SYSCALL_CATCH(msgrcv, -EINVAL), -#endif -#ifdef __NR_msgsnd - SYSCALL_CATCH(msgsnd, -EFAULT), -#endif -#ifdef __NR_semtimedop - SYSCALL_CATCH(semtimedop, -EINVAL), -#endif -#ifdef __NR_add_key - SYSCALL_CATCH(add_key, -EINVAL), -#endif -#ifdef __NR_request_key - SYSCALL_CATCH(request_key, -EINVAL), -#endif -#ifdef __NR_keyctl - SYSCALL_CATCH(keyctl, -EOPNOTSUPP), -#endif -#ifdef __NR_mmap - SYSCALL_CATCH(mmap, -EINVAL), -#endif -#ifdef __NR_mincore - SYSCALL_CATCH(mincore, -EINVAL), -#endif -#ifdef __NR_mbind - SYSCALL_CATCH(mbind, -EINVAL), -#endif -#ifdef __NR_set_mempolicy - SYSCALL_CATCH(set_mempolicy, -EINVAL), -#endif -#ifdef __NR_migrate_pages - SYSCALL_CATCH(migrate_pages, -EINVAL), -#endif -#ifdef __NR_accept4 - SYSCALL_CATCH(accept4, -EINVAL), -#endif -#ifdef __NR_recvmmsg - SYSCALL_CATCH(recvmmsg, -EINVAL), -#endif -#ifdef __NR_link - SYSCALL_CATCH(link, -EPERM), -#endif -#ifdef __NR_unlink - SYSCALL_CATCH(unlink, -EPERM), -#endif -#ifdef __NR_mknod - SYSCALL_CATCH(mknod, -EPERM), -#endif -#ifdef __NR_chmod - SYSCALL_CATCH(chmod, -EPERM), -#endif -#ifdef __NR_chown - SYSCALL_CATCH(chown, -EPERM), -#endif -#ifdef __NR_mkdir - SYSCALL_CATCH(mkdir, -EPERM), -#endif -#ifdef __NR_lchown - SYSCALL_CATCH(lchown, -EPERM), -#endif -#ifdef __NR_rename - SYSCALL_CATCH(rename, -EPERM), -#endif -#ifdef __NR_epoll_wait - SYSCALL_CATCH(epoll_wait, -EINVAL), -#endif -#ifdef __NR_sysctl - SYSCALL_CATCH(sysctl, -EFAULT), -#endif -}; diff --git a/security/samsung/defex_lsm/catch_engine/defex_catch_list_compat.c b/security/samsung/defex_lsm/catch_engine/defex_catch_list_compat.c deleted file mode 100755 index df9ee085a..000000000 --- a/security/samsung/defex_lsm/catch_engine/defex_catch_list_compat.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include "include/defex_catch_list.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) -#define __COMPAT_SYSCALL_NR -#include -#else -#ifdef __NR_clone3 -#define __NR_compat_syscalls (__NR_clone3 + 10) -#elif defined(__NR_rseq) -#define __NR_compat_syscalls (__NR_rseq + 10) -#elif defined(__NR_seccomp) -#define __NR_compat_syscalls (__NR_seccomp + 10) -#else -#define __NR_compat_syscalls 400 -#endif -#endif /* < KERNEL_VERSION(4, 0, 0) */ - -#define DEFEX_CATCH_COUNT __NR_compat_syscalls -const int defex_nr_syscalls_compat = DEFEX_CATCH_COUNT; - -#include "defex_catch_list.inc" - -const struct local_syscall_struct *get_local_syscall_compat(int syscall_no) -{ - if ((unsigned int)syscall_no >= __NR_compat_syscalls) - return NULL; - - if (!syscall_catch_arr[syscall_no].local_syscall && !syscall_catch_arr[syscall_no].err_code && syscall_no) { - return &syscall_catch_arr[0]; - } - - return &syscall_catch_arr[syscall_no]; -} diff --git a/security/samsung/defex_lsm/catch_engine/defex_ht.c b/security/samsung/defex_lsm/catch_engine/defex_ht.c deleted file mode 100755 index abc6671c9..000000000 --- a/security/samsung/defex_lsm/catch_engine/defex_ht.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "include/defex_catch_list.h" -#include "include/defex_internal.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -#include -#include -#endif - -#define MAX_PID_32 32768 -#define DEFEX_MEM_CACHE_SIZE 32 -#define DEFEX_MEM_CACHE_COUNT 3 -#define CACHE_CRED_DATA 0 -#define CACHE_CRED_DATA_ID 1 -#define CACHE_HTABLE_ITEM 2 - -struct id_set { - unsigned int uid, fsuid, egid; -}; - -struct proc_cred_data { - unsigned short cred_flags; - unsigned short tcnt; - struct id_set default_ids; - struct id_set main_ids[]; -}; - -struct hash_item_struct { - struct hlist_node node; - struct proc_cred_data *cred_data; - int id; -}; - -struct mem_cache_list { - atomic_t count; - char name[8]; - struct kmem_cache *allocator; - void *mem_cache_array[DEFEX_MEM_CACHE_SIZE]; -}; - -#ifdef DEFEX_PED_ENABLE -DECLARE_HASHTABLE(creds_hash, 15); -__visible_for_testing DEFINE_SPINLOCK(creds_hash_update_lock); -static struct proc_cred_data *creds_fast_hash[MAX_PID_32 + 1]; -__visible_for_testing struct mem_cache_list mem_cache[DEFEX_MEM_CACHE_COUNT]; -static int creds_fast_hash_ready __ro_after_init; -__visible_for_testing void mem_cache_alloc(void); - - -void __init creds_fast_hash_init(void) -{ - unsigned int i; - static const int sizes[DEFEX_MEM_CACHE_COUNT] __initdata = { - sizeof(struct proc_cred_data), - sizeof(struct proc_cred_data) + sizeof(struct id_set), - sizeof(struct hash_item_struct) - }; - - hash_init(creds_hash); - for (i = 0; i <= MAX_PID_32; i++) - creds_fast_hash[i] = NULL; - - for(i = 0; i < ARRAY_SIZE(sizes); i++) { - snprintf(mem_cache[i].name, sizeof(mem_cache[i].name), "defex%d", i); - mem_cache[i].allocator = kmem_cache_create(mem_cache[i].name, sizes[i], 0, 0, NULL); - } - - for(i = 0; i < (DEFEX_MEM_CACHE_SIZE / 2); i++) - mem_cache_alloc(); - - creds_fast_hash_ready = 1; -} - -int is_task_creds_ready(void) -{ - return creds_fast_hash_ready; -} - -__visible_for_testing inline void *mem_cache_get(int cache_number) -{ - int n; - n = atomic_read(&mem_cache[cache_number].count); - if (n) { - atomic_dec(&mem_cache[cache_number].count); - return mem_cache[cache_number].mem_cache_array[n - 1]; - } - return NULL; -} - -__visible_for_testing inline void *mem_cache_reclaim(int cache_number, void *ptr) -{ - int n; - n = atomic_read(&mem_cache[cache_number].count); - if (n < DEFEX_MEM_CACHE_SIZE) { - atomic_inc(&mem_cache[cache_number].count); - mem_cache[cache_number].mem_cache_array[n] = ptr; - ptr = NULL; - } - return ptr; -} - -__visible_for_testing void mem_cache_alloc(void) -{ - int mem_allocated = 0; - int i, n; - unsigned long flags; - void *mem_block[DEFEX_MEM_CACHE_COUNT]; - - for(i = 0; i < DEFEX_MEM_CACHE_COUNT; i++) { - mem_block[i] = NULL; - n = atomic_read(&mem_cache[i].count); - if (n < (DEFEX_MEM_CACHE_SIZE / 2)) { - mem_block[i] = kmem_cache_alloc(mem_cache[i].allocator, in_atomic() ? GFP_ATOMIC:GFP_KERNEL); - mem_allocated++; - } - } - - if (!mem_allocated) - return; - - spin_lock_irqsave(&creds_hash_update_lock, flags); - for(i = 0; i < DEFEX_MEM_CACHE_COUNT; i++) { - n = atomic_read(&mem_cache[i].count); - if (mem_block[i] && n < DEFEX_MEM_CACHE_SIZE) { - mem_cache[i].mem_cache_array[n] = mem_block[i]; - mem_block[i] = NULL; - atomic_inc(&mem_cache[i].count); - mem_allocated--; - } - } - spin_unlock_irqrestore(&creds_hash_update_lock, flags); - - if (!mem_allocated) - return; - - for(i = 0; i < DEFEX_MEM_CACHE_COUNT; i++) { - if (mem_block[i]) { - kmem_cache_free(mem_cache[i].allocator, mem_block[i]); - } - } -} - -__visible_for_testing struct proc_cred_data *get_cred_data(int id) -{ - struct proc_cred_data *cred_data = NULL; - struct hash_item_struct *obj; - - if (id < 0) - return NULL; - if (id <= MAX_PID_32) { - cred_data = creds_fast_hash[id]; - } else { - hash_for_each_possible(creds_hash, obj, node, id) { - if (obj->id == id) { - cred_data = obj->cred_data; - break; - } - } - } - return cred_data; -} - -__visible_for_testing struct proc_cred_data **get_cred_ptr(int id) -{ - struct proc_cred_data **cred_ptr = NULL; - struct hash_item_struct *obj; - - if (id < 0) - return NULL; - if (id <= MAX_PID_32) { - cred_ptr = &creds_fast_hash[id]; - } else { - hash_for_each_possible(creds_hash, obj, node, id) { - if (obj->id == id) { - cred_ptr = &obj->cred_data; - break; - } - } - } - return cred_ptr; -} - -__visible_for_testing void set_cred_data(int id, struct proc_cred_data **cred_ptr, struct proc_cred_data *cred_data) -{ - struct hash_item_struct *obj; - - if (id < 0) - return; - if (cred_ptr) { - *cred_ptr = cred_data; - } else { - if (id > MAX_PID_32) { - obj = mem_cache_get(CACHE_HTABLE_ITEM); - if (!obj) - return; - obj->id = id; - obj->cred_data = cred_data; - hash_add(creds_hash, &obj->node, id); - } - } -} - -void get_task_creds(struct task_struct *p, unsigned int *uid_ptr, unsigned int *fsuid_ptr, unsigned int *egid_ptr, unsigned short *cred_flags_ptr) -{ - struct proc_cred_data *cred_data, *thread_cred_data; - struct id_set *ids_ptr; - unsigned int uid = 0, fsuid = 0, egid = 0; - unsigned short cred_flags = CRED_FLAGS_PROOT; - unsigned long flags; - int tgid = p->tgid, pid = p->pid; - - spin_lock_irqsave(&creds_hash_update_lock, flags); - cred_data = get_cred_data(tgid); - if (cred_data) { - if (tgid == pid) { - ids_ptr = (cred_data->cred_flags & CRED_FLAGS_MAIN_UPDATED) ? \ - (&cred_data->main_ids[0]) : (&cred_data->default_ids); - } else { - if (cred_data->cred_flags & CRED_FLAGS_SUB_UPDATED) { - thread_cred_data = get_cred_data(pid); - if (thread_cred_data) - cred_data = thread_cred_data; - } - ids_ptr = &cred_data->default_ids; - } - GET_CREDS(ids_ptr, cred_data); - } - spin_unlock_irqrestore(&creds_hash_update_lock, flags); - *uid_ptr = uid; - *fsuid_ptr = fsuid; - *egid_ptr = egid; - *cred_flags_ptr = cred_flags; -} - -int set_task_creds(struct task_struct *p, unsigned int uid, unsigned int fsuid, unsigned int egid, unsigned short cred_flags) -{ - struct proc_cred_data *cred_data = NULL, *tmp_data, **cred_ptr; - struct id_set *ids_ptr; - unsigned long flags; - int err = -1, tgid = p->tgid, pid = p->pid; - void *free_buff = NULL; - - - mem_cache_alloc(); - spin_lock_irqsave(&creds_hash_update_lock, flags); - - /* Search for main proces's data */ - cred_ptr = get_cred_ptr(tgid); - cred_data = (cred_ptr) ? (*cred_ptr) : NULL; - if (!cred_data) { - /* Not found? Allocate a new data */ - cred_data = mem_cache_get(CACHE_CRED_DATA); - if (!cred_data) - goto set_finish; - cred_data->cred_flags = 0; - cred_data->tcnt = 1; - set_cred_data(tgid, cred_ptr, cred_data); - } - ids_ptr = &cred_data->default_ids; - - if (cred_data->tcnt >= 2) { - if (tgid == pid) { - /* Allocate extended data for main process, copy and remove old data */ - if (!(cred_data->cred_flags & CRED_FLAGS_MAIN_UPDATED)) { - cred_data->cred_flags |= CRED_FLAGS_MAIN_UPDATED; - tmp_data = mem_cache_get(CACHE_CRED_DATA_ID); - if (!tmp_data) - goto set_finish; - *tmp_data = *cred_data; - free_buff = mem_cache_reclaim(CACHE_CRED_DATA, cred_data); - cred_data = tmp_data; - set_cred_data(tgid, cred_ptr, cred_data); - } - ids_ptr = &cred_data->main_ids[0]; - } else { - cred_data->cred_flags |= CRED_FLAGS_SUB_UPDATED; - /* Search for thread's data. Allocate, if not found */ - cred_ptr = get_cred_ptr(pid); - cred_data = (cred_ptr) ? (*cred_ptr) : NULL; - if (!cred_data) { - cred_data = mem_cache_get(CACHE_CRED_DATA); - if (!cred_data) - goto set_finish; - set_cred_data(pid, cred_ptr, cred_data); - } - cred_data->cred_flags = 0; - ids_ptr = &cred_data->default_ids; - } - } - SET_CREDS(ids_ptr, cred_data); - err = 0; - -set_finish: - spin_unlock_irqrestore(&creds_hash_update_lock, flags); - /* Free the pending pointer */ - if (free_buff) - kmem_cache_free(mem_cache[CACHE_CRED_DATA].allocator, free_buff); - mem_cache_alloc(); - return err; -} - -void set_task_creds_tcnt(struct task_struct *p, int addition) -{ - struct hash_item_struct *tgid_obj = NULL, *pid_obj = NULL; - struct proc_cred_data **cred_ptr, *tgid_cred_data = NULL, *pid_cred_data = NULL; - struct proc_cred_data *free_buff1 = NULL, *free_buff2 = NULL; - int tgid = p->tgid, pid = p->pid; - unsigned long flags; - - spin_lock_irqsave(&creds_hash_update_lock, flags); - /* Remove the thread's data, if found */ - if (tgid != pid && addition == -1) { - cred_ptr = get_cred_ptr(pid); - pid_cred_data = (cred_ptr) ? (*cred_ptr) : NULL; - if (pid_cred_data) { - *cred_ptr = NULL; - /* Return to pre-allocated pool, if possible */ - free_buff1 = mem_cache_reclaim(CACHE_CRED_DATA, pid_cred_data); - } - /* Remove the thread's hash container */ - if (cred_ptr && pid > MAX_PID_32) { - pid_obj = container_of(cred_ptr, struct hash_item_struct, cred_data); - hash_del(&pid_obj->node); - /* Return to pre-allocated pool, if possible */ - pid_obj = mem_cache_reclaim(CACHE_HTABLE_ITEM, pid_obj); - } - } - /* Search for the main process's data */ - cred_ptr = get_cred_ptr(tgid); - tgid_cred_data = (cred_ptr) ? (*cred_ptr) : NULL; - if (tgid_cred_data) { - tgid_cred_data->tcnt += addition; - /* No threads, remove process data */ - if (!tgid_cred_data->tcnt) { - *cred_ptr = NULL; - /* Return to pre-allocated pool, if possible */ - free_buff2 = mem_cache_reclaim((tgid_cred_data->cred_flags & CRED_FLAGS_MAIN_UPDATED) ? \ - CACHE_CRED_DATA_ID : CACHE_CRED_DATA, tgid_cred_data); - /* Remove the process's hash container */ - if (tgid > MAX_PID_32) { - tgid_obj = container_of(cred_ptr, struct hash_item_struct, cred_data); - hash_del(&tgid_obj->node); - /* Return to pre-allocated pool, if possible */ - tgid_obj = mem_cache_reclaim(CACHE_HTABLE_ITEM, tgid_obj); - } - } - } - spin_unlock_irqrestore(&creds_hash_update_lock, flags); - /* Free all pending pointers */ - if (free_buff1) - kmem_cache_free(mem_cache[CACHE_CRED_DATA].allocator, free_buff1); - if (free_buff2) - kmem_cache_free(mem_cache[(free_buff2->cred_flags & CRED_FLAGS_MAIN_UPDATED) ? \ - CACHE_CRED_DATA_ID : CACHE_CRED_DATA].allocator, free_buff2); - if (pid_obj) - kmem_cache_free(mem_cache[CACHE_HTABLE_ITEM].allocator, pid_obj); - if (tgid_obj) - kmem_cache_free(mem_cache[CACHE_HTABLE_ITEM].allocator, tgid_obj); - return; -} - -#else - -int is_task_creds_ready(void) -{ - return 0; -} - -void set_task_creds_tcnt(struct task_struct *p, int addition) -{ - (void)p; - (void)addition; -} - -#endif /* DEFEX_PED_ENABLE */ diff --git a/security/samsung/defex_lsm/cert/defex_cert.S b/security/samsung/defex_lsm/cert/defex_cert.S deleted file mode 100755 index f7368f7be..000000000 --- a/security/samsung/defex_lsm/cert/defex_cert.S +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include - - __INITRODATA - -.align 8 - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) || !defined(VMLINUX_SYMBOL)) -#define VMLINUX_SYMBOL(name) name -#endif - -#define GLOBAL(name) \ - .globl VMLINUX_SYMBOL(name); \ - VMLINUX_SYMBOL(name): - - .section ".ref.data", "aw" - -GLOBAL(defex_public_key_start) -#ifdef DEFEX_DEBUG_ENABLE - .incbin "security/samsung/defex_lsm/cert/pubkey_eng.der" -#else - .incbin "security/samsung/defex_lsm/cert/pubkey_user.der" -#endif -GLOBAL(defex_public_key_end) diff --git a/security/samsung/defex_lsm/cert/defex_sign.c b/security/samsung/defex_lsm/cert/defex_sign.c deleted file mode 100755 index 8a115622e..000000000 --- a/security/samsung/defex_lsm/cert/defex_sign.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "include/defex_debug.h" -#include "include/defex_sign.h" - -#ifdef DEFEX_KUNIT_ENABLED -#include -#endif - -#define SHA256_DIGEST_SIZE 32 - -extern char defex_public_key_start[]; -extern char defex_public_key_end[]; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) - -__visible_for_testing int defex_public_key_verify_signature(unsigned char *pub_key, - int pub_key_size, - unsigned char *signature, - unsigned char *hash_sha256) -{ - (void)pub_key; - (void)pub_key_size; - (void)signature; - (void)hash_sha256; - /* Skip signarue check at kernel version < 3.7.0 */ - defex_log_warn("Skip signature check in current kernel version"); - return 0; -} - -#else - -#include - -static struct key *defex_keyring; - -__visible_for_testing struct key *defex_keyring_alloc(const char *description, - kuid_t uid, kgid_t gid, - const struct cred *cred, - unsigned long flags) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - return keyring_alloc(description, uid, gid, cred, flags, NULL) -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) - key_perm_t perm = ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH); - return keyring_alloc(description, uid, gid, cred, perm, flags, NULL); -#else - key_perm_t perm = ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH); - return keyring_alloc(description, uid, gid, cred, perm, flags, NULL, NULL); -#endif -} - -__visible_for_testing int defex_keyring_init(void) -{ - int err = 0; - const struct cred *cred = current_cred(); - static const char keyring_name[] = "defex_keyring"; - - if (defex_keyring) - return err; - - defex_keyring = defex_keyring_alloc(keyring_name, KUIDT_INIT(0), KGIDT_INIT(0), - cred, KEY_ALLOC_NOT_IN_QUOTA); - if (!defex_keyring) { - err = -1; - defex_log_info("Can't allocate %s keyring (NULL)", keyring_name); - } else if (IS_ERR(defex_keyring)) { - err = PTR_ERR(defex_keyring); - defex_log_info("Can't allocate %s keyring, err=%d", keyring_name, err); - defex_keyring = NULL; - } - return err; -} - -__visible_for_testing int defex_public_key_verify_signature(unsigned char *pub_key, - int pub_key_size, - unsigned char *signature, - unsigned char *hash_sha256) -{ - int ret = -1; - key_ref_t key_ref; - struct key *key; - struct public_key_signature pks; - static const char key_name[] = "defex_key"; - - if (defex_keyring_init() != 0) - return ret; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0) - key_ref = keyring_search(make_key_ref(defex_keyring, 1), &key_type_asymmetric, key_name); -#else - key_ref = keyring_search(make_key_ref(defex_keyring, 1), &key_type_asymmetric, key_name, true); -#endif - if (IS_ERR(key_ref)) { - key_ref = key_create_or_update(make_key_ref(defex_keyring, 1), - "asymmetric", - key_name, - pub_key, - pub_key_size, - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ), - KEY_ALLOC_NOT_IN_QUOTA); - } - if (IS_ERR(key_ref)) { - defex_log_err("Invalid key reference (%ld)", PTR_ERR(key_ref)); - return ret; - } - - key = key_ref_to_ptr(key_ref); - - memset(&pks, 0, sizeof(pks)); - pks.digest = hash_sha256; - pks.digest_size = SHA256_DIGEST_SIZE; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) - pks.pkey_algo = PKEY_ALGO_RSA; -#endif - pks.pkey_hash_algo = HASH_ALGO_SHA256; - pks.nr_mpi = 1; - pks.rsa.s = mpi_read_raw_data(signature, SIGN_SIZE); - if (pks.rsa.s) - ret = verify_signature(key, &pks); - mpi_free(pks.rsa.s); -#else - pks.pkey_algo = "rsa"; - pks.hash_algo = "sha256"; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) - pks.encoding = "pkcs1"; -#endif - pks.s = signature; - pks.s_size = SIGN_SIZE; - ret = verify_signature(key, &pks); -#endif - key_ref_put(key_ref); - return ret; -} -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */ - -int defex_calc_hash(const char *data, unsigned int size, unsigned char *hash) -{ - struct crypto_shash *handle; - struct shash_desc* shash; - int err = -1; - - handle = crypto_alloc_shash("sha256", 0, 0); - if (IS_ERR_OR_NULL(handle)) { - defex_log_err("Can't alloc sha256"); - return err; - } - - shash = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(handle), GFP_KERNEL); - if (!shash) - goto clean_handle; - - shash->tfm = handle; - - do { - err = crypto_shash_init(shash); - if (err < 0) - break; - - err = crypto_shash_update(shash, data, size); - if (err < 0) - break; - - err = crypto_shash_final(shash, hash); - if (err < 0) - break; - } while(0); - - kfree(shash); -clean_handle: - crypto_free_shash(handle); - return err; -} - -int defex_rules_signature_check(const char *rules_buffer, unsigned int rules_data_size, unsigned int *rules_size) -{ - int res = -1; - unsigned int defex_public_key_size = (unsigned int)((defex_public_key_end - defex_public_key_start) & 0xffffffff); - unsigned char *hash_sha256; - unsigned char *hash_sha256_first; - unsigned char *signature; - unsigned char *pub_key; - - if (rules_data_size < SIGN_SIZE) - return res; - hash_sha256_first = kmalloc(SHA256_DIGEST_SIZE, GFP_KERNEL); - if (!hash_sha256_first) - return res; - hash_sha256 = kmalloc(SHA256_DIGEST_SIZE, GFP_KERNEL); - if (!hash_sha256) - goto clean_hash_sha256_first; - signature = kmalloc(SIGN_SIZE, GFP_KERNEL); - if (!signature) - goto clean_hash_sha256; - pub_key = kmalloc(defex_public_key_size, GFP_KERNEL); - if (!pub_key) - goto clean_signature; - - memcpy(pub_key, defex_public_key_start, defex_public_key_size); - memcpy(signature, (u8*)(rules_buffer + rules_data_size - SIGN_SIZE), SIGN_SIZE); - - defex_calc_hash(rules_buffer, rules_data_size - SIGN_SIZE, hash_sha256_first); - defex_calc_hash(hash_sha256_first, SHA256_DIGEST_SIZE, hash_sha256); - -#ifdef DEFEX_DEBUG_ENABLE - defex_log_info("Rules signature size = %d", SIGN_SIZE); - blob("Rules signature dump:", signature, SIGN_SIZE, 16); - defex_log_info("Key size = %d", defex_public_key_size); - blob("Key dump:", pub_key, defex_public_key_size, 16); - blob("Final hash dump:", hash_sha256, SHA256_DIGEST_SIZE, 16); -#endif - - res = defex_public_key_verify_signature(pub_key, defex_public_key_size, signature, hash_sha256); - if (rules_size && !res) - *rules_size = rules_data_size - SIGN_SIZE; - kfree(pub_key); -clean_signature: - kfree(signature); -clean_hash_sha256: - kfree(hash_sha256); -clean_hash_sha256_first: - kfree(hash_sha256_first); - return res; -} diff --git a/security/samsung/defex_lsm/cert/x509_five_eng.der b/security/samsung/defex_lsm/cert/x509_five_eng.der deleted file mode 100755 index 2dfd0ad73..000000000 Binary files a/security/samsung/defex_lsm/cert/x509_five_eng.der and /dev/null differ diff --git a/security/samsung/defex_lsm/cert/x509_five_user.der b/security/samsung/defex_lsm/cert/x509_five_user.der deleted file mode 100755 index 7c15ba096..000000000 Binary files a/security/samsung/defex_lsm/cert/x509_five_user.der and /dev/null differ diff --git a/security/samsung/defex_lsm/core/defex_common.c b/security/samsung/defex_lsm/core/defex_common.c deleted file mode 100755 index a0b6f2334..000000000 --- a/security/samsung/defex_lsm/core/defex_common.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "include/defex_caches.h" -#include "include/defex_catch_list.h" -#include "include/defex_config.h" -#include "include/defex_internal.h" -#include "include/defex_rules.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) -#include "../security/integrity/integrity.h" -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) - -inline ssize_t __vfs_read(struct file *file, char __user *buf, - size_t count, loff_t *pos) -{ - ssize_t ret; - - if (file->f_op->read) - ret = file->f_op->read(file, buf, count, pos); - else if (file->f_op->aio_read) - ret = do_sync_read(file, buf, count, pos); - else if (file->f_op->read_iter) - ret = new_sync_read(file, buf, count, pos); - else - ret = -EINVAL; - - return ret; -} -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) -#define GET_KERNEL_DS KERNEL_DS -#else -#define GET_KERNEL_DS get_ds() -#endif - -struct file *local_fopen(const char *fname, int flags, umode_t mode) -{ - struct file *f; -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) - mm_segment_t old_fs; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) - old_fs = get_fs(); - set_fs(GET_KERNEL_DS); -#endif - f = filp_open(fname, flags, mode); -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) - set_fs(old_fs); -#endif - return f; -} - -int local_fread(struct file *f, loff_t offset, void *ptr, unsigned long bytes) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) - mm_segment_t old_fs; - char __user *buf = (char __user *)ptr; -#endif - ssize_t ret; - - if (!(f->f_mode & FMODE_READ)) - return -EBADF; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) - old_fs = get_fs(); - set_fs(GET_KERNEL_DS); - ret = vfs_read(f, buf, bytes, &offset); - set_fs(old_fs); -#else - ret = (ssize_t)integrity_kernel_read(f, offset, ptr, bytes); -#endif - - return (int)ret; -} - -const char unknown_file[] = ""; - -__visible_for_testing bool check_slab_ptr(void *ptr) -{ - struct page *page; - - if (IS_ERR_OR_NULL(ptr) || ptr < (void *)PAGE_SIZE || !virt_addr_valid(ptr)) - return false; - page = virt_to_head_page(ptr); - return PageSlab(page); -} - -int init_defex_context(struct defex_context *dc, int syscall, struct task_struct *p, struct file *f) -{ - memset(dc, 0, offsetof(struct defex_context, cred)); - if (check_slab_ptr(f)) { - get_file(f); - dc->target_file = f; - } - dc->syscall_no = syscall; - dc->task = p; - if (p == current) - dc->cred = (struct cred *)current_cred(); - if (!dc->cred) - return 0; - return 1; -} - -void release_defex_context(struct defex_context *dc) -{ - kfree(dc->process_name_buff); - kfree(dc->target_name_buff); - if (dc->target_file) - fput(dc->target_file); -#ifndef DEFEX_CACHES_ENABLE - if (dc->process_file) - fput(dc->process_file); -#endif /* DEFEX_CACHES_ENABLE */ -} - -struct file *get_dc_process_file(struct defex_context *dc) -{ - if (!dc->process_file) - dc->process_file = defex_get_source_file(dc->task); - return dc->process_file; -} - -const struct path *get_dc_process_dpath(struct defex_context *dc) -{ - const struct path *dpath; - struct file *exe_file = NULL; - - if (dc->process_dpath) - return dc->process_dpath; - - exe_file = get_dc_process_file(dc); - if (!IS_ERR_OR_NULL(exe_file)) { - dpath = &exe_file->f_path; - if (dpath->dentry && dpath->dentry->d_inode) { - dc->process_dpath = dpath; - return dpath; - } - } - return NULL; -} - -char *get_dc_process_name(struct defex_context *dc) -{ - const struct path *dpath; - char *path = NULL; - - if (!dc->process_name) { - dpath = get_dc_process_dpath(dc); - if (dpath) { - dc->process_name_buff = kmalloc(PATH_MAX, GFP_KERNEL); - if (dc->process_name_buff) - path = d_path(dpath, dc->process_name_buff, PATH_MAX); - } - dc->process_name = (IS_ERR_OR_NULL(path)) ? (char *)unknown_file : path; - } - return dc->process_name; -} - -const struct path *get_dc_target_dpath(struct defex_context *dc) -{ - const struct path *dpath; - - if (dc->target_dpath) - return dc->target_dpath; - - if (dc->target_file) { - dpath = &(dc->target_file->f_path); - if (dpath->dentry && dpath->dentry->d_inode) { - dc->target_dpath = dpath; - return dpath; - } - } - return NULL; -} - -char *get_dc_target_name(struct defex_context *dc) -{ - const struct path *dpath; - char *path = NULL; - - if (!dc->target_name) { - dpath = get_dc_target_dpath(dc); - if (dpath) { - dc->target_name_buff = kmalloc(PATH_MAX, GFP_KERNEL); - if (dc->target_name_buff) - path = d_path(dpath, dc->target_name_buff, PATH_MAX); - } - dc->target_name = (IS_ERR_OR_NULL(path)) ? (char *)unknown_file : path; - } - return dc->target_name; -} - -struct file *defex_get_source_file(struct task_struct *p) -{ - struct file *file_addr = NULL; - struct mm_struct *proc_mm; - -#ifdef DEFEX_CACHES_ENABLE - bool self; - file_addr = defex_file_cache_find(p->pid); - - if (!file_addr) { - proc_mm = get_task_mm(p); - if (!proc_mm) - return NULL; - file_addr = get_mm_exe_file(proc_mm); - mmput(proc_mm); - if (!file_addr) - return NULL; - defex_file_cache_add(p->pid, file_addr); - } else { - self = (p == current); - proc_mm = (self)?p->mm:get_task_mm(p); - if (!proc_mm) - return NULL; - if (self) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0) - if (!down_read_trylock(&proc_mm->mmap_sem)) - return NULL; -#else - if (!down_read_trylock(&proc_mm->mmap_lock)) - return NULL; -#endif - if (file_addr != proc_mm->exe_file) { - file_addr = proc_mm->exe_file; - if (!file_addr) - goto clean_mm; - get_file(file_addr); - defex_file_cache_update(file_addr); - } -clean_mm: - if (self) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0) - up_read(&proc_mm->mmap_sem); -#else - up_read(&proc_mm->mmap_lock); -#endif - else - mmput(proc_mm); - } -#else - - proc_mm = get_task_mm(p); - if (!proc_mm) - return NULL; - file_addr = get_mm_exe_file(proc_mm); - mmput(proc_mm); -#endif /* DEFEX_CACHES_ENABLE */ - return file_addr; -} - -char *defex_get_filename(struct task_struct *p) -{ - struct file *exe_file = NULL; - const struct path *dpath = NULL; - char *path = NULL, *buff = NULL; - char *filename = NULL; - - exe_file = defex_get_source_file(p); - if (IS_ERR_OR_NULL(exe_file)) - goto out_filename; - - dpath = &exe_file->f_path; - if (!dpath->dentry || !dpath->dentry->d_inode) { - fput(exe_file); - goto out_filename; - } - path_get(dpath); - - buff = kmalloc(PATH_MAX, GFP_KERNEL); - if (buff) - path = d_path(dpath, buff, PATH_MAX); - path_put(dpath); - -#ifndef DEFEX_CACHES_ENABLE - fput(exe_file); -#endif /* DEFEX_CACHES_ENABLE */ - -out_filename: - if (path && !IS_ERR(path)) - filename = kstrdup(path, GFP_KERNEL); - - if (!filename) - filename = (char *)unknown_file; - - if (buff) - kfree(buff); - return filename; -} - -/* Resolve the filename to absolute path, follow the links - name - input file name - out_buff - output pointer to the allocated buffer (should be freed) - Returns: pointer to resolved filename or NULL - */ -char* defex_resolve_filename(const char *name, char **out_buff) -{ - char *target_file = NULL, *buff = NULL; - struct path path; - - if (*out_buff) - buff = *out_buff; - else - buff = kmalloc(PATH_MAX, GFP_KERNEL); - if (buff) { - if (!kern_path(name, LOOKUP_FOLLOW, &path)) { - target_file = d_path(&path, buff, PATH_MAX); - path_put(&path); - } - if (IS_ERR_OR_NULL(target_file)) { - kfree(buff); - buff = NULL; - target_file = NULL; - } - } - *out_buff = buff; - return target_file; -} - -int defex_files_identical(const struct file *f1, const struct file *f2) -{ - const struct path *dpath1, *dpath2; - const struct inode *inode1, *inode2; - - if (f1 && f2) { - dpath1 = &f1->f_path; - dpath2 = &f2->f_path; - if (dpath1->dentry && dpath2->dentry) { - inode1 = dpath1->dentry->d_inode; - inode2 = dpath2->dentry->d_inode; - return (inode1 == inode2); - } - } - return 0; -} diff --git a/security/samsung/defex_lsm/core/defex_get_mode.c b/security/samsung/defex_lsm/core/defex_get_mode.c deleted file mode 100755 index 89b9797f0..000000000 --- a/security/samsung/defex_lsm/core/defex_get_mode.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "include/defex_internal.h" - -int defex_get_features(void) -{ - int features = 0; -#ifdef DEFEX_PED_ENABLE -#if !defined(DEFEX_PERMISSIVE_PED) - features |= GLOBAL_PED_STATUS; -#else - if (global_privesc_status != 0) - features |= FEATURE_CHECK_CREDS; - if (global_privesc_status == 2) - features |= FEATURE_CHECK_CREDS_SOFT; -#endif /* DEFEX_PERMISSIVE_PED */ -#endif /* DEFEX_PED_ENABLE */ - -#ifdef DEFEX_INTEGRITY_ENABLE -#if !defined(DEFEX_PERMISSIVE_INT) - features |= GLOBAL_INTEGRITY_STATUS; -#else - if (global_integrity_status != 0) - features |= FEATURE_INTEGRITY; - if (global_integrity_status == 2) - features |= FEATURE_INTEGRITY_SOFT; -#endif /* DEFEX_PERMISSIVE_INT */ -#endif /* DEFEX_INTEGRITY_ENABLE */ - -#ifdef DEFEX_SAFEPLACE_ENABLE -#if !defined(DEFEX_PERMISSIVE_SP) - features |= GLOBAL_SAFEPLACE_STATUS; -#else - if (global_safeplace_status != 0) - features |= FEATURE_SAFEPLACE; - if (global_safeplace_status == 2) - features |= FEATURE_SAFEPLACE_SOFT; -#endif /* DEFEX_PERMISSIVE_SP */ -#endif /* DEFEX_SAFEPLACE_ENABLE */ - -#ifdef DEFEX_TRUSTED_MAP_ENABLE -#if !defined(DEFEX_PERMISSIVE_TM) - features |= GLOBAL_TRUSTED_MAP_STATUS; -#else - if (global_trusted_map_status != 0) - features |= FEATURE_TRUSTED_MAP; - if (global_trusted_map_status & DEFEX_TM_PERMISSIVE_MODE) - features |= FEATURE_TRUSTED_MAP_SOFT; -#endif /* DEFEX_PERMISSIVE_TM */ -#endif /* DEFEX_TRUSTED_MAP_ENABLE */ - -#ifdef DEFEX_IMMUTABLE_ENABLE -#if !defined(DEFEX_PERMISSIVE_IM) - features |= GLOBAL_IMMUTABLE_STATUS; -#else - if (global_immutable_status != 0) - features |= FEATURE_IMMUTABLE; - if (global_immutable_status == 2) - features |= FEATURE_IMMUTABLE_SOFT; -#endif /* DEFEX_PERMISSIVE_IM */ -#endif /* DEFEX_IMMUTABLE_ENABLE */ - return features; -} diff --git a/security/samsung/defex_lsm/core/defex_lsm.c b/security/samsung/defex_lsm/core/defex_lsm.c deleted file mode 100755 index e2d201e8a..000000000 --- a/security/samsung/defex_lsm/core/defex_lsm.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "include/defex_caches.h" -#include "include/defex_catch_list.h" -#include "include/defex_debug.h" -#include "include/defex_internal.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) -#include -#endif - -MODULE_DESCRIPTION("Defex Linux Security Module"); - -bool boot_state_recovery __ro_after_init; - -#ifdef DEFEX_DEPENDING_ON_OEMUNLOCK -bool boot_state_unlocked __ro_after_init; -int warranty_bit __ro_after_init; -#endif /* DEFEX_DEPENDING_ON_OEMUNLOCK */ - -asmlinkage int defex_syscall_enter(long int syscallno, struct pt_regs *regs); -asmlinkage int (* const defex_syscall_catch_enter)(long int syscallno, struct pt_regs *regs) = defex_syscall_enter; -static int defex_init_done __initdata; - -asmlinkage int defex_syscall_enter(long int syscallno, struct pt_regs *regs) -{ - long err; - const struct local_syscall_struct *item; - - if (!current) - return 0; - -#if !defined(__arm__) && defined(CONFIG_COMPAT) - if (regs->pstate & PSR_MODE32_BIT) - item = get_local_syscall_compat(syscallno); - else -#endif /* __arm__ && CONFIG_COMPAT */ - item = get_local_syscall(syscallno); - - if (!item) - return 0; - - err = item->err_code; - if (err) { - if (task_defex_enforce(current, NULL, item->local_syscall)) - return err; - } - return 0; -} - - -#ifdef DEFEX_DEPENDING_ON_OEMUNLOCK -__visible_for_testing int __init verifiedboot_state_setup(char *str) -{ - static const char unlocked[] = "orange"; - - if (str && !strncmp(str, unlocked, sizeof(unlocked))) { - boot_state_unlocked = true; - defex_log_crit("Device is unlocked and DEFEX will be disabled"); - } - return 0; -} - -__visible_for_testing int __init warrantybit_setup(char *str) -{ - if (get_option(&str, &warranty_bit)) - defex_log_crit("Warranty bit setup"); - return 0; -} - -__setup("androidboot.verifiedbootstate=", verifiedboot_state_setup); -__setup("androidboot.warranty_bit=", warrantybit_setup); -#endif /* DEFEX_DEPENDING_ON_OEMUNLOCK */ - -__visible_for_testing int __init bootstate_recovery_setup(char *str) -{ - if (str && *str == '2') { - boot_state_recovery = true; - defex_log_crit("Recovery mode setup"); - } - return 0; -} -__setup("bootmode=", bootstate_recovery_setup); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) -void __init defex_bootconfig_setup(void) -{ - char *value; - -#ifdef DEFEX_DEPENDING_ON_OEMUNLOCK - value = (char *)xbc_find_value("androidboot.verifiedbootstate", NULL); - verifiedboot_state_setup(value); - - value = (char *)xbc_find_value("androidboot.warranty_bit", NULL); - warrantybit_setup(value); -#endif /* DEFEX_DEPENDING_ON_OEMUNLOCK */ - - value = (char *)xbc_find_value("androidboot.boot_recovery", NULL); - bootstate_recovery_setup(value); -} -#endif /* LINUX_VERSION_CODE */ - - -//INIT///////////////////////////////////////////////////////////////////////// -__visible_for_testing int __init defex_lsm_init(void) -{ -#ifdef DEFEX_DEBUG_ENABLE - int ret; -#endif /* DEFEX_DEBUG_ENABLE */ - -#ifdef DEFEX_CACHES_ENABLE - defex_file_cache_init(); -#endif /* DEFEX_CACHES_ENABLE */ - -#ifdef DEFEX_PED_ENABLE - creds_fast_hash_init(); -#endif /* DEFEX_PED_ENABLE */ - -#ifdef DEFEX_DEBUG_ENABLE - ret = defex_init_sysfs(); - if (ret) { - defex_log_crit("LSM defex_init_sysfs() failed!"); - return ret; - } -#endif /* DEFEX_DEBUG_ENABLE */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) - defex_bootconfig_setup(); -#endif /* LINUX_VERSION_CODE */ - - defex_log_info("LSM started"); -#ifdef DEFEX_LP_ENABLE - defex_log_info("ADB LP Enabled"); -#endif /* DEFEX_LP_ENABLE */ - defex_init_done = 1; - return 0; -} - -__visible_for_testing int __init defex_lsm_load(void) -{ - if (!boot_state_unlocked && defex_init_done) - do_load_rules(); - return 0; -} - -module_init(defex_lsm_init); -late_initcall(defex_lsm_load); diff --git a/security/samsung/defex_lsm/core/defex_main.c b/security/samsung/defex_lsm/core/defex_main.c deleted file mode 100755 index aa8d82be8..000000000 --- a/security/samsung/defex_lsm/core/defex_main.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#ifdef DEFEX_DSMS_ENABLE -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef DEFEX_DSMS_ENABLE -#include -#endif -#include -#include -#include -#include -#include "include/defex_caches.h" -#include "include/defex_catch_list.h" -#include "include/defex_config.h" -#include "include/defex_debug.h" -#include "include/defex_internal.h" -#include "include/defex_rules.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) -#define is_task_used(tsk) refcount_read(&(tsk)->usage) -#else -#define is_task_used(tsk) atomic_read(&(tsk)->usage) -#endif - - -__visible_for_testing struct task_struct *get_parent_task(const struct task_struct *p) -{ - struct task_struct *parent = NULL; - - read_lock(&tasklist_lock); - parent = p->parent; - if (parent) - get_task_struct(parent); - read_unlock(&tasklist_lock); - return parent; -} - -#ifdef DEFEX_DSMS_ENABLE - -# define PED_VIOLATION "DFX1" -# define SAFEPLACE_VIOLATION "DFX2" -# define INTEGRITY_VIOLATION "DFX3" -# define IMMUTABLE_VIOLATION "DFX4" -# define MESSAGE_BUFFER_SIZE 200 -# define STORED_CREDS_SIZE 100 - -__visible_for_testing void defex_report_violation(const char *violation, uint64_t counter, - struct defex_context *dc, uid_t stored_uid, uid_t stored_fsuid, uid_t stored_egid, int case_num) -{ - int usermode_result; - char message[MESSAGE_BUFFER_SIZE + 1]; - - struct task_struct *parent = NULL, *p = dc->task; - const uid_t uid = uid_get_value(dc->cred->uid); - const uid_t euid = uid_get_value(dc->cred->euid); - const uid_t fsuid = uid_get_value(dc->cred->fsuid); - const uid_t egid = uid_get_value(dc->cred->egid); - const char *process_name = p->comm; - const char *prt_process_name = NULL; - const char *program_path = get_dc_process_name(dc); - char *prt_program_path = NULL; - char *file_path = NULL; - char stored_creds[STORED_CREDS_SIZE + 1]; - - parent = get_parent_task(p); - if (!parent) - return; - - prt_process_name = parent->comm; - prt_program_path = defex_get_filename(parent); - - if (dc->target_file && !case_num) { - file_path = get_dc_target_name(dc); - } else { - snprintf(stored_creds, sizeof(stored_creds), - "[%ld, %ld, %ld]", (long)stored_uid, (long)stored_fsuid, (long)stored_egid); - stored_creds[sizeof(stored_creds) - 1] = 0; - } - snprintf(message, sizeof(message), "%d, %d, sc=%d, tsk=%s(%s), %s(%s), [%ld %ld %ld %ld], %s%s, %d", - warranty_bit, boot_state_unlocked, dc->syscall_no, process_name, program_path, prt_process_name, - prt_program_path, (long)uid, (long)euid, (long)fsuid, (long)egid, - (file_path ? "file=" : "stored "), (file_path ? file_path : stored_creds), case_num); - message[sizeof(message) - 1] = 0; - - usermode_result = dsms_send_message(violation, message, counter); -#ifdef DEFEX_DEBUG_ENABLE - defex_log_err("Violation : feature=%s value=%ld, detail=[%s]", violation, (long)counter, message); - defex_log_err("Result : %d", usermode_result); -#endif /* DEFEX_DEBUG_ENABLE */ - - safe_str_free(prt_program_path); - put_task_struct(parent); -} -#endif /* DEFEX_DSMS_ENABLE */ - -#if defined(DEFEX_SAFEPLACE_ENABLE) || defined(DEFEX_TRUSTED_MAP_ENABLE) || defined(DEFEX_INTEGRITY_ENABLE) -__visible_for_testing long kill_process(struct task_struct *p) -{ - read_lock(&tasklist_lock); - send_sig(SIGKILL, p, 0); - read_unlock(&tasklist_lock); - return 0; -} -#endif /* DEFEX_SAFEPLACE_ENABLE || DEFEX_TRUSTED_MAP_ENABLE || DEFEX_INTEGRITY_ENABLE */ - -#ifdef DEFEX_PED_ENABLE -__visible_for_testing long kill_process_group(struct task_struct *p, int tgid, int pid) -{ - read_lock(&tasklist_lock); - for_each_process(p) { - if (p->tgid == tgid) - send_sig(SIGKILL, p, 0); - } - send_sig(SIGKILL, current, 0); - read_unlock(&tasklist_lock); - return 0; -} - -__visible_for_testing int check_incfs(struct defex_context *dc) -{ - char *new_file; - struct file *f = dc->target_file; - static const char incfs_path[] = "/data/incremental/"; - - if (f) { - new_file = get_dc_target_name(dc); - if (!strncmp(new_file, incfs_path, sizeof(incfs_path) - 1)) { -#ifdef DEFEX_DEBUG_ENABLE - defex_log_crit("Allow IncFS access"); -#endif /* DEFEX_DEBUG_ENABLE */ - return 1; - } - } - return 0; -} - -__visible_for_testing int task_defex_is_secured(struct defex_context *dc) -{ - struct file *exe_file = get_dc_process_file(dc); - char *proc_name = get_dc_process_name(dc); - int is_secured = 0; - - if (!get_dc_process_dpath(dc)) - return is_secured; - is_secured = !rules_lookup(proc_name, feature_ped_exception, exe_file); - return is_secured; -} - -__visible_for_testing int at_same_group(unsigned int uid1, unsigned int uid2) -{ - static const unsigned int lod_base = 0x61A8; - - /* allow the weaken privilege */ - if (uid1 >= 10000 && uid2 < 10000) return 1; - /* allow traverse in the same class */ - if ((uid1 / 1000) == (uid2 / 1000)) return 1; - /* allow traverse to isolated ranges */ - if (uid1 >= 90000) return 1; - /* allow LoD process */ - return ((uid1 >> 16) == lod_base) && ((uid2 >> 16) == lod_base); -} - -__visible_for_testing int at_same_group_gid(unsigned int gid1, unsigned int gid2) -{ - static const unsigned int lod_base = 0x61A8, inet = 3003; - - /* allow the weaken privilege */ - if (gid1 >= 10000 && gid2 < 10000) return 1; - /* allow traverse in the same class */ - if ((gid1 / 1000) == (gid2 / 1000)) return 1; - /* allow traverse to isolated ranges */ - if (gid1 >= 90000) return 1; - /* allow LoD process */ - return (((gid1 >> 16) == lod_base) || (gid1 == inet)) && ((gid2 >> 16) == lod_base); -} - -#ifdef DEFEX_LP_ENABLE -/* Lower Permission feature decision function */ -__visible_for_testing int lower_adb_permission(struct defex_context *dc, unsigned short cred_flags) -{ - char *parent_file; - struct task_struct *parent = NULL, *p = dc->task; -#ifndef DEFEX_PERMISSIVE_LP - struct cred *shellcred; - static const char adbd_str[] = "/apex/com.android.adbd/bin/adbd"; -#endif /* DEFEX_PERMISSIVE_LP */ - int ret = 0; - - parent = get_parent_task(p); - if (!parent || p->pid == 1 || parent->pid == 1) - goto out; - - parent_file = defex_get_filename(parent); - -#ifndef DEFEX_PERMISSIVE_LP - if (!strncmp(parent_file, adbd_str, sizeof(adbd_str))) { - shellcred = prepare_creds(); - defex_log_crit("ADB with root"); - if (!shellcred) { - defex_log_crit("Prepare_creds fail"); - ret = 0; - goto out; - } - - uid_set_value(shellcred->uid, 2000); - uid_set_value(shellcred->suid, 2000); - uid_set_value(shellcred->euid, 2000); - uid_set_value(shellcred->fsuid, 2000); - uid_set_value(shellcred->gid, 2000); - uid_set_value(shellcred->sgid, 2000); - uid_set_value(shellcred->egid, 2000); - uid_set_value(shellcred->fsgid, 2000); - commit_creds(shellcred); - dc->cred = (struct cred *)current_cred(); //shellcred; - set_task_creds(p, 2000, 2000, 2000, cred_flags); - - ret = 1; - } -#endif /* DEFEX_PERMISSIVE_LP */ - - safe_str_free(parent_file); -out: - if (parent) - put_task_struct(parent); - return ret; -} -#endif /* DEFEX_LP_ENABLE */ - -/* Cred. violation feature decision function */ -#define AID_MEDIA_RW 1023 -#define AID_MEDIA_OBB 1059 -#define AID_SYSTEM 1000 - -__visible_for_testing int task_defex_check_creds(struct defex_context *dc) -{ - char *path = NULL; - int check_deeper, case_num; - unsigned int cur_uid, cur_euid, cur_fsuid, cur_egid; - unsigned int ref_uid, ref_fsuid, ref_egid; - struct task_struct *parent, *p = dc->task; - unsigned short cred_flags; - const struct cred *parent_cred; - static const unsigned int dead_uid = 0xDEADBEAF; - - if (!is_task_creds_ready() || !p->cred) - goto out; - - get_task_creds(p, &ref_uid, &ref_fsuid, &ref_egid, &cred_flags); - - cur_uid = uid_get_value(dc->cred->uid); - cur_euid = uid_get_value(dc->cred->euid); - cur_fsuid = uid_get_value(dc->cred->fsuid); - cur_egid = uid_get_value(dc->cred->egid); - - if (!ref_uid) { - if (p->tgid != p->pid && p->tgid != 1) { - path = get_dc_process_name(dc); - defex_log_crit("[6]: cred wasn't stored [task=%s, filename=%s, uid=%d, tgid=%u, pid=%u, ppid=%u]", - p->comm, path, cur_uid, p->tgid, p->pid, p->real_parent->pid); - defex_log_crit("[6]: stored [euid=%d fsuid=%d egid=%d] current [uid=%d euid=%d fsuid=%d egid=%d]", - ref_uid, ref_fsuid, ref_egid, cur_uid, cur_euid, cur_fsuid, cur_egid); - goto exit; - } - - parent = get_parent_task(p); - if (parent) { - parent_cred = get_task_cred(parent); - if (CHECK_ROOT_CREDS(parent_cred)) - cred_flags |= CRED_FLAGS_PROOT; - put_cred(parent_cred); - put_task_struct(parent); - } - - if (CHECK_ROOT_CREDS(dc->cred)) { -#ifdef DEFEX_LP_ENABLE - if (!lower_adb_permission(dc, cred_flags)) -#endif /* DEFEX_LP_ENABLE */ - { - set_task_creds(p, 1, 1, 1, cred_flags); - } - } - else - set_task_creds(p, cur_euid, cur_fsuid, cur_egid, cred_flags); - } else if (ref_uid == 1) { - if (!CHECK_ROOT_CREDS(dc->cred)) - set_task_creds(p, cur_euid, cur_fsuid, cur_egid, cred_flags); - } else if (ref_uid == dead_uid) { - path = get_dc_process_name(dc); - defex_log_crit("[5]: process wasn't killed [task=%s, filename=%s, uid=%d, tgid=%u, pid=%u, ppid=%u]", - p->comm, path, cur_uid, p->tgid, p->pid, p->real_parent->pid); - defex_log_crit("[5]: stored [euid=%d fsuid=%d egid=%d] current [uid=%d euid=%d fsuid=%d egid=%d]", - ref_uid, ref_fsuid, ref_egid, cur_uid, cur_euid, cur_fsuid, cur_egid); - goto exit; - } else { - check_deeper = 0; - /* temporary allow fsuid changes to "media_rw" */ - if ( (cur_uid != ref_uid) || - (cur_euid != ref_uid) || - (cur_egid != ref_egid) || - !((cur_fsuid == ref_fsuid) || - (cur_fsuid == ref_uid) || - (cur_fsuid%100000 == AID_SYSTEM) || - (cur_fsuid%100000 == AID_MEDIA_RW) || - (cur_fsuid%100000 == AID_MEDIA_OBB)) ) { - check_deeper = 1; - if (CHECK_ROOT_CREDS(dc->cred)) - set_task_creds(p, 1, 1, 1, cred_flags); - else - set_task_creds(p, cur_euid, cur_fsuid, cur_egid, cred_flags); - } - if (check_deeper && - (!at_same_group(cur_uid, ref_uid) || - !at_same_group(cur_euid, ref_uid) || - !at_same_group_gid(cur_egid, ref_egid) || - !at_same_group(cur_fsuid, ref_fsuid)) && - task_defex_is_secured(dc)) { - case_num = ((p->tgid == p->pid) ? 1 : 2); - goto trigger_violation; - } - } - - if (CHECK_ROOT_CREDS(dc->cred) && !(cred_flags & CRED_FLAGS_PROOT) && task_defex_is_secured(dc)) { - if (p->tgid != p->pid) { - case_num = 3; - goto trigger_violation; - } - case_num = 4; - goto trigger_violation; - } - -out: - return DEFEX_ALLOW; - -trigger_violation: - if (check_incfs(dc)) - return DEFEX_ALLOW; - set_task_creds(p, dead_uid, dead_uid, dead_uid, cred_flags); - path = get_dc_process_name(dc); - defex_log_crit("[%d]: credential violation [task=%s, filename=%s, uid=%d, tgid=%u, pid=%u, ppid=%u]", - case_num, p->comm, path, cur_uid, p->tgid, p->pid, p->real_parent->pid); - defex_log_crit("[%d]: stored [euid=%d fsuid=%d egid=%d] current [uid=%d euid=%d fsuid=%d egid=%d]", - case_num, ref_uid, ref_fsuid, ref_egid, cur_uid, cur_euid, cur_fsuid, cur_egid); - -#ifdef DEFEX_DSMS_ENABLE - defex_report_violation(PED_VIOLATION, 0, dc, ref_uid, ref_fsuid, ref_egid, case_num); -#endif /* DEFEX_DSMS_ENABLE */ - -exit: - return -DEFEX_DENY; -} -#endif /* DEFEX_PED_ENABLE */ - -#ifdef DEFEX_INTEGRITY_ENABLE -__visible_for_testing int task_defex_integrity(struct defex_context *dc) -{ - int ret = DEFEX_ALLOW, is_violation = 0; - char *proc_file, *new_file; - struct task_struct *p = dc->task; - - if (!get_dc_target_dpath(dc)) - goto out; - - new_file = get_dc_target_name(dc); - is_violation = rules_lookup(new_file, feature_integrity_check, dc->target_file); - - if (is_violation == DEFEX_INTEGRITY_FAIL) { - ret = -DEFEX_DENY; - proc_file = get_dc_process_name(dc); - - defex_log_crit("Integrity violation [task=%s (%s), child=%s, uid=%d]", - p->comm, proc_file, new_file, uid_get_value(dc->cred->uid)); -#ifdef DEFEX_DSMS_ENABLE - defex_report_violation(INTEGRITY_VIOLATION, 0, dc, 0, 0, 0, 0); -#endif /* DEFEX_DSMS_ENABLE */ - } -out: - return ret; -} -#endif /* DEFEX_INTEGRITY_ENABLE */ - -#ifdef DEFEX_SAFEPLACE_ENABLE -/* Safeplace feature decision function */ -__visible_for_testing int task_defex_safeplace(struct defex_context *dc) -{ - int ret = DEFEX_ALLOW, is_violation = 0; - char *proc_file, *new_file; - struct task_struct *p = dc->task; - - if (!CHECK_ROOT_CREDS(dc->cred)) - goto out; - - if (!get_dc_target_dpath(dc)) - goto out; - - new_file = get_dc_target_name(dc); - is_violation = !rules_lookup(new_file, feature_safeplace_path, dc->target_file); - - if (is_violation) { - ret = -DEFEX_DENY; - proc_file = get_dc_process_name(dc); - - defex_log_crit("Safeplace violation [task=%s (%s), child=%s, uid=%d]", - p->comm, proc_file, new_file, uid_get_value(dc->cred->uid)); -#ifdef DEFEX_DSMS_ENABLE - defex_report_violation(SAFEPLACE_VIOLATION, 0, dc, 0, 0, 0, 0); -#endif /* DEFEX_DSMS_ENABLE */ - } -out: - return ret; -} -#endif /* DEFEX_SAFEPLACE_ENABLE */ - -#ifdef DEFEX_TRUSTED_MAP_ENABLE -/* Trusted map feature decision function */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) -__visible_for_testing int task_defex_trusted_map(struct defex_context *dc, va_list ap) -{ - int ret = DEFEX_ALLOW, argc; - struct linux_binprm *bprm; - - if (!CHECK_ROOT_CREDS(&dc->cred)) - goto out; - - bprm = va_arg(ap, struct linux_binprm *); - argc = bprm->argc; -#ifdef DEFEX_DEBUG_ENABLE - if (argc <= 0) - defex_log_crit("[DTM] Invalid trusted map arguments - check integration on fs/exec.c (argc %d)", argc); -#endif - - ret = defex_trusted_map_lookup(dc, argc, bprm); - if (defex_tm_mode_enabled(DEFEX_TM_PERMISSIVE_MODE)) - ret = DEFEX_ALLOW; -out: - return ret; -} -#else -__visible_for_testing int task_defex_trusted_map(struct defex_context *dc, va_list ap) -{ - int ret = DEFEX_ALLOW, argc; - void *argv; - - if (!CHECK_ROOT_CREDS(dc->cred)) - goto out; - - argc = va_arg(ap, int); - argv = va_arg(ap, void *); -#ifdef DEFEX_DEBUG_ENABLE - if (argc <= 0) - defex_log_crit( - "[DTM] Invalid trusted map arguments - check integration on fs/exec.c (argc %d)", argc); -#endif - - ret = defex_trusted_map_lookup(dc, argc, argv); - if (defex_tm_mode_enabled(DEFEX_TM_PERMISSIVE_MODE)) - ret = DEFEX_ALLOW; -out: - return ret; -} -#endif -#endif /* DEFEX_TRUSTED_MAP_ENABLE */ - -#ifdef DEFEX_IMMUTABLE_ENABLE - -/* Immutable feature decision function */ -__visible_for_testing int task_defex_src_exception(struct defex_context *dc) -{ - struct file *exe_file = get_dc_process_file(dc); - char *proc_name = get_dc_process_name(dc); - int allow = 1; - - if (!get_dc_process_dpath(dc)) - return allow; - - exe_file = get_dc_process_file(dc); - allow = rules_lookup(proc_name, feature_immutable_src_exception, exe_file); - return allow; -} - -/* Immutable feature decision function */ -__visible_for_testing int task_defex_immutable(struct defex_context *dc, int attribute) -{ - int ret = DEFEX_ALLOW, is_violation = 0; - char *proc_file, *new_file; - struct task_struct *p = dc->task; - - if (!get_dc_target_dpath(dc)) - goto out; - - new_file = get_dc_target_name(dc); - is_violation = rules_lookup(new_file, attribute, dc->target_file); - - if (is_violation) { - /* Check the Source exception and self-access */ - if (attribute == feature_immutable_path_open && - (task_defex_src_exception(dc) || - defex_files_identical(get_dc_process_file(dc), dc->target_file))) - goto out; - - ret = -DEFEX_DENY; - proc_file = get_dc_process_name(dc); - defex_log_crit("Immutable %s violation [task=%s (%s), access to:%s]", - (attribute==feature_immutable_path_open)?"open":"write", p->comm, proc_file, new_file); -#ifdef DEFEX_DSMS_ENABLE - defex_report_violation(IMMUTABLE_VIOLATION, 0, dc, 0, 0, 0, 0); -#endif /* DEFEX_DSMS_ENABLE */ - } -out: - return ret; -} -#endif /* DEFEX_IMMUTABLE_ENABLE */ - -/* Main decision function */ -int task_defex_enforce(struct task_struct *p, struct file *f, int syscall, ...) -{ - int ret = DEFEX_ALLOW; - int feature_flag; - const struct local_syscall_struct *item; - struct defex_context dc; -#ifdef DEFEX_TRUSTED_MAP_ENABLE - va_list ap; -#endif - - if (boot_state_unlocked) - return ret; - - if (!p || p->pid == 1 || !p->mm || !is_task_used(p)) - return ret; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) - if ((p->state & (__TASK_STOPPED | TASK_DEAD)) || (p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD))) -#else - if ((p->__state & (__TASK_STOPPED | TASK_DEAD)) || (p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD))) -#endif - return ret; - - if (syscall < 0) { - item = get_local_syscall(-syscall); - if (!item) - return ret; - syscall = item->local_syscall; - } - - feature_flag = defex_get_features(); - get_task_struct(p); - if (!init_defex_context(&dc, syscall, p, f)) - goto do_allow; - -#ifdef DEFEX_PED_ENABLE - /* Credential escalation feature */ - if (feature_flag & FEATURE_CHECK_CREDS) { - ret = task_defex_check_creds(&dc); - if (ret) { - if (!(feature_flag & FEATURE_CHECK_CREDS_SOFT)) { - release_defex_context(&dc); - put_task_struct(p); - kill_process_group(p, p->tgid, p->pid); - return -DEFEX_DENY; - } - } - } -#endif /* DEFEX_PED_ENABLE */ - -#ifdef DEFEX_INTEGRITY_ENABLE - /* Integrity feature */ - if (feature_flag & FEATURE_INTEGRITY) { - if (syscall == __DEFEX_execve) { - ret = task_defex_integrity(&dc); - if (ret == -DEFEX_DENY) { - if (!(feature_flag & FEATURE_INTEGRITY_SOFT)) { - release_defex_context(&dc); - put_task_struct(p); - kill_process(p); - return -DEFEX_DENY; - } - } - } - } -#endif /* DEFEX_INTEGRITY_ENABLE */ - -#ifdef DEFEX_SAFEPLACE_ENABLE - /* Safeplace feature */ - if (feature_flag & FEATURE_SAFEPLACE) { - if (syscall == __DEFEX_execve) { - ret = task_defex_safeplace(&dc); - if (ret == -DEFEX_DENY) { - if (!(feature_flag & FEATURE_SAFEPLACE_SOFT)) { - release_defex_context(&dc); - put_task_struct(p); - kill_process(p); - return -DEFEX_DENY; - } - } - } - } -#endif /* DEFEX_SAFEPLACE_ENABLE */ - -#ifdef DEFEX_IMMUTABLE_ENABLE - /* Immutable feature */ - if (feature_flag & FEATURE_IMMUTABLE) { - if (syscall == __DEFEX_openat || syscall == __DEFEX_write) { - ret = task_defex_immutable(&dc, - (syscall == __DEFEX_openat)?feature_immutable_path_open:feature_immutable_path_write); - if (ret == -DEFEX_DENY) { - if (!(feature_flag & FEATURE_IMMUTABLE_SOFT)) { - goto do_deny; - } - } - } - } -#endif /* DEFEX_IMMUTABLE_ENABLE */ - -#ifdef DEFEX_TRUSTED_MAP_ENABLE - /* Trusted map feature */ - if (feature_flag & FEATURE_TRUSTED_MAP) { - if (syscall == __DEFEX_execve) { - va_start(ap, syscall); - ret = task_defex_trusted_map(&dc, ap); - va_end(ap); - if (ret == -DEFEX_DENY) { - if (!(feature_flag & FEATURE_TRUSTED_MAP_SOFT)) { - kill_process(p); - goto do_deny; - } - } - } - } -#endif /* DEFEX_TRUSTED_MAP_ENABLE */ -do_allow: - release_defex_context(&dc); - put_task_struct(p); - return DEFEX_ALLOW; -#if defined(DEFEX_IMMUTABLE_ENABLE) || defined(DEFEX_TRUSTED_MAP_ENABLE) -do_deny: - release_defex_context(&dc); - put_task_struct(p); - return -DEFEX_DENY; -#endif /* DEFEX_IMMUTABLE_ENABLE || DEFEX_TRUSTED_MAP_ENABLE */ -} - -int task_defex_zero_creds(struct task_struct *tsk) -{ - int is_fork = -1; - if (tsk->flags & (PF_KTHREAD | PF_WQ_WORKER)) { - return 0; - } - if (is_task_creds_ready()) { - is_fork = ((tsk->flags & PF_FORKNOEXEC) && (!tsk->on_rq)); -#ifdef TASK_NEW -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) - if (!is_fork && (tsk->state & TASK_NEW)) -#else - if (!is_fork && (tsk->__state & TASK_NEW)) -#endif - is_fork = 1; -#endif /* TASK_NEW */ - set_task_creds_tcnt(tsk, is_fork?1:-1); - } - -#ifdef DEFEX_CACHES_ENABLE - defex_file_cache_delete(tsk->pid); -#endif /* DEFEX_CACHES_ENABLE */ - return 0; -} - -int task_defex_user_exec(const char *new_file) -{ -#ifdef DEFEX_UMH_RESTRICTION_ENABLE - int res = DEFEX_ALLOW, is_violation; - struct file *fp = NULL; - static unsigned int rules_load_cnt; - - if (boot_state_unlocked) - return DEFEX_ALLOW; - - if (!check_rules_ready()) { - if (rules_load_cnt++%100 == 0) - defex_log_warn("Rules not ready"); - goto umh_out; - } - - if (current == NULL || current->fs == NULL) { - goto umh_out; - } - - fp = local_fopen(new_file, O_RDONLY, 0); - if (IS_ERR(fp) || (fp == NULL)) { - res = DEFEX_DENY; - goto umh_out; - } else { - filp_close(fp, NULL); - } - - is_violation = !rules_lookup(new_file, feature_umhbin_path, NULL); - if (is_violation) { - defex_log_warn("UMH Exec Denied: %s", new_file); - res = DEFEX_DENY; - goto umh_out; - } - -umh_out: - return res; -#else - return DEFEX_ALLOW; -#endif /* DEFEX_UMH_RESTRICTION_ENABLE */ -} diff --git a/security/samsung/defex_lsm/core/defex_rules_proc.c b/security/samsung/defex_lsm/core/defex_rules_proc.c deleted file mode 100755 index 8e1f691cf..000000000 --- a/security/samsung/defex_lsm/core/defex_rules_proc.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) -#include -#endif /* < KERNEL_VERSION(4, 12, 0) */ - -#include "include/defex_debug.h" -#include "include/defex_internal.h" -#include "include/defex_rules.h" -#include "include/defex_sign.h" -#ifdef DEFEX_TRUSTED_MAP_ENABLE -#include "include/defex_tailer.h" -#include "include/ptree.h" -#endif - -#define LOAD_FLAG_DPOLICY 0x01 -#define LOAD_FLAG_DPOLICY_SYSTEM 0x02 -#define LOAD_FLAG_SYSTEM_FIRST 0x04 -#define LOAD_FLAG_TIMEOUT 0x08 -#define LOAD_FLAG_RECOVERY 0x10 - -#define DEFEX_RULES_ARRAY_SIZE_MIN 64 -#define DEFEX_RULES_ARRAY_SIZE_FIXED (32 * 1024) -#define DEFEX_RULES_ARRAY_SIZE_MAX (256 * 1024) - - -/* - * Variant 1: Platform build, use static packed rules array - */ -#include "defex_packed_rules.inc" - -#ifdef DEFEX_RAMDISK_ENABLE -/* - * Variant 2: Platform build, load rules from kernel ramdisk or system partition - */ -#ifdef DEFEX_SIGN_ENABLE -#include "include/defex_sign.h" -#endif -#if (DEFEX_RULES_ARRAY_SIZE < 8) -#undef DEFEX_RULES_ARRAY_SIZE -#define DEFEX_RULES_ARRAY_SIZE DEFEX_RULES_ARRAY_SIZE_MIN -#endif -#ifdef DEFEX_KERNEL_ONLY -#undef DEFEX_RULES_ARRAY_SIZE -#define DEFEX_RULES_ARRAY_SIZE DEFEX_RULES_ARRAY_SIZE_MAX -__visible_for_testing unsigned char packed_rules_primary[DEFEX_RULES_ARRAY_SIZE] = {0}; -#else -#if (DEFEX_RULES_ARRAY_SIZE < DEFEX_RULES_ARRAY_SIZE_FIXED) -#undef DEFEX_RULES_ARRAY_SIZE -#define DEFEX_RULES_ARRAY_SIZE DEFEX_RULES_ARRAY_SIZE_FIXED -#endif -__visible_for_testing unsigned char packed_rules_primary[DEFEX_RULES_ARRAY_SIZE] __ro_after_init = {0}; -#endif /* DEFEX_KERNEL_ONLY */ -static unsigned char *packed_rules_secondary; -#ifdef DEFEX_TRUSTED_MAP_ENABLE -struct PPTree dtm_tree; -#endif - -#endif /* DEFEX_RAMDISK_ENABLE */ - -#ifdef DEFEX_TRUSTED_MAP_ENABLE -/* In loaded policy, title of DTM's section; set by tailer -t in buildscript/build_external/defex. */ -#define DEFEX_DTM_SECTION_NAME "dtm_rules" -#endif - -#ifdef DEFEX_INTEGRITY_ENABLE - -#include -#include -#include -#include -#include "../../integrity/integrity.h" -#define SHA256_DIGEST_SIZE 32 -#endif /* DEFEX_INTEGRITY_ENABLE */ - -struct rules_file_struct { - char *name; - int flags; -}; - -static const struct rules_file_struct rules_files[4] = { - { "/dpolicy", LOAD_FLAG_DPOLICY }, - { "/first_stage_ramdisk/dpolicy", LOAD_FLAG_DPOLICY }, - { "/vendor/etc/dpolicy", LOAD_FLAG_DPOLICY }, - { "/dpolicy_system", LOAD_FLAG_DPOLICY_SYSTEM } -}; -static volatile unsigned int load_flags; - - -__visible_for_testing unsigned long get_current_sec(void) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) - return get_seconds(); -#else - return ktime_get_seconds(); -#endif -} - -__visible_for_testing char *get_rules_ptr(int is_system) -{ - if (load_flags & LOAD_FLAG_SYSTEM_FIRST) - is_system = !is_system; - - return is_system ? (char *)packed_rules_secondary : (char *)packed_rules_primary; -} - -__visible_for_testing int get_rules_size(int is_system) -{ - struct rule_item_struct *rules_ptr = (struct rule_item_struct *)get_rules_ptr(is_system); - - return rules_ptr ? rules_ptr->data_size : 0; -} - -int check_rules_ready(void) -{ - struct rule_item_struct *base = (struct rule_item_struct *)packed_rules_primary; - - return (!base || !base->data_size)?0:1; -} - -__visible_for_testing int check_system_mount(void) -{ - static int mount_system_root = -1; - struct file *fp; - - if (mount_system_root < 0) { - fp = local_fopen("/sbin/recovery", O_RDONLY, 0); - if (IS_ERR(fp)) - fp = local_fopen("/system/bin/recovery", O_RDONLY, 0); - - if (!IS_ERR(fp)) { - defex_log_crit("Recovery mode"); - filp_close(fp, NULL); - load_flags |= LOAD_FLAG_RECOVERY; - } else { - defex_log_crit("Normal mode"); - } - - mount_system_root = 0; - fp = local_fopen("/system_root", O_DIRECTORY | O_PATH, 0); - if (!IS_ERR(fp)) { - filp_close(fp, NULL); - mount_system_root = 1; - defex_log_crit("System_root=TRUE"); - } else { - defex_log_crit("System_root=FALSE"); - } - } - return (mount_system_root > 0); -} - -#ifdef DEFEX_INTEGRITY_ENABLE -__visible_for_testing int defex_check_integrity(struct file *f, unsigned char *hash) -{ - struct crypto_shash *handle = NULL; - struct shash_desc *shash = NULL; - static const unsigned char buff_zero[SHA256_DIGEST_SIZE] = {0}; - unsigned char hash_sha256[SHA256_DIGEST_SIZE]; - unsigned char *buff = NULL; - size_t buff_size = PAGE_SIZE; - loff_t file_size = 0; - int ret = 0, err = 0, read_size = 0; - - // A saved hash is zero, skip integrity check - if (!memcmp(buff_zero, hash, SHA256_DIGEST_SIZE)) - return ret; - - if (IS_ERR(f)) - goto hash_error; - - handle = crypto_alloc_shash("sha256", 0, 0); - if (IS_ERR(handle)) { - err = PTR_ERR(handle); - defex_log_err("Can't alloc sha256, error : %d", err); - return -1; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) - shash = (struct shash_desc *)kvzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(handle), GFP_KERNEL); -#else - shash = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(handle), GFP_KERNEL); -#endif /* < KERNEL_VERSION(4, 12, 0) */ - - if (shash == NULL) - goto hash_error; - - shash->tfm = handle; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) - buff = kvmalloc(buff_size, GFP_KERNEL); -#else - buff = kmalloc(buff_size, GFP_KERNEL); -#endif /* < KERNEL_VERSION(4, 12, 0) */ - - if (buff == NULL) - goto hash_error; - - err = crypto_shash_init(shash); - if (err < 0) - goto hash_error; - - - while (1) { - read_size = local_fread(f, file_size, (char *)buff, buff_size); - if (read_size < 0) - goto hash_error; - if (read_size == 0) - break; - file_size += read_size; - err = crypto_shash_update(shash, buff, read_size); - if (err < 0) - goto hash_error; - } - - err = crypto_shash_final(shash, hash_sha256); - if (err < 0) - goto hash_error; - - ret = memcmp(hash_sha256, hash, SHA256_DIGEST_SIZE); - - goto hash_exit; - -hash_error: - ret = -1; -hash_exit: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) - kvfree(buff); - kvfree(shash); -#else - kfree(buff); - kfree(shash); -#endif /* < KERNEL_VERSION(4, 12, 0) */ - - if (handle) - crypto_free_shash(handle); - return ret; - -} - -__visible_for_testing int defex_integrity_default(const char *file_path) -{ - static const char integrity_default[] = "/system/bin/install-recovery.sh"; - - return strncmp(integrity_default, file_path, sizeof(integrity_default)); -} - -#endif /* DEFEX_INTEGRITY_ENABLE */ - -#if defined(DEFEX_RAMDISK_ENABLE) - -#ifdef DEFEX_TRUSTED_MAP_ENABLE -static const unsigned char *find_policy_section(const char *name, const char *data, int data_size, long *section_size) -{ - return data_size > 0 ? defex_tailerp_find(data, data_size, name, section_size) : 0; -} -#endif - -__visible_for_testing int check_rule_structure(unsigned char *data_buff) -{ - struct rule_item_struct *rules_ptr = (struct rule_item_struct *)data_buff; - int res = 0; - const int req_size = sizeof(struct rule_item_struct) + rules_ptr->size; - -#ifdef DEFEX_INTEGRITY_ENABLE - const int integrity_state = 1; -#else - const int integrity_state = 0; -#endif /* DEFEX_INTEGRITY_ENABLE */ - if (rules_ptr->next_level != req_size || memcmp(rules_ptr->name, "DEFEX_RULES_FILE", 16) != 0) { - defex_log_err("Rules structure is wrong. Integrity state: %d", integrity_state); - res = -1; - } else { - defex_log_info("Rules structure is OK. Integrity state: %d", integrity_state); - } - return res; -} - -__visible_for_testing int load_rules_common(struct file *f, int flags) -{ - int res = -1, data_size, rules_size; - unsigned char *data_buff = NULL; - - data_size = i_size_read(file_inode(f)); - if (data_size <= 0 || data_size > DEFEX_RULES_ARRAY_SIZE_MAX) - goto do_clean; - data_buff = vmalloc(data_size); - if (!data_buff) - goto do_clean; - - rules_size = local_fread(f, 0, data_buff, data_size); - if (rules_size <= 0) { - defex_log_err("Failed to read rules file (%d)", rules_size); - goto do_clean; - } - defex_log_info("Read %d bytes", rules_size); - -#ifdef DEFEX_SIGN_ENABLE - res = defex_rules_signature_check((char *)data_buff, (unsigned int)rules_size, (unsigned int *)&rules_size); - - if (!res) - defex_log_info("Rules signature verified successfully"); - else - defex_log_err("Rules signature incorrect!!!"); -#else - res = 0; -#endif - - if (!res) - res = check_rule_structure(data_buff); - - if (!res) { - const unsigned char *policy_data = NULL; /* where additional features like DTM could look for policy data */ - if (!(load_flags & (LOAD_FLAG_DPOLICY | LOAD_FLAG_DPOLICY_SYSTEM))) { - if (rules_size > sizeof(packed_rules_primary)) { - res = -1; - goto do_clean; - } - memcpy(packed_rules_primary, data_buff, rules_size); - policy_data = packed_rules_primary; - if (flags & LOAD_FLAG_DPOLICY_SYSTEM) - load_flags |= LOAD_FLAG_SYSTEM_FIRST; - defex_log_info("Primary rules have been stored"); - } else { - if (rules_size > 0) { - policy_data = packed_rules_secondary = data_buff; - data_buff = NULL; - defex_log_info("Secondary rules have been stored"); - } - } -#ifdef DEFEX_SHOW_RULES_ENABLE - if (policy_data) - defex_show_structure((void *)policy_data, rules_size); -#endif /* DEFEX_SHOW_RULES_ENABLE */ -#ifdef DEFEX_TRUSTED_MAP_ENABLE - if (policy_data && !dtm_tree.data) { /* DTM not yet initialized */ - const unsigned char *dtm_section = find_policy_section(DEFEX_DTM_SECTION_NAME, policy_data, rules_size, 0); - if (dtm_section) - pptree_set_data(&dtm_tree, dtm_section); - } -#endif - load_flags |= flags; - res = rules_size; - } - -do_clean: - filp_close(f, NULL); - vfree(data_buff); - return res; -} - -int load_rules_late(int forced_load) -{ - struct file *f = NULL; - int f_index, res = 0; - static atomic_t load_lock = ATOMIC_INIT(1); - const struct rules_file_struct *item; - static unsigned long start_time; - static unsigned long last_time; - static int load_counter = 0; - unsigned long cur_time = get_current_sec(); - - if (load_flags & LOAD_FLAG_TIMEOUT) - return -1; - - if (!atomic_dec_and_test(&load_lock)) { - atomic_inc(&load_lock); - return res; - } - - /* The first try to load, initialize time values */ - if (!start_time) - start_time = cur_time; - /* Skip this try, wait for next second */ - if (!forced_load && (cur_time == last_time)) - goto do_exit; - last_time = cur_time; - /* Load has been attempted for 20 seconds, give up. */ - if ((cur_time - start_time) > 20) { - res = -1; - load_flags |= LOAD_FLAG_TIMEOUT; - defex_log_warn("Late load timeout. Try counter = %d", load_counter); - goto do_exit; - } - load_counter++; - - for (f_index = 0; f_index < ARRAY_SIZE(rules_files); f_index++) { - item = &rules_files[f_index]; - if (!(item->flags & load_flags)) { - f = local_fopen(item->name, O_RDONLY, 0); - if (!IS_ERR_OR_NULL(f)) { - defex_log_info("Late load rules file: %s", item->name); - break; - } - } - } - if (IS_ERR_OR_NULL(f)) { -#ifdef DEFEX_KERNEL_ONLY - defex_log_err("Failed to open rules file (%ld)", (long)PTR_ERR(f)); -#endif /* DEFEX_KERNEL_ONLY */ - goto do_exit; - } - - res = load_rules_common(f, item->flags); - res = (res < 0) ? res : (res > 0); - -do_exit: - atomic_inc(&load_lock); - return res; -} - -int __init do_load_rules(void) -{ - struct file *f = NULL; - int res = -1; - unsigned int f_index = 0; - const struct rules_file_struct *item; - - if (boot_state_recovery) - load_flags |= LOAD_FLAG_RECOVERY; - -load_next: - while (f_index < ARRAY_SIZE(rules_files)) { - item = &rules_files[f_index]; - if (!(load_flags & item->flags)) { - f = local_fopen(item->name, O_RDONLY, 0); - if (!IS_ERR_OR_NULL(f)) { - defex_log_info("Load rules file: %s", item->name); - break; - } - } - f_index++; - }; - - if (f_index == ARRAY_SIZE(rules_files)) { - if (load_flags & (LOAD_FLAG_DPOLICY_SYSTEM | LOAD_FLAG_DPOLICY)) - return 0; - defex_log_err("Failed to open rules file (%ld)", (long)PTR_ERR(f)); - -#ifdef DEFEX_KERNEL_ONLY - if (load_flags & LOAD_FLAG_RECOVERY) - res = 0; -#endif /* DEFEX_KERNEL_ONLY */ - return res; - } - - res = load_rules_common(f, item->flags); - res = (res < 0) ? res : 0; - -#ifdef DEFEX_KERNEL_ONLY - if ((load_flags & LOAD_FLAG_RECOVERY) && res != 0) { - res = 0; - defex_log_info("Kernel Only & recovery mode, rules loading is passed"); - } -#endif - if (++f_index < ARRAY_SIZE(rules_files)) - goto load_next; - return res; -} - -#endif /* DEFEX_RAMDISK_ENABLE */ - -__visible_for_testing struct rule_item_struct *lookup_dir(struct rule_item_struct *base, - const char *name, - int l, - int for_recovery, - char *base_start) -{ - struct rule_item_struct *item = NULL; - unsigned int offset; - - if (!base || !base->next_level || !base_start) - return item; - item = GET_ITEM_PTR(base->next_level, base_start); - do { - if ((!(item->feature_type & feature_is_file) - || (!!(item->feature_type & feature_for_recovery)) == for_recovery) - && item->size == l && !memcmp(name, item->name, l)) - return item; - offset = item->next_file; - item = GET_ITEM_PTR(offset, base_start); - } while (offset); - return NULL; -} - -__visible_for_testing int lookup_tree(const char *file_path, int attribute, struct file *f) -{ - const char *ptr, *next_separator; - struct rule_item_struct *base, *cur_item = NULL; - char *base_start; - int l, is_system, forced_load; - const int is_recovery = !!(load_flags & LOAD_FLAG_RECOVERY); - const unsigned int load_both_mask = (LOAD_FLAG_DPOLICY | LOAD_FLAG_DPOLICY_SYSTEM); - int iterator = 0; - - if (!file_path || *file_path != '/') - return 0; - - is_system = ((strncmp("/system/", file_path, 8) == 0) || - (strncmp("/product/", file_path, 9) == 0) || - (strncmp("/apex/", file_path, 6) == 0) || - (strncmp("/system_ext/", file_path, 12) == 0))?1:0; - - forced_load = is_system && - (attribute == feature_safeplace_path || - attribute == feature_umhbin_path); - - if ((load_flags & load_both_mask) != load_both_mask && - !(load_flags & LOAD_FLAG_TIMEOUT)) { - /* allow all requests if rules were not loaded for Recovery mode */ - if (!load_rules_late(forced_load) || is_recovery) - return (attribute == feature_ped_exception || - attribute == feature_safeplace_path)?1:0; - } - -try_not_system: - - base_start = get_rules_ptr(get_rules_size(is_system) ? is_system : (!is_system)); - base = (struct rule_item_struct *)base_start; - - if (!base || !base->data_size) { - /* block all requests if rules were not loaded */ - return 0; - } - - ptr = file_path + 1; - do { - next_separator = strchr(ptr, '/'); - if (!next_separator) - l = strlen(ptr); - else - l = next_separator - ptr; - if (!l) - return 0; - cur_item = lookup_dir(base, ptr, l, is_recovery, base_start); - if (!cur_item) - cur_item = lookup_dir(base, ptr, l, !is_recovery, base_start); - if (!cur_item) - break; - if (cur_item->feature_type & attribute) { -#ifdef DEFEX_INTEGRITY_ENABLE - /* Integrity acceptable only for files */ - if ((cur_item->feature_type & feature_integrity_check) && - (cur_item->feature_type & feature_is_file) && f) { - if (defex_integrity_default(file_path) - && defex_check_integrity(f, cur_item->integrity)) - return DEFEX_INTEGRITY_FAIL; - } -#endif /* DEFEX_INTEGRITY_ENABLE */ - if (attribute & (feature_immutable_path_open | feature_immutable_path_write) - && !(cur_item->feature_type & feature_is_file)) { - /* Allow open the folder by default */ - if (!next_separator || *(ptr + l + 1) == 0) - return 0; - } - return 1; - } - base = cur_item; - ptr += l; - if (next_separator) - ptr++; - } while (*ptr); - if ((load_flags & load_both_mask) == load_both_mask && ++iterator < 2) { - is_system = !is_system; - goto try_not_system; - } - return 0; -} - -int rules_lookup(const char *target_file, int attribute, struct file *f) -{ - int ret = 0; -#if (defined(DEFEX_SAFEPLACE_ENABLE) || defined(DEFEX_IMMUTABLE_ENABLE) || defined(DEFEX_PED_ENABLE)) - static const char system_root_txt[] = "/system_root"; - - if (check_system_mount() && - !strncmp(target_file, system_root_txt, sizeof(system_root_txt) - 1)) - target_file += (sizeof(system_root_txt) - 1); - - ret = lookup_tree(target_file, attribute, f); -#endif - return ret; -} - -void __init defex_load_rules(void) -{ -#if defined(DEFEX_RAMDISK_ENABLE) - if (!boot_state_unlocked && do_load_rules() != 0) { -#if !(defined(DEFEX_DEBUG_ENABLE) || defined(DEFEX_KERNEL_ONLY)) - panic("[DEFEX] Signature mismatch.\n"); -#endif - } -#endif /* DEFEX_RAMDISK_ENABLE */ -} diff --git a/security/samsung/defex_lsm/core/defex_sysfs.c b/security/samsung/defex_lsm/core/defex_sysfs.c deleted file mode 100755 index 6e28d8c01..000000000 --- a/security/samsung/defex_lsm/core/defex_sysfs.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "include/defex_debug.h" -#include "include/defex_internal.h" -#include "include/defex_rules.h" - -static struct kset *defex_kset; - -int __init defex_init_sysfs(void) -{ - defex_kset = kset_create_and_add("defex", NULL, NULL); - if (!defex_kset) - return -ENOMEM; - -#if defined(DEFEX_DEBUG_ENABLE) - if (defex_create_debug(defex_kset) != DEFEX_OK) - goto kset_error; -#endif /* DEFEX_DEBUG_ENABLE */ - - return 0; - -kset_error: - kset_unregister(defex_kset); - defex_kset = NULL; - - return -ENOMEM; -} - - diff --git a/security/samsung/defex_lsm/core/defex_tailer.c b/security/samsung/defex_lsm/core/defex_tailer.c deleted file mode 100755 index 20799337b..000000000 --- a/security/samsung/defex_lsm/core/defex_tailer.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Routines for handling archival-like files where each new contents is - * appended and linked backwards - memory-only variants. - */ - -#include -#include "include/defex_tailer.h" - -/* Reads int from 4-byte big-endian */ -static int be2int(const unsigned char *p) -{ - return (*p << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; -} - -long defex_tailerp_has_suffix(const unsigned char *p, long size) -{ - return !p || size < TAIL_MAGIC_LEN + 8 + 1 + 2 || - memcmp(p + size - TAIL_MAGIC_LEN, TAIL_MAGIC, TAIL_MAGIC_LEN) - ? 0 : size - TAIL_MAGIC_LEN; -} - -int defex_tailerp_iterate(const unsigned char *p, long size, - int (*task)(const char *title, int titleLen, - const unsigned char *start, long size, - void *data), - void *data) -{ - long start, offset = defex_tailerp_has_suffix(p, size); - char buffer[TAIL_MAX_TITLE_LENGTH]; - - if (!offset) - return 0; - for (offset -= 2; ; offset = start - 2) { - int i, ttlLength; - long size; - - /* Possibly change behavior depending on version - * (p[offset] and p[offset + 1]) - */ - ttlLength = p[--offset]; - if (offset - 4 - 4 - ttlLength < 0) - return -1; - memcpy(buffer, p + (offset -= ttlLength), ttlLength); - size = be2int(p + (offset -= 4)); - start = be2int(p + (offset -= 4)); - if (task) { - i = (*task)(buffer, ttlLength, - p + start, size, data); - if (i < 0) - return i; - } - if (!start) - break; - } - return 0; -} - -/* Auxiliary data for finding an entry */ -struct find_data { - const char *title; - int titleLen; - int found; - const unsigned char *start; - long size; -}; - -static int tailerp_iteratefind(const char *title, int titleLen, - const unsigned char *start, long size, - void *data) -{ - struct find_data *fd = (struct find_data *)data; - - if (fd->titleLen == titleLen && - !memcmp(title, fd->title, titleLen)) { - fd->found = 1; - fd->start = start; - fd->size = size; - return -1; - } - return 0; -} - -const unsigned char *defex_tailerp_find(const unsigned char *p, long size, - const char *title, long *sizep) -{ - struct find_data fd; - - fd.title = title; - fd.titleLen = strlen(title); - fd.found = 0; - if (!defex_tailerp_iterate(p, size, tailerp_iteratefind, &fd)) - return 0; - if (fd.found) { - if (sizep) - *sizep = fd.size; - return fd.start; - } - return 0; -} diff --git a/security/samsung/defex_lsm/debug/defex_debug.c b/security/samsung/defex_lsm/debug/defex_debug.c deleted file mode 100755 index 2b09e5f21..000000000 --- a/security/samsung/defex_lsm/debug/defex_debug.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#ifdef DEFEX_LOG_BUFFER_ENABLE -#include -#include -#include -#endif /* DEFEX_LOG_BUFFER_ENABLE */ -#include -#include -#ifdef DEFEX_LOG_BUFFER_ENABLE -#include -#endif /* DEFEX_LOG_BUFFER_ENABLE */ -#include -#include -#include "include/defex_debug.h" -#include "include/defex_internal.h" - -static int last_cmd; - -#ifdef DEFEX_LOG_BUFFER_ENABLE -unsigned char *log_buf; -DEFINE_SPINLOCK(log_buf_lock); -static unsigned int log_buf_in_index, log_buf_out_index; -static unsigned long log_buf_size, log_buf_mask; - -static int log_buf_init(void) -{ - int ret = 0; - - log_buf_size = DEFEX_LOG_BUF_SIZE; - do { - log_buf = vmalloc(log_buf_size); - if (log_buf) - break; - log_buf_size >>= 1; - } while (log_buf_size > PAGE_SIZE); - if (!log_buf) - ret = -1; - - log_buf_in_index = 0; - log_buf_out_index = 0; - log_buf_mask = log_buf_size - 1; - - defex_log_info("Log buffer size set to %ld bytes", log_buf_size); - - return ret; -} - -static int log_buffer_put(const char *msg, int msg_len) -{ - char c; - int avail, ret = -1; - - if (!log_buf_size) - return ret; - - spin_lock(&log_buf_lock); - avail = log_buf_size - ((log_buf_in_index - log_buf_out_index) & log_buf_mask); - if (avail > msg_len) { - do { - c = *msg++; - log_buf[log_buf_in_index++] = c; - log_buf_in_index &= log_buf_mask; - } while (--msg_len); - if (c != '\n') { - log_buf[log_buf_in_index++] = '\n'; - log_buf_in_index &= log_buf_mask; - } - ret = 0; - } - spin_unlock(&log_buf_lock); - return ret; -} - -static int log_buffer_get(char *str, int buff_size) -{ - char value; - int index = 0; - unsigned int log_buf_out_local; - - if (log_buf_in_index == log_buf_out_index || buff_size < 2) - return 0; - - spin_lock(&log_buf_lock); - log_buf_out_local = log_buf_out_index; - do { - value = log_buf[log_buf_out_local++]; - str[index++] = value; - log_buf_out_local &= log_buf_mask; - if (value == '\n') { - str[index] = 0; - log_buf_out_index = log_buf_out_local; - spin_unlock(&log_buf_lock); - return index; - } - } while (--buff_size > 1 && (log_buf_in_index != log_buf_out_local)); - spin_unlock(&log_buf_lock); - return 0; -} - -void log_buffer_flush(void) -{ - char msg[MAX_LEN]; - int msg_len; - - pr_info("%s== Buffer flushing begin ==", DEFEX_LOG_TAG); - - do { - msg_len = log_buffer_get(&msg[0], MAX_LEN); - if (msg_len) - pr_info("%s", msg); - } while (msg_len); - - pr_info("%s== Buffer flushing end ==", DEFEX_LOG_TAG); -} -#endif /* DEFEX_LOG_BUFFER_ENABLE */ - -void defex_print_msg(const enum defex_log_level msg_type, const char *format, ...) -{ - char msg[MAX_LEN]; - int msg_len, ktime_msg_len = 0; - va_list aptr; - static const char header[] = DEFEX_LOG_TAG; - -#ifdef DEFEX_LOG_BUFFER_ENABLE - if ((msg_type != MSG_TIMEOFF) && (msg_type != MSG_BLOB)) { - ktime_t cur_time = ktime_get_boottime(); - - ktime_msg_len = snprintf(msg, MAX_LEN, - "[% 4lld.%04lld] ", cur_time/1000000000, (cur_time%1000000000)/100000); - } -#endif /* DEFEX_LOG_BUFFER_ENABLE */ - - va_start(aptr, format); - msg_len = vsnprintf(msg + ktime_msg_len, MAX_LEN - ktime_msg_len, format, aptr); - va_end(aptr); -#ifdef DEFEX_LOG_BUFFER_ENABLE - if (DEFEX_LOG_LEVEL_MASK & msg_type) - if (!log_buffer_put(msg, msg_len + ktime_msg_len)) - return; -#endif /* DEFEX_LOG_BUFFER_ENABLE */ - switch (msg_type) { - case MSG_CRIT: - pr_crit("%s%s\n", header, msg + ktime_msg_len); - break; - case MSG_ERR: - pr_err("%s%s\n", header, msg + ktime_msg_len); - break; - case MSG_WARN: - pr_warn("%s%s\n", header, msg + ktime_msg_len); - break; - case MSG_INFO: - case MSG_TIMEOFF: - pr_info("%s%s\n", header, msg + ktime_msg_len); - break; - case MSG_DEBUG: - pr_debug("%s%s\n", header, msg + ktime_msg_len); - break; - case MSG_BLOB: - pr_crit("%s\n", msg + ktime_msg_len); - break; - } -} - -void blob(const char *title, const char *buffer, const size_t bufLen, const int lineSize) -{ - size_t i = 0, line; - size_t j = 0, len = bufLen; - int offset = 0; - char c, stringToPrint[MAX_DATA_LEN]; - - defex_log_blob("%s", title); - - do { - line = (len > lineSize)?lineSize:len; - offset = 0; - offset += snprintf(stringToPrint + offset, MAX_DATA_LEN - offset, "| 0x%08lX | ", i); - - for (j = 0; j < line; j++) - offset += snprintf(stringToPrint + offset, MAX_DATA_LEN - offset, "%02X ", - (unsigned char)buffer[i + j]); - if (line < lineSize) { - for (j = 0; j < lineSize - line; j++) - offset += snprintf(stringToPrint + offset, MAX_DATA_LEN - offset, " "); - } - offset += snprintf(stringToPrint + offset, MAX_DATA_LEN - offset, "| "); - - for (j = 0; j < line; j++) { - c = buffer[i + j]; - c = (c < 0x20) || (c >= 0x7F)?'.':c; - offset += snprintf(stringToPrint + offset, MAX_DATA_LEN - offset, "%c", c); - } - if (line < lineSize) { - for (j = 0; j < lineSize - line; j++) - offset += snprintf(stringToPrint + offset, MAX_DATA_LEN - offset, " "); - } - - offset += snprintf(stringToPrint + offset, MAX_DATA_LEN - offset, " |"); - defex_log_blob("%s", stringToPrint); - memset(stringToPrint, 0, MAX_DATA_LEN); - i += line; - len -= line; - } while (len); -} - -__visible_for_testing int set_user(struct cred *new_cred) -{ - struct user_struct *new_user; - - new_user = alloc_uid(new_cred->uid); - if (!new_user) - return -EAGAIN; - - free_uid(new_cred->user); - new_cred->user = new_user; - return 0; -} - -/* - * target_id = (0 - set all uids, 1 - set fsuid, 2 - set all gids) - */ -__visible_for_testing int set_cred(int target_id, int new_val) -{ - struct user_namespace *ns = current_user_ns(); - const struct cred *old_cred; - struct cred *new_cred; - kuid_t kuid; - kgid_t kgid; - uid_t new_uid; - gid_t new_gid; - - new_cred = prepare_creds(); - if (!new_cred) - return -ENOMEM; - old_cred = current_cred(); - - switch (target_id) { - case 0: - new_uid = new_val; - kuid = make_kuid(ns, new_uid); - if (!uid_valid(kuid)) - goto do_abort; - new_cred->uid = new_cred->euid = new_cred->suid = new_cred->fsuid = kuid; - if (!uid_eq(new_cred->uid, old_cred->uid)) { - if (set_user(new_cred) < 0) - goto do_abort; - } - break; - - case 1: - new_uid = new_val; - kuid = make_kuid(ns, new_uid); - if (!uid_valid(kuid)) - goto do_abort; - new_cred->fsuid = kuid; - break; - - case 2: - new_gid = new_val; - kgid = make_kgid(ns, new_gid); - if (!gid_valid(kgid)) - goto do_abort; - new_cred->gid = new_cred->egid = new_cred->sgid = new_cred->fsgid = kgid; - break; - } - return commit_creds(new_cred); - -do_abort: - abort_creds(new_cred); - return -EPERM; -} - -__visible_for_testing ssize_t debug_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) -{ - struct task_struct *p = current; - int i, l, new_val = -1; - int ret = 0; - - static const char *prefix[] = { - "uid=", - "fsuid=", - "gid=", - "pe_status=", - "im_status=", - "sp_status=", - "int_status=", - "get_log" - }; - - if (!buf || !p) - return -EINVAL; - - for (i = 0; i < sizeof(prefix) / sizeof(prefix[0]); i++) { - l = strlen(prefix[i]); - if (!strncmp(buf, prefix[i], l)) - break; - } - if (i == (sizeof(prefix) / sizeof(prefix[0]))) - return -EINVAL; - - switch (i) { - case DBG_SETUID ... DBG_SETGID: - ret = kstrtoint(buf + l, 10, &new_val); - if (ret != 0) - return -EINVAL; - ret = set_cred(i, new_val); - break; - case DBG_SET_PE_STATUS: -#ifdef DEFEX_PED_ENABLE - privesc_status_store(buf + l); -#endif /* DEFEX_PED_ENABLE */ - break; - case DBG_SET_IM_STATUS: -#ifdef DEFEX_IMMUTABLE_ENABLE - immutable_status_store(buf + l); -#endif /* DEFEX_IMMUTABLE_ENABLE */ - break; - case DBG_SET_SP_STATUS: -#ifdef DEFEX_SAFEPLACE_ENABLE - safeplace_status_store(buf + l); -#endif /* DEFEX_SAFEPLACE_ENABLE */ - break; - case DBG_SET_INT_STATUS: -#ifdef DEFEX_INTEGRITY_ENABLE - integrity_status_store(buf + l); -#endif /* DEFEX_INTEGRITY_ENABLE */ - break; - case DBG_GET_LOG: - break; - default: - break; - } - - last_cmd = i; - return (!ret)?count:ret; -} - -__visible_for_testing ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) -{ - struct task_struct *p = current; - int res = 0; -#ifdef DEFEX_LOG_BUFFER_ENABLE - int buff_size, msg_len; -#endif /* DEFEX_LOG_BUFFER_ENABLE */ - - if (!p) - return 0; - - switch (last_cmd) { - case DBG_SETUID ... DBG_SETGID: - res = snprintf(buf, MAX_LEN + 1, "pid=%d\nuid=%d\ngid=%d\neuid=%d\negid=%d\n", - p->pid, - uid_get_value(p->cred->uid), - uid_get_value(p->cred->gid), - uid_get_value(p->cred->euid), - uid_get_value(p->cred->egid)); - break; - case DBG_GET_LOG: -#ifdef DEFEX_LOG_BUFFER_ENABLE - buff_size = PAGE_SIZE; - do { - msg_len = log_buffer_get(&buf[res], buff_size); - res += msg_len; - buff_size -= msg_len; - } while (msg_len && buff_size >= MAX_LEN); - if (!msg_len) - res += snprintf(&buf[res], buff_size, "=== EOF ===\n"); - else - res += snprintf(&buf[res], buff_size, "=== %lu bytes left ===\n", - (unsigned long)(log_buf_in_index - log_buf_out_index) & DEFEX_LOG_BUF_MASK); -#else - res = snprintf(buf, MAX_LEN + 1, "Log buffer disabled...\n"); -#endif /* DEFEX_LOG_BUFFER_ENABLE */ - break; - } - - return res; -} - -__visible_for_testing struct kobj_attribute debug_attribute = __ATTR(debug, 0660, debug_show, debug_store); - -int defex_create_debug(struct kset *defex_kset) -{ - int retval; - -#ifdef DEFEX_LOG_BUFFER_ENABLE - retval = log_buf_init(); - if (retval) - defex_log_err("Log buffer init failed. Log output only via /dev/kmsg"); - else - defex_log_info("Logging started..."); -#endif /* DEFEX_LOG_BUFFER_ENABLE */ - last_cmd = DBG_GET_LOG; - - retval = sysfs_create_file(&defex_kset->kobj, &debug_attribute.attr); - if (retval) - return DEFEX_NOK; - - kobject_uevent(&defex_kset->kobj, KOBJ_ADD); - return DEFEX_OK; -} diff --git a/security/samsung/defex_lsm/debug/defex_rules_show.c b/security/samsung/defex_lsm/debug/defex_rules_show.c deleted file mode 100755 index 3c2aaceac..000000000 --- a/security/samsung/defex_lsm/debug/defex_rules_show.c +++ /dev/null @@ -1,174 +0,0 @@ -#include - -#include "include/defex_debug.h" -#include "include/defex_rules.h" - -const char header_name[16] = {"DEFEX_RULES_FILE"}; -struct rule_item_struct *defex_packed_rules; -static char work_path[512]; -static int packfiles_size, global_data_size; - - -const struct feature_match_entry feature_match[] = { - {"feature_safeplace_path", feature_safeplace_path}, - {"feature_ped_exception", feature_ped_exception}, - {"feature_immutable_path_open", feature_immutable_path_open}, - {"feature_immutable_path_write", feature_immutable_path_write}, - {"feature_immutable_src_exception", feature_immutable_src_exception}, - {"feature_umhbin_path", feature_umhbin_path}, - {"feature_integrity_check", feature_integrity_check}, -}; - -const int feature_match_size = ARRAY_SIZE(feature_match); - -static void feature_to_str(char *str, unsigned short flags) -{ - int i; - - str[0] = 0; - for (i = 0; i < feature_match_size; i++) - if (flags & feature_match[i].feature_num) { - if (str[0]) - strcat(str, ", "); - strcat(str, feature_match[i].feature_name); - } - if (flags & feature_for_recovery) { - if (str[0]) - strcat(str, ", "); - strcat(str, "feature_for_recovery"); - } -} - -static int check_array_size(struct rule_item_struct *ptr) -{ - unsigned long offset = (unsigned long)ptr - (unsigned long)defex_packed_rules; - int min_size = (global_data_size < packfiles_size)?global_data_size:packfiles_size; - - offset += sizeof(struct rule_item_struct); - - if (offset > min_size) - return 1; - - offset += ptr->size; - if (offset > min_size) - return 2; - return 0; -} - -static int parse_items(struct rule_item_struct *base, int path_length, int level) -{ - int l, err, ret = 0; - unsigned int offset; - struct rule_item_struct *child_item; - static char feature_list[128]; - - if (level > 8) { - defex_log_timeoff("Level is too deep"); - return -1; - - } - if (path_length > (sizeof(work_path) - 128)) { - defex_log_timeoff("Work path is too long"); - return -1; - } - while (base) { - err = check_array_size(base); - if (err) { - defex_log_timeoff("%s/ - out of array bounds", work_path); - return -1; - } - l = base->size; - if (!l) { - defex_log_timeoff("WARNING: Name field is incorrect, structure error!"); - return -1; - - } - - memcpy(work_path + path_length, base->name, l); - l += path_length; - work_path[l] = 0; - offset = base->next_level; - if (offset) { - if (base->feature_type & feature_is_file) { - defex_log_timeoff("%s - is a file, but has children, structure error!", work_path); - ret = -1; - } else if (base->feature_type != 0) { - feature_to_str(feature_list, base->feature_type); - defex_log_blob("%s%c - %s", work_path, - ((base->feature_type & feature_is_file)?' ':'/'), feature_list); - } - child_item = GET_ITEM_PTR(offset, defex_packed_rules); - work_path[l++] = '/'; - work_path[l] = 0; - err = check_array_size(child_item); - if (!err) { - err = parse_items(child_item, l, level + 1); - if (err != 0) - return err; - } else { - defex_log_timeoff("%s/ - out of array bounds", work_path); - ret = -1; - } - } else { - feature_to_str(feature_list, base->feature_type); - defex_log_blob("%s%c - %s", work_path, - ((base->feature_type & feature_is_file)?' ':'/'), feature_list); - } - work_path[path_length] = 0; - offset = base->next_file; - base = (offset)?GET_ITEM_PTR(offset, defex_packed_rules):NULL; - } - return ret; -} - -int defex_show_structure(void *packed_rules, int rules_size) -{ - struct rule_item_struct *base; - int res, offset; - int first_item_size = sizeof(struct rule_item_struct) + sizeof(header_name); - - defex_packed_rules = (struct rule_item_struct *)packed_rules; - - work_path[0] = '/'; - work_path[1] = 0; - - packfiles_size = rules_size; - global_data_size = defex_packed_rules->data_size; - - defex_log_timeoff("Rules binary size: %d", packfiles_size); - defex_log_timeoff("Rules internal data size: %d", global_data_size); - - if (global_data_size > packfiles_size) - defex_log_timeoff("WARNING: Internal size is bigger than binary size, possible structure error!"); - - if (packfiles_size < first_item_size) { - defex_log_timeoff("ERROR: Too short binary size, can't continue!"); - return -1; - } - - if (global_data_size < first_item_size) - defex_log_timeoff("WARNING: Too short data size, possible structure error!"); - - if (defex_packed_rules->size != sizeof(header_name)) - defex_log_timeoff("WARNING: incorrect size field (%d), possible structure error!", - (int)defex_packed_rules->size); - - if (memcmp(header_name, defex_packed_rules->name, sizeof(header_name)) != 0) - defex_log_timeoff("WARNING: incorrect name field, possible structure error!"); - - defex_log_timeoff("File List:\n"); - offset = defex_packed_rules->next_level; - base = (offset)?GET_ITEM_PTR(offset, defex_packed_rules):NULL; - if (!base) { - defex_log_timeoff("- empty list\n"); - return 0; - } else if (check_array_size(base)) { - defex_log_timeoff("- list is out of array bounds!"); - return -1; - } - - res = parse_items(base, 1, 1); - defex_log_timeoff("== End of File List =="); - return res; -} - diff --git a/security/samsung/defex_lsm/defex_packed_rules.bin b/security/samsung/defex_lsm/defex_packed_rules.bin deleted file mode 100755 index 969fa8b3c..000000000 Binary files a/security/samsung/defex_lsm/defex_packed_rules.bin and /dev/null differ diff --git a/security/samsung/defex_lsm/defex_rules.c b/security/samsung/defex_lsm/defex_rules.c deleted file mode 100755 index dd36911f5..000000000 --- a/security/samsung/defex_lsm/defex_rules.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#if 0 - /* Rules start after this line */ - - {feature_ped_exception,"/system/bin/run-as"}, /* DEFAULT */ - {feature_ped_exception,"/system/bin/dumpstate"}, /* DEFAULT */ - {feature_safeplace_path,"/init"}, - {feature_safeplace_path,"/system/bin/init"}, - {feature_safeplace_path,"/system/bin/app_process32"}, - {feature_safeplace_path,"/system/bin/app_process64"}, - {feature_safeplace_path,"/system/bin/blkid"}, - {feature_safeplace_path,"/system/bin/clatd"}, - {feature_safeplace_path,"/system/bin/cmd"}, - {feature_safeplace_path,"/system/bin/corehelper.sh"}, - {feature_safeplace_path,"/system/bin/crash_dump32"}, - {feature_safeplace_path,"/system/bin/crash_dump64"}, - {feature_safeplace_path,"/system/bin/debuggerd"}, - {feature_safeplace_path,"/system/bin/dnsmasq"}, - {feature_safeplace_path,"/system/bin/dsms"}, - {feature_safeplace_path,"/system/bin/dumpstate"}, - {feature_safeplace_path,"/system/bin/fsck.vfat"}, - {feature_safeplace_path,"/system/bin/fsck.exfat"}, - {feature_safeplace_path,"/system/bin/gatekeeperd"}, - {feature_safeplace_path,"/system/bin/healthd"}, - {feature_safeplace_path,"/system/bin/installd"}, - {feature_safeplace_path,"/system/bin/iod"}, - {feature_safeplace_path,"/system/bin/ip"}, - {feature_safeplace_path,"/system/bin/iptables"}, - {feature_safeplace_path,"/system/bin/iptables-restore"}, - {feature_safeplace_path,"/system/bin/ip6tables"}, - {feature_safeplace_path,"/system/bin/ip6tables-restore"}, - {feature_safeplace_path,"/system/bin/lmkd"}, - {feature_safeplace_path,"/system/bin/lshal"}, - {feature_safeplace_path,"/system/bin/mdf_fota"}, - {feature_safeplace_path,"/system/bin/mkfs.vfat"}, - {feature_safeplace_path,"/system/bin/mkfs.exfat"}, - {feature_safeplace_path,"/system/bin/netd"}, - {feature_safeplace_path,"/system/bin/nst"}, - {feature_safeplace_path,"/system/bin/perfmond"}, - {feature_safeplace_path,"/system/bin/perfprofd"}, - {feature_safeplace_path,"/system/bin/sgdisk"}, - {feature_safeplace_path,"/system/bin/sh"}, - {feature_safeplace_path,"/system/bin/ss"}, - {feature_safeplace_path,"/system/bin/storaged"}, - {feature_safeplace_path,"/system/bin/tc"}, - {feature_safeplace_path,"/system/bin/uncrypt"}, - {feature_safeplace_path,"/system/bin/vold"}, - {feature_safeplace_path,"/system/bin/webview_zygote32"}, - {feature_safeplace_path,"/system/bin/grep"}, - {feature_safeplace_path,"/system/bin/e2fsck"}, - {feature_safeplace_path,"/system/bin/scs"}, - {feature_safeplace_path,"/system/bin/vdc"}, - {feature_safeplace_path,"/system/bin/vaultkeeperd"}, - {feature_safeplace_path,"/system/bin/prepare_param.sh"}, - {feature_safeplace_path,"/system/bin/smdexe"}, - {feature_safeplace_path,"/system/bin/diagexe"}, - {feature_safeplace_path,"/system/bin/ddexe"}, - {feature_safeplace_path,"/system/bin/connfwexe"}, - {feature_safeplace_path,"/system/bin/at_distributor"}, - {feature_safeplace_path,"/system/bin/sdcard"}, - {feature_safeplace_path,"/system/bin/resetreason"}, - {feature_safeplace_path,"/system/bin/lpm"}, - {feature_safeplace_path,"/system/bin/resize2fs"}, - {feature_safeplace_path,"/system/bin/tune2fs"}, - {feature_safeplace_path,"/system/bin/patchoat"}, - {feature_safeplace_path,"/system/bin/knox_changer"}, - {feature_safeplace_path,"/system/bin/knox_changer_recovery"}, - {feature_safeplace_path,"/sbin/sswap"}, - {feature_safeplace_path,"/sbin/cbd"}, - {feature_safeplace_path,"/sbin/adbd"}, - {feature_safeplace_path,"/sbin/recovery"}, - {feature_safeplace_path,"/sbin/mke2fs_static"}, - {feature_safeplace_path,"/vendor/bin/hw/wpa_supplicant"}, - {feature_safeplace_path,"/vendor/bin/hw/macloader"}, - {feature_safeplace_path,"/vendor/bin/hw/mfgloader"}, - {feature_safeplace_path,"/sbin/dm_verity_hash"}, - {feature_safeplace_path,"/sbin/dm_verity_signature_checker"}, - {feature_safeplace_path,"/vendor/bin/qseecomd"}, - {feature_safeplace_path,"/system/bin/vold_prepare_subdirs"}, - {feature_safeplace_path,"/vendor/bin/init.qcom.early_boot.sh"}, - {feature_safeplace_path,"/vendor/bin/toybox_vendor"}, - {feature_safeplace_path,"/vendor/bin/toolbox"}, - {feature_safeplace_path,"/vendor/bin/hw/android.hardware.usb@1.1-service.wahoo"}, - {feature_safeplace_path,"/vendor/bin/hw/vendor.qti.hardware.iop@2.0-service"}, - {feature_safeplace_path,"/vendor/bin/hw/vendor.qti.hardware.perf@1.0-service"}, - {feature_safeplace_path,"/vendor/bin/init.qcom.class_core.sh"}, - {feature_safeplace_path,"/vendor/bin/irsc_util"}, - {feature_safeplace_path,"/vendor/bin/rmt_storage"}, - {feature_safeplace_path,"/system/bin/toybox"}, - {feature_safeplace_path,"/vendor/bin/init.qcom.usb.sh"}, - {feature_safeplace_path,"/vendor/bin/tftp_server"}, - {feature_safeplace_path,"/vendor/bin/init.qcom.sensors.sh"}, - {feature_safeplace_path,"/system/bin/insthk"}, - {feature_safeplace_path,"/vendor/bin/init.class_main.sh"}, - {feature_safeplace_path,"/vendor/bin/time_daemon"}, - {feature_safeplace_path,"/vendor/bin/thermal-engine"}, - {feature_safeplace_path,"/system/bin/sec_diag_uart_log"}, - {feature_safeplace_path,"/vendor/bin/init.qcom.sh"}, - {feature_safeplace_path,"/system/bin/usbd"}, - {feature_safeplace_path,"/vendor/bin/init.qcom.post_boot.sh"}, - {feature_safeplace_path,"/system/bin/adbd"}, - {feature_safeplace_path,"/system/bin/atrace"}, - {feature_safeplace_path,"/system/bin/fsdbg"}, - {feature_safeplace_path,"/system/bin/dumpsys"}, - {feature_safeplace_path,"/system/bin/logcat"}, - {feature_safeplace_path,"/system/bin/toolbox"}, - {feature_safeplace_path,"/system/bin/mke2fs"}, - {feature_safeplace_path,"/vendor/bin/cbd"}, - {feature_safeplace_path,"/vendor/bin/adsprpcd"}, - {feature_safeplace_path,"/sbin/e2fsdroid_static"}, - {feature_safeplace_path,"/system/bin/e2fsdroid"}, - {feature_safeplace_path,"/system/bin/fsck.f2fs"}, - {feature_safeplace_path,"/system/bin/make_f2fs"}, - {feature_safeplace_path,"/system/bin/sload_f2fs"}, - {feature_safeplace_path,"/system/bin/bpfloader"}, - {feature_safeplace_path,"/system/bin/wait_for_keymaster"}, - {feature_safeplace_path,"/system/bin/secdiscard"}, - {feature_safeplace_path,"/system/bin/idledefrag"}, - {feature_safeplace_path,"/vendor/bin/init.mdm.sh"}, - {feature_safeplace_path,"/vendor/bin/mdm_helper"}, - {feature_safeplace_path,"/vendor/bin/ks"}, - {feature_safeplace_path,"/vendor/bin/sh"}, - {feature_safeplace_path,"/system/bin/e4defrag"}, - {feature_safeplace_path,"/sbin/dm_verity_tz_cmd"}, - {feature_safeplace_path,"/sbin/mcDriverDaemon_static"}, - {feature_safeplace_path,"/sbin/qseecomfsd"}, - {feature_safeplace_path,"/sbin/tzdaemon_recovery"}, - {feature_safeplace_path,"/vendor/bin/hvdcp_opti"}, - {feature_safeplace_path,"/sbin/mkfs.f2fs"}, - {feature_safeplace_path,"/sbin/sload.f2fs"}, - {feature_safeplace_path,"/system/bin/secilc"}, - {feature_safeplace_path,"/system/bin/apexd"}, - {feature_safeplace_path,"/system/bin/art_apex_boot_integrity"}, - {feature_safeplace_path,"/system/bin/gsid"}, - {feature_safeplace_path,"/system/bin/idmap2"}, - {feature_safeplace_path,"/system/bin/charger"}, - {feature_safeplace_path,"/system/bin/recovery"}, - {feature_safeplace_path,"/system/bin/watchdogd"}, - {feature_safeplace_path,"/vendor/bin/hw/vendor.qti.hardware.perf@2.0-service"}, - {feature_safeplace_path,"/system/bin/netutils-wrapper-1.0"}, - {feature_safeplace_path,"/system/bin/bugreport"}, - {feature_safeplace_path,"/system/bin/minadbd"}, - {feature_safeplace_path,"/system/bin/migrate_legacy_obb_data.sh"}, - {feature_safeplace_path,"/vendor/bin/shsusrd"}, - {feature_safeplace_path,"/system/bin/defrag_f2fs"}, - {feature_safeplace_path,"/system/bin/fastbootd"}, - {feature_safeplace_path,"/vendor/bin/hw/vendor.qti.hardware.perf@2.1-service"}, - {feature_safeplace_path,"/vendor/bin/hw/vendor.qti.hardware.perf@2.2-service"}, - {feature_safeplace_path,"/vendor/bin/grep"}, - {feature_safeplace_path,"/vendor/bin/memlogd"}, - {feature_safeplace_path,"/vendor/bin/init.insmod.sh"}, - {feature_safeplace_path,"/vendor/bin/dsmsca"}, - {feature_safeplace_path,"/vendor/bin/hw/android.hardware.usb@1.3-service.coral"}, - {feature_safeplace_path,"/vendor/bin/hw/vendor.qti.hardware.perf-hal-service"}, - {feature_safeplace_path,"/vendor/bin/iod"}, - {feature_safeplace_path,"/vendor/bin/hqread"}, - {feature_safeplace_path,"/system/bin/hqcpsnbin"}, - {feature_safeplace_path,"/system/bin/rdxd"}, - {feature_safeplace_path,"/system/system_ext/bin/dpmd"}, - {feature_safeplace_path,"/vendor/bin/init.qti.dcvs.sh"}, - {feature_safeplace_path,"/vendor/bin/vendor_modprobe.sh"}, - {feature_safeplace_path,"/vendor/bin/init.qti.qcv.sh"}, - {feature_safeplace_path,"/vendor/bin/init.qcom.crashdata.sh"}, - {feature_safeplace_path,"/vendor/bin/energy-awareness"}, - {feature_safeplace_path,"/vendor/bin/qcom-system-daemon"}, - {feature_safeplace_path,"/vendor/bin/init.qti.kernel.sh"}, - {feature_safeplace_path,"/vendor/bin/init.kernel.post_boot.sh"}, - {feature_safeplace_path,"/vendor/bin/init.kernel.post_boot-lahaina.sh"}, - {feature_safeplace_path,"/vendor/bin/init.qti.keymaster.sh"}, - {feature_safeplace_path,"/vendor/bin/init.qti.early_init.sh"}, - {feature_safeplace_path,"/vendor/bin/msm_irqbalance"}, - {feature_safeplace_path,"/vendor/bin/poweropt-service"}, - {feature_safeplace_path,"/vendor/bin/hw/vendor.qti.hardware.limits@1.0-service"}, - {feature_safeplace_path,"/vendor/bin/thermal_manager"}, - {feature_safeplace_path,"/system/bin/linkerconfig"}, - {feature_safeplace_path,"/system/bin/snapshotctl"}, - {feature_safeplace_path,"/system/bin/boringssl_self_test32"}, - {feature_safeplace_path,"/system/bin/boringssl_self_test64"}, - {feature_safeplace_path,"/vendor/bin/boringssl_self_test32"}, - {feature_safeplace_path,"/vendor/bin/boringssl_self_test64"}, - {feature_safeplace_path,"/apex/com.android.adbd/bin/adbd"}, - {feature_safeplace_path,"/apex/com.android.sdkext/bin/derive_sdk"}, - {feature_safeplace_path,"/apex/com.android.conscrypt/bin/boringssl_self_test32"}, - {feature_safeplace_path,"/apex/com.android.conscrypt/bin/boringssl_self_test64"}, - {feature_safeplace_path,"/system/bin/applypatch"}, - {feature_safeplace_path,"/vendor/bin/applypatch"}, - {feature_safeplace_path,"/system/bin/clean_scratch_files"}, - {feature_safeplace_path,"/system/bin/fsverity"}, - {feature_safeplace_path,"/system/bin/fsverity_init"}, - {feature_safeplace_path,"/system/xbin/librank"}, - {feature_safeplace_path,"/system/xbin/procrank"}, - {feature_safeplace_path,"/system/xbin/showmap"}, - {feature_safeplace_path,"/system/bin/librank"}, - {feature_safeplace_path,"/system/bin/procrank"}, - {feature_safeplace_path,"/system/bin/showmap"}, - {feature_safeplace_path,"/product/bin/dmabuf_dump"}, - {feature_safeplace_path,"/apex/com.android.runtime/bin/spqr"}, - {feature_safeplace_path,"/system/bin/perfetto"}, - {feature_safeplace_path,"/system/bin/update_verifier"}, - {feature_safeplace_path,"/system/bin/bootstrap/linkerconfig"}, - {feature_safeplace_path,"/apex/com.android.runtime/bin/linkerconfig"}, - {feature_safeplace_path,"/system/bin/otapreopt_slot"}, - {feature_safeplace_path,"/apex/com.android.art/bin/dex2oat32"}, - {feature_safeplace_path,"/apex/com.android.art/bin/dex2oat64"}, - {feature_safeplace_path,"/system/bin/incident"}, - {feature_safeplace_path,"/tmp/update_binary;updater_intermediates/updater;obj/EXECUTABLES"}, - {feature_safeplace_path,"/tmp/update-binary"}, - {feature_safeplace_path,"/system/bin/install-recovery.sh"}, /* DEFAULT */ - {feature_safeplace_path,"/vendor/bin/install-recovery.sh"}, /* DEFAULT */ - {feature_safeplace_path,"/system/bin/odsign"}, /* DEFAULT */ - {feature_safeplace_path,"/apex/com.android.art/bin/odrefresh"}, /* DEFAULT */ - {feature_immutable_path_write,"/system/"}, /* DEFAULT */ - {feature_immutable_path_write,"/vendor/"}, /* DEFAULT */ - {feature_immutable_path_open,"/system/bin/"}, /* DEFAULT */ - {feature_immutable_path_open,"/vendor/bin/"}, /* DEFAULT */ - {feature_immutable_src_exception,"/system/bin/icd"}, - {feature_immutable_src_exception,"/system/bin/iof"}, - {feature_immutable_src_exception,"/system/bin/sh"}, - {feature_immutable_src_exception,"/system/bin/app_process32"}, - {feature_immutable_src_exception,"/system/bin/app_process64"}, - {feature_immutable_src_exception,"/system/bin/crash_dump32"}, - {feature_immutable_src_exception,"/system/bin/crash_dump64"}, - {feature_immutable_src_exception,"/system/bin/mediaextractor"}, - {feature_immutable_src_exception,"/system/bin/surfaceflinger"}, - {feature_immutable_src_exception,"/vendor/bin/sh"}, - {feature_immutable_src_exception,"/vendor/bin/hw/android.hardware.media.omx@1.0-service"}, - {feature_immutable_src_exception,"/vendor/bin/snap_utility_32"}, - {feature_immutable_src_exception,"/vendor/bin/snap_utility_64"}, - {feature_immutable_src_exception,"/vendor/bin/icd_vendor"}, - {feature_immutable_src_exception,"/vendor/bin/iof_vendor"}, - {feature_immutable_src_exception,"/init"}, - {feature_immutable_src_exception,"/system/bin/init"}, - {feature_immutable_src_exception,"/system/bin/lshal"}, - {feature_integrity_check,"/vendor/bin/hw/android.hardware.gatekeeper@1.0-service"}, - {feature_integrity_check,"/vendor/bin/hw/android.hardware.keymaster@4.0-service"}, - {feature_integrity_check,"/vendor/bin/hw/android.hardware.security.keymint-service"}, - {feature_integrity_check,"/vendor/bin/hw/vendor.samsung.hardware.tlc.kg@1.0-service"}, - {feature_integrity_check,"/vendor/bin/vendor.samsung.hardware.security.wsm@1.0-service"}, - {feature_integrity_check,"/vendor/bin/vaultkeeperd"}, - {feature_integrity_check,"/vendor/bin/hw/vendor.samsung.hardware.tlc.kg@1.1-service"}, - /* Rules will be added here */ - /* Never modify the above line. Rules will be added for buildtime */ -#endif /* if 0 */ diff --git a/security/samsung/defex_lsm/feature_immutable/defex_immutable.c b/security/samsung/defex_lsm/feature_immutable/defex_immutable.c deleted file mode 100755 index d39ed4dba..000000000 --- a/security/samsung/defex_lsm/feature_immutable/defex_immutable.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include "include/defex_internal.h" - -#ifdef DEFEX_PERMISSIVE_IM -unsigned char global_immutable_status = 2; -#else -unsigned char global_immutable_status = 1; -#endif /* DEFEX_PERMISSIVE_IM */ - -int immutable_status_store(const char *status_str) -{ - int ret; - unsigned int status; - - if (!status_str) - return -EINVAL; - - ret = kstrtouint(status_str, 10, &status); - if (ret != 0 || status > 2) - return -EINVAL; - - global_immutable_status = status; - return 0; -} diff --git a/security/samsung/defex_lsm/feature_privilege_escalation_detection/defex_priv.c b/security/samsung/defex_lsm/feature_privilege_escalation_detection/defex_priv.c deleted file mode 100755 index dc64b2267..000000000 --- a/security/samsung/defex_lsm/feature_privilege_escalation_detection/defex_priv.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include "include/defex_internal.h" - -#ifdef DEFEX_PERMISSIVE_PED -unsigned char global_privesc_status = 2; -#else -unsigned char global_privesc_status = 1; -#endif /* DEFEX_PERMISSIVE_PED */ - -int privesc_status_store(const char *status_str) -{ - int ret; - unsigned int status; - - if (!status_str) - return -EINVAL; - - ret = kstrtouint(status_str, 10, &status); - if (ret != 0 || status > 2) - return -EINVAL; - global_privesc_status = status; - - return 0; -} - diff --git a/security/samsung/defex_lsm/feature_safeplace/defex_integrity.c b/security/samsung/defex_lsm/feature_safeplace/defex_integrity.c deleted file mode 100755 index aaf3ba11f..000000000 --- a/security/samsung/defex_lsm/feature_safeplace/defex_integrity.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include "include/defex_internal.h" - -#ifdef DEFEX_PERMISSIVE_INT -unsigned char global_integrity_status = 2; -#else -unsigned char global_integrity_status = 1; -#endif /* DEFEX_PERMISSIVE_INT */ - -int integrity_status_store(const char *status_str) -{ - int ret; - unsigned int status; - - if (!status_str) - return -EINVAL; - - ret = kstrtouint(status_str, 10, &status); - if (ret != 0 || status > 2) - return -EINVAL; - - global_integrity_status = status; - - return 0; -} diff --git a/security/samsung/defex_lsm/feature_safeplace/defex_safeplace.c b/security/samsung/defex_lsm/feature_safeplace/defex_safeplace.c deleted file mode 100755 index bed0e288a..000000000 --- a/security/samsung/defex_lsm/feature_safeplace/defex_safeplace.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include "include/defex_internal.h" - -#ifdef DEFEX_PERMISSIVE_SP -unsigned char global_safeplace_status = 2; -#else -unsigned char global_safeplace_status = 1; -#endif /* DEFEX_PERMISSIVE_SP */ - -int safeplace_status_store(const char *status_str) -{ - int ret; - unsigned int status; - - if (!status_str) - return -EINVAL; - - ret = kstrtouint(status_str, 10, &status); - if (ret != 0 || status > 2) - return -EINVAL; - - global_safeplace_status = status; - - return 0; -} diff --git a/security/samsung/defex_lsm/feature_trusted_map/defex_trusted_map.c b/security/samsung/defex_lsm/feature_trusted_map/defex_trusted_map.c deleted file mode 100755 index c59d28eaf..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/defex_trusted_map.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include "include/defex_internal.h" - -unsigned char global_trusted_map_status = DEFEX_TM_ENFORCING_MODE -#ifdef DEFEX_PERMISSIVE_TM - | DEFEX_TM_PERMISSIVE_MODE -#endif - | DEFEX_TM_DEBUG_VIOLATIONS - ; diff --git a/security/samsung/defex_lsm/feature_trusted_map/dtm.c b/security/samsung/defex_lsm/feature_trusted_map/dtm.c deleted file mode 100755 index cd6cd09e6..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/dtm.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -#include -#endif - -#include "include/dtm.h" -#include "include/dtm_engine.h" -#include "include/dtm_log.h" -#include "include/dtm_utils.h" - -/* From fs/exec.c: SM8150_Q, SM8250_Q, SM8250_R, exynos9820, exynos9830 */ -struct user_arg_ptr { -#ifdef CONFIG_COMPAT - bool is_compat; -#endif - union { - const char __user *const __user *native; -#ifdef CONFIG_COMPAT - const compat_uptr_t __user *compat; -#endif - } ptr; -}; - -/* From fs/exec.c: SM8150_Q, SM8250_Q, SM8250_R, exynos9820, exynos9830 */ -static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) -{ - const char __user *native; - -#ifdef CONFIG_COMPAT - if (unlikely(argv.is_compat)) { - compat_uptr_t compat; - - if (get_user(compat, argv.ptr.compat + nr)) - return ERR_PTR(-EFAULT); - - return compat_ptr(compat); - } -#endif - - if (get_user(native, argv.ptr.native + nr)) - return ERR_PTR(-EFAULT); - - return native; -} - -static void dtm_kfree_args(struct dtm_context *context) -{ - const char **argv; - int arg, to_free; - - if (unlikely(!is_dtm_context_valid(context))) - return; - argv = context->callee_argv; - arg = min_t(int, context->callee_argc, DTM_MAX_ARGC); - to_free = context->callee_copied_argc; - context->callee_copied_argc = 0; - while (--arg >= 0 && to_free > 0) { - if (!argv[arg]) - continue; - kfree(argv[arg]); - to_free--; - } -} - -/* - * Gets call argument value, copying from user if needed. - */ -const char *dtm_get_callee_arg(struct dtm_context *context, int arg_index) -{ - struct user_arg_ptr argv; - const char __user *user_str; - char *copy; - int max_argc, arg_len, copy_len; - - if (unlikely(!is_dtm_context_valid(context))) - return NULL; - max_argc = min_t(int, context->callee_argc, DTM_MAX_ARGC); - if (unlikely((arg_index < 0) || (arg_index >= max_argc))) - return NULL; - if (context->callee_argv[arg_index]) - return context->callee_argv[arg_index]; - - argv = *(struct user_arg_ptr *)context->callee_argv_ref; - user_str = get_user_arg_ptr(argv, arg_index); - if (IS_ERR(user_str)) - return NULL; - - arg_len = strnlen_user(user_str, MAX_ARG_STRLEN); - if (unlikely(!arg_len)) - return NULL; - - copy_len = min_t(int, arg_len, DTM_MAX_ARG_STRLEN); - copy = kzalloc(copy_len, GFP_KERNEL); - if (unlikely(!copy)) - return NULL; - - if (unlikely(copy_from_user(copy, user_str, copy_len))) - goto out_free_copy; - copy[copy_len - 1] = '\0'; - - context->callee_argv[arg_index] = copy; - context->callee_copied_argc++; - context->callee_copied_args_len += copy_len; - context->callee_total_args_len += arg_len; - return copy; - -out_free_copy: - kfree(copy); - return NULL; -} - -/* - * Initializes dtm context data structure. - */ -__visible_for_testing bool dtm_context_get(struct dtm_context *context, - struct defex_context *defex_context, - int callee_argc, - void *callee_argv_ref) -{ - memset(context, 0, sizeof(*context)); - context->defex_context = defex_context; - context->callee_argc = callee_argc; - context->callee_argv_ref = callee_argv_ref; - return true; -} - -/* - * Releases resources associated to dtm context. - */ -__visible_for_testing void dtm_context_put(struct dtm_context *context) -{ - dtm_kfree_args(context); -} - -/* - * Gets program name for current call. - */ -const char *dtm_get_program_name(struct dtm_context *context) -{ - if (unlikely(!is_dtm_context_valid(context))) - return NULL; - if (context->program_name) - return context->program_name; - context->program_name = dtm_get_callee_arg(context, 0); - if (context->program_name == NULL) - context->program_name = DTM_UNKNOWN; - return context->program_name; -} - -/** - * Gets stdin mode bit for current call. - */ -int dtm_get_stdin_mode_bit(struct dtm_context *context) -{ - if (unlikely(!context)) - return DTM_FD_MODE_ERROR; - if (!context->stdin_mode_bit) - context->stdin_mode_bit = dtm_get_fd_mode_bit(0); - return context->stdin_mode_bit; -} - -/** - * Gets stdin mode for current call. - */ -const char *dtm_get_stdin_mode(struct dtm_context *context) -{ - if (unlikely(!context)) - return NULL; - if (!context->stdin_mode) - context->stdin_mode = dtm_get_fd_mode_bit_name( - dtm_get_stdin_mode_bit(context)); - return context->stdin_mode; -} - -int defex_trusted_map_lookup(struct defex_context *defex_context, - int callee_argc, void *callee_argv_ref) -{ - int ret = DTM_DENY; - struct dtm_context context; - - if (unlikely(!defex_context || !(defex_context->task))) - goto out; - if (unlikely(!dtm_context_get(&context, defex_context, callee_argc, callee_argv_ref))) - goto out; - ret = dtm_enforce(&context); - dtm_context_put(&context); -out: - return ret; -} diff --git a/security/samsung/defex_lsm/feature_trusted_map/dtm_engine.c b/security/samsung/defex_lsm/feature_trusted_map/dtm_engine.c deleted file mode 100755 index 192d2015e..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/dtm_engine.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "include/defex_debug.h" -#include "include/defex_rules.h" -#include "include/dtm.h" -#include "include/dtm_engine.h" -#include "include/dtm_log.h" -#include "include/dtm_utils.h" -#include "include/ptree.h" - -#define DTM_ANY_VALUE "*" /* wildcard value for files and arguments */ -#if defined(DEFEX_TM_DEFAULT_POLICY_ENABLE) || defined(DEFEX_KERNEL_ONLY) -/* Kernel-only builds don't use DEFEX's dynamic policy loading mechanism. */ -#define USE_EMBEDDED_POLICY -static struct PPTree embedded_header; -/* File with hardcoded policy */ -#include "dtm_engine_defaultpolicy.h" -#endif - -#ifdef DEFEX_KUNIT_ENABLED -static struct PPTree override_header, *pptree_override; - -void dtm_engine_override_data(const unsigned char *p) -{ - if (p) { - defex_log_warn("Dtm_engine data overridden"); - pptree_set_data(pptree_override = &override_header, p); - } else { - defex_log_warn("Dtm_engine override data back to normal"); - pptree_override = 0; - } -} -#endif - -static int dtm_check_stdin(struct dtm_context *context, int allowed_stdin_modes) -{ - if (unlikely(!(dtm_get_stdin_mode_bit(context) & allowed_stdin_modes))) { - dtm_report_violation(DTM_STDIN_VIOLATION, context); - return DTM_DENY; - } - return DTM_ALLOW; -} - -/* - * Enforces DTM policy for an exec system call. - */ -int dtm_enforce(struct dtm_context *context) -{ - const char *callee_path, *caller_path; - const char *program_name; - int ret, argc, call_argc; - const char *argument_value; - struct PPTree *pptree; /* effective header of policy rules */ - struct PPTreeContext pp_ctx; /* context for policy search */ - static char first_run = 1; /* flag for one-time policy actions */ - - if (first_run) { - if (dtm_tree.data) - defex_log_info("DTM engine: policy found"); - else - defex_log_warn("DTM engine: dynamic policy not loaded"); - first_run = 0; -#ifdef USE_EMBEDDED_POLICY - pptree_set_data(&embedded_header, dtm_engine_defaultpolicy); -#endif - } - - defex_log_info("Pid : %d %d", current->tgid, current->pid); - - if (!context || unlikely(!is_dtm_context_valid(context))) { - defex_log_info("(0) TMED no or invalid context"); - return DTM_DENY; - } - /* Check callee */ - callee_path = dtm_get_callee_path(context); - if (unlikely(!callee_path)) { - defex_log_info("(1) TMED null callee"); - return DTM_DENY; - } - -#ifdef DEFEX_KUNIT_ENABLED - if (pptree_override) /* test code has opportunity to use test policy instead */ - pptree = pptree_override; - else -#endif -#ifdef USE_EMBEDDED_POLICY /* try dynamic policy first, use embedded if not found */ - pptree = dtm_tree.data ? &dtm_tree : &embedded_header; -#else /* only dynamically loaded policy is acceptable */ - pptree = &dtm_tree; -#endif - if (!pptree->data) { /* Should never happen */ - defex_log_warn("(0) DTM engine: neither dynamic nor hardcoded rules loaded"); - return DTM_ALLOW; - } - memset(&pp_ctx, 0, sizeof(pp_ctx)); - if (!(pptree_find_path(pptree, - *callee_path == '/' ? - callee_path + 1 : callee_path, '/', &pp_ctx) && - (pp_ctx.types & PTREE_DATA_PATH))) { - defex_log_info("(2) TME callee '%s' not found", callee_path); - return DTM_ALLOW; - } - /* Check caller */ - caller_path = dtm_get_caller_path(context); - if (unlikely(!caller_path)) { - defex_log_info("(3) TMED callee '%s': null caller", callee_path); - return DTM_DENY; - } - if (!(pptree_find_path(pptree, caller_path + 1, '/', &pp_ctx) && - (pp_ctx.types & PTREE_DATA_PATH))) { - defex_log_info("(4) TMED callee '%s': caller '%s' not found", - callee_path, caller_path); - dtm_report_violation(DTM_CALLER_VIOLATION, context); - return DTM_DENY; - } - /* Check program, if any */ - program_name = dtm_get_program_name(context); - if (!program_name) { - defex_log_info("(5) TMED callee '%s', caller '%s': null program", - callee_path, caller_path); - return DTM_DENY; - } - pp_ctx.types |= PTREE_FIND_PEEK; - if (pptree_child_count(pptree, &pp_ctx) == 1 && - pptree_find_path(pptree, DTM_ANY_VALUE, 0, &pp_ctx)) { - defex_log_info("[TME callee '%s', caller '%s': program may be '*...'", - callee_path, caller_path); - pp_ctx.types |= PTREE_FIND_PEEKED; - pptree_find_path(pptree, 0, 0, &pp_ctx); - } else { - pp_ctx.types &= ~PTREE_FIND_PEEK; - if (!(pptree_find_path(pptree, program_name, 0, &pp_ctx) && - (pp_ctx.types & PTREE_DATA_INT2))) { - defex_log_info("(6) TMED callee '%s', caller '%s': program '%s' not found", - callee_path, caller_path, program_name); - dtm_report_violation(DTM_PROGRAM_VIOLATION, context); - return DTM_DENY; - } - } - /* Check standard input mode */ - if (pp_ctx.types & PTREE_DATA_INT2) { - ret = dtm_check_stdin(context, pp_ctx.value.int2); - if (unlikely(ret != DTM_ALLOW)) { - defex_log_info("(7) TMED callee '%s', caller '%s', program '%s': stdin mode %d, should be %d", - callee_path, caller_path, - program_name ? program_name : "(null)", - dtm_get_stdin_mode_bit(context), pp_ctx.value.int2); - return ret; - } - } - /* Check program arguments, if any */ - pp_ctx.types |= PTREE_FIND_CONTINUE; - for (call_argc = context->callee_argc, argc = 1; - argc <= call_argc && pptree_child_count(pptree, &pp_ctx); - ++argc) { - pp_ctx.types |= PTREE_FIND_PEEK; - if (pptree_find_path(pptree, DTM_ANY_VALUE, 0, &pp_ctx)) { - defex_log_info("(8) TME callee '%s', caller '%s', program '%s': any arguments accepted", - callee_path, caller_path, program_name); - return DTM_ALLOW; - } - pp_ctx.types &= PTREE_FIND_PEEKED; - pp_ctx.types |= PTREE_FIND_CONTINUE; - argument_value = dtm_get_callee_arg(context, argc); - if (!pptree_find_path(pptree, argument_value, 0, &pp_ctx)) { - defex_log_info( - "(9) TMED callee '%s', caller '%s', program '%s': argument '%s' (%d of %d) not found", - callee_path, caller_path, program_name, - argument_value ? argument_value : "(null)", - argc, call_argc); - dtm_report_violation(DTM_ARGUMENTS_VIOLATION, context); - return DTM_DENY; - } - if (pp_ctx.value.bits) { - defex_log_info("(10) TME callee '%s', caller '%s', program '%s': argument '%s' accepts '*'", - callee_path, caller_path, program_name, - argument_value ? argument_value : "(null)"); - return DTM_ALLOW; - } - } - if (call_argc && argc > call_argc) - defex_log_info("TME callee '%s', caller '%s', program '%s': all %d argument(s) checked", - callee_path, caller_path, program_name, call_argc); - return DTM_ALLOW; -} diff --git a/security/samsung/defex_lsm/feature_trusted_map/dtm_engine_defaultpolicy.h b/security/samsung/defex_lsm/feature_trusted_map/dtm_engine_defaultpolicy.h deleted file mode 100755 index 4730bfb61..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/dtm_engine_defaultpolicy.h +++ /dev/null @@ -1,4 +0,0 @@ -static unsigned char dtm_engine_defaultpolicy[] = { -80,80,84,114,101,101,45,1,0,0,0,0,1,0,0,0,0,1,0,0,0, -0,1,0,0,0,0,1,0,1,1,0,0, -}; diff --git a/security/samsung/defex_lsm/feature_trusted_map/dtm_log.c b/security/samsung/defex_lsm/feature_trusted_map/dtm_log.c deleted file mode 100755 index 939808581..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/dtm_log.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -#include "include/dtm.h" -#include "include/dtm_log.h" -#include "include/dtm_utils.h" - -#define DTM_MAX_LOG_SIZE (1024) -#define DTM_MAX_DETAIL_SIZE (1024) - -#ifdef DEFEX_DSMS_ENABLE -#include -#else -#define DSMS_SUCCESS (0) -#define dsms_send_message(feature_code, message, value) (DSMS_SUCCESS) -#endif - -static inline bool should_send_dsms_event(void) -{ -#ifdef DEFEX_DSMS_ENABLE - return IS_ENABLED(CONFIG_SECURITY_DSMS); -#else - return false; -#endif -} - -__visible_for_testing void dtm_append_argv(char *message, size_t size, - char separator, - int argc, const char **argv) -{ - const char *from; - char *to; - size_t len; - int arg, available; - - if (!message || size <= 0 || !separator) - return; - if (argc <= 0 || !argv || !argv[0]) - return; - - arg = 0; - len = strnlen(message, size); - available = size - len - 1; - to = message + len; - while (arg < argc && available > 0) { - from = argv[arg++]; - if (!from) - from = "(null)"; - len = strnlen(from, available); - strncpy(to, from, len); - to += len; - available -= len; - if (available-- > 0) - *to++ = separator; - } - *to = 0; -} - -__visible_for_testing void dtm_prepare_message(char *message, size_t size, - const char *where, const char *sep, - struct dtm_context *context) -{ - int total_argc, max_argc, arg; - - /* load all arguments to update attributes and fill arg values */ - total_argc = context->callee_argc; - max_argc = min_t(int, total_argc, ARRAY_SIZE(context->callee_argv)); - if (context->callee_copied_argc != max_argc) - for (arg = 0; arg < max_argc; arg++) - if (!context->callee_argv[arg]) - dtm_get_callee_arg(context, arg); - - snprintf(message, size, "%s%s%d:%d:%ld:%ld:%s:%s:%s:", where, sep, - context->callee_copied_argc, total_argc, - context->callee_copied_args_len, context->callee_total_args_len, - dtm_get_caller_path(context), dtm_get_callee_path(context), - dtm_get_stdin_mode(context)); - dtm_append_argv(message, size, ':', max_argc, context->callee_argv); -} - -#ifdef DEFEX_DEBUG_ENABLE -void dtm_debug_call(const char *where, struct dtm_context *context) -{ - char message[DTM_MAX_LOG_SIZE]; - - dtm_prepare_message(message, sizeof(message), where, ": ", context); - DTM_LOG_DEBUG("%s", message); -} -#endif - -noinline void dtm_report_violation(const char *feature_code, - struct dtm_context *context) -{ - char message[DTM_MAX_DETAIL_SIZE + 1]; - int ret; - - dtm_prepare_message(message, sizeof(message), "", "", context); - DTM_DEBUG(VIOLATIONS, "[%s]%s", feature_code, message); - if (should_send_dsms_event()) { - ret = dsms_send_message(feature_code, message, 0); - if (unlikely(ret != DSMS_SUCCESS)) - DTM_LOG_ERROR("Error %d while sending DSMS report", ret); - } -} diff --git a/security/samsung/defex_lsm/feature_trusted_map/dtm_utils.c b/security/samsung/defex_lsm/feature_trusted_map/dtm_utils.c deleted file mode 100755 index 799321a41..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/dtm_utils.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -#include -#endif - -#include "include/dtm.h" -#include "include/dtm_log.h" -#include "include/dtm_utils.h" - -const char * const DTM_UNKNOWN = ""; - -static inline int dtm_get_file_attr(struct path *path, struct kstat *stat) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) - return vfs_getattr(path, stat, STATX_BASIC_STATS, 0); -#else - return vfs_getattr(path, stat); -#endif -} - -/* - * Gets mode bit value for a file status. - */ -int dtm_get_stat_mode_bit(struct kstat *stat) -{ - int mode, mode_bit; - - if (!stat) - return DTM_FD_MODE_ERROR; - - mode = (stat->mode) & S_IFMT; - switch (mode) { - case S_IFBLK: - mode_bit = DTM_FD_MODE_BLK; - break; - case S_IFCHR: - mode_bit = DTM_FD_MODE_CHR; - break; - case S_IFDIR: - mode_bit = DTM_FD_MODE_DIR; - break; - case S_IFIFO: - mode_bit = DTM_FD_MODE_FIFO; - break; - case S_IFLNK: - mode_bit = DTM_FD_MODE_LNK; - break; - case S_IFREG: - mode_bit = DTM_FD_MODE_REG; - break; - case S_IFSOCK: - mode_bit = DTM_FD_MODE_SOCK; - break; - default: - mode_bit = DTM_FD_MODE_UNKNOWN; - DTM_LOG_ERROR("Unknown stat mode %d", mode); - } - return mode_bit; -} - -/* - * Gets mode bit value for a file descriptor. - */ -int dtm_get_fd_mode_bit(int fd) -{ - struct kstat stat; - struct fd sf; - int error; - - if (fd < 0) - return DTM_FD_MODE_ERROR; - - sf = fdget_raw(fd); - if (unlikely(!sf.file)) - return DTM_FD_MODE_CLOSED; - - error = dtm_get_file_attr(&sf.file->f_path, &stat); - fdput(sf); - if (unlikely(error < 0)) - return DTM_FD_MODE_ERROR; - - return dtm_get_stat_mode_bit(&stat); -} - -/* - * Gets printable name for a fd mode bit value. - */ -const char *dtm_get_fd_mode_bit_name(int mode_bit) -{ - switch (mode_bit) { - case DTM_FD_MODE_NONE: - return "NONE"; - case DTM_FD_MODE_BLK: - return "BLK"; - case DTM_FD_MODE_CHR: - return "CHR"; - case DTM_FD_MODE_DIR: - return "DIR"; - case DTM_FD_MODE_FIFO: - return "FIFO"; - case DTM_FD_MODE_LNK: - return "LNK"; - case DTM_FD_MODE_REG: - return "REG"; - case DTM_FD_MODE_SOCK: - return "SOCK"; - case DTM_FD_MODE_CLOSED: - return "CLOSED"; - case DTM_FD_MODE_ERROR: - return "ERROR"; - case DTM_FD_MODE_UNKNOWN: - return "UNKNOWN"; - } - DTM_LOG_ERROR("Unexpected mode bit %d", mode_bit); - return "INVALID"; -} diff --git a/security/samsung/defex_lsm/feature_trusted_map/include/dtm.h b/security/samsung/defex_lsm/feature_trusted_map/include/dtm.h deleted file mode 100755 index c4412b5c0..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/include/dtm.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#ifndef _INCLUDE_DTM_H -#define _INCLUDE_DTM_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dtm_utils.h" -#include "include/defex_internal.h" - -// DTM Kernel Interface - -#define DTM_CALLER_VIOLATION "DTM1" -#define DTM_PROGRAM_VIOLATION "DTM2" -#define DTM_STDIN_VIOLATION "DTM3" -#define DTM_ARGUMENTS_VIOLATION "DTM4" - -enum dtm_result_code { - DTM_ALLOW = DEFEX_ALLOW, - DTM_DENY = -DEFEX_DENY, -}; - -enum dtm_constants { - DTM_MAX_ARGC = 5, // max args checked (incl. program name) - DTM_MAX_ARG_STRLEN = 100, // max arg len checked (including '\0') -}; - -struct dtm_context { - struct defex_context *defex_context; - void *callee_argv_ref; - const char *callee_argv[DTM_MAX_ARGC]; - int callee_argc; - int callee_copied_argc; - long callee_copied_args_len; - long callee_total_args_len; - const char *program_name; - const char *stdin_mode; - int stdin_mode_bit; -}; - -/* Verifies if a dtm_context was properly initialized */ -static inline bool is_dtm_context_valid(struct dtm_context *context) -{ - return !ZERO_OR_NULL_PTR(context) - && !ZERO_OR_NULL_PTR(context->defex_context) - && !ZERO_OR_NULL_PTR(context->defex_context->task) - && !ZERO_OR_NULL_PTR(context->callee_argv_ref); -} - -/* Gets caller path for current call */ -static inline const char *dtm_get_caller_path(struct dtm_context *context) -{ - return get_dc_process_name(context->defex_context); -} - -/* Gets callee path for current call */ -static inline const char *dtm_get_callee_path(struct dtm_context *context) -{ - return get_dc_target_name(context->defex_context); -} - -/* Gets program name for current call */ -const char *dtm_get_program_name(struct dtm_context *context); -/* Gets stdin mode bit for current call */ -int dtm_get_stdin_mode_bit(struct dtm_context *context); -/* Gets stdin mode for current call */ -const char *dtm_get_stdin_mode(struct dtm_context *context); -/* Gets call argument value, copying from user if needed */ -const char *dtm_get_callee_arg(struct dtm_context *context, int arg_index); - -#endif /* _INCLUDE_DTM_H */ diff --git a/security/samsung/defex_lsm/feature_trusted_map/include/dtm_engine.h b/security/samsung/defex_lsm/feature_trusted_map/include/dtm_engine.h deleted file mode 100755 index af9f858cc..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/include/dtm_engine.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#ifndef _INCLUDE_DTM_ENGINE_H -#define _INCLUDE_DTM_ENGINE_H - -#include "dtm.h" - -/* Enforces DTM policy for an exec system call */ -extern int dtm_enforce(struct dtm_context *context); -#ifdef DEFEX_KUNIT_ENABLED -/* Replaces DTM policy (use NULL to return to normal) */ -extern void dtm_engine_override_data(const unsigned char *); -#endif - -#endif /* _INCLUDE_DTM_ENGINE_H */ diff --git a/security/samsung/defex_lsm/feature_trusted_map/include/dtm_log.h b/security/samsung/defex_lsm/feature_trusted_map/include/dtm_log.h deleted file mode 100755 index 17f9d95ba..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/include/dtm_log.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#ifndef _INCLUDE_DTM_LOG_H -#define _INCLUDE_DTM_LOG_H - -#define DTM_TAG "[DTM] " -#define DTM_LOG_INFO(format, ...) pr_info(DTM_TAG format, ##__VA_ARGS__) -#define DTM_LOG_ERROR(format, ...) pr_err(DTM_TAG format, ##__VA_ARGS__) -#define DTM_LOG_DEBUG(format, ...) pr_debug(DTM_TAG format, ##__VA_ARGS__) - -struct dtm_context; - -extern noinline void dtm_report_violation(const char *feature_code, - struct dtm_context *context); - -#ifdef DEFEX_DEBUG_ENABLE - -#define DTM_DEBUG(mode, format, ...) \ - do { \ - if (defex_tm_mode_enabled(DEFEX_TM_DEBUG_##mode)) \ - DTM_LOG_DEBUG(format, ##__VA_ARGS__); \ - } while (0) - -#define DTM_DEBUG_CALL(message, context) \ - do { \ - if (defex_tm_mode_enabled(DEFEX_TM_DEBUG_CALLS)) \ - dtm_debug_call("dtm_enforce", context); \ - } while (0) - -extern void dtm_debug_call(const char *where, struct dtm_context *context); - -#else -#define DTM_DEBUG(mode, format, ...) (0) -#define DTM_DEBUG_CALL(message, context) (0) -#endif /* DEFEX_DEBUG_ENABLE */ - -#endif /* _INCLUDE_DTM_LOG_H */ diff --git a/security/samsung/defex_lsm/feature_trusted_map/include/dtm_utils.h b/security/samsung/defex_lsm/feature_trusted_map/include/dtm_utils.h deleted file mode 100755 index 15022cbee..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/include/dtm_utils.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2020-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#ifndef _INCLUDE_DTM_UTILS_H -#define _INCLUDE_DTM_UTILS_H - -#include -#include -#include -#include -#include - -#include "../../include/defex_internal.h" - -enum dtm_stdin_descriptor_allow { - DTM_FD_MODE_NONE = 0, - DTM_FD_MODE_BLK = 1, - DTM_FD_MODE_CHR = 2, - DTM_FD_MODE_DIR = 4, - DTM_FD_MODE_FIFO = 8, - DTM_FD_MODE_LNK = 16, - DTM_FD_MODE_REG = 32, - DTM_FD_MODE_SOCK = 64, - DTM_FD_MODE_CLOSED = 128, - DTM_FD_MODE_ERROR = 256, - DTM_FD_MODE_UNKNOWN = 512, -}; - -extern const char * const DTM_UNKNOWN; - -/* Gets mode bit value for a file status */ -int dtm_get_stat_mode_bit(struct kstat *stat); - -/* Gets mode bit value for a file descriptor */ -extern int dtm_get_fd_mode_bit(int fd); - -/* Gets printable name for a fd mode bit value */ -const char *dtm_get_fd_mode_bit_name(int mode_bit); - -#endif /* _INCLUDE_DTM_UTILS_H */ diff --git a/security/samsung/defex_lsm/feature_trusted_map/ptree.c b/security/samsung/defex_lsm/feature_trusted_map/ptree.c deleted file mode 100755 index a31ce013b..000000000 --- a/security/samsung/defex_lsm/feature_trusted_map/ptree.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (c) 2021-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include -#include -#include "include/defex_debug.h" -#include "include/ptree.h" - -/* Functions for "using" (i.e., loading and searching) p-tree in portable - * variant. - */ - -/* Big-endian uchar -> int */ -static unsigned int charp2UInt(const unsigned char *p, int size) -{ - unsigned int i = *p; - - if (size > 1) { - i = (i << 8) | p[1]; - if (size > 2) { - i = (i << 8) | p[2]; - if (size > 3) - i = (i << 8) | p[3]; - } - } - return i; -} - -/* Checks magic number, loads important constants from prologue - */ -static int pptree_set_header(struct PPTree *tree) -{ - const unsigned char *pp = tree->data; - - /* Only PPTREE_MAGIC_FIXEDSIZE bytes are mandatory, remaining - * two can encode version information for compatibility - */ - if (strncmp((char *)pp, PPTREE_MAGIC, PPTREE_MAGIC_FIXEDSIZE)) { - defex_log_warn("Ptree: Bad magic number"); - return -1; - } - pp += PPTREE_MAGIC_FIXEDSIZE + 2; - tree->sTable.fullSize = charp2UInt(pp, UPPER_COUNT_SIZE); - pp += UPPER_COUNT_SIZE; - tree->sTable.size = charp2UInt(pp, UPPER_COUNT_SIZE); - pp += UPPER_COUNT_SIZE; - tree->sTable.indexSize = charp2UInt(pp++, 1); - tree->sTable.table = pp; - pp += tree->sTable.fullSize; - - tree->bTable.fullSize = charp2UInt(pp, UPPER_COUNT_SIZE); - pp += UPPER_COUNT_SIZE; - tree->bTable.size = charp2UInt(pp, UPPER_COUNT_SIZE); - pp += UPPER_COUNT_SIZE; - tree->bTable.indexSize = charp2UInt(pp++, 1); - tree->bTable.table = pp; - pp += tree->bTable.fullSize; - - tree->nodes.childCountSize = charp2UInt(pp++, 1); - tree->nodes.offsetSize = charp2UInt(pp++, 1); - tree->nodes.root = pp; - return 0; -} - -int pptree_set_data(struct PPTree *tree, const unsigned char *data) -{ - tree->data = data; - tree->allocated = 0; - return pptree_set_header(tree); -} - -void pptree_free(struct PPTree *tree) -{ - if (tree->allocated && tree->data) { - kfree((void *)tree->data); - tree->data = 0; - tree->allocated = 0; - } -} - -/* Gets a string (either a component of a search key or data associated - * with an item) given index - */ -static const unsigned char *pptree_string(const struct PPTree *tree, int i) -{ - const unsigned char *sTable = tree->sTable.table; - int index, bcs = tree->sTable.indexSize; - - if (i < 0 || i >= tree->sTable.size) { - defex_log_warn("Ptree: bad string index: %d (max %d)", i, tree->sTable.size); - return 0; - } - index = charp2UInt(sTable + i * bcs, bcs); - return sTable + (1 + tree->sTable.size) * bcs + index; -} - -/* Gets a bytearray given index */ -static const unsigned char *pptree_bytearray(const struct PPTree *tree, int i, - int *length) -{ - const unsigned char *bTable = tree->bTable.table; - int index, indexNext, bcs = tree->bTable.indexSize; - - if (i < 0 || i >= tree->bTable.size) { - defex_log_warn("Ptree: Bad bytearray index: %d (max %d)", i, tree->bTable.size); - if (length) - *length = 0; - return ""; - } - index = charp2UInt(bTable + i * bcs, bcs); - if (length) { - indexNext = charp2UInt(bTable + (i + 1) * bcs, bcs); - *length = indexNext - index; - } - return bTable + (1 + tree->bTable.size) * bcs + index; -} - -/* Given a pointer to the start of a tree node, load important values - * and advance pointer to the start of item index. - */ -static void load_node_prologue(const struct PPTree *tree, - const unsigned char **p, - unsigned int *itemSize, - unsigned int *dataTypes, - unsigned int *childCount) -{ - /* is the |-ing of data masks of all items in this node, - * thus all possible data types associated to items. - * By extension, it determines , which is the size in bytes - * of all items in this node. - */ - int dtTypes = charp2UInt((*p)++, 1), - itSize = tree->sTable.indexSize + tree->nodes.offsetSize; - if (dtTypes && itSize) { - ++itSize; - if (dtTypes & PTREE_DATA_BYTES) - itSize += tree->bTable.indexSize; - if (dtTypes & PTREE_DATA_STRING) - itSize += tree->sTable.indexSize; - if (dtTypes & PTREE_DATA_INT1) - itSize++; - if (dtTypes & PTREE_DATA_INT2) - itSize += 2; - if (dtTypes & PTREE_DATA_INT4) - itSize += 4; - if (dtTypes & PTREE_DATA_PATH) - itSize += tree->nodes.offsetSize; - } - if (childCount) - *childCount = charp2UInt(*p, tree->nodes.childCountSize); - *p += tree->nodes.childCountSize; - if (dataTypes) - *dataTypes = dtTypes; - if (itemSize) - *itemSize = itSize; -} - -/* Calculate offset from root node. It depends on a previous search, if any */ -static int pptree_get_offset(const struct PPTree *tree, - struct PPTreeContext *ctx) -{ - return ctx ? - /* Continue from the result of a previous search? */ - (ctx->types & PTREE_FIND_CONTINUE) && ctx->last ? - ctx->last - tree->nodes.root : - /* Continue from subpath of a previous search, if any? */ - ctx->types & PTREE_DATA_PATH ? - ctx->value.childPath : - 0 : - 0; /* No context, use root itself */ -} - -/* Load item-related data.

should be pointing to data type byte */ -static const unsigned char *pptree_get_itemData(const struct PPTree *tree, - const unsigned char *p, - int dataTypes, - struct PPTreeContext *ctx) -{ - memset(&ctx->value, 0, sizeof(ctx->value)); - ctx->types = (ctx->types & ~PTREE_DATA_MASK) | charp2UInt(p++, 1); - if (dataTypes & PTREE_DATA_BYTES) { - if (ctx->types & PTREE_DATA_BYTES) - ctx->value.bytearray.bytes = - pptree_bytearray(tree, - charp2UInt(p, - tree->bTable.indexSize), - &ctx->value.bytearray.length); - p += tree->bTable.indexSize; - } - if (dataTypes & PTREE_DATA_STRING) { - if (ctx->types & PTREE_DATA_STRING) - ctx->value.string = - (const char *) - pptree_string(tree, - charp2UInt(p, - tree->sTable.indexSize)); - p += tree->sTable.indexSize; - } - if (dataTypes & PTREE_DATA_BITA) - ctx->value.bits = (ctx->types & PTREE_DATA_BITA) && - (ctx->types & PTREE_DATA_BITA_MASK) - ? 1 : 0; - if (dataTypes & PTREE_DATA_INT1) { - if (ctx->types & PTREE_DATA_INT1) - ctx->value.int1 = charp2UInt(p, 1); - ++p; - } - if (dataTypes & PTREE_DATA_INT2) { - if (ctx->types & PTREE_DATA_INT2) - ctx->value.int2 = charp2UInt(p, 2); - p += 2; - } - if (dataTypes & PTREE_DATA_INT4) { - if (ctx->types & PTREE_DATA_INT4) - ctx->value.int4 = charp2UInt(p, 4); - p += 4; - } - if (dataTypes & PTREE_DATA_PATH) { - if (ctx->types & PTREE_DATA_PATH) - ctx->value.childPath = - charp2UInt(p, tree->nodes.offsetSize); - p += tree->nodes.offsetSize; - } - return p; -} - -int pptree_find(const struct PPTree *tree, const char **path, int pathLen, - struct PPTreeContext *ctx) -{ - int depth; - unsigned int dataTypes = 0; - const unsigned char *pFound = 0, - *p = tree->nodes.root + pptree_get_offset(tree, ctx); - - if (ctx->types & PTREE_FIND_PEEKED) { - /* If a previous call used PTREE_FIND_PEEK ignore , - * only advance context's offset - */ - if (ctx->lastPeeked) { - ctx->last = ctx->lastPeeked; - ctx->lastPeeked = 0; - return 1; - } - ctx->types &= ~(PTREE_FIND_PEEK | PTREE_FIND_PEEKED); - } - if (pathLen < 1) - return 0; - for (depth = 0; depth < pathLen; ++depth) { - const char *s; - int rCmp, sIndex, i; - unsigned int itemSize, childCount; - - load_node_prologue(tree, &p, &itemSize, &dataTypes, &childCount); - rCmp = -1; - if (childCount < 5) { /* linear ordered search */ - for (i = 0; i < childCount; ++i) { - sIndex = charp2UInt(p + i * itemSize, - tree->sTable.indexSize); - rCmp = strncmp(path[depth], - (const char *) - pptree_string(tree, sIndex), - PTREE_FINDPATH_MAX); - if (!rCmp) - break; - if (rCmp < 0) - return 0; - } - if (i == childCount) - return 0; - } else { /* binary search */ - int l = 0, r = childCount - 1; - - while (l <= r) { - i = l + (r - l) / 2; - sIndex = charp2UInt(p + i * itemSize, - tree->sTable.indexSize); - s = (const char *)pptree_string(tree, sIndex); - rCmp = strncmp(path[depth], s, - PTREE_FINDPATH_MAX); - if (rCmp < 0) - r = i - 1; - else - if (rCmp) - l = i + 1; - else - break; - } - if (rCmp) - return 0; - } - pFound = p + i * itemSize + tree->sTable.indexSize; - p = tree->nodes.root + charp2UInt(pFound, - tree->nodes.offsetSize); - } - if (ctx) { - if (ctx->types & PTREE_FIND_PEEK) - /* Don't advance context, just store it here */ - ctx->lastPeeked = p; - else { - ctx->last = p; - ctx->lastPeeked = 0; - } - if (dataTypes) - pptree_get_itemData(tree, - pFound + tree->nodes.offsetSize, - dataTypes, ctx); - else - /* Clear all bits for associated data */ - ctx->types &= ~PTREE_DATA_MASK; - } - return 1; -} - -int pptree_find_path(const struct PPTree *tree, const char *path, char delim, - struct PPTreeContext *ctx) -{ - int i, itemCount, findRes, flags = ctx->types; - char *ppath, *p, **pathItems; - const char *q, *pathItems1[1]; - - if (!path) - return 0; - /* Convenience: split in components, invoke pptree_find */ - if (ctx->types & PTREE_FIND_PEEKED) { - /* No path array to fill, just use last result */ - pathItems = 0; - itemCount = 0; - } else { - if (!delim) { - /* Special case, consider the whole string as - * a single component - */ - pathItems = (char **)pathItems1; - pathItems1[0] = path; - itemCount = 1; - } else { - ppath = kstrndup(path, PTREE_FINDPATH_MAX, GFP_KERNEL); - if (!ppath) - return 0; - for (itemCount = *path ? 1 : 0, q = path; *q; ++q) - if (*q == delim) - ++itemCount; - pathItems = kmalloc((itemCount ? itemCount : 1) * - sizeof(const char *), - GFP_KERNEL); - if (!pathItems) { - kfree((void *)ppath); - return 0; - } - *pathItems = ppath; - for (i = 1, p = ppath; *p; ++p) - if (*p == delim) { - *p = 0; - if (i < itemCount) - pathItems[i++] = p + 1; - } - } - } - findRes = pptree_find(tree, (const char **)pathItems, itemCount, ctx); - if (!(flags & PTREE_FIND_PEEKED) && delim) { - kfree((void *) pathItems); - kfree((void *) ppath); - } - return findRes; -} - -int pptree_child_count(const struct PPTree *tree, - struct PPTreeContext *ctx) -{ - const unsigned char *p = tree->nodes.root + - pptree_get_offset(tree, ctx); - unsigned int childCount; - - load_node_prologue(tree, &p, 0, 0, &childCount); - return childCount; -} - -int pptree_iterate_children(const struct PPTree *tree, - struct PPTreeContext *ctx, - int (*f)(const struct PPTree *tree, - const char *name, - const struct PPTreeContext *itemData, - void *data), - void *data) -{ - const unsigned char *p; - unsigned int i, childCount, itemSize, dataTypes, sIndex; - int ret; - - if (!f) - return 0; - p = tree->nodes.root + pptree_get_offset(tree, ctx); - load_node_prologue(tree, &p, &itemSize, &dataTypes, &childCount); - for (ret = i = 0; i < childCount; ++i) { - struct PPTreeContext itemData; - - sIndex = charp2UInt(p, tree->sTable.indexSize); - if (dataTypes) - pptree_get_itemData(tree, - p + tree->nodes.offsetSize + - tree->nodes.offsetSize, - dataTypes, &itemData); - else - itemData.types = 0; - ret = (*f)(tree, (const char *)pptree_string(tree, sIndex), - &itemData, data); - if (ret < 0) - return ret; - p += itemSize; - } - return ret; -} - -/* Recursively traverses all children in subpath of a node given - * by +, invoking on all paths ending on a leaf. - * Returns last result of . Stops prematurely if returns nonzero. - */ -static int pptree_iterate_subpaths(const struct PPTree *tree, - int offset, int pathDepth, - int (*f)(const struct PPTree *tree, - const char **path, - int pathLen, void *data), - const char **path, int maxDepth, - void *data) -{ - const unsigned char *p = tree->nodes.root + offset; - unsigned int i, childCount, itemSize, dataTypes; - - load_node_prologue(tree, &p, &itemSize, &dataTypes, &childCount); - for (i = 0; i < childCount; ++i) { - const unsigned char *pp = p + i * itemSize; - int sIndex, childIndex, j; - - sIndex = charp2UInt(pp, tree->sTable.indexSize); - pp += tree->sTable.indexSize; - childIndex = charp2UInt(pp, tree->nodes.offsetSize); - pp += tree->nodes.offsetSize; - path[pathDepth] = (const char *)pptree_string(tree, sIndex); - if (childIndex) { - if (pathDepth < maxDepth) { - j = pptree_iterate_subpaths(tree, childIndex, - pathDepth + 1, f, - path, maxDepth, - data); - if (j) - return j; - } - } else - if (f) { - int j = (*f)(tree, path, pathDepth + 1, data); - - if (j) - return j; - } - } - return 0; -} - -int pptree_iterate_paths(const struct PPTree *tree, - struct PPTreeContext *ctx, - int (*f)(const struct PPTree *tree, - const char **path, - int pathLen, void *data), - const char **path, int maxPathLen, - void *data) -{ - return pptree_iterate_subpaths(tree, pptree_get_offset(tree, ctx), - 0, f, path, maxPathLen, data); -} - diff --git a/security/samsung/defex_lsm/include/defex_caches.h b/security/samsung/defex_lsm/include/defex_caches.h deleted file mode 100755 index 3436a6d8c..000000000 --- a/security/samsung/defex_lsm/include/defex_caches.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#ifndef __DEFEX_CACHES_H -#define __DEFEX_CACHES_H - -#include "defex_config.h" -#include "defex_internal.h" - -#define FILE_CACHE_SIZE 0x40 - -struct defex_file_cache_entry { - int prev_entry; - int next_entry; - int pid; - struct file *file_addr; -}; - -struct defex_file_cache_list { - struct defex_file_cache_entry entry[FILE_CACHE_SIZE]; - int first_entry; - int last_entry; -}; - -void defex_file_cache_init(void); -void defex_file_cache_add(int pid, struct file *file_addr); -void defex_file_cache_update(struct file *file_addr); -void defex_file_cache_delete(int pid); -struct file *defex_file_cache_find(int pid); - -#endif /* __DEFEX_CACHES_H */ diff --git a/security/samsung/defex_lsm/include/defex_catch_list.h b/security/samsung/defex_lsm/include/defex_catch_list.h deleted file mode 100755 index 65e7fb532..000000000 --- a/security/samsung/defex_lsm/include/defex_catch_list.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#ifndef __CONFIG_SECURITY_DEFEX_CATCH_LIST_H -#define __CONFIG_SECURITY_DEFEX_CATCH_LIST_H - -#include "defex_config.h" - -//DEFINES////////////////////////////////////////////////////////////////////// -#define defex_do_str(s) #s -#define defex_make_str(s) defex_do_str(s) - -#define SYSCALL_CATCH(name, errno) \ - [__NR_##name] = { \ - .local_syscall = __DEFEX_##name, \ - .err_code = (errno) \ -} - -enum defex_local_syscall { - __DEFEX_empty = 0, - __DEFEX_rmdir, - __DEFEX_utimes, - __DEFEX_stat, - __DEFEX_lstat, - __DEFEX_umount, - __DEFEX_utime, - __DEFEX_futimesat, - __DEFEX_uselib, - __DEFEX_send, - __DEFEX_ustat, - __DEFEX_getdents, - __DEFEX_recv, - __DEFEX_fork, - __DEFEX_vfork, - __DEFEX_sigprocmask, - __DEFEX_sigpending, - __DEFEX_sigaction, - __DEFEX_sigaltstack, - __DEFEX_sigsuspend, - __DEFEX_truncate64, - __DEFEX_ftruncate64, - __DEFEX_fstat64, - __DEFEX_fstatat64, - __DEFEX_statfs64, - __DEFEX_stat64, - __DEFEX_lstat64, - __DEFEX_eventfd, - __DEFEX_epoll_create, - __DEFEX_shmget, - __DEFEX_shmctl, - __DEFEX_semctl, - __DEFEX_move_pages, - __DEFEX_lookup_dcookie, - __DEFEX_truncate, - __DEFEX_ftruncate, - __DEFEX_chdir, - __DEFEX_chroot, - __DEFEX_fchmod, - __DEFEX_fchmodat, - __DEFEX_fchownat, - __DEFEX_fchown, - __DEFEX_open, // -> included to the source - __DEFEX_openat, // -> included to the source - __DEFEX_write, // -> included to the source - __DEFEX_writev, - __DEFEX_pwrite64, - __DEFEX_pwritev, - __DEFEX_sendfile, - __DEFEX_signalfd4, - __DEFEX_vmsplice, - __DEFEX_splice, - __DEFEX_tee, - __DEFEX_fsync, - __DEFEX_fdatasync, - __DEFEX_sync_file_range, - __DEFEX_acct, - __DEFEX_sched_setparam, - __DEFEX_sched_setscheduler, - __DEFEX_sched_setaffinity, - __DEFEX_reboot, - __DEFEX_mq_timedsend, - __DEFEX_mq_timedreceive, - __DEFEX_msgrcv, - __DEFEX_msgsnd, - __DEFEX_semtimedop, - __DEFEX_add_key, - __DEFEX_request_key, - __DEFEX_keyctl, - __DEFEX_mmap, - __DEFEX_mincore, - __DEFEX_mbind, - __DEFEX_set_mempolicy, - __DEFEX_migrate_pages, - __DEFEX_accept4, - __DEFEX_recvmmsg, - __DEFEX_link, - __DEFEX_unlink, - __DEFEX_mknod, - __DEFEX_chmod, - __DEFEX_chown, - __DEFEX_mknodat, - __DEFEX_mkdirat, - __DEFEX_unlinkat, - __DEFEX_symlinkat, - __DEFEX_linkat, - __DEFEX_mkdir, - __DEFEX_lchown, - __DEFEX_rename, - __DEFEX_epoll_wait, - __DEFEX_sysctl, - __DEFEX_renameat, - __DEFEX_umount2, - __DEFEX_mount, - __DEFEX_pivot_root, - __DEFEX_utimensat, - __DEFEX_fcntl, - __DEFEX_kexec_load, - __DEFEX_ptrace, - __DEFEX_setgroups, - __DEFEX_settimeofday, - __DEFEX_delete_module, - __DEFEX_init_module, - __DEFEX_capset, - __DEFEX_setpriority, - __DEFEX_setregid, - __DEFEX_setgid, - __DEFEX_setreuid, - __DEFEX_setuid, - __DEFEX_setresuid, - __DEFEX_setresgid, - __DEFEX_setpgid, - __DEFEX_setfsuid, // -> included to the source - __DEFEX_setfsgid, // -> included to the source - __DEFEX_getsid, - __DEFEX_setsid, - __DEFEX_sethostname, - __DEFEX_setdomainname, - __DEFEX_setrlimit, - __DEFEX_umask, // -> included to the source - __DEFEX_prctl, - __DEFEX_getcpu, - __DEFEX_kill, - __DEFEX_tgkill, - __DEFEX_tkill, - __DEFEX_rt_tgsigqueueinfo, - __DEFEX_rt_sigqueueinfo, - __DEFEX_listen, - __DEFEX_accept, - __DEFEX_shutdown, - __DEFEX_shmat, - __DEFEX_shmdt, - __DEFEX_semget, - __DEFEX_semop, - __DEFEX_faccessat, - __DEFEX_fchdir, - __DEFEX_fstat, - __DEFEX_readlinkat, - __DEFEX_statfs, - __DEFEX_fstatfs, - __DEFEX_getcwd, - __DEFEX_futex, - __DEFEX_perf_event_open, - __DEFEX_socket, - __DEFEX_bind, - __DEFEX_connect, - __DEFEX_sendto, - __DEFEX_mprotect, - __DEFEX_mremap, - __DEFEX_pselect6, - __DEFEX_ioctl, - __DEFEX_ioprio_set, - __DEFEX_pipe2, - __DEFEX_getdents64, - __DEFEX_setitimer, - __DEFEX_capget, - __DEFEX_getresuid, - __DEFEX_getresgid, - __DEFEX_rt_sigprocmask, - __DEFEX_socketpair, - __DEFEX_getsockname, - __DEFEX_getpeername, - __DEFEX_recvfrom, - __DEFEX_setsockopt, - __DEFEX_sendmsg, - __DEFEX_recvmsg, - __DEFEX_socketcall, - __DEFEX_rt_sigsuspend, - __DEFEX_rt_sigpending, - __DEFEX_rt_sigaction, - __DEFEX_signal, - __DEFEX_remap_file_pages, - __DEFEX_ppoll, - __DEFEX_dup, - __DEFEX_dup3, - __DEFEX_eventfd2, - __DEFEX_timerfd_create, - __DEFEX_timerfd_gettime, - __DEFEX_timerfd_settime, - __DEFEX_epoll_create1, - __DEFEX_epoll_ctl, - __DEFEX_epoll_pwait, - __DEFEX_rt_sigtimedwait, - __DEFEX_clone, - __DEFEX_execve, // -> included to the source - __DEFEX_setxattr, - __DEFEX_lsetxattr, - __DEFEX_fsetxattr, - __DEFEX_removexattr, - __DEFEX_lremovexattr, - __DEFEX_fremovexattr, - __DEFEX_inotify_init1, - __DEFEX_syscalls, -}; - -struct local_syscall_struct { - enum defex_local_syscall local_syscall; - long int err_code; -}; - -const struct local_syscall_struct *get_local_syscall(int syscall_no); -const struct local_syscall_struct *get_local_syscall_compat(int syscall_no); -int syscall_local2global(int syscall_no); - -#endif /* __CONFIG_SECURITY_DEFEX_CATCH_LIST_H */ diff --git a/security/samsung/defex_lsm/include/defex_config.h b/security/samsung/defex_lsm/include/defex_config.h deleted file mode 100755 index 54df331bf..000000000 --- a/security/samsung/defex_lsm/include/defex_config.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#ifndef __CONFIG_SECURITY_DEFEX_CONFIG_H -#define __CONFIG_SECURITY_DEFEX_CONFIG_H - -/* MAX VALUES */ -#define MAX_LEN 256 -#define MAX_EXCEPTIONS 1024 -#define MAX_PROTECTED 1024 - -#ifdef DEFEX_PERMISSIVE_PED -#define GLOBAL_PED_STATUS (FEATURE_CHECK_CREDS | FEATURE_CHECK_CREDS_SOFT) -#else -#define GLOBAL_PED_STATUS FEATURE_CHECK_CREDS -#endif - -#ifdef DEFEX_PERMISSIVE_INT -#define GLOBAL_INTEGRITY_STATUS (FEATURE_INTEGRITY | FEATURE_INTEGRITY_SOFT) -#else -#define GLOBAL_INTEGRITY_STATUS FEATURE_INTEGRITY -#endif - -#ifdef DEFEX_PERMISSIVE_SP -#define GLOBAL_SAFEPLACE_STATUS (FEATURE_SAFEPLACE | FEATURE_SAFEPLACE_SOFT) -#else -#define GLOBAL_SAFEPLACE_STATUS FEATURE_SAFEPLACE -#endif - -#ifdef DEFEX_PERMISSIVE_TM -#define GLOBAL_TRUSTED_MAP_STATUS (FEATURE_TRUSTED_MAP | FEATURE_TRUSTED_MAP_SOFT) -#else -#define GLOBAL_TRUSTED_MAP_STATUS FEATURE_TRUSTED_MAP -#endif - -#ifdef DEFEX_PERMISSIVE_IM -#define GLOBAL_IMMUTABLE_STATUS (FEATURE_IMMUTABLE | FEATURE_IMMUTABLE_SOFT) -#else -#define GLOBAL_IMMUTABLE_STATUS FEATURE_IMMUTABLE -#endif - -/* Uncomment for Kernels, that require it */ -#define STRICT_UID_TYPE_CHECKS 1 - -#if defined(DEFEX_PED_ENABLE) || defined(DEFEX_SAFEPLACE_ENABLE) || defined(DEFEX_TRUSTED_MAP_ENABLE) || defined(DEFEX_IMMUTABLE_ENABLE) -#define DEFEX_FEATURE_ENABLE -#endif /* DEFEX_PED_ENABLE || DEFEX_SAFEPLACE_ENABLE || DEFEX_TRUSTED_MAP_ENABLE || DEFEX_IMMUTABLE_ENABLE */ - -int defex_get_features(void); - -#endif /* CONFIG_SECURITY_DEFEX_CONFIG_H */ diff --git a/security/samsung/defex_lsm/include/defex_debug.h b/security/samsung/defex_lsm/include/defex_debug.h deleted file mode 100755 index fdffb746d..000000000 --- a/security/samsung/defex_lsm/include/defex_debug.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#ifndef __DEFEX_DEBUG_H -#define __DEFEX_DEBUG_H - -#define DBG_SETUID 0 -#define DBG_SET_FSUID 1 -#define DBG_SETGID 2 - -#define DBG_SET_PE_STATUS 3 -#define DBG_SET_IM_STATUS 4 -#define DBG_SET_SP_STATUS 5 -#define DBG_SET_INT_STATUS 6 -#define DBG_GET_LOG 7 - -#define MAX_DATA_LEN 300 - -#define DEFEX_LOG_TAG "[DEFEX] " -#define DEFEX_LOG_BUF_SIZE (PAGE_SIZE << 0) -#define DEFEX_LOG_BUF_MASK (DEFEX_LOG_BUF_SIZE - 1) -#define DEFEX_LOG_LEVEL_MASK (MSG_CRIT | MSG_ERR | MSG_WARN | MSG_INFO | MSG_DEBUG | MSG_TIMEOFF | MSG_BLOB) - -enum defex_log_level { - MSG_CRIT = 1, - MSG_ERR = 2, - MSG_WARN = 4, - MSG_INFO = 8, - MSG_DEBUG = 16, - MSG_TIMEOFF = 32, - MSG_BLOB = 64 -}; - -int defex_create_debug(struct kset *defex_kset); - -void blob(const char *title, const char *buffer, const size_t bufLen, const int lineSize); - -#ifdef DEFEX_DEBUG_ENABLE -#define defex_log_crit(fmt, ...) defex_print_msg(MSG_CRIT, fmt, ##__VA_ARGS__) -#define defex_log_err(fmt, ...) defex_print_msg(MSG_ERR, fmt, ##__VA_ARGS__) -#define defex_log_warn(fmt, ...) defex_print_msg(MSG_WARN, fmt, ##__VA_ARGS__) -#define defex_log_info(fmt, ...) defex_print_msg(MSG_INFO, fmt, ##__VA_ARGS__) -#define defex_log_debug(fmt, ...) defex_print_msg(MSG_DEBUG, fmt, ##__VA_ARGS__) -#define defex_log_timeoff(fmt, ...) defex_print_msg(MSG_TIMEOFF, fmt, ##__VA_ARGS__) -#define defex_log_blob(fmt, ...) defex_print_msg(MSG_BLOB, fmt, ##__VA_ARGS__) -void defex_print_msg(const enum defex_log_level msg_type, const char *format, ...); -#else -#define defex_log_crit(fmt, ...) pr_crit(DEFEX_LOG_TAG fmt "\n", ##__VA_ARGS__) -#define defex_log_err(fmt, ...) pr_err(DEFEX_LOG_TAG fmt "\n", ##__VA_ARGS__) -#define defex_log_warn(fmt, ...) pr_warn(DEFEX_LOG_TAG fmt "\n", ##__VA_ARGS__) -#define defex_log_info(fmt, ...) pr_info(DEFEX_LOG_TAG fmt "\n", ##__VA_ARGS__) -#define defex_log_debug(fmt, ...) pr_debug(DEFEX_LOG_TAG fmt "\n", ##__VA_ARGS__) -#define defex_log_timeoff(fmt, ...) pr_info(DEFEX_LOG_TAG fmt "\n", ##__VA_ARGS__) -#define defex_log_blob(fmt, ...) pr_crit(fmt "\n", ##__VA_ARGS__) -#endif /* DEFEX_DEBUG_ENABLE */ - -#ifdef DEFEX_LOG_BUFFER_ENABLE -void log_buffer_flush(void); -#endif /* DEFEX_LOG_BUFFER_ENABLE */ - -#ifdef DEFEX_SHOW_RULES_ENABLE -int defex_show_structure(void *packed_rules, int rules_size); -#endif /* DEFEX_SHOW_RULES_ENABLE */ - -#endif /* __DEFEX_DEBUG_H */ diff --git a/security/samsung/defex_lsm/include/defex_internal.h b/security/samsung/defex_lsm/include/defex_internal.h deleted file mode 100755 index 4a7598f4f..000000000 --- a/security/samsung/defex_lsm/include/defex_internal.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#ifndef __CONFIG_SECURITY_DEFEX_INTERNAL_H -#define __CONFIG_SECURITY_DEFEX_INTERNAL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "defex_config.h" - -#ifdef DEFEX_KUNIT_ENABLED -#include -#endif - -#define DEFEX_MAJOR_VERSION 2 -#define DEFEX_MINOR_VERSION 6 -#define DEFEX_REVISION "rel" - -/* DEFEX Features */ -#define FEATURE_NONE 0 -#define FEATURE_CHECK_CREDS (1 << 0) -#define FEATURE_CHECK_CREDS_SOFT (1 << 1) -#define FEATURE_JAILHOUSE (1 << 2) /* reserved for future use */ -#define FEATURE_JAILHOUSE_SOFT (1 << 3) /* reserved for future use */ -#define FEATURE_RESTRICT_SYSCALL (1 << 4) /* reserved for future use */ -#define FEATURE_RESTRICT_SYSCALL_SOFT (1 << 5) /* reserved for future use */ -#define FEATURE_IMMUTABLE (1 << 6) -#define FEATURE_IMMUTABLE_SOFT (1 << 7) -#define FEATURE_SAFEPLACE (1 << 8) -#define FEATURE_SAFEPLACE_SOFT (1 << 9) -#define FEATURE_FIVE (1 << 10) /* reserved for future use */ -#define FEATURE_FIVE_SOFT (1 << 11) /* reserved for future use */ -#define FEATURE_TRUSTED_MAP (1 << 12) -#define FEATURE_TRUSTED_MAP_SOFT (1 << 13) -#define FEATURE_INTEGRITY (1 << 14) -#define FEATURE_INTEGRITY_SOFT (1 << 15) - -#define FEATURE_CLEAR_ALL (0xFF0000) - -#define DEFEX_ALLOW 0 -#define DEFEX_DENY 1 - -#define DEFEX_OK 0 -#define DEFEX_NOK 1 - -#define DEFEX_STARTED 1 - - -/* -------------------------------------------------------------------------- */ -/* Integrity feature */ -/* -------------------------------------------------------------------------- */ - -#define DEFEX_INTEGRITY_FAIL (1 << 1) - -/* -------------------------------------------------------------------------- */ -/* PrivEsc feature */ -/* -------------------------------------------------------------------------- */ - -#ifdef STRICT_UID_TYPE_CHECKS -#define CHECK_ROOT_CREDS(x) (uid_eq((x)->uid, GLOBAL_ROOT_UID) || \ - gid_eq((x)->gid, GLOBAL_ROOT_GID) || \ - uid_eq((x)->euid, GLOBAL_ROOT_UID) || \ - gid_eq((x)->egid, GLOBAL_ROOT_GID)) - -#define GLOBAL_SYS_UID KUIDT_INIT(1000) -#define GLOBAL_SYS_GID KGIDT_INIT(1000) - -#define CHECK_SYS_CREDS(x) (uid_eq((x)->uid, GLOBAL_SYS_UID) || \ - gid_eq((x)->gid, GLOBAL_SYS_GID) || \ - uid_eq((x)->euid, GLOBAL_SYS_UID) || \ - gid_eq((x)->egid, GLOBAL_SYS_GID)) - -#define uid_get_value(x) (x.val) -#define uid_set_value(x, v) x.val = v - -#else -#define CHECK_ROOT_CREDS(x) (((x)->uid == 0) || ((x)->gid == 0) || \ - ((x)->euid == 0) || ((x)->egid == 0)) -#define uid_get_value(x) (x) -#define uid_set_value(x, v) (x = v) -#endif /* STRICT_UID_TYPE_CHECKS */ - -#define CRED_FLAGS_PROOT (1 << 0) /* parent is root */ -#define CRED_FLAGS_MAIN_UPDATED (1 << 1) /* main thread's permission updated */ -#define CRED_FLAGS_SUB_UPDATED (1 << 2) /* sub thread's permission updated */ - -#define GET_CREDS(ids_ptr, cred_data_ptr) do { uid = (ids_ptr)->uid; \ - fsuid = (ids_ptr)->fsuid; \ - egid = (ids_ptr)->egid; \ - cred_flags = (cred_data_ptr)->cred_flags; } while(0) - -#define SET_CREDS(ids_ptr, cred_data_ptr) do { (ids_ptr)->uid = uid; \ - (ids_ptr)->fsuid = fsuid; \ - (ids_ptr)->egid = egid; \ - (cred_data_ptr)->cred_flags |= cred_flags; } while(0) - -extern unsigned char global_privesc_status; - -void get_task_creds(struct task_struct *p, unsigned int *uid_ptr, unsigned int *fsuid_ptr, unsigned int *egid_ptr, unsigned short *cred_flags_ptr); -int set_task_creds(struct task_struct *p, unsigned int uid, unsigned int fsuid, unsigned int egid, unsigned short cred_flags); -void set_task_creds_tcnt(struct task_struct *p, int addition); -int is_task_creds_ready(void); - -/* -------------------------------------------------------------------------- */ -/* Integrity feature */ -/* -------------------------------------------------------------------------- */ - -extern unsigned char global_integrity_status; - -/* -------------------------------------------------------------------------- */ -/* SafePlace feature */ -/* -------------------------------------------------------------------------- */ - -extern unsigned char global_safeplace_status; - -/* -------------------------------------------------------------------------- */ -/* Immutable feature */ -/* -------------------------------------------------------------------------- */ - -extern unsigned char global_immutable_status; - -/* -------------------------------------------------------------------------- */ -/* Trusted Map feature */ -/* -------------------------------------------------------------------------- */ - -extern unsigned char global_trusted_map_status; - -enum trusted_map_status { - DEFEX_TM_ENFORCING_MODE = (1 << 0), - DEFEX_TM_PERMISSIVE_MODE = (1 << 1), - DEFEX_TM_DEBUG_VIOLATIONS = (1 << 2), - DEFEX_TM_DEBUG_CALLS = (1 << 3), - DEFEX_TM_LAST_STATUS = (1 << 4) - 1 -}; - -static inline int defex_tm_mode_enabled(int mode_flag) -{ - return global_trusted_map_status & mode_flag; -} - -struct defex_context; -int defex_trusted_map_lookup(struct defex_context *dc, int argc, void *argv); - -/* -------------------------------------------------------------------------- */ -/* Common Helper API */ -/* -------------------------------------------------------------------------- */ - -struct defex_context { - int syscall_no; - struct task_struct *task; - struct file *process_file; - struct file *target_file; - const struct path *process_dpath; - const struct path *target_dpath; - char *process_name; - char *target_name; - char *target_name_buff; - char *process_name_buff; - - /* NB: cred must be the last field */ - struct cred *cred; -}; - -extern const char unknown_file[]; - -struct file *local_fopen(const char *fname, int flags, umode_t mode); -int local_fread(struct file *f, loff_t offset, void *ptr, unsigned long bytes); -int init_defex_context(struct defex_context *dc, int syscall, struct task_struct *p, struct file *f); -void release_defex_context(struct defex_context *dc); -struct file *get_dc_process_file(struct defex_context *dc); -const struct path *get_dc_process_dpath(struct defex_context *dc); -char *get_dc_process_name(struct defex_context *dc); -const struct path *get_dc_target_dpath(struct defex_context *dc); -char *get_dc_target_name(struct defex_context *dc); -struct file *defex_get_source_file(struct task_struct *p); -char *defex_get_filename(struct task_struct *p); -char* defex_resolve_filename(const char *name, char **out_buff); -int defex_files_identical(const struct file *f1, const struct file *f2); -static inline void safe_str_free(void *ptr) -{ - if (ptr && ptr != unknown_file) - kfree(ptr); -} - - -/* -------------------------------------------------------------------------- */ -/* Defex lookup API */ -/* -------------------------------------------------------------------------- */ - -int rules_lookup(const char *target_file, int attribute, struct file *f); - -/* -------------------------------------------------------------------------- */ -/* Defex init API */ -/* -------------------------------------------------------------------------- */ - -int __init defex_init_sysfs(void); -void __init creds_fast_hash_init(void); -int __init do_load_rules(void); - -/* -------------------------------------------------------------------------- */ -/* Defex debug API */ -/* -------------------------------------------------------------------------- */ - -int immutable_status_store(const char *status_str); -int privesc_status_store(const char *status_str); -int safeplace_status_store(const char *status_str); -int integrity_status_store(const char *status_str); - -extern bool boot_state_recovery __ro_after_init; -#ifdef DEFEX_DEPENDING_ON_OEMUNLOCK -extern bool boot_state_unlocked __ro_after_init; -extern int warranty_bit __ro_after_init; -#else -#define boot_state_unlocked (0) -#define warranty_bit (0) -#endif /* DEFEX_DEPENDING_ON_OEMUNLOCK */ - -#endif /* CONFIG_SECURITY_DEFEX_INTERNAL_H */ diff --git a/security/samsung/defex_lsm/include/defex_rules.h b/security/samsung/defex_lsm/include/defex_rules.h deleted file mode 100755 index 64a8fb272..000000000 --- a/security/samsung/defex_lsm/include/defex_rules.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#ifndef __DEFEX_RULES_H -#define __DEFEX_RULES_H - -#ifdef DEFEX_TRUSTED_MAP_ENABLE -#include "ptree.h" -#endif - -#define STATIC_RULES_MAX_STR 32 -#define INTEGRITY_LENGTH 32 -#define FEATURE_NAME_MAX_STR 32 - -#define GET_ITEM_OFFSET(item_ptr) (((char *)item_ptr) - ((char *)defex_packed_rules)) -#define GET_ITEM_PTR(offset, base_ptr) ((struct rule_item_struct *)(((char *)base_ptr) + (offset))) - -enum feature_types { - feature_is_file = 1, - feature_for_recovery = 2, - feature_ped_path = 4, - feature_ped_exception = 8, - feature_ped_status = 16, - feature_safeplace_path = 32, - feature_safeplace_status = 64, - feature_immutable_path_open = 128, - feature_immutable_path_write = 256, - feature_immutable_src_exception = 512, - feature_immutable_status = 1024, - feature_umhbin_path = 2048, - feature_trusted_map_status = 4096, - feature_integrity_check = 8192 -}; - -struct feature_match_entry { - char feature_name[FEATURE_NAME_MAX_STR]; - int feature_num; -}; - -struct static_rule { - unsigned int feature_type; - char rule[STATIC_RULES_MAX_STR]; -}; - -struct rule_item_struct { - unsigned short int next_level; - union { - struct { - unsigned short int next_file; - unsigned short int feature_type; - } __attribute__((packed)); - unsigned int data_size; - } __attribute__((packed)); - unsigned char size; -#ifdef DEFEX_INTEGRITY_ENABLE - unsigned char integrity[INTEGRITY_LENGTH]; -#endif /* DEFEX_INTEGRITY_ENABLE */ - char name[0]; -} __attribute__((packed)); - -int check_rules_ready(void); - -#ifdef DEFEX_TRUSTED_MAP_ENABLE -/* "Header" for DTM's dynamically loaded policy */ -extern struct PPTree dtm_tree; -#endif - -#endif /* __DEFEX_RULES_H */ diff --git a/security/samsung/defex_lsm/include/defex_sign.h b/security/samsung/defex_lsm/include/defex_sign.h deleted file mode 100755 index cd47e4a9c..000000000 --- a/security/samsung/defex_lsm/include/defex_sign.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. -*/ - -#ifndef __DEFEX_SIGN_H -#define __DEFEX_SIGN_H - -#define SIGN_SIZE 256 - -int defex_rules_signature_check(const char *rules_buffer, unsigned int rules_data_size, unsigned int *rules_size); - -#endif /* __DEFEX_SIGN_H */ diff --git a/security/samsung/defex_lsm/include/defex_tailer.h b/security/samsung/defex_lsm/include/defex_tailer.h deleted file mode 100755 index 9478491e2..000000000 --- a/security/samsung/defex_lsm/include/defex_tailer.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __INCLUDE_TAILER_H__ -#define __INCLUDE_TAILER_H__ - -/* Functions for managing a "tailer file", which is similar to a tar - * archive but, in order to support ordinary unadorned files - * - stores metainformation after each archived file - * - stores a single magic number at the very end. - */ - -/* Magic number, occurs only once at the end of tailer file. Should it - * change, be sure to update TAIL_MAGIC_LEN - */ -#define TAIL_MAGIC "#TAIL_GUARD#" -#define TAIL_MAGIC_LEN 12 -/* Maximum length of title associated with a stored file. Arbitrary, but - * should it increase, metainfo size (currently 1 byte) must change - * accordingly - */ -#define TAIL_MAX_TITLE_LENGTH 255 - -/* Each file's metainfo entry comprises (version 1,0): - * - offset where actual contents start: 4-byte big-endian - * - size of contents in bytes: 4-byte big-endian - * - title, up to TAIL_MAX_TITLE_LENGTH bytes, non 0-terminated - * - title length, 1 byte - * - major/minor version number, 1 byte each - * - * A tailer file is either an unadorned one or a linked list of content+ - * metainfo entries which goes backwards from the magic number. - */ - -/* Functions for handling tailer data as memory buffers */ - -/* If a memory buffer

with given ends with the tailer magic - * suffix, returns its offset, else returns -1 - */ -extern long defex_tailerp_has_suffix(const unsigned char *p, long size); -/* Given buffer

of given, returns address of last occurrence - * of contents of given (and if <sizep> sets *<sizep> to - * contents size), or 0 if <p> is unadorned has no such - * occurrences - */ -extern const unsigned char *defex_tailerp_find(const unsigned char *p, long size, - const char *title, long *sizep); -/* Given buffer <p> with <size> bytes, returns 0 if unadorned. Else, - * executes <task> for each entry, from last to first, passing arguments - * <title> (unterminated), title length, absolute <start> address and - * <size> in bytes, plus <data>. Terminates immediately if <task> returns - * negative. Returns last result of <task>. - */ -extern int defex_tailerp_iterate(const unsigned char *p, long size, - int (*task)(const char *title, int titleLen, - const unsigned char *start, - long size, void *data), - void *data); - -#endif diff --git a/security/samsung/defex_lsm/include/defex_test.h b/security/samsung/defex_lsm/include/defex_test.h deleted file mode 100755 index 63d0826e3..000000000 --- a/security/samsung/defex_lsm/include/defex_test.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#ifndef _DEFEX_TEST_H -#define _DEFEX_TEST_H -#ifdef DEFEX_KUNIT_ENABLED -#include <kunit/mock.h> - -#include <linux/types.h> -#include <linux/sysfs.h> - -/* -------------------------------------------------------------------------- */ -/* defex_debug */ -/* -------------------------------------------------------------------------- */ - -extern struct kobj_attribute debug_attribute; - -extern int set_user(struct cred *new_cred); -extern int set_cred(int target_id, int new_val); -extern ssize_t debug_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count); -extern ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf); - -/* -------------------------------------------------------------------------- */ -/* defex_immutable */ -/* -------------------------------------------------------------------------- */ - -extern int immutable_status_store(const char *status_str); - -/* -------------------------------------------------------------------------- */ -/* defex_priv */ -/* -------------------------------------------------------------------------- */ - -extern int privesc_status_store(const char *status_str); - -/* -------------------------------------------------------------------------- */ -/* defex_safeplace */ -/* -------------------------------------------------------------------------- */ - -extern int safeplace_status_store(const char *status_str); - -/* -------------------------------------------------------------------------- */ -/* defex_main */ -/* -------------------------------------------------------------------------- */ - -struct defex_context; - -extern struct task_struct *get_parent_task(const struct task_struct *p); - -#ifdef DEFEX_DSMS_ENABLE -extern void defex_report_violation(const char *violation, uint64_t counter, struct defex_context *dc, - uid_t stored_uid, uid_t stored_fsuid, uid_t stored_egid, int case_num); -#endif - -#ifdef DEFEX_SAFEPLACE_ENABLE -extern long kill_process(struct task_struct *p); -#endif - -#ifdef DEFEX_PED_ENABLE -extern long kill_process_group(struct task_struct *p, int tgid, int pid); -extern int task_defex_is_secured(struct defex_context *dc); -extern int at_same_group(unsigned int uid1, unsigned int uid2); -extern int at_same_group_gid(unsigned int gid1, unsigned int gid2); - -#ifdef DEFEX_LP_ENABLE -extern int lower_adb_permission(struct defex_context *dc, unsigned short cred_flags); -#endif /* DEFEX_LP_ENABLE */ -extern int task_defex_check_creds(struct defex_context *dc); -#endif /* DEFEX_PED_ENABLE */ - -#ifdef DEFEX_SAFEPLACE_ENABLE -extern int task_defex_safeplace(struct defex_context *dc); -#endif /* DEFEX_SAFEPLACE_ENABLE */ - -#ifdef DEFEX_IMMUTABLE_ENABLE -extern int task_defex_src_exception(struct defex_context *dc); -extern int task_defex_immutable(struct defex_context *dc, int attribute); -#endif /* DEFEX_IMMUTABLE_ENABLE */ - -#endif /* DEFEX_KUNIT_ENABLED */ -#endif /* _DEFEX_TEST_H */ diff --git a/security/samsung/defex_lsm/include/ptree.h b/security/samsung/defex_lsm/include/ptree.h deleted file mode 100755 index cfc3610e1..000000000 --- a/security/samsung/defex_lsm/include/ptree.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2021-2022 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#ifndef __PTREE_H__ - -/* A "P-tree" is a n-ary search tree whose keys are strings. A p-tree - * node may be associated with data like a string, a byte array or - * an entry point for an additional search (unrelated to the node's - * children). - * - * P-trees are represented in two variants: - * - a "build" data structure with traditional structs and pointers, used for - * building, converting, merging or exporting - * - a "portable" format packed with integer indices instead of pointers, - * stored as a byte array and used (read-only) by target applications. - * In both, all strings are stored at a dictionary and represented in nodes - * by indices, therefore child data have constant size; in addition, child - * lists are sorted, allowing efficient search. - */ - -/* Masks for data types. Should any be created, PTREE_DATA_MASK must - * be updated accordingly - */ -#define PTREE_DATA_BYTES 1 /* byte array */ -#define PTREE_DATA_STRING 2 /* zero-terminated string */ -#define PTREE_DATA_PATH 4 /* subpath */ -#define PTREE_DATA_INT1 8 /* byte */ -#define PTREE_DATA_INT2 16 /* 2-byte short */ -#define PTREE_DATA_INT4 32 /* 4-byte int */ -#define PTREE_DATA_BITA 64 /* bit */ -/* Bit A is stored directly in the bit below */ -#define PTREE_DATA_BITA_MASK 128 - -#define PTREE_DATA_MASK 255 /* ORs all PTREE_DATA masks */ - -/* Modifiers for search behavior */ -#define PTREE_FIND_CONTINUE 256 /* pptree_find should continue from - * previous result, if any - */ -#define PTREE_FIND_PEEK 512 /* a successful search does not advance - * the context, therefore the next search - * will start from the same point - */ -#define PTREE_FIND_PEEKED 1024 /* go to where a previous search would have - * gone had it not used PTREE_FIND_PEEKED - */ - -/* *************************************************************************** - * Declarations needed for _using_ exported P-trees - * ***************************************************************************/ - -/* Header for portable P-tree. This is not the binary format, rather after - * loading it caches the tree's details. - */ -struct PPTree { - const unsigned char *data; - struct { - int fullSize; - int size; - char indexSize; - const unsigned char *table; - } sTable; - struct { - int fullSize; - int size; - char indexSize; - const unsigned char *table; - } bTable; - struct { - char offsetSize; - char childCountSize; - const unsigned char *root; - } nodes; - char allocated; -}; - -/* Magic number (fixed portion, plus two version bytes) */ -#define PPTREE_MAGIC "PPTree-\1\0" -#define PPTREE_MAGIC_FIXEDSIZE 7 - -/* Sets a byte array as a p-tree's data. Returns 0 if successful. */ -extern int pptree_set_data(struct PPTree *tree, const unsigned char *data); -/* Releases pptree data, if needed */ -extern void pptree_free(struct PPTree *tree); - -/* Context data for portable p-tree operations, especially searching. - * Used for both input (key data) and output (result's place and data) - * Search starts from root, or, - * if .types is PPTREE_DATA_PATH and there's a subpath, from .value.childPath - * if .types is PPTREE_FIND_CONTINUE, from latest sucessful search - * If .types contains PTREE_DATA_PEEK, context does not advance even if - * search is successful. It will advance (and no search will be done) if next - * search include PTREE_DATA_PEEKED. - */ -struct PPTreeContext { - int types; - struct { - struct { - const unsigned char *bytes; - int length; - } bytearray; - const char *string; - int childPath; - int int1; - int int2; - int int4; - unsigned char bits; - } value; - const unsigned char *last, *lastPeeked; - unsigned int childCount; -}; -/* Search for given path. Return 0 if not found, 1 otherwise - * (and fills in *ctx). - * See PPTreeContext for where the search starts. - */ -extern int pptree_find(const struct PPTree *tree, - const char **path, int pathLen, - struct PPTreeContext *ctx); -/* Maximum key length, mostly an arbitrary limit against DoS */ -#define PTREE_FINDPATH_MAX 8000 -/* Search for a given path. - * Similar to pptree_find, but splits <path> at every occurrence of <delim> - * (unless delim is 0). In kernelspace, returns 0 if <path> length exceeds - * PTREE_FINDPATH_MAX. - */ -extern int pptree_find_path(const struct PPTree *tree, const char *path, - char delim, struct PPTreeContext *ctx); -/* Returns number of children. - * See PPTreeContext for which is the parent node. - */ -extern int pptree_child_count(const struct PPTree *tree, - struct PPTreeContext *ctx); -/* Iterates on immediate children. - * See PPTreeContext for iteration root. - * Executes <f> for all children until <f> returns nonzero. Returns - * last return of <f>. - */ -extern int pptree_iterate_children(const struct PPTree *tree, - struct PPTreeContext *ctx, - int (*f)(const struct PPTree *tree, - const char *name, - const struct PPTreeContext *itemData, - void *data), - void *data); - -/* Iterate on subpaths. - * See PPTreeContext for iteration root. - * Executes <f> for all subpaths ending on a leaf, stopping if <f> - * returns nonzero. - * Returns last result of <f> - */ -extern int pptree_iterate_paths(const struct PPTree *tree, - struct PPTreeContext *ctx, - int (*f)(const struct PPTree *tree, - const char **path, - int pathLen, void *data), - const char **path, int maxDepth, - void *data); -/* Dumps to stdout in human-readable format */ -extern void pptree_dump(const struct PPTree *tree); - -/* Maximum number of bytes for counters (practical reasonable limit) */ -#define UPPER_COUNT_SIZE 4 - -#define __PTREE_H__ -#endif diff --git a/security/samsung/defex_lsm/pack_rules b/security/samsung/defex_lsm/pack_rules deleted file mode 100755 index 89ccfc576..000000000 Binary files a/security/samsung/defex_lsm/pack_rules and /dev/null differ diff --git a/security/samsung/defex_lsm/pack_rules.c b/security/samsung/defex_lsm/pack_rules.c deleted file mode 100755 index 979f6b4ca..000000000 --- a/security/samsung/defex_lsm/pack_rules.c +++ /dev/null @@ -1,893 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include "include/defex_rules.h" - -#define SAFE_STRCOPY(dst, src) do { strncpy(dst, src, sizeof(dst)); dst[sizeof(dst) - 1] = 0; } while(0) - -const struct feature_match_entry feature_match[] = { - {"feature_safeplace_path", feature_safeplace_path}, - {"feature_ped_exception", feature_ped_exception}, - {"feature_immutable_path_open", feature_immutable_path_open}, - {"feature_immutable_path_write", feature_immutable_path_write}, - {"feature_immutable_src_exception", feature_immutable_src_exception}, - {"feature_umhbin_path", feature_umhbin_path}, - {"feature_integrity_check", feature_integrity_check}, -}; - -const int feature_match_size = sizeof(feature_match) / sizeof(feature_match[0]); - -struct file_list_item { - char file_name[PATH_MAX]; -#ifdef DEFEX_INTEGRITY_ENABLE - char integrity[INTEGRITY_LENGTH * 2 + 1]; -#endif /* DEFEX_INTEGRITY_ENABLE */ - int is_recovery; -}; - -struct rule_item_struct *defex_packed_rules; -int packfiles_count, packfiles_size; - -struct file_list_item *file_list = NULL; -int file_list_count = 0; - -#ifndef DEFEX_DEBUG_ENABLE -int debug_ifdef_is_active = 0; -void process_debug_ifdef(const char *src_str); -#endif - -/* Show rules vars */ -const char header_name[16] = {"DEFEX_RULES_FILE"}; -static char work_path[512]; -static int global_data_size; - -/* Suplementary functions for packing rules */ -struct rule_item_struct *create_file_item(const char *name, int l); -struct rule_item_struct *add_file_item(struct rule_item_struct *base, const char *name, int l); -struct rule_item_struct *lookup_dir(struct rule_item_struct *base, const char *name, int l, int for_recovery); -struct rule_item_struct *add_file_path(const char *file_path, int for_recovery); -struct rule_item_struct *addline2tree(char *src_line, enum feature_types feature); -char *extract_rule_text(const char *src_line); -int lookup_tree(const char *file_path, int attribute, int for_recovery); -int store_tree(FILE *f, FILE *f_bin); - -#ifdef DEFEX_INTEGRITY_ENABLE -/* Transfer string to hex */ -unsigned char ascii_to_hex(unsigned char input); -int string_to_hex(unsigned char *input, size_t inputLen, unsigned char *output); -char null_integrity[INTEGRITY_LENGTH * 2 + 1]; -#endif /* DEFEX_INTEGRITY_ENABLE */ - -/* Suplementary functions for reducing rules */ -int remove_substr(char *str, const char *part); -void trim_cr_lf(char *str); -char* remove_redundant_chars(char *str); -int load_file_list(const char *name); -int lookup_file_list(const char *rule, int for_recovery); - -/* Main processing functions */ -int reduce_rules(const char *source_rules_file, const char *reduced_rules_file, const char *list_file); -int pack_rules(const char *source_rules_file, const char *packed_rules_file, const char *packed_rules_binfile); - -struct rule_item_struct *create_file_item(const char *name, int l) -{ - struct rule_item_struct *item; - unsigned int offset; - - if (!name) - l = 0; - offset = packfiles_size; - packfiles_size += (sizeof(struct rule_item_struct) + l); - packfiles_count++; - item = GET_ITEM_PTR(offset, defex_packed_rules); - item->next_file = 0; - item->next_level = 0; - item->feature_type = 0; - item->size = l; -#ifdef DEFEX_INTEGRITY_ENABLE - memset(item->integrity, 0, INTEGRITY_LENGTH); -#endif /* DEFEX_INTEGRITY_ENABLE */ - if (l) - memcpy(item->name, name, l); - return item; -} - -struct rule_item_struct *add_file_item(struct rule_item_struct *base, const char *name, int l) -{ - struct rule_item_struct *item, *new_item = NULL; - - if (!base) - return new_item; - - new_item = create_file_item(name, l); - if (!base->next_level) { - base->next_level = GET_ITEM_OFFSET(new_item); - } else { - item = GET_ITEM_PTR(base->next_level, defex_packed_rules); - while(item->next_file) { - item = GET_ITEM_PTR(item->next_file, defex_packed_rules); - } - item->next_file = GET_ITEM_OFFSET(new_item); - } - return new_item; -} - -struct rule_item_struct *lookup_dir(struct rule_item_struct *base, const char *name, int l, int for_recovery) -{ - struct rule_item_struct *item = NULL; - unsigned int offset; - - if (!base || !base->next_level) - return item; - item = GET_ITEM_PTR(base->next_level, defex_packed_rules); - do { - if ((!(item->feature_type & feature_is_file) - || (!!(item->feature_type & feature_for_recovery)) == for_recovery) - && item->size == l - && !memcmp(name, item->name, l)) return item; - offset = item->next_file; - item = GET_ITEM_PTR(offset, defex_packed_rules); - } while(offset); - return NULL; -} - -struct rule_item_struct *add_file_path(const char *file_path, int for_recovery) -{ - const char *ptr, *next_separator; - struct rule_item_struct *base, *cur_item = NULL; - int l; - - if (!file_path || *file_path != '/') - return NULL; - if (!defex_packed_rules) { - packfiles_count = 0; - packfiles_size = 0; - defex_packed_rules = calloc(sizeof(struct rule_item_struct), 100 * 1024); - if (!defex_packed_rules) { - printf("WARNING: Can not create the new item!\n"); - exit(-1); - } - create_file_item(header_name, sizeof(header_name)); - } - base = defex_packed_rules; - ptr = file_path + 1; - do { - next_separator = strchr(ptr, '/'); - if (!next_separator) - l = strlen(ptr); - else - l = next_separator - ptr; - if (!l) - return NULL; /* two slashes in sequence */ - cur_item = lookup_dir(base, ptr, l, for_recovery); - if (!cur_item) { - cur_item = add_file_item(base, ptr, l); - /* slash wasn't found, it's a file */ - if (!next_separator) { - cur_item->feature_type |= feature_is_file; - if (for_recovery) - cur_item->feature_type |= feature_for_recovery; - } - } - base = cur_item; - ptr += l; - if (next_separator) - ptr++; - } while(*ptr); - return cur_item; -} - -int lookup_tree(const char *file_path, int attribute, int for_recovery) -{ - const char *ptr, *next_separator; - struct rule_item_struct *base, *cur_item = NULL; - int l; - - if (!file_path || *file_path != '/' || !defex_packed_rules) - return 0; - base = defex_packed_rules; - ptr = file_path + 1; - do { - next_separator = strchr(ptr, '/'); - if (!next_separator) - l = strlen(ptr); - else - l = next_separator - ptr; - if (!l) - return 0; - cur_item = lookup_dir(base, ptr, l, for_recovery); - if (!cur_item) - break; - if (cur_item->feature_type & attribute) - return 1; - base = cur_item; - ptr += l; - if (next_separator) - ptr++; - } while(*ptr); - return 0; -} - -char *extract_rule_text(const char *src_line) -{ - char *start_ptr, *end_ptr; - - start_ptr = strchr(src_line, '\"'); - if (start_ptr) { - start_ptr++; - end_ptr = strchr(start_ptr, '\"'); - if (end_ptr) { - *end_ptr = 0; - return start_ptr; - } - } - return NULL; -} - -#ifdef DEFEX_INTEGRITY_ENABLE -unsigned char ascii_to_hex(unsigned char input) -{ - if (input >= 0x30 && input <=0x39) - return input - 0x30; - else if (input >= 0x41 && input <= 0x46) - return input - 0x37; - else if (input >= 0x61 && input <= 0x66) - return input - 0x57; - else - return 0xFF; -} - -int string_to_hex(unsigned char *input, size_t inputLen, unsigned char *output) -{ - unsigned char convert1, convert2; - size_t i; - - if (input == NULL || output == NULL) - return 0; - - // Check input is a paired value. - if (inputLen % 2 != 0) - return 0; - - // Convert ascii code to hexa. - for (i = 0; i < inputLen / 2; i++) { - convert1 = ascii_to_hex(input[2*i]); - convert2 = ascii_to_hex(input[2*i+1]); - - if (convert1 == 0xFF || convert2 == 0xFF) - return 0; - - output[i] = (char)((convert1 << 4) | convert2); - } - - return 1; -} -#endif /* DEFEX_INTEGRITY_ENABLE */ - -struct rule_item_struct *addline2tree(char *src_line, enum feature_types feature) -{ - struct rule_item_struct *item = NULL; - char *str; - -#ifdef DEFEX_INTEGRITY_ENABLE - unsigned char *integrity, *n_sign = NULL, *r_sign = NULL; - int value; -#endif /* DEFEX_INTEGRITY_ENABLE */ - - str = extract_rule_text(src_line); - if (!str) - return NULL; - -#ifndef DEFEX_INTEGRITY_ENABLE - item = add_file_path(str, 0); - if (item) - item->feature_type |= feature; -#else - integrity = (unsigned char *)extract_rule_text(str + strnlen(str, PATH_MAX) + 1); - if (integrity) { - n_sign = (unsigned char *)strchr((const char *)integrity, 'N'); - r_sign = (unsigned char *)strchr((const char *)integrity, 'R'); - } - if (!(n_sign == NULL && r_sign != NULL)) { - item = add_file_path(str, 0); - if (item) { - item->feature_type |= feature; - if (n_sign) { - value = string_to_hex(n_sign + 1, INTEGRITY_LENGTH * 2, item->integrity); - if (!value) - return NULL; - } - - } - } - if (r_sign != NULL) { - item = add_file_path(str, 1); - if (item) { - item->feature_type |= feature; - value = string_to_hex(r_sign + 1, INTEGRITY_LENGTH * 2, item->integrity); - if (!value) - return NULL; - - } - } -#endif /* DEFEX_INTEGRITY_ENABLE */ - return item; -} - -int store_tree(FILE *f, FILE *f_bin) -{ - unsigned char *ptr = (unsigned char *)defex_packed_rules; - static char work_str[4096]; - int i, offset = 0, index = 0; - - if (packfiles_size) - defex_packed_rules->data_size = packfiles_size; - - work_str[0] = 0; - fprintf(f, "#ifndef DEFEX_RAMDISK_ENABLE\n\n"); - fprintf(f, "const unsigned char defex_packed_rules[] = {\n"); - for (i = 0; i < packfiles_size; i++) { - if (index) - offset += snprintf(work_str + offset, sizeof(work_str) - offset, ", "); - offset += snprintf(work_str + offset, sizeof(work_str) - offset, "0x%02x", ptr[i]); - index++; - if (index == 16) { - fprintf(f, "\t%s,\n", work_str); - index = 0; - offset = 0; - } - } - if (index) - fprintf(f, "\t%s\n", work_str); - fprintf(f, "};\n"); - fprintf(f, "\n#endif /* DEFEX_RAMDISK_ENABLE */\n\n"); - fprintf(f, "#define DEFEX_RULES_ARRAY_SIZE\t\t%d\n", packfiles_size); - if (f_bin) - fwrite(defex_packed_rules, 1, packfiles_size, f_bin); - return 0; -} - -int remove_substr(char *str, const char *part) -{ - int l, part_l, found = 0; - char *ptr; - - l = strnlen(str, PATH_MAX - 1); - ptr = strstr(str, part); - if (ptr) { - part_l = strnlen(part, 32) - 1; - memmove(ptr, ptr + part_l, l - (ptr - str) - part_l + 1); - found = 1; - } - return found; -} - -void trim_cr_lf(char *str) -{ - char *ptr; - /* remove CR or LF at the end */ - ptr = strchr(str, '\r'); - if (ptr) - *ptr = 0; - ptr = strchr(str, '\n'); - if (ptr) - *ptr = 0; -} - -char* remove_redundant_chars(char *str) -{ - int l; - - /* skip hash values in the begin */ - str += 65; - trim_cr_lf(str); - l = strnlen(str, PATH_MAX - 1); - /* remove starting dot or space */ - while(l && (*str == '.' || *str == ' ')) - str++; - return str; -} - -int load_file_list(const char *name) -{ - int found; - char *str; - FILE *lst_file = NULL; - struct file_list_item *file_list_new; - static char work_str[PATH_MAX*2]; - - lst_file = fopen(name, "r"); - if (!lst_file) - return -1; - - while(!feof(lst_file)) { - if (!fgets(work_str, sizeof(work_str), lst_file)) - break; - str = remove_redundant_chars(work_str); - if (*str == '/' && - (!strncmp(str, "/root/", 6) || - !strncmp(str, "/product/", 9) || - !strncmp(str, "/recovery/", 10) || - !strncmp(str, "/system/", 8) || - !strncmp(str, "/tmp/", 5) || - !strncmp(str, "/vendor/", 8) || -#if defined(DEFEX_FACTORY_ENABLE) - !strncmp(str, "/data/", 6) || -#endif - !strncmp(str, "/apex/", 6) || - !strncmp(str, "/system_ext/", 12))) { - remove_substr(str, "/root/"); - found = remove_substr(str, "/recovery/"); - file_list_count++; - file_list_new = realloc(file_list, sizeof(struct file_list_item) * file_list_count); - if (!file_list_new) { - free(file_list); - printf("WARNING: Can not allocate the filelist item!\n"); - exit(-1); - } - file_list = file_list_new; -#ifdef DEFEX_INTEGRITY_ENABLE - strncpy(file_list[file_list_count - 1].integrity, work_str, INTEGRITY_LENGTH * 2); - file_list[file_list_count - 1].integrity[INTEGRITY_LENGTH * 2] = 0; -#endif /* DEFEX_INTEGRITY_ENABLE */ - SAFE_STRCOPY(file_list[file_list_count - 1].file_name, str); - file_list[file_list_count - 1].is_recovery = found; - } - } - fclose(lst_file); - return 0; -} - -int lookup_file_list(const char *rule, int for_recovery) -{ - int i; - - for (i = 0; i < file_list_count; i++) { - if (file_list[i].is_recovery == for_recovery - && !strncmp(file_list[i].file_name, rule, strnlen(rule, PATH_MAX)) - && !strncmp(file_list[i].file_name, rule, strnlen(file_list[i].file_name, PATH_MAX))) - return i+1; - } - return 0; -} - -#ifndef DEFEX_DEBUG_ENABLE -void process_debug_ifdef(const char *src_str) -{ - char *ptr; - ptr = strstr(src_str, "#ifdef DEFEX_DEBUG_ENABLE"); - if (ptr) { - while(ptr > src_str) { - ptr--; - if (*ptr != ' ' && *ptr != '\t') - return; - } - debug_ifdef_is_active = 1; - return; - } - ptr = strstr(src_str, "#endif"); - if (ptr && debug_ifdef_is_active) { - while(ptr > src_str) { - ptr--; - if (*ptr != ' ' && *ptr != '\t') - return; - } - debug_ifdef_is_active = 0; - return; - } -} -#endif - -static int str_to_feature(const char *str) -{ - int i; - - for (i = 0; i < feature_match_size; i++) { - if (strstr(str, feature_match[i].feature_name)) { - return feature_match[i].feature_num; - } - } - - return 0; -} - -int reduce_rules(const char *source_rules_file, const char *reduced_rules_file, const char *list_file) -{ - int ret_val = -1; - int found_normal = 0, found_recovery = 0; - char *rule; - static char work_str[PATH_MAX*2], tmp_str[PATH_MAX*2]; - FILE *src_file = NULL, *dst_file = NULL; -#ifdef DEFEX_INTEGRITY_ENABLE - char *line_end, *integrity_normal; - char *integrity_recovery; -#endif /* DEFEX_INTEGRITY_ENABLE */ - - src_file = fopen(source_rules_file, "r"); - if (!src_file) - return -1; - dst_file = fopen(reduced_rules_file, "wt"); - if (!dst_file) - goto do_close2; - - if (load_file_list(list_file) != 0) - goto do_close1; - -#ifdef DEFEX_INTEGRITY_ENABLE - memset(null_integrity, '0', sizeof(null_integrity) - 1); - null_integrity[sizeof(null_integrity) - 1] = 0; -#endif /* DEFEX_INTEGRITY_ENABLE */ - - while(!feof(src_file)) { - if (!fgets(work_str, sizeof(work_str), src_file)) - break; - - if (str_to_feature(work_str)) { - trim_cr_lf(work_str); - SAFE_STRCOPY(tmp_str, work_str); - rule = extract_rule_text(tmp_str); - found_normal = lookup_file_list(rule, 0); - found_recovery = lookup_file_list(rule, 1); - if (rule && !found_normal && !found_recovery && !strstr(work_str, "/* DEFAULT */")) { - printf("removed rule: %s\n", rule); - continue; - } -#ifdef DEFEX_INTEGRITY_ENABLE - integrity_normal = null_integrity; - integrity_recovery = null_integrity; - if (found_normal) - integrity_normal = file_list[found_normal - 1].integrity; - if (found_recovery) - integrity_recovery = file_list[found_recovery - 1].integrity; - - line_end = strstr(work_str, "},"); - if (line_end) { - *line_end = 0; - line_end += 2; - } - - /* Add hash vale after each file path */ - if (found_normal || (!found_normal && !found_recovery)) - printf("remained rule: %s, %s %s\n", - rule, integrity_normal, (line_end != NULL)?line_end:""); - if (found_recovery) - printf("remained rule: %s, %s %s (R)\n", - rule, integrity_recovery, (line_end != NULL)?line_end:""); - - fprintf(dst_file, "%s,\"", work_str); - if (found_normal) - fprintf(dst_file, "N%s", integrity_normal); - if (found_recovery) - fprintf(dst_file, "R%s", integrity_recovery); - - fprintf(dst_file, "\"}, %s\n", (line_end != NULL)?line_end:""); - -#else - printf("remained rule: %s\n", work_str); - fputs(work_str, dst_file); - fputs("\n", dst_file); -#endif /* DEFEX_INTEGRITY_ENABLE */ - } else - fputs(work_str, dst_file); - } - ret_val = 0; -do_close1: - fclose(dst_file); -do_close2: - fclose(src_file); - return ret_val; -} - -int pack_rules(const char *source_rules_file, const char *packed_rules_file, const char *packed_rules_binfile) -{ - int ret_val = -1; - int feature; - FILE *src_file = NULL, *dst_file = NULL, *dst_binfile = NULL; - static char work_str[PATH_MAX*2]; - - src_file = fopen(source_rules_file, "r"); - if (!src_file) { - printf("Failed to open %s, %s\n", source_rules_file, strerror(errno)); - return -1; - } - dst_file = fopen(packed_rules_file, "wt"); - if (!dst_file) { - printf("Failed to open %s, %s\n", packed_rules_file, strerror(errno)); - goto do_close2; - } - if (packed_rules_binfile) { - dst_binfile = fopen(packed_rules_binfile, "wt"); - if (!dst_binfile) - printf("Failed to open %s, %s - Ignore\n", packed_rules_binfile, strerror(errno)); - } - - while(!feof(src_file)) { - if (!fgets(work_str, sizeof(work_str), src_file)) - break; -#ifndef DEFEX_DEBUG_ENABLE - process_debug_ifdef(work_str); - if (!debug_ifdef_is_active) { -#endif - feature = str_to_feature(work_str); - if (feature) { - addline2tree(work_str, feature); - continue; - } -#ifndef DEFEX_DEBUG_ENABLE - } -#endif - } - store_tree(dst_file, dst_binfile); - if (!packfiles_count) - printf("WARNING: Defex packed rules tree is empty!\n"); - ret_val = 0; - if (dst_binfile) - fclose(dst_binfile); - fclose(dst_file); -do_close2: - fclose(src_file); - return ret_val; -} - -static void feature_to_str(char *str, unsigned short flags) -{ - int i; - - str[0] = 0; - for (i = 0; i < feature_match_size; i++) - if (flags & feature_match[i].feature_num) { - if (str[0]) - strcat(str, ", "); - strcat(str, feature_match[i].feature_name); - } - if (flags & feature_for_recovery) { - if (str[0]) - strcat(str, ", "); - strcat(str, "feature_for_recovery"); - } -} - -static int check_array_size(struct rule_item_struct *ptr) -{ - unsigned long offset = (unsigned long)ptr - (unsigned long)defex_packed_rules; - int min_size = (global_data_size < packfiles_size)?global_data_size:packfiles_size; - - offset += sizeof(struct rule_item_struct); - - if (offset > min_size) - return 1; - - offset += ptr->size; - if (offset > min_size) - return 2; - return 0; -} - -static int parse_items(struct rule_item_struct *base, int path_length, int level) -{ - int l, err, ret = 0; - unsigned int offset; - struct rule_item_struct *child_item; - static char feature_list[128]; - - if (level > 8) { - printf("Level is too deep\n"); - return -1; - - } - if (path_length > (sizeof(work_path) - 128)) { - printf("Work path is too long\n"); - return -1; - } - while (base) { - err = check_array_size(base); - if (err) { - printf("%s/<?> - out of array bounds\n", work_path); - return -1; - } - l = base->size; - if (!l) { - printf("WARNING: Name field is incorrect, structure error!\n"); - return -1; - - } - - memcpy(work_path + path_length, base->name, l); - l += path_length; - work_path[l] = 0; - offset = base->next_level; - if (offset) { - if (base->feature_type & feature_is_file) { - printf("%s - is a file, but has children, structure error!\n", work_path); - ret = -1; - } else if (base->feature_type != 0) { - feature_to_str(feature_list, base->feature_type); - printf("%s%c - %s\n", work_path, - ((base->feature_type & feature_is_file)?' ':'/'), feature_list); - } - child_item = GET_ITEM_PTR(offset, defex_packed_rules); - work_path[l++] = '/'; - work_path[l] = 0; - err = check_array_size(child_item); - if (!err) { - err = parse_items(child_item, l, level + 1); - if (err != 0) - return err; - } else { - printf("%s/<?> - out of array bounds\n", work_path); - ret = -1; - } - } else { - feature_to_str(feature_list, base->feature_type); - printf("%s%c - %s\n", work_path, - ((base->feature_type & feature_is_file)?' ':'/'), feature_list); - } - work_path[path_length] = 0; - offset = base->next_file; - base = (offset)?GET_ITEM_PTR(offset, defex_packed_rules):NULL; - } - return ret; -} - -static int defex_show_structure(void *packed_rules, int rules_size) -{ - struct rule_item_struct *base; - int res, offset; - int first_item_size = sizeof(struct rule_item_struct) + sizeof(header_name); - - defex_packed_rules = (struct rule_item_struct *)packed_rules; - - work_path[0] = '/'; - work_path[1] = 0; - - packfiles_size = rules_size; - global_data_size = defex_packed_rules->data_size; - - printf("Rules binary size: %d\n", packfiles_size); - printf("Rules internal data size: %d\n", global_data_size); - - if (global_data_size > packfiles_size) - printf("WARNING: Internal size is bigger than binary size, possible structure error!\n"); - - if (packfiles_size < first_item_size) { - printf("ERROR: Too short binary size, can't continue!\n"); - return -1; - } - - if (global_data_size < first_item_size) - printf("WARNING: Too short data size, possible structure error!\n"); - - if (defex_packed_rules->size != sizeof(header_name)) - printf("WARNING: incorrect size field (%d), possible structure error!\n", - (int)defex_packed_rules->size); - - - if (memcmp(header_name, defex_packed_rules->name, sizeof(header_name)) != 0) - printf("WARNING: incorrect name field, possible structure error!\n"); - - printf("File List:\n"); - offset = defex_packed_rules->next_level; - base = (offset)?GET_ITEM_PTR(offset, defex_packed_rules):NULL; - if (!base) { - printf("- empty list\n"); - return 0; - } else if (check_array_size(base)) { - printf("- list is out of array bounds!\n"); - return -1; - } - - res = parse_items(base, 1, 1); - printf("== End of File List ==\n"); - return res; -} - -static int parse_packed_bin_file(const char *source_bin_file) -{ - struct stat sb; - FILE *policy_file = NULL; - int policy_size; - unsigned char *policy_data = NULL; - - if (stat(source_bin_file, &sb) == -1) { - perror("Error"); - return -1; - } - - policy_size = sb.st_size; - - printf("Try to parse file: %s\n", source_bin_file); - - policy_file = fopen(source_bin_file, "r"); - if (policy_file == NULL) { - perror("Error"); - return -1; - } - - policy_data = malloc(policy_size); - - if (policy_data == NULL) { - perror("Error"); - goto exit; - } - - if ((fread(policy_data, policy_size, 1, policy_file)) == -1) { - perror("Error"); - goto exit; - } - - defex_show_structure((void *)policy_data, policy_size); - -exit: - free(policy_data); - fclose(policy_file); - return 0; -} - -int main(int argc, char **argv) -{ - static char param[4][PATH_MAX]; - char *src_file = NULL, *packed_file = NULL, *packed_bin_file = NULL; - char *reduced_file = NULL, *list_file = NULL; - int i; - - if (argc == 3) { - if (!strncmp(argv[1], "-s", 2)) { - SAFE_STRCOPY(param[0], argv[2]); - src_file = param[0]; - parse_packed_bin_file(src_file); - return 0; - } - } - - if (argc < 4 || argc > 5) { - printf("Invalid number of arguments\n"); - goto show_help; - } - - for(i = 0; i < (argc - 2); i++) { - SAFE_STRCOPY(param[i], argv[i + 2]); - switch(i) { - case 0: - src_file = param[i]; - break; - case 1: - packed_file = reduced_file = param[i]; - break; - case 2: - packed_bin_file = list_file = param[i]; - break; - } - } - - if (!strncmp(argv[1], "-p", 2)) { - if (pack_rules(src_file, packed_file, packed_bin_file) != 0) - goto show_help; - return 0; - - } else if (!strncmp(argv[1], "-r", 2) && list_file) { - if (reduce_rules(src_file, reduced_file, list_file) != 0) - goto show_help; - return 0; - } - printf("Invalid command\n"); - -show_help: - printf("Defex rules processing utility.\nUSAGE:\n%s <CMD> <PARAMS>\n" - "Commands:\n" - " -p - Pack rules file to the tree. Params: <SOURCE_FILE> <PACKED_FILE> [PACKED_BIN_FILE]\n" - " -r - Reduce rules file (remove unexistent files). Params: <SOURCE_FILE> <REDUCED_FILE> <FILE_LIST>\n" - " -s - Show rules binary file content. Params: <PACKED_BIN_FILE>\n", - argv[0]); - return -1; -} diff --git a/security/samsung/five/Kconfig b/security/samsung/five/Kconfig deleted file mode 100755 index 4bb10c192..000000000 --- a/security/samsung/five/Kconfig +++ /dev/null @@ -1,108 +0,0 @@ -# Task Integrity Verifier - -config FIVE - bool "File Based Task Integrity Verifier (FIVE)(based on IMA)" - depends on INTEGRITY && DM_VERITY && BLK_DEV_LOOP - select CRYPTO - select CRYPTO_SHA1 - select CRYPTO_SHA1_ARM64_CE if ARM64_CRYPTO && KERNEL_MODE_NEON - select CRYPTO_HASH_INFO - select INTEGRITY_SIGNATURE - select INTEGRITY_ASYMMETRIC_KEYS - default n - help - File Based Task Integrity Verifier (FIVE) maintains - signatures of executables and other sensitive system files, - as they are read or executed. If an attacker manages - to change the contents of an important system file - being measured, we can tell. - -config FIVE_GKI_10 - bool "GKI 1.0 compatible version of FIVE" - depends on FIVE - default n - help - Build GKI 1.0 compatible version of FIVE - -config FIVE_GKI_20 - bool "GKI 2.0 compatible version of FIVE" - depends on FIVE - default n - help - Build GKI 2.0 compatible version of FIVE - -config FIVE_DEBUG - bool "FIVE Debug mode" - depends on FIVE - default n - help - Enable the debug mode in the FIVE - -config FIVE_CERT_ENG - string "FIVE certificate to verify signatures for eng binary" - depends on FIVE_DEBUG - default "x509_five_eng.der" - help - Path to CERT which will be built-in to eng binary - -config FIVE_CERT_USER - string "FIVE certificate to verify signatures for user binary" - depends on FIVE - default "x509_five_user.der" - help - Path to CERT which will be built-in to user binary - -choice - prompt "Default integrity hash algorithm" - depends on FIVE - default FIVE_DEFAULT_HASH_SHA1 - help - Select the default hash algorithm used for the measurement - list, integrity appraisal and audit log. - - config FIVE_DEFAULT_HASH_SHA1 - bool "SHA1 (default)" - depends on CRYPTO_SHA1 - - config FIVE_DEFAULT_HASH_SHA256 - bool "SHA256" - depends on CRYPTO_SHA256 - - config FIVE_DEFAULT_HASH_SHA512 - bool "SHA512" - depends on CRYPTO_SHA512 - - config FIVE_DEFAULT_HASH_WP512 - bool "WP512" - depends on CRYPTO_WP512 -endchoice - -config FIVE_DEFAULT_HASH - string - depends on FIVE - default "sha1" if FIVE_DEFAULT_HASH_SHA1 - default "sha256" if FIVE_DEFAULT_HASH_SHA256 - default "sha512" if FIVE_DEFAULT_HASH_SHA512 - default "wp512" if FIVE_DEFAULT_HASH_WP512 - -config FIVE_TRUSTED_KEYRING - bool "Require all keys on the .five keyring be signed" - depends on FIVE && SYSTEM_TRUSTED_KEYRING - default y - help - This option requires that all keys added to the .five - keyring be signed by a key on the system trusted keyring. - -config FIVE_PA_FEATURE - bool "Process authenticator" - depends on FIVE && !PROCA - default y - help - Enable Process Authenticator related code - -config FIVE_AUDIT_VERBOSE - bool "FIVE verbose audit logs" - depends on FIVE_DEBUG - default n - help - Enable verbose audit logs. diff --git a/security/samsung/five/Makefile b/security/samsung/five/Makefile deleted file mode 100755 index 8c548f526..000000000 --- a/security/samsung/five/Makefile +++ /dev/null @@ -1,36 +0,0 @@ - -obj-$(CONFIG_FIVE) += five.o -obj-$(CONFIG_FIVE_PA_FEATURE) += five_pa.o - -EXTRA_CFLAGS += -I$(src) -asflags-y += -Isecurity/integrity/five -asflags-y += -Isecurity/samsung/five -ccflags-y += -I$(srctree) -ccflags-y += -Wformat - -five-y := five_lv.o five_cert.o five_keyring.o five_init.o \ - five_cert_builtin.o five_cache.o \ - five_dmverity.o -five-$(CONFIG_FIVE_DSMS) += five_dsms.o - -ifdef CONFIG_FIVE_GKI_20 - FILES := five_main.o five_appraise.o five_crypto.o five_audit.o \ - five_hooks.o task_integrity.o five_state.o five_vfs.o \ - five_tint_dev.o five_tee_interface.o - five-y += $(addprefix gki/,$(FILES)) -else - five-y += five_crypto.o five_audit.o \ - five_hooks.o task_integrity.o five_state.o - ifdef CONFIG_PROCA_S_OS - five-y += s_os/five_main.o s_os/five_appraise.o - else - five-y += five_main.o five_appraise.o five_tee_interface.o - endif -endif - -# kunit tests options: -ifeq ($(CONFIG_SEC_KUNIT)$(CONFIG_UML), yy) - GCOV_PROFILE := y - five-$(CONFIG_FIVE) += five_dsms.o - EXTRA_CFLAGS += -DFIVE_KUNIT_ENABLED -endif diff --git a/security/samsung/five/five.h b/security/samsung/five/five.h deleted file mode 100755 index 6f67c195c..000000000 --- a/security/samsung/five/five.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_H -#define __LINUX_FIVE_H - -#include <linux/types.h> -#include <linux/crypto.h> -#include <linux/security.h> -#include <linux/hash.h> -#include <linux/audit.h> -#include <linux/workqueue.h> -#include <linux/xattr.h> - -#include "five_cert.h" -#include "five_crypto.h" - -#define XATTR_FIVE_SUFFIX "five" -#define XATTR_NAME_FIVE (XATTR_SECURITY_PREFIX XATTR_FIVE_SUFFIX) - -#define XATTR_PA_SUFFIX "pa" -#define XATTR_NAME_PA (XATTR_USER_PREFIX XATTR_PA_SUFFIX) - -/* set during initialization */ -extern int five_hash_algo; -struct worker_context { - struct work_struct data_work; - struct task_integrity *tint; -}; - -struct f_signature_task { - struct task_integrity *tint; - struct file *file; -}; - -struct f_signature_context { - struct work_struct data_work; - struct f_signature_task payload; -}; - -struct five_stat { - u64 inode_iversion; - u64 cache_iversion; - u32 cache_status; - u32 is_dm_verity; -}; - -/* Internal FIVE function definitions */ -int five_init(void); - -/* FIVE policy related functions */ -enum five_hooks { - FILE_CHECK = 1, - MMAP_CHECK, - BPRM_CHECK, - POST_SETATTR -}; - -struct file_verification_result { - struct task_struct *task; - struct file *file; - struct integrity_iint_cache *iint; - enum five_hooks fn; - int five_result; - void *xattr; - size_t xattr_len; -}; - -static inline void file_verification_result_init( - struct file_verification_result *result) -{ - memset(result, 0, sizeof(*result)); -} - -static inline void file_verification_result_deinit( - struct file_verification_result *result) -{ - kfree(result->xattr); - memset(result, 0, sizeof(*result)); -} - -int five_appraise_measurement(struct task_struct *task, int func, - struct integrity_iint_cache *iint, - struct file *file, - struct five_cert *cert); - -int five_read_xattr(struct dentry *dentry, char **xattr_value); -int five_check_params(struct task_struct *task, struct file *file); -const char *five_d_path(const struct path *path, char **pathbuf, - char *namebuf); - -int five_digsig_verify(struct five_cert *cert, - const char *digest, int digestlen); -int five_reboot_notifier(struct notifier_block *nb, - unsigned long action, void *unused); -int __init five_load_built_x509(void); -int __init five_keyring_init(void); - -const char *five_get_string_fn(enum five_hooks fn); -#endif diff --git a/security/samsung/five/five_appraise.c b/security/samsung/five/five_appraise.c deleted file mode 100755 index 5253c6f17..000000000 --- a/security/samsung/five/five_appraise.c +++ /dev/null @@ -1,852 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/magic.h> -#include <crypto/hash_info.h> - -#include <linux/task_integrity.h> -#include "five.h" -#include "five_audit.h" -#include "five_hooks.h" -#include "five_tee_api.h" -#include "five_porting.h" -#include "five_cache.h" -#include "five_dmverity.h" - -#define FIVE_RSA_SIGNATURE_MAX_LENGTH (2048/8) -/* Identify extend structure of integrity label */ -#define FIVE_ID_INTEGRITY_LABEL_EX 0xFFFF -#define FIVE_LABEL_VERSION1 1 -/* Maximum length of data integrity label. - * This limit is applied because: - * 1. TEEgris doesn't support signing data longer than 480 bytes; - * 2. The label's length is limited to 3965 byte according to the data - * transmission protocol between five_tee_driver and TA. - */ -#define FIVE_LABEL_MAX_LEN 256 - -/** - * Extend structure of integrity label. - * If field "len" equals 0xffff then it is extend integrity label, - * otherwise simple integrity label. - */ -struct integrity_label_ex { - uint16_t len; - uint8_t version; - uint8_t reserved[2]; - uint8_t hash_algo; - uint8_t hash[64]; - struct integrity_label label; -} __packed; - -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP -static const bool panic_on_error = true; -#else -static const bool panic_on_error; -#endif - -static DECLARE_RWSEM(sign_fcntl_lock); - -/* - * five_collect_measurement - collect file measurement - * - * Must be called with iint->mutex held. - * - * Return 0 on success, error code otherwise. - */ -static int five_collect_measurement(struct file *file, u8 hash_algo, - u8 *hash, size_t hash_len) -{ - int result = 0; - - BUG_ON(!file || !hash); - - result = five_calc_file_hash(file, hash_algo, hash, &hash_len); - if (result) { - five_audit_err(current, file, "collect_measurement", 0, - 0, "calculate file hash failed", result); - } - return result; -} - -static int get_integrity_label(struct five_cert *cert, - void **label_data, size_t *label_len) -{ - int rc = -ENODATA; - struct five_cert_header *header = - (struct five_cert_header *)cert->body.header->value; - - if (header && header->signature_type == FIVE_XATTR_HMAC) { - *label_data = cert->body.label->value; - *label_len = cert->body.label->length; - rc = 0; - } - return rc; -} - -static int get_signature(struct five_cert *cert, void **sig, - size_t *sig_len) -{ - int rc = -ENODATA; - struct five_cert_header *header = - (struct five_cert_header *)cert->body.header->value; - - if (header && header->signature_type == FIVE_XATTR_HMAC) { - if (cert->signature->length == 0) - return rc; - *sig = cert->signature->value; - *sig_len = cert->signature->length; - - rc = 0; - } - - return rc; -} - -static int update_label(struct integrity_iint_cache *iint, - const void *label_data, size_t label_len) -{ - struct integrity_label *l; - - if (!label_data) - return 0; - - l = kmalloc(sizeof(struct integrity_label) + label_len, GFP_NOFS); - if (l) { - l->len = label_len; - memcpy(l->data, label_data, label_len); - kfree(iint->five_label); - iint->five_label = l; - } else { - return -ENOMEM; - } - - return 0; -} - -static int five_fix_xattr(struct task_struct *task, - struct dentry *dentry, - struct file *file, - void **raw_cert, - size_t *raw_cert_len, - struct integrity_iint_cache *iint, - struct integrity_label_ex *label) -{ - int rc = 0; - u8 hash[FIVE_MAX_DIGEST_SIZE], *hash_file, *sig = NULL; - size_t hash_len = sizeof(hash), hash_file_len, sig_len; - void *file_label = label->label.data; - u16 file_label_len = label->label.len; - struct five_cert_body body_cert = {0}; - struct five_cert_header *header; - - BUG_ON(!task || !dentry || !file || !raw_cert || !(*raw_cert) || !iint); - BUG_ON(!raw_cert_len); - - rc = five_cert_body_fillout(&body_cert, *raw_cert, *raw_cert_len); - if (unlikely(rc)) - return -EINVAL; - - header = (struct five_cert_header *)body_cert.header->value; - hash_file = body_cert.hash->value; - hash_file_len = body_cert.hash->length; - if (unlikely(!header || !hash_file)) - return -EINVAL; - - if (label->version == FIVE_LABEL_VERSION1) { - rc = five_collect_measurement(file, header->hash_algo, - hash_file, hash_file_len); - if (unlikely(rc)) - return rc; - } else { - memcpy(hash_file, label->hash, hash_file_len); - } - - rc = five_cert_calc_hash(&body_cert, hash, &hash_len); - if (unlikely(rc)) - return rc; - - sig_len = (size_t)body_cert.hash->length + file_label_len; - - sig = kzalloc(sig_len, GFP_NOFS); - if (!sig) - return -ENOMEM; - - rc = sign_hash(header->hash_algo, hash, hash_len, - file_label, file_label_len, sig, &sig_len); - - if (!rc) { - rc = five_cert_append_signature(raw_cert, raw_cert_len, - sig, sig_len); - if (!rc) { - int count = 1; - - do { - rc = __vfs_setxattr_noperm(d_real_comp(dentry), - XATTR_NAME_FIVE, - *raw_cert, - *raw_cert_len, - 0); - count--; - } while (count >= 0 && rc != 0); - - if (!rc) { - rc = update_label(iint, - file_label, file_label_len); - } - } - } else if (panic_on_error) { - panic("FIVE failed to sign %s (ret code = %d)", - dentry->d_name.name, rc); - } else { - five_audit_sign_err(current, file, "fix_xattr", 0, - 0, "can't sign the file", rc); - } - - kfree(sig); - - return rc; -} - -int five_read_xattr(struct dentry *dentry, char **xattr_value) -{ - ssize_t ret; - - ret = vfs_getxattr_alloc(dentry, XATTR_NAME_FIVE, xattr_value, - 0, GFP_NOFS); - if (ret < 0) - ret = 0; - - return ret; -} - -static bool bad_fs(struct inode *inode) -{ - if (inode->i_sb->s_magic == EXT4_SUPER_MAGIC || - inode->i_sb->s_magic == F2FS_SUPER_MAGIC || - inode->i_sb->s_magic == OVERLAYFS_SUPER_MAGIC || - inode->i_sb->s_magic == EROFS_SUPER_MAGIC_V1) - return false; - - return true; -} - -static bool readonly_sb(struct inode *inode) -{ - if (inode->i_sb->s_flags & MS_RDONLY) - return true; - - return false; -} - -/* - * five_is_fsverity_protected - checks if file is protected by FSVERITY - * - * Return true/false - */ -static bool five_is_fsverity_protected(const struct inode *inode) -{ - return IS_VERITY(inode); -} - -/* - * five_appraise_measurement - appraise file measurement - * - * Return 0 on success, error code otherwise - */ -int five_appraise_measurement(struct task_struct *task, int func, - struct integrity_iint_cache *iint, - struct file *file, - struct five_cert *cert) -{ - enum task_integrity_reset_cause cause = CAUSE_UNKNOWN; - struct dentry *dentry = NULL; - struct inode *inode = NULL; - enum five_file_integrity status = FIVE_FILE_UNKNOWN; - enum task_integrity_value prev_integrity; - int rc = 0; - u8 *file_hash; - u8 stored_file_hash[FIVE_MAX_DIGEST_SIZE] = {0}; - size_t file_hash_len = 0; - struct five_cert_header *header = NULL; - - BUG_ON(!task || !iint || !file); - - prev_integrity = task_integrity_read(TASK_INTEGRITY(task)); - dentry = file->f_path.dentry; - inode = d_backing_inode(dentry); - - if (bad_fs(inode)) { - status = FIVE_FILE_FAIL; - cause = CAUSE_BAD_FS; - rc = -ENOTSUPP; - goto out; - } - - if (!cert) { - cause = CAUSE_NO_CERT; - if (five_is_fsverity_protected(inode)) - status = FIVE_FILE_FSVERITY; - else if (five_is_dmverity_protected(file)) - status = FIVE_FILE_DMVERITY; - goto out; - } - - header = (struct five_cert_header *)cert->body.header->value; - file_hash = cert->body.hash->value; - file_hash_len = cert->body.hash->length; - if (file_hash_len > sizeof(stored_file_hash)) { - cause = CAUSE_INVALID_HASH_LENGTH; - rc = -EINVAL; - goto out; - } - - memcpy(stored_file_hash, file_hash, file_hash_len); - - if (unlikely(!header || !file_hash)) { - cause = CAUSE_INVALID_HEADER; - rc = -EINVAL; - goto out; - } - - rc = five_collect_measurement(file, header->hash_algo, file_hash, - file_hash_len); - if (rc) { - cause = CAUSE_CALC_HASH_FAILED; - goto out; - } - - switch (header->signature_type) { - case FIVE_XATTR_HMAC: { - u8 *sig = NULL; - u8 algo = header->hash_algo; - void *file_label_data; - size_t file_label_len, sig_len = 0; - u8 cert_hash[FIVE_MAX_DIGEST_SIZE] = {0}; - size_t cert_hash_len = sizeof(cert_hash); - - status = FIVE_FILE_FAIL; - - rc = get_integrity_label(cert, &file_label_data, - &file_label_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_LABEL_DATA; - break; - } - - if (unlikely(file_label_len > PAGE_SIZE)) { - cause = CAUSE_INVALID_LABEL_DATA; - break; - } - - rc = get_signature(cert, (void **)&sig, &sig_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_SIGNATURE_DATA; - break; - } - - rc = five_cert_calc_hash(&cert->body, cert_hash, - &cert_hash_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_CALC_CERT_HASH; - break; - } - - rc = verify_hash(algo, cert_hash, - cert_hash_len, - file_label_data, file_label_len, - sig, sig_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_HASH; - if (cert) { - five_audit_hexinfo(file, "stored hash", - stored_file_hash, file_hash_len); - five_audit_hexinfo(file, "calculated hash", - file_hash, file_hash_len); - five_audit_hexinfo(file, "HMAC signature", - sig, sig_len); - } - break; - } - - rc = update_label(iint, file_label_data, file_label_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_UPDATE_LABEL; - break; - } - - status = FIVE_FILE_HMAC; - - break; - } - case FIVE_XATTR_DIGSIG: { - u8 cert_hash[FIVE_MAX_DIGEST_SIZE] = {0}; - size_t cert_hash_len = sizeof(cert_hash); - - status = FIVE_FILE_FAIL; - - rc = five_cert_calc_hash(&cert->body, cert_hash, - &cert_hash_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_CALC_CERT_HASH; - break; - } - - rc = five_digsig_verify(cert, cert_hash, cert_hash_len); - - if (rc) { - cause = CAUSE_INVALID_SIGNATURE; - if (cert) { - five_audit_hexinfo(file, "stored hash", - stored_file_hash, file_hash_len); - five_audit_hexinfo(file, "calculated hash", - file_hash, file_hash_len); - five_audit_hexinfo(file, "RSA signature", - cert->signature->value, - cert->signature->length); - } - break; - } - - status = FIVE_FILE_RSA; - - break; - } - default: - status = FIVE_FILE_FAIL; - cause = CAUSE_UKNOWN_FIVE_DATA; - break; - } - -out: - if (status == FIVE_FILE_FAIL || status == FIVE_FILE_UNKNOWN) { - task_integrity_set_reset_reason(TASK_INTEGRITY(task), - cause, file); - five_audit_verbose(task, file, five_get_string_fn(func), - prev_integrity, prev_integrity, - tint_reset_cause_to_string(cause), rc); - } - - five_set_cache_status(iint, status); - - return rc; -} - -/* - * five_update_xattr - update 'security.five' hash value - */ -static int five_update_xattr(struct task_struct *task, - struct integrity_iint_cache *iint, struct file *file, - struct integrity_label_ex *label) -{ - struct dentry *dentry; - int rc = 0; - uint8_t *hash; - size_t hash_len; - uint8_t *raw_cert; - size_t raw_cert_len; - struct five_cert_header header = { - .version = FIVE_CERT_VERSION1, - .privilege = FIVE_PRIV_DEFAULT, - .hash_algo = five_hash_algo, - .signature_type = FIVE_XATTR_HMAC }; - - BUG_ON(!task || !iint || !file || !label); - - if (label->version == FIVE_LABEL_VERSION1) { - hash_len = (size_t)hash_digest_size[five_hash_algo]; - } else { - header.hash_algo = label->hash_algo; - if (label->hash_algo >= HASH_ALGO__LAST) - return -EINVAL; - - hash_len = (size_t)hash_digest_size[label->hash_algo]; - if (hash_len > sizeof(label->hash)) - return -EINVAL; - } - - hash = kzalloc(hash_len, GFP_KERNEL); - if (!hash) - return -ENOMEM; - - dentry = file->f_path.dentry; - - /* do not collect and update hash for digital signatures */ - if (five_get_cache_status(iint) == FIVE_FILE_RSA) { - char dummy[512]; - struct inode *inode = file_inode(file); - - rc = __vfs_getxattr(d_real_comp(dentry), inode, XATTR_NAME_FIVE, - dummy, sizeof(dummy), XATTR_NOSECURITY); - - // Check if xattr is exist - if (rc > 0 || rc != -ENODATA) { - kfree(hash); - return -EPERM; - } else { // xattr does not exist. - five_set_cache_status(iint, FIVE_FILE_UNKNOWN); - pr_err("FIVE: ERROR: Cache is unsynchronized"); - } - } - - rc = five_cert_body_alloc(&header, hash, hash_len, - label->label.data, label->label.len, - &raw_cert, &raw_cert_len); - if (rc) - goto exit; - - if (task_integrity_allow_sign(TASK_INTEGRITY(task))) { - rc = five_fix_xattr(task, dentry, file, - (void **)&raw_cert, &raw_cert_len, iint, label); - if (rc) - pr_err("FIVE: Can't sign hash: rc=%d\n", rc); - } else { - rc = -EPERM; - } - - five_hook_file_signed(task, file, raw_cert, raw_cert_len, rc); - - five_cert_free(raw_cert); - -exit: - kfree(hash); - return rc; -} - -static void five_reset_appraise_flags(struct dentry *dentry) -{ - struct inode *inode = d_backing_inode(dentry); - struct integrity_iint_cache *iint; - - if (!S_ISREG(inode->i_mode)) - return; - - iint = integrity_iint_find(inode); - if (iint) - five_set_cache_status(iint, FIVE_FILE_UNKNOWN); -} - -/** - * five_inode_post_setattr - reflect file metadata changes - * @dentry: pointer to the affected dentry - * - * Changes to a dentry's metadata might result in needing to appraise. - * - * This function is called from notify_change(), which expects the caller - * to lock the inode's i_mutex. - */ -void five_inode_post_setattr(struct task_struct *task, struct dentry *dentry) -{ - five_reset_appraise_flags(dentry); -} - -/* - * five_protect_xattr - protect 'security.five' - * - * Ensure that not just anyone can modify or remove 'security.five'. - */ -static int five_protect_xattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) -{ - if (strcmp(xattr_name, XATTR_NAME_FIVE) == 0) { - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return 1; - } - return 0; -} - -int five_inode_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) -{ - int result = five_protect_xattr(dentry, xattr_name, xattr_value, - xattr_value_len); - - if (result == 1 && xattr_value_len == 0) { - five_reset_appraise_flags(dentry); - return 0; - } - - if (result == 1) { - bool digsig; - struct five_cert_header *header; - struct five_cert cert = { {0} }; - - result = five_cert_fillout(&cert, xattr_value, xattr_value_len); - if (result) - return result; - - header = (struct five_cert_header *)cert.body.header->value; - - if (!xattr_value_len || !header || - (header->signature_type >= FIVE_XATTR_END)) - return -EINVAL; - - digsig = (header->signature_type == FIVE_XATTR_DIGSIG); - if (!digsig) - return -EPERM; - - five_reset_appraise_flags(dentry); - result = 0; - } - - return result; -} - -int five_inode_removexattr(struct dentry *dentry, const char *xattr_name) -{ - int result; - - result = five_protect_xattr(dentry, xattr_name, NULL, 0); - if (result == 1) { - five_reset_appraise_flags(dentry); - result = 0; - } - return result; -} - -int five_reboot_notifier(struct notifier_block *nb, - unsigned long action, void *unused) -{ - down_write(&sign_fcntl_lock); - /* Need to wait for five_fcntl_sign finish */ - up_write(&sign_fcntl_lock); - - return NOTIFY_DONE; -} - -static int copy_label(const struct integrity_label __user *ulabel, - struct integrity_label_ex **out_label) -{ - u16 len; - size_t label_len; - int rc = 0; - struct integrity_label_ex header = {0}; - struct integrity_label_ex *label = NULL; - - if (unlikely(!ulabel || !out_label)) { - rc = -EINVAL; - goto error; - } - - if (unlikely(copy_from_user(&len, ulabel, sizeof(len)))) { - rc = -EFAULT; - goto error; - } - - if (len == FIVE_ID_INTEGRITY_LABEL_EX) { - if (unlikely(copy_from_user(&header, ulabel, sizeof(header)))) { - rc = -EFAULT; - goto error; - } - - if (len != header.len || - header.label.len > FIVE_LABEL_MAX_LEN || - header.version <= FIVE_LABEL_VERSION1) { - rc = -EINVAL; - goto error; - } - - label_len = sizeof(header) + header.label.len; - - label = kzalloc(label_len, GFP_NOFS); - if (unlikely(!label)) { - rc = -ENOMEM; - goto error; - } - - memcpy(label, &header, sizeof(header)); - if (unlikely(copy_from_user(&label->label.data[0], - (const u8 __user *)ulabel + sizeof(header), - label_len - sizeof(header)))) { - rc = -EFAULT; - goto error; - } - } else { - if (len > FIVE_LABEL_MAX_LEN) { - rc = -EINVAL; - goto error; - } - - label_len = sizeof(header) + len; - - label = kzalloc(label_len, GFP_NOFS); - if (unlikely(!label)) { - rc = -ENOMEM; - goto error; - } - - if (unlikely(copy_from_user(&label->label, ulabel, - sizeof(len) + len))) { - rc = -EFAULT; - goto error; - } - - if (len != label->label.len) { - rc = -EINVAL; - goto error; - } - - label->version = FIVE_LABEL_VERSION1; - } - - *out_label = label; -error: - if (rc) - kfree(label); - - return rc; -} - -/* Called from do_fcntl */ -int five_fcntl_sign(struct file *file, struct integrity_label __user *label) -{ - struct integrity_iint_cache *iint; - struct inode *inode = file_inode(file); - struct integrity_label_ex *l = NULL; - int rc = 0; - - if (!S_ISREG(inode->i_mode)) - return -EINVAL; - - if (readonly_sb(inode)) { - pr_err("FIVE: Can't sign a file on RO FS\n"); - return -EROFS; - } - - if (task_integrity_allow_sign(TASK_INTEGRITY(current))) { - rc = copy_label(label, &l); - if (rc) { - pr_err("FIVE: Can't copy integrity label\n"); - return rc; - } - } else { - enum task_integrity_value tint = - task_integrity_read(TASK_INTEGRITY(current)); - - five_audit_err(current, file, "fcntl_sign", tint, tint, - "sign:no-perm", -EPERM); - return -EPERM; - } - - iint = integrity_inode_get(inode); - if (!iint) { - kfree(l); - return -ENOMEM; - } - - if (file->f_op && file->f_op->flush) { - if (file->f_op->flush(file, current->files)) { - kfree(l); - return -EOPNOTSUPP; - } - } - - down_read(&sign_fcntl_lock); - inode_lock(inode); - rc = five_update_xattr(current, iint, file, l); - iint->five_signing = false; - inode_unlock(inode); - up_read(&sign_fcntl_lock); - - kfree(l); - - return rc; -} - -static int check_input_inode(struct inode *inode) -{ - if (!S_ISREG(inode->i_mode)) - return -EINVAL; - - if (readonly_sb(inode)) { - pr_err("FIVE: Can't sign a file on RO FS\n"); - return -EROFS; - } - - return 0; -} - -int five_fcntl_edit(struct file *file) -{ - int rc; - struct dentry *dentry; - uint8_t *raw_cert = NULL; - size_t raw_cert_len = 0; - struct integrity_iint_cache *iint; - struct inode *inode = file_inode(file); - - rc = check_input_inode(inode); - if (rc) - return rc; - - if (!task_integrity_allow_sign(TASK_INTEGRITY(current))) - return -EPERM; - - inode_lock(inode); - dentry = file->f_path.dentry; - rc = __vfs_setxattr_noperm(d_real_comp(dentry), - XATTR_NAME_FIVE, - raw_cert, - raw_cert_len, - 0); - iint = integrity_inode_get(inode); - if (iint) - iint->five_signing = true; - inode_unlock(inode); - - return rc; -} - -int five_fcntl_close(struct file *file) -{ - int rc; - ssize_t xattr_len; - struct dentry *dentry; - struct integrity_iint_cache *iint; - struct inode *inode = file_inode(file); - - rc = check_input_inode(inode); - if (rc) - return rc; - - inode_lock(inode); - iint = integrity_inode_get(inode); - if (!iint) { - inode_unlock(inode); - return -ENOMEM; - } - - if (iint->five_signing) { - dentry = file->f_path.dentry; - xattr_len = __vfs_getxattr(d_real_comp(dentry), inode, - XATTR_NAME_FIVE, NULL, 0, XATTR_NOSECURITY); - if (xattr_len == 0) - rc = __vfs_removexattr(d_real_comp(dentry), - XATTR_NAME_FIVE); - - iint->five_signing = false; - } - inode_unlock(inode); - - return rc; -} diff --git a/security/samsung/five/five_audit.c b/security/samsung/five/five_audit.c deleted file mode 100755 index d2908c078..000000000 --- a/security/samsung/five/five_audit.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Audit calls for FIVE audit subsystem. - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/fs.h> -#include <linux/gfp.h> -#include <linux/audit.h> -#include <linux/task_integrity.h> -#include <linux/version.h> -#include "five.h" -#include "five_audit.h" -#include "five_cache.h" -#include "five_porting.h" -#include "five_dsms.h" -#include "five_testing.h" - -__visible_for_testing __mockable -void five_audit_msg(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); - -#ifdef CONFIG_FIVE_AUDIT_VERBOSE -__mockable -void five_audit_verbose(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - five_audit_msg(task, file, op, prev, tint, cause, result); -} -#else -__mockable -void five_audit_verbose(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ -} -#endif - -void five_audit_info(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - five_audit_msg(task, file, op, prev, tint, cause, result); -} - -__visible_for_testing __mockable -void call_five_dsms_reset_integrity(const char *task_name, int result, - const char *file_name) -{ - five_dsms_reset_integrity(task_name, result, file_name); -} - -/** - * There are two kind of event that can come to the function: error - * and tampering attempt. 'result' is for identification of error type - * and it should be non-zero in case of error but is always zero in - * case of tampering. - */ -void five_audit_err(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - five_audit_msg(task, file, op, prev, tint, cause, result); - - if (!result) { - char comm[TASK_COMM_LEN]; - struct task_struct *tsk = task ? task : current; - - call_five_dsms_reset_integrity(get_task_comm(comm, tsk), 0, op); - } -} - -__visible_for_testing __mockable -void call_five_dsms_sign_err(const char *app, int result) -{ - five_dsms_sign_err(app, result); -} - -void five_audit_sign_err(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - char comm[TASK_COMM_LEN]; - struct task_struct *tsk = task ? task : current; - - get_task_comm(comm, tsk); - call_five_dsms_sign_err(comm, result); -} - -__visible_for_testing __mockable -void five_audit_msg(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - struct audit_buffer *ab; - struct inode *inode = NULL; - const char *fname = NULL; - char *pathbuf = NULL; - char filename[NAME_MAX]; - char comm[TASK_COMM_LEN]; - const char *name = ""; - struct task_struct *tsk = task ? task : current; - struct integrity_iint_cache *iint = NULL; - - if (file) { - inode = file_inode(file); - fname = five_d_path(&file->f_path, &pathbuf, filename); - } - - ab = audit_log_start(current->audit_context, GFP_KERNEL, - AUDIT_INTEGRITY_DATA); - if (unlikely(!ab)) { - pr_err("Can't get a context of audit logs\n"); - goto exit; - } - - audit_log_format(ab, " pid=%d", task_pid_nr(tsk)); - audit_log_format(ab, " tgid=%d", task_tgid_nr(tsk)); - audit_log_task_context(ab); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) - audit_log_format(ab, " op=%s", op); -#else - audit_log_format(ab, " op="); - audit_log_string(ab, op); -#endif - audit_log_format(ab, " cint=0x%x", tint); - audit_log_format(ab, " pint=0x%x", prev); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) - audit_log_format(ab, " cause=%s", cause); -#else - audit_log_format(ab, " cause="); - audit_log_string(ab, cause); -#endif - audit_log_format(ab, " comm="); - audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); - if (fname) { - audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, fname); - name = fname; - } - if (inode) { - audit_log_format(ab, " dev="); - audit_log_untrustedstring(ab, inode->i_sb->s_id); - audit_log_format(ab, " ino=%lu", inode->i_ino); - audit_log_format(ab, " i_version=%llu ", - inode_query_iversion(inode)); - iint = integrity_inode_get(inode); - if (iint) { - audit_log_format(ab, " five_status=%d ", - five_get_cache_status(iint)); - audit_log_format(ab, " version=%llu ", - (unsigned long long)iint->version); - } - } - audit_log_format(ab, " res=%d", result); - audit_log_end(ab); - -exit: - if (pathbuf) - __putname(pathbuf); -} - -void five_audit_tee_msg(const char *func, const char *cause, int rc, - uint32_t origin) -{ - struct audit_buffer *ab; - - ab = audit_log_start(current->audit_context, GFP_KERNEL, - AUDIT_INTEGRITY_DATA); - if (unlikely(!ab)) { - pr_err("Can't get a context of audit logs\n"); - return; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) - audit_log_format(ab, " func=%s", func); - audit_log_format(ab, " cause=%s", cause); -#else - audit_log_format(ab, " func="); - audit_log_string(ab, func); - audit_log_format(ab, " cause="); - audit_log_string(ab, cause); -#endif - audit_log_format(ab, " rc=0x%x, ", rc); - audit_log_format(ab, " origin=0x%x", origin); - audit_log_end(ab); -} - -void five_audit_hexinfo(struct file *file, const char *msg, char *data, - size_t data_length) -{ - struct audit_buffer *ab; - struct inode *inode = NULL; - const unsigned char *fname = NULL; - char filename[NAME_MAX]; - char *pathbuf = NULL; - struct integrity_iint_cache *iint = NULL; - - if (file) { - fname = five_d_path(&file->f_path, &pathbuf, filename); - inode = file_inode(file); - } - - ab = audit_log_start(current->audit_context, GFP_KERNEL, - AUDIT_INTEGRITY_DATA); - if (unlikely(!ab)) { - pr_err("Can't get a context of audit logs\n"); - goto exit; - } - - if (fname) { - audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, fname); - } - if (inode) { - audit_log_format(ab, " i_version=%llu ", - inode_query_iversion(inode)); - - iint = integrity_inode_get(inode); - if (iint) { - audit_log_format(ab, " cache_value=%lu ", - iint->five_flags); - audit_log_format(ab, " five_status=%d ", - five_get_cache_status(iint)); - audit_log_format(ab, " version=%llu ", - (unsigned long long)iint->version); - } - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) - audit_log_format(ab, "%s", msg); -#else - audit_log_string(ab, msg); -#endif - audit_log_n_hex(ab, data, data_length); - audit_log_end(ab); -exit: - if (pathbuf) - __putname(pathbuf); -} diff --git a/security/samsung/five/five_audit.h b/security/samsung/five/five_audit.h deleted file mode 100755 index e0838399a..000000000 --- a/security/samsung/five/five_audit.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Audit calls for FIVE audit subsystem. - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_AUDIT_H -#define __LINUX_FIVE_AUDIT_H - -#include <linux/task_integrity.h> - -void five_audit_verbose(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); -void five_audit_info(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); -void five_audit_err(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); -void five_audit_sign_err(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); -void five_audit_tee_msg(const char *func, const char *cause, int rc, - uint32_t origin); - -void five_audit_hexinfo(struct file *file, - const char *msg, char *data, size_t data_length); - -#endif diff --git a/security/samsung/five/five_cache.c b/security/samsung/five/five_cache.c deleted file mode 100755 index c23f6028c..000000000 --- a/security/samsung/five/five_cache.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * FIVE cache functions - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "five_cache.h" -#include "five_porting.h" - -enum five_file_integrity five_get_cache_status( - const struct integrity_iint_cache *iint) -{ - if (unlikely(!iint)) - return FIVE_FILE_UNKNOWN; - - if (!inode_eq_iversion(iint->inode, iint->version)) - return FIVE_FILE_UNKNOWN; - - return iint->five_status; -} - -void five_set_cache_status(struct integrity_iint_cache *iint, - enum five_file_integrity status) -{ - if (unlikely(!iint)) - return; - - iint->version = inode_query_iversion(iint->inode); - iint->five_status = status; -} - diff --git a/security/samsung/five/five_cache.h b/security/samsung/five/five_cache.h deleted file mode 100755 index a40bfa019..000000000 --- a/security/samsung/five/five_cache.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * FIVE cache functions - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_CACHE_H -#define __LINUX_FIVE_CACHE_H - -#include "security/integrity/integrity.h" - -enum five_file_integrity five_get_cache_status( - const struct integrity_iint_cache *iint); -void five_set_cache_status(struct integrity_iint_cache *iint, - enum five_file_integrity status); - -#endif // __LINUX_FIVE_CACHE_H diff --git a/security/samsung/five/five_cert.c b/security/samsung/five/five_cert.c deleted file mode 100755 index c523374e1..000000000 --- a/security/samsung/five/five_cert.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This code is originated from Samsung Electronics proprietary sources. - * Author: Viacheslav Vovchenko, <v.vovchenko@samsung.com> - * Created: 10 Jul 2017 - * - * Copyright (C) 2016 Samsung Electronics, Inc. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include "five_crypto.h" -#include "five_cert.h" - -int five_cert_body_alloc(struct five_cert_header *header, - uint8_t *hash, size_t hash_len, - uint8_t *label, size_t label_len, - uint8_t **raw_cert, size_t *raw_cert_len) -{ - size_t data_len; - uint8_t *data; - struct lv *next; - const void *end; - int rc = 0; - struct five_cert_body body_cert = {0}; - - if (unlikely(!header || !raw_cert || !raw_cert_len)) - return -EINVAL; - - data_len = sizeof(*body_cert.header) + sizeof(*header) + - sizeof(*body_cert.hash) + hash_len + - sizeof(*body_cert.label) + label_len; - - if (unlikely(data_len > FIVE_MAX_CERTIFICATE_SIZE)) - return -EINVAL; - - data = kzalloc(data_len, GFP_NOFS); - if (unlikely(!data)) - return -ENOMEM; - - next = body_cert.header = (struct lv *)data; - end = data + data_len; - - /* Fill header data */ - rc = lv_set(next, header, sizeof(*header), end); - if (unlikely(rc)) - goto exit; - next = body_cert.hash = lv_get_next(next, end); - if (unlikely(!next)) - goto exit; - - /* Fill hash data */ - rc = lv_set(next, hash, hash_len, end); - if (unlikely(rc)) - goto exit; - next = body_cert.label = lv_get_next(next, end); - if (unlikely(!next)) - goto exit; - - /* Fill label data */ - rc = lv_set(next, label, label_len, end); - if (unlikely(rc)) - goto exit; - -exit: - if (likely(!rc)) { - *raw_cert = data; - *raw_cert_len = data_len; - } else { - kfree(data); - } - - return rc; -} - -void five_cert_free(void *raw_cert) -{ - kfree(raw_cert); -} - -int five_cert_append_signature(void **raw_cert, size_t *raw_cert_len, - void *signature, size_t signature_len) -{ - int rc = 0; - void *new_raw_cert; - size_t new_raw_cert_len; - const void *end; - struct five_cert cert = { {0} }; - - if (unlikely(!raw_cert || !raw_cert_len || !signature)) - return -EINVAL; - - new_raw_cert_len = *raw_cert_len + sizeof(cert.signature->length) + - signature_len; - if (unlikely(new_raw_cert_len > FIVE_MAX_CERTIFICATE_SIZE)) - return -EINVAL; - - new_raw_cert = krealloc(*raw_cert, new_raw_cert_len, GFP_NOFS); - if (unlikely(!new_raw_cert)) - return -ENOMEM; - - *raw_cert = new_raw_cert; - *raw_cert_len = new_raw_cert_len; - end = (uint8_t *)new_raw_cert + new_raw_cert_len; - - rc = five_cert_fillout(&cert, new_raw_cert, new_raw_cert_len); - if (unlikely(rc)) - return rc; - - rc = lv_set(cert.signature, signature, signature_len, end); - - return rc; -} - -int five_cert_body_fillout(struct five_cert_body *body_cert, - const void *raw_cert, size_t raw_cert_len) -{ - struct lv *next; - const void *end; - struct five_cert_header *hdr; - - if (unlikely(!body_cert || !raw_cert || - raw_cert_len > FIVE_MAX_CERTIFICATE_SIZE)) - return -EINVAL; - - next = body_cert->header = (struct lv *)raw_cert; - end = (uint8_t *)raw_cert + raw_cert_len; - - /* Check if we had an error at the previous step */ - if (!lv_get_next(next, end)) - return -EINVAL; - - if (sizeof(*hdr) != body_cert->header->length) - return -EINVAL; - - hdr = (struct five_cert_header *)body_cert->header->value; - if (hdr->version != FIVE_CERT_VERSION1) - return -EINVAL; - - next = body_cert->hash = lv_get_next(next, end); - if (unlikely(!next)) - return -EINVAL; - - next = body_cert->label = lv_get_next(next, end); - if (unlikely(!next)) - return -EINVAL; - - return 0; -} - -int five_cert_fillout(struct five_cert *cert, const void *raw_cert, - size_t raw_cert_len) -{ - int rc; - struct lv *next; - const void *end; - - if (unlikely(!cert || !raw_cert)) - return -EINVAL; - - if (unlikely(raw_cert_len > FIVE_MAX_CERTIFICATE_SIZE)) - return -EINVAL; - - rc = five_cert_body_fillout(&cert->body, raw_cert, raw_cert_len); - if (unlikely(rc)) - return rc; - - next = cert->body.label; - end = (uint8_t *)raw_cert + raw_cert_len; - - if (!lv_get_next(next, end)) - return -EINVAL; - - next = cert->signature = lv_get_next(next, end); - if (unlikely(!next)) - return -EINVAL; - - return 0; -} - -int five_cert_calc_hash(struct five_cert_body *body_cert, uint8_t *out_hash, - size_t *out_hash_len) -{ - int rc; - size_t hash_len, body_len; - struct five_cert_header *header; - - if (unlikely(!body_cert || !out_hash || !out_hash_len)) - return -EINVAL; - - hash_len = *out_hash_len; - header = (struct five_cert_header *)body_cert->header->value; - body_len = sizeof(*body_cert->header) + body_cert->header->length + - sizeof(*body_cert->hash) + body_cert->hash->length + - sizeof(*body_cert->label) + body_cert->label->length; - - if (unlikely(body_len > FIVE_MAX_CERTIFICATE_SIZE)) - return -EINVAL; - - rc = five_calc_data_hash((const uint8_t *)body_cert->header, body_len, - header->hash_algo, out_hash, &hash_len); - if (unlikely(rc)) - return rc; - - *out_hash_len = hash_len; - - return 0; -} diff --git a/security/samsung/five/five_cert.h b/security/samsung/five/five_cert.h deleted file mode 100755 index e3b9e6845..000000000 --- a/security/samsung/five/five_cert.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This code is originated from Samsung Electronics proprietary sources. - * Author: Viacheslav Vovchenko, <v.vovchenko@samsung.com> - * Created: 10 Jul 2017 - * - * Copyright (C) 2016 Samsung Electronics, Inc. - */ - -#ifndef __FIVE_CERT_H__ -#define __FIVE_CERT_H__ - -#include "five_lv.h" - -#define FIVE_MAX_DIGEST_SIZE 64 -#define FIVE_MAX_CERTIFICATE_SIZE 4096 - -enum five_signature_type { - FIVE_XATTR_NONE = 0x00, - FIVE_XATTR_DIGSIG = 0x01, - FIVE_XATTR_HMAC = 0x02, - FIVE_XATTR_END -}; - -enum five_version { - FIVE_CERT_VERSION1 = 1 -}; - -enum five_privilege { - FIVE_PRIV_DEFAULT = 0, - FIVE_PRIV_ALLOW_SIGN -}; - -struct five_cert_header { - uint8_t version; /* signature format version */ - uint8_t signature_type; /* signature type, e.g. HMAC, RSA */ - uint8_t privilege; /* privilege of file saved in certificate */ - uint8_t hash_algo; /* use hash algorithm for file and signature */ - uint32_t key_id; /* use for find key in keyrings */ -} __packed; - -/* - * --------------------------------------------- - * | Raw data of certificate FIVE in memory | - * --------------------------------------------- - * | u16 | header_len | - * | struct five_cert_header | header_value | - * | u16 | hash_len | - * | array | hash_value | - * | u16 | label_len | - * | array | label_value | - * | u16 | signature_len | - * | array | signature_value | - * --------------------------------------------- - */ -struct five_cert { - struct five_cert_body { - struct lv *header; - struct lv *hash; - struct lv *label; - } body; - struct lv *signature; -}; - -/** - * Allocates and fills raw certificate buffer without signature. - * Call five_cert_free() to release the allocated buffer. - * Returns 0 on success, otherwise - error. - */ -int five_cert_body_alloc(struct five_cert_header *header, - uint8_t *hash, size_t hash_len, - uint8_t *label, size_t label_len, - uint8_t **raw_cert, size_t *raw_cert_len); - -/** - * Releases raw certificate buffer allocated previously by five_cert_alloc(). - */ -void five_cert_free(void *raw_cert); - -/** - * Appends signature to raw certificate buffer. raw_cert memory will be - * re-allocated to contain the signature. - * Returns 0 on success, otherwise - error - */ -int five_cert_append_signature(void **raw_cert, size_t *raw_cert_len, - void *signature, size_t signature_len); - -/** - * Parse certificate raw data and fill items helper body_cert structure. - * Notice, body_cert object is reference to data of raw_cert. It will valid - * until raw_cert memory is valid. - * In case of raw_cert is changed we should be update body_cert again. - * Returns 0 on success, otherwise - error. - */ -int five_cert_body_fillout(struct five_cert_body *body_cert, - const void *raw_cert, size_t raw_cert_len); - -/** - * Parse certificate raw data and fill items helper cert structure. - * Notice, cert object is reference to data of raw_cert. It will valid until - * raw_cert memory is valid. - * In case of raw_cert is changed we should be update cert again. - * Returns 0 on success, otherwise - error. - */ -int five_cert_fillout(struct five_cert *cert, const void *raw_cert, - size_t raw_cert_len); - -/** - * Calculates hash of certificate, that contains header structure, - * hash and label. - * Returns 0 on success, otherwise - error. - */ -int five_cert_calc_hash(struct five_cert_body *body_cert, uint8_t *out_hash, - size_t *out_hash_len); - -#endif /* __FIVE_CERT_H__ */ diff --git a/security/samsung/five/five_cert_builtin.S b/security/samsung/five/five_cert_builtin.S deleted file mode 100755 index 122db3813..000000000 --- a/security/samsung/five/five_cert_builtin.S +++ /dev/null @@ -1,43 +0,0 @@ -/* - * five_cert_builtin.S - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/export.h> -#include <linux/init.h> -#include <linux/version.h> - - __INITRODATA - -.align 8 - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) -#define VMLINUX_SYMBOL(name) name -#endif - -#define GLOBAL(name) \ - .globl VMLINUX_SYMBOL(name); \ - VMLINUX_SYMBOL(name): - -#ifdef CONFIG_FIVE_CERT_ENG -GLOBAL(five_local_ca_start_eng) - .incbin CONFIG_FIVE_CERT_ENG -GLOBAL(five_local_ca_end_eng) -#endif - -#ifdef CONFIG_FIVE_CERT_USER -GLOBAL(five_local_ca_start_user) - .incbin CONFIG_FIVE_CERT_USER -GLOBAL(five_local_ca_end_user) -#endif diff --git a/security/samsung/five/five_crypto.c b/security/samsung/five/five_crypto.c deleted file mode 100755 index 5ba1d0207..000000000 --- a/security/samsung/five/five_crypto.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/moduleparam.h> -#include <linux/ratelimit.h> -#include <linux/file.h> -#include <linux/crypto.h> -#include <linux/scatterlist.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <crypto/hash.h> -#include <crypto/hash_info.h> -#include <linux/freezer.h> -#include "five.h" -#include "five_crypto_comp.h" -#include "five_porting.h" -#include "security/integrity/integrity.h" -#include "five_testing.h" - -struct ahash_completion { - struct completion completion; - int err; -}; - -/* minimum file size for ahash use */ -static unsigned long five_ahash_minsize; -module_param_named(ahash_minsize, five_ahash_minsize, ulong, 0644); -MODULE_PARM_DESC(ahash_minsize, "Minimum file size for ahash use"); - -/* default is 0 - 1 page. */ -static int five_maxorder; -static unsigned long five_bufsize = PAGE_SIZE; - -__visible_for_testing __mockable struct crypto_shash *call_crypto_alloc_shash( - const char *alg_name, u32 type, u32 mask) -{ - return crypto_alloc_shash(alg_name, type, mask); -} - -static int param_set_bufsize(const char *val, const struct kernel_param *kp) -{ - unsigned long long size; - int order; - - size = memparse(val, NULL); - order = get_order(size); - if (order >= MAX_ORDER) - return -EINVAL; - five_maxorder = order; - five_bufsize = PAGE_SIZE << order; - return 0; -} - -static const struct kernel_param_ops param_ops_bufsize = { - .set = param_set_bufsize, - .get = param_get_uint, -}; - -#define param_check_bufsize(name, p) __param_check(name, p, unsigned int) - -module_param_named(ahash_bufsize, five_bufsize, ulong, 0644); -MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size"); - -static struct crypto_shash *five_shash_tfm; -static struct crypto_ahash *five_ahash_tfm; - -int __init five_init_crypto(void) -{ - long rc; - - five_shash_tfm = call_crypto_alloc_shash( - hash_algo_name[five_hash_algo], 0, 0); - if (IS_ERR(five_shash_tfm)) { - rc = PTR_ERR(five_shash_tfm); - pr_err("Can not allocate %s (reason: %ld)\n", - hash_algo_name[five_hash_algo], rc); - return rc; - } - return 0; -} - -static struct crypto_shash *five_alloc_tfm(enum hash_algo algo) -{ - struct crypto_shash *tfm = five_shash_tfm; - int rc; - - if (algo < 0 || algo >= HASH_ALGO__LAST) - algo = five_hash_algo; - - if (algo != five_hash_algo) { - tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); - if (IS_ERR(tfm)) { - rc = PTR_ERR(tfm); - pr_err("Can not allocate %s (reason: %d)\n", - hash_algo_name[algo], rc); - } - } - return tfm; -} - -static void five_free_tfm(struct crypto_shash *tfm) -{ - if (tfm != five_shash_tfm) - crypto_free_shash(tfm); -} - -/** - * five_alloc_pages() - Allocate contiguous pages. - * @max_size: Maximum amount of memory to allocate. - * @allocated_size: Returned size of actual allocation. - * @last_warn: Should the min_size allocation warn or not. - * - * Tries to do opportunistic allocation for memory first trying to allocate - * max_size amount of memory and then splitting that until zero order is - * reached. Allocation is tried without generating allocation warnings unless - * last_warn is set. Last_warn set affects only last allocation of zero order. - * - * By default, five_maxorder is 0 and it is equivalent to kmalloc(GFP_KERNEL) - * - * Return pointer to allocated memory, or NULL on failure. - */ -static void *five_alloc_pages(loff_t max_size, size_t *allocated_size, - int last_warn) -{ - void *ptr; - int order = five_maxorder; - gfp_t gfp_mask = __GFP_RECLAIM | __GFP_NOWARN | __GFP_NORETRY; - - if (order) - order = min(get_order(max_size), order); - - for (; order; order--) { - ptr = (void *)__get_free_pages(gfp_mask, order); - if (ptr) { - *allocated_size = PAGE_SIZE << order; - return ptr; - } - } - - /* order is zero - one page */ - - gfp_mask = GFP_KERNEL; - - if (!last_warn) - gfp_mask |= __GFP_NOWARN; - - ptr = (void *)__get_free_pages(gfp_mask, 0); - if (ptr) { - *allocated_size = PAGE_SIZE; - return ptr; - } - - *allocated_size = 0; - return NULL; -} - -/** - * five_free_pages() - Free pages allocated by five_alloc_pages(). - * @ptr: Pointer to allocated pages. - * @size: Size of allocated buffer. - */ -static void five_free_pages(void *ptr, size_t size) -{ - if (!ptr) - return; - free_pages((unsigned long)ptr, get_order(size)); -} - -static struct crypto_ahash *five_alloc_atfm(enum hash_algo algo) -{ - struct crypto_ahash *tfm = five_ahash_tfm; - int rc; - - if (algo < 0 || algo >= HASH_ALGO__LAST) - algo = five_hash_algo; - - if (algo != five_hash_algo || !tfm) { - tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0); - if (!IS_ERR(tfm)) { - if (algo == five_hash_algo) - five_ahash_tfm = tfm; - } else { - rc = PTR_ERR(tfm); - pr_err("Can not allocate %s (reason: %d)\n", - hash_algo_name[algo], rc); - } - } - return tfm; -} - -static void five_free_atfm(struct crypto_ahash *tfm) -{ - if (tfm != five_ahash_tfm) - crypto_free_ahash(tfm); -} - -static void ahash_complete(struct crypto_async_request *req, int err) -{ - struct ahash_completion *res = req->data; - - if (err == -EINPROGRESS) - return; - res->err = err; - complete(&res->completion); -} - -static int ahash_wait(int err, struct ahash_completion *res) -{ - try_to_freeze(); - - switch (err) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&res->completion); - reinit_completion(&res->completion); - err = res->err; - fallthrough; - default: - pr_crit_ratelimited("ahash calculation failed: err: %d\n", err); - } - - return err; -} - -static int five_calc_file_hash_atfm(struct file *file, - u8 *hash, size_t *hash_len, - struct crypto_ahash *tfm) -{ - const size_t len = crypto_ahash_digestsize(tfm); - loff_t i_size, offset; - char *rbuf[2] = { NULL, }; - int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0; - struct ahash_request *req; - struct scatterlist sg[1]; - struct ahash_completion res; - size_t rbuf_size[2]; - - if (*hash_len < len) - return -EINVAL; - - req = ahash_request_alloc(tfm, GFP_KERNEL); - if (!req) - return -ENOMEM; - - init_completion(&res.completion); - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - ahash_complete, &res); - - rc = ahash_wait(crypto_ahash_init(req), &res); - if (rc) - goto out1; - - i_size = i_size_read(file_inode(file)); - - if (i_size == 0) - goto out2; - - /* - * Try to allocate maximum size of memory. - * Fail if even a single page cannot be allocated. - */ - rbuf[0] = five_alloc_pages(i_size, &rbuf_size[0], 1); - if (!rbuf[0]) { - rc = -ENOMEM; - goto out1; - } - - /* Only allocate one buffer if that is enough. */ - if (i_size > rbuf_size[0]) { - /* - * Try to allocate secondary buffer. If that fails fallback to - * using single buffering. Use previous memory allocation size - * as baseline for possible allocation size. - */ - rbuf[1] = five_alloc_pages(i_size - rbuf_size[0], - &rbuf_size[1], 0); - } - - if (!(file->f_mode & FMODE_READ)) { - file->f_mode |= FMODE_READ; - read = 1; - } - - for (offset = 0; offset < i_size; offset += rbuf_len) { - if (!rbuf[1] && offset) { - /* Not using two buffers, and it is not the first - * read/request, wait for the completion of the - * previous ahash_update() request. - */ - rc = ahash_wait(ahash_rc, &res); - if (rc) - goto out3; - } - /* read buffer */ - rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]); - rc = integrity_kernel_read(file, offset, rbuf[active], - rbuf_len); - if (rc != rbuf_len) - goto out3; - - if (rbuf[1] && offset) { - /* Using two buffers, and it is not the first - * read/request, wait for the completion of the - * previous ahash_update() request. - */ - rc = ahash_wait(ahash_rc, &res); - if (rc) - goto out3; - } - - sg_init_one(&sg[0], rbuf[active], rbuf_len); - ahash_request_set_crypt(req, sg, NULL, rbuf_len); - - ahash_rc = crypto_ahash_update(req); - - if (rbuf[1]) - active = !active; /* swap buffers, if we use two */ - } - /* wait for the last update request to complete */ - rc = ahash_wait(ahash_rc, &res); -out3: - if (read) - file->f_mode &= ~FMODE_READ; - five_free_pages(rbuf[0], rbuf_size[0]); - five_free_pages(rbuf[1], rbuf_size[1]); -out2: - if (!rc) { - ahash_request_set_crypt(req, NULL, hash, 0); - rc = ahash_wait(crypto_ahash_final(req), &res); - if (!rc) - *hash_len = len; - } -out1: - ahash_request_free(req); - return rc; -} - -static int five_calc_file_ahash(struct file *file, - u8 hash_algo, u8 *hash, - size_t *hash_len) -{ - struct crypto_ahash *tfm; - int rc; - - tfm = five_alloc_atfm(hash_algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - rc = five_calc_file_hash_atfm(file, hash, hash_len, tfm); - - five_free_atfm(tfm); - - return rc; -} - -static int five_calc_file_hash_tfm(struct file *file, - u8 *hash, size_t *hash_len, - struct crypto_shash *tfm) -{ - SHASH_DESC_ON_STACK(shash, tfm); - const size_t len = crypto_shash_digestsize(tfm); - loff_t i_size, offset = 0; - char *rbuf; - int rc, read = 0; - - if (*hash_len < len) - return -EINVAL; - - shash->tfm = tfm; - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) - shash->flags = 0; - #endif - - rc = crypto_shash_init(shash); - if (rc != 0) - return rc; - - i_size = i_size_read(file_inode(file)); - - if (i_size == 0) - goto out; - - rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); - if (!rbuf) - return -ENOMEM; - - if (!(file->f_mode & FMODE_READ)) { - file->f_mode |= FMODE_READ; - read = 1; - } - - while (offset < i_size) { - int rbuf_len; - - rbuf_len = integrity_kernel_read(file, offset, rbuf, PAGE_SIZE); - if (rbuf_len < 0) { - rc = rbuf_len; - break; - } - if (rbuf_len == 0) - break; - offset += rbuf_len; - - try_to_freeze(); - - rc = crypto_shash_update(shash, rbuf, rbuf_len); - if (rc) - break; - } - if (read) - file->f_mode &= ~FMODE_READ; - kfree(rbuf); -out: - if (!rc) - rc = crypto_shash_final(shash, hash); - - if (!rc) - *hash_len = len; - - return rc; -} - -static int five_calc_hash_tfm(const u8 *data, size_t data_len, - u8 *hash, size_t *hash_len, struct crypto_shash *tfm) -{ - SHASH_DESC_ON_STACK(shash, tfm); - const size_t len = crypto_shash_digestsize(tfm); - int rc; - - if (*hash_len < len || data_len == 0) - return -EINVAL; - - shash->tfm = tfm; - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) - shash->flags = 0; - #endif - - rc = crypto_shash_init(shash); - if (rc != 0) - return rc; - - rc = crypto_shash_update(shash, data, data_len); - if (!rc) { - rc = crypto_shash_final(shash, hash); - - if (!rc) - *hash_len = len; - } - - return rc; -} - -static int five_calc_file_shash(struct file *file, - u8 hash_algo, - u8 *hash, - size_t *hash_len) -{ - struct crypto_shash *tfm; - int rc; - - tfm = five_alloc_tfm(hash_algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - rc = five_calc_file_hash_tfm(file, hash, hash_len, tfm); - - five_free_tfm(tfm); - - return rc; -} - -static int five_calc_data_shash(const u8 *data, size_t data_len, u8 hash_algo, - u8 *hash, size_t *hash_len) -{ - struct crypto_shash *tfm; - int rc; - - tfm = five_alloc_tfm(hash_algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - rc = five_calc_hash_tfm(data, data_len, hash, hash_len, tfm); - - five_free_tfm(tfm); - - return rc; -} - -/* - * five_calc_file_hash - calculate file hash - * - * Asynchronous hash (ahash) allows using HW acceleration for calculating - * a hash. ahash performance varies for different data sizes on different - * crypto accelerators. shash performance might be better for smaller files. - * The 'five.ahash_minsize' module parameter allows specifying the best - * minimum file size for using ahash on the system. - * - * If the five.ahash_minsize parameter is not specified, this function uses - * shash for the hash calculation. If ahash fails, it falls back to using - * shash. - */ -int five_calc_file_hash(struct file *file, u8 hash_algo, u8 *hash, - size_t *hash_len) -{ - loff_t i_size; - int rc; - - i_size = i_size_read(file_inode(file)); - - if (five_ahash_minsize && i_size >= five_ahash_minsize) { - rc = five_calc_file_ahash(file, hash_algo, hash, hash_len); - if (!rc) - return 0; - } - - return five_calc_file_shash(file, hash_algo, hash, hash_len); -} - -int five_calc_data_hash(const uint8_t *data, size_t data_len, - uint8_t hash_algo, uint8_t *hash, size_t *hash_len) -{ - return five_calc_data_shash(data, data_len, hash_algo, hash, hash_len); -} diff --git a/security/samsung/five/five_crypto.h b/security/samsung/five/five_crypto.h deleted file mode 100755 index 1f675a3b0..000000000 --- a/security/samsung/five/five_crypto.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * FIVE crypto API - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_CRYPTO_H -#define __LINUX_FIVE_CRYPTO_H - -#include <linux/file.h> - -int five_init_crypto(void); -int five_calc_file_hash(struct file *file, u8 hash_algo, u8 *hash, - size_t *hash_len); - -int five_calc_data_hash(const uint8_t *data, size_t data_len, - uint8_t hash_algo, uint8_t *hash, size_t *hash_len); - -#endif // __LINUX_FIVE_CRYPTO_H diff --git a/security/samsung/five/five_crypto_comp.h b/security/samsung/five/five_crypto_comp.h deleted file mode 100755 index c93e65220..000000000 --- a/security/samsung/five/five_crypto_comp.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Wrappers for backward compatibility with old Kernels. - * - * Copyright (C) 2019 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_CRYPTO_COMP_H -#define __LINUX_FIVE_CRYPTO_COMP_H - -#include <linux/version.h> -#include <crypto/public_key.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) -static inline int five_verify_signature(struct key *key, - struct public_key_signature *pks, - struct five_cert *cert, - struct five_cert_header *header) -{ - int ret = -ENOMEM; - - pks->pkey_hash_algo = header->hash_algo; - pks->nr_mpi = 1; - pks->rsa.s = mpi_read_raw_data(cert->signature->value, - cert->signature->length); - - if (pks->rsa.s) - ret = verify_signature(key, pks); - - mpi_free(pks->rsa.s); - - return ret; -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) -static inline int five_verify_signature(struct key *key, - struct public_key_signature *pks, - struct five_cert *cert, - struct five_cert_header *header) -{ - int ret = -ENOMEM; - - pks->pkey_algo = "rsa"; - pks->hash_algo = hash_algo_name[header->hash_algo]; - pks->s = cert->signature->value; - pks->s_size = cert->signature->length; - - ret = verify_signature(key, pks); - - return ret; -} -#else -static inline int five_verify_signature(struct key *key, - struct public_key_signature *pks, - struct five_cert *cert, - struct five_cert_header *header) -{ - int ret = -ENOMEM; - - pks->pkey_algo = "rsa"; - pks->encoding = "pkcs1"; - pks->hash_algo = hash_algo_name[header->hash_algo]; - pks->s = cert->signature->value; - pks->s_size = cert->signature->length; - - ret = verify_signature(key, pks); - - return ret; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) -static inline struct key *five_keyring_alloc(const char *description, - kuid_t uid, kgid_t gid, const struct cred *cred, - key_perm_t perm, unsigned long flags) -{ - return keyring_alloc(description, uid, gid, cred, - perm, flags, NULL); -} -#else -static inline struct key *five_keyring_alloc(const char *description, - kuid_t uid, kgid_t gid, const struct cred *cred, - key_perm_t perm, unsigned long flags) -{ - return keyring_alloc(description, uid, gid, cred, - perm, flags, NULL, NULL); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0) -#define keyring_search(keyring, type, desc, recurse) \ - keyring_search(keyring, type, desc) -#endif - -#endif /* __LINUX_FIVE_CRYPTO_COMP_H */ diff --git a/security/samsung/five/five_dmverity.c b/security/samsung/five/five_dmverity.c deleted file mode 100755 index 20ae6bac2..000000000 --- a/security/samsung/five/five_dmverity.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * FIVE dmverity functions - * - * Copyright (C) 2019 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "five_dmverity.h" -#include "five.h" -#include "five_testing.h" -#include "five_porting.h" - -#include "drivers/md/dm.h" - -#ifdef CONFIG_FIVE_DEBUG -#include <linux/debugfs.h> -#endif - -#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) || defined(CONFIG_FIVE_DEBUG) -__visible_for_testing -bool check_prebuilt_paths_dmverity; -#endif - -static inline int __init init_fs(void); - -__visible_for_testing __mockable -struct mapped_device *call_dm_get_md(dev_t dev) -{ - return dm_get_md(dev); -} - -__visible_for_testing __mockable -struct dm_table *call_dm_get_live_table( - struct mapped_device *md, int *srcu_idx) -{ - return dm_get_live_table(md, srcu_idx); -} - -__visible_for_testing __mockable -fmode_t call_dm_table_get_mode(struct dm_table *t) -{ - return dm_table_get_mode(t); -} - -__visible_for_testing __mockable -unsigned int call_dm_table_get_num_targets(struct dm_table *t) -{ - return dm_table_get_num_targets(t); -} - -__visible_for_testing __mockable -struct dm_target *call_dm_table_get_target( - struct dm_table *t, unsigned int index) -{ - return dm_table_get_target(t, index); -} - -__visible_for_testing __mockable -void call_dm_put_live_table(struct mapped_device *md, int srcu_idx) -{ - dm_put_live_table(md, srcu_idx); - return; -} - -__visible_for_testing __mockable -void call_dm_put(struct mapped_device *md) -{ - dm_put(md); - return; -} - -__visible_for_testing __mockable -struct block_device *call_blkdev_get_by_dev( - dev_t dev, fmode_t mode, void *holder) -{ - return blkdev_get_by_dev(dev, mode, holder); -} - -__visible_for_testing __mockable -void call_blkdev_put(struct block_device *bdev, fmode_t mode) -{ - blkdev_put(bdev, mode); - return; -} - -int __init five_init_dmverity(void) -{ - return init_fs(); -} - -__visible_for_testing -bool is_loop_device(const struct file *file) -{ - const struct inode *inode; - - inode = file_inode(file); - if (unlikely(!inode || !inode->i_sb)) - return false; - - return MAJOR(inode->i_sb->s_dev) == LOOP_MAJOR ? true : false; -} - -/* Check whether the file belongs to the device mapper's enabled target - * Need to check: - * - Super block points to a block device. - * - The block device is created by the device mapper - * (dm_get_md/dm_put_md functions). - * - The block device is a disk with a name "dm-[1-9]". - * - The disk is in readonly mode. - * - There is only one enabled target in the device mapper table. - * - The target name is known target name. - */ -__visible_for_testing -enum five_dmverity_codes is_dmverity_partition( - const struct file *file) -{ - const char dm_dev_prefix[] = "dm-"; - const char * const dm_targets_name[] = { - "verity", "verity-fec" - }; - enum five_dmverity_codes result = FIVE_DMV_NO_DM_TARGET_NAME; - int srcu_idx; - unsigned int num_targets; - size_t i; - const struct inode *inode; - struct super_block *i_sb; - struct mapped_device *md; - struct gendisk *disk; - struct dm_table *table; - struct dm_target *target; - - inode = file_inode(file); - if (unlikely(!inode)) { - result = FIVE_DMV_BAD_INPUT; - goto exit; - } - - i_sb = inode->i_sb; - if (unlikely(!i_sb)) { - result = FIVE_DMV_BAD_INPUT; - goto exit; - } - - md = call_dm_get_md(i_sb->s_dev); - if (!md) { - result = FIVE_DMV_NO_DM_DEVICE; - goto exit; - } - - disk = dm_disk(md); - if (!disk) { - result = FIVE_DMV_NO_DM_DISK; - goto exit_free_dm; - } - - if (!get_disk_ro(disk)) { - result = FIVE_DMV_NOT_READONLY_DM_DISK; - goto exit_free_dm; - } - - if (strncmp(disk->disk_name, dm_dev_prefix, - sizeof(dm_dev_prefix) - 1)) { - result = FIVE_DMV_BAD_DM_PREFIX_NAME; - goto exit_free_dm; - } - - table = call_dm_get_live_table(md, &srcu_idx); - if (!table) { - result = FIVE_DMV_NO_DM_TABLE; - goto exit_free_dm; - } - - if (call_dm_table_get_mode(table) & ~FMODE_READ) { - result = FIVE_DMV_NOT_READONLY_DM_TABLE; - goto exit_free_table; - } - - num_targets = call_dm_table_get_num_targets(table); - target = call_dm_table_get_target(table, 0); - if (!target) { - result = FIVE_DMV_NO_DM_TARGET; - goto exit_free_table; - } - - /* Only support devices that have a single target */ - if (num_targets != 1) { - result = FIVE_DMV_NOT_SINGLE_TARGET; - goto exit_free_table; - } - - /* Checks the specific target name from available targets - * in device mapper. - */ - for (i = 0; i < ARRAY_SIZE(dm_targets_name); ++i) { - if (!strncmp(target->type->name, dm_targets_name[i], - strlen(dm_targets_name[i]) + 1)) { - result = FIVE_DMV_PARTITION; - break; - } - } - -exit_free_table: - call_dm_put_live_table(md, srcu_idx); -exit_free_dm: - call_dm_put(md); -exit: - return result; -} - -__visible_for_testing -enum five_dmverity_codes is_dmverity_loop( - const struct file *file) -{ - const fmode_t mode_bdev = FMODE_READ; - enum five_dmverity_codes result = FIVE_DMV_NO_SB_LOOP_DEVICE; - struct super_block *i_sb; - const struct inode *inode; - struct block_device *bdev; - struct gendisk *bd_disk; - struct file *file_mount_to_lo_dev; - struct loop_device *lo_dev; - - inode = file_inode(file); - i_sb = inode->i_sb; - - if (MAJOR(i_sb->s_dev) != LOOP_MAJOR) - goto exit; - - bdev = call_blkdev_get_by_dev(i_sb->s_dev, mode_bdev, NULL); - if (IS_ERR_OR_NULL(bdev) || MAJOR(bdev->bd_dev) != LOOP_MAJOR) { - result = FIVE_DMV_NO_BD_LOOP_DEVICE; - goto exit; - } - - bd_disk = bdev->bd_disk; - if (unlikely(!bd_disk)) { - result = FIVE_DMV_NO_BD_DISK; - goto exit_free_blkdev; - } - - lo_dev = bd_disk->private_data; - if (unlikely(!lo_dev)) { - result = FIVE_DMV_NO_LOOP_DEV; - goto exit_free_blkdev; - } - - file_mount_to_lo_dev = lo_dev->lo_backing_file; - if (unlikely(!file_mount_to_lo_dev)) { - result = FIVE_DMV_NO_LOOP_BACK_FILE; - goto exit_free_blkdev; - } - - result = is_dmverity_partition(file_mount_to_lo_dev); - -exit_free_blkdev: - call_blkdev_put(bdev, mode_bdev); -exit: - return result; -} - -#if defined(CONFIG_SAMSUNG_PRODUCT_SHIP) && !defined(CONFIG_FIVE_DEBUG) -bool five_is_dmverity_protected(const struct file *file) -{ - enum five_dmverity_codes dmv_file_status; - bool result = false; - - if (unlikely(!file)) - return result; - - /* Checks is loop device /dev/block/loopX or no */ - if (is_loop_device(file)) - /* Checks /dev/block/loopX mounted to /apex/name@version and - * it should specify to /system/apex/[name].apex under dmverity - * protection. - */ - dmv_file_status = is_dmverity_loop(file); - else - /* Checks file on dmverity partition, in case of dmverity is - * disabled need to check prebuilt paths of dmverity. - */ - dmv_file_status = is_dmverity_partition(file); - - if (dmv_file_status == FIVE_DMV_PARTITION) - result = true; - - return result; -} -#else -static bool is_dmverity_prebuit_path(const struct file *file) -{ - const char * const paths[] = { - "/system/", "/system_ext/", "/vendor/", "/apex/", - "/product/", "/odm/", "/prism/", "/optics/" - }; - const char *pathname = NULL; - char *pathbuf = NULL; - char filename[NAME_MAX]; - bool result = false; - size_t i; - - pathname = five_d_path(&file->f_path, &pathbuf, filename); - - for (i = 0; i < ARRAY_SIZE(paths); ++i) { - if (!strncmp(pathname, paths[i], strlen(paths[i]))) { - result = true; - break; - } - } - - if (pathbuf) - __putname(pathbuf); - - return result; -} - -bool five_is_dmverity_protected(const struct file *file) -{ - enum five_dmverity_codes dmv_file_status; - bool result = false; - - if (unlikely(!file)) - return result; - - if (check_prebuilt_paths_dmverity) - return is_dmverity_prebuit_path(file); - - /* Checks is loop device /dev/block/loopX or no */ - if (is_loop_device(file)) - /* Checks /dev/block/loopX mounted to /apex/name@version/ and - * it should specify to /system/apex/[name].apex under dmverity - * protection. - */ - dmv_file_status = is_dmverity_loop(file); - else - /* Checks file on dmverity partition, in case of dmverity is - * disabled need to check prebuilt paths dmverity. - */ - dmv_file_status = is_dmverity_partition(file); - - if (dmv_file_status == FIVE_DMV_PARTITION) - result = true; - else - result = is_dmverity_prebuit_path(file); - - return result; -} -#endif - -#ifdef CONFIG_FIVE_DEBUG -static ssize_t five_check_prebuilt_paths_dmverity_read(struct file *file, - char __user *user_buf, size_t count, loff_t *pos) -{ - char buf[2]; - - buf[0] = check_prebuilt_paths_dmverity ? '1' : '0'; - buf[1] = '\n'; - - return simple_read_from_buffer(user_buf, count, pos, buf, sizeof(buf)); -} - -static ssize_t five_check_prebuilt_paths_dmverity_write(struct file *file, - const char __user *buf, size_t count, loff_t *pos) -{ - char command; - - if (get_user(command, buf)) - return -EFAULT; - - switch (command) { - case '0': - check_prebuilt_paths_dmverity = false; - break; - case '1': - check_prebuilt_paths_dmverity = true; - break; - default: - pr_err("FIVE: %s: unknown cmd: %hhx\n", __func__, command); - return -EINVAL; - } - - pr_info("FIVE debug: Check dm-verity file paths %s\n", - check_prebuilt_paths_dmverity ? "enabled" : "disabled"); - return count; -} - -static const struct file_operations five_dmverity_fops = { - .owner = THIS_MODULE, - .read = five_check_prebuilt_paths_dmverity_read, - .write = five_check_prebuilt_paths_dmverity_write -}; - -static inline int __init init_fs(void) -{ - struct dentry *debug_file = NULL; - const umode_t umode = 0664; - - debug_file = debugfs_create_file("five_prebuilt_paths_dmverity", - umode, NULL, NULL, &five_dmverity_fops); - if (IS_ERR_OR_NULL(debug_file)) - goto error; - - return 0; -error: - if (debug_file) - return -PTR_ERR(debug_file); - - return -EEXIST; -} -#else -static inline int __init init_fs(void) -{ - return 0; -} -#endif diff --git a/security/samsung/five/five_dmverity.h b/security/samsung/five/five_dmverity.h deleted file mode 100755 index 93c625403..000000000 --- a/security/samsung/five/five_dmverity.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * FIVE dmverity functions - * - * Copyright (C) 2019 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_DMVERITY_H -#define __LINUX_FIVE_DMVERITY_H - -#include <linux/init.h> - -struct file; - -enum five_dmverity_codes { - FIVE_DMV_PARTITION, - FIVE_DMV_BAD_INPUT, - FIVE_DMV_NO_DM_DEVICE, - FIVE_DMV_NO_DM_DISK, - FIVE_DMV_NOT_READONLY_DM_DISK, - FIVE_DMV_BAD_DM_PREFIX_NAME, - FIVE_DMV_NO_DM_TABLE, - FIVE_DMV_NOT_READONLY_DM_TABLE, - FIVE_DMV_NO_DM_TARGET, - FIVE_DMV_NOT_SINGLE_TARGET, - FIVE_DMV_NO_DM_TARGET_NAME, - FIVE_DMV_NO_SB_LOOP_DEVICE, - FIVE_DMV_NO_BD_LOOP_DEVICE, - FIVE_DMV_NO_BD_DISK, - FIVE_DMV_NO_LOOP_DEV, - FIVE_DMV_NO_LOOP_BACK_FILE -}; - -int __init five_init_dmverity(void); -bool five_is_dmverity_protected(const struct file *file); - -#endif // __LINUX_FIVE_DMVERITY_H diff --git a/security/samsung/five/five_dsms.c b/security/samsung/five/five_dsms.c deleted file mode 100755 index 1d022501b..000000000 --- a/security/samsung/five/five_dsms.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * FIVE-DSMS integration. - * - * Copyright (C) 2020 Samsung Electronics, Inc. - * Yevgen Kopylov, <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/workqueue.h> -#include <linux/string.h> -#include <linux/crc16.h> -#include "five.h" - -#include "five_testing.h" -#ifndef FIVE_KUNIT_ENABLED -#include <linux/dsms.h> -#include "five_dsms.h" -#endif - -#define MESSAGE_BUFFER_SIZE 600 -#define MESSAGE_FIVE_INIT_SIZE 32 -#define DEFERRED_TIME (1000 * 300) -#define MAX_FIV1_NUM 16 -#define MAX_FIV2_NUM 96 - -#define FIV3_FIRST 1 -#define FIV3_FEW 20 -#define FIV3_LOT 100 - -struct sign_err_event { - char comm[TASK_COMM_LEN]; - int result; - int count; -}; - -static struct five_dsms_report_context { - struct delayed_work work; - char message[MESSAGE_FIVE_INIT_SIZE]; -} context; - -static DEFINE_SPINLOCK(five_dsms_lock); -static struct sign_err_event sign_err_events[MAX_FIV1_NUM]; -static bool fiv3_overflow; -static DECLARE_BITMAP(mask, MAX_FIV2_NUM); -static bool oem_unlocking_state __ro_after_init; - -static int __init verifiedboot_state_setup(char *str) -{ - static const char unlocked[] = "orange"; - - oem_unlocking_state = !strncmp(str, unlocked, sizeof(unlocked)); - - if (oem_unlocking_state) - pr_err("FIVE: Device is unlocked\n"); - - return 0; -} - -__setup("androidboot.verifiedbootstate=", verifiedboot_state_setup); - -// proxy to call kernel func -u16 __mockable call_crc16(u16 crc, u8 const *buffer, size_t len) -{ - return crc16(crc, buffer, len); -} - -/*`noinline` is required by DSMS. - * Don't rename this function. File_name/function_name - * is used by DSMS in dsms_whitelist as an access rule. - */ -noinline void __mockable five_dsms_msg(const char *tag, const char *msg) -{ - int ret; - - ret = dsms_send_message(tag, msg, 0); - if (ret) - pr_err("FIVE: unable to send dsms message(result:%d)\n", ret); -} - -static void five_dsms_init_report(struct work_struct *in_data) -{ - struct five_dsms_report_context *context = container_of(in_data, - struct five_dsms_report_context, work.work); - - five_dsms_msg("FIV0", context->message); -} - -void five_dsms_sign_err(const char *app, int result) -{ - int i, current_count; - struct sign_err_event *same_event = NULL; - char dsms_msg[MESSAGE_BUFFER_SIZE]; - bool send_overflow = false; - - spin_lock(&five_dsms_lock); - for (i = 0; i < MAX_FIV1_NUM; i++) { - if (sign_err_events[i].count == 0) { - same_event = &sign_err_events[i]; - current_count = ++same_event->count; - strlcpy(same_event->comm, app, TASK_COMM_LEN); - same_event->result = result; - break; - } else if (sign_err_events[i].result == result && - !strncmp(sign_err_events[i].comm, app, TASK_COMM_LEN)) { - same_event = &sign_err_events[i]; - current_count = ++same_event->count; - break; - } - } - if (!same_event && !fiv3_overflow) { - fiv3_overflow = true; - send_overflow = true; - } - spin_unlock(&five_dsms_lock); - - if (same_event) { - switch (current_count) { - case FIV3_FIRST: - case FIV3_FEW: - case FIV3_LOT: - snprintf(dsms_msg, MESSAGE_BUFFER_SIZE, - "%s res = %d count = %d", same_event->comm, - same_event->result, current_count); - five_dsms_msg("FIV3", dsms_msg); - } - } else if (unlikely(send_overflow)) { - five_dsms_msg("FIV3", "data buffer overflow"); - } -} - -void five_dsms_reset_integrity(const char *task_name, int result, - const char *file_name) -{ - char dsms_msg[MESSAGE_BUFFER_SIZE]; - unsigned short crc; - int msg_size; - bool sent = true; - - if (oem_unlocking_state) - return; - - msg_size = snprintf(dsms_msg, MESSAGE_BUFFER_SIZE, "%s|%d|%s", - task_name, result, file_name ? kbasename(file_name) : ""); - - if (unlikely(msg_size < 0)) { - pr_err("FIVE: unable to create dsms message from task_name: %s, result: %d, file_name: %s\n", - task_name, result, file_name); - return; - } - if (unlikely(msg_size >= MESSAGE_BUFFER_SIZE)) { - pr_warn("FIVE: dsms message size: %d exceeds max buffer size: %d. The tail was truncated! Resulting message is: %s\n", - msg_size, MESSAGE_BUFFER_SIZE, dsms_msg); - msg_size = MESSAGE_BUFFER_SIZE - 1; - } - crc = call_crc16(0, dsms_msg, msg_size) % MAX_FIV2_NUM; - - spin_lock(&five_dsms_lock); - if (!test_bit(crc, mask)) { - sent = false; - set_bit(crc, mask); - } - spin_unlock(&five_dsms_lock); - - if (!sent) - five_dsms_msg("FIV2", dsms_msg); - - return; -} - -void five_dsms_init(const char *version, int result) -{ - snprintf(context.message, MESSAGE_FIVE_INIT_SIZE, "%s", version); - INIT_DELAYED_WORK(&context.work, five_dsms_init_report); - schedule_delayed_work(&context.work, msecs_to_jiffies(DEFERRED_TIME)); -} diff --git a/security/samsung/five/five_dsms.h b/security/samsung/five/five_dsms.h deleted file mode 100755 index f4be82716..000000000 --- a/security/samsung/five/five_dsms.h +++ /dev/null @@ -1,42 +0,0 @@ - -/* - * FIVE-DSMS integration. - * - * Copyright (C) 2020 Samsung Electronics, Inc. - * Yevgen Kopylov, <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_DSMS_H -#define __LINUX_FIVE_DSMS_H - -#ifdef CONFIG_FIVE_DSMS -void five_dsms_sign_err(const char *app, int result); -void five_dsms_reset_integrity(const char *task_name, int result, - const char *file_name); -void five_dsms_init(const char *version, int result); -#else -static inline void five_dsms_sign_err(const char *app, int result) -{ -} - -static inline void five_dsms_reset_integrity(const char *task_name, int result, - const char *file_name) -{ -} - -static inline void five_dsms_init(const char *version, int result) -{ - pr_debug("FIVE: DSMS is not supported\n"); -} -#endif - -#endif diff --git a/security/samsung/five/five_hooks.c b/security/samsung/five/five_hooks.c deleted file mode 100755 index cc01e2ca7..000000000 --- a/security/samsung/five/five_hooks.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Five Event interface - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Ivan Vorobiov, <i.vorobiov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "five_hooks.h" -#include "five_porting.h" -#include "five_testing.h" - -#include <linux/fs.h> -#include <linux/slab.h> - -#define call_void_hook(FUNC, ...) \ - do { \ - struct five_hook_list *P; \ - \ - list_for_each_entry(P, &five_hook_heads.FUNC, list) \ - P->hook.FUNC(__VA_ARGS__); \ - } while (0) - -struct five_hook_heads five_hook_heads = { - .file_processed = - LIST_HEAD_INIT(five_hook_heads.file_processed), - .file_skipped = - LIST_HEAD_INIT(five_hook_heads.file_skipped), - .file_signed = - LIST_HEAD_INIT(five_hook_heads.file_signed), - .task_forked = - LIST_HEAD_INIT(five_hook_heads.task_forked), - .integrity_reset = - LIST_HEAD_INIT(five_hook_heads.integrity_reset), - .integrity_reset2 = - LIST_HEAD_INIT(five_hook_heads.integrity_reset2), -}; -EXPORT_SYMBOL_GPL(five_hook_heads); - -enum five_hook_event { - FILE_PROCESSED, - FILE_SKIPPED, - FILE_SIGNED, - TASK_FORKED, - INTEGRITY_RESET -}; - -struct hook_wq_event { - enum five_hook_event event; - union { - struct { - struct task_struct *task; - enum task_integrity_value tint_value; - struct file *file; - void *xattr; - size_t xattr_size; - int result; - } processed; - struct { - struct task_struct *task; - enum task_integrity_value tint_value; - struct file *file; - } skipped; - struct { - struct task_struct *parent; - enum task_integrity_value parent_tint_value; - struct task_struct *child; - enum task_integrity_value child_tint_value; - } forked; - struct { - struct task_struct *task; - struct file *file; - enum task_integrity_reset_cause cause; - } reset; - }; -}; - -static void hook_wq_event_destroy(struct hook_wq_event *event) -{ - switch (event->event) { - case FILE_PROCESSED: { - fput(event->processed.file); - put_task_struct(event->processed.task); - kfree(event->processed.xattr); - break; - } - case FILE_SKIPPED: { - fput(event->skipped.file); - put_task_struct(event->skipped.task); - break; - } - case FILE_SIGNED: { - fput(event->processed.file); - put_task_struct(event->processed.task); - kfree(event->processed.xattr); - break; - } - case TASK_FORKED: { - put_task_struct(event->forked.parent); - put_task_struct(event->forked.child); - break; - } - case INTEGRITY_RESET: { - if (event->reset.file) - fput(event->reset.file); - put_task_struct(event->reset.task); - break; - } - } -} - -struct hook_wq_context { - struct work_struct data_work; - struct hook_wq_event payload; -}; - -static struct workqueue_struct *g_hook_workqueue; - -static void hook_handler(struct work_struct *in_data) -{ - struct hook_wq_event *event; - struct hook_wq_context *context = container_of(in_data, - struct hook_wq_context, data_work); - - if (unlikely(!context)) - return; - event = &context->payload; - - switch (event->event) { - case FILE_PROCESSED: { - call_void_hook(file_processed, - event->processed.task, - event->processed.tint_value, - event->processed.file, - event->processed.xattr, - event->processed.xattr_size, - event->processed.result); - break; - } - case FILE_SKIPPED: { - call_void_hook(file_skipped, - event->skipped.task, - event->skipped.tint_value, - event->skipped.file); - break; - } - case FILE_SIGNED: { - call_void_hook(file_signed, - event->processed.task, - event->processed.tint_value, - event->processed.file, - event->processed.xattr, - event->processed.xattr_size, - event->processed.result); - break; - } - case TASK_FORKED: { - call_void_hook(task_forked, - event->forked.parent, - event->forked.parent_tint_value, - event->forked.child, - event->forked.child_tint_value); - break; - } - case INTEGRITY_RESET: { - call_void_hook(integrity_reset, - event->reset.task); - call_void_hook(integrity_reset2, event->reset.task, - event->reset.file, event->reset.cause); - break; - } - } - - hook_wq_event_destroy(event); - kfree(context); -} - -static int __push_event(struct hook_wq_event *event, gfp_t flags) -{ - struct hook_wq_context *context; - - if (!g_hook_workqueue) - return -ENAVAIL; - - context = kmalloc(sizeof(struct hook_wq_context), flags); - if (unlikely(!context)) - return -ENOMEM; - - context->payload = *event; - - INIT_WORK(&context->data_work, hook_handler); - return queue_work(g_hook_workqueue, &context->data_work) ? 0 : 1; -} - -void five_hook_file_processed(struct task_struct *task, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - struct hook_wq_event event = {0}; - - event.event = FILE_PROCESSED; - get_task_struct(task); - get_file(file); - event.processed.task = task; - event.processed.tint_value = task_integrity_read(TASK_INTEGRITY(task)); - event.processed.file = file; - /* - * xattr parameters are optional, because FIVE could get results - * from cache where xattr absents, so we may ignore kmemdup errors - */ - if (xattr) { - event.processed.xattr = kmemdup(xattr, xattr_size, GFP_KERNEL); - if (event.processed.xattr) - event.processed.xattr_size = xattr_size; - } - event.processed.result = result; - - if (__push_event(&event, GFP_KERNEL) < 0) - hook_wq_event_destroy(&event); -} - -void five_hook_file_signed(struct task_struct *task, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - struct hook_wq_event event = {0}; - - event.event = FILE_SIGNED; - get_task_struct(task); - get_file(file); - event.processed.task = task; - event.processed.tint_value = task_integrity_read(TASK_INTEGRITY(task)); - event.processed.file = file; - /* xattr parameters are optional, so we may ignore kmemdup errors */ - if (xattr) { - event.processed.xattr = kmemdup(xattr, xattr_size, GFP_KERNEL); - if (event.processed.xattr) - event.processed.xattr_size = xattr_size; - } - event.processed.result = result; - - if (__push_event(&event, GFP_KERNEL) < 0) - hook_wq_event_destroy(&event); -} - -void five_hook_file_skipped(struct task_struct *task, struct file *file) -{ - struct hook_wq_event event = {0}; - - event.event = FILE_SKIPPED; - get_task_struct(task); - get_file(file); - event.skipped.task = task; - event.skipped.tint_value = task_integrity_read(TASK_INTEGRITY(task)); - event.skipped.file = file; - - if (__push_event(&event, GFP_KERNEL) < 0) - hook_wq_event_destroy(&event); -} - -void five_hook_task_forked(struct task_struct *parent, - struct task_struct *child) -{ - struct hook_wq_event event = {0}; - - event.event = TASK_FORKED; - get_task_struct(parent); - get_task_struct(child); - event.forked.parent = parent; - event.forked.parent_tint_value = - task_integrity_read(TASK_INTEGRITY(parent)); - event.forked.child = child; - event.forked.child_tint_value = - task_integrity_read(TASK_INTEGRITY(child)); - - if (__push_event(&event, GFP_ATOMIC) < 0) - hook_wq_event_destroy(&event); -} - -int five_hook_wq_init(void) -{ - g_hook_workqueue = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, "five_hook_wq"); - if (!g_hook_workqueue) - return -ENOMEM; - - return 0; -} - -__mockable -void five_hook_integrity_reset(struct task_struct *task, - struct file *file, - enum task_integrity_reset_cause cause) -{ - struct hook_wq_event event = {0}; - - if (task == NULL) - return; - - event.event = INTEGRITY_RESET; - get_task_struct(task); - if (file) - get_file(file); - event.reset.task = task; - event.reset.file = file; - event.reset.cause = cause; - - if (__push_event(&event, GFP_KERNEL) < 0) - hook_wq_event_destroy(&event); -} diff --git a/security/samsung/five/five_hooks.h b/security/samsung/five/five_hooks.h deleted file mode 100755 index 78b6dfb49..000000000 --- a/security/samsung/five/five_hooks.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Five Event interface - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Ivan Vorobiov, <i.vorobiov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _FIVE_HOOKS_H -#define _FIVE_HOOKS_H - -#include <linux/file.h> -#include <linux/rculist.h> -#include <linux/sched.h> -#include <linux/task_integrity.h> - -void five_hook_file_processed(struct task_struct *task, - struct file *file, void *xattr, - size_t xattr_size, int result); - -void five_hook_task_forked(struct task_struct *parent, - struct task_struct *child); - -void five_hook_file_skipped(struct task_struct *task, - struct file *file); - -void five_hook_file_signed(struct task_struct *task, - struct file *file, void *xattr, - size_t xattr_size, int result); - -void five_hook_integrity_reset(struct task_struct *task, - struct file *file, - enum task_integrity_reset_cause cause); - -union five_list_options { - void (*file_processed)(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, - void *xattr, - size_t xattr_size, - int result); - - void (*file_skipped)(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file); - - void (*task_forked)(struct task_struct *parent, - enum task_integrity_value parent_tint_value, - struct task_struct *child, - enum task_integrity_value child_tint_value); - - void (*file_signed)(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result); - void (*integrity_reset)(struct task_struct *task); - void (*integrity_reset2)(struct task_struct *task, - struct file *file, - enum task_integrity_reset_cause cause); -}; - -struct five_hook_heads { - struct list_head file_processed; - struct list_head file_skipped; - struct list_head file_signed; - struct list_head task_forked; - struct list_head integrity_reset; - struct list_head integrity_reset2; -}; - -/* - * FIVE module hook list structure. - * For use with generic list macros for common operations. - */ -struct five_hook_list { - struct list_head list; - struct list_head *head; - union five_list_options hook; -}; - -/* - * Initializing a five_hook_list structure takes - * up a lot of space in a source file. This macro takes - * care of the common case and reduces the amount of - * text involved. - */ -#define FIVE_HOOK_INIT(HEAD, HOOK) \ - { .head = &five_hook_heads.HEAD, .hook = { .HEAD = HOOK } } - -extern struct five_hook_heads five_hook_heads; - -static inline void five_add_hooks(struct five_hook_list *hooks, - int count) -{ - int i; - - for (i = 0; i < count; i++) - list_add_tail_rcu(&hooks[i].list, hooks[i].head); -} - -int five_hook_wq_init(void); - -#endif /* _FIVE_HOOKS_H */ diff --git a/security/samsung/five/five_init.c b/security/samsung/five/five_init.c deleted file mode 100755 index b46c3c464..000000000 --- a/security/samsung/five/five_init.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <crypto/hash_info.h> -#include "five.h" - -int __init five_init(void) -{ - int rc; - - rc = five_keyring_init(); - if (rc) - return rc; - rc = five_load_built_x509(); - if (rc) - return rc; - rc = five_init_crypto(); - - return rc; -} diff --git a/security/samsung/five/five_keyring.c b/security/samsung/five/five_keyring.c deleted file mode 100755 index 92a691a5f..000000000 --- a/security/samsung/five/five_keyring.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * FIVE keyring - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Yevgen Kopylov, <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/key-type.h> -#include <crypto/public_key.h> -#include <keys/asymmetric-type.h> -#include <crypto/hash_info.h> -#include "five.h" -#include "five_crypto_comp.h" -#include "five_porting.h" -#include "five_testing.h" - -__visible_for_testing -struct key *five_keyring; - -#ifndef CONFIG_FIVE_TRUSTED_KEYRING -__visible_for_testing -const char *five_keyring_name = "_five"; -#else -__visible_for_testing -const char *five_keyring_name = ".five"; -#endif - -__visible_for_testing __mockable -key_ref_t call_keyring_search( - key_ref_t keyring, struct key_type *type, - const char *description, bool recurse) -{ - return keyring_search(keyring, type, description, recurse); -} - -__visible_for_testing __mockable -struct key *call_request_key(struct key_type *type, - const char *description, - const char *callout_info) -{ - return request_key(type, description, callout_info); -} - -__visible_for_testing __mockable -key_ref_t call_key_create_or_update( - key_ref_t keyring_ref, - const char *type, - const char *description, - const void *payload, - size_t plen, - key_perm_t perm, - unsigned long flags) -{ - return key_create_or_update( - keyring_ref, type, description, - payload, plen, perm, flags); -} - -__visible_for_testing __mockable -void call_key_ref_put(key_ref_t key_ref) -{ - key_ref_put(key_ref); -} - -__visible_for_testing __mockable -void call_key_put(struct key *key) -{ - key_put(key); -} - -__visible_for_testing __mockable -int call_five_verify_signature(struct key *key, - struct public_key_signature *pks, - struct five_cert *cert, - struct five_cert_header *header) -{ - return five_verify_signature(key, pks, cert, header); -} - -__visible_for_testing __mockable -struct key *call_five_keyring_alloc( - const char *description, - kuid_t uid, kgid_t gid, const struct cred *cred, - key_perm_t perm, unsigned long flags) -{ - return five_keyring_alloc(description, uid, gid, cred, perm, flags); -} - -/* - * Request an asymmetric key. - */ -__visible_for_testing -struct key *five_request_asymmetric_key(uint32_t keyid) -{ - struct key *key; - char name[12]; - - snprintf(name, sizeof(name), "id:%08x", keyid); - - pr_debug("key search: \"%s\"\n", name); - - if (five_keyring) { - /* search in specific keyring */ - key_ref_t kref; - - kref = call_keyring_search(make_key_ref(five_keyring, 1), - &key_type_asymmetric, name, true); - if (IS_ERR(kref)) - key = ERR_CAST(kref); - else - key = key_ref_to_ptr(kref); - } else { - return ERR_PTR(-ENOKEY); - } - - if (IS_ERR(key)) { - switch (PTR_ERR(key)) { - /* Hide some search errors */ - case -EACCES: - case -ENOTDIR: - case -EAGAIN: - return ERR_PTR(-ENOKEY); - default: - return key; - } - } - - pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key)); - - return key; -} - -static int five_asymmetric_verify(struct five_cert *cert, - const char *data, int datalen) -{ - struct public_key_signature pks; - struct five_cert_header *header; - struct key *key; - int ret = -ENOMEM; - - header = (struct five_cert_header *)cert->body.header->value; - if (header->hash_algo >= HASH_ALGO__LAST) - return -ENOPKG; - - key = five_request_asymmetric_key(__be32_to_cpu(header->key_id)); - if (IS_ERR(key)) - return PTR_ERR(key); - - memset(&pks, 0, sizeof(pks)); - - pks.digest = (u8 *)data; - pks.digest_size = datalen; - ret = call_five_verify_signature(key, &pks, cert, header); - - call_key_put(key); - pr_debug("%s() = %d\n", __func__, ret); - return ret; -} - -int five_digsig_verify(struct five_cert *cert, - const char *digest, int digestlen) -{ - if (!five_keyring) { - five_keyring = call_request_key( - &key_type_keyring, five_keyring_name, NULL); - if (IS_ERR(five_keyring)) { - int err = PTR_ERR(five_keyring); - - pr_err("no %s keyring: %d\n", five_keyring_name, err); - five_keyring = NULL; - return err; - } - } - - return five_asymmetric_verify(cert, digest, digestlen); -} - -__visible_for_testing -int __init five_load_x509_from_mem(const char *data, size_t size) -{ - key_ref_t key; - int rc = 0; - - if (!five_keyring || size == 0) - return -EINVAL; - - key = call_key_create_or_update(make_key_ref(five_keyring, 1), - "asymmetric", - NULL, - data, - size, - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW | KEY_USR_READ), - KEY_ALLOC_NOT_IN_QUOTA); - if (IS_ERR(key)) { - rc = PTR_ERR(key); - pr_err("Problem loading X.509 certificate (%d): %s\n", - rc, "built-in"); - } else { - pr_notice("Loaded X.509 cert '%s': %s\n", - key_ref_to_ptr(key)->description, "built-in"); - call_key_ref_put(key); - } - - return rc; -} - -#ifdef CONFIG_FIVE_CERT_ENG -extern char five_local_ca_start_eng[]; -extern char five_local_ca_end_eng[]; - -__visible_for_testing -int __init five_import_eng_key(void) -{ - size_t size = five_local_ca_end_eng - five_local_ca_start_eng; - - return five_load_x509_from_mem(five_local_ca_start_eng, size); -} -#else -__visible_for_testing -int __init five_import_eng_key(void) -{ - return 0; -} -#endif - -#ifdef CONFIG_FIVE_CERT_USER -extern char five_local_ca_start_user[]; -extern char five_local_ca_end_user[]; - -__visible_for_testing -int __init five_import_user_key(void) -{ - size_t size = five_local_ca_end_user - five_local_ca_start_user; - - return five_load_x509_from_mem(five_local_ca_start_user, size); -} -#else -__visible_for_testing -int __init five_import_user_key(void) -{ - return 0; -} -#endif - -int __init five_load_built_x509(void) -{ - int rc; - - rc = five_import_eng_key(); - if (rc) - return rc; - - rc = five_import_user_key(); - - return rc; -} - -int __init five_keyring_init(void) -{ - const struct cred *cred = current_cred(); - int err = 0; - - five_keyring = call_five_keyring_alloc(five_keyring_name, KUIDT_INIT(0), - KGIDT_INIT(0), cred, - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW | KEY_USR_READ | - KEY_USR_SEARCH), - KEY_ALLOC_NOT_IN_QUOTA); - if (IS_ERR(five_keyring)) { - err = PTR_ERR(five_keyring); - pr_info("Can't allocate %s keyring (%d)\n", - five_keyring_name, err); - five_keyring = NULL; - } - return err; -} diff --git a/security/samsung/five/five_lv.c b/security/samsung/five/five_lv.c deleted file mode 100755 index f7ad12095..000000000 --- a/security/samsung/five/five_lv.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This code is originated from Samsung Electronics proprietary sources. - * Author: Viacheslav Vovchenko, <v.vovchenko@samsung.com> - * Created: 10 Jul 2017 - * - * Copyright (C) 2016 Samsung Electronics, Inc. - */ - -#include <linux/module.h> -#include "five_lv.h" - -struct lv *lv_get_next(struct lv *field, const void *end) -{ - size_t lv_len; - uint8_t *pbegin = (uint8_t *)field; - const uint8_t *pend = (const uint8_t *)end; - - if (unlikely(!pbegin || !pend || pbegin >= pend)) - return NULL; - - /* Check if we can read 'length' field */ - if (unlikely(pend - pbegin < sizeof(field->length))) - return NULL; - - lv_len = sizeof(field->length) + field->length; - /* Check if we can read the value */ - if (unlikely(pend - pbegin < lv_len)) - return NULL; - - return (struct lv *)(pbegin + lv_len); -} - -int lv_set(struct lv *field, const void *data, uint16_t data_len, - const void *end) -{ - size_t lv_len; - uint8_t *pbegin = (uint8_t *)field; - const uint8_t *pend = (const uint8_t *)end; - - if (unlikely(!pbegin || !pend)) - return -EINVAL; - - lv_len = sizeof(field->length) + data_len; - - if (unlikely(pbegin >= pend || (pend - pbegin < lv_len) || - (data_len > 0 && !data))) - return -EINVAL; - - field->length = data_len; - - if (data) - memcpy(field->value, data, data_len); - - return 0; -} diff --git a/security/samsung/five/five_lv.h b/security/samsung/five/five_lv.h deleted file mode 100755 index 03dbc2ce3..000000000 --- a/security/samsung/five/five_lv.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This code is originated from Samsung Electronics proprietary sources. - * Author: Viacheslav Vovchenko, <v.vovchenko@samsung.com> - * Created: 10 Jul 2017 - * - * Copyright (C) 2016 Samsung Electronics, Inc. - */ - -#ifndef __FIVE_LV_H__ -#define __FIVE_LV_H__ - -#include <linux/types.h> - -/** - * Length/Value structure - */ -struct lv { - uint16_t length; - uint8_t value[]; -} __packed; - -/** - * Returns the next element from the chain of LV (length/value) data. - * Returns NULL in a case of memory limits violation - */ -struct lv *lv_get_next(struct lv *field, const void *end); - -/** - * Sets value of LV data and checks memory bounds. - * Returns 0 on success, otherwise - error. - */ -int lv_set(struct lv *field, const void *data, uint16_t data_len, - const void *end); - -#endif /* __FIVE_LV_H__ */ diff --git a/security/samsung/five/five_main.c b/security/samsung/five/five_main.c deleted file mode 100755 index 2b8af0e12..000000000 --- a/security/samsung/five/five_main.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/binfmts.h> -#include <linux/mount.h> -#include <linux/mman.h> -#include <linux/slab.h> -#include <crypto/hash_info.h> -#include <linux/ptrace.h> -#include <linux/task_integrity.h> -#include <linux/reboot.h> -#include <linux/debugfs.h> -#include <linux/fs.h> -#include <linux/shmem_fs.h> -#include <linux/version.h> - -#include "five.h" -#include "five_audit.h" -#include "five_hooks.h" -#include "five_state.h" -#include "five_pa.h" -#include "five_porting.h" -#include "five_cache.h" -#include "five_dmverity.h" -#include "five_dsms.h" -#include "five_testing.h" - -/* crash_dump in Android 12 uses this request even if Kernel doesn't - * support it */ -#ifndef PTRACE_PEEKMTETAGS -#define PTRACE_PEEKMTETAGS 33 -#endif - -static const bool check_dex2oat_binary = true; -static const bool check_memfd_file = true; - -static struct file *memfd_file __ro_after_init; - -static struct workqueue_struct *g_five_workqueue; - -static inline void task_integrity_processing(struct task_integrity *tint); -static inline void task_integrity_done(struct task_integrity *tint); -static void process_measurement(const struct processing_event_list *params); -static inline struct processing_event_list *five_event_create( - enum five_event event, struct task_struct *task, - struct file *file, int function, gfp_t flags); -static inline void five_event_destroy( - const struct processing_event_list *file); - -#ifdef CONFIG_FIVE_DEBUG -static int five_enabled = 1; - -static ssize_t five_enabled_write(struct file *file, const char __user *buf, - size_t count, loff_t *pos) -{ - char command; - - if (get_user(command, buf)) - return -EFAULT; - - switch (command) { - case '0': - five_enabled = 0; - break; - case '1': - five_enabled = 1; - break; - default: - pr_err("FIVE: %s: unknown cmd: %hhx\n", __func__, command); - return -EINVAL; - } - - pr_info("FIVE debug: FIVE %s\n", five_enabled ? "enabled" : "disabled"); - return count; -} - -static ssize_t five_enabled_read(struct file *file, char __user *user_buf, - size_t count, loff_t *pos) -{ - char buf[2]; - - buf[0] = five_enabled ? '1' : '0'; - buf[1] = '\n'; - - return simple_read_from_buffer(user_buf, count, pos, buf, sizeof(buf)); -} - -static const struct file_operations five_enabled_fops = { - .owner = THIS_MODULE, - .read = five_enabled_read, - .write = five_enabled_write -}; - -static int __init init_fs(void) -{ - struct dentry *debug_file = NULL; - umode_t umode = (S_IRUGO | S_IWUSR | S_IWGRP); - - debug_file = debugfs_create_file( - "five_enabled", umode, NULL, NULL, &five_enabled_fops); - if (IS_ERR_OR_NULL(debug_file)) - goto error; - - return 0; -error: - if (debug_file) - return -PTR_ERR(debug_file); - - return -EEXIST; -} - -static inline int is_five_enabled(void) -{ - return five_enabled; -} - -int five_fcntl_debug(struct file *file, void __user *argp) -{ - struct inode *inode; - struct five_stat stat = {0}; - struct integrity_iint_cache *iint; - - if (unlikely(!file || !argp)) - return -EINVAL; - - inode = file_inode(file); - - inode_lock(inode); - iint = integrity_inode_get(inode); - if (unlikely(!iint)) { - inode_unlock(inode); - return -ENOMEM; - } - - stat.cache_status = five_get_cache_status(iint); - stat.cache_iversion = inode_query_iversion(iint->inode); - stat.inode_iversion = inode_query_iversion(inode); - - inode_unlock(inode); - - if (unlikely(copy_to_user(argp, &stat, sizeof(stat)))) - return -EFAULT; - - return 0; -} -#else -static int __init init_fs(void) -{ - return 0; -} - -static inline int is_five_enabled(void) -{ - return 1; -} -#endif - -static void work_handler(struct work_struct *in_data) -{ - struct worker_context *context = container_of(in_data, - struct worker_context, data_work); - struct task_integrity *intg; - - if (unlikely(!context)) - return; - - intg = context->tint; - - spin_lock(&intg->list_lock); - while (!list_empty(&(intg->events.list))) { - struct processing_event_list *five_file; - - five_file = list_entry(intg->events.list.next, - struct processing_event_list, list); - spin_unlock(&intg->list_lock); - switch (five_file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - process_measurement(five_file); - break; - } - case FIVE_RESET_INTEGRITY: { - task_integrity_reset(intg); - five_hook_integrity_reset(five_file->task, - NULL, CAUSE_UNKNOWN); - break; - } - default: - break; - } - spin_lock(&intg->list_lock); - list_del(&five_file->list); - five_event_destroy(five_file); - } - - task_integrity_done(intg); - spin_unlock(&intg->list_lock); - task_integrity_put(intg); - - kfree(context); -} - -__mockable -const char *five_d_path(const struct path *path, char **pathbuf, char *namebuf) -{ - char *pathname = NULL; - - *pathbuf = __getname(); - if (*pathbuf) { - pathname = d_absolute_path(path, *pathbuf, PATH_MAX); - if (IS_ERR(pathname)) { - __putname(*pathbuf); - *pathbuf = NULL; - pathname = NULL; - } - } - - if (!pathname) { - strlcpy(namebuf, path->dentry->d_name.name, NAME_MAX); - pathname = namebuf; - } - - return pathname; -} - -int five_check_params(struct task_struct *task, struct file *file) -{ - struct inode *inode; - - if (unlikely(!file)) - return 1; - - inode = file_inode(file); - if (!S_ISREG(inode->i_mode)) - return 1; - - return 0; -} - -/* cut a list into two - * @cur_list: a list with entries - * @new_list: a new list to add all removed entries. Should be an empty list - * - * Use it under spin_lock - * - * The function moves second entry and following entries to new list. - * First entry is left in cur_list. - * - * Initial state: - * [cur_list]<=>[first]<=>[second]<=>[third]<=>...<=>[last] [new_list] - * ^=================================================^ ^====^ - * Result: - * [cur_list]<=>[first] - * ^==========^ - * [new_list]<=>[second]<=>[third]<=>...<=>[last] - * ^=====================================^ - * - * the function is similar to kernel list_cut_position, but there are few - * differences: - * - cut position is second entry - * - original list is left with only first entry - * - moving entries are from second entry to last entry - */ -static void list_cut_tail(struct list_head *cur_list, - struct list_head *new_list) -{ - if ((!list_empty(cur_list)) && - (!list_is_singular(cur_list))) { - new_list->next = cur_list->next->next; - cur_list->next->next->prev = new_list; - cur_list->next->next = cur_list; - new_list->prev = cur_list->prev; - cur_list->prev->next = new_list; - cur_list->prev = cur_list->next; - } -} - -static void free_files_list(struct list_head *list) -{ - struct list_head *tmp, *list_entry; - struct processing_event_list *file_entry; - - list_for_each_safe(list_entry, tmp, list) { - file_entry = list_entry(list_entry, - struct processing_event_list, list); - list_del(&file_entry->list); - five_event_destroy(file_entry); - } -} - -static int push_file_event_bunch(struct task_struct *task, struct file *file, - int function) -{ - int rc = 0; - struct worker_context *context; - struct processing_event_list *five_file; - - if (unlikely(!is_five_enabled()) || five_check_params(task, file)) - return 0; - - context = kmalloc(sizeof(struct worker_context), GFP_KERNEL); - if (unlikely(!context)) - return -ENOMEM; - - five_file = five_event_create(FIVE_VERIFY_BUNCH_FILES, task, file, - function, GFP_KERNEL); - if (unlikely(!five_file)) { - kfree(context); - return -ENOMEM; - } - - spin_lock(&TASK_INTEGRITY(task)->list_lock); - - if (list_empty(&(TASK_INTEGRITY(task)->events.list))) { - task_integrity_get(TASK_INTEGRITY(task)); - task_integrity_processing(TASK_INTEGRITY(task)); - - context->tint = TASK_INTEGRITY(task); - - list_add_tail(&five_file->list, - &TASK_INTEGRITY(task)->events.list); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - INIT_WORK(&context->data_work, work_handler); - rc = queue_work(g_five_workqueue, &context->data_work) ? 0 : 1; - } else { - struct list_head dead_list; - - INIT_LIST_HEAD(&dead_list); - if ((function == BPRM_CHECK) && - (!list_is_singular(&(TASK_INTEGRITY(task)->events.list)))) { - list_cut_tail(&TASK_INTEGRITY(task)->events.list, - &dead_list); - } - list_add_tail(&five_file->list, - &TASK_INTEGRITY(task)->events.list); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - free_files_list(&dead_list); - kfree(context); - } - return rc; -} - -static int push_reset_event(struct task_struct *task, - enum task_integrity_reset_cause cause, struct file *file) -{ - struct list_head dead_list; - struct task_integrity *current_tint; - struct processing_event_list *five_reset; - - if (unlikely(!is_five_enabled())) - return 0; - - INIT_LIST_HEAD(&dead_list); - current_tint = TASK_INTEGRITY(task); - task_integrity_get(current_tint); - - task_integrity_set_reset_reason(current_tint, cause, file); - - five_reset = five_event_create(FIVE_RESET_INTEGRITY, task, NULL, 0, - GFP_KERNEL); - if (unlikely(!five_reset)) { - task_integrity_reset_both(current_tint); - five_hook_integrity_reset(task, file, cause); - task_integrity_put(current_tint); - return -ENOMEM; - } - - task_integrity_reset_both(current_tint); - five_hook_integrity_reset(task, file, cause); - spin_lock(¤t_tint->list_lock); - if (!list_empty(¤t_tint->events.list)) { - list_cut_tail(¤t_tint->events.list, &dead_list); - five_reset->event = FIVE_RESET_INTEGRITY; - list_add_tail(&five_reset->list, ¤t_tint->events.list); - spin_unlock(¤t_tint->list_lock); - } else { - spin_unlock(¤t_tint->list_lock); - five_event_destroy(five_reset); - } - - task_integrity_put(current_tint); - /* remove dead_list */ - free_files_list(&dead_list); - return 0; -} - -void task_integrity_delayed_reset(struct task_struct *task, - enum task_integrity_reset_cause cause, struct file *file) -{ - push_reset_event(task, cause, file); -} - -static void five_check_last_writer(struct integrity_iint_cache *iint, - struct inode *inode, struct file *file) -{ - fmode_t mode = file->f_mode; - - if (!(mode & FMODE_WRITE)) - return; - - inode_lock(inode); - if (atomic_read(&inode->i_writecount) == 1) { - if (!inode_eq_iversion(inode, iint->version)) - five_set_cache_status(iint, FIVE_FILE_UNKNOWN); - } - iint->five_signing = false; - inode_unlock(inode); -} - -/** - * five_file_free - called on __fput() - * @file: pointer to file structure being freed - * - * Flag files that changed, based on i_version - */ -void five_file_free(struct file *file) -{ - struct inode *inode = file_inode(file); - struct integrity_iint_cache *iint; - - if (!S_ISREG(inode->i_mode)) - return; - - fivepa_fsignature_free(file); - - iint = integrity_iint_find(inode); - if (!iint) - return; - - five_check_last_writer(iint, inode, file); -} - -void five_task_free(struct task_struct *task) -{ - task_integrity_put(TASK_INTEGRITY(task)); -} - -/* Returns string representation of input function */ -const char *five_get_string_fn(enum five_hooks fn) -{ - switch (fn) { - case FILE_CHECK: - return "file-check"; - case MMAP_CHECK: - return "mmap-check"; - case BPRM_CHECK: - return "bprm-check"; - case POST_SETATTR: - return "post-setattr"; - } - return "unknown-function"; -} - -static inline bool is_dex2oat_binary(const struct file *file) -{ - const char *pathname = NULL; - char *pathbuf = NULL; - const char * const dex2oat_full_path[] = { - /* R OS */ - "/apex/com.android.art/bin/dex2oat", - "/apex/com.android.art/bin/dex2oat32", - "/apex/com.android.art/bin/dex2oat64", - /* Q OS */ - "/apex/com.android.runtime/bin/dex2oat" - }; - char filename[NAME_MAX]; - bool res = false; - size_t i; - - if (!file || !file->f_path.dentry) - return false; - - if (strncmp(file->f_path.dentry->d_iname, "dex2oat", - sizeof("dex2oat")) && - strncmp(file->f_path.dentry->d_iname, "dex2oat32", - sizeof("dex2oat32")) && - strncmp(file->f_path.dentry->d_iname, "dex2oat64", - sizeof("dex2oat64"))) - return false; - - pathname = five_d_path(&file->f_path, &pathbuf, filename); - - for (i = 0; i < ARRAY_SIZE(dex2oat_full_path); ++i) { - if (!strncmp(pathname, dex2oat_full_path[i], - strlen(dex2oat_full_path[i]) + 1)) { - res = true; - break; - } - } - - if (pathbuf) - __putname(pathbuf); - - return res; -} - -static inline bool match_trusted_executable(const struct five_cert *cert, - const struct integrity_iint_cache *iint, - const struct file *file) -{ - const struct five_cert_header *hdr = NULL; - - if (!cert) - return check_dex2oat_binary && is_dex2oat_binary(file); - - if (five_get_cache_status(iint) != FIVE_FILE_RSA) - return false; - - hdr = (const struct five_cert_header *)cert->body.header->value; - - if (hdr->privilege == FIVE_PRIV_ALLOW_SIGN) - return true; - - return false; -} - -static inline void task_integrity_processing(struct task_integrity *tint) -{ - tint->user_value = INTEGRITY_PROCESSING; -} - -static inline void task_integrity_done(struct task_integrity *tint) -{ - tint->user_value = task_integrity_read(tint); -} - -static void process_file(struct task_struct *task, - struct file *file, - int function, - struct file_verification_result *result) -{ - struct inode *inode = d_real_inode(file_dentry(file)); - struct integrity_iint_cache *iint = NULL; - struct five_cert cert = { {0} }; - struct five_cert *pcert = NULL; - int rc = -ENOMEM; - char *xattr_value = NULL; - int xattr_len = 0; - - if (!S_ISREG(inode->i_mode)) { - rc = 0; - goto out; - } - - iint = integrity_inode_get(inode); - if (!iint) - goto out; - - /* Nothing to do, just return existing appraised status */ - if (five_get_cache_status(iint) != FIVE_FILE_UNKNOWN) { - rc = 0; - goto out; - } - - xattr_len = five_read_xattr(d_real_comp(file->f_path.dentry), - &xattr_value); - if (xattr_value) { - if (xattr_len) { - rc = five_cert_fillout(&cert, xattr_value, xattr_len); - if (rc) { - pr_err("FIVE: certificate is incorrect inode=%lu\n", - inode->i_ino); - goto out; - } - - pcert = &cert; - - if (file->f_flags & O_DIRECT) { - rc = -EACCES; - goto out; - } - } else { - five_audit_info(task, file, "zero length", 0, 0, - "Found a dummy-cert", rc); - } - } - - rc = five_appraise_measurement(task, function, iint, file, pcert); - if (!rc && match_trusted_executable(pcert, iint, file)) - iint->five_flags |= FIVE_TRUSTED_FILE; - -out: - if (rc && iint) - iint->five_flags &= ~FIVE_TRUSTED_FILE; - - result->file = file; - result->task = task; - result->iint = iint; - result->fn = function; - result->xattr = xattr_value; - result->xattr_len = (size_t)xattr_len; - - if (!iint || five_get_cache_status(iint) == FIVE_FILE_UNKNOWN - || five_get_cache_status(iint) == FIVE_FILE_FAIL) - result->five_result = 1; - else - result->five_result = 0; -} - -static void process_measurement(const struct processing_event_list *params) -{ - struct task_struct *task = params->task; - struct task_integrity *integrity = TASK_INTEGRITY(task); - struct file *file = params->file; - struct inode *inode = file_inode(file); - int function = params->function; - struct file_verification_result file_result; - - if (function != BPRM_CHECK) { - if (task_integrity_read(integrity) == INTEGRITY_NONE) - return; - } - - file_verification_result_init(&file_result); - inode_lock(inode); - - process_file(task, file, function, &file_result); - - five_hook_file_processed(task, file, - file_result.xattr, file_result.xattr_len, - file_result.five_result); - - five_state_proceed(integrity, &file_result); - - inode_unlock(inode); - file_verification_result_deinit(&file_result); -} - -#define MFD_NAME_PREFIX "memfd:" -#define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1) - -static bool is_memfd_file(struct file *file) -{ - struct inode *inode; - struct inode *memfd_inode; - - if (!file) - return false; - - memfd_inode = file_inode(memfd_file); - inode = file_inode(file); - if (inode && memfd_inode && inode->i_sb == memfd_inode->i_sb) - if (file->f_path.dentry && - !strncmp(file->f_path.dentry->d_iname, MFD_NAME_PREFIX, - MFD_NAME_PREFIX_LEN)) - return true; - - return false; -} - -/** - * five_file_mmap - measure files being mapped executable based on - * the process_measurement() policy decision. - * @file: pointer to the file to be measured (May be NULL) - * @prot: contains the protection that will be applied by the kernel. - * - * On success return 0. - */ -int five_file_mmap(struct file *file, unsigned long prot) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (five_check_params(task, file)) - return 0; - - if (check_memfd_file && is_memfd_file(file)) - return 0; - - if (file && task_integrity_user_read(tint)) { - if (prot & PROT_EXEC) { - rc = push_file_event_bunch(task, file, MMAP_CHECK); - if (rc) - return rc; - } else { - five_hook_file_skipped(task, file); - } - } - - return rc; -} - -/** - * five_bprm_check - Measure executable being launched based on - * the process_measurement() policy decision. - * @bprm: contains the linux_binprm structure - * - * Notes: - * bprm_check could be called few times for one process when few binary loaders - * are used. Example: execution of shell script. - * In this case we should process first file (e.g. shell script) as main and - * use BPRM_CHECK. The second file (interpetator ) will be processed as general - * mapping (MMAP_CHECK). - * To implement this option variable bprm->recursion_depth is used. - * - * On success return 0. - */ -int __five_bprm_check(struct linux_binprm *bprm, int depth) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *old_tint = TASK_INTEGRITY(task); - - if (unlikely(task->ptrace)) - return rc; - - if (depth > 0) { - rc = push_file_event_bunch(task, bprm->file, MMAP_CHECK); - } else { - struct task_integrity *tint = task_integrity_alloc(); - - task_integrity_assign(task, tint); - if (likely(TASK_INTEGRITY(task))) { - rc = push_file_event_bunch(task, - bprm->file, BPRM_CHECK); - } else { - rc = -ENOMEM; - } - task_integrity_put(old_tint); - } - - return rc; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) -int five_bprm_check(struct linux_binprm *bprm, int depth) -{ - return __five_bprm_check(bprm, depth); -} -#else -int five_bprm_check(struct linux_binprm *bprm) -{ - return __five_bprm_check(bprm, bprm->recursion_depth); -} -#endif - -/** - * This function handles two situations: - * 1. Device had been rebooted before five_sign finished. - * Then xattr_len will be zero and iint->five_signing will be false. - * 2. The file is being signing when another process tries to open it. - * Then xattr_len will be zero and iint->five_signing will be true. - * - * - five_fcntl_edit stores the xattr with zero length and set - * iint->five_signing to true - * - five_fcntl_sign stores correct certificates and set - * iint->five_signing to false - * - * On success returns 0 - */ -int five_file_open(struct file *file) -{ - ssize_t xattr_len; - struct inode *inode = file_inode(file); - - if (!S_ISREG(inode->i_mode)) - return 0; - - xattr_len = vfs_getxattr(file->f_path.dentry, XATTR_NAME_FIVE, - NULL, 0); - if (xattr_len == 0) { - five_audit_verbose(current, file, "dummy-cert", 0, 0, - "Found a dummy-cert", 0); - } - - return 0; -} - -/** - * five_file_verify - force five integrity measurements for file - * the process_measurement() policy decision. This check affects - * task integrity. - * @file: pointer to the file to be measured (May be NULL) - * - * On success return 0. - */ -int five_file_verify(struct task_struct *task, struct file *file) -{ - int rc = 0; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (file && task_integrity_user_read(tint)) - rc = push_file_event_bunch(task, file, FILE_CHECK); - - return rc; -} - -static struct notifier_block five_reboot_nb = { - .notifier_call = five_reboot_notifier, - .priority = INT_MAX, -}; - -int five_hash_algo __ro_after_init = HASH_ALGO_SHA1; - -static int __init hash_setup(const char *str) -{ - int i; - - for (i = 0; i < HASH_ALGO__LAST; i++) { - if (strcmp(str, hash_algo_name[i]) == 0) { - five_hash_algo = i; - break; - } - } - - return 1; -} - -int __init init_five(void) -{ - int error; - - g_five_workqueue = alloc_workqueue("%s", WQ_FREEZABLE | WQ_MEM_RECLAIM, - 0, "five_wq"); - if (!g_five_workqueue) - return -ENOMEM; - - hash_setup(CONFIG_FIVE_DEFAULT_HASH); - error = five_init(); - if (error) - return error; - - error = five_hook_wq_init(); - if (error) - return error; - - error = register_reboot_notifier(&five_reboot_nb); - if (error) - return error; - -/** - * This empty file is needed in is_memfd_file() function. - * The only way to check whether the file was created using memfd_create() - * syscall is to compare its superblock address with address of another memfd - * file. - */ - memfd_file = shmem_kernel_file_setup( - "five_memfd_check", 0, VM_NORESERVE); - if (IS_ERR(memfd_file)) { - error = PTR_ERR(memfd_file); - memfd_file = NULL; - return error; - } - - error = init_fs(); - if (error) - return error; - - five_dsms_init("1", 0); - - error = five_init_dmverity(); - - return error; -} - -static int fcntl_verify(struct file *file) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint)) - rc = push_file_event_bunch(task, file, FILE_CHECK); - return rc; -} - -/* Called from do_fcntl */ -int five_fcntl_verify_async(struct file *file) -{ - return fcntl_verify(file); -} - -/* Called from do_fcntl */ -int five_fcntl_verify_sync(struct file *file) -{ - return -EINVAL; -} - -int five_fork(struct task_struct *task, struct task_struct *child_task) -{ - int rc = 0; - - spin_lock(&TASK_INTEGRITY(task)->list_lock); - - if (!list_empty(&TASK_INTEGRITY(task)->events.list)) { - /*copy the list*/ - struct list_head *tmp; - struct processing_event_list *from_entry; - struct worker_context *context; - - context = kmalloc(sizeof(struct worker_context), GFP_ATOMIC); - if (unlikely(!context)) { - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - return -ENOMEM; - } - - list_for_each(tmp, &TASK_INTEGRITY(task)->events.list) { - struct processing_event_list *five_file; - - from_entry = list_entry(tmp, - struct processing_event_list, list); - - five_file = five_event_create( - from_entry->event, - child_task, - from_entry->file, - from_entry->function, - GFP_ATOMIC); - if (unlikely(!five_file)) { - kfree(context); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - return -ENOMEM; - } - - list_add_tail(&five_file->list, - &TASK_INTEGRITY(child_task)->events.list); - } - - context->tint = TASK_INTEGRITY(child_task); - - rc = task_integrity_copy(TASK_INTEGRITY(task), - TASK_INTEGRITY(child_task)); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - task_integrity_get(context->tint); - task_integrity_processing(TASK_INTEGRITY(child_task)); - INIT_WORK(&context->data_work, work_handler); - rc = queue_work(g_five_workqueue, &context->data_work) ? 0 : 1; - } else { - rc = task_integrity_copy(TASK_INTEGRITY(task), - TASK_INTEGRITY(child_task)); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - } - - if (!rc) - five_hook_task_forked(task, child_task); - - return rc; -} - -int five_ptrace(struct task_struct *task, long request) -{ - switch (request) { - case PTRACE_TRACEME: - case PTRACE_ATTACH: - case PTRACE_SEIZE: - case PTRACE_INTERRUPT: - case PTRACE_CONT: - case PTRACE_DETACH: - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - case PTRACE_PEEKUSR: - case PTRACE_GETREGSET: - case PTRACE_GETSIGINFO: - case PTRACE_PEEKSIGINFO: - case PTRACE_GETSIGMASK: - case PTRACE_GETEVENTMSG: - case PTRACE_PEEKMTETAGS: -#if defined(CONFIG_ARM64) || defined(KUNIT_UML) - case COMPAT_PTRACE_GETREGS: - case COMPAT_PTRACE_GET_THREAD_AREA: - case COMPAT_PTRACE_GETVFPREGS: - case COMPAT_PTRACE_GETHBPREGS: -#else - case PTRACE_GETREGS: - case PTRACE_GET_THREAD_AREA: - case PTRACE_GETVFPREGS: - case PTRACE_GETHBPREGS: -#endif - break; - default: { - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint) == INTEGRITY_NONE) - break; - - task_integrity_delayed_reset(task, CAUSE_PTRACE, NULL); - five_audit_err(task, NULL, "ptrace", task_integrity_read(tint), - INTEGRITY_NONE, "reset-integrity", 0); - break; - } - } - - return 0; -} - -int five_process_vm_rw(struct task_struct *task, int write) -{ - if (write) { - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint) == INTEGRITY_NONE) - goto exit; - - task_integrity_delayed_reset(task, CAUSE_VMRW, NULL); - five_audit_err(task, NULL, "process_vm_rw", - task_integrity_read(tint), INTEGRITY_NONE, - "reset-integrity", 0); - } - -exit: - return 0; -} - -static inline struct processing_event_list *five_event_create( - enum five_event event, struct task_struct *task, - struct file *file, int function, gfp_t flags) -{ - struct processing_event_list *five_file; - - five_file = kzalloc(sizeof(struct processing_event_list), flags); - if (unlikely(!five_file)) - return NULL; - - five_file->event = event; - - switch (five_file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - get_task_struct(task); - get_file(file); - five_file->task = task; - five_file->file = file; - five_file->function = function; - break; - } - case FIVE_RESET_INTEGRITY: { - get_task_struct(task); - five_file->task = task; - break; - } - default: - break; - } - - return five_file; -} - -static inline void five_event_destroy( - const struct processing_event_list *file) -{ - switch (file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - fput(file->file); - put_task_struct(file->task); - break; - } - case FIVE_RESET_INTEGRITY: { - put_task_struct(file->task); - break; - } - default: - break; - } - kfree(file); -} - -late_initcall(init_five); - -MODULE_DESCRIPTION("File-based process Integrity Verifier"); -MODULE_LICENSE("GPL"); diff --git a/security/samsung/five/five_pa.c b/security/samsung/five/five_pa.c deleted file mode 100755 index 25ca83935..000000000 --- a/security/samsung/five/five_pa.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Process Authentificator helpers - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/file.h> -#include <linux/module.h> -#include <linux/task_integrity.h> -#include <linux/proca.h> -#include <linux/version.h> - -#include "five.h" -#include "five_pa.h" -#include "five_hooks.h" -#include "five_lv.h" -#include "five_porting.h" -#include "five_testing.h" - -__visible_for_testing __mockable -int call_five_read_xattr(struct dentry *dentry, char **xattr_value) -{ - return five_read_xattr(dentry, xattr_value); -} - -__visible_for_testing __mockable -int call_vfs_setxattr_noperm(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - return __vfs_setxattr_noperm(dentry, name, value, size, flags); -} - -__visible_for_testing __mockable -bool call_task_integrity_allow_sign(struct task_integrity *intg) -{ - return task_integrity_allow_sign(intg); -} - -#ifdef CONFIG_FIVE_GKI_10 - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) -#define F_SIGNATURE(file) ((void *)((file)->android_oem_data1)) - -static inline void f_signature_assign(struct file *file, void *f_signature) -{ - file->android_oem_data1 = (u64)f_signature; -} -#else -#define F_SIGNATURE(file) ((void *)((file)->android_vendor_data1)) - -static inline void f_signature_assign(struct file *file, void *f_signature) -{ - file->android_vendor_data1 = (u64)f_signature; -} -#endif - -#else -#define F_SIGNATURE(file) ((file)->f_signature) - -static inline void f_signature_assign(struct file *file, void *f_signature) -{ - file->f_signature = f_signature; -} -#endif - -__visible_for_testing -void pa_process_file(struct task_struct *task, struct file *file) -{ - char *xattr_value = NULL; - - if (five_check_params(task, file)) - return; - - if (F_SIGNATURE(file)) - return; - - call_five_read_xattr(d_real_comp(file->f_path.dentry), &xattr_value); - f_signature_assign(file, xattr_value); -} - -void fivepa_fsignature_free(struct file *file) -{ - kfree(F_SIGNATURE(file)); - f_signature_assign(file, NULL); -} - -int proca_fcntl_setxattr(struct file *file, void __user *lv_xattr) -{ - struct inode *inode; - struct lv lv_hdr = {0}; - int rc = -EPERM; - void *x = NULL; - - if (unlikely(!file || !lv_xattr)) - return -EINVAL; - - inode = file_inode(file); - - if (unlikely(copy_from_user(&lv_hdr, lv_xattr, sizeof(lv_hdr)))) - return -EFAULT; - - if (unlikely(lv_hdr.length > PAGE_SIZE)) - return -EINVAL; - - x = kmalloc(lv_hdr.length, GFP_NOFS); - if (unlikely(!x)) - return -ENOMEM; - - if (unlikely(copy_from_user(x, lv_xattr + sizeof(lv_hdr), - lv_hdr.length))) { - rc = -EFAULT; - goto out; - } - - if (file->f_op && file->f_op->flush) - if (file->f_op->flush(file, current->files)) { - rc = -EOPNOTSUPP; - goto out; - } - - inode_lock(inode); - - if (call_task_integrity_allow_sign(TASK_INTEGRITY(current))) { - rc = call_vfs_setxattr_noperm(d_real_comp(file->f_path.dentry), - XATTR_NAME_PA, - x, - lv_hdr.length, - 0); - } - inode_unlock(inode); - -out: - kfree(x); - - return rc; -} - -static void proca_hook_file_processed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result); - -static void proca_hook_file_skipped(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file); - -static struct five_hook_list five_ops[] = { - FIVE_HOOK_INIT(file_processed, proca_hook_file_processed), - FIVE_HOOK_INIT(file_skipped, proca_hook_file_skipped), -}; - -static void proca_hook_file_processed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - pa_process_file(task, file); -} - -static void proca_hook_file_skipped(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file) -{ - pa_process_file(task, file); -} - -static __init int proca_module_init(void) -{ - five_add_hooks(five_ops, ARRAY_SIZE(five_ops)); - pr_info("PROCA was initialized\n"); - - return 0; -} -late_initcall(proca_module_init); - -MODULE_DESCRIPTION("PROCA module"); -MODULE_LICENSE("GPL"); diff --git a/security/samsung/five/five_pa.h b/security/samsung/five/five_pa.h deleted file mode 100755 index 1e55ebf22..000000000 --- a/security/samsung/five/five_pa.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Process Authentificator helpers - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_PROCA_H -#define __LINUX_FIVE_PROCA_H - -#ifdef CONFIG_FIVE_PA_FEATURE -void fivepa_fsignature_free(struct file *file); -#else -static inline void fivepa_fsignature_free(struct file *file) -{ -} -#endif - -#endif // __LINUX_FIVE_PROCA_H diff --git a/security/samsung/five/five_porting.h b/security/samsung/five/five_porting.h deleted file mode 100755 index 1ee59c8e4..000000000 --- a/security/samsung/five/five_porting.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * This is needed backporting of source code from Kernel version 4.x - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_PORTING_H -#define __LINUX_FIVE_PORTING_H - -#include <linux/version.h> -#include <linux/magic.h> - -/* fallthrough is defined since v5.4.0 */ -#ifndef fallthrough -#define fallthrough do {} while (0) /* fallthrough */ -#endif - - -/* OVERLAYFS_SUPER_MAGIC is defined since v4.5.0 */ -#ifndef OVERLAYFS_SUPER_MAGIC -#define OVERLAYFS_SUPER_MAGIC 0x794c7630 -#endif - -/* EROFS_SUPER_MAGIC_V1 is defined since v5.4 */ -#ifndef EROFS_SUPER_MAGIC_V1 -#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 21) -/* d_backing_inode is absent on some Linux Kernel 3.x. but it back porting for - * few Samsung kernels: - * Exynos7570 (3.18.14): CL 13680422 - * Exynos7870 (3.18.14): CL 14632149 - * SDM450 (3.18.71): initially - */ -#if !defined(CONFIG_SOC_EXYNOS7570) && !defined(CONFIG_ARCH_SDM450) && \ - !defined(CONFIG_SOC_EXYNOS7870) -#define d_backing_inode(dentry) ((dentry)->d_inode) -#endif -#define inode_lock(inode) mutex_lock(&(inode)->i_mutex) -#define inode_lock_nested(inode, subclass) \ - mutex_lock_nested(&(inode)->i_mutex, subclass) -#define inode_unlock(inode) mutex_unlock(&(inode)->i_mutex) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) -#include <linux/fs.h> - -#ifndef IS_VERITY -#define IS_VERITY(inode) 0 -#endif -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 20, 0) -/* It is added for initialization purposes. - * For developing LSM, please, use DEFINE_LSM - */ -#define security_initcall(fn) late_initcall(fn) -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 20, 17) -/* This file was added in v5.0.0 */ -#include <uapi/linux/mount.h> -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 20) -/* kmemcheck is gone. - * Since Kernel 4.14.21 SLAB_NOTRACK isn't present in Kernel. - * But for backward compatibility with old Kernels - * we have to define it here. - */ -#define SLAB_NOTRACK 0 -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 10, 17) -/* Some linux headers are moved. - * Since Kernel 4.11 get_task_struct moved to sched/ folder. - */ -#include <linux/sched/task.h> -#else -#include <linux/sched.h> -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) -#include <linux/fs.h> - -static inline int __vfs_removexattr(struct dentry *dentry, const char *name) -{ - struct inode *inode = d_inode(dentry); - - if (!inode->i_op->removexattr) - return -EOPNOTSUPP; - - return inode->i_op->removexattr(dentry, name); -} - -static inline ssize_t __vfs_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *value, size_t size) -{ - if (!inode->i_op->getxattr) - return -EOPNOTSUPP; - - return inode->i_op->getxattr(dentry, name, value, size); -} -#endif - -#if (defined(CONFIG_ANDROID) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) || \ - LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))) || \ - LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) -/* - * __vfs_getxattr was changed in Android Kernel v5.4 - * https://android.googlesource.com/kernel/common/+/3484eba91d6b529cc606486a2db79513f3db6c67 - * and was reverted in Android Kernel v5.15 - * https://android.googlesource.com/kernel/common/+/e884438aa554219a6d0df3a18ff0b23ea678c36c - */ -#define XATTR_NOSECURITY 0x4 /* get value, do not involve security check */ -#define __vfs_getxattr(dentry, inode, name, value, size, flags) \ - __vfs_getxattr(dentry, inode, name, value, size) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) -#define vfs_getxattr_alloc(dentry, name, xattr_value, size, flags) \ - vfs_getxattr_alloc(&init_user_ns, dentry, name, xattr_value, \ - size, flags) -#define __vfs_setxattr_noperm(dentry, name, value, size, flags) \ - __vfs_setxattr_noperm(&init_user_ns, dentry, name, value, size, flags) -#define __vfs_removexattr(dentry, name) \ - __vfs_removexattr(&init_user_ns, dentry, name) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) -/* __GFP_WAIT was changed to __GFP_RECLAIM in - * https://lore.kernel.org/patchwork/patch/592262/ - */ -#define __GFP_RECLAIM __GFP_WAIT -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) -#include <linux/uaccess.h> - -static inline ssize_t __vfs_read(struct file *file, char __user *buf, - size_t count, loff_t *pos) -{ - ssize_t ret; - - if (file->f_op->read) - ret = file->f_op->read(file, buf, count, pos); - else if (file->f_op->aio_read) - ret = do_sync_read(file, buf, count, pos); - else if (file->f_op->read_iter) - ret = new_sync_read(file, buf, count, pos); - else - ret = -EINVAL; - - return ret; -} - -static inline int integrity_kernel_read(struct file *file, loff_t offset, - char *addr, unsigned long count) -{ - mm_segment_t old_fs; - char __user *buf = (char __user *)addr; - ssize_t ret; - struct inode *inode = file_inode(file); - - if (!(file->f_mode & FMODE_READ)) - return -EBADF; - - old_fs = get_fs(); - set_fs(get_ds()); - - if (inode->i_sb->s_magic == OVERLAYFS_SUPER_MAGIC && file->private_data) - file = (struct file *)file->private_data; - - ret = __vfs_read(file, buf, count, &offset); - set_fs(old_fs); - - return ret; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0) -#include <linux/fs.h> - -static inline bool -inode_eq_iversion(const struct inode *inode, u64 old) -{ - return inode->i_version == old; -} - -static inline u64 -inode_query_iversion(struct inode *inode) -{ - return inode->i_version; -} -#else -#include <linux/iversion.h> -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 8) -static inline struct dentry *file_dentry(const struct file *file) -{ - return file->f_path.dentry; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 2) -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return dentry; -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return d_real(dentry); -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return d_real(dentry, NULL, 0); -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return d_real(dentry, NULL, 0, 0); -} -#else -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return d_real(dentry, d_real_inode(dentry)); -} -#endif - -/* d_real_inode was added in v4.4.16, removed in v4.5.0 and added again in v4.6.5 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 16) || \ - (LINUX_VERSION_CODE > KERNEL_VERSION(4, 5, 0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 5)) -static inline struct inode *d_real_inode(struct dentry *dentry) -{ - return d_backing_inode(d_real_comp(dentry)); -} -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) -#include "drivers/md/dm-core.h" -#include "uapi/linux/major.h" -#include "uapi/linux/loop.h" -#include "linux/device-mapper.h" - -struct loop_device { - int lo_number; - loff_t lo_offset; - loff_t lo_sizelimit; - int lo_flags; - char lo_file_name[LO_NAME_SIZE]; - - struct file * lo_backing_file; - struct block_device *lo_device; - - gfp_t old_gfp_mask; - - spinlock_t lo_lock; - int lo_state; - spinlock_t lo_work_lock; - struct workqueue_struct *workqueue; - struct work_struct rootcg_work; - struct list_head rootcg_cmd_list; - struct list_head idle_worker_list; - struct rb_root worker_tree; - struct timer_list timer; - bool use_dio; - bool sysfs_inited; - - struct request_queue *lo_queue; - struct blk_mq_tag_set tag_set; - struct gendisk *lo_disk; - struct mutex lo_mutex; - bool idr_visible; -}; -#else -#include "drivers/block/loop.h" -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) -#define dm_table_get_num_targets(t) t->num_targets -#endif -#endif /* __LINUX_FIVE_PORTING_H */ diff --git a/security/samsung/five/five_state.c b/security/samsung/five/five_state.c deleted file mode 100755 index a452ebde9..000000000 --- a/security/samsung/five/five_state.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * FIVE State machine - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/task_integrity.h> -#include "five_audit.h" -#include "five_state.h" -#include "five_hooks.h" -#include "five_cache.h" -#ifndef FIVE_KUNIT_ENABLED -#include "five_dsms.h" -#else -void five_dsms_reset_integrity(const char *task_name, int result, - const char *file_name); -#endif -#include "five_testing.h" - -enum task_integrity_state_cause { - STATE_CAUSE_UNKNOWN, - STATE_CAUSE_DIGSIG, - STATE_CAUSE_DMV_PROTECTED, - STATE_CAUSE_TRUSTED, - STATE_CAUSE_HMAC, - STATE_CAUSE_SYSTEM_LABEL, - STATE_CAUSE_NOCERT, - STATE_CAUSE_TAMPERED, - STATE_CAUSE_MISMATCH_LABEL, - STATE_CAUSE_FSV_PROTECTED -}; - -struct task_verification_result { - enum task_integrity_value new_tint; - enum task_integrity_value prev_tint; - enum task_integrity_state_cause cause; -}; - -__visible_for_testing -const char *task_integrity_state_str( - enum task_integrity_state_cause cause) -{ - const char *str = "unknown"; - - switch (cause) { - case STATE_CAUSE_DIGSIG: - str = "digsig"; - break; - case STATE_CAUSE_DMV_PROTECTED: - str = "dmv_protected"; - break; - case STATE_CAUSE_FSV_PROTECTED: - str = "fsv_protected"; - break; - case STATE_CAUSE_TRUSTED: - str = "trusted"; - break; - case STATE_CAUSE_HMAC: - str = "hmac"; - break; - case STATE_CAUSE_SYSTEM_LABEL: - str = "system_label"; - break; - case STATE_CAUSE_NOCERT: - str = "nocert"; - break; - case STATE_CAUSE_MISMATCH_LABEL: - str = "mismatch_label"; - break; - case STATE_CAUSE_TAMPERED: - str = "tampered"; - break; - case STATE_CAUSE_UNKNOWN: - str = "unknown"; - break; - } - - return str; -} - -__visible_for_testing -enum task_integrity_reset_cause state_to_reason_cause( - enum task_integrity_state_cause cause) -{ - enum task_integrity_reset_cause reset_cause; - - switch (cause) { - case STATE_CAUSE_UNKNOWN: - reset_cause = CAUSE_UNKNOWN; - break; - case STATE_CAUSE_TAMPERED: - reset_cause = CAUSE_TAMPERED; - break; - case STATE_CAUSE_NOCERT: - reset_cause = CAUSE_NO_CERT; - break; - case STATE_CAUSE_MISMATCH_LABEL: - reset_cause = CAUSE_MISMATCH_LABEL; - break; - default: - /* Integrity is not NONE. */ - reset_cause = CAUSE_UNSET; - break; - } - - return reset_cause; -} - -__visible_for_testing -int is_system_label(struct integrity_label *label) -{ - if (label && label->len == 0) - return 1; /* system label */ - - return 0; -} - -__visible_for_testing -inline int integrity_label_cmp(struct integrity_label *l1, - struct integrity_label *l2) -{ - return 0; -} - -__visible_for_testing -int verify_or_update_label(struct task_integrity *intg, - struct integrity_iint_cache *iint) -{ - struct integrity_label *l; - struct integrity_label *file_label = iint->five_label; - int rc = 0; - - if (!file_label) /* digsig doesn't have label */ - return 0; - - if (is_system_label(file_label)) - return 0; - - spin_lock(&intg->value_lock); - l = intg->label; - - if (l) { - if (integrity_label_cmp(file_label, l)) { - rc = -EPERM; - goto out; - } - } else { - struct integrity_label *new_label; - - new_label = kmalloc(sizeof(file_label->len) + file_label->len, - GFP_ATOMIC); - if (!new_label) { - rc = -ENOMEM; - goto out; - } - - new_label->len = file_label->len; - memcpy(new_label->data, file_label->data, new_label->len); - intg->label = new_label; - } - -out: - spin_unlock(&intg->value_lock); - - return rc; -} - -__visible_for_testing -bool set_first_state(struct integrity_iint_cache *iint, - struct task_integrity *integrity, - struct task_verification_result *result) -{ - enum task_integrity_value tint = INTEGRITY_NONE; - enum five_file_integrity status = five_get_cache_status(iint); - bool trusted_file = iint->five_flags & FIVE_TRUSTED_FILE; - enum task_integrity_state_cause cause = STATE_CAUSE_UNKNOWN; - - result->new_tint = result->prev_tint = task_integrity_read(integrity); - task_integrity_clear(integrity); - - switch (status) { - case FIVE_FILE_RSA: - if (trusted_file) { - cause = STATE_CAUSE_TRUSTED; - tint = INTEGRITY_PRELOAD_ALLOW_SIGN; - } else { - cause = STATE_CAUSE_DIGSIG; - tint = INTEGRITY_PRELOAD; - } - break; - case FIVE_FILE_FSVERITY: - case FIVE_FILE_DMVERITY: - if (trusted_file) { - cause = STATE_CAUSE_TRUSTED; - tint = INTEGRITY_DMVERITY_ALLOW_SIGN; - } else { - cause = (status == FIVE_FILE_FSVERITY) - ? STATE_CAUSE_FSV_PROTECTED - : STATE_CAUSE_DMV_PROTECTED; - tint = INTEGRITY_DMVERITY; - } - break; - case FIVE_FILE_HMAC: - cause = STATE_CAUSE_HMAC; - tint = INTEGRITY_MIXED; - break; - case FIVE_FILE_FAIL: - cause = STATE_CAUSE_TAMPERED; - tint = INTEGRITY_NONE; - break; - case FIVE_FILE_UNKNOWN: - cause = STATE_CAUSE_NOCERT; - tint = INTEGRITY_NONE; - break; - default: - cause = STATE_CAUSE_NOCERT; - tint = INTEGRITY_NONE; - break; - } - - task_integrity_set(integrity, tint); - result->new_tint = tint; - result->cause = cause; - - return true; -} - -__visible_for_testing -bool set_next_state(struct integrity_iint_cache *iint, - struct task_integrity *integrity, - struct task_verification_result *result) -{ - bool is_newstate = false; - enum five_file_integrity status = five_get_cache_status(iint); - bool has_digsig = (status == FIVE_FILE_RSA); - bool dmv_protected = (status == FIVE_FILE_DMVERITY); - bool fsv_protected = (status == FIVE_FILE_FSVERITY); - bool xv_protected = dmv_protected || fsv_protected; - struct integrity_label *label = iint->five_label; - enum task_integrity_state_cause cause = STATE_CAUSE_UNKNOWN; - enum task_integrity_value state_tint = INTEGRITY_NONE; - - result->new_tint = result->prev_tint = task_integrity_read(integrity); - - if (has_digsig) - return is_newstate; - - if (status == FIVE_FILE_UNKNOWN || status == FIVE_FILE_FAIL) { - spin_lock(&integrity->value_lock); - - if (status == FIVE_FILE_UNKNOWN) - cause = STATE_CAUSE_NOCERT; - else - cause = STATE_CAUSE_TAMPERED; - - state_tint = INTEGRITY_NONE; - is_newstate = true; - goto out; - } - - if (verify_or_update_label(integrity, iint)) { - spin_lock(&integrity->value_lock); - cause = STATE_CAUSE_MISMATCH_LABEL; - state_tint = INTEGRITY_NONE; - is_newstate = true; - goto out; - } - - spin_lock(&integrity->value_lock); - switch (integrity->value) { - case INTEGRITY_PRELOAD_ALLOW_SIGN: - if (xv_protected) { - cause = fsv_protected ? STATE_CAUSE_FSV_PROTECTED - : STATE_CAUSE_DMV_PROTECTED; - state_tint = INTEGRITY_DMVERITY_ALLOW_SIGN; - } else if (is_system_label(label)) { - cause = STATE_CAUSE_SYSTEM_LABEL; - state_tint = INTEGRITY_MIXED_ALLOW_SIGN; - } else { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - } - is_newstate = true; - break; - case INTEGRITY_PRELOAD: - if (xv_protected) { - cause = fsv_protected ? STATE_CAUSE_FSV_PROTECTED - : STATE_CAUSE_DMV_PROTECTED; - state_tint = INTEGRITY_DMVERITY; - } else { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - } - is_newstate = true; - break; - case INTEGRITY_MIXED_ALLOW_SIGN: - if (!xv_protected && !is_system_label(label)) { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - is_newstate = true; - } - break; - case INTEGRITY_DMVERITY: - if (!xv_protected) { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - is_newstate = true; - } - break; - case INTEGRITY_DMVERITY_ALLOW_SIGN: - if (!xv_protected) { - if (is_system_label(label)) { - cause = STATE_CAUSE_SYSTEM_LABEL; - state_tint = INTEGRITY_MIXED_ALLOW_SIGN; - } else { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - } - is_newstate = true; - } - break; - case INTEGRITY_MIXED: - break; - case INTEGRITY_NONE: - break; - default: - // Unknown state - cause = STATE_CAUSE_UNKNOWN; - state_tint = INTEGRITY_NONE; - is_newstate = true; - } - -out: - - if (is_newstate) { - __task_integrity_set(integrity, state_tint); - result->new_tint = state_tint; - result->cause = cause; - } - spin_unlock(&integrity->value_lock); - - return is_newstate; -} - -void five_state_proceed(struct task_integrity *integrity, - struct file_verification_result *file_result) -{ - struct integrity_iint_cache *iint = file_result->iint; - enum five_hooks fn = file_result->fn; - struct task_struct *task = file_result->task; - struct file *file = file_result->file; - bool is_newstate; - struct task_verification_result task_result = {}; - - if (!iint) - return; - - if (fn == BPRM_CHECK) - is_newstate = set_first_state(iint, integrity, &task_result); - else - is_newstate = set_next_state(iint, integrity, &task_result); - - if (is_newstate) { - if (task_result.new_tint == INTEGRITY_NONE) { - task_integrity_set_reset_reason(integrity, - state_to_reason_cause(task_result.cause), file); - five_hook_integrity_reset(task, file, - state_to_reason_cause(task_result.cause)); - - if (fn != BPRM_CHECK) { - char comm[TASK_COMM_LEN]; - char filename[NAME_MAX]; - char *pathbuf = NULL; - - five_dsms_reset_integrity( - get_task_comm(comm, task), - task_result.cause, - five_d_path(&file->f_path, &pathbuf, - filename)); - if (pathbuf) - __putname(pathbuf); - } - } - five_audit_verbose(task, file, five_get_string_fn(fn), - task_result.prev_tint, task_result.new_tint, - task_integrity_state_str(task_result.cause), - file_result->five_result); - } -} - diff --git a/security/samsung/five/five_state.h b/security/samsung/five/five_state.h deleted file mode 100755 index 358e570bf..000000000 --- a/security/samsung/five/five_state.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * FIVE State machine - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_STATE_MACHINE_H -#define __LINUX_FIVE_STATE_MACHINE_H - -#include "five.h" - -void five_state_proceed(struct task_integrity *integrity, - struct file_verification_result *result); - -#endif // __LINUX_FIVE_STATE_MACHINE_H diff --git a/security/samsung/five/five_tee_api.h b/security/samsung/five/five_tee_api.h deleted file mode 100755 index 6312813fd..000000000 --- a/security/samsung/five/five_tee_api.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * FIVE TEE API - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_TEE_API_H -#define __LINUX_FIVE_TEE_API_H - -#include <crypto/hash_info.h> -#include <linux/types.h> -#include <five_tee_interface.h> - -int verify_hash(enum hash_algo algo, const void *hash, size_t hash_len, - const void *label, size_t label_len, - const void *signature, size_t signature_len); -int sign_hash(enum hash_algo algo, const void *hash, size_t hash_len, - const void *label, size_t label_len, - void *signature, size_t *signature_len); - -#endif /* __LINUX_FIVE_TEE_API_H */ diff --git a/security/samsung/five/five_tee_interface.c b/security/samsung/five/five_tee_interface.c deleted file mode 100755 index e7291c06e..000000000 --- a/security/samsung/five/five_tee_interface.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Interface for TEE Driver - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <crypto/hash_info.h> -#include "five_tee_interface.h" -#include "five_tee_api.h" - -static struct five_tee_driver_fns *g_tee_driver_fn; -static char is_registered; -static DECLARE_RWSEM(usage_lock); - -int register_five_tee_driver( - struct five_tee_driver_fns *tee_driver_fns) -{ - int rc = 0; - - if (!tee_driver_fns) - return -EINVAL; - - down_write(&usage_lock); - if (is_registered) { - rc = -EACCES; - goto exit; - } - - g_tee_driver_fn = kmalloc(sizeof(*g_tee_driver_fn), GFP_KERNEL); - if (!g_tee_driver_fn) { - rc = -ENOMEM; - goto exit; - } - - g_tee_driver_fn->verify_hmac = tee_driver_fns->verify_hmac; - g_tee_driver_fn->sign_hmac = tee_driver_fns->sign_hmac; - is_registered = 1; - -exit: - up_write(&usage_lock); - - return rc; -} -EXPORT_SYMBOL_GPL(register_five_tee_driver); - -void unregister_five_tee_driver(void) -{ - down_write(&usage_lock); - if (is_registered) { - kfree(g_tee_driver_fn); - g_tee_driver_fn = NULL; - is_registered = 0; - } - up_write(&usage_lock); -} -EXPORT_SYMBOL_GPL(unregister_five_tee_driver); - -int verify_hash(enum hash_algo algo, const void *hash, size_t hash_len, - const void *label, size_t label_len, - const void *signature, size_t signature_len) -{ - int rc = -ENODEV; - struct tee_iovec args = { - .algo = algo, - .hash = hash, - .hash_len = hash_len, - .label = label, - .label_len = label_len, - .signature = (void *)signature, - .signature_len = signature_len - }; - - down_read(&usage_lock); - if (is_registered) - rc = g_tee_driver_fn->verify_hmac(&args); - up_read(&usage_lock); - - return rc; -} - -int sign_hash(enum hash_algo algo, const void *hash, size_t hash_len, - const void *label, size_t label_len, - void *signature, size_t *signature_len) -{ - int rc = -ENODEV; - struct tee_iovec args = { - .algo = algo, - .hash = hash, - .hash_len = hash_len, - .label = label, - .label_len = label_len, - .signature = signature, - .signature_len = *signature_len - }; - - down_read(&usage_lock); - if (is_registered) - rc = g_tee_driver_fn->sign_hmac(&args); - up_read(&usage_lock); - - *signature_len = args.signature_len; - - return rc; -} diff --git a/security/samsung/five/five_tee_interface.h b/security/samsung/five/five_tee_interface.h deleted file mode 100755 index 6ff986d05..000000000 --- a/security/samsung/five/five_tee_interface.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Interface for TEE Driver - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef INTEGRITY_TEE_DRIVER_H -#define INTEGRITY_TEE_DRIVER_H - -#include <linux/types.h> -#include <crypto/hash_info.h> - -struct tee_iovec { - enum hash_algo algo; - - const void *hash; - size_t hash_len; - - const void *label; - size_t label_len; - - void *signature; - size_t signature_len; - - int rc; -}; - -struct five_tee_driver_fns { - int (*verify_hmac)(const struct tee_iovec *verify_args); - int (*sign_hmac)(struct tee_iovec *sign_args); -}; - -int register_five_tee_driver( - struct five_tee_driver_fns *tee_driver_fns); -void unregister_five_tee_driver(void); - -#endif diff --git a/security/samsung/five/five_testing.h b/security/samsung/five/five_testing.h deleted file mode 100755 index d058cbce8..000000000 --- a/security/samsung/five/five_testing.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __LINUX_FIVE_TESTING_H -#define __LINUX_FIVE_TESTING_H - -#if defined(FIVE_KUNIT_ENABLED) || defined(PROCA_KUNIT_ENABLED) -#define KUNIT_UML // this define should be used for adding UML-specific modifications -#define __mockable __weak -#define __visible_for_testing -/* <for five_dsms.c> dsms_send_message stub. Never called. - * To isolate FIVE from DSMS during KUnit testing - */ -static inline int dsms_send_message(const char *feature_code, - const char *detail, - int64_t value) -{ return 1; } -// <for five_main.c: five_ptrace(...)> -#ifdef KUNIT_UML -#define COMPAT_PTRACE_GETREGS 12 -#define COMPAT_PTRACE_GET_THREAD_AREA 22 -#define COMPAT_PTRACE_GETVFPREGS 27 -#define COMPAT_PTRACE_GETHBPREGS 29 -#endif -#else -#define __mockable -#define __visible_for_testing static -#endif // FIVE_KUNIT_ENABLED || PROCA_KUNIT_ENABLED - -#endif // __LINUX_FIVE_TESTING_H diff --git a/security/samsung/five/gki/five.h b/security/samsung/five/gki/five.h deleted file mode 100755 index 516811e77..000000000 --- a/security/samsung/five/gki/five.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_H -#define __LINUX_FIVE_H - -#include <linux/types.h> -#include <linux/crypto.h> -#include <linux/security.h> -#include <linux/hash.h> -#include <linux/audit.h> -#include <linux/workqueue.h> - -#include "five_cert.h" -#include "five_crypto.h" - -/* set during initialization */ -extern int five_hash_algo; -struct worker_context { - struct work_struct data_work; - struct task_integrity *tint; -}; - -struct f_signature_task { - struct task_integrity *tint; - struct file *file; -}; - -struct f_signature_context { - struct work_struct data_work; - struct f_signature_task payload; -}; - -struct five_stat { - u64 inode_iversion; - u64 cache_iversion; - u32 cache_status; - u32 is_dm_verity; -}; - -/* Internal FIVE function definitions */ -int five_init(void); - -/* FIVE policy related functions */ -enum five_hooks { - FILE_CHECK = 1, - MMAP_CHECK, - BPRM_CHECK, - POST_SETATTR -}; - -struct file_verification_result { - struct task_struct *task; - struct file *file; - struct integrity_iint_cache *iint; - enum five_hooks fn; - int five_result; - void *xattr; - size_t xattr_len; -}; - -static inline void file_verification_result_init( - struct file_verification_result *result) -{ - memset(result, 0, sizeof(*result)); -} - -static inline void file_verification_result_deinit( - struct file_verification_result *result) -{ - kfree(result->xattr); - memset(result, 0, sizeof(*result)); -} - -int five_appraise_measurement(struct task_struct *task, int func, - struct integrity_iint_cache *iint, - struct file *file, - struct five_cert *cert); - -int five_read_xattr(struct dentry *dentry, char **xattr_value); -int five_check_params(struct task_struct *task, struct file *file); -const char *five_d_path(const struct path *path, char **pathbuf, - char *namebuf); - -int five_digsig_verify(struct five_cert *cert, - const char *digest, int digestlen); -int five_reboot_notifier(struct notifier_block *nb, - unsigned long action, void *unused); -int __init five_load_built_x509(void); -int __init five_keyring_init(void); -int __init five_task_integrity_cache_init(void); - -const char *five_get_string_fn(enum five_hooks fn); -#endif diff --git a/security/samsung/five/gki/five_appraise.c b/security/samsung/five/gki/five_appraise.c deleted file mode 100755 index 8f00e7d84..000000000 --- a/security/samsung/five/gki/five_appraise.c +++ /dev/null @@ -1,854 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/xattr.h> -#include <linux/magic.h> -#include <crypto/hash_info.h> - -#include <linux/task_integrity.h> -#include "five.h" -#include "five_audit.h" -#include "five_hooks.h" -#include "five_tee_api.h" -#include "five_porting.h" -#include "five_cache.h" -#include "five_dmverity.h" -#include "five_vfs.h" - -#define FIVE_RSA_SIGNATURE_MAX_LENGTH (2048/8) -/* Identify extend structure of integrity label */ -#define FIVE_ID_INTEGRITY_LABEL_EX 0xFFFF -#define FIVE_LABEL_VERSION1 1 -/* Maximum length of data integrity label. - * This limit is applied because: - * 1. TEEgris doesn't support signing data longer than 480 bytes; - * 2. The label's length is limited to 3965 byte according to the data - * transmission protocol between five_tee_driver and TA. - */ -#define FIVE_LABEL_MAX_LEN 256 - -/** - * Extend structure of integrity label. - * If field "len" equals 0xffff then it is extend integrity label, - * otherwise simple integrity label. - */ -struct integrity_label_ex { - uint16_t len; - uint8_t version; - uint8_t reserved[2]; - uint8_t hash_algo; - uint8_t hash[64]; - struct integrity_label label; -} __packed; - -#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP -static const bool panic_on_error = true; -#else -static const bool panic_on_error; -#endif - -static DECLARE_RWSEM(sign_fcntl_lock); - -/* - * five_collect_measurement - collect file measurement - * - * Must be called with iint->mutex held. - * - * Return 0 on success, error code otherwise. - */ -static int five_collect_measurement(struct file *file, u8 hash_algo, - u8 *hash, size_t hash_len) -{ - int result = 0; - - BUG_ON(!file || !hash); - - result = five_calc_file_hash(file, hash_algo, hash, &hash_len); - if (result) { - five_audit_err(current, file, "collect_measurement", 0, - 0, "calculate file hash failed", result); - } - return result; -} - -static int get_integrity_label(struct five_cert *cert, - void **label_data, size_t *label_len) -{ - int rc = -ENODATA; - struct five_cert_header *header = - (struct five_cert_header *)cert->body.header->value; - - if (header && header->signature_type == FIVE_XATTR_HMAC) { - *label_data = cert->body.label->value; - *label_len = cert->body.label->length; - rc = 0; - } - return rc; -} - -static int get_signature(struct five_cert *cert, void **sig, - size_t *sig_len) -{ - int rc = -ENODATA; - struct five_cert_header *header = - (struct five_cert_header *)cert->body.header->value; - - if (header && header->signature_type == FIVE_XATTR_HMAC) { - if (cert->signature->length == 0) - return rc; - *sig = cert->signature->value; - *sig_len = cert->signature->length; - - rc = 0; - } - - return rc; -} - -static int update_label(struct integrity_iint_cache *iint, - const void *label_data, size_t label_len) -{ - struct integrity_label *l; - - if (!label_data) - return 0; - - l = kmalloc(sizeof(struct integrity_label) + label_len, GFP_NOFS); - if (l) { - l->len = label_len; - memcpy(l->data, label_data, label_len); - kfree(iint->five_label); - iint->five_label = l; - } else { - return -ENOMEM; - } - - return 0; -} - -static int five_fix_xattr(struct task_struct *task, - struct dentry *dentry, - struct file *file, - void **raw_cert, - size_t *raw_cert_len, - struct integrity_iint_cache *iint, - struct integrity_label_ex *label) -{ - int rc = 0; - u8 hash[FIVE_MAX_DIGEST_SIZE], *hash_file, *sig = NULL; - size_t hash_len = sizeof(hash), hash_file_len, sig_len; - void *file_label = label->label.data; - u16 file_label_len = label->label.len; - struct five_cert_body body_cert = {0}; - struct five_cert_header *header; - - BUG_ON(!task || !dentry || !file || !raw_cert || !(*raw_cert) || !iint); - BUG_ON(!raw_cert_len); - - rc = five_cert_body_fillout(&body_cert, *raw_cert, *raw_cert_len); - if (unlikely(rc)) - return -EINVAL; - - header = (struct five_cert_header *)body_cert.header->value; - hash_file = body_cert.hash->value; - hash_file_len = body_cert.hash->length; - if (unlikely(!header || !hash_file)) - return -EINVAL; - - if (label->version == FIVE_LABEL_VERSION1) { - rc = five_collect_measurement(file, header->hash_algo, - hash_file, hash_file_len); - if (unlikely(rc)) - return rc; - } else { - memcpy(hash_file, label->hash, hash_file_len); - } - - rc = five_cert_calc_hash(&body_cert, hash, &hash_len); - if (unlikely(rc)) - return rc; - - sig_len = (size_t)body_cert.hash->length + file_label_len; - - sig = kzalloc(sig_len, GFP_NOFS); - if (!sig) - return -ENOMEM; - - rc = sign_hash(header->hash_algo, hash, hash_len, - file_label, file_label_len, sig, &sig_len); - - if (!rc) { - rc = five_cert_append_signature(raw_cert, raw_cert_len, - sig, sig_len); - if (!rc) { - int count = 1; - - do { - rc = five_setxattr_noperm(d_real_comp(dentry), - XATTR_NAME_FIVE, - *raw_cert, - *raw_cert_len, - 0); - count--; - } while (count >= 0 && rc != 0); - - if (!rc) { - rc = update_label(iint, - file_label, file_label_len); - } - } - } else if (panic_on_error) { - panic("FIVE failed to sign %s (ret code = %d)", - dentry->d_name.name, rc); - } else { - five_audit_sign_err(current, file, "fix_xattr", 0, - 0, "can't sign the file", rc); - } - - kfree(sig); - - return rc; -} - -int five_read_xattr(struct dentry *dentry, char **xattr_value) -{ - ssize_t ret; - - ret = five_getxattr_alloc(dentry, XATTR_NAME_FIVE, xattr_value, - 0, GFP_NOFS); - if (ret < 0) - ret = 0; - - return ret; -} - -static bool bad_fs(struct inode *inode) -{ - if (inode->i_sb->s_magic == EXT4_SUPER_MAGIC || - inode->i_sb->s_magic == F2FS_SUPER_MAGIC || - inode->i_sb->s_magic == OVERLAYFS_SUPER_MAGIC || - inode->i_sb->s_magic == EROFS_SUPER_MAGIC_V1) - return false; - - return true; -} - -static bool readonly_sb(struct inode *inode) -{ - if (inode->i_sb->s_flags & MS_RDONLY) - return true; - - return false; -} - -/* - * five_is_fsverity_protected - checks if file is protected by FSVERITY - * - * Return true/false - */ -static bool five_is_fsverity_protected(const struct inode *inode) -{ - return IS_VERITY(inode); -} - -/* - * five_appraise_measurement - appraise file measurement - * - * Return 0 on success, error code otherwise - */ -int five_appraise_measurement(struct task_struct *task, int func, - struct integrity_iint_cache *iint, - struct file *file, - struct five_cert *cert) -{ - enum task_integrity_reset_cause cause = CAUSE_UNKNOWN; - struct dentry *dentry = NULL; - struct inode *inode = NULL; - enum five_file_integrity status = FIVE_FILE_UNKNOWN; - enum task_integrity_value prev_integrity; - int rc = 0; - u8 *file_hash; - u8 stored_file_hash[FIVE_MAX_DIGEST_SIZE] = {0}; - size_t file_hash_len = 0; - struct five_cert_header *header = NULL; - - BUG_ON(!task || !iint || !file); - - prev_integrity = task_integrity_read(TASK_INTEGRITY(task)); - dentry = file->f_path.dentry; - inode = d_backing_inode(dentry); - - if (bad_fs(inode)) { - status = FIVE_FILE_FAIL; - cause = CAUSE_BAD_FS; - rc = -ENOTSUPP; - goto out; - } - - if (!cert) { - cause = CAUSE_NO_CERT; - if (five_is_fsverity_protected(inode)) - status = FIVE_FILE_FSVERITY; - else if (five_is_dmverity_protected(file)) - status = FIVE_FILE_DMVERITY; - goto out; - } - - header = (struct five_cert_header *)cert->body.header->value; - file_hash = cert->body.hash->value; - file_hash_len = cert->body.hash->length; - if (file_hash_len > sizeof(stored_file_hash)) { - cause = CAUSE_INVALID_HASH_LENGTH; - rc = -EINVAL; - goto out; - } - - memcpy(stored_file_hash, file_hash, file_hash_len); - - if (unlikely(!header || !file_hash)) { - cause = CAUSE_INVALID_HEADER; - rc = -EINVAL; - goto out; - } - - rc = five_collect_measurement(file, header->hash_algo, file_hash, - file_hash_len); - if (rc) { - cause = CAUSE_CALC_HASH_FAILED; - goto out; - } - - switch (header->signature_type) { - case FIVE_XATTR_HMAC: { - u8 *sig = NULL; - u8 algo = header->hash_algo; - void *file_label_data; - size_t file_label_len, sig_len = 0; - u8 cert_hash[FIVE_MAX_DIGEST_SIZE] = {0}; - size_t cert_hash_len = sizeof(cert_hash); - - status = FIVE_FILE_FAIL; - - rc = get_integrity_label(cert, &file_label_data, - &file_label_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_LABEL_DATA; - break; - } - - if (unlikely(file_label_len > PAGE_SIZE)) { - cause = CAUSE_INVALID_LABEL_DATA; - break; - } - - rc = get_signature(cert, (void **)&sig, &sig_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_SIGNATURE_DATA; - break; - } - - rc = five_cert_calc_hash(&cert->body, cert_hash, - &cert_hash_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_CALC_CERT_HASH; - break; - } - - rc = verify_hash(algo, cert_hash, - cert_hash_len, - file_label_data, file_label_len, - sig, sig_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_HASH; - if (cert) { - five_audit_hexinfo(file, "stored hash", - stored_file_hash, file_hash_len); - five_audit_hexinfo(file, "calculated hash", - file_hash, file_hash_len); - five_audit_hexinfo(file, "HMAC signature", - sig, sig_len); - } - break; - } - - rc = update_label(iint, file_label_data, file_label_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_UPDATE_LABEL; - break; - } - - status = FIVE_FILE_HMAC; - - break; - } - case FIVE_XATTR_DIGSIG: { - u8 cert_hash[FIVE_MAX_DIGEST_SIZE] = {0}; - size_t cert_hash_len = sizeof(cert_hash); - - status = FIVE_FILE_FAIL; - - rc = five_cert_calc_hash(&cert->body, cert_hash, - &cert_hash_len); - if (unlikely(rc)) { - cause = CAUSE_INVALID_CALC_CERT_HASH; - break; - } - - rc = five_digsig_verify(cert, cert_hash, cert_hash_len); - - if (rc) { - cause = CAUSE_INVALID_SIGNATURE; - if (cert) { - five_audit_hexinfo(file, "stored hash", - stored_file_hash, file_hash_len); - five_audit_hexinfo(file, "calculated hash", - file_hash, file_hash_len); - five_audit_hexinfo(file, "RSA signature", - cert->signature->value, - cert->signature->length); - } - break; - } - - status = FIVE_FILE_RSA; - - break; - } - default: - status = FIVE_FILE_FAIL; - cause = CAUSE_UKNOWN_FIVE_DATA; - break; - } - -out: - if (status == FIVE_FILE_FAIL || status == FIVE_FILE_UNKNOWN) { - task_integrity_set_reset_reason(TASK_INTEGRITY(task), - cause, file); - five_audit_verbose(task, file, five_get_string_fn(func), - prev_integrity, prev_integrity, - tint_reset_cause_to_string(cause), rc); - } - - five_set_cache_status(iint, status); - - return rc; -} - -/* - * five_update_xattr - update 'security.five' hash value - */ -static int five_update_xattr(struct task_struct *task, - struct integrity_iint_cache *iint, struct file *file, - struct integrity_label_ex *label) -{ - struct dentry *dentry; - int rc = 0; - uint8_t *hash; - size_t hash_len; - uint8_t *raw_cert; - size_t raw_cert_len; - struct five_cert_header header = { - .version = FIVE_CERT_VERSION1, - .privilege = FIVE_PRIV_DEFAULT, - .hash_algo = five_hash_algo, - .signature_type = FIVE_XATTR_HMAC }; - - BUG_ON(!task || !iint || !file || !label); - - if (label->version == FIVE_LABEL_VERSION1) { - hash_len = (size_t)hash_digest_size[five_hash_algo]; - } else { - header.hash_algo = label->hash_algo; - if (label->hash_algo >= HASH_ALGO__LAST) - return -EINVAL; - - hash_len = (size_t)hash_digest_size[label->hash_algo]; - if (hash_len > sizeof(label->hash)) - return -EINVAL; - } - - hash = kzalloc(hash_len, GFP_KERNEL); - if (!hash) - return -ENOMEM; - - dentry = file->f_path.dentry; - - /* do not collect and update hash for digital signatures */ - if (five_get_cache_status(iint) == FIVE_FILE_RSA) { - char dummy[512]; - struct inode *inode = file_inode(file); - - rc = __vfs_getxattr(d_real_comp(dentry), inode, XATTR_NAME_FIVE, - dummy, sizeof(dummy), XATTR_NOSECURITY); - - // Check if xattr is exist - if (rc > 0 || rc != -ENODATA) { - kfree(hash); - return -EPERM; - } else { // xattr does not exist. - five_set_cache_status(iint, FIVE_FILE_UNKNOWN); - pr_err("FIVE: ERROR: Cache is unsynchronized"); - } - } - - rc = five_cert_body_alloc(&header, hash, hash_len, - label->label.data, label->label.len, - &raw_cert, &raw_cert_len); - if (rc) - goto exit; - - if (task_integrity_allow_sign(TASK_INTEGRITY(task))) { - rc = five_fix_xattr(task, dentry, file, - (void **)&raw_cert, &raw_cert_len, iint, label); - if (rc) - pr_err("FIVE: Can't sign hash: rc=%d\n", rc); - } else { - rc = -EPERM; - } - - five_hook_file_signed(task, file, raw_cert, raw_cert_len, rc); - - five_cert_free(raw_cert); - -exit: - kfree(hash); - return rc; -} - -static void five_reset_appraise_flags(struct dentry *dentry) -{ - struct inode *inode = d_backing_inode(dentry); - struct integrity_iint_cache *iint; - - if (!S_ISREG(inode->i_mode)) - return; - - iint = integrity_iint_find(inode); - if (iint) - five_set_cache_status(iint, FIVE_FILE_UNKNOWN); -} - -/** - * five_inode_post_setattr - reflect file metadata changes - * @dentry: pointer to the affected dentry - * - * Changes to a dentry's metadata might result in needing to appraise. - * - * This function is called from notify_change(), which expects the caller - * to lock the inode's i_mutex. - */ -void five_inode_post_setattr(struct task_struct *task, struct dentry *dentry) -{ - five_reset_appraise_flags(dentry); -} - -/* - * five_protect_xattr - protect 'security.five' - * - * Ensure that not just anyone can modify or remove 'security.five'. - */ -static int five_protect_xattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) -{ - if (strcmp(xattr_name, XATTR_NAME_FIVE) == 0) { - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return 1; - } - return 0; -} - -int five_inode_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) -{ - int result = five_protect_xattr(dentry, xattr_name, xattr_value, - xattr_value_len); - - if (result == 1 && xattr_value_len == 0) { - five_reset_appraise_flags(dentry); - return 0; - } - - if (result == 1) { - bool digsig; - struct five_cert_header *header; - struct five_cert cert = { {0} }; - - result = five_cert_fillout(&cert, xattr_value, xattr_value_len); - if (result) - return result; - - header = (struct five_cert_header *)cert.body.header->value; - - if (!xattr_value_len || !header || - (header->signature_type >= FIVE_XATTR_END)) - return -EINVAL; - - digsig = (header->signature_type == FIVE_XATTR_DIGSIG); - if (!digsig) - return -EPERM; - - five_reset_appraise_flags(dentry); - result = 0; - } - - return result; -} - -int five_inode_removexattr(struct dentry *dentry, const char *xattr_name) -{ - int result; - - result = five_protect_xattr(dentry, xattr_name, NULL, 0); - if (result == 1) { - five_reset_appraise_flags(dentry); - result = 0; - } - return result; -} - -int five_reboot_notifier(struct notifier_block *nb, - unsigned long action, void *unused) -{ - down_write(&sign_fcntl_lock); - /* Need to wait for five_fcntl_sign finish */ - up_write(&sign_fcntl_lock); - - return NOTIFY_DONE; -} - -static int copy_label(const struct integrity_label __user *ulabel, - struct integrity_label_ex **out_label) -{ - u16 len; - size_t label_len; - int rc = 0; - struct integrity_label_ex header = {0}; - struct integrity_label_ex *label = NULL; - - if (unlikely(!ulabel || !out_label)) { - rc = -EINVAL; - goto error; - } - - if (unlikely(copy_from_user(&len, ulabel, sizeof(len)))) { - rc = -EFAULT; - goto error; - } - - if (len == FIVE_ID_INTEGRITY_LABEL_EX) { - if (unlikely(copy_from_user(&header, ulabel, sizeof(header)))) { - rc = -EFAULT; - goto error; - } - - if (len != header.len || - header.label.len > FIVE_LABEL_MAX_LEN || - header.version <= FIVE_LABEL_VERSION1) { - rc = -EINVAL; - goto error; - } - - label_len = sizeof(header) + header.label.len; - - label = kzalloc(label_len, GFP_NOFS); - if (unlikely(!label)) { - rc = -ENOMEM; - goto error; - } - - memcpy(label, &header, sizeof(header)); - if (unlikely(copy_from_user(&label->label.data[0], - (const u8 __user *)ulabel + sizeof(header), - label_len - sizeof(header)))) { - rc = -EFAULT; - goto error; - } - } else { - if (len > FIVE_LABEL_MAX_LEN) { - rc = -EINVAL; - goto error; - } - - label_len = sizeof(header) + len; - - label = kzalloc(label_len, GFP_NOFS); - if (unlikely(!label)) { - rc = -ENOMEM; - goto error; - } - - if (unlikely(copy_from_user(&label->label, ulabel, - sizeof(len) + len))) { - rc = -EFAULT; - goto error; - } - - if (len != label->label.len) { - rc = -EINVAL; - goto error; - } - - label->version = FIVE_LABEL_VERSION1; - } - - *out_label = label; -error: - if (rc) - kfree(label); - - return rc; -} - -/* Called from do_fcntl */ -int five_fcntl_sign(struct file *file, struct integrity_label __user *label) -{ - struct integrity_iint_cache *iint; - struct inode *inode = file_inode(file); - struct integrity_label_ex *l = NULL; - int rc = 0; - - if (!S_ISREG(inode->i_mode)) - return -EINVAL; - - if (readonly_sb(inode)) { - pr_err("FIVE: Can't sign a file on RO FS\n"); - return -EROFS; - } - - if (task_integrity_allow_sign(TASK_INTEGRITY(current))) { - rc = copy_label(label, &l); - if (rc) { - pr_err("FIVE: Can't copy integrity label\n"); - return rc; - } - } else { - enum task_integrity_value tint = - task_integrity_read(TASK_INTEGRITY(current)); - - five_audit_err(current, file, "fcntl_sign", tint, tint, - "sign:no-perm", -EPERM); - return -EPERM; - } - - iint = integrity_inode_get(inode); - if (!iint) { - kfree(l); - return -ENOMEM; - } - - if (file->f_op && file->f_op->flush) { - if (file->f_op->flush(file, current->files)) { - kfree(l); - return -EOPNOTSUPP; - } - } - - down_read(&sign_fcntl_lock); - inode_lock(inode); - rc = five_update_xattr(current, iint, file, l); - iint->five_signing = false; - inode_unlock(inode); - up_read(&sign_fcntl_lock); - - kfree(l); - - return rc; -} - -static int check_input_inode(struct inode *inode) -{ - if (!S_ISREG(inode->i_mode)) - return -EINVAL; - - if (readonly_sb(inode)) { - pr_err("FIVE: Can't sign a file on RO FS\n"); - return -EROFS; - } - - return 0; -} - -int five_fcntl_edit(struct file *file) -{ - int rc; - struct dentry *dentry; - uint8_t *raw_cert = NULL; - size_t raw_cert_len = 0; - struct integrity_iint_cache *iint; - struct inode *inode = file_inode(file); - - rc = check_input_inode(inode); - if (rc) - return rc; - - if (!task_integrity_allow_sign(TASK_INTEGRITY(current))) - return -EPERM; - - inode_lock(inode); - dentry = file->f_path.dentry; - rc = five_setxattr_noperm(d_real_comp(dentry), - XATTR_NAME_FIVE, - raw_cert, - raw_cert_len, - 0); - iint = integrity_inode_get(inode); - if (iint) - iint->five_signing = true; - inode_unlock(inode); - - return rc; -} - -int five_fcntl_close(struct file *file) -{ - int rc; - ssize_t xattr_len; - struct dentry *dentry; - struct integrity_iint_cache *iint; - struct inode *inode = file_inode(file); - - rc = check_input_inode(inode); - if (rc) - return rc; - - inode_lock(inode); - iint = integrity_inode_get(inode); - if (!iint) { - inode_unlock(inode); - return -ENOMEM; - } - - if (iint->five_signing) { - dentry = file->f_path.dentry; - xattr_len = __vfs_getxattr(d_real_comp(dentry), inode, - XATTR_NAME_FIVE, NULL, 0, XATTR_NOSECURITY); - if (xattr_len == 0) - rc = __vfs_removexattr(d_real_comp(dentry), - XATTR_NAME_FIVE); - - iint->five_signing = false; - } - inode_unlock(inode); - - return rc; -} diff --git a/security/samsung/five/gki/five_audit.c b/security/samsung/five/gki/five_audit.c deleted file mode 100755 index dd49bd0bc..000000000 --- a/security/samsung/five/gki/five_audit.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Audit calls for FIVE audit subsystem. - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/fs.h> -#include <linux/gfp.h> -#include <linux/audit.h> -#include <linux/task_integrity.h> -#include "five.h" -#include "five_audit.h" -#include "five_cache.h" -#include "five_porting.h" -#include "five_dsms.h" - -static void five_audit_msg(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); - -#ifdef CONFIG_FIVE_AUDIT_VERBOSE -void five_audit_verbose(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - five_audit_msg(task, file, op, prev, tint, cause, result); -} -#else -void five_audit_verbose(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ -} -#endif - -void five_audit_info(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - five_audit_msg(task, file, op, prev, tint, cause, result); -} - -/** - * There are two kind of event that can come to the function: error - * and tampering attempt. 'result' is for identification of error type - * and it should be non-zero in case of error but is always zero in - * case of tampering. - */ -void five_audit_err(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - five_audit_msg(task, file, op, prev, tint, cause, result); - - if (!result) { - char comm[TASK_COMM_LEN]; - struct task_struct *tsk = task ? task : current; - - five_dsms_reset_integrity(get_task_comm(comm, tsk), 0, op); - } -} - -void five_audit_sign_err(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - char comm[TASK_COMM_LEN]; - struct task_struct *tsk = task ? task : current; - - get_task_comm(comm, tsk); - five_dsms_sign_err(comm, result); -} - -static void five_audit_msg(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result) -{ - struct audit_buffer *ab; - struct inode *inode = NULL; - const char *fname = NULL; - char *pathbuf = NULL; - char filename[NAME_MAX]; - char comm[TASK_COMM_LEN]; - const char *name = ""; - struct task_struct *tsk = task ? task : current; - struct integrity_iint_cache *iint = NULL; - - if (file) { - inode = file_inode(file); - fname = five_d_path(&file->f_path, &pathbuf, filename); - } - - ab = audit_log_start(current->audit_context, GFP_KERNEL, - AUDIT_INTEGRITY_DATA); - if (unlikely(!ab)) { - pr_err("Can't get a context of audit logs\n"); - goto exit; - } - - audit_log_format(ab, " pid=%d", task_pid_nr(tsk)); - audit_log_format(ab, " tgid=%d", task_tgid_nr(tsk)); - audit_log_task_context(ab); - audit_log_format(ab, " op="); - audit_log_string(ab, op); - audit_log_format(ab, " cint=0x%x", tint); - audit_log_format(ab, " pint=0x%x", prev); - audit_log_format(ab, " cause="); - audit_log_string(ab, cause); - audit_log_format(ab, " comm="); - audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); - if (fname) { - audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, fname); - name = fname; - } - if (inode) { - audit_log_format(ab, " dev="); - audit_log_untrustedstring(ab, inode->i_sb->s_id); - audit_log_format(ab, " ino=%lu", inode->i_ino); - audit_log_format(ab, " i_version=%llu ", - inode_query_iversion(inode)); - iint = integrity_inode_get(inode); - if (iint) { - audit_log_format(ab, " five_status=%d ", - five_get_cache_status(iint)); - audit_log_format(ab, " version=%llu ", - (unsigned long long)iint->version); - } - } - audit_log_format(ab, " res=%d", result); - audit_log_end(ab); - -exit: - if (pathbuf) - __putname(pathbuf); -} - -void five_audit_tee_msg(const char *func, const char *cause, int rc, - uint32_t origin) -{ - struct audit_buffer *ab; - - ab = audit_log_start(current->audit_context, GFP_KERNEL, - AUDIT_INTEGRITY_DATA); - if (unlikely(!ab)) { - pr_err("Can't get a context of audit logs\n"); - return; - } - - audit_log_format(ab, " func="); - audit_log_string(ab, func); - audit_log_format(ab, " cause="); - audit_log_string(ab, cause); - audit_log_format(ab, " rc=0x%x, ", rc); - audit_log_format(ab, " origin=0x%x", origin); - audit_log_end(ab); -} - -void five_audit_hexinfo(struct file *file, const char *msg, char *data, - size_t data_length) -{ - struct audit_buffer *ab; - struct inode *inode = NULL; - const unsigned char *fname = NULL; - char filename[NAME_MAX]; - char *pathbuf = NULL; - struct integrity_iint_cache *iint = NULL; - - if (file) { - fname = five_d_path(&file->f_path, &pathbuf, filename); - inode = file_inode(file); - } - - ab = audit_log_start(current->audit_context, GFP_KERNEL, - AUDIT_INTEGRITY_DATA); - if (unlikely(!ab)) { - pr_err("Can't get a context of audit logs\n"); - goto exit; - } - - if (fname) { - audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, fname); - } - if (inode) { - audit_log_format(ab, " i_version=%llu ", - inode_query_iversion(inode)); - - iint = integrity_inode_get(inode); - if (iint) { - audit_log_format(ab, " cache_value=%lu ", - iint->five_flags); - audit_log_format(ab, " five_status=%d ", - five_get_cache_status(iint)); - audit_log_format(ab, " version=%llu ", - (unsigned long long)iint->version); - } - } - - audit_log_string(ab, msg); - audit_log_n_hex(ab, data, data_length); - audit_log_end(ab); -exit: - if (pathbuf) - __putname(pathbuf); -} diff --git a/security/samsung/five/gki/five_audit.h b/security/samsung/five/gki/five_audit.h deleted file mode 100755 index e0838399a..000000000 --- a/security/samsung/five/gki/five_audit.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Audit calls for FIVE audit subsystem. - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_AUDIT_H -#define __LINUX_FIVE_AUDIT_H - -#include <linux/task_integrity.h> - -void five_audit_verbose(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); -void five_audit_info(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); -void five_audit_err(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); -void five_audit_sign_err(struct task_struct *task, struct file *file, - const char *op, enum task_integrity_value prev, - enum task_integrity_value tint, const char *cause, int result); -void five_audit_tee_msg(const char *func, const char *cause, int rc, - uint32_t origin); - -void five_audit_hexinfo(struct file *file, - const char *msg, char *data, size_t data_length); - -#endif diff --git a/security/samsung/five/gki/five_cache.c b/security/samsung/five/gki/five_cache.c deleted file mode 100755 index c23f6028c..000000000 --- a/security/samsung/five/gki/five_cache.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * FIVE cache functions - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "five_cache.h" -#include "five_porting.h" - -enum five_file_integrity five_get_cache_status( - const struct integrity_iint_cache *iint) -{ - if (unlikely(!iint)) - return FIVE_FILE_UNKNOWN; - - if (!inode_eq_iversion(iint->inode, iint->version)) - return FIVE_FILE_UNKNOWN; - - return iint->five_status; -} - -void five_set_cache_status(struct integrity_iint_cache *iint, - enum five_file_integrity status) -{ - if (unlikely(!iint)) - return; - - iint->version = inode_query_iversion(iint->inode); - iint->five_status = status; -} - diff --git a/security/samsung/five/gki/five_cache.h b/security/samsung/five/gki/five_cache.h deleted file mode 100755 index a40bfa019..000000000 --- a/security/samsung/five/gki/five_cache.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * FIVE cache functions - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_FIVE_CACHE_H -#define __LINUX_FIVE_CACHE_H - -#include "security/integrity/integrity.h" - -enum five_file_integrity five_get_cache_status( - const struct integrity_iint_cache *iint); -void five_set_cache_status(struct integrity_iint_cache *iint, - enum five_file_integrity status); - -#endif // __LINUX_FIVE_CACHE_H diff --git a/security/samsung/five/gki/five_crypto.c b/security/samsung/five/gki/five_crypto.c deleted file mode 100755 index 08c9399fd..000000000 --- a/security/samsung/five/gki/five_crypto.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/moduleparam.h> -#include <linux/ratelimit.h> -#include <linux/file.h> -#include <linux/crypto.h> -#include <linux/scatterlist.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <crypto/hash.h> -#include <crypto/hash_info.h> -#include <linux/freezer.h> -#include "five.h" -#include "five_porting.h" -#include "five_vfs.h" - -struct ahash_completion { - struct completion completion; - int err; -}; - -/* minimum file size for ahash use */ -static unsigned long five_ahash_minsize; -module_param_named(ahash_minsize, five_ahash_minsize, ulong, 0644); -MODULE_PARM_DESC(ahash_minsize, "Minimum file size for ahash use"); - -/* default is 0 - 1 page. */ -static int five_maxorder; -static unsigned long five_bufsize = PAGE_SIZE; - -static int param_set_bufsize(const char *val, const struct kernel_param *kp) -{ - unsigned long long size; - int order; - - size = memparse(val, NULL); - order = get_order(size); - if (order >= MAX_ORDER) - return -EINVAL; - five_maxorder = order; - five_bufsize = PAGE_SIZE << order; - return 0; -} - -static const struct kernel_param_ops param_ops_bufsize = { - .set = param_set_bufsize, - .get = param_get_uint, -}; - -#define param_check_bufsize(name, p) __param_check(name, p, unsigned int) - -module_param_named(ahash_bufsize, five_bufsize, ulong, 0644); -MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size"); - -static struct crypto_shash *five_shash_tfm; -static struct crypto_ahash *five_ahash_tfm; - -int __init five_init_crypto(void) -{ - long rc; - - five_shash_tfm = crypto_alloc_shash( - hash_algo_name[five_hash_algo], 0, 0); - if (IS_ERR(five_shash_tfm)) { - rc = PTR_ERR(five_shash_tfm); - pr_err("Can not allocate %s (reason: %ld)\n", - hash_algo_name[five_hash_algo], rc); - return rc; - } - return 0; -} - -static struct crypto_shash *five_alloc_tfm(enum hash_algo algo) -{ - struct crypto_shash *tfm = five_shash_tfm; - int rc; - - if (algo < 0 || algo >= HASH_ALGO__LAST) - algo = five_hash_algo; - - if (algo != five_hash_algo) { - tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); - if (IS_ERR(tfm)) { - rc = PTR_ERR(tfm); - pr_err("Can not allocate %s (reason: %d)\n", - hash_algo_name[algo], rc); - } - } - return tfm; -} - -static void five_free_tfm(struct crypto_shash *tfm) -{ - if (tfm != five_shash_tfm) - crypto_free_shash(tfm); -} - -/** - * five_alloc_pages() - Allocate contiguous pages. - * @max_size: Maximum amount of memory to allocate. - * @allocated_size: Returned size of actual allocation. - * @last_warn: Should the min_size allocation warn or not. - * - * Tries to do opportunistic allocation for memory first trying to allocate - * max_size amount of memory and then splitting that until zero order is - * reached. Allocation is tried without generating allocation warnings unless - * last_warn is set. Last_warn set affects only last allocation of zero order. - * - * By default, five_maxorder is 0 and it is equivalent to kmalloc(GFP_KERNEL) - * - * Return pointer to allocated memory, or NULL on failure. - */ -static void *five_alloc_pages(loff_t max_size, size_t *allocated_size, - int last_warn) -{ - void *ptr; - int order = five_maxorder; - gfp_t gfp_mask = __GFP_RECLAIM | __GFP_NOWARN | __GFP_NORETRY; - - if (order) - order = min(get_order(max_size), order); - - for (; order; order--) { - ptr = (void *)__get_free_pages(gfp_mask, order); - if (ptr) { - *allocated_size = PAGE_SIZE << order; - return ptr; - } - } - - /* order is zero - one page */ - - gfp_mask = GFP_KERNEL; - - if (!last_warn) - gfp_mask |= __GFP_NOWARN; - - ptr = (void *)__get_free_pages(gfp_mask, 0); - if (ptr) { - *allocated_size = PAGE_SIZE; - return ptr; - } - - *allocated_size = 0; - return NULL; -} - -/** - * five_free_pages() - Free pages allocated by five_alloc_pages(). - * @ptr: Pointer to allocated pages. - * @size: Size of allocated buffer. - */ -static void five_free_pages(void *ptr, size_t size) -{ - if (!ptr) - return; - free_pages((unsigned long)ptr, get_order(size)); -} - -static struct crypto_ahash *five_alloc_atfm(enum hash_algo algo) -{ - struct crypto_ahash *tfm = five_ahash_tfm; - int rc; - - if (algo < 0 || algo >= HASH_ALGO__LAST) - algo = five_hash_algo; - - if (algo != five_hash_algo || !tfm) { - tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0); - if (!IS_ERR(tfm)) { - if (algo == five_hash_algo) - five_ahash_tfm = tfm; - } else { - rc = PTR_ERR(tfm); - pr_err("Can not allocate %s (reason: %d)\n", - hash_algo_name[algo], rc); - } - } - return tfm; -} - -static void five_free_atfm(struct crypto_ahash *tfm) -{ - if (tfm != five_ahash_tfm) - crypto_free_ahash(tfm); -} - -static void ahash_complete(struct crypto_async_request *req, int err) -{ - struct ahash_completion *res = req->data; - - if (err == -EINPROGRESS) - return; - res->err = err; - complete(&res->completion); -} - -static int ahash_wait(int err, struct ahash_completion *res) -{ - try_to_freeze(); - - switch (err) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&res->completion); - reinit_completion(&res->completion); - err = res->err; - /* fall through */ - default: - pr_crit_ratelimited("ahash calculation failed: err: %d\n", err); - } - - return err; -} - -static int five_calc_file_hash_atfm(struct file *file, - u8 *hash, size_t *hash_len, - struct crypto_ahash *tfm) -{ - const size_t len = crypto_ahash_digestsize(tfm); - loff_t i_size, offset; - char *rbuf[2] = { NULL, }; - int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0; - struct ahash_request *req; - struct scatterlist sg[1]; - struct ahash_completion res; - size_t rbuf_size[2]; - - if (*hash_len < len) - return -EINVAL; - - req = ahash_request_alloc(tfm, GFP_KERNEL); - if (!req) - return -ENOMEM; - - init_completion(&res.completion); - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - ahash_complete, &res); - - rc = ahash_wait(crypto_ahash_init(req), &res); - if (rc) - goto out1; - - i_size = i_size_read(file_inode(file)); - - if (i_size == 0) - goto out2; - - /* - * Try to allocate maximum size of memory. - * Fail if even a single page cannot be allocated. - */ - rbuf[0] = five_alloc_pages(i_size, &rbuf_size[0], 1); - if (!rbuf[0]) { - rc = -ENOMEM; - goto out1; - } - - /* Only allocate one buffer if that is enough. */ - if (i_size > rbuf_size[0]) { - /* - * Try to allocate secondary buffer. If that fails fallback to - * using single buffering. Use previous memory allocation size - * as baseline for possible allocation size. - */ - rbuf[1] = five_alloc_pages(i_size - rbuf_size[0], - &rbuf_size[1], 0); - } - - if (!(file->f_mode & FMODE_READ)) { - file->f_mode |= FMODE_READ; - read = 1; - } - - for (offset = 0; offset < i_size; offset += rbuf_len) { - if (!rbuf[1] && offset) { - /* Not using two buffers, and it is not the first - * read/request, wait for the completion of the - * previous ahash_update() request. - */ - rc = ahash_wait(ahash_rc, &res); - if (rc) - goto out3; - } - /* read buffer */ - rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]); - rc = five_kernel_read(file, offset, rbuf[active], - rbuf_len); - if (rc != rbuf_len) - goto out3; - - if (rbuf[1] && offset) { - /* Using two buffers, and it is not the first - * read/request, wait for the completion of the - * previous ahash_update() request. - */ - rc = ahash_wait(ahash_rc, &res); - if (rc) - goto out3; - } - - sg_init_one(&sg[0], rbuf[active], rbuf_len); - ahash_request_set_crypt(req, sg, NULL, rbuf_len); - - ahash_rc = crypto_ahash_update(req); - - if (rbuf[1]) - active = !active; /* swap buffers, if we use two */ - } - /* wait for the last update request to complete */ - rc = ahash_wait(ahash_rc, &res); -out3: - if (read) - file->f_mode &= ~FMODE_READ; - five_free_pages(rbuf[0], rbuf_size[0]); - five_free_pages(rbuf[1], rbuf_size[1]); -out2: - if (!rc) { - ahash_request_set_crypt(req, NULL, hash, 0); - rc = ahash_wait(crypto_ahash_final(req), &res); - if (!rc) - *hash_len = len; - } -out1: - ahash_request_free(req); - return rc; -} - -static int five_calc_file_ahash(struct file *file, - u8 hash_algo, u8 *hash, - size_t *hash_len) -{ - struct crypto_ahash *tfm; - int rc; - - tfm = five_alloc_atfm(hash_algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - rc = five_calc_file_hash_atfm(file, hash, hash_len, tfm); - - five_free_atfm(tfm); - - return rc; -} - -static int five_calc_file_hash_tfm(struct file *file, - u8 *hash, size_t *hash_len, - struct crypto_shash *tfm) -{ - SHASH_DESC_ON_STACK(shash, tfm); - const size_t len = crypto_shash_digestsize(tfm); - loff_t i_size, offset = 0; - char *rbuf; - int rc, read = 0; - - if (*hash_len < len) - return -EINVAL; - - shash->tfm = tfm; - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) - shash->flags = 0; - #endif - - rc = crypto_shash_init(shash); - if (rc != 0) - return rc; - - i_size = i_size_read(file_inode(file)); - - if (i_size == 0) - goto out; - - rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); - if (!rbuf) - return -ENOMEM; - - if (!(file->f_mode & FMODE_READ)) { - file->f_mode |= FMODE_READ; - read = 1; - } - - while (offset < i_size) { - int rbuf_len; - - rbuf_len = five_kernel_read(file, offset, rbuf, PAGE_SIZE); - if (rbuf_len < 0) { - rc = rbuf_len; - break; - } - if (rbuf_len == 0) - break; - offset += rbuf_len; - - try_to_freeze(); - - rc = crypto_shash_update(shash, rbuf, rbuf_len); - if (rc) - break; - } - if (read) - file->f_mode &= ~FMODE_READ; - kfree(rbuf); -out: - if (!rc) - rc = crypto_shash_final(shash, hash); - - if (!rc) - *hash_len = len; - - return rc; -} - -static int five_calc_hash_tfm(const u8 *data, size_t data_len, - u8 *hash, size_t *hash_len, struct crypto_shash *tfm) -{ - SHASH_DESC_ON_STACK(shash, tfm); - const size_t len = crypto_shash_digestsize(tfm); - int rc; - - if (*hash_len < len || data_len == 0) - return -EINVAL; - - shash->tfm = tfm; - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) - shash->flags = 0; - #endif - - rc = crypto_shash_init(shash); - if (rc != 0) - return rc; - - rc = crypto_shash_update(shash, data, data_len); - if (!rc) { - rc = crypto_shash_final(shash, hash); - - if (!rc) - *hash_len = len; - } - - return rc; -} - -static int five_calc_file_shash(struct file *file, - u8 hash_algo, - u8 *hash, - size_t *hash_len) -{ - struct crypto_shash *tfm; - int rc; - - tfm = five_alloc_tfm(hash_algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - rc = five_calc_file_hash_tfm(file, hash, hash_len, tfm); - - five_free_tfm(tfm); - - return rc; -} - -static int five_calc_data_shash(const u8 *data, size_t data_len, u8 hash_algo, - u8 *hash, size_t *hash_len) -{ - struct crypto_shash *tfm; - int rc; - - tfm = five_alloc_tfm(hash_algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - rc = five_calc_hash_tfm(data, data_len, hash, hash_len, tfm); - - five_free_tfm(tfm); - - return rc; -} - -/* - * five_calc_file_hash - calculate file hash - * - * Asynchronous hash (ahash) allows using HW acceleration for calculating - * a hash. ahash performance varies for different data sizes on different - * crypto accelerators. shash performance might be better for smaller files. - * The 'five.ahash_minsize' module parameter allows specifying the best - * minimum file size for using ahash on the system. - * - * If the five.ahash_minsize parameter is not specified, this function uses - * shash for the hash calculation. If ahash fails, it falls back to using - * shash. - */ -int five_calc_file_hash(struct file *file, u8 hash_algo, u8 *hash, - size_t *hash_len) -{ - loff_t i_size; - int rc; - - i_size = i_size_read(file_inode(file)); - - if (five_ahash_minsize && i_size >= five_ahash_minsize) { - rc = five_calc_file_ahash(file, hash_algo, hash, hash_len); - if (!rc) - return 0; - } - - return five_calc_file_shash(file, hash_algo, hash, hash_len); -} - -int five_calc_data_hash(const uint8_t *data, size_t data_len, - uint8_t hash_algo, uint8_t *hash, size_t *hash_len) -{ - return five_calc_data_shash(data, data_len, hash_algo, hash, hash_len); -} diff --git a/security/samsung/five/gki/five_hooks.c b/security/samsung/five/gki/five_hooks.c deleted file mode 100755 index 05ffe25de..000000000 --- a/security/samsung/five/gki/five_hooks.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Five Event interface - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Ivan Vorobiov, <i.vorobiov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "five_hooks.h" -#include "five_porting.h" - -#include <linux/fs.h> -#include <linux/slab.h> - -#define call_void_hook(FUNC, ...) \ - do { \ - struct five_hook_list *P; \ - \ - list_for_each_entry(P, &five_hook_heads.FUNC, list) \ - P->hook.FUNC(__VA_ARGS__); \ - } while (0) - -struct five_hook_heads five_hook_heads = { - .file_processed = - LIST_HEAD_INIT(five_hook_heads.file_processed), - .file_skipped = - LIST_HEAD_INIT(five_hook_heads.file_skipped), - .file_signed = - LIST_HEAD_INIT(five_hook_heads.file_signed), - .task_forked = - LIST_HEAD_INIT(five_hook_heads.task_forked), - .integrity_reset = - LIST_HEAD_INIT(five_hook_heads.integrity_reset), - .integrity_reset2 = - LIST_HEAD_INIT(five_hook_heads.integrity_reset2), -}; - -enum five_hook_event { - FILE_PROCESSED, - FILE_SKIPPED, - FILE_SIGNED, - TASK_FORKED, - INTEGRITY_RESET -}; - -struct hook_wq_event { - enum five_hook_event event; - union { - struct { - struct task_struct *task; - enum task_integrity_value tint_value; - struct file *file; - void *xattr; - size_t xattr_size; - int result; - } processed; - struct { - struct task_struct *task; - enum task_integrity_value tint_value; - struct file *file; - } skipped; - struct { - struct task_struct *parent; - enum task_integrity_value parent_tint_value; - struct task_struct *child; - enum task_integrity_value child_tint_value; - } forked; - struct { - struct task_struct *task; - struct file *file; - enum task_integrity_reset_cause cause; - } reset; - }; -}; - -static void hook_wq_event_destroy(struct hook_wq_event *event) -{ - switch (event->event) { - case FILE_PROCESSED: { - fput(event->processed.file); - put_task_struct(event->processed.task); - kfree(event->processed.xattr); - break; - } - case FILE_SKIPPED: { - fput(event->skipped.file); - put_task_struct(event->skipped.task); - break; - } - case FILE_SIGNED: { - fput(event->processed.file); - put_task_struct(event->processed.task); - kfree(event->processed.xattr); - break; - } - case TASK_FORKED: { - put_task_struct(event->forked.parent); - put_task_struct(event->forked.child); - break; - } - case INTEGRITY_RESET: { - if (event->reset.file) - fput(event->reset.file); - put_task_struct(event->reset.task); - break; - } - } -} - -struct hook_wq_context { - struct work_struct data_work; - struct hook_wq_event payload; -}; - -static struct workqueue_struct *g_hook_workqueue; - -static void hook_handler(struct work_struct *in_data) -{ - struct hook_wq_event *event; - struct hook_wq_context *context = container_of(in_data, - struct hook_wq_context, data_work); - - if (unlikely(!context)) - return; - event = &context->payload; - - switch (event->event) { - case FILE_PROCESSED: { - call_void_hook(file_processed, - event->processed.task, - event->processed.tint_value, - event->processed.file, - event->processed.xattr, - event->processed.xattr_size, - event->processed.result); - break; - } - case FILE_SKIPPED: { - call_void_hook(file_skipped, - event->skipped.task, - event->skipped.tint_value, - event->skipped.file); - break; - } - case FILE_SIGNED: { - call_void_hook(file_signed, - event->processed.task, - event->processed.tint_value, - event->processed.file, - event->processed.xattr, - event->processed.xattr_size, - event->processed.result); - break; - } - case TASK_FORKED: { - call_void_hook(task_forked, - event->forked.parent, - event->forked.parent_tint_value, - event->forked.child, - event->forked.child_tint_value); - break; - } - case INTEGRITY_RESET: { - call_void_hook(integrity_reset, - event->reset.task); - call_void_hook(integrity_reset2, event->reset.task, - event->reset.file, event->reset.cause); - break; - } - } - - hook_wq_event_destroy(event); - kfree(context); -} - -static int __push_event(struct hook_wq_event *event, gfp_t flags) -{ - struct hook_wq_context *context; - - if (!g_hook_workqueue) - return -ENAVAIL; - - context = kmalloc(sizeof(struct hook_wq_context), flags); - if (unlikely(!context)) - return -ENOMEM; - - context->payload = *event; - - INIT_WORK(&context->data_work, hook_handler); - return queue_work(g_hook_workqueue, &context->data_work) ? 0 : 1; -} - -void five_hook_file_processed(struct task_struct *task, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - struct hook_wq_event event = {0}; - - event.event = FILE_PROCESSED; - get_task_struct(task); - get_file(file); - event.processed.task = task; - event.processed.tint_value = task_integrity_read(TASK_INTEGRITY(task)); - event.processed.file = file; - /* - * xattr parameters are optional, because FIVE could get results - * from cache where xattr absents, so we may ignore kmemdup errors - */ - if (xattr) { - event.processed.xattr = kmemdup(xattr, xattr_size, GFP_KERNEL); - if (event.processed.xattr) - event.processed.xattr_size = xattr_size; - } - event.processed.result = result; - - if (__push_event(&event, GFP_KERNEL) < 0) - hook_wq_event_destroy(&event); -} - -void five_hook_file_signed(struct task_struct *task, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - struct hook_wq_event event = {0}; - - event.event = FILE_SIGNED; - get_task_struct(task); - get_file(file); - event.processed.task = task; - event.processed.tint_value = task_integrity_read(TASK_INTEGRITY(task)); - event.processed.file = file; - /* xattr parameters are optional, so we may ignore kmemdup errors */ - if (xattr) { - event.processed.xattr = kmemdup(xattr, xattr_size, GFP_KERNEL); - if (event.processed.xattr) - event.processed.xattr_size = xattr_size; - } - event.processed.result = result; - - if (__push_event(&event, GFP_KERNEL) < 0) - hook_wq_event_destroy(&event); -} - -void five_hook_file_skipped(struct task_struct *task, struct file *file) -{ - struct hook_wq_event event = {0}; - - event.event = FILE_SKIPPED; - get_task_struct(task); - get_file(file); - event.skipped.task = task; - event.skipped.tint_value = task_integrity_read(TASK_INTEGRITY(task)); - event.skipped.file = file; - - if (__push_event(&event, GFP_KERNEL) < 0) - hook_wq_event_destroy(&event); -} - -void five_hook_task_forked(struct task_struct *parent, - struct task_struct *child) -{ - struct hook_wq_event event = {0}; - - event.event = TASK_FORKED; - get_task_struct(parent); - get_task_struct(child); - event.forked.parent = parent; - event.forked.parent_tint_value = - task_integrity_read(TASK_INTEGRITY(parent)); - event.forked.child = child; - event.forked.child_tint_value = - task_integrity_read(TASK_INTEGRITY(child)); - - if (__push_event(&event, GFP_ATOMIC) < 0) - hook_wq_event_destroy(&event); -} - -int five_hook_wq_init(void) -{ - g_hook_workqueue = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, "five_hook_wq"); - if (!g_hook_workqueue) - return -ENOMEM; - - return 0; -} - -void five_hook_integrity_reset(struct task_struct *task, - struct file *file, - enum task_integrity_reset_cause cause) -{ - struct hook_wq_event event = {0}; - - if (task == NULL) - return; - - event.event = INTEGRITY_RESET; - get_task_struct(task); - if (file) - get_file(file); - event.reset.task = task; - event.reset.file = file; - event.reset.cause = cause; - - if (__push_event(&event, GFP_KERNEL) < 0) - hook_wq_event_destroy(&event); -} diff --git a/security/samsung/five/gki/five_hooks.h b/security/samsung/five/gki/five_hooks.h deleted file mode 100755 index 78b6dfb49..000000000 --- a/security/samsung/five/gki/five_hooks.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Five Event interface - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Ivan Vorobiov, <i.vorobiov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _FIVE_HOOKS_H -#define _FIVE_HOOKS_H - -#include <linux/file.h> -#include <linux/rculist.h> -#include <linux/sched.h> -#include <linux/task_integrity.h> - -void five_hook_file_processed(struct task_struct *task, - struct file *file, void *xattr, - size_t xattr_size, int result); - -void five_hook_task_forked(struct task_struct *parent, - struct task_struct *child); - -void five_hook_file_skipped(struct task_struct *task, - struct file *file); - -void five_hook_file_signed(struct task_struct *task, - struct file *file, void *xattr, - size_t xattr_size, int result); - -void five_hook_integrity_reset(struct task_struct *task, - struct file *file, - enum task_integrity_reset_cause cause); - -union five_list_options { - void (*file_processed)(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, - void *xattr, - size_t xattr_size, - int result); - - void (*file_skipped)(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file); - - void (*task_forked)(struct task_struct *parent, - enum task_integrity_value parent_tint_value, - struct task_struct *child, - enum task_integrity_value child_tint_value); - - void (*file_signed)(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result); - void (*integrity_reset)(struct task_struct *task); - void (*integrity_reset2)(struct task_struct *task, - struct file *file, - enum task_integrity_reset_cause cause); -}; - -struct five_hook_heads { - struct list_head file_processed; - struct list_head file_skipped; - struct list_head file_signed; - struct list_head task_forked; - struct list_head integrity_reset; - struct list_head integrity_reset2; -}; - -/* - * FIVE module hook list structure. - * For use with generic list macros for common operations. - */ -struct five_hook_list { - struct list_head list; - struct list_head *head; - union five_list_options hook; -}; - -/* - * Initializing a five_hook_list structure takes - * up a lot of space in a source file. This macro takes - * care of the common case and reduces the amount of - * text involved. - */ -#define FIVE_HOOK_INIT(HEAD, HOOK) \ - { .head = &five_hook_heads.HEAD, .hook = { .HEAD = HOOK } } - -extern struct five_hook_heads five_hook_heads; - -static inline void five_add_hooks(struct five_hook_list *hooks, - int count) -{ - int i; - - for (i = 0; i < count; i++) - list_add_tail_rcu(&hooks[i].list, hooks[i].head); -} - -int five_hook_wq_init(void); - -#endif /* _FIVE_HOOKS_H */ diff --git a/security/samsung/five/gki/five_iint.c b/security/samsung/five/gki/five_iint.c deleted file mode 100755 index 36e6c0824..000000000 --- a/security/samsung/five/gki/five_iint.c +++ /dev/null @@ -1,258 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2008 IBM Corporation - * - * Authors: - * Mimi Zohar <zohar@us.ibm.com> - * - * File: integrity_iint.c - * - implements the integrity hooks: integrity_inode_alloc, - * integrity_inode_free - * - cache integrity information associated with an inode - * using a rbtree tree. - */ -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/rbtree.h> -#include <linux/file.h> -#include <linux/uaccess.h> -#include <linux/security.h> -#include <linux/lsm_hooks.h> -#ifdef CONFIG_FIVE -#include <uapi/linux/magic.h> -#endif -#include "integrity.h" - -static struct rb_root integrity_iint_tree = RB_ROOT; -static DEFINE_RWLOCK(integrity_iint_lock); -static struct kmem_cache *iint_cache __read_mostly; - -struct dentry *integrity_dir; - -/* - * __integrity_iint_find - return the iint associated with an inode - */ -static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode) -{ - struct integrity_iint_cache *iint; - struct rb_node *n = integrity_iint_tree.rb_node; - - while (n) { - iint = rb_entry(n, struct integrity_iint_cache, rb_node); - - if (inode < iint->inode) - n = n->rb_left; - else if (inode > iint->inode) - n = n->rb_right; - else - break; - } - if (!n) - return NULL; - - return iint; -} - -/* - * integrity_iint_find - return the iint associated with an inode - */ -struct integrity_iint_cache *integrity_iint_find(struct inode *inode) -{ - struct integrity_iint_cache *iint; - - if (!IS_IMA(inode)) - return NULL; - - read_lock(&integrity_iint_lock); - iint = __integrity_iint_find(inode); - read_unlock(&integrity_iint_lock); - - return iint; -} - -static void iint_free(struct integrity_iint_cache *iint) -{ -#ifdef CONFIG_FIVE - kfree(iint->five_label); - iint->five_label = NULL; - iint->five_flags = 0UL; - iint->five_status = FIVE_FILE_UNKNOWN; - iint->five_signing = false; -#endif - kfree(iint->ima_hash); - iint->ima_hash = NULL; - iint->version = 0; - iint->flags = 0UL; - iint->atomic_flags = 0UL; - iint->ima_file_status = INTEGRITY_UNKNOWN; - iint->ima_mmap_status = INTEGRITY_UNKNOWN; - iint->ima_bprm_status = INTEGRITY_UNKNOWN; - iint->ima_read_status = INTEGRITY_UNKNOWN; - iint->ima_creds_status = INTEGRITY_UNKNOWN; - iint->evm_status = INTEGRITY_UNKNOWN; - iint->measured_pcrs = 0; - kmem_cache_free(iint_cache, iint); -} - -/** - * integrity_inode_get - find or allocate an iint associated with an inode - * @inode: pointer to the inode - * @return: allocated iint - * - * Caller must lock i_mutex - */ -struct integrity_iint_cache *integrity_inode_get(struct inode *inode) -{ - struct rb_node **p; - struct rb_node *node, *parent = NULL; - struct integrity_iint_cache *iint, *test_iint; - - iint = integrity_iint_find(inode); - if (iint) - return iint; - - iint = kmem_cache_alloc(iint_cache, GFP_NOFS); - if (!iint) - return NULL; - - write_lock(&integrity_iint_lock); - - p = &integrity_iint_tree.rb_node; - while (*p) { - parent = *p; - test_iint = rb_entry(parent, struct integrity_iint_cache, - rb_node); - if (inode < test_iint->inode) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - - iint->inode = inode; - node = &iint->rb_node; - inode->i_flags |= S_IMA; - rb_link_node(node, parent, p); - rb_insert_color(node, &integrity_iint_tree); - - write_unlock(&integrity_iint_lock); - return iint; -} - -/** - * integrity_inode_free - called on security_inode_free - * @inode: pointer to the inode - * - * Free the integrity information(iint) associated with an inode. - */ -void integrity_inode_free(struct inode *inode) -{ - struct integrity_iint_cache *iint; - - if (!IS_IMA(inode)) - return; - - write_lock(&integrity_iint_lock); - iint = __integrity_iint_find(inode); - rb_erase(&iint->rb_node, &integrity_iint_tree); - write_unlock(&integrity_iint_lock); - - iint_free(iint); -} - -static void init_once(void *foo) -{ - struct integrity_iint_cache *iint = foo; - - memset(iint, 0, sizeof(*iint)); -#ifdef CONFIG_FIVE - iint->five_flags = 0UL; - iint->five_status = FIVE_FILE_UNKNOWN; - iint->five_signing = false; -#endif - iint->ima_file_status = INTEGRITY_UNKNOWN; - iint->ima_mmap_status = INTEGRITY_UNKNOWN; - iint->ima_bprm_status = INTEGRITY_UNKNOWN; - iint->ima_read_status = INTEGRITY_UNKNOWN; - iint->ima_creds_status = INTEGRITY_UNKNOWN; - iint->evm_status = INTEGRITY_UNKNOWN; - mutex_init(&iint->mutex); -} - -static int __init integrity_iintcache_init(void) -{ - iint_cache = - kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), - 0, SLAB_PANIC, init_once); - return 0; -} - -DEFINE_LSM(integrity) = { - .name = "integrity", - .init = integrity_iintcache_init, -}; - -/* - * integrity_kernel_read - read data from the file - * - * This is a function for reading file content instead of kernel_read(). - * It does not perform locking checks to ensure it cannot be blocked. - * It does not perform security checks because it is irrelevant for IMA. - * - */ -int integrity_kernel_read(struct file *file, loff_t offset, - void *addr, unsigned long count) -{ - mm_segment_t old_fs; - char __user *buf = (char __user *)addr; - ssize_t ret; -#ifdef CONFIG_FIVE - struct inode *inode = file_inode(file); -#endif - - if (!(file->f_mode & FMODE_READ)) - return -EBADF; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - -#ifdef CONFIG_FIVE - if (inode->i_sb->s_magic == OVERLAYFS_SUPER_MAGIC && file->private_data) - file = (struct file *)file->private_data; -#endif - - ret = __vfs_read(file, buf, count, &offset); - set_fs(old_fs); - - return ret; -} - -/* - * integrity_load_keys - load integrity keys hook - * - * Hooks is called from init/main.c:kernel_init_freeable() - * when rootfs is ready - */ -void __init integrity_load_keys(void) -{ - ima_load_x509(); - evm_load_x509(); -} - -static int __init integrity_fs_init(void) -{ - integrity_dir = securityfs_create_dir("integrity", NULL); - if (IS_ERR(integrity_dir)) { - int ret = PTR_ERR(integrity_dir); - - if (ret != -ENODEV) - pr_err("Unable to create integrity sysfs dir: %d\n", - ret); - integrity_dir = NULL; - return ret; - } - - return 0; -} - -late_initcall(integrity_fs_init) diff --git a/security/samsung/five/gki/five_iint.h b/security/samsung/five/gki/five_iint.h deleted file mode 100755 index 03413eca1..000000000 --- a/security/samsung/five/gki/five_iint.h +++ /dev/null @@ -1,286 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2009-2010 IBM Corporation - * - * Authors: - * Mimi Zohar <zohar@us.ibm.com> - */ - -#include <linux/types.h> -#include <linux/integrity.h> -#include <crypto/sha.h> -#include <linux/key.h> -#include <linux/audit.h> - -struct integrity_label; - -enum five_file_integrity { - FIVE_FILE_UNKNOWN, - FIVE_FILE_FAIL, - FIVE_FILE_RSA, - FIVE_FILE_DMVERITY, - FIVE_FILE_FSVERITY, - FIVE_FILE_HMAC -}; - -/* iint action cache flags */ -#define IMA_MEASURE 0x00000001 -#define IMA_MEASURED 0x00000002 -#define IMA_APPRAISE 0x00000004 -#define IMA_APPRAISED 0x00000008 -/*#define IMA_COLLECT 0x00000010 do not use this flag */ -#define IMA_COLLECTED 0x00000020 -#define IMA_AUDIT 0x00000040 -#define IMA_AUDITED 0x00000080 -#define IMA_HASH 0x00000100 -#define IMA_HASHED 0x00000200 - -/* iint cache flags */ -#define IMA_ACTION_FLAGS 0xff000000 -#define IMA_DIGSIG_REQUIRED 0x01000000 -#define IMA_PERMIT_DIRECTIO 0x02000000 -#define IMA_NEW_FILE 0x04000000 -#define EVM_IMMUTABLE_DIGSIG 0x08000000 -#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 -#define IMA_MODSIG_ALLOWED 0x20000000 - -#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ - IMA_HASH | IMA_APPRAISE_SUBMASK) -#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED | \ - IMA_HASHED | IMA_COLLECTED | \ - IMA_APPRAISED_SUBMASK) - -/* iint subaction appraise cache flags */ -#define IMA_FILE_APPRAISE 0x00001000 -#define IMA_FILE_APPRAISED 0x00002000 -#define IMA_MMAP_APPRAISE 0x00004000 -#define IMA_MMAP_APPRAISED 0x00008000 -#define IMA_BPRM_APPRAISE 0x00010000 -#define IMA_BPRM_APPRAISED 0x00020000 -#define IMA_READ_APPRAISE 0x00040000 -#define IMA_READ_APPRAISED 0x00080000 -#define IMA_CREDS_APPRAISE 0x00100000 -#define IMA_CREDS_APPRAISED 0x00200000 - -#define FIVE_DMVERITY_PROTECTED 0x00040000 -#define FIVE_TRUSTED_FILE 0x00080000 - -#define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ - IMA_BPRM_APPRAISE | IMA_READ_APPRAISE | \ - IMA_CREDS_APPRAISE) -#define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ - IMA_BPRM_APPRAISED | IMA_READ_APPRAISED | \ - IMA_CREDS_APPRAISED) - -/* iint cache atomic_flags */ -#define IMA_CHANGE_XATTR 0 -#define IMA_UPDATE_XATTR 1 -#define IMA_CHANGE_ATTR 2 -#define IMA_DIGSIG 3 -#define IMA_MUST_MEASURE 4 - -enum evm_ima_xattr_type { - IMA_XATTR_DIGEST = 0x01, - EVM_XATTR_HMAC, - EVM_IMA_XATTR_DIGSIG, - IMA_XATTR_DIGEST_NG, - EVM_XATTR_PORTABLE_DIGSIG, - IMA_XATTR_LAST -}; - -struct evm_ima_xattr_data { - u8 type; - u8 data[]; -} __packed; - -/* Only used in the EVM HMAC code. */ -struct evm_xattr { - struct evm_ima_xattr_data data; - u8 digest[SHA1_DIGEST_SIZE]; -} __packed; - -#define IMA_MAX_DIGEST_SIZE 64 - -struct ima_digest_data { - u8 algo; - u8 length; - union { - struct { - u8 unused; - u8 type; - } sha1; - struct { - u8 type; - u8 algo; - } ng; - u8 data[2]; - } xattr; - u8 digest[0]; -} __packed; - -/* - * signature format v2 - for using with asymmetric keys - */ -struct signature_v2_hdr { - uint8_t type; /* xattr type */ - uint8_t version; /* signature format version */ - uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */ - __be32 keyid; /* IMA key identifier - not X509/PGP specific */ - __be16 sig_size; /* signature size */ - uint8_t sig[0]; /* signature payload */ -} __packed; - -/* integrity data associated with an inode */ -struct integrity_iint_cache { - struct rb_node rb_node; /* rooted in integrity_iint_tree */ - struct mutex mutex; /* protects: version, flags, digest */ - struct inode *inode; /* back pointer to inode in question */ - u64 version; /* track inode changes */ - unsigned long flags; - unsigned long measured_pcrs; - unsigned long atomic_flags; - enum integrity_status ima_file_status:4; - enum integrity_status ima_mmap_status:4; - enum integrity_status ima_bprm_status:4; - enum integrity_status ima_read_status:4; - enum integrity_status ima_creds_status:4; - enum integrity_status evm_status:4; - struct ima_digest_data *ima_hash; -#ifdef CONFIG_FIVE - unsigned long five_flags; - enum five_file_integrity five_status; - struct integrity_label *five_label; - bool five_signing; -#endif -}; - -/* rbtree tree calls to lookup, insert, delete - * integrity data associated with an inode. - */ -struct integrity_iint_cache *integrity_iint_find(struct inode *inode); - -int integrity_kernel_read(struct file *file, loff_t offset, - void *addr, unsigned long count); - -#define INTEGRITY_KEYRING_EVM 0 -#define INTEGRITY_KEYRING_IMA 1 -#define INTEGRITY_KEYRING_PLATFORM 2 -#define INTEGRITY_KEYRING_MAX 3 - -extern struct dentry *integrity_dir; - -struct modsig; - -#ifdef CONFIG_INTEGRITY_SIGNATURE - -int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, - const char *digest, int digestlen); -int integrity_modsig_verify(unsigned int id, const struct modsig *modsig); - -int __init integrity_init_keyring(const unsigned int id); -int __init integrity_load_x509(const unsigned int id, const char *path); -int __init integrity_load_cert(const unsigned int id, const char *source, - const void *data, size_t len, key_perm_t perm); -#else - -static inline int integrity_digsig_verify(const unsigned int id, - const char *sig, int siglen, - const char *digest, int digestlen) -{ - return -EOPNOTSUPP; -} - -static inline int integrity_modsig_verify(unsigned int id, - const struct modsig *modsig) -{ - return -EOPNOTSUPP; -} - -static inline int integrity_init_keyring(const unsigned int id) -{ - return 0; -} - -static inline int __init integrity_load_cert(const unsigned int id, - const char *source, - const void *data, size_t len, - key_perm_t perm) -{ - return 0; -} -#endif /* CONFIG_INTEGRITY_SIGNATURE */ - -#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS -int asymmetric_verify(struct key *keyring, const char *sig, - int siglen, const char *data, int datalen); -#else -static inline int asymmetric_verify(struct key *keyring, const char *sig, - int siglen, const char *data, int datalen) -{ - return -EOPNOTSUPP; -} -#endif - -#ifdef CONFIG_IMA_APPRAISE_MODSIG -int ima_modsig_verify(struct key *keyring, const struct modsig *modsig); -#else -static inline int ima_modsig_verify(struct key *keyring, - const struct modsig *modsig) -{ - return -EOPNOTSUPP; -} -#endif - -#ifdef CONFIG_IMA_LOAD_X509 -void __init ima_load_x509(void); -#else -static inline void ima_load_x509(void) -{ -} -#endif - -#ifdef CONFIG_EVM_LOAD_X509 -void __init evm_load_x509(void); -#else -static inline void evm_load_x509(void) -{ -} -#endif - -#ifdef CONFIG_INTEGRITY_AUDIT -/* declarations */ -void integrity_audit_msg(int audit_msgno, struct inode *inode, - const unsigned char *fname, const char *op, - const char *cause, int result, int info); - -static inline struct audit_buffer * -integrity_audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type) -{ - return audit_log_start(ctx, gfp_mask, type); -} - -#else -static inline void integrity_audit_msg(int audit_msgno, struct inode *inode, - const unsigned char *fname, - const char *op, const char *cause, - int result, int info) -{ -} - -static inline struct audit_buffer * -integrity_audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type) -{ - return NULL; -} - -#endif - -#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING -void __init add_to_platform_keyring(const char *source, const void *data, - size_t len); -#else -static inline void __init add_to_platform_keyring(const char *source, - const void *data, size_t len) -{ -} -#endif diff --git a/security/samsung/five/gki/five_init.c b/security/samsung/five/gki/five_init.c deleted file mode 100755 index 0c6598226..000000000 --- a/security/samsung/five/gki/five_init.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <crypto/hash_info.h> -#include "five.h" - -int __init five_init(void) -{ - int rc; - - rc = five_keyring_init(); - if (rc) - return rc; - rc = five_load_built_x509(); - if (rc) - return rc; - rc = five_task_integrity_cache_init(); - if (rc) - return rc; - rc = five_init_crypto(); - - return rc; -} diff --git a/security/samsung/five/gki/five_main.c b/security/samsung/five/gki/five_main.c deleted file mode 100755 index 0f65a1593..000000000 --- a/security/samsung/five/gki/five_main.c +++ /dev/null @@ -1,1141 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/binfmts.h> -#include <linux/mount.h> -#include <linux/mman.h> -#include <linux/slab.h> -#include <linux/xattr.h> -#include <crypto/hash_info.h> -#include <linux/ptrace.h> -#include <linux/task_integrity.h> -#include <linux/reboot.h> -#include <linux/debugfs.h> -#include <linux/fs.h> -#include <linux/shmem_fs.h> - -#include "five.h" -#include "five_audit.h" -#include "five_hooks.h" -#include "five_state.h" -#include "five_pa.h" -#include "five_porting.h" -#include "five_cache.h" -#include "five_dmverity.h" -#include "five_dsms.h" -#include "five_tint_dev.h" - -static const bool unlink_on_error; // false - -static const bool check_dex2oat_binary = true; -static const bool check_memfd_file = true; - -static struct file *memfd_file __ro_after_init; - -static struct workqueue_struct *g_five_workqueue; - -static inline void task_integrity_processing(struct task_integrity *tint); -static inline void task_integrity_done(struct task_integrity *tint); -static void process_measurement(const struct processing_event_list *params); -static inline struct processing_event_list *five_event_create( - enum five_event event, struct task_struct *task, - struct file *file, int function, gfp_t flags); -static inline void five_event_destroy( - const struct processing_event_list *file); - -#ifdef CONFIG_FIVE_DEBUG -static int five_enabled = 1; - -static ssize_t five_enabled_write(struct file *file, const char __user *buf, - size_t count, loff_t *pos) -{ - char command; - - if (get_user(command, buf)) - return -EFAULT; - - switch (command) { - case '0': - five_enabled = 0; - break; - case '1': - five_enabled = 1; - break; - default: - pr_err("FIVE: %s: unknown cmd: %hhx\n", __func__, command); - return -EINVAL; - } - - pr_info("FIVE debug: FIVE %s\n", five_enabled ? "enabled" : "disabled"); - return count; -} - -static ssize_t five_enabled_read(struct file *file, char __user *user_buf, - size_t count, loff_t *pos) -{ - char buf[2]; - - buf[0] = five_enabled ? '1' : '0'; - buf[1] = '\n'; - - return simple_read_from_buffer(user_buf, count, pos, buf, sizeof(buf)); -} - -static const struct file_operations five_enabled_fops = { - .owner = THIS_MODULE, - .read = five_enabled_read, - .write = five_enabled_write -}; - -static int __init init_fs(void) -{ - struct dentry *debug_file = NULL; - umode_t umode = (S_IRUGO | S_IWUSR | S_IWGRP); - - debug_file = debugfs_create_file( - "five_enabled", umode, NULL, NULL, &five_enabled_fops); - if (IS_ERR_OR_NULL(debug_file)) - goto error; - - return 0; -error: - if (debug_file) - return -PTR_ERR(debug_file); - - return -EEXIST; -} - -static inline int is_five_enabled(void) -{ - return five_enabled; -} - -int five_fcntl_debug(struct file *file, void __user *argp) -{ - struct inode *inode; - struct five_stat stat = {0}; - struct integrity_iint_cache *iint; - - if (unlikely(!file || !argp)) - return -EINVAL; - - inode = file_inode(file); - - inode_lock(inode); - iint = integrity_inode_get(inode); - if (unlikely(!iint)) { - inode_unlock(inode); - return -ENOMEM; - } - - stat.cache_status = five_get_cache_status(iint); - stat.cache_iversion = inode_query_iversion(iint->inode); - stat.inode_iversion = inode_query_iversion(inode); - - inode_unlock(inode); - - if (unlikely(copy_to_user(argp, &stat, sizeof(stat)))) - return -EFAULT; - - return 0; -} -#else -static int __init init_fs(void) -{ - return 0; -} - -static inline int is_five_enabled(void) -{ - return 1; -} -#endif - -static void work_handler(struct work_struct *in_data) -{ - struct worker_context *context = container_of(in_data, - struct worker_context, data_work); - struct task_integrity *intg; - - if (unlikely(!context)) - return; - - intg = context->tint; - - spin_lock(&intg->list_lock); - while (!list_empty(&(intg->events.list))) { - struct processing_event_list *five_file; - - five_file = list_entry(intg->events.list.next, - struct processing_event_list, list); - spin_unlock(&intg->list_lock); - switch (five_file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - process_measurement(five_file); - break; - } - case FIVE_RESET_INTEGRITY: { - task_integrity_reset(intg); - five_hook_integrity_reset(five_file->task, - NULL, CAUSE_UNKNOWN); - break; - } - default: - break; - } - spin_lock(&intg->list_lock); - list_del(&five_file->list); - five_event_destroy(five_file); - } - - task_integrity_done(intg); - spin_unlock(&intg->list_lock); - task_integrity_put(intg); - - kfree(context); -} - -static void fix_dpath(const struct path *path, char *pathbuf, char *pathname) -{ - /* `d_path' appends " (deleted)" string if a file is unlinked. Below - * code removes it. - * `d_path' fills the buffer from the end of it therefore we can easily - * calculate the length of the pathname. - */ - const long pathname_size = pathbuf + PATH_MAX - pathname; - const char str_deleted[] = " (deleted)"; - const int deleted_size = sizeof(str_deleted); - - if (pathname_size > deleted_size && d_unlinked(path->dentry)) { - char *start_deleted = pathbuf + PATH_MAX - deleted_size; - - if (!strncmp(str_deleted, start_deleted, deleted_size)) - *start_deleted = '\0'; - } -} - -const char *five_d_path(const struct path *path, char **pathbuf, char *namebuf) -{ - char *pathname = NULL; - - *pathbuf = __getname(); - if (*pathbuf) { - pathname = d_path(path, *pathbuf, PATH_MAX); - if (IS_ERR(pathname)) { - __putname(*pathbuf); - *pathbuf = NULL; - pathname = NULL; - } - fix_dpath(path, *pathbuf, pathname); - } - - if (!pathname) { - strlcpy(namebuf, path->dentry->d_name.name, NAME_MAX); - pathname = namebuf; - } - - return pathname; -} - -int five_check_params(struct task_struct *task, struct file *file) -{ - struct inode *inode; - - if (unlikely(!file)) - return 1; - - inode = file_inode(file); - if (!S_ISREG(inode->i_mode)) - return 1; - - return 0; -} - -/* cut a list into two - * @cur_list: a list with entries - * @new_list: a new list to add all removed entries. Should be an empty list - * - * Use it under spin_lock - * - * The function moves second entry and following entries to new list. - * First entry is left in cur_list. - * - * Initial state: - * [cur_list]<=>[first]<=>[second]<=>[third]<=>...<=>[last] [new_list] - * ^=================================================^ ^====^ - * Result: - * [cur_list]<=>[first] - * ^==========^ - * [new_list]<=>[second]<=>[third]<=>...<=>[last] - * ^=====================================^ - * - * the function is similar to kernel list_cut_position, but there are few - * differences: - * - cut position is second entry - * - original list is left with only first entry - * - moving entries are from second entry to last entry - */ -static void list_cut_tail(struct list_head *cur_list, - struct list_head *new_list) -{ - if ((!list_empty(cur_list)) && - (!list_is_singular(cur_list))) { - new_list->next = cur_list->next->next; - cur_list->next->next->prev = new_list; - cur_list->next->next = cur_list; - new_list->prev = cur_list->prev; - cur_list->prev->next = new_list; - cur_list->prev = cur_list->next; - } -} - -static void free_files_list(struct list_head *list) -{ - struct list_head *tmp, *list_entry; - struct processing_event_list *file_entry; - - list_for_each_safe(list_entry, tmp, list) { - file_entry = list_entry(list_entry, - struct processing_event_list, list); - list_del(&file_entry->list); - five_event_destroy(file_entry); - } -} - -static int push_file_event_bunch(struct task_struct *task, struct file *file, - int function) -{ - int rc = 0; - struct worker_context *context; - struct processing_event_list *five_file; - - if (unlikely(!is_five_enabled()) || five_check_params(task, file)) - return 0; - - context = kmalloc(sizeof(struct worker_context), GFP_KERNEL); - if (unlikely(!context)) - return -ENOMEM; - - five_file = five_event_create(FIVE_VERIFY_BUNCH_FILES, task, file, - function, GFP_KERNEL); - if (unlikely(!five_file)) { - kfree(context); - return -ENOMEM; - } - - spin_lock(&TASK_INTEGRITY(task)->list_lock); - - if (list_empty(&(TASK_INTEGRITY(task)->events.list))) { - task_integrity_get(TASK_INTEGRITY(task)); - task_integrity_processing(TASK_INTEGRITY(task)); - - context->tint = TASK_INTEGRITY(task); - - list_add_tail(&five_file->list, - &TASK_INTEGRITY(task)->events.list); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - INIT_WORK(&context->data_work, work_handler); - rc = queue_work(g_five_workqueue, &context->data_work) ? 0 : 1; - } else { - struct list_head dead_list; - - INIT_LIST_HEAD(&dead_list); - if ((function == BPRM_CHECK) && - (!list_is_singular(&(TASK_INTEGRITY(task)->events.list)))) { - list_cut_tail(&TASK_INTEGRITY(task)->events.list, - &dead_list); - } - list_add_tail(&five_file->list, - &TASK_INTEGRITY(task)->events.list); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - free_files_list(&dead_list); - kfree(context); - } - return rc; -} - -static int push_reset_event(struct task_struct *task, - enum task_integrity_reset_cause cause, struct file *file) -{ - struct list_head dead_list; - struct task_integrity *current_tint; - struct processing_event_list *five_reset; - - if (unlikely(!is_five_enabled())) - return 0; - - INIT_LIST_HEAD(&dead_list); - current_tint = TASK_INTEGRITY(task); - task_integrity_get(current_tint); - - task_integrity_set_reset_reason(current_tint, cause, file); - - five_reset = five_event_create(FIVE_RESET_INTEGRITY, task, NULL, 0, - GFP_KERNEL); - if (unlikely(!five_reset)) { - task_integrity_reset_both(current_tint); - five_hook_integrity_reset(task, file, cause); - task_integrity_put(current_tint); - return -ENOMEM; - } - - task_integrity_reset_both(current_tint); - five_hook_integrity_reset(task, file, cause); - spin_lock(¤t_tint->list_lock); - if (!list_empty(¤t_tint->events.list)) { - list_cut_tail(¤t_tint->events.list, &dead_list); - five_reset->event = FIVE_RESET_INTEGRITY; - list_add_tail(&five_reset->list, ¤t_tint->events.list); - spin_unlock(¤t_tint->list_lock); - } else { - spin_unlock(¤t_tint->list_lock); - five_event_destroy(five_reset); - } - - task_integrity_put(current_tint); - /* remove dead_list */ - free_files_list(&dead_list); - return 0; -} - -void task_integrity_delayed_reset(struct task_struct *task, - enum task_integrity_reset_cause cause, struct file *file) -{ - push_reset_event(task, cause, file); -} - -static void five_check_last_writer(struct integrity_iint_cache *iint, - struct inode *inode, struct file *file) -{ - fmode_t mode = file->f_mode; - - if (!(mode & FMODE_WRITE)) - return; - - inode_lock(inode); - if (atomic_read(&inode->i_writecount) == 1) { - if (!inode_eq_iversion(inode, iint->version)) - five_set_cache_status(iint, FIVE_FILE_UNKNOWN); - } - iint->five_signing = false; - inode_unlock(inode); -} - -/** - * five_file_free - called on __fput() - * @file: pointer to file structure being freed - * - * Flag files that changed, based on i_version - */ -void five_file_free(struct file *file) -{ - struct inode *inode = file_inode(file); - struct integrity_iint_cache *iint; - - if (!S_ISREG(inode->i_mode)) - return; - - fivepa_fsignature_free(file); - - iint = integrity_iint_find(inode); - if (!iint) - return; - - five_check_last_writer(iint, inode, file); -} - -void five_task_free(struct task_struct *task) -{ - task_integrity_put(TASK_INTEGRITY(task)); -} - -/* Returns string representation of input function */ -const char *five_get_string_fn(enum five_hooks fn) -{ - switch (fn) { - case FILE_CHECK: - return "file-check"; - case MMAP_CHECK: - return "mmap-check"; - case BPRM_CHECK: - return "bprm-check"; - case POST_SETATTR: - return "post-setattr"; - } - return "unknown-function"; -} - -static inline bool is_dex2oat_binary(const struct file *file) -{ - const char *pathname = NULL; - char *pathbuf = NULL; - const char * const dex2oat_full_path[] = { - /* R OS */ - "/apex/com.android.art/bin/dex2oat", - "/apex/com.android.art/bin/dex2oat32", - "/apex/com.android.art/bin/dex2oat64", - /* Q OS */ - "/apex/com.android.runtime/bin/dex2oat" - }; - char filename[NAME_MAX]; - bool res = false; - size_t i; - - if (!file || !file->f_path.dentry) - return false; - - if (strncmp(file->f_path.dentry->d_iname, "dex2oat", - sizeof("dex2oat")) && - strncmp(file->f_path.dentry->d_iname, "dex2oat32", - sizeof("dex2oat32")) && - strncmp(file->f_path.dentry->d_iname, "dex2oat64", - sizeof("dex2oat64"))) - return false; - - pathname = five_d_path(&file->f_path, &pathbuf, filename); - - for (i = 0; i < ARRAY_SIZE(dex2oat_full_path); ++i) { - if (!strncmp(pathname, dex2oat_full_path[i], - strlen(dex2oat_full_path[i]) + 1)) { - res = true; - break; - } - } - - if (pathbuf) - __putname(pathbuf); - - return res; -} - -static inline bool match_trusted_executable(const struct five_cert *cert, - const struct integrity_iint_cache *iint, - const struct file *file) -{ - const struct five_cert_header *hdr = NULL; - - if (!cert) - return check_dex2oat_binary && is_dex2oat_binary(file); - - if (five_get_cache_status(iint) != FIVE_FILE_RSA) - return false; - - hdr = (const struct five_cert_header *)cert->body.header->value; - - if (hdr->privilege == FIVE_PRIV_ALLOW_SIGN) - return true; - - return false; -} - -static inline void task_integrity_processing(struct task_integrity *tint) -{ - tint->user_value = INTEGRITY_PROCESSING; -} - -static inline void task_integrity_done(struct task_integrity *tint) -{ - tint->user_value = task_integrity_read(tint); -} - -static void process_file(struct task_struct *task, - struct file *file, - int function, - struct file_verification_result *result) -{ - struct inode *inode = d_real_inode(file_dentry(file)); - struct integrity_iint_cache *iint = NULL; - struct five_cert cert = { {0} }; - struct five_cert *pcert = NULL; - int rc = -ENOMEM; - char *xattr_value = NULL; - int xattr_len = 0; - - if (!S_ISREG(inode->i_mode)) { - rc = 0; - goto out; - } - - iint = integrity_inode_get(inode); - if (!iint) - goto out; - - /* Nothing to do, just return existing appraised status */ - if (five_get_cache_status(iint) != FIVE_FILE_UNKNOWN) { - rc = 0; - goto out; - } - - xattr_len = five_read_xattr(d_real_comp(file->f_path.dentry), - &xattr_value); - if (xattr_value && xattr_len) { - rc = five_cert_fillout(&cert, xattr_value, xattr_len); - if (rc) { - pr_err("FIVE: certificate is incorrect inode=%lu\n", - inode->i_ino); - goto out; - } - - pcert = &cert; - - if (file->f_flags & O_DIRECT) { - rc = -EACCES; - goto out; - } - } - - rc = five_appraise_measurement(task, function, iint, file, pcert); - if (!rc && match_trusted_executable(pcert, iint, file)) - iint->five_flags |= FIVE_TRUSTED_FILE; - -out: - if (rc && iint) - iint->five_flags &= ~FIVE_TRUSTED_FILE; - - result->file = file; - result->task = task; - result->iint = iint; - result->fn = function; - result->xattr = xattr_value; - result->xattr_len = (size_t)xattr_len; - - if (!iint || five_get_cache_status(iint) == FIVE_FILE_UNKNOWN - || five_get_cache_status(iint) == FIVE_FILE_FAIL) - result->five_result = 1; - else - result->five_result = 0; -} - -static void process_measurement(const struct processing_event_list *params) -{ - struct task_struct *task = params->task; - struct task_integrity *integrity = TASK_INTEGRITY(task); - struct file *file = params->file; - struct inode *inode = file_inode(file); - int function = params->function; - struct file_verification_result file_result; - - if (function != BPRM_CHECK) { - if (task_integrity_read(integrity) == INTEGRITY_NONE) - return; - } - - file_verification_result_init(&file_result); - inode_lock(inode); - - process_file(task, file, function, &file_result); - - five_hook_file_processed(task, file, - file_result.xattr, file_result.xattr_len, - file_result.five_result); - - five_state_proceed(integrity, &file_result); - - inode_unlock(inode); - file_verification_result_deinit(&file_result); -} - -#define MFD_NAME_PREFIX "memfd:" -#define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1) - -static bool is_memfd_file(struct file *file) -{ - struct inode *inode; - struct inode *memfd_inode; - - if (!file) - return false; - - memfd_inode = file_inode(memfd_file); - inode = file_inode(file); - if (inode && memfd_inode && inode->i_sb == memfd_inode->i_sb) - if (file->f_path.dentry && - !strncmp(file->f_path.dentry->d_iname, MFD_NAME_PREFIX, - MFD_NAME_PREFIX_LEN)) - return true; - - return false; -} - -/** - * five_file_mmap - measure files being mapped executable based on - * the process_measurement() policy decision. - * @file: pointer to the file to be measured (May be NULL) - * @prot: contains the protection that will be applied by the kernel. - * - * On success return 0. - */ -int five_file_mmap(struct file *file, unsigned long prot) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (five_check_params(task, file)) - return 0; - - if (check_memfd_file && is_memfd_file(file)) - return 0; - - if (file && task_integrity_user_read(tint)) { - if (prot & PROT_EXEC) { - rc = push_file_event_bunch(task, file, MMAP_CHECK); - if (rc) - return rc; - } else { - five_hook_file_skipped(task, file); - } - } - - return rc; -} - -/** - * five_bprm_check - Measure executable being launched based on - * the process_measurement() policy decision. - * @bprm: contains the linux_binprm structure - * - * Notes: - * bprm_check could be called few times for one process when few binary loaders - * are used. Example: execution of shell script. - * In this case we should process first file (e.g. shell script) as main and - * use BPRM_CHECK. The second file (interpetator ) will be processed as general - * mapping (MMAP_CHECK). - * To implement this option variable bprm->recursion_depth is used. - * - * On success return 0. - */ -int five_bprm_check(struct linux_binprm *bprm) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *old_tint = TASK_INTEGRITY(task); - - if (unlikely(task->ptrace)) - return rc; - - if (bprm->recursion_depth > 0) { - rc = push_file_event_bunch(task, bprm->file, MMAP_CHECK); - } else { - struct task_integrity *tint = task_integrity_alloc(); - - task_integrity_assign(task, tint); - if (likely(TASK_INTEGRITY(task))) { - rc = push_file_event_bunch(task, - bprm->file, BPRM_CHECK); - } else { - rc = -ENOMEM; - } - task_integrity_put(old_tint); - } - - return rc; -} - -/* Does `unlink' of the `file'. - * This function breaks delegation (drops file's leases. See - * man 2 fcntl "Leases"). do_unlinkat function in fs/namei.c was used - * as an example. - */ -static int five_unlink(struct file *file) -{ - int rc; - struct dentry *dentry = file->f_path.dentry; - struct inode *inode = d_backing_inode(dentry->d_parent); - struct inode *delegated_inode = NULL; - bool retry; - - do { - delegated_inode = NULL; - retry = false; - inode_lock_nested(inode, I_MUTEX_PARENT); - ihold(inode); - rc = vfs_unlink(inode, dentry, &delegated_inode); - inode_unlock(inode); - iput(inode); - if (rc == -EWOULDBLOCK && delegated_inode) { - rc = break_deleg_wait(&delegated_inode); - if (!rc) - retry = true; - } - } while (retry); - - five_audit_info(current, file, "five_unlink", 0, 0, - "Unlink a file", rc); - - return rc; -} - -/** - * This function handles two situations: - * 1. Device had been rebooted before five_sign finished. - * Then xattr_len will be zero and iint->five_signing will be false. - * 2. The file is being signing when another process tries to open it. - * Then xattr_len will be zero and iint->five_signing will be true. - * - * - five_fcntl_edit stores the xattr with zero length and set - * iint->five_signing to true - * - five_fcntl_sign stores correct certificates and set - * iint->five_signing to false - * - * On success returns 0 - */ -int five_file_open(struct file *file) -{ - ssize_t xattr_len; - struct inode *inode = file_inode(file); - - if (!S_ISREG(inode->i_mode)) - return 0; - - xattr_len = vfs_getxattr(file->f_path.dentry, XATTR_NAME_FIVE, - NULL, 0); - if (xattr_len == 0) { - struct integrity_iint_cache *iint; - bool is_signing = false; - - if (!unlink_on_error) { - five_audit_info(current, file, "five_unlink", 0, 0, - "Found a dummy-cert", 0); - return 0; - } - - inode_lock(inode); - iint = integrity_iint_find(inode); - if (iint) - is_signing = iint->five_signing; - inode_unlock(inode); - - if (!is_signing) { - int rc; - - rc = five_unlink(file); - rc = rc ?: -ENOENT; - - return rc; - } - return -EPERM; - } - - return 0; -} - -/** - * five_file_verify - force five integrity measurements for file - * the process_measurement() policy decision. This check affects - * task integrity. - * @file: pointer to the file to be measured (May be NULL) - * - * On success return 0. - */ -int five_file_verify(struct task_struct *task, struct file *file) -{ - int rc = 0; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (file && task_integrity_user_read(tint)) - rc = push_file_event_bunch(task, file, FILE_CHECK); - - return rc; -} - -static struct notifier_block five_reboot_nb = { - .notifier_call = five_reboot_notifier, - .priority = INT_MAX, -}; - -int five_hash_algo __ro_after_init = HASH_ALGO_SHA1; - -static int __init hash_setup(const char *str) -{ - int i; - - for (i = 0; i < HASH_ALGO__LAST; i++) { - if (strcmp(str, hash_algo_name[i]) == 0) { - five_hash_algo = i; - break; - } - } - - return 1; -} - -static int __init init_five(void) -{ - int error; - - g_five_workqueue = alloc_workqueue("%s", WQ_FREEZABLE | WQ_MEM_RECLAIM, - 0, "five_wq"); - if (!g_five_workqueue) - return -ENOMEM; - - hash_setup(CONFIG_FIVE_DEFAULT_HASH); - error = five_init(); - if (error) - return error; - - error = five_hook_wq_init(); - if (error) - return error; - - error = register_reboot_notifier(&five_reboot_nb); - if (error) - return error; - -/** - * This empty file is needed in is_memfd_file() function. - * The only way to check whether the file was created using memfd_create() - * syscall is to compare its superblock address with address of another memfd - * file. - * - * Below code is copied from shmem_kernel_file_setup(). The difference between - * shmem_file_setup() isshmem_kernel_file_setup() calls __shmem_file_setup() - * with S_PRIVATE flag but shmem_file_setup() calls it without one. After that - * __shmem_file_setup() sets S_PRIVATE flag in inode->i_flags: - inode->i_flags |= i_flags; - */ - memfd_file = shmem_file_setup( - "five_memfd_check", 0, VM_NORESERVE); - if (IS_ERR(memfd_file)) { - error = PTR_ERR(memfd_file); - memfd_file = NULL; - return error; - } - file_inode(memfd_file)->i_flags |= S_PRIVATE; - - error = init_fs(); - if (error) - return error; - - five_dsms_init("1", 0); - - error = five_init_dmverity(); - if (error) - return error; - - error = five_tint_init_dev(); - - return error; -} - -static int fcntl_verify(struct file *file) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint)) - rc = push_file_event_bunch(task, file, FILE_CHECK); - return rc; -} - -/* Called from do_fcntl */ -int five_fcntl_verify_async(struct file *file) -{ - return fcntl_verify(file); -} - -/* Called from do_fcntl */ -int five_fcntl_verify_sync(struct file *file) -{ - return -EINVAL; -} - -int five_fork(struct task_struct *task, struct task_struct *child_task) -{ - int rc = 0; - - spin_lock(&TASK_INTEGRITY(task)->list_lock); - - if (!list_empty(&TASK_INTEGRITY(task)->events.list)) { - /*copy the list*/ - struct list_head *tmp; - struct processing_event_list *from_entry; - struct worker_context *context; - - context = kmalloc(sizeof(struct worker_context), GFP_ATOMIC); - if (unlikely(!context)) { - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - return -ENOMEM; - } - - list_for_each(tmp, &TASK_INTEGRITY(task)->events.list) { - struct processing_event_list *five_file; - - from_entry = list_entry(tmp, - struct processing_event_list, list); - - five_file = five_event_create( - from_entry->event, - child_task, - from_entry->file, - from_entry->function, - GFP_ATOMIC); - if (unlikely(!five_file)) { - kfree(context); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - return -ENOMEM; - } - - list_add_tail(&five_file->list, - &TASK_INTEGRITY(child_task)->events.list); - } - - context->tint = TASK_INTEGRITY(child_task); - - rc = task_integrity_copy(TASK_INTEGRITY(task), - TASK_INTEGRITY(child_task)); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - task_integrity_get(context->tint); - task_integrity_processing(TASK_INTEGRITY(child_task)); - INIT_WORK(&context->data_work, work_handler); - rc = queue_work(g_five_workqueue, &context->data_work) ? 0 : 1; - } else { - rc = task_integrity_copy(TASK_INTEGRITY(task), - TASK_INTEGRITY(child_task)); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - } - - if (!rc) - five_hook_task_forked(task, child_task); - - return rc; -} - -int five_ptrace(struct task_struct *task, long request) -{ - switch (request) { - case PTRACE_TRACEME: - case PTRACE_ATTACH: - case PTRACE_SEIZE: - case PTRACE_INTERRUPT: - case PTRACE_CONT: - case PTRACE_DETACH: - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - case PTRACE_PEEKUSR: - case PTRACE_GETREGSET: - case PTRACE_GETSIGINFO: - case PTRACE_PEEKSIGINFO: - case PTRACE_GETSIGMASK: - case PTRACE_GETEVENTMSG: -#ifdef CONFIG_ARM64 - case COMPAT_PTRACE_GETREGS: - case COMPAT_PTRACE_GET_THREAD_AREA: - case COMPAT_PTRACE_GETVFPREGS: - case COMPAT_PTRACE_GETHBPREGS: -#else - case PTRACE_GETREGS: - case PTRACE_GET_THREAD_AREA: - case PTRACE_GETVFPREGS: - case PTRACE_GETHBPREGS: -#endif - break; - default: { - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint) == INTEGRITY_NONE) - break; - - task_integrity_delayed_reset(task, CAUSE_PTRACE, NULL); - five_audit_err(task, NULL, "ptrace", task_integrity_read(tint), - INTEGRITY_NONE, "reset-integrity", 0); - break; - } - } - - return 0; -} - -int five_process_vm_rw(struct task_struct *task, int write) -{ - if (write) { - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint) == INTEGRITY_NONE) - goto exit; - - task_integrity_delayed_reset(task, CAUSE_VMRW, NULL); - five_audit_err(task, NULL, "process_vm_rw", - task_integrity_read(tint), INTEGRITY_NONE, - "reset-integrity", 0); - } - -exit: - return 0; -} - -static inline struct processing_event_list *five_event_create( - enum five_event event, struct task_struct *task, - struct file *file, int function, gfp_t flags) -{ - struct processing_event_list *five_file; - - five_file = kzalloc(sizeof(struct processing_event_list), flags); - if (unlikely(!five_file)) - return NULL; - - five_file->event = event; - - switch (five_file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - get_task_struct(task); - get_file(file); - five_file->task = task; - five_file->file = file; - five_file->function = function; - break; - } - case FIVE_RESET_INTEGRITY: { - get_task_struct(task); - five_file->task = task; - break; - } - default: - break; - } - - return five_file; -} - -static inline void five_event_destroy( - const struct processing_event_list *file) -{ - switch (file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - fput(file->file); - put_task_struct(file->task); - break; - } - case FIVE_RESET_INTEGRITY: { - put_task_struct(file->task); - break; - } - default: - break; - } - kfree(file); -} - -late_initcall(init_five); - -MODULE_DESCRIPTION("File-based process Integrity Verifier"); -MODULE_LICENSE("GPL"); diff --git a/security/samsung/five/gki/five_pa.c b/security/samsung/five/gki/five_pa.c deleted file mode 100755 index eac7742b6..000000000 --- a/security/samsung/five/gki/five_pa.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Process Authentificator helpers - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/file.h> -#include <linux/module.h> -#include <linux/task_integrity.h> -#include <linux/proca.h> -#include <linux/xattr.h> -#include <linux/version.h> - -#include "five.h" -#include "five_pa.h" -#include "five_hooks.h" -#include "five_lv.h" -#include "five_porting.h" - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) -#define F_SIGNATURE(file) ((void *)((file)->android_oem_data1)) - -static inline void f_signature_assign(struct file *file, void *f_signature) -{ - file->android_oem_data1 = (u64)f_signature; -} -#else -#define F_SIGNATURE(file) ((void *)((file)->android_vendor_data1)) - -static inline void f_signature_assign(struct file *file, void *f_signature) -{ - file->android_vendor_data1 = (u64)f_signature; -} -#endif - -static void process_file(struct task_struct *task, struct file *file) -{ - char *xattr_value = NULL; - - if (F_SIGNATURE(file)) - return; - - if (five_check_params(task, file)) - return; - - five_read_xattr(d_real_comp(file->f_path.dentry), &xattr_value); - f_signature_assign(file, xattr_value); -} - -void fivepa_fsignature_free(struct file *file) -{ - kfree(F_SIGNATURE(file)); - f_signature_assign(file, NULL); -} - -int proca_fcntl_setxattr(struct file *file, void __user *lv_xattr) -{ - struct inode *inode = file_inode(file); - struct lv lv_hdr = {0}; - int rc = -EPERM; - void *x = NULL; - - if (unlikely(!file || !lv_xattr)) - return -EINVAL; - - if (unlikely(copy_from_user(&lv_hdr, lv_xattr, sizeof(lv_hdr)))) - return -EFAULT; - - if (unlikely(lv_hdr.length > PAGE_SIZE)) - return -EINVAL; - - x = kmalloc(lv_hdr.length, GFP_NOFS); - if (unlikely(!x)) - return -ENOMEM; - - if (unlikely(copy_from_user(x, lv_xattr + sizeof(lv_hdr), - lv_hdr.length))) { - rc = -EFAULT; - goto out; - } - - if (file->f_op && file->f_op->flush) - if (file->f_op->flush(file, current->files)) { - rc = -EOPNOTSUPP; - goto out; - } - - inode_lock(inode); - - if (task_integrity_allow_sign(TASK_INTEGRITY(current))) { - rc = __vfs_setxattr_noperm(d_real_comp(file->f_path.dentry), - XATTR_NAME_PA, - x, - lv_hdr.length, - 0); - } - inode_unlock(inode); - -out: - kfree(x); - - return rc; -} - -static void proca_hook_file_processed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result); - -static void proca_hook_file_skipped(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file); - -static struct five_hook_list five_ops[] = { - FIVE_HOOK_INIT(file_processed, proca_hook_file_processed), - FIVE_HOOK_INIT(file_skipped, proca_hook_file_skipped), -}; - -static void proca_hook_file_processed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - process_file(task, file); -} - -static void proca_hook_file_skipped(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file) -{ - process_file(task, file); -} - -static __init int proca_module_init(void) -{ - five_add_hooks(five_ops, ARRAY_SIZE(five_ops)); - pr_info("PROCA was initialized\n"); - - return 0; -} -late_initcall(proca_module_init); - -MODULE_DESCRIPTION("PROCA module"); -MODULE_LICENSE("GPL"); diff --git a/security/samsung/five/gki/five_state.c b/security/samsung/five/gki/five_state.c deleted file mode 100755 index a8c03ce46..000000000 --- a/security/samsung/five/gki/five_state.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * FIVE State machine - * - * Copyright (C) 2017 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/task_integrity.h> -#include "five_audit.h" -#include "five_state.h" -#include "five_hooks.h" -#include "five_cache.h" -#include "five_dsms.h" - -enum task_integrity_state_cause { - STATE_CAUSE_UNKNOWN, - STATE_CAUSE_DIGSIG, - STATE_CAUSE_DMV_PROTECTED, - STATE_CAUSE_TRUSTED, - STATE_CAUSE_HMAC, - STATE_CAUSE_SYSTEM_LABEL, - STATE_CAUSE_NOCERT, - STATE_CAUSE_TAMPERED, - STATE_CAUSE_MISMATCH_LABEL, - STATE_CAUSE_FSV_PROTECTED -}; - -struct task_verification_result { - enum task_integrity_value new_tint; - enum task_integrity_value prev_tint; - enum task_integrity_state_cause cause; -}; - -static const char *task_integrity_state_str( - enum task_integrity_state_cause cause) -{ - const char *str = "unknown"; - - switch (cause) { - case STATE_CAUSE_DIGSIG: - str = "digsig"; - break; - case STATE_CAUSE_DMV_PROTECTED: - str = "dmv_protected"; - break; - case STATE_CAUSE_FSV_PROTECTED: - str = "fsv_protected"; - break; - case STATE_CAUSE_TRUSTED: - str = "trusted"; - break; - case STATE_CAUSE_HMAC: - str = "hmac"; - break; - case STATE_CAUSE_SYSTEM_LABEL: - str = "system_label"; - break; - case STATE_CAUSE_NOCERT: - str = "nocert"; - break; - case STATE_CAUSE_MISMATCH_LABEL: - str = "mismatch_label"; - break; - case STATE_CAUSE_TAMPERED: - str = "tampered"; - break; - case STATE_CAUSE_UNKNOWN: - str = "unknown"; - break; - } - - return str; -} - -static enum task_integrity_reset_cause state_to_reason_cause( - enum task_integrity_state_cause cause) -{ - enum task_integrity_reset_cause reset_cause; - - switch (cause) { - case STATE_CAUSE_UNKNOWN: - reset_cause = CAUSE_UNKNOWN; - break; - case STATE_CAUSE_TAMPERED: - reset_cause = CAUSE_TAMPERED; - break; - case STATE_CAUSE_NOCERT: - reset_cause = CAUSE_NO_CERT; - break; - case STATE_CAUSE_MISMATCH_LABEL: - reset_cause = CAUSE_MISMATCH_LABEL; - break; - default: - /* Integrity is not NONE. */ - reset_cause = CAUSE_UNSET; - break; - } - - return reset_cause; -} - -static int is_system_label(struct integrity_label *label) -{ - if (label && label->len == 0) - return 1; /* system label */ - - return 0; -} - -static inline int integrity_label_cmp(struct integrity_label *l1, - struct integrity_label *l2) -{ - return 0; -} - -static int verify_or_update_label(struct task_integrity *intg, - struct integrity_iint_cache *iint) -{ - struct integrity_label *l; - struct integrity_label *file_label = iint->five_label; - int rc = 0; - - if (!file_label) /* digsig doesn't have label */ - return 0; - - if (is_system_label(file_label)) - return 0; - - spin_lock(&intg->value_lock); - l = intg->label; - - if (l) { - if (integrity_label_cmp(file_label, l)) { - rc = -EPERM; - goto out; - } - } else { - struct integrity_label *new_label; - - new_label = kmalloc(sizeof(file_label->len) + file_label->len, - GFP_ATOMIC); - if (!new_label) { - rc = -ENOMEM; - goto out; - } - - new_label->len = file_label->len; - memcpy(new_label->data, file_label->data, new_label->len); - intg->label = new_label; - } - -out: - spin_unlock(&intg->value_lock); - - return rc; -} - -static bool set_first_state(struct integrity_iint_cache *iint, - struct task_integrity *integrity, - struct task_verification_result *result) -{ - enum task_integrity_value tint = INTEGRITY_NONE; - enum five_file_integrity status = five_get_cache_status(iint); - bool trusted_file = iint->five_flags & FIVE_TRUSTED_FILE; - enum task_integrity_state_cause cause = STATE_CAUSE_UNKNOWN; - - result->new_tint = result->prev_tint = task_integrity_read(integrity); - task_integrity_clear(integrity); - - switch (status) { - case FIVE_FILE_RSA: - if (trusted_file) { - cause = STATE_CAUSE_TRUSTED; - tint = INTEGRITY_PRELOAD_ALLOW_SIGN; - } else { - cause = STATE_CAUSE_DIGSIG; - tint = INTEGRITY_PRELOAD; - } - break; - case FIVE_FILE_FSVERITY: - case FIVE_FILE_DMVERITY: - if (trusted_file) { - cause = STATE_CAUSE_TRUSTED; - tint = INTEGRITY_DMVERITY_ALLOW_SIGN; - } else { - cause = (status == FIVE_FILE_FSVERITY) - ? STATE_CAUSE_FSV_PROTECTED - : STATE_CAUSE_DMV_PROTECTED; - tint = INTEGRITY_DMVERITY; - } - break; - case FIVE_FILE_HMAC: - cause = STATE_CAUSE_HMAC; - tint = INTEGRITY_MIXED; - break; - case FIVE_FILE_FAIL: - cause = STATE_CAUSE_TAMPERED; - tint = INTEGRITY_NONE; - break; - case FIVE_FILE_UNKNOWN: - cause = STATE_CAUSE_NOCERT; - tint = INTEGRITY_NONE; - break; - default: - cause = STATE_CAUSE_NOCERT; - tint = INTEGRITY_NONE; - break; - } - - task_integrity_set(integrity, tint); - result->new_tint = tint; - result->cause = cause; - - return true; -} - -static bool set_next_state(struct integrity_iint_cache *iint, - struct task_integrity *integrity, - struct task_verification_result *result) -{ - bool is_newstate = false; - enum five_file_integrity status = five_get_cache_status(iint); - bool has_digsig = (status == FIVE_FILE_RSA); - bool dmv_protected = (status == FIVE_FILE_DMVERITY); - bool fsv_protected = (status == FIVE_FILE_FSVERITY); - bool xv_protected = dmv_protected || fsv_protected; - struct integrity_label *label = iint->five_label; - enum task_integrity_state_cause cause = STATE_CAUSE_UNKNOWN; - enum task_integrity_value state_tint = INTEGRITY_NONE; - - result->new_tint = result->prev_tint = task_integrity_read(integrity); - - if (has_digsig) - return is_newstate; - - if (status == FIVE_FILE_UNKNOWN || status == FIVE_FILE_FAIL) { - spin_lock(&integrity->value_lock); - - if (status == FIVE_FILE_UNKNOWN) - cause = STATE_CAUSE_NOCERT; - else - cause = STATE_CAUSE_TAMPERED; - - state_tint = INTEGRITY_NONE; - is_newstate = true; - goto out; - } - - if (verify_or_update_label(integrity, iint)) { - spin_lock(&integrity->value_lock); - cause = STATE_CAUSE_MISMATCH_LABEL; - state_tint = INTEGRITY_NONE; - is_newstate = true; - goto out; - } - - spin_lock(&integrity->value_lock); - switch (integrity->value) { - case INTEGRITY_PRELOAD_ALLOW_SIGN: - if (xv_protected) { - cause = fsv_protected ? STATE_CAUSE_FSV_PROTECTED - : STATE_CAUSE_DMV_PROTECTED; - state_tint = INTEGRITY_DMVERITY_ALLOW_SIGN; - } else if (is_system_label(label)) { - cause = STATE_CAUSE_SYSTEM_LABEL; - state_tint = INTEGRITY_MIXED_ALLOW_SIGN; - } else { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - } - is_newstate = true; - break; - case INTEGRITY_PRELOAD: - if (xv_protected) { - cause = fsv_protected ? STATE_CAUSE_FSV_PROTECTED - : STATE_CAUSE_DMV_PROTECTED; - state_tint = INTEGRITY_DMVERITY; - } else { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - } - is_newstate = true; - break; - case INTEGRITY_MIXED_ALLOW_SIGN: - if (!xv_protected && !is_system_label(label)) { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - is_newstate = true; - } - break; - case INTEGRITY_DMVERITY: - if (!xv_protected) { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - is_newstate = true; - } - break; - case INTEGRITY_DMVERITY_ALLOW_SIGN: - if (!xv_protected) { - if (is_system_label(label)) { - cause = STATE_CAUSE_SYSTEM_LABEL; - state_tint = INTEGRITY_MIXED_ALLOW_SIGN; - } else { - cause = STATE_CAUSE_HMAC; - state_tint = INTEGRITY_MIXED; - } - is_newstate = true; - } - break; - case INTEGRITY_MIXED: - break; - case INTEGRITY_NONE: - break; - default: - // Unknown state - cause = STATE_CAUSE_UNKNOWN; - state_tint = INTEGRITY_NONE; - is_newstate = true; - } - -out: - - if (is_newstate) { - __task_integrity_set(integrity, state_tint); - result->new_tint = state_tint; - result->cause = cause; - } - spin_unlock(&integrity->value_lock); - - return is_newstate; -} - -void five_state_proceed(struct task_integrity *integrity, - struct file_verification_result *file_result) -{ - struct integrity_iint_cache *iint = file_result->iint; - enum five_hooks fn = file_result->fn; - struct task_struct *task = file_result->task; - struct file *file = file_result->file; - bool is_newstate; - struct task_verification_result task_result = {}; - - if (!iint) - return; - - if (fn == BPRM_CHECK) - is_newstate = set_first_state(iint, integrity, &task_result); - else - is_newstate = set_next_state(iint, integrity, &task_result); - - if (is_newstate) { - if (task_result.new_tint == INTEGRITY_NONE) { - task_integrity_set_reset_reason(integrity, - state_to_reason_cause(task_result.cause), file); - five_hook_integrity_reset(task, file, - state_to_reason_cause(task_result.cause)); - - if (fn != BPRM_CHECK) { - char comm[TASK_COMM_LEN]; - char filename[NAME_MAX]; - char *pathbuf = NULL; - - five_dsms_reset_integrity( - get_task_comm(comm, task), - task_result.cause, - five_d_path(&file->f_path, &pathbuf, - filename)); - if (pathbuf) - __putname(pathbuf); - } - } - five_audit_verbose(task, file, five_get_string_fn(fn), - task_result.prev_tint, task_result.new_tint, - task_integrity_state_str(task_result.cause), - file_result->five_result); - } -} - diff --git a/security/samsung/five/gki/five_tee_interface.c b/security/samsung/five/gki/five_tee_interface.c deleted file mode 100755 index e7291c06e..000000000 --- a/security/samsung/five/gki/five_tee_interface.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Interface for TEE Driver - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <crypto/hash_info.h> -#include "five_tee_interface.h" -#include "five_tee_api.h" - -static struct five_tee_driver_fns *g_tee_driver_fn; -static char is_registered; -static DECLARE_RWSEM(usage_lock); - -int register_five_tee_driver( - struct five_tee_driver_fns *tee_driver_fns) -{ - int rc = 0; - - if (!tee_driver_fns) - return -EINVAL; - - down_write(&usage_lock); - if (is_registered) { - rc = -EACCES; - goto exit; - } - - g_tee_driver_fn = kmalloc(sizeof(*g_tee_driver_fn), GFP_KERNEL); - if (!g_tee_driver_fn) { - rc = -ENOMEM; - goto exit; - } - - g_tee_driver_fn->verify_hmac = tee_driver_fns->verify_hmac; - g_tee_driver_fn->sign_hmac = tee_driver_fns->sign_hmac; - is_registered = 1; - -exit: - up_write(&usage_lock); - - return rc; -} -EXPORT_SYMBOL_GPL(register_five_tee_driver); - -void unregister_five_tee_driver(void) -{ - down_write(&usage_lock); - if (is_registered) { - kfree(g_tee_driver_fn); - g_tee_driver_fn = NULL; - is_registered = 0; - } - up_write(&usage_lock); -} -EXPORT_SYMBOL_GPL(unregister_five_tee_driver); - -int verify_hash(enum hash_algo algo, const void *hash, size_t hash_len, - const void *label, size_t label_len, - const void *signature, size_t signature_len) -{ - int rc = -ENODEV; - struct tee_iovec args = { - .algo = algo, - .hash = hash, - .hash_len = hash_len, - .label = label, - .label_len = label_len, - .signature = (void *)signature, - .signature_len = signature_len - }; - - down_read(&usage_lock); - if (is_registered) - rc = g_tee_driver_fn->verify_hmac(&args); - up_read(&usage_lock); - - return rc; -} - -int sign_hash(enum hash_algo algo, const void *hash, size_t hash_len, - const void *label, size_t label_len, - void *signature, size_t *signature_len) -{ - int rc = -ENODEV; - struct tee_iovec args = { - .algo = algo, - .hash = hash, - .hash_len = hash_len, - .label = label, - .label_len = label_len, - .signature = signature, - .signature_len = *signature_len - }; - - down_read(&usage_lock); - if (is_registered) - rc = g_tee_driver_fn->sign_hmac(&args); - up_read(&usage_lock); - - *signature_len = args.signature_len; - - return rc; -} diff --git a/security/samsung/five/gki/five_tee_interface.h b/security/samsung/five/gki/five_tee_interface.h deleted file mode 100755 index 6ff986d05..000000000 --- a/security/samsung/five/gki/five_tee_interface.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Interface for TEE Driver - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef INTEGRITY_TEE_DRIVER_H -#define INTEGRITY_TEE_DRIVER_H - -#include <linux/types.h> -#include <crypto/hash_info.h> - -struct tee_iovec { - enum hash_algo algo; - - const void *hash; - size_t hash_len; - - const void *label; - size_t label_len; - - void *signature; - size_t signature_len; - - int rc; -}; - -struct five_tee_driver_fns { - int (*verify_hmac)(const struct tee_iovec *verify_args); - int (*sign_hmac)(struct tee_iovec *sign_args); -}; - -int register_five_tee_driver( - struct five_tee_driver_fns *tee_driver_fns); -void unregister_five_tee_driver(void); - -#endif diff --git a/security/samsung/five/gki/five_tint_dev.c b/security/samsung/five/gki/five_tint_dev.c deleted file mode 100755 index 6172b5bcd..000000000 --- a/security/samsung/five/gki/five_tint_dev.c +++ /dev/null @@ -1,419 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * FIVE task integrity - * - * Copyright (C) 2020 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/cdev.h> -#include <linux/fs.h> -#include <linux/sched/task.h> -#include <linux/uaccess.h> -#include <linux/slab.h> -#include <asm/uaccess.h> -#include <linux/file.h> - -#include "task_integrity.h" -#include "five_tint_dev.h" - -struct tint_message { - uint32_t version; - uint32_t param; - uint64_t reserved; - union __packed { - enum task_integrity_value value; - struct __packed { - uint64_t value_ptr; - uint16_t len_buf; - } label; - struct __packed { - uint64_t i_ino; - enum task_integrity_reset_cause cause; - struct __packed { - uint64_t pathname_ptr; - uint16_t len_buf; - } path; - } reset_file; - struct __packed { - uint64_t label_ptr; - } sign; - } data; -} __packed; - -#define TINT_VERSION 1 -#define TINT_DEV "task_integrity" -#define TINT_IOC_MAGIC 'f' -#define TINT_IOCTL_GET_VALUE \ - _IOWR(TINT_IOC_MAGIC, 1, struct tint_message) -#define TINT_IOCTL_GET_LABEL \ - _IOWR(TINT_IOC_MAGIC, 2, struct tint_message) -#define TINT_IOCTL_GET_RESET_FILE \ - _IOWR(TINT_IOC_MAGIC, 3, struct tint_message) -#define TINT_IOCTL_SIGN_FILE \ - _IOWR(TINT_IOC_MAGIC, 4, struct tint_message) -#define TINT_IOCTL_EDIT_FILE \ - _IOWR(TINT_IOC_MAGIC, 5, struct tint_message) -#define TINT_IOCTL_CLOSE_FILE \ - _IOWR(TINT_IOC_MAGIC, 6, struct tint_message) -#define TINT_IOCTL_VERIFY_SYNC_FILE \ - _IOWR(TINT_IOC_MAGIC, 7, struct tint_message) -#define TINT_IOCTL_VERIFY_ASYNC_FILE \ - _IOWR(TINT_IOC_MAGIC, 8, struct tint_message) - -static struct tint_control { - struct device *pdev; - struct class *driver_class; - dev_t device_no; - struct cdev cdev; -} dev_ctrl; - -static struct task_struct *get_task_by_pid(pid_t pid) -{ - struct task_struct *task = NULL; - struct pid *pid_data; - - pid_data = find_get_pid(pid); - if (unlikely(!pid_data)) { - pr_err("FIVE: Can't find PID: %u\n", pid); - return NULL; - } - - task = get_pid_task(pid_data, PIDTYPE_PID); - if (unlikely(!task)) - pr_err("FIVE: Can't find task by PID: %u\n", pid); - - put_pid(pid_data); - - return task; -} - -static struct task_struct *get_tint_and_task(pid_t pid) -{ - struct task_struct *task = get_task_by_pid(pid); - - if (!task) - return NULL; - - task_integrity_get(TASK_INTEGRITY(task)); - - return task; -} - -static void put_tint_and_task(struct task_struct *task) -{ - if (!task) - return; - - task_integrity_put(TASK_INTEGRITY(task)); - put_task_struct(task); -} - -static int do_command_file(unsigned int cmd, unsigned int fd, - struct integrity_label __user *label) -{ - int ret = 0; - struct file *file; - - file = fget(fd); - if (!file) { - pr_err("FIVE: Can't get file struct: %u\n", cmd); - return -EFAULT; - } - - switch (cmd) { - case TINT_IOCTL_SIGN_FILE: { - ret = five_fcntl_sign(file, label); - break; - } - case TINT_IOCTL_EDIT_FILE: { - ret = five_fcntl_edit(file); - break; - } - case TINT_IOCTL_CLOSE_FILE: { - ret = five_fcntl_close(file); - break; - } - case TINT_IOCTL_VERIFY_SYNC_FILE: { - ret = five_fcntl_verify_sync(file); - break; - } - case TINT_IOCTL_VERIFY_ASYNC_FILE: { - ret = five_fcntl_verify_async(file); - break; - } - default: { - pr_err("FIVE: Invalid IOCTL command: %u\n", cmd); - ret = -ENOIOCTLCMD; - } - } - - if (ret) - pr_err("FIVE: Command failed: %u %d\n", cmd, ret); - - fput(file); - - return ret; -} - -static long tint_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret = 0; - struct tint_message __user *argp = (void __user *) arg; - struct task_struct *task; - struct tint_message msg = {0}; - - if (_IOC_TYPE(cmd) != TINT_IOC_MAGIC) { - pr_err("FIVE: IOCTL type is wrong\n"); - return -ENOTTY; - } - - ret = copy_from_user(&msg, argp, sizeof(msg)); - if (ret) { - pr_err("FIVE: copy_from_user failed ret: %ld\n", ret); - return -EFAULT; - } - - if (msg.version != TINT_VERSION) { - pr_err("FIVE: Unsupported protocol version: %u\n", msg.version); - return -EINVAL; - } - - switch (cmd) { - case TINT_IOCTL_GET_VALUE: { - task = get_tint_and_task(msg.param); - if (!task) { - ret = -ESRCH; - break; - } - - msg.data.value = task_integrity_user_read(TASK_INTEGRITY(task)); - - ret = copy_to_user( - (void __user *) &argp->data.value, &msg.data.value, - sizeof(msg.data.value)); - if (unlikely(ret)) { - pr_err("FIVE: copy_to_user failed: %u %ld\n", - cmd, ret); - ret = -EFAULT; - } - - put_tint_and_task(task); - break; - } - case TINT_IOCTL_GET_LABEL: { - const struct integrity_label *label; - - task = get_tint_and_task(msg.param); - if (!task) { - ret = -ESRCH; - break; - } - - spin_lock(&TASK_INTEGRITY(task)->value_lock); - label = TASK_INTEGRITY(task)->label; - spin_unlock(&TASK_INTEGRITY(task)->value_lock); - - if (!label) { - ret = -ENOENT; - put_tint_and_task(task); - break; - } - - if (msg.data.label.len_buf < sizeof(label->len) + label->len) { - pr_err("FIVE: User buffer is small for label: %u %u", - cmd, msg.data.label.len_buf); - ret = -EINVAL; - put_tint_and_task(task); - break; - } - - ret = copy_to_user( - (void __user *) msg.data.label.value_ptr, label, - sizeof(label->len) + label->len); - if (unlikely(ret)) { - pr_err("FIVE: copy_to_user failed len: %u %ld\n", - cmd, ret); - ret = -EFAULT; - } - - put_tint_and_task(task); - break; - } - case TINT_IOCTL_GET_RESET_FILE: { - const struct file *reset_file; - const struct inode *inode; - uint16_t len_buf; - char *buf, *pathname; - - task = get_tint_and_task(msg.param); - if (!task) { - ret = -ESRCH; - break; - } - - reset_file = TASK_INTEGRITY(task)->reset_file; - if (!reset_file) { - ret = -ENOENT; - put_tint_and_task(task); - break; - } - - inode = file_inode(reset_file); - msg.data.reset_file.i_ino = inode->i_ino; - msg.data.reset_file.cause = TASK_INTEGRITY(task)->reset_cause; - len_buf = msg.data.reset_file.path.len_buf; - - if (!len_buf || len_buf > PAGE_SIZE) { - pr_err("FIVE: Bad size of user buffer: %u %u", - cmd, len_buf); - ret = -EINVAL; - put_tint_and_task(task); - break; - } - - buf = kmalloc(len_buf, GFP_KERNEL); - if (unlikely(!buf)) { - pr_err("FIVE: Can't allocate memory: %u %u", - cmd, len_buf); - ret = -ENOMEM; - put_tint_and_task(task); - break; - } - - pathname = d_path(&reset_file->f_path, buf, len_buf); - if (IS_ERR(pathname)) { - pr_err("FIVE: Can't obtain path: %u", len_buf); - ret = -ENOMEM; - kfree(buf); - put_tint_and_task(task); - break; - } - - len_buf = strnlen(pathname, len_buf) + 1; - - ret = copy_to_user( - (void __user *) msg.data.reset_file.path.pathname_ptr, - pathname, len_buf); - if (unlikely(ret)) { - pr_err("FIVE: copy_to_user failed path: %u %ld\n", - cmd, ret); - ret = -EFAULT; - kfree(buf); - put_tint_and_task(task); - break; - } - - ret = copy_to_user((void __user *) &argp->data.reset_file, - &msg.data.reset_file, - sizeof(msg.data.reset_file)); - - if (unlikely(ret)) { - pr_err("FIVE: copy_to_user failed: %u %ld\n", - cmd, ret); - ret = -EFAULT; - } - - kfree(buf); - put_tint_and_task(task); - break; - } - case TINT_IOCTL_SIGN_FILE: - case TINT_IOCTL_EDIT_FILE: - case TINT_IOCTL_CLOSE_FILE: - case TINT_IOCTL_VERIFY_SYNC_FILE: - case TINT_IOCTL_VERIFY_ASYNC_FILE: { - ret = do_command_file(cmd, msg.param, - (struct integrity_label __user *) msg.data.sign.label_ptr); - break; - } - default: { - pr_err("FIVE: Invalid IOCTL command: %u\n", cmd); - ret = -ENOIOCTLCMD; - } - } - - return ret; -} - -#ifdef CONFIG_COMPAT -static long tint_compact_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return tint_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); -} -#endif - -static const struct file_operations tint_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = tint_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = tint_compact_ioctl, -#endif -}; - -int __init five_tint_init_dev(void) -{ - int rc = 0; - - rc = alloc_chrdev_region(&dev_ctrl.device_no, 0, 1, TINT_DEV); - if (unlikely(rc < 0)) { - pr_err("FIVE: alloc_chrdev_region failed %d\n", rc); - return rc; - } - - dev_ctrl.driver_class = class_create(THIS_MODULE, TINT_DEV); - if (IS_ERR(dev_ctrl.driver_class)) { - rc = PTR_ERR(dev_ctrl.driver_class); - pr_err("FIVE: class_create failed %d\n", rc); - goto exit_unreg_chrdev_region; - } - - dev_ctrl.pdev = device_create(dev_ctrl.driver_class, NULL, - dev_ctrl.device_no, NULL, TINT_DEV); - if (IS_ERR(dev_ctrl.pdev)) { - rc = PTR_ERR(dev_ctrl.pdev); - pr_err("FIVE: class_device_create failed %d\n", rc); - goto exit_destroy_class; - } - - cdev_init(&dev_ctrl.cdev, &tint_fops); - dev_ctrl.cdev.owner = THIS_MODULE; - - rc = cdev_add(&dev_ctrl.cdev, - MKDEV(MAJOR(dev_ctrl.device_no), 0), 1); - if (unlikely(rc < 0)) { - pr_err("FIVE: cdev_add failed %d\n", rc); - goto exit_destroy_device; - } - - return 0; - -exit_destroy_device: - device_destroy(dev_ctrl.driver_class, dev_ctrl.device_no); -exit_destroy_class: - class_destroy(dev_ctrl.driver_class); -exit_unreg_chrdev_region: - unregister_chrdev_region(dev_ctrl.device_no, 1); - - return rc; -} - -void __exit five_tint_deinit_dev(void) -{ - cdev_del(&dev_ctrl.cdev); - device_destroy(dev_ctrl.driver_class, dev_ctrl.device_no); - class_destroy(dev_ctrl.driver_class); - unregister_chrdev_region(dev_ctrl.device_no, 1); -} diff --git a/security/samsung/five/gki/five_tint_dev.h b/security/samsung/five/gki/five_tint_dev.h deleted file mode 100755 index 18014364b..000000000 --- a/security/samsung/five/gki/five_tint_dev.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * FIVE task integrity - * - * Copyright (C) 2020 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef __LINUX_FIVE_GKI_FIVE_TINT_DEV_H -#define __LINUX_FIVE_GKI_FIVE_TINT_DEV_H - -int __init five_tint_init_dev(void); -void __exit five_tint_deinit_dev(void); - -#endif diff --git a/security/samsung/five/gki/five_vfs.c b/security/samsung/five/gki/five_vfs.c deleted file mode 100755 index 40f476160..000000000 --- a/security/samsung/five/gki/five_vfs.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * FIVE vfs functions - * - * Copyright (C) 2020 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/fs.h> -#include <linux/xattr.h> -#include <linux/uio.h> -#include "five_vfs.h" - -/* This function is an alternative implementation of vfs_getxattr_alloc() */ -ssize_t five_getxattr_alloc(struct dentry *dentry, const char *name, - char **xattr_value, size_t xattr_size, gfp_t flags) -{ - struct inode *inode = dentry->d_inode; - char *value = *xattr_value; - int error; - - error = __vfs_getxattr(dentry, inode, name, NULL, 0, XATTR_NOSECURITY); - if (error < 0) - return error; - - if (!value || (error > xattr_size)) { - value = krealloc(*xattr_value, error + 1, flags); - if (!value) - return -ENOMEM; - memset(value, 0, error + 1); - } - - error = __vfs_getxattr(dentry, inode, name, value, error, - XATTR_NOSECURITY); - *xattr_value = value; - return error; -} - -/* This function is copied from new_sync_read() */ -static ssize_t new_sync_read(struct file *filp, char __user *buf, - size_t len, loff_t *ppos) -{ - struct iovec iov = { .iov_base = buf, .iov_len = len }; - struct kiocb kiocb; - struct iov_iter iter; - ssize_t ret; - - init_sync_kiocb(&kiocb, filp); - kiocb.ki_pos = (ppos ? *ppos : 0); - iov_iter_init(&iter, READ, &iov, 1, len); - - ret = call_read_iter(filp, &kiocb, &iter); - BUG_ON(ret == -EIOCBQUEUED); - if (ppos) - *ppos = kiocb.ki_pos; - return ret; -} - -/* This function is copied from __vfs_read() */ -ssize_t five_vfs_read(struct file *file, char __user *buf, size_t count, - loff_t *pos) -{ - if (file->f_op->read) - return file->f_op->read(file, buf, count, pos); - else if (file->f_op->read_iter) - return new_sync_read(file, buf, count, pos); - else - return -EINVAL; -} - -/* This function is copied from __vfs_setxattr_noperm() */ -int five_setxattr_noperm(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - struct inode *inode = dentry->d_inode; - int error = -EAGAIN; - int issec = !strncmp(name, XATTR_SECURITY_PREFIX, - XATTR_SECURITY_PREFIX_LEN); - - if (issec) - inode->i_flags &= ~S_NOSEC; - if (inode->i_opflags & IOP_XATTR) { - error = __vfs_setxattr(dentry, inode, name, value, size, flags); - } else { - if (unlikely(is_bad_inode(inode))) - return -EIO; - } - - return error; -} - -/* - * five_kernel_read - read data from the file - * - * This is a function for reading file content instead of kernel_read(). - * It does not perform locking checks to ensure it cannot be blocked. - * It does not perform security checks because it is irrelevant for IMA. - * - * This function is copied from integrity_kernel_read() - */ -int five_kernel_read(struct file *file, loff_t offset, - void *addr, unsigned long count) -{ - mm_segment_t old_fs; - char __user *buf = (char __user *)addr; - ssize_t ret; - struct inode *inode = file_inode(file); - - if (!(file->f_mode & FMODE_READ)) - return -EBADF; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - if (inode->i_sb->s_magic == OVERLAYFS_SUPER_MAGIC && file->private_data) - file = (struct file *)file->private_data; - - ret = five_vfs_read(file, buf, count, &offset); - set_fs(old_fs); - - return ret; -} diff --git a/security/samsung/five/gki/five_vfs.h b/security/samsung/five/gki/five_vfs.h deleted file mode 100755 index 980ad105b..000000000 --- a/security/samsung/five/gki/five_vfs.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * FIVE vfs functions - * - * Copyright (C) 2020 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -ssize_t five_getxattr_alloc(struct dentry *dentry, const char *name, - char **xattr_value, size_t xattr_size, gfp_t flags); -ssize_t five_vfs_read(struct file *file, char __user *buf, - size_t count, loff_t *pos); -int five_kernel_read(struct file *file, loff_t offset, - void *addr, unsigned long count); -int five_setxattr_noperm(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); diff --git a/security/samsung/five/gki/task_integrity.c b/security/samsung/five/gki/task_integrity.c deleted file mode 100755 index 449409814..000000000 --- a/security/samsung/five/gki/task_integrity.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Task Integrity Verifier - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/task_integrity.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/slab.h> -#include "five_porting.h" - -static struct kmem_cache *task_integrity_cache; - -static void init_once(void *foo) -{ - struct task_integrity *tint = foo; - - memset(tint, 0, sizeof(*tint)); - spin_lock_init(&tint->value_lock); - spin_lock_init(&tint->list_lock); -} - -int __init five_task_integrity_cache_init(void) -{ - task_integrity_cache = kmem_cache_create("task_integrity_cache", - sizeof(struct task_integrity), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, init_once); - - if (!task_integrity_cache) - return -ENOMEM; - - return 0; -} - -struct task_integrity *task_integrity_alloc(void) -{ - struct task_integrity *tint; - - tint = kmem_cache_alloc(task_integrity_cache, GFP_KERNEL); - if (tint) { - atomic_set(&tint->usage_count, 1); - INIT_LIST_HEAD(&tint->events.list); - } - - return tint; -} - -void task_integrity_free(struct task_integrity *tint) -{ - if (tint) { - /* These values should be changed under "value_lock" spinlock. - But then lockdep prints warning because this function can be called - from sw-irq (from function free_task). - Actually deadlock never happens because this function is called - only if usage_count is 0 (no reference to this struct), - so changing these values without spinlock is safe. - */ - kfree(tint->label); - tint->label = NULL; - tint->user_value = INTEGRITY_NONE; - tint->value = INTEGRITY_NONE; - atomic_set(&tint->usage_count, 0); - - tint->reset_cause = CAUSE_UNSET; - if (tint->reset_file) { - fput(tint->reset_file); - tint->reset_file = NULL; - } - - kmem_cache_free(task_integrity_cache, tint); - } -} - -void task_integrity_clear(struct task_integrity *tint) -{ - task_integrity_set(tint, INTEGRITY_NONE); - spin_lock(&tint->value_lock); - kfree(tint->label); - tint->label = NULL; - spin_unlock(&tint->value_lock); - - tint->reset_cause = CAUSE_UNSET; - if (tint->reset_file) { - fput(tint->reset_file); - tint->reset_file = NULL; - } -} - -static int copy_label(struct task_integrity *from, struct task_integrity *to) -{ - int ret = 0; - struct integrity_label *l = NULL; - - if (task_integrity_read(from) && from->label) - l = from->label; - - if (l) { - struct integrity_label *label; - - label = kmalloc(sizeof(*label) + l->len, GFP_ATOMIC); - if (!label) { - ret = -ENOMEM; - goto exit; - } - - label->len = l->len; - memcpy(label->data, l->data, label->len); - to->label = label; - } - -exit: - return ret; -} - -int task_integrity_copy(struct task_integrity *from, struct task_integrity *to) -{ - int rc = -EPERM; - enum task_integrity_value value = task_integrity_read(from); - - task_integrity_set(to, value); - - if (list_empty(&from->events.list)) - to->user_value = value; - - rc = copy_label(from, to); - - to->reset_cause = from->reset_cause; - if (from->reset_file) { - get_file(from->reset_file); - to->reset_file = from->reset_file; - } - - return rc; -} - -char const * const tint_reset_cause_to_string( - enum task_integrity_reset_cause cause) -{ - static const char * const tint_cause2str[] = { - [CAUSE_UNSET] = "unset", - [CAUSE_UNKNOWN] = "unknown", - [CAUSE_MISMATCH_LABEL] = "mismatch-label", - [CAUSE_BAD_FS] = "bad-fs", - [CAUSE_NO_CERT] = "no-cert", - [CAUSE_INVALID_HASH_LENGTH] = "invalid-hash-length", - [CAUSE_INVALID_HEADER] = "invalid-header", - [CAUSE_CALC_HASH_FAILED] = "calc-hash-failed", - [CAUSE_INVALID_LABEL_DATA] = "invalid-label-data", - [CAUSE_INVALID_SIGNATURE_DATA] = "invalid-signature-data", - [CAUSE_INVALID_HASH] = "invalid-hash", - [CAUSE_INVALID_CALC_CERT_HASH] = "invalid-calc-cert-hash", - [CAUSE_INVALID_UPDATE_LABEL] = "invalid-update-label", - [CAUSE_INVALID_SIGNATURE] = "invalid-signature", - [CAUSE_UKNOWN_FIVE_DATA] = "unknown-five-data", - [CAUSE_PTRACE] = "ptrace", - [CAUSE_VMRW] = "vmrw", - [CAUSE_EXEC] = "exec", - [CAUSE_TAMPERED] = "tampered", - [CAUSE_MAX] = "incorrect-cause", - }; - - if (cause > CAUSE_MAX) - cause = CAUSE_MAX; - - return tint_cause2str[cause]; -} - -/* - * task_integrity_set_reset_reason - * - * Only first call of this function per task will have effect, because first - * reason will be root cause. - */ -void task_integrity_set_reset_reason(struct task_integrity *tint, - enum task_integrity_reset_cause cause, struct file *file) -{ - if (tint->reset_cause != CAUSE_UNSET) - return; - - tint->reset_cause = cause; - if (file) { - get_file(file); - tint->reset_file = file; - } -} diff --git a/security/samsung/five/gki/task_integrity.h b/security/samsung/five/gki/task_integrity.h deleted file mode 100755 index 5f8e0d0e5..000000000 --- a/security/samsung/five/gki/task_integrity.h +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Task Integrity Verifier - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _LINUX_TASK_INTEGRITY_H -#define _LINUX_TASK_INTEGRITY_H - -#include <linux/atomic.h> -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/list.h> -#include <linux/dcache.h> -#include <linux/version.h> - -struct linux_binprm; -struct task_integrity; - -struct integrity_label { - uint16_t len; - uint8_t data[0]; -} __packed; - -enum five_event { - FIVE_RESET_INTEGRITY, - FIVE_VERIFY_BUNCH_FILES, -}; - -/* - * This is list of numbers which Hamming distance is 16 - * - * 0x00000000 <-- used - * 0x0f0f0f0f, - * 0xf0f0f0f0, - * 0x0000ffff, - * 0xffff0000, - * 0xff00ff00, - * 0x00ff00ff, - * 0x33333333,<-- used - * 0xcccccccc,<-- used - * 0x55555555,<-- used - * 0x5a5a5a5a,<-- used - * 0xa5a5a5a5, - * 0xaaaaaaaa,<-- used - * 0x3c3c3c3c,<-- used - * 0xc3c3c3c3, - * 0xffffffff <-- used - */ -enum task_integrity_value { - INTEGRITY_NONE = 0x00000000, - INTEGRITY_PRELOAD = 0x33333333, - INTEGRITY_PRELOAD_ALLOW_SIGN = 0xcccccccc, - INTEGRITY_MIXED = 0x55555555, - INTEGRITY_MIXED_ALLOW_SIGN = 0x5a5a5a5a, - INTEGRITY_DMVERITY = 0xaaaaaaaa, - INTEGRITY_DMVERITY_ALLOW_SIGN = 0x3c3c3c3c, - INTEGRITY_PROCESSING = 0xffffffff -}; - -struct processing_event_list { - enum five_event event; - struct task_struct *task; - struct file *file; - int function; - struct list_head list; -}; - -enum task_integrity_reset_cause { - CAUSE_UNSET, - CAUSE_UNKNOWN, - CAUSE_MISMATCH_LABEL, - CAUSE_BAD_FS, - CAUSE_NO_CERT, - CAUSE_INVALID_HASH_LENGTH, - CAUSE_INVALID_HEADER, - CAUSE_CALC_HASH_FAILED, - CAUSE_INVALID_LABEL_DATA, - CAUSE_INVALID_SIGNATURE_DATA, - CAUSE_INVALID_HASH, - CAUSE_INVALID_CALC_CERT_HASH, - CAUSE_INVALID_UPDATE_LABEL, - CAUSE_INVALID_SIGNATURE, - CAUSE_UKNOWN_FIVE_DATA, - CAUSE_PTRACE, - CAUSE_VMRW, - CAUSE_EXEC, - CAUSE_TAMPERED, - CAUSE_MAX, -}; - -struct task_integrity { - enum task_integrity_value user_value; - enum task_integrity_value value; - atomic_t usage_count; - spinlock_t value_lock; - spinlock_t list_lock; - struct integrity_label *label; - struct processing_event_list events; - enum task_integrity_reset_cause reset_cause; - struct file *reset_file; -}; - -#ifdef CONFIG_FIVE - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) -#define TASK_INTEGRITY(task) \ - ((struct task_integrity *)((task)->android_oem_data1[2])) - -static inline void task_integrity_assign(struct task_struct *task, - struct task_integrity *tint) -{ - task->android_oem_data1[2] = (u64)tint; -} -#else -#define TASK_INTEGRITY(task) \ - ((struct task_integrity *)((task)->android_vendor_data1[2])) - -static inline void task_integrity_assign(struct task_struct *task, - struct task_integrity *tint) -{ - task->android_vendor_data1[2] = (u64)tint; -} -#endif - -extern void task_integrity_set_reset_reason(struct task_integrity *tint, - enum task_integrity_reset_cause cause, struct file *file); - -struct task_integrity *task_integrity_alloc(void); -void task_integrity_free(struct task_integrity *tint); -void task_integrity_clear(struct task_integrity *tint); - -static inline void task_integrity_get(struct task_integrity *tint) -{ - BUG_ON(!atomic_read(&tint->usage_count)); - atomic_inc(&tint->usage_count); -} - -static inline void task_integrity_put(struct task_integrity *tint) -{ - BUG_ON(!atomic_read(&tint->usage_count)); - if (atomic_dec_and_test(&tint->usage_count)) - task_integrity_free(tint); -} - -static inline void __task_integrity_set(struct task_integrity *tint, - enum task_integrity_value value) -{ - tint->value = value; -} - -static inline void task_integrity_set(struct task_integrity *tint, - enum task_integrity_value value) -{ - spin_lock(&tint->value_lock); - tint->value = value; - spin_unlock(&tint->value_lock); -} - -static inline void task_integrity_reset(struct task_integrity *tint) -{ - task_integrity_set(tint, INTEGRITY_NONE); - // If cause is already set, this function will be skipped - task_integrity_set_reset_reason(tint, CAUSE_UNKNOWN, NULL); -} - -extern void task_integrity_delayed_reset(struct task_struct *task, - enum task_integrity_reset_cause cause, struct file *file); - -static inline enum task_integrity_value task_integrity_read( - struct task_integrity *tint) -{ - enum task_integrity_value value; - - spin_lock(&tint->value_lock); - value = tint->value; - spin_unlock(&tint->value_lock); - - return value; -} - -static inline bool task_integrity_value_allow_sign( - enum task_integrity_value value) -{ - if (value == INTEGRITY_PRELOAD_ALLOW_SIGN - || value == INTEGRITY_MIXED_ALLOW_SIGN - || value == INTEGRITY_DMVERITY_ALLOW_SIGN) { - return true; - } - - return false; -} - -/** - * task_integrity_allow_sign - check whether application is allowed to sign - * @tint: pointer to the corresponding integrity struct (Should not be NULL) - * - * On success return true. - */ -static inline bool task_integrity_allow_sign(struct task_integrity *tint) -{ - enum task_integrity_value value = task_integrity_read(tint); - - return task_integrity_value_allow_sign(value); -} - -static inline enum task_integrity_value task_integrity_user_read( - struct task_integrity *tint) -{ - return tint->user_value; -} - -static inline void task_integrity_user_set(struct task_integrity *tint, - enum task_integrity_value value) -{ - tint->user_value = value; -} - -static inline void task_integrity_reset_both(struct task_integrity *tint) -{ - task_integrity_reset(tint); - tint->user_value = INTEGRITY_NONE; -} - -extern int task_integrity_copy(struct task_integrity *from, - struct task_integrity *to); -extern int five_bprm_check(struct linux_binprm *bprm); -extern void five_file_free(struct file *file); -extern int five_file_mmap(struct file *file, unsigned long prot); -extern int five_file_open(struct file *file); -extern int five_file_verify(struct task_struct *task, struct file *file); -extern void five_task_free(struct task_struct *task); - -extern void five_inode_post_setattr(struct task_struct *tsk, - struct dentry *dentry); -extern int five_inode_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len); -extern int five_inode_removexattr(struct dentry *dentry, - const char *xattr_name); -extern int five_fcntl_sign(struct file *file, - struct integrity_label __user *label); -extern int five_fcntl_verify_async(struct file *file); -extern int five_fcntl_verify_sync(struct file *file); -extern int five_fcntl_edit(struct file *file); -extern int five_fcntl_close(struct file *file); -extern int five_fcntl_debug(struct file *file, void __user *arg); -extern int five_fork(struct task_struct *task, struct task_struct *child_task); -extern int five_ptrace(struct task_struct *task, long request); -extern int five_process_vm_rw(struct task_struct *task, int write); -extern char const * const tint_reset_cause_to_string( - enum task_integrity_reset_cause cause); -#else -#define TASK_INTEGRITY(task) (NULL) - -static inline void task_integrity_assign(struct task_struct *task, - struct task_integrity *tint) -{ -} - -static inline struct task_integrity *task_integrity_alloc(void) -{ - return NULL; -} - -static inline void task_integrity_free(struct task_integrity *tint) -{ -} - -static inline void task_integrity_clear(struct task_integrity *tint) -{ -} - -static inline void task_integrity_set(struct task_integrity *tint, - enum task_integrity_value value) -{ -} - -static inline void task_integrity_reset(struct task_integrity *tint) -{ -} - -static inline enum task_integrity_value task_integrity_read( - struct task_integrity *tint) -{ - return INTEGRITY_NONE; -} - -static inline void task_integrity_user_set(struct task_integrity *tint, - enum task_integrity_value value) -{ -} - -static inline enum task_integrity_value task_integrity_user_read( - struct task_integrity *tint) -{ - return INTEGRITY_NONE; -} - -static inline void task_integrity_delayed_reset(struct task_struct *task, - enum task_integrity_reset_cause cause, struct file *file) -{ -} - -static inline void task_integrity_reset_both(struct task_integrity *tint) -{ -} - -static inline void task_integrity_add_file(struct task_integrity *tint) -{ -} - -static inline void task_integrity_report_file(struct task_integrity *tint) -{ -} - -static inline int five_bprm_check(struct linux_binprm *bprm) -{ - return 0; -} - -static inline void five_file_free(struct file *file) -{ -} - -static inline int five_file_mmap(struct file *file, unsigned long prot) -{ - return 0; -} - -static inline int five_file_open(struct file *file) -{ - return 0; -} - -static inline int five_file_verify(struct task_struct *task, struct file *file) -{ - return 0; -} - -static inline void five_task_free(struct task_struct *task) -{ -} - -static inline void five_inode_post_setattr(struct task_struct *tsk, - struct dentry *dentry) -{ -} - -static inline int five_inode_setxattr(struct dentry *dentry, - const char *xattr_name, - const void *xattr_value, - size_t xattr_value_len) -{ - return 0; -} - -static inline int five_inode_removexattr(struct dentry *dentry, - const char *xattr_name) -{ - return 0; -} - -static inline int five_fcntl_sign(struct file *file, - struct integrity_label __user *label) -{ - return 0; -} - -static inline int five_fcntl_verify_async(struct file *file) -{ - return 0; -} - -static inline int five_fcntl_verify_sync(struct file *file) -{ - return 0; -} - -static inline int five_fcntl_edit(struct file *file) -{ - return 0; -} - -static inline int five_fcntl_close(struct file *file) -{ - return 0; -} - -static inline int five_fcntl_debug(struct file *file, void __user *arg) -{ - return 0; -} - -static inline int five_fork(struct task_struct *task, - struct task_struct *child_task) -{ - return 0; -} - -static inline int five_ptrace(struct task_struct *task, long request) -{ - return 0; -} - -static inline int five_process_vm_rw(struct task_struct *task, int write) -{ - return 0; -} - -static inline int task_integrity_copy(struct task_integrity *from, - struct task_integrity *to) -{ - return 0; -} - -static inline char const * const tint_reset_cause_to_string( - enum task_integrity_reset_cause cause) -{ - return NULL; -} - -static inline void task_integrity_set_reset_reason(struct task_integrity *tint, - enum task_integrity_reset_cause cause, struct file *file) -{ -} -#endif - -#endif /* _LINUX_TASK_INTEGRITY_H */ diff --git a/security/samsung/five/s_os/dummy.h b/security/samsung/five/s_os/dummy.h deleted file mode 100755 index 668fc5389..000000000 --- a/security/samsung/five/s_os/dummy.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Dummy header - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Jonghun Song, <justin.song@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ diff --git a/security/samsung/five/s_os/five_appraise.c b/security/samsung/five/s_os/five_appraise.c deleted file mode 100755 index a731272f0..000000000 --- a/security/samsung/five/s_os/five_appraise.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/magic.h> -#include <crypto/hash_info.h> - -#include <linux/task_integrity.h> -#include "five.h" -#include "five_audit.h" -#include "five_hooks.h" -#include "five_tee_api.h" -#include "five_porting.h" -#include "five_cache.h" -#include "five_dmverity.h" - -int five_read_xattr(struct dentry *dentry, char **xattr_value) -{ - ssize_t ret; - - ret = vfs_getxattr_alloc(dentry, XATTR_NAME_FIVE, xattr_value, - 0, GFP_NOFS); - if (ret < 0) - ret = 0; - - return ret; -} - -static bool bad_fs(struct inode *inode) -{ - if (inode->i_sb->s_magic == EXT4_SUPER_MAGIC || - inode->i_sb->s_magic == F2FS_SUPER_MAGIC || - inode->i_sb->s_magic == OVERLAYFS_SUPER_MAGIC || - inode->i_sb->s_magic == EROFS_SUPER_MAGIC_V1) - return false; - - return true; -} - -static bool readonly_sb(struct inode *inode) -{ - if (inode->i_sb->s_flags & MS_RDONLY) - return true; - - return false; -} - -/* - * five_is_fsverity_protected - checks if file is protected by FSVERITY - * - * Return true/false - */ -static bool five_is_fsverity_protected(const struct inode *inode) -{ - return IS_VERITY(inode); -} - -/* - * five_appraise_measurement - appraise file measurement - * - * Return 0 on success, error code otherwise - */ -int five_appraise_measurement(struct task_struct *task, int func, - struct integrity_iint_cache *iint, - struct file *file, - struct five_cert *cert) -{ - enum task_integrity_reset_cause cause = CAUSE_UNKNOWN; - struct dentry *dentry = NULL; - struct inode *inode = NULL; - enum five_file_integrity status = FIVE_FILE_UNKNOWN; - enum task_integrity_value prev_integrity; - int rc = 0; - - BUG_ON(!task || !iint || !file); - - prev_integrity = task_integrity_read(TASK_INTEGRITY(task)); - dentry = file->f_path.dentry; - inode = d_backing_inode(dentry); - - if (bad_fs(inode)) { - status = FIVE_FILE_FAIL; - cause = CAUSE_BAD_FS; - rc = -ENOTSUPP; - goto out; - } - - cause = CAUSE_NO_CERT; - if (five_is_fsverity_protected(inode)) - status = FIVE_FILE_FSVERITY; - else if (five_is_dmverity_protected(file)) - status = FIVE_FILE_DMVERITY; - -out: - if (status == FIVE_FILE_FAIL || status == FIVE_FILE_UNKNOWN) { - task_integrity_set_reset_reason(TASK_INTEGRITY(task), - cause, file); - five_audit_verbose(task, file, five_get_string_fn(func), - prev_integrity, prev_integrity, - tint_reset_cause_to_string(cause), rc); - } - - five_set_cache_status(iint, status); - - return rc; -} - -static void five_reset_appraise_flags(struct dentry *dentry) -{ - struct inode *inode = d_backing_inode(dentry); - struct integrity_iint_cache *iint; - - if (!S_ISREG(inode->i_mode)) - return; - - iint = integrity_iint_find(inode); - if (iint) - five_set_cache_status(iint, FIVE_FILE_UNKNOWN); -} - -/** - * five_inode_post_setattr - reflect file metadata changes - * @dentry: pointer to the affected dentry - * - * Changes to a dentry's metadata might result in needing to appraise. - * - * This function is called from notify_change(), which expects the caller - * to lock the inode's i_mutex. - */ -void five_inode_post_setattr(struct task_struct *task, struct dentry *dentry) -{ - five_reset_appraise_flags(dentry); -} - -/* - * five_protect_xattr - protect 'security.five' - * - * Ensure that not just anyone can modify or remove 'security.five'. - */ -static int five_protect_xattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) -{ - if (strcmp(xattr_name, XATTR_NAME_FIVE) == 0) { - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return 1; - } - return 0; -} - -int five_inode_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) -{ - int result = five_protect_xattr(dentry, xattr_name, xattr_value, - xattr_value_len); - - if (result == 1 && xattr_value_len == 0) { - five_reset_appraise_flags(dentry); - return 0; - } - - if (result == 1) { - bool digsig; - struct five_cert_header *header; - struct five_cert cert = { {0} }; - - result = five_cert_fillout(&cert, xattr_value, xattr_value_len); - if (result) - return result; - - header = (struct five_cert_header *)cert.body.header->value; - - if (!xattr_value_len || !header || - (header->signature_type >= FIVE_XATTR_END)) - return -EINVAL; - - digsig = (header->signature_type == FIVE_XATTR_DIGSIG); - if (!digsig) - return -EPERM; - - five_reset_appraise_flags(dentry); - result = 0; - } - - return result; -} - -int five_inode_removexattr(struct dentry *dentry, const char *xattr_name) -{ - int result; - - result = five_protect_xattr(dentry, xattr_name, NULL, 0); - if (result == 1) { - five_reset_appraise_flags(dentry); - result = 0; - } - return result; -} - -/* Called from do_fcntl */ -int five_fcntl_sign(struct file *file, struct integrity_label __user *label) -{ - return -EOPNOTSUPP; -} - -static int check_input_inode(struct inode *inode) -{ - if (!S_ISREG(inode->i_mode)) - return -EINVAL; - - if (readonly_sb(inode)) { - pr_err("FIVE: Can't sign a file on RO FS\n"); - return -EROFS; - } - - return 0; -} - -int five_fcntl_edit(struct file *file) -{ - int rc; - struct dentry *dentry; - uint8_t *raw_cert = NULL; - size_t raw_cert_len = 0; - struct integrity_iint_cache *iint; - struct inode *inode = file_inode(file); - - rc = check_input_inode(inode); - if (rc) - return rc; - - if (!task_integrity_allow_sign(TASK_INTEGRITY(current))) - return -EPERM; - - inode_lock(inode); - dentry = file->f_path.dentry; - rc = __vfs_setxattr_noperm(d_real_comp(dentry), - XATTR_NAME_FIVE, - raw_cert, - raw_cert_len, - 0); - iint = integrity_inode_get(inode); - if (iint) - iint->five_signing = true; - inode_unlock(inode); - - return rc; -} - -int five_fcntl_close(struct file *file) -{ - int rc; - ssize_t xattr_len; - struct dentry *dentry; - struct integrity_iint_cache *iint; - struct inode *inode = file_inode(file); - - rc = check_input_inode(inode); - if (rc) - return rc; - - inode_lock(inode); - iint = integrity_inode_get(inode); - if (!iint) { - inode_unlock(inode); - return -ENOMEM; - } - - if (iint->five_signing) { - dentry = file->f_path.dentry; - xattr_len = __vfs_getxattr(d_real_comp(dentry), inode, - XATTR_NAME_FIVE, NULL, 0, XATTR_NOSECURITY); - if (xattr_len == 0) - rc = __vfs_removexattr(d_real_comp(dentry), - XATTR_NAME_FIVE); - - iint->five_signing = false; - } - inode_unlock(inode); - - return rc; -} diff --git a/security/samsung/five/s_os/five_main.c b/security/samsung/five/s_os/five_main.c deleted file mode 100755 index e0ee4c5f6..000000000 --- a/security/samsung/five/s_os/five_main.c +++ /dev/null @@ -1,974 +0,0 @@ -/* - * This code is based on IMA's code - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * Viacheslav Vovchenko <v.vovchenko@samsung.com> - * Yevgen Kopylov <y.kopylov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/binfmts.h> -#include <linux/mount.h> -#include <linux/mman.h> -#include <linux/slab.h> -#include <crypto/hash_info.h> -#include <linux/ptrace.h> -#include <linux/task_integrity.h> -#include <linux/debugfs.h> -#include <linux/fs.h> -#include <linux/shmem_fs.h> -#include <linux/version.h> - -#include "five.h" -#include "five_audit.h" -#include "five_hooks.h" -#include "five_state.h" -#include "five_pa.h" -#include "five_porting.h" -#include "five_cache.h" -#include "five_dmverity.h" -#include "five_dsms.h" -#include "five_testing.h" - -/* crash_dump in Android 12 uses this request even if Kernel doesn't - * support it */ -#ifndef PTRACE_PEEKMTETAGS -#define PTRACE_PEEKMTETAGS 33 -#endif - -static const bool check_memfd_file = true; - -static struct file *memfd_file __ro_after_init; -static bool is_five_initialized __ro_after_init; - -static struct workqueue_struct *g_five_workqueue; - -static inline void task_integrity_processing(struct task_integrity *tint); -static inline void task_integrity_done(struct task_integrity *tint); -static void process_measurement(const struct processing_event_list *params); -static inline struct processing_event_list *five_event_create( - enum five_event event, struct task_struct *task, - struct file *file, int function, gfp_t flags); -static inline void five_event_destroy( - const struct processing_event_list *file); - -#ifdef CONFIG_FIVE_DEBUG -static int five_enabled = 1; - -static ssize_t five_enabled_write(struct file *file, const char __user *buf, - size_t count, loff_t *pos) -{ - char command; - - if (get_user(command, buf)) - return -EFAULT; - - switch (command) { - case '0': - five_enabled = 0; - break; - case '1': - five_enabled = 1; - break; - default: - pr_err("FIVE: %s: unknown cmd: %hhx\n", __func__, command); - return -EINVAL; - } - - pr_info("FIVE debug: FIVE %s\n", five_enabled ? "enabled" : "disabled"); - return count; -} - -static ssize_t five_enabled_read(struct file *file, char __user *user_buf, - size_t count, loff_t *pos) -{ - char buf[2]; - - buf[0] = five_enabled ? '1' : '0'; - buf[1] = '\n'; - - return simple_read_from_buffer(user_buf, count, pos, buf, sizeof(buf)); -} - -static const struct file_operations five_enabled_fops = { - .owner = THIS_MODULE, - .read = five_enabled_read, - .write = five_enabled_write -}; - -static int __init init_fs(void) -{ - struct dentry *debug_file = NULL; - umode_t umode = (S_IRUGO | S_IWUSR | S_IWGRP); - - debug_file = debugfs_create_file( - "five_enabled", umode, NULL, NULL, &five_enabled_fops); - if (IS_ERR_OR_NULL(debug_file)) - goto error; - - return 0; -error: - if (debug_file) - return -PTR_ERR(debug_file); - - return -EEXIST; -} - -static inline int is_five_enabled(void) -{ - return five_enabled; -} - -int five_fcntl_debug(struct file *file, void __user *argp) -{ - struct inode *inode; - struct five_stat stat = {0}; - struct integrity_iint_cache *iint; - - if (unlikely(!file || !argp)) - return -EINVAL; - - inode = file_inode(file); - - inode_lock(inode); - iint = integrity_inode_get(inode); - if (unlikely(!iint)) { - inode_unlock(inode); - return -ENOMEM; - } - - stat.cache_status = five_get_cache_status(iint); - stat.cache_iversion = inode_query_iversion(iint->inode); - stat.inode_iversion = inode_query_iversion(inode); - - inode_unlock(inode); - - if (unlikely(copy_to_user(argp, &stat, sizeof(stat)))) - return -EFAULT; - - return 0; -} -#else -static int __init init_fs(void) -{ - return 0; -} - -static inline int is_five_enabled(void) -{ - return 1; -} -#endif - -static void work_handler(struct work_struct *in_data) -{ - struct worker_context *context = container_of(in_data, - struct worker_context, data_work); - struct task_integrity *intg; - - if (unlikely(!context)) - return; - - intg = context->tint; - - spin_lock(&intg->list_lock); - while (!list_empty(&(intg->events.list))) { - struct processing_event_list *five_file; - - five_file = list_entry(intg->events.list.next, - struct processing_event_list, list); - spin_unlock(&intg->list_lock); - switch (five_file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - process_measurement(five_file); - break; - } - case FIVE_RESET_INTEGRITY: { - task_integrity_reset(intg); - five_hook_integrity_reset(five_file->task, - NULL, CAUSE_UNKNOWN); - break; - } - default: - break; - } - spin_lock(&intg->list_lock); - list_del(&five_file->list); - five_event_destroy(five_file); - } - - task_integrity_done(intg); - spin_unlock(&intg->list_lock); - task_integrity_put(intg); - - kfree(context); -} - -__mockable -const char *five_d_path(const struct path *path, char **pathbuf, char *namebuf) -{ - char *pathname = NULL; - - *pathbuf = __getname(); - if (*pathbuf) { - pathname = d_absolute_path(path, *pathbuf, PATH_MAX); - if (IS_ERR(pathname)) { - __putname(*pathbuf); - *pathbuf = NULL; - pathname = NULL; - } - } - - if (!pathname) { - strlcpy(namebuf, path->dentry->d_name.name, NAME_MAX); - pathname = namebuf; - } - - return pathname; -} - -int five_check_params(struct task_struct *task, struct file *file) -{ - struct inode *inode; - - if (unlikely(!file)) - return 1; - - inode = file_inode(file); - if (!S_ISREG(inode->i_mode)) - return 1; - - return 0; -} - -/* cut a list into two - * @cur_list: a list with entries - * @new_list: a new list to add all removed entries. Should be an empty list - * - * Use it under spin_lock - * - * The function moves second entry and following entries to new list. - * First entry is left in cur_list. - * - * Initial state: - * [cur_list]<=>[first]<=>[second]<=>[third]<=>...<=>[last] [new_list] - * ^=================================================^ ^====^ - * Result: - * [cur_list]<=>[first] - * ^==========^ - * [new_list]<=>[second]<=>[third]<=>...<=>[last] - * ^=====================================^ - * - * the function is similar to kernel list_cut_position, but there are few - * differences: - * - cut position is second entry - * - original list is left with only first entry - * - moving entries are from second entry to last entry - */ -static void list_cut_tail(struct list_head *cur_list, - struct list_head *new_list) -{ - if ((!list_empty(cur_list)) && - (!list_is_singular(cur_list))) { - new_list->next = cur_list->next->next; - cur_list->next->next->prev = new_list; - cur_list->next->next = cur_list; - new_list->prev = cur_list->prev; - cur_list->prev->next = new_list; - cur_list->prev = cur_list->next; - } -} - -static void free_files_list(struct list_head *list) -{ - struct list_head *tmp, *list_entry; - struct processing_event_list *file_entry; - - list_for_each_safe(list_entry, tmp, list) { - file_entry = list_entry(list_entry, - struct processing_event_list, list); - list_del(&file_entry->list); - five_event_destroy(file_entry); - } -} - -static int push_file_event_bunch(struct task_struct *task, struct file *file, - int function) -{ - int rc = 0; - struct worker_context *context; - struct processing_event_list *five_file; - - if (unlikely(!is_five_enabled()) || five_check_params(task, file)) - return 0; - - context = kmalloc(sizeof(struct worker_context), GFP_KERNEL); - if (unlikely(!context)) - return -ENOMEM; - - five_file = five_event_create(FIVE_VERIFY_BUNCH_FILES, task, file, - function, GFP_KERNEL); - if (unlikely(!five_file)) { - kfree(context); - return -ENOMEM; - } - - spin_lock(&TASK_INTEGRITY(task)->list_lock); - - if (list_empty(&(TASK_INTEGRITY(task)->events.list))) { - task_integrity_get(TASK_INTEGRITY(task)); - task_integrity_processing(TASK_INTEGRITY(task)); - - context->tint = TASK_INTEGRITY(task); - - list_add_tail(&five_file->list, - &TASK_INTEGRITY(task)->events.list); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - INIT_WORK(&context->data_work, work_handler); - rc = queue_work(g_five_workqueue, &context->data_work) ? 0 : 1; - } else { - struct list_head dead_list; - - INIT_LIST_HEAD(&dead_list); - if ((function == BPRM_CHECK) && - (!list_is_singular(&(TASK_INTEGRITY(task)->events.list)))) { - list_cut_tail(&TASK_INTEGRITY(task)->events.list, - &dead_list); - } - list_add_tail(&five_file->list, - &TASK_INTEGRITY(task)->events.list); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - free_files_list(&dead_list); - kfree(context); - } - return rc; -} - -static int push_reset_event(struct task_struct *task, - enum task_integrity_reset_cause cause, struct file *file) -{ - struct list_head dead_list; - struct task_integrity *current_tint; - struct processing_event_list *five_reset; - - if (unlikely(!is_five_enabled())) - return 0; - - INIT_LIST_HEAD(&dead_list); - current_tint = TASK_INTEGRITY(task); - task_integrity_get(current_tint); - - task_integrity_set_reset_reason(current_tint, cause, file); - - five_reset = five_event_create(FIVE_RESET_INTEGRITY, task, NULL, 0, - GFP_KERNEL); - if (unlikely(!five_reset)) { - task_integrity_reset_both(current_tint); - five_hook_integrity_reset(task, file, cause); - task_integrity_put(current_tint); - return -ENOMEM; - } - - task_integrity_reset_both(current_tint); - five_hook_integrity_reset(task, file, cause); - spin_lock(¤t_tint->list_lock); - if (!list_empty(¤t_tint->events.list)) { - list_cut_tail(¤t_tint->events.list, &dead_list); - five_reset->event = FIVE_RESET_INTEGRITY; - list_add_tail(&five_reset->list, ¤t_tint->events.list); - spin_unlock(¤t_tint->list_lock); - } else { - spin_unlock(¤t_tint->list_lock); - five_event_destroy(five_reset); - } - - task_integrity_put(current_tint); - /* remove dead_list */ - free_files_list(&dead_list); - return 0; -} - -void task_integrity_delayed_reset(struct task_struct *task, - enum task_integrity_reset_cause cause, struct file *file) -{ - push_reset_event(task, cause, file); -} - -static void five_check_last_writer(struct integrity_iint_cache *iint, - struct inode *inode, struct file *file) -{ - fmode_t mode = file->f_mode; - - if (!(mode & FMODE_WRITE)) - return; - - inode_lock(inode); - if (atomic_read(&inode->i_writecount) == 1) { - if (!inode_eq_iversion(inode, iint->version)) - five_set_cache_status(iint, FIVE_FILE_UNKNOWN); - } - iint->five_signing = false; - inode_unlock(inode); -} - -/** - * five_file_free - called on __fput() - * @file: pointer to file structure being freed - * - * Flag files that changed, based on i_version - */ -void five_file_free(struct file *file) -{ - struct inode *inode = file_inode(file); - struct integrity_iint_cache *iint; - - if (!S_ISREG(inode->i_mode)) - return; - - fivepa_fsignature_free(file); - - iint = integrity_iint_find(inode); - if (!iint) - return; - - five_check_last_writer(iint, inode, file); -} - -void five_task_free(struct task_struct *task) -{ - task_integrity_put(TASK_INTEGRITY(task)); -} - -/* Returns string representation of input function */ -const char *five_get_string_fn(enum five_hooks fn) -{ - switch (fn) { - case FILE_CHECK: - return "file-check"; - case MMAP_CHECK: - return "mmap-check"; - case BPRM_CHECK: - return "bprm-check"; - case POST_SETATTR: - return "post-setattr"; - } - return "unknown-function"; -} - -static inline void task_integrity_processing(struct task_integrity *tint) -{ - tint->user_value = INTEGRITY_PROCESSING; -} - -static inline void task_integrity_done(struct task_integrity *tint) -{ - tint->user_value = task_integrity_read(tint); -} - -static void process_file(struct task_struct *task, - struct file *file, - int function, - struct file_verification_result *result) -{ - struct inode *inode = d_real_inode(file_dentry(file)); - struct integrity_iint_cache *iint = NULL; - int rc = -ENOMEM; - - if (!S_ISREG(inode->i_mode)) { - rc = 0; - goto out; - } - - iint = integrity_inode_get(inode); - if (!iint) - goto out; - - /* Nothing to do, just return existing appraised status */ - if (five_get_cache_status(iint) != FIVE_FILE_UNKNOWN) { - rc = 0; - goto out; - } - - rc = five_appraise_measurement(task, function, iint, file, NULL); - -out: - if (rc && iint) - iint->five_flags &= ~FIVE_TRUSTED_FILE; - - result->file = file; - result->task = task; - result->iint = iint; - result->fn = function; - result->xattr = NULL; - result->xattr_len = 0; - - if (!iint || five_get_cache_status(iint) == FIVE_FILE_UNKNOWN - || five_get_cache_status(iint) == FIVE_FILE_FAIL) - result->five_result = 1; - else - result->five_result = 0; -} - -static void process_measurement(const struct processing_event_list *params) -{ - struct task_struct *task = params->task; - struct task_integrity *integrity = TASK_INTEGRITY(task); - struct file *file = params->file; - struct inode *inode = file_inode(file); - int function = params->function; - struct file_verification_result file_result; - - if (function != BPRM_CHECK) { - if (task_integrity_read(integrity) == INTEGRITY_NONE) - return; - } - - file_verification_result_init(&file_result); - inode_lock(inode); - - process_file(task, file, function, &file_result); - - five_hook_file_processed(task, file, - file_result.xattr, file_result.xattr_len, - file_result.five_result); - - five_state_proceed(integrity, &file_result); - - inode_unlock(inode); - file_verification_result_deinit(&file_result); -} - -#define MFD_NAME_PREFIX "memfd:" -#define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1) - -static bool is_memfd_file(struct file *file) -{ - struct inode *inode; - struct inode *memfd_inode; - - if (!file) - return false; - - memfd_inode = file_inode(memfd_file); - inode = file_inode(file); - if (inode && memfd_inode && inode->i_sb == memfd_inode->i_sb) - if (file->f_path.dentry && - !strncmp(file->f_path.dentry->d_iname, MFD_NAME_PREFIX, - MFD_NAME_PREFIX_LEN)) - return true; - - return false; -} - -static bool is_dalvik_cache_file(struct file *file) -{ - const char dalvik_prefix[] = "/data/dalvik-cache/arm"; - - const char *pathname = NULL; - char *pathbuf = NULL; - - char filename[NAME_MAX]; - bool res = false; - - if (!file || !file->f_path.dentry) - return false; - - pathname = five_d_path(&file->f_path, &pathbuf, filename); - if (!strncmp(pathname, dalvik_prefix, strlen(dalvik_prefix))) - res = true; - - if (pathbuf) - __putname(pathbuf); - - return res; -} - -/** - * five_file_mmap - measure files being mapped executable based on - * the process_measurement() policy decision. - * @file: pointer to the file to be measured (May be NULL) - * @prot: contains the protection that will be applied by the kernel. - * - * On success return 0. - */ -int five_file_mmap(struct file *file, unsigned long prot) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (unlikely(!is_five_initialized) || five_check_params(task, file)) - return 0; - - if (check_memfd_file && is_memfd_file(file)) - return 0; - - if (file && task_integrity_user_read(tint)) { - if ((prot & PROT_EXEC) && !is_dalvik_cache_file(file)) { - rc = push_file_event_bunch(task, file, MMAP_CHECK); - if (rc) - return rc; - } else { - five_hook_file_skipped(task, file); - } - } - - return rc; -} - -/** - * five_bprm_check - Measure executable being launched based on - * the process_measurement() policy decision. - * @bprm: contains the linux_binprm structure - * - * Notes: - * bprm_check could be called few times for one process when few binary loaders - * are used. Example: execution of shell script. - * In this case we should process first file (e.g. shell script) as main and - * use BPRM_CHECK. The second file (interpetator ) will be processed as general - * mapping (MMAP_CHECK). - * To implement this option variable bprm->recursion_depth is used. - * - * On success return 0. - */ -int __five_bprm_check(struct linux_binprm *bprm, int depth) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *old_tint = TASK_INTEGRITY(task); - - if (unlikely(!is_five_initialized) || unlikely(task->ptrace)) - return rc; - - if (depth > 0) { - rc = push_file_event_bunch(task, bprm->file, MMAP_CHECK); - } else { - struct task_integrity *tint = task_integrity_alloc(); - - task_integrity_assign(task, tint); - if (likely(TASK_INTEGRITY(task))) { - rc = push_file_event_bunch(task, - bprm->file, BPRM_CHECK); - } else { - rc = -ENOMEM; - } - task_integrity_put(old_tint); - } - - return rc; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) -int five_bprm_check(struct linux_binprm *bprm, int depth) -{ - return __five_bprm_check(bprm, depth); -} -#else -int five_bprm_check(struct linux_binprm *bprm) -{ - return __five_bprm_check(bprm, bprm->recursion_depth); -} -#endif - -int five_file_open(struct file *file) -{ - return 0; -} - -/** - * five_file_verify - force five integrity measurements for file - * the process_measurement() policy decision. This check affects - * task integrity. - * @file: pointer to the file to be measured (May be NULL) - * - * On success return 0. - */ -int five_file_verify(struct task_struct *task, struct file *file) -{ - int rc = 0; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (file && task_integrity_user_read(tint)) - rc = push_file_event_bunch(task, file, FILE_CHECK); - - return rc; -} - -int five_hash_algo __ro_after_init = HASH_ALGO_SHA1; - -static int __init hash_setup(const char *str) -{ - int i; - - for (i = 0; i < HASH_ALGO__LAST; i++) { - if (strcmp(str, hash_algo_name[i]) == 0) { - five_hash_algo = i; - break; - } - } - - return 1; -} - -int __init init_five(void) -{ - int error; - - g_five_workqueue = alloc_workqueue("%s", WQ_FREEZABLE | WQ_MEM_RECLAIM, - 0, "five_wq"); - if (!g_five_workqueue) - return -ENOMEM; - - hash_setup(CONFIG_FIVE_DEFAULT_HASH); - error = five_init(); - if (error) - return error; - - error = five_hook_wq_init(); - if (error) - return error; - -/** - * This empty file is needed in is_memfd_file() function. - * The only way to check whether the file was created using memfd_create() - * syscall is to compare its superblock address with address of another memfd - * file. - */ - memfd_file = shmem_kernel_file_setup( - "five_memfd_check", 0, VM_NORESERVE); - if (IS_ERR(memfd_file)) { - error = PTR_ERR(memfd_file); - memfd_file = NULL; - return error; - } - - error = init_fs(); - if (error) - return error; - - five_dsms_init("1", 0); - - error = five_init_dmverity(); - - if (!error) - is_five_initialized = true; - - return error; -} - -static int fcntl_verify(struct file *file) -{ - int rc = 0; - struct task_struct *task = current; - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint)) - rc = push_file_event_bunch(task, file, FILE_CHECK); - return rc; -} - -/* Called from do_fcntl */ -int five_fcntl_verify_async(struct file *file) -{ - return fcntl_verify(file); -} - -/* Called from do_fcntl */ -int five_fcntl_verify_sync(struct file *file) -{ - return -EINVAL; -} - -int five_fork(struct task_struct *task, struct task_struct *child_task) -{ - int rc = 0; - - spin_lock(&TASK_INTEGRITY(task)->list_lock); - - if (!list_empty(&TASK_INTEGRITY(task)->events.list)) { - /*copy the list*/ - struct list_head *tmp; - struct processing_event_list *from_entry; - struct worker_context *context; - - context = kmalloc(sizeof(struct worker_context), GFP_ATOMIC); - if (unlikely(!context)) { - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - return -ENOMEM; - } - - list_for_each(tmp, &TASK_INTEGRITY(task)->events.list) { - struct processing_event_list *five_file; - - from_entry = list_entry(tmp, - struct processing_event_list, list); - - five_file = five_event_create( - from_entry->event, - child_task, - from_entry->file, - from_entry->function, - GFP_ATOMIC); - if (unlikely(!five_file)) { - kfree(context); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - return -ENOMEM; - } - - list_add_tail(&five_file->list, - &TASK_INTEGRITY(child_task)->events.list); - } - - context->tint = TASK_INTEGRITY(child_task); - - rc = task_integrity_copy(TASK_INTEGRITY(task), - TASK_INTEGRITY(child_task)); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - task_integrity_get(context->tint); - task_integrity_processing(TASK_INTEGRITY(child_task)); - INIT_WORK(&context->data_work, work_handler); - rc = queue_work(g_five_workqueue, &context->data_work) ? 0 : 1; - } else { - rc = task_integrity_copy(TASK_INTEGRITY(task), - TASK_INTEGRITY(child_task)); - spin_unlock(&TASK_INTEGRITY(task)->list_lock); - } - - if (!rc) - five_hook_task_forked(task, child_task); - - return rc; -} - -int five_ptrace(struct task_struct *task, long request) -{ - switch (request) { - case PTRACE_TRACEME: - case PTRACE_ATTACH: - case PTRACE_SEIZE: - case PTRACE_INTERRUPT: - case PTRACE_CONT: - case PTRACE_DETACH: - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - case PTRACE_PEEKUSR: - case PTRACE_GETREGSET: - case PTRACE_GETSIGINFO: - case PTRACE_PEEKSIGINFO: - case PTRACE_GETSIGMASK: - case PTRACE_GETEVENTMSG: - case PTRACE_PEEKMTETAGS: -#if defined(CONFIG_ARM64) || defined(KUNIT_UML) - case COMPAT_PTRACE_GETREGS: - case COMPAT_PTRACE_GET_THREAD_AREA: - case COMPAT_PTRACE_GETVFPREGS: - case COMPAT_PTRACE_GETHBPREGS: -#else - case PTRACE_GETREGS: - case PTRACE_GET_THREAD_AREA: - case PTRACE_GETVFPREGS: - case PTRACE_GETHBPREGS: -#endif - break; - default: { - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint) == INTEGRITY_NONE) - break; - - task_integrity_delayed_reset(task, CAUSE_PTRACE, NULL); - five_audit_err(task, NULL, "ptrace", task_integrity_read(tint), - INTEGRITY_NONE, "reset-integrity", 0); - break; - } - } - - return 0; -} - -int five_process_vm_rw(struct task_struct *task, int write) -{ - if (write) { - struct task_integrity *tint = TASK_INTEGRITY(task); - - if (task_integrity_user_read(tint) == INTEGRITY_NONE) - goto exit; - - task_integrity_delayed_reset(task, CAUSE_VMRW, NULL); - five_audit_err(task, NULL, "process_vm_rw", - task_integrity_read(tint), INTEGRITY_NONE, - "reset-integrity", 0); - } - -exit: - return 0; -} - -static inline struct processing_event_list *five_event_create( - enum five_event event, struct task_struct *task, - struct file *file, int function, gfp_t flags) -{ - struct processing_event_list *five_file; - - five_file = kzalloc(sizeof(struct processing_event_list), flags); - if (unlikely(!five_file)) - return NULL; - - five_file->event = event; - - switch (five_file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - get_task_struct(task); - get_file(file); - five_file->task = task; - five_file->file = file; - five_file->function = function; - break; - } - case FIVE_RESET_INTEGRITY: { - get_task_struct(task); - five_file->task = task; - break; - } - default: - break; - } - - return five_file; -} - -static inline void five_event_destroy( - const struct processing_event_list *file) -{ - switch (file->event) { - case FIVE_VERIFY_BUNCH_FILES: { - fput(file->file); - put_task_struct(file->task); - break; - } - case FIVE_RESET_INTEGRITY: { - put_task_struct(file->task); - break; - } - default: - break; - } - kfree(file); -} - -late_initcall(init_five); - -MODULE_DESCRIPTION("File-based process Integrity Verifier"); -MODULE_LICENSE("GPL"); diff --git a/security/samsung/five/task_integrity.c b/security/samsung/five/task_integrity.c deleted file mode 100755 index bfaf0e61b..000000000 --- a/security/samsung/five/task_integrity.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Task Integrity Verifier - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/task_integrity.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/slab.h> -#include "five_porting.h" -#include "five_testing.h" - -static struct kmem_cache *task_integrity_cache; - -__visible_for_testing -void init_once(void *foo) -{ - struct task_integrity *intg = foo; - - memset(intg, 0, sizeof(*intg)); - spin_lock_init(&intg->value_lock); - spin_lock_init(&intg->list_lock); -} - -static int __init task_integrity_cache_init(void) -{ - task_integrity_cache = kmem_cache_create("task_integrity_cache", - sizeof(struct task_integrity), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, init_once); - - if (!task_integrity_cache) - return -ENOMEM; - - return 0; -} - -security_initcall(task_integrity_cache_init); - -struct task_integrity *task_integrity_alloc(void) -{ - struct task_integrity *intg; - - intg = kmem_cache_alloc(task_integrity_cache, GFP_KERNEL); - if (intg) { - atomic_set(&intg->usage_count, 1); - INIT_LIST_HEAD(&intg->events.list); - } - - return intg; -} - -void task_integrity_free(struct task_integrity *intg) -{ - if (intg) { - /* These values should be changed under "value_lock" spinlock. - But then lockdep prints warning because this function can be called - from sw-irq (from function free_task). - Actually deadlock never happens because this function is called - only if usage_count is 0 (no reference to this struct), - so changing these values without spinlock is safe. - */ - kfree(intg->label); - intg->label = NULL; - intg->user_value = INTEGRITY_NONE; - intg->value = INTEGRITY_NONE; - atomic_set(&intg->usage_count, 0); - - intg->reset_cause = CAUSE_UNSET; - if (intg->reset_file) { - fput(intg->reset_file); - intg->reset_file = NULL; - } - - kmem_cache_free(task_integrity_cache, intg); - } -} - -void task_integrity_clear(struct task_integrity *tint) -{ - task_integrity_set(tint, INTEGRITY_NONE); - spin_lock(&tint->value_lock); - kfree(tint->label); - tint->label = NULL; - spin_unlock(&tint->value_lock); - - tint->reset_cause = CAUSE_UNSET; - if (tint->reset_file) { - fput(tint->reset_file); - tint->reset_file = NULL; - } -} - -__visible_for_testing -int copy_label(struct task_integrity *from, struct task_integrity *to) -{ - int ret = 0; - struct integrity_label *l = NULL; - - if (task_integrity_read(from) && from->label) - l = from->label; - - if (l) { - struct integrity_label *label; - - label = kmalloc(sizeof(*label) + l->len, GFP_ATOMIC); - if (!label) { - ret = -ENOMEM; - goto exit; - } - - label->len = l->len; - memcpy(label->data, l->data, label->len); - to->label = label; - } - -exit: - return ret; -} - -int task_integrity_copy(struct task_integrity *from, struct task_integrity *to) -{ - int rc = -EPERM; - enum task_integrity_value value = task_integrity_read(from); - - task_integrity_set(to, value); - - if (list_empty(&from->events.list)) - to->user_value = value; - - rc = copy_label(from, to); - - to->reset_cause = from->reset_cause; - if (from->reset_file) { - get_file(from->reset_file); - to->reset_file = from->reset_file; - } - - return rc; -} - -char const * const tint_reset_cause_to_string( - enum task_integrity_reset_cause cause) -{ - static const char * const tint_cause2str[] = { - [CAUSE_UNSET] = "unset", - [CAUSE_UNKNOWN] = "unknown", - [CAUSE_MISMATCH_LABEL] = "mismatch-label", - [CAUSE_BAD_FS] = "bad-fs", - [CAUSE_NO_CERT] = "no-cert", - [CAUSE_INVALID_HASH_LENGTH] = "invalid-hash-length", - [CAUSE_INVALID_HEADER] = "invalid-header", - [CAUSE_CALC_HASH_FAILED] = "calc-hash-failed", - [CAUSE_INVALID_LABEL_DATA] = "invalid-label-data", - [CAUSE_INVALID_SIGNATURE_DATA] = "invalid-signature-data", - [CAUSE_INVALID_HASH] = "invalid-hash", - [CAUSE_INVALID_CALC_CERT_HASH] = "invalid-calc-cert-hash", - [CAUSE_INVALID_UPDATE_LABEL] = "invalid-update-label", - [CAUSE_INVALID_SIGNATURE] = "invalid-signature", - [CAUSE_UKNOWN_FIVE_DATA] = "unknown-five-data", - [CAUSE_PTRACE] = "ptrace", - [CAUSE_VMRW] = "vmrw", - [CAUSE_EXEC] = "exec", - [CAUSE_TAMPERED] = "tampered", - [CAUSE_MAX] = "incorrect-cause", - }; - - if (cause > CAUSE_MAX) - cause = CAUSE_MAX; - - return tint_cause2str[cause]; -} - -/* - * task_integrity_set_reset_reason - * - * Only first call of this function per task will have effect, because first - * reason will be root cause. - */ -void task_integrity_set_reset_reason(struct task_integrity *intg, - enum task_integrity_reset_cause cause, struct file *file) -{ - if (intg->reset_cause != CAUSE_UNSET) - return; - - intg->reset_cause = cause; - if (file) { - get_file(file); - intg->reset_file = file; - } -} diff --git a/security/samsung/five/x509_five_eng.der b/security/samsung/five/x509_five_eng.der deleted file mode 100755 index 2dfd0ad73..000000000 Binary files a/security/samsung/five/x509_five_eng.der and /dev/null differ diff --git a/security/samsung/five/x509_five_user.der b/security/samsung/five/x509_five_user.der deleted file mode 100755 index 7c15ba096..000000000 Binary files a/security/samsung/five/x509_five_user.der and /dev/null differ diff --git a/security/samsung/proca/Kconfig b/security/samsung/proca/Kconfig deleted file mode 100755 index 885b92fdd..000000000 --- a/security/samsung/proca/Kconfig +++ /dev/null @@ -1,36 +0,0 @@ -# -# PROCA feature configuration -# - -config PROCA - bool "Process Authenticator" - depends on FIVE - default n - help - Enable Process Authenticator - -config PROCA_GKI_10 - bool "GKI 1.0 compatible version of PROCA" - depends on PROCA - default y if FIVE_GKI_10 - default n - help - Build GKI 1.0 compatible version of PROCA - -config PROCA_S_OS - bool "S OS compatible version of PROCA" - depends on PROCA - default n - help - Build S OS compatible version of PROCA - -config PROCA_DEBUG - bool "PROCA Debug mode" - depends on PROCA && !SAMSUNG_PRODUCT_SHIP - default y - help - Enable the debug mode in the PROCA. When this option is enabled - PROCA driver creates file /proc/<pid>/integrity/proca_certificate - which contains hex representation of binary proca certificate. It - might be used to check existence of task descriptor for some task - in proca table. diff --git a/security/samsung/proca/Makefile b/security/samsung/proca/Makefile deleted file mode 100755 index 3135ae40c..000000000 --- a/security/samsung/proca/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -SHELL := /bin/bash - -KERNEL := $(VERSION)_$(PATCHLEVEL) - -# For kernel version 4.14 or lower -ifeq ($(KERNEL),4_14) -$(obj)/proca_certificate-asn1.o: $(obj)/proca_certificate-asn1.c \ - $(obj)/proca_certificate-asn1.h - -$(obj)/proca_certificate.o: $(obj)/proca_certificate-asn1.h - -obj-$(CONFIG_PROCA) += proca_identity.o proca_fcntl.o \ - proca_task_descr.o proca_certificate-asn1.o \ - proca_certificate.o proca_table.o \ - proca_config.o -else -$(obj)/proca_certificate.asn1.o: $(obj)/proca_certificate.asn1.c \ - $(obj)/proca_certificate.asn1.h - -$(obj)/proca_certificate.o: $(obj)/proca_certificate.asn1.h - - -obj-$(CONFIG_PROCA) += proca_identity.o proca_fcntl.o \ - proca_task_descr.o proca_certificate.asn1.o \ - proca_certificate.o proca_table.o \ - proca_config.o -endif - -ccflags-y += -I$(srctree)/security/samsung/proca/ -ccflags-y += -I$(srctree)/security/samsung/five/ - -ifdef CONFIG_PROCA_S_OS -obj-$(CONFIG_PROCA) += s_os/proca_lsm.o -else -obj-$(CONFIG_PROCA) += proca_lsm.o -endif - -# clean-files is given relative to the current directory, -# so don't use (obj)/ prefix here. -# Look at file ../../scripts/Makefile.clean for details. -ifeq ($(KERNEL),4_14) -clean-files += proca_certificate-asn1.c proca_certificate-asn1.h -else -clean-files += proca_certificate.asn1.c proca_certificate.asn1.h -endif - -subdir-ccflags-y += -Wformat - -# kunit tests options: -ifeq ($(CONFIG_SEC_KUNIT)$(CONFIG_UML), yy) - GCOV_PROFILE := y - ccflags-$(CONFIG_PROCA) += -DPROCA_KUNIT_ENABLED -endif diff --git a/security/samsung/proca/gaf/Kconfig b/security/samsung/proca/gaf/Kconfig deleted file mode 100755 index 6f49c684a..000000000 --- a/security/samsung/proca/gaf/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -config GAF - bool "Use GAF structure" - default y if PROCA || FIVE - default n - help - Enable GAF structure - -if GAF -# When adding new entries keep the list in alphabetical order -choice - prompt "Version of GAF structure" - default GAF_V5 if PROCA - default GAF_V4 if FIVE - default GAF_V3 - config GAF_V3 - bool "Use GAF structure version 3" - help - Default option for FIVE-disabled kernel - config GAF_V4 - bool "Use GAF structure version 4" - help - Default option for kernel without PROCA LSM module. - config GAF_V5 - bool "Use GAF structure version 5" - help - Default option for kernel with PROCA 2.0-2.1 LSM module. - config GAF_V6 - bool "Use GAF structure version 6" - help - Default option for kernel with PROCA 2.2+ LSM module. -endchoice - -endif #GAF diff --git a/security/samsung/proca/gaf/Makefile b/security/samsung/proca/gaf/Makefile deleted file mode 100755 index 44edbc2a9..000000000 --- a/security/samsung/proca/gaf/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# When adding new entries keep the list in alphabetical order -obj-$(CONFIG_GAF_V3) += gaf_v3.o -obj-$(CONFIG_GAF_V4) += gaf_v4.o -obj-$(CONFIG_GAF_V5) += gaf_v5.o -obj-$(CONFIG_GAF_V6) += gaf_v6.o - -ccflags-y += -I$(srctree)/security/samsung/proca - -# kunit tests options: -ifeq ($(CONFIG_SEC_KUNIT)$(CONFIG_UML), yy) - GCOV_PROFILE := y - ccflags-$(CONFIG_PROCA) += -DPROCA_KUNIT_ENABLED -endif - diff --git a/security/samsung/proca/gaf/gaf_v3.c b/security/samsung/proca/gaf/gaf_v3.c deleted file mode 100755 index f45deb4a1..000000000 --- a/security/samsung/proca/gaf/gaf_v3.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * gaf_v3.c - * - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/mount.h> -#include <asm/pgtable.h> - -static struct GAForensicINFO { - unsigned short ver; - unsigned int size; - unsigned short task_struct_struct_state; - unsigned short task_struct_struct_comm; - unsigned short task_struct_struct_tasks; - unsigned short task_struct_struct_pid; - unsigned short task_struct_struct_stack; - unsigned short task_struct_struct_mm; - unsigned short mm_struct_struct_start_data; - unsigned short mm_struct_struct_end_data; - unsigned short mm_struct_struct_start_brk; - unsigned short mm_struct_struct_brk; - unsigned short mm_struct_struct_start_stack; - unsigned short mm_struct_struct_arg_start; - unsigned short mm_struct_struct_arg_end; - unsigned short mm_struct_struct_pgd; - unsigned short mm_struct_struct_mmap; - unsigned short vm_area_struct_struct_vm_start; - unsigned short vm_area_struct_struct_vm_end; - unsigned short vm_area_struct_struct_vm_next; - unsigned short vm_area_struct_struct_vm_file; -#ifndef CONFIG_ARM64 - unsigned short thread_info_struct_cpu_context; - unsigned short cpu_context_save_struct_sp; -#endif - unsigned short file_struct_f_path; - unsigned short path_struct_mnt; - unsigned short path_struct_dentry; - unsigned short dentry_struct_d_parent; - unsigned short dentry_struct_d_name; - unsigned short qstr_struct_name; - unsigned short vfsmount_struct_mnt_mountpoint; - unsigned short vfsmount_struct_mnt_root; - unsigned short vfsmount_struct_mnt_parent; -#ifdef CONFIG_ARM64 - unsigned long pgdir_shift; - unsigned long ptrs_per_pte; - unsigned long phys_offset; - unsigned long page_offset; - unsigned long page_shift; - unsigned long page_size; -#else - unsigned int pgdir_shift; - unsigned int ptrs_per_pte; - unsigned int phys_offset; - unsigned int page_offset; - unsigned int page_shift; - unsigned int page_size; -#endif - unsigned short task_struct_struct_thread_group; - unsigned short task_struct_struct_thread; - unsigned short task_struct_struct_utime; - unsigned short task_struct_struct_stime; - unsigned short list_head_struct_next; - unsigned short list_head_struct_prev; - unsigned short rq_struct_curr; - - unsigned short thread_info_struct_cpu; - - unsigned short task_struct_struct_prio; - unsigned short task_struct_struct_static_prio; - unsigned short task_struct_struct_normal_prio; - unsigned short task_struct_struct_rt_priority; - - unsigned short task_struct_struct_se; - - unsigned short sched_entity_struct_exec_start; - unsigned short sched_entity_struct_sum_exec_runtime; - unsigned short sched_entity_struct_prev_sum_exec_runtime; - - unsigned short task_struct_struct_sched_info; - - unsigned short sched_info_struct_pcount; - unsigned short sched_info_struct_run_delay; - unsigned short sched_info_struct_last_arrival; - unsigned short sched_info_struct_last_queued; - - unsigned short task_struct_struct_blocked_on; - - unsigned short mutex_waiter_struct_list; - unsigned short mutex_waiter_struct_task; - - unsigned short sched_entity_struct_cfs_rq_struct; - unsigned short cfs_rq_struct_rq_struct; - unsigned short gaf_fp; - unsigned short GAFINFOCheckSum; -} GAFINFO = { - .ver = 0x0300, /* by dh3s.choi 2010 12 14 */ - .size = sizeof(GAFINFO), - .task_struct_struct_state = offsetof(struct task_struct, state), - .task_struct_struct_comm = offsetof(struct task_struct, comm), - .task_struct_struct_tasks = offsetof(struct task_struct, tasks), - .task_struct_struct_pid = offsetof(struct task_struct, pid), - .task_struct_struct_stack = offsetof(struct task_struct, stack), - .task_struct_struct_mm = offsetof(struct task_struct, mm), - .mm_struct_struct_start_data = offsetof(struct mm_struct, start_data), - .mm_struct_struct_end_data = offsetof(struct mm_struct, end_data), - .mm_struct_struct_start_brk = offsetof(struct mm_struct, start_brk), - .mm_struct_struct_brk = offsetof(struct mm_struct, brk), - .mm_struct_struct_start_stack = offsetof(struct mm_struct, start_stack), - .mm_struct_struct_arg_start = offsetof(struct mm_struct, arg_start), - .mm_struct_struct_arg_end = offsetof(struct mm_struct, arg_end), - .mm_struct_struct_pgd = offsetof(struct mm_struct, pgd), - .mm_struct_struct_mmap = offsetof(struct mm_struct, mmap), - .vm_area_struct_struct_vm_start - = offsetof(struct vm_area_struct, vm_start), - .vm_area_struct_struct_vm_end - = offsetof(struct vm_area_struct, vm_end), - .vm_area_struct_struct_vm_next - = offsetof(struct vm_area_struct, vm_next), - .vm_area_struct_struct_vm_file - = offsetof(struct vm_area_struct, vm_file), -#ifndef CONFIG_ARM64 - .thread_info_struct_cpu_context - = offsetof(struct thread_info, cpu_context), - .cpu_context_save_struct_sp = offsetof(struct cpu_context_save, sp), -#endif - .file_struct_f_path = offsetof(struct file, f_path), - .path_struct_mnt = offsetof(struct path, mnt), - .path_struct_dentry = offsetof(struct path, dentry), - .dentry_struct_d_parent = offsetof(struct dentry, d_parent), - .dentry_struct_d_name = offsetof(struct dentry, d_name), - .qstr_struct_name = offsetof(struct qstr, name), -#if 0 - .vfsmount_struct_mnt_mountpoint - = offsetof(struct vfsmount, mnt_mountpoint), -#endif - .vfsmount_struct_mnt_root = offsetof(struct vfsmount, mnt_root), -#if 0 - .vfsmount_struct_mnt_parent = offsetof(struct vfsmount, mnt_parent), -#endif - .pgdir_shift = PGDIR_SHIFT, - .ptrs_per_pte = PTRS_PER_PTE, - /* .phys_offset = PHYS_OFFSET, */ - .page_offset = PAGE_OFFSET, - .page_shift = PAGE_SHIFT, - .page_size = PAGE_SIZE, - .task_struct_struct_thread_group - = offsetof(struct task_struct, thread_group), - .task_struct_struct_thread = offsetof(struct task_struct, thread), - .task_struct_struct_utime = offsetof(struct task_struct, utime), - .task_struct_struct_stime = offsetof(struct task_struct, stime), - .list_head_struct_next = offsetof(struct list_head, next), - .list_head_struct_prev = offsetof(struct list_head, prev), - - .rq_struct_curr = 0, - - .thread_info_struct_cpu = 0, - - .task_struct_struct_prio = offsetof(struct task_struct, prio), - .task_struct_struct_static_prio - = offsetof(struct task_struct, static_prio), - .task_struct_struct_normal_prio - = offsetof(struct task_struct, normal_prio), - .task_struct_struct_rt_priority - = offsetof(struct task_struct, rt_priority), - - .task_struct_struct_se = offsetof(struct task_struct, se), - - .sched_entity_struct_exec_start - = offsetof(struct sched_entity, exec_start), - .sched_entity_struct_sum_exec_runtime - = offsetof(struct sched_entity, sum_exec_runtime), - .sched_entity_struct_prev_sum_exec_runtime - = offsetof(struct sched_entity, prev_sum_exec_runtime), - -#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) - .task_struct_struct_sched_info - = offsetof(struct task_struct, sched_info), - .sched_info_struct_pcount - = offsetof(struct sched_info, pcount), - .sched_info_struct_run_delay - = offsetof(struct sched_info, run_delay), - .sched_info_struct_last_arrival - = offsetof(struct sched_info, last_arrival), - .sched_info_struct_last_queued - = offsetof(struct sched_info, last_queued), -#else - .task_struct_struct_sched_info = 0x1223, - .sched_info_struct_pcount = 0x1224, - .sched_info_struct_run_delay = 0x1225, - .sched_info_struct_last_arrival = 0x1226, - .sched_info_struct_last_queued = 0x1227, -#endif - -#ifdef CONFIG_DEBUG_MUTEXES - .task_struct_struct_blocked_on - = offsetof(struct task_struct, blocked_on), - .mutex_waiter_struct_list = offsetof(struct mutex_waiter, list), - .mutex_waiter_struct_task = offsetof(struct mutex_waiter, task), -#else - .task_struct_struct_blocked_on = 0x1228, - .mutex_waiter_struct_list = 0x1229, - .mutex_waiter_struct_task = 0x122a, -#endif - -#ifdef CONFIG_FAIR_GROUP_SCHED - .sched_entity_struct_cfs_rq_struct - = offsetof(struct sched_entity, cfs_rq), -#else - .sched_entity_struct_cfs_rq_struct = 0x1223, -#endif - - .cfs_rq_struct_rq_struct = 0, - -#ifdef CONFIG_FRAME_POINTER - .gaf_fp = 1, -#else - .gaf_fp = 0, -#endif - - .GAFINFOCheckSum = 0 -}; - -static int __init proca_init_gaf(void) -{ - unsigned short *checksum = &(GAFINFO.GAFINFOCheckSum); - unsigned char *memory = (unsigned char *)&GAFINFO; - unsigned char address; - /* - * Add GAForensic init for preventing symbol removal for optimization. - */ - GAFINFO.phys_offset = PHYS_OFFSET; - GAFINFO.rq_struct_curr = 0; - - for (*checksum = 0, address = 0; - address < (sizeof(GAFINFO) - sizeof(GAFINFO.GAFINFOCheckSum)); - address++) { - if ((*checksum) & 0x8000) - (*checksum) = - (((*checksum) << 1) | 1) ^ memory[address]; - else - (*checksum) = ((*checksum) << 1) ^ memory[address]; - } - - return 0; -} -core_initcall(proca_init_gaf); diff --git a/security/samsung/proca/gaf/gaf_v4.c b/security/samsung/proca/gaf/gaf_v4.c deleted file mode 100755 index 020fb56bb..000000000 --- a/security/samsung/proca/gaf/gaf_v4.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * gaf_v4.c - * - */ -#include "proca_gaf.h" - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/mount.h> -#include <asm/pgtable.h> -#include <linux/kernel_stat.h> -#include "../fs/mount.h" - -#ifdef CONFIG_FIVE_GKI_10 -#define OFFSETOF_INTEGRITY offsetof(struct task_struct, android_vendor_data1[2]) -#define OFFSETOF_F_SIGNATURE offsetof(struct file, android_vendor_data1) -#else -#define OFFSETOF_INTEGRITY offsetof(struct task_struct, integrity) -#define OFFSETOF_F_SIGNATURE offsetof(struct file, f_signature) -#endif - -static struct GAForensicINFO { - unsigned short ver; - unsigned int size; - unsigned short task_struct_struct_state; - unsigned short task_struct_struct_comm; - unsigned short task_struct_struct_tasks; - unsigned short task_struct_struct_pid; - unsigned short task_struct_struct_stack; - unsigned short task_struct_struct_mm; - unsigned short mm_struct_struct_start_data; - unsigned short mm_struct_struct_end_data; - unsigned short mm_struct_struct_start_brk; - unsigned short mm_struct_struct_brk; - unsigned short mm_struct_struct_start_stack; - unsigned short mm_struct_struct_arg_start; - unsigned short mm_struct_struct_arg_end; - unsigned short mm_struct_struct_pgd; - unsigned short mm_struct_struct_mmap; - unsigned short vm_area_struct_struct_vm_start; - unsigned short vm_area_struct_struct_vm_end; - unsigned short vm_area_struct_struct_vm_next; - unsigned short vm_area_struct_struct_vm_flags; - unsigned short vm_area_struct_struct_vm_file; -#ifndef CONFIG_ARM64 - unsigned short thread_info_struct_cpu_context; - unsigned short cpu_context_save_struct_sp; -#endif - unsigned short file_struct_f_path; - unsigned short path_struct_mnt; - unsigned short path_struct_dentry; - unsigned short dentry_struct_d_parent; - unsigned short dentry_struct_d_name; - unsigned short qstr_struct_name; - unsigned short vfsmount_struct_mnt_mountpoint; - unsigned short vfsmount_struct_mnt_root; - unsigned short vfsmount_struct_mnt_parent; -#ifdef CONFIG_ARM64 - unsigned long pgdir_shift; - unsigned long ptrs_per_pte; - unsigned long phys_offset; - unsigned long page_offset; - unsigned long page_shift; - unsigned long page_size; -#else - unsigned int pgdir_shift; - unsigned int ptrs_per_pte; - unsigned int phys_offset; - unsigned int page_offset; - unsigned int page_shift; - unsigned int page_size; -#endif - unsigned short task_struct_struct_thread_group; -#ifdef CONFIG_ARM64 - unsigned short task_struct_struct_thread; -#endif - unsigned short task_struct_struct_utime; - unsigned short task_struct_struct_stime; - unsigned short list_head_struct_next; - unsigned short list_head_struct_prev; - unsigned short rq_struct_curr; - unsigned short thread_info_struct_cpu; - unsigned short task_struct_struct_prio; - unsigned short task_struct_struct_static_prio; - unsigned short task_struct_struct_normal_prio; - unsigned short task_struct_struct_rt_priority; - unsigned short task_struct_struct_se; - unsigned short sched_entity_struct_exec_start; - unsigned short sched_entity_struct_sum_exec_runtime; - unsigned short sched_entity_struct_prev_sum_exec_runtime; - unsigned short task_struct_struct_sched_info; - unsigned short sched_info_struct_pcount; - unsigned short sched_info_struct_run_delay; - unsigned short sched_info_struct_last_arrival; - unsigned short sched_info_struct_last_queued; - unsigned short task_struct_struct_blocked_on; - unsigned short mutex_waiter_struct_list; - unsigned short mutex_waiter_struct_task; - unsigned short sched_entity_struct_cfs_rq_struct; - unsigned short cfs_rq_struct_rq_struct; - unsigned short gaf_fp; - unsigned short task_struct_integrity; - unsigned short file_struct_f_signature; - unsigned short mm_struct_struct_mm_rb; - unsigned short vm_area_struct_struct_vm_rb; - unsigned short qstr_struct_len; - unsigned short mount_struct_mnt_mountpoint; - unsigned short pid_struct_numbers; - unsigned short upid_struct_pid_chain; - unsigned short upid_struct_nr; - unsigned short hlist_node_struct_next; - unsigned short task_struct_pids; - unsigned short pid_struct_first; - signed short vfsmount_struct_bp_mount; - unsigned short GAFINFOCheckSum; -} GAFINFO = { - .ver = 0x0400, /* by i.vorobiov 2017 08 25 */ - .size = sizeof(GAFINFO), - .task_struct_struct_state = offsetof(struct task_struct, state), - .task_struct_struct_comm = offsetof(struct task_struct, comm), - .task_struct_struct_tasks = offsetof(struct task_struct, tasks), - .task_struct_struct_pid = offsetof(struct task_struct, pid), - .task_struct_struct_stack = offsetof(struct task_struct, stack), - .task_struct_struct_mm = offsetof(struct task_struct, mm), - .mm_struct_struct_start_data = offsetof(struct mm_struct, start_data), - .mm_struct_struct_end_data = offsetof(struct mm_struct, end_data), - .mm_struct_struct_start_brk = offsetof(struct mm_struct, start_brk), - .mm_struct_struct_brk = offsetof(struct mm_struct, brk), - .mm_struct_struct_start_stack = offsetof(struct mm_struct, start_stack), - .mm_struct_struct_arg_start = offsetof(struct mm_struct, arg_start), - .mm_struct_struct_arg_end = offsetof(struct mm_struct, arg_end), - .mm_struct_struct_pgd = offsetof(struct mm_struct, pgd), - .mm_struct_struct_mmap = offsetof(struct mm_struct, mmap), - .mm_struct_struct_mm_rb = offsetof(struct mm_struct, mm_rb), - .vm_area_struct_struct_vm_start = - offsetof(struct vm_area_struct, vm_start), - .vm_area_struct_struct_vm_end = offsetof(struct vm_area_struct, vm_end), - .vm_area_struct_struct_vm_next = - offsetof(struct vm_area_struct, vm_next), - .vm_area_struct_struct_vm_flags = - offsetof(struct vm_area_struct, vm_flags), - .vm_area_struct_struct_vm_file = - offsetof(struct vm_area_struct, vm_file), - .vm_area_struct_struct_vm_rb - = offsetof(struct vm_area_struct, vm_rb), - .pid_struct_numbers = offsetof(struct pid, numbers[0]), - .upid_struct_pid_chain = 0, - .upid_struct_nr = 0, - .hlist_node_struct_next = offsetof(struct hlist_node, next), - .task_struct_pids = 0, - .pid_struct_first - = offsetof(struct pid, tasks[0]) - + offsetof(struct hlist_head, first), -#ifndef CONFIG_ARM64 - .thread_info_struct_cpu_context = - offsetof(struct thread_info, cpu_context), - .cpu_context_save_struct_sp = offsetof(struct cpu_context_save, sp), -#endif - .file_struct_f_path = offsetof(struct file, f_path), - .path_struct_mnt = offsetof(struct path, mnt), - .path_struct_dentry = offsetof(struct path, dentry), - .dentry_struct_d_parent = offsetof(struct dentry, d_parent), - .dentry_struct_d_name = offsetof(struct dentry, d_name), - .qstr_struct_name = offsetof(struct qstr, name), - .qstr_struct_len = offsetof(struct qstr, len), - .vfsmount_struct_mnt_root = offsetof(struct vfsmount, mnt_root), - .pgdir_shift = PGDIR_SHIFT, - .ptrs_per_pte = PTRS_PER_PTE, -//TEMP .phys_offset = PHYS_OFFSET, - .page_offset = PAGE_OFFSET, - .page_shift = PAGE_SHIFT, - .page_size = PAGE_SIZE, - .task_struct_struct_thread_group = - offsetof(struct task_struct, thread_group), -#ifdef CONFIG_ARM64 - .task_struct_struct_thread = offsetof(struct task_struct, thread), -#endif - .task_struct_struct_utime = offsetof(struct task_struct, utime), - .task_struct_struct_stime = offsetof(struct task_struct, stime), - .list_head_struct_next = offsetof(struct list_head, next), - .list_head_struct_prev = offsetof(struct list_head, prev), - .rq_struct_curr = 0, - .thread_info_struct_cpu = 0, - .task_struct_struct_prio = offsetof(struct task_struct, prio), - .task_struct_struct_static_prio = - offsetof(struct task_struct, static_prio), - .task_struct_struct_normal_prio = - offsetof(struct task_struct, normal_prio), - .task_struct_struct_rt_priority = - offsetof(struct task_struct, rt_priority), - .task_struct_struct_se = offsetof(struct task_struct, se), - .sched_entity_struct_exec_start = - offsetof(struct sched_entity, exec_start), - .sched_entity_struct_sum_exec_runtime = - offsetof(struct sched_entity, sum_exec_runtime), - .sched_entity_struct_prev_sum_exec_runtime = - offsetof(struct sched_entity, prev_sum_exec_runtime), -#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) - .task_struct_struct_sched_info = - offsetof(struct task_struct, sched_info), - .sched_info_struct_pcount = offsetof(struct sched_info, pcount), - .sched_info_struct_run_delay = offsetof(struct sched_info, run_delay), - .sched_info_struct_last_arrival = - offsetof(struct sched_info, last_arrival), - .sched_info_struct_last_queued = - offsetof(struct sched_info, last_queued), -#else - .task_struct_struct_sched_info = 0x1223, - .sched_info_struct_pcount = 0x1224, - .sched_info_struct_run_delay = 0x1225, - .sched_info_struct_last_arrival = 0x1226, - .sched_info_struct_last_queued = 0x1227, -#endif -#ifdef CONFIG_DEBUG_MUTEXES - .task_struct_struct_blocked_on = - offsetof(struct task_struct, blocked_on), - .mutex_waiter_struct_list = offsetof(struct mutex_waiter, list), - .mutex_waiter_struct_task = offsetof(struct mutex_waiter, task), -#else - .task_struct_struct_blocked_on = 0x1228, - .mutex_waiter_struct_list = 0x1229, - .mutex_waiter_struct_task = 0x122a, -#endif -#ifdef CONFIG_FAIR_GROUP_SCHED - .sched_entity_struct_cfs_rq_struct = - offsetof(struct sched_entity, cfs_rq), -#else - .sched_entity_struct_cfs_rq_struct = 0x1223, -#endif - .cfs_rq_struct_rq_struct = 0, -#ifdef CONFIG_FRAME_POINTER - .gaf_fp = 1, -#else - .gaf_fp = 0, -#endif -#ifdef CONFIG_FIVE - .task_struct_integrity = OFFSETOF_INTEGRITY, -#if defined(CONFIG_FIVE_PA_FEATURE) || defined(CONFIG_PROCA) - .file_struct_f_signature = OFFSETOF_F_SIGNATURE, -#endif -#endif - .mount_struct_mnt_mountpoint = offsetof(struct mount, mnt_mountpoint), -#if defined(CONFIG_KDP_NS) || defined(CONFIG_RUSTUH_KDP_NS) -#if defined(CONFIG_SOC_EXYNOS2100) || defined(CONFIG_ARCH_LAHAINA) - .vfsmount_struct_bp_mount = offsetof(struct kdp_vfsmount, bp_mount), -#else - .vfsmount_struct_bp_mount = offsetof(struct vfsmount, bp_mount), -#endif -#else - .vfsmount_struct_bp_mount = - (short)(offsetof(struct mount, mnt_mountpoint) - - offsetof(struct mount, mnt)), -#endif - .GAFINFOCheckSum = 0 -}; - -static int __init proca_init_gaf(void) -{ - const unsigned short size = - offsetof(struct GAForensicINFO, GAFINFOCheckSum); - unsigned char *memory = (unsigned char *)&GAFINFO; - unsigned short i = 0; - unsigned short checksum = 0; - /* - * Add GAForensic init for preventing symbol removal for optimization. - */ - GAFINFO.rq_struct_curr = 0; - - for (i = 0; i < size; i++) { - if (checksum & 0x8000) - checksum = ((checksum << 1) | 1) ^ memory[i]; - else - checksum = (checksum << 1) ^ memory[i]; - } - GAFINFO.GAFINFOCheckSum = checksum; - - return 0; -} -core_initcall(proca_init_gaf) diff --git a/security/samsung/proca/gaf/gaf_v5.c b/security/samsung/proca/gaf/gaf_v5.c deleted file mode 100755 index 92eb20936..000000000 --- a/security/samsung/proca/gaf/gaf_v5.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * gaf_v5.c - * - */ -#include "proca_gaf.h" - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/mount.h> -#include <asm/pgtable.h> -#include <linux/kernel_stat.h> -#include "../fs/mount.h" - -#include "proca_certificate.h" -#include "proca_identity.h" -#include "proca_task_descr.h" -#include "proca_table.h" - -static struct GAForensicINFO { - unsigned short ver; - unsigned int size; - unsigned short task_struct_struct_state; - unsigned short task_struct_struct_comm; - unsigned short task_struct_struct_tasks; - unsigned short task_struct_struct_pid; - unsigned short task_struct_struct_stack; - unsigned short task_struct_struct_mm; - unsigned short mm_struct_struct_start_data; - unsigned short mm_struct_struct_end_data; - unsigned short mm_struct_struct_start_brk; - unsigned short mm_struct_struct_brk; - unsigned short mm_struct_struct_start_stack; - unsigned short mm_struct_struct_arg_start; - unsigned short mm_struct_struct_arg_end; - unsigned short mm_struct_struct_pgd; - unsigned short mm_struct_struct_mmap; - unsigned short vm_area_struct_struct_vm_start; - unsigned short vm_area_struct_struct_vm_end; - unsigned short vm_area_struct_struct_vm_next; - unsigned short vm_area_struct_struct_vm_flags; - unsigned short vm_area_struct_struct_vm_file; -#ifndef CONFIG_ARM64 - unsigned short thread_info_struct_cpu_context; - unsigned short cpu_context_save_struct_sp; -#endif - unsigned short file_struct_f_path; - unsigned short path_struct_mnt; - unsigned short path_struct_dentry; - unsigned short dentry_struct_d_parent; - unsigned short dentry_struct_d_name; - unsigned short qstr_struct_name; - unsigned short vfsmount_struct_mnt_mountpoint; - unsigned short vfsmount_struct_mnt_root; - unsigned short vfsmount_struct_mnt_parent; -#ifdef CONFIG_ARM64 - unsigned long pgdir_shift; - unsigned long ptrs_per_pte; - unsigned long phys_offset; - unsigned long page_offset; - unsigned long page_shift; - unsigned long page_size; -#else - unsigned int pgdir_shift; - unsigned int ptrs_per_pte; - unsigned int phys_offset; - unsigned int page_offset; - unsigned int page_shift; - unsigned int page_size; -#endif - unsigned short task_struct_struct_thread_group; -#ifdef CONFIG_ARM64 - unsigned short task_struct_struct_thread; -#endif - unsigned short task_struct_struct_utime; - unsigned short task_struct_struct_stime; - unsigned short list_head_struct_next; - unsigned short list_head_struct_prev; - unsigned short rq_struct_curr; - unsigned short thread_info_struct_cpu; - unsigned short task_struct_struct_prio; - unsigned short task_struct_struct_static_prio; - unsigned short task_struct_struct_normal_prio; - unsigned short task_struct_struct_rt_priority; - unsigned short task_struct_struct_se; - unsigned short sched_entity_struct_exec_start; - unsigned short sched_entity_struct_sum_exec_runtime; - unsigned short sched_entity_struct_prev_sum_exec_runtime; - unsigned short task_struct_struct_sched_info; - unsigned short sched_info_struct_pcount; - unsigned short sched_info_struct_run_delay; - unsigned short sched_info_struct_last_arrival; - unsigned short sched_info_struct_last_queued; - unsigned short task_struct_struct_blocked_on; - unsigned short mutex_waiter_struct_list; - unsigned short mutex_waiter_struct_task; - unsigned short sched_entity_struct_cfs_rq_struct; - unsigned short cfs_rq_struct_rq_struct; - unsigned short gaf_fp; - unsigned short task_struct_integrity; - unsigned short proca_task_descr_task; - unsigned short proca_task_descr_proca_identity; - unsigned short proca_task_descr_pid_map_node; - unsigned short proca_task_descr_app_name_map_node; - unsigned short proca_identity_struct_certificate; - unsigned short proca_identity_struct_certificate_size; - unsigned short proca_identity_struct_parsed_cert; - unsigned short proca_identity_struct_file; - unsigned short file_struct_f_signature; - unsigned short proca_table_hash_tables_shift; - unsigned short proca_table_pid_map; - unsigned short proca_table_app_name_map; - unsigned short proca_certificate_struct_app_name; - unsigned short proca_certificate_struct_app_name_size; - unsigned short mm_struct_struct_mm_rb; - unsigned short vm_area_struct_struct_vm_rb; - unsigned short qstr_struct_len; - unsigned short mount_struct_mnt_mountpoint; - unsigned short pid_struct_numbers; - unsigned short upid_struct_pid_chain; - unsigned short upid_struct_nr; - unsigned short hlist_node_struct_next; - unsigned short task_struct_pids; - unsigned short pid_struct_first; - signed short vfsmount_struct_bp_mount; - unsigned short GAFINFOCheckSum; -} GAFINFO = { - .ver = 0x0500, /* by hryhorii tur 2018 09 14 */ - .size = sizeof(GAFINFO), - .task_struct_struct_state = offsetof(struct task_struct, state), - .task_struct_struct_comm = offsetof(struct task_struct, comm), - .task_struct_struct_tasks = offsetof(struct task_struct, tasks), - .task_struct_struct_pid = offsetof(struct task_struct, pid), - .task_struct_struct_stack = offsetof(struct task_struct, stack), - .task_struct_struct_mm = offsetof(struct task_struct, mm), - .mm_struct_struct_start_data = offsetof(struct mm_struct, start_data), - .mm_struct_struct_end_data = offsetof(struct mm_struct, end_data), - .mm_struct_struct_start_brk = offsetof(struct mm_struct, start_brk), - .mm_struct_struct_brk = offsetof(struct mm_struct, brk), - .mm_struct_struct_start_stack = offsetof(struct mm_struct, start_stack), - .mm_struct_struct_arg_start = offsetof(struct mm_struct, arg_start), - .mm_struct_struct_arg_end = offsetof(struct mm_struct, arg_end), - .mm_struct_struct_pgd = offsetof(struct mm_struct, pgd), - .mm_struct_struct_mmap = offsetof(struct mm_struct, mmap), - .mm_struct_struct_mm_rb = offsetof(struct mm_struct, mm_rb), - .vm_area_struct_struct_vm_start = - offsetof(struct vm_area_struct, vm_start), - .vm_area_struct_struct_vm_end = offsetof(struct vm_area_struct, vm_end), - .vm_area_struct_struct_vm_next = - offsetof(struct vm_area_struct, vm_next), - .vm_area_struct_struct_vm_flags = - offsetof(struct vm_area_struct, vm_flags), - .vm_area_struct_struct_vm_file = - offsetof(struct vm_area_struct, vm_file), - .vm_area_struct_struct_vm_rb - = offsetof(struct vm_area_struct, vm_rb), - .pid_struct_numbers = offsetof(struct pid, numbers[0]), - .upid_struct_pid_chain = 0, - .upid_struct_nr = 0, - .hlist_node_struct_next = offsetof(struct hlist_node, next), - .task_struct_pids = 0, - .pid_struct_first - = offsetof(struct pid, tasks[0]) - + offsetof(struct hlist_head, first), -#ifndef CONFIG_ARM64 - .thread_info_struct_cpu_context = - offsetof(struct thread_info, cpu_context), - .cpu_context_save_struct_sp = offsetof(struct cpu_context_save, sp), -#endif - .file_struct_f_path = offsetof(struct file, f_path), - .path_struct_mnt = offsetof(struct path, mnt), - .path_struct_dentry = offsetof(struct path, dentry), - .dentry_struct_d_parent = offsetof(struct dentry, d_parent), - .dentry_struct_d_name = offsetof(struct dentry, d_name), - .qstr_struct_name = offsetof(struct qstr, name), - .qstr_struct_len = offsetof(struct qstr, len), - .vfsmount_struct_mnt_root = offsetof(struct vfsmount, mnt_root), - .pgdir_shift = PGDIR_SHIFT, - .ptrs_per_pte = PTRS_PER_PTE, -//TEMP .phys_offset = PHYS_OFFSET, - .page_offset = PAGE_OFFSET, - .page_shift = PAGE_SHIFT, - .page_size = PAGE_SIZE, - .task_struct_struct_thread_group = - offsetof(struct task_struct, thread_group), -#ifdef CONFIG_ARM64 - .task_struct_struct_thread = offsetof(struct task_struct, thread), -#endif - .task_struct_struct_utime = offsetof(struct task_struct, utime), - .task_struct_struct_stime = offsetof(struct task_struct, stime), - .list_head_struct_next = offsetof(struct list_head, next), - .list_head_struct_prev = offsetof(struct list_head, prev), - .rq_struct_curr = 0, - .thread_info_struct_cpu = 0, - .task_struct_struct_prio = offsetof(struct task_struct, prio), - .task_struct_struct_static_prio = - offsetof(struct task_struct, static_prio), - .task_struct_struct_normal_prio = - offsetof(struct task_struct, normal_prio), - .task_struct_struct_rt_priority = - offsetof(struct task_struct, rt_priority), - .task_struct_struct_se = offsetof(struct task_struct, se), - .sched_entity_struct_exec_start = - offsetof(struct sched_entity, exec_start), - .sched_entity_struct_sum_exec_runtime = - offsetof(struct sched_entity, sum_exec_runtime), - .sched_entity_struct_prev_sum_exec_runtime = - offsetof(struct sched_entity, prev_sum_exec_runtime), -#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) - .task_struct_struct_sched_info = - offsetof(struct task_struct, sched_info), - .sched_info_struct_pcount = offsetof(struct sched_info, pcount), - .sched_info_struct_run_delay = offsetof(struct sched_info, run_delay), - .sched_info_struct_last_arrival = - offsetof(struct sched_info, last_arrival), - .sched_info_struct_last_queued = - offsetof(struct sched_info, last_queued), -#else - .task_struct_struct_sched_info = 0x1223, - .sched_info_struct_pcount = 0x1224, - .sched_info_struct_run_delay = 0x1225, - .sched_info_struct_last_arrival = 0x1226, - .sched_info_struct_last_queued = 0x1227, -#endif -#ifdef CONFIG_DEBUG_MUTEXES - .task_struct_struct_blocked_on = - offsetof(struct task_struct, blocked_on), - .mutex_waiter_struct_list = offsetof(struct mutex_waiter, list), - .mutex_waiter_struct_task = offsetof(struct mutex_waiter, task), -#else - .task_struct_struct_blocked_on = 0x1228, - .mutex_waiter_struct_list = 0x1229, - .mutex_waiter_struct_task = 0x122a, -#endif -#ifdef CONFIG_FAIR_GROUP_SCHED - .sched_entity_struct_cfs_rq_struct = - offsetof(struct sched_entity, cfs_rq), -#else - .sched_entity_struct_cfs_rq_struct = 0x1223, -#endif - .cfs_rq_struct_rq_struct = 0, -#ifdef CONFIG_FRAME_POINTER - .gaf_fp = 1, -#else - .gaf_fp = 0, -#endif -#ifdef CONFIG_FIVE - .task_struct_integrity = offsetof(struct task_struct, integrity), -#else - .task_struct_integrity = 0xECEF, -#endif -#if defined(CONFIG_FIVE_PA_FEATURE) || defined(CONFIG_PROCA) - .file_struct_f_signature = offsetof(struct file, f_signature), -#endif -#ifdef CONFIG_PROCA - .proca_task_descr_task = - offsetof(struct proca_task_descr, task), - .proca_task_descr_proca_identity = - offsetof(struct proca_task_descr, proca_identity), - .proca_task_descr_pid_map_node = - offsetof(struct proca_task_descr, pid_map_node), - .proca_task_descr_app_name_map_node = - offsetof(struct proca_task_descr, app_name_map_node), - .proca_identity_struct_certificate = - offsetof(struct proca_identity, certificate), - .proca_identity_struct_certificate_size = - offsetof(struct proca_identity, certificate_size), - .proca_identity_struct_parsed_cert = - offsetof(struct proca_identity, parsed_cert), - .proca_table_hash_tables_shift = - offsetof(struct proca_table, hash_tables_shift), - .proca_table_pid_map = - offsetof(struct proca_table, pid_map), - .proca_table_app_name_map = - offsetof(struct proca_table, app_name_map), - .proca_identity_struct_file = - offsetof(struct proca_identity, file), - .proca_certificate_struct_app_name = - offsetof(struct proca_certificate, app_name), - .proca_certificate_struct_app_name_size = - offsetof(struct proca_certificate, app_name_size), -#endif - .mount_struct_mnt_mountpoint = offsetof(struct mount, mnt_mountpoint), -#if defined(CONFIG_KDP_NS) || defined(CONFIG_RUSTUH_KDP_NS) -#if defined(CONFIG_SOC_EXYNOS2100) || defined(CONFIG_ARCH_LAHAINA) - .vfsmount_struct_bp_mount = offsetof(struct kdp_vfsmount, bp_mount), -#else - .vfsmount_struct_bp_mount = offsetof(struct vfsmount, bp_mount), -#endif -#else - .vfsmount_struct_bp_mount = - (short)(offsetof(struct mount, mnt_mountpoint) - - offsetof(struct mount, mnt)), -#endif - .GAFINFOCheckSum = 0 -}; - -const void *proca_gaf_get_addr(void) -{ - return &GAFINFO; -} - -static int __init proca_init_gaf(void) -{ - const unsigned short size = - offsetof(struct GAForensicINFO, GAFINFOCheckSum); - unsigned char *memory = (unsigned char *)&GAFINFO; - unsigned short i = 0; - unsigned short checksum = 0; - /* - * Add GAForensic init for preventing symbol removal for optimization. - */ - GAFINFO.rq_struct_curr = 0; - - for (i = 0; i < size; i++) { - if (checksum & 0x8000) - checksum = ((checksum << 1) | 1) ^ memory[i]; - else - checksum = (checksum << 1) ^ memory[i]; - } - GAFINFO.GAFINFOCheckSum = checksum; - - return 0; -} -core_initcall(proca_init_gaf) diff --git a/security/samsung/proca/gaf/gaf_v6.c b/security/samsung/proca/gaf/gaf_v6.c deleted file mode 100755 index e93137ba9..000000000 --- a/security/samsung/proca/gaf/gaf_v6.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * gaf_v6.c - * - */ -#include "proca_gaf.h" - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/mount.h> -#include <linux/version.h> -#include <asm/pgtable.h> -#include <linux/kernel_stat.h> -#include "../fs/mount.h" - -#include "proca_certificate.h" -#include "proca_identity.h" -#include "proca_task_descr.h" -#include "proca_table.h" - -#ifdef CONFIG_PROCA_GKI_10 -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) -#define OFFSETOF_INTEGRITY offsetof(struct task_struct, android_oem_data1[2]) -#define OFFSETOF_F_SIGNATURE 0 -#else -#define OFFSETOF_INTEGRITY offsetof(struct task_struct, android_vendor_data1[2]) -#define OFFSETOF_F_SIGNATURE offsetof(struct file, android_vendor_data1) -#endif -#else -#define OFFSETOF_INTEGRITY offsetof(struct task_struct, integrity) -#define OFFSETOF_F_SIGNATURE offsetof(struct file, f_signature) -#endif - -static struct GAForensicINFO { - unsigned short ver; - unsigned int size; - unsigned short task_struct_struct_state; - unsigned short task_struct_struct_comm; - unsigned short task_struct_struct_tasks; - unsigned short task_struct_struct_pid; - unsigned short task_struct_struct_mm; - unsigned short mm_struct_struct_pgd; - unsigned short mm_struct_struct_mmap; - unsigned short mm_struct_struct_mm_rb; - unsigned short vm_area_struct_struct_vm_start; - unsigned short vm_area_struct_struct_vm_end; - unsigned short vm_area_struct_struct_vm_next; - unsigned short vm_area_struct_struct_vm_flags; - unsigned short vm_area_struct_struct_vm_file; - unsigned short vm_area_struct_struct_vm_rb; - unsigned short file_struct_f_path; - unsigned short path_struct_mnt; - unsigned short path_struct_dentry; - unsigned short dentry_struct_d_parent; - unsigned short dentry_struct_d_name; - unsigned short qstr_struct_name; - unsigned short qstr_struct_len; - unsigned short struct_mount_mnt_mountpoint; - unsigned short struct_mount_mnt; - unsigned short struct_mount_mnt_parent; - unsigned short list_head_struct_next; - unsigned short list_head_struct_prev; - unsigned short is_kdp_ns_on; - unsigned short task_struct_integrity; - unsigned short proca_task_descr_task; - unsigned short proca_task_descr_proca_identity; - unsigned short proca_task_descr_pid_map_node; - unsigned short proca_task_descr_app_name_map_node; - unsigned short proca_identity_struct_certificate; - unsigned short proca_identity_struct_certificate_size; - unsigned short proca_identity_struct_parsed_cert; - unsigned short proca_identity_struct_file; - unsigned short file_struct_f_signature; - unsigned short proca_table_hash_tables_shift; - unsigned short proca_table_pid_map; - unsigned short proca_table_app_name_map; - unsigned short proca_certificate_struct_app_name; - unsigned short proca_certificate_struct_app_name_size; - unsigned short hlist_node_struct_next; - unsigned short struct_vfsmount_bp_mount; - char reserved[1022]; - unsigned short GAFINFOCheckSum; -} GAFINFO = { - .ver = 0x0600, /* by hryhorii tur 2019 10 21 */ - .size = sizeof(GAFINFO), -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)) - .task_struct_struct_state = offsetof(struct task_struct, __state), -#else - .task_struct_struct_state = offsetof(struct task_struct, state), -#endif - .task_struct_struct_comm = offsetof(struct task_struct, comm), - .task_struct_struct_tasks = offsetof(struct task_struct, tasks), - .task_struct_struct_pid = offsetof(struct task_struct, pid), - .task_struct_struct_mm = offsetof(struct task_struct, mm), - .mm_struct_struct_pgd = offsetof(struct mm_struct, pgd), -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) - .mm_struct_struct_mmap = offsetof(struct mm_struct, mm_mt), - .mm_struct_struct_mm_rb = offsetof(struct mm_struct, mm_mt), - .vm_area_struct_struct_vm_next = - offsetof(struct vm_area_struct, vm_start), - .vm_area_struct_struct_vm_rb - = offsetof(struct vm_area_struct, vm_mm), -#else - .mm_struct_struct_mmap = offsetof(struct mm_struct, mmap), - .mm_struct_struct_mm_rb = offsetof(struct mm_struct, mm_rb), - .vm_area_struct_struct_vm_next = - offsetof(struct vm_area_struct, vm_next), - .vm_area_struct_struct_vm_rb - = offsetof(struct vm_area_struct, vm_rb), -#endif - .vm_area_struct_struct_vm_start = - offsetof(struct vm_area_struct, vm_start), - .vm_area_struct_struct_vm_end = offsetof(struct vm_area_struct, vm_end), - .vm_area_struct_struct_vm_flags = - offsetof(struct vm_area_struct, vm_flags), - .vm_area_struct_struct_vm_file = - offsetof(struct vm_area_struct, vm_file), - .hlist_node_struct_next = offsetof(struct hlist_node, next), - .file_struct_f_path = offsetof(struct file, f_path), - .path_struct_mnt = offsetof(struct path, mnt), - .path_struct_dentry = offsetof(struct path, dentry), - .dentry_struct_d_parent = offsetof(struct dentry, d_parent), - .dentry_struct_d_name = offsetof(struct dentry, d_name), - .qstr_struct_name = offsetof(struct qstr, name), - .qstr_struct_len = offsetof(struct qstr, len), - .struct_mount_mnt_mountpoint = offsetof(struct mount, mnt_mountpoint), - .struct_mount_mnt = offsetof(struct mount, mnt), - .struct_mount_mnt_parent = offsetof(struct mount, mnt_parent), - .list_head_struct_next = offsetof(struct list_head, next), - .list_head_struct_prev = offsetof(struct list_head, prev), -#if defined(CONFIG_KDP_NS) || defined(CONFIG_RKP_NS_PROT) || defined(CONFIG_RUSTUH_KDP_NS) - .is_kdp_ns_on = true, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) - .struct_vfsmount_bp_mount = offsetof(struct kdp_vfsmount, bp_mount), -#else - .struct_vfsmount_bp_mount = offsetof(struct vfsmount, bp_mount), -#endif -#else - .is_kdp_ns_on = false, -#endif - -#ifdef CONFIG_FIVE - .task_struct_integrity = OFFSETOF_INTEGRITY, -#else - .task_struct_integrity = 0xECEF, -#endif -#if defined(CONFIG_FIVE_PA_FEATURE) || defined(CONFIG_PROCA) - .file_struct_f_signature = OFFSETOF_F_SIGNATURE, -#endif -#ifdef CONFIG_PROCA - .proca_task_descr_task = - offsetof(struct proca_task_descr, task), - .proca_task_descr_proca_identity = - offsetof(struct proca_task_descr, proca_identity), - .proca_task_descr_pid_map_node = - offsetof(struct proca_task_descr, pid_map_node), - .proca_task_descr_app_name_map_node = - offsetof(struct proca_task_descr, app_name_map_node), - .proca_identity_struct_certificate = - offsetof(struct proca_identity, certificate), - .proca_identity_struct_certificate_size = - offsetof(struct proca_identity, certificate_size), - .proca_identity_struct_parsed_cert = - offsetof(struct proca_identity, parsed_cert), - .proca_table_hash_tables_shift = - offsetof(struct proca_table, hash_tables_shift), - .proca_table_pid_map = - offsetof(struct proca_table, pid_map), - .proca_table_app_name_map = - offsetof(struct proca_table, app_name_map), - .proca_identity_struct_file = - offsetof(struct proca_identity, file), - .proca_certificate_struct_app_name = - offsetof(struct proca_certificate, app_name), - .proca_certificate_struct_app_name_size = - offsetof(struct proca_certificate, app_name_size), -#endif - .GAFINFOCheckSum = 0 -}; - -const void *proca_gaf_get_addr(void) -{ - return &GAFINFO; -} - -static int __init proca_init_gaf(void) -{ - const unsigned short size = - offsetof(struct GAForensicINFO, GAFINFOCheckSum); - unsigned char *memory = (unsigned char *)&GAFINFO; - unsigned short i = 0; - unsigned short checksum = 0; - - for (i = 0; i < size; i++) { - if (checksum & 0x8000) - checksum = ((checksum << 1) | 1) ^ memory[i]; - else - checksum = (checksum << 1) ^ memory[i]; - } - GAFINFO.GAFINFOCheckSum = checksum; - - return 0; -} -core_initcall(proca_init_gaf) diff --git a/security/samsung/proca/gaf/proca_gaf.h b/security/samsung/proca/gaf/proca_gaf.h deleted file mode 100755 index 58c76b76e..000000000 --- a/security/samsung/proca/gaf/proca_gaf.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * PROCA GAF - * - * Copyright (C) 2019 Samsung Electronics, Inc. - * Ivan Vorobiov <i.vorobiov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef _SECURITY_PROCA_GAF_H -#define _SECURITY_PROCA_GAF_H -const void *proca_gaf_get_addr(void); -#endif /* _SECURITY_PROCA_GAF_H */ diff --git a/security/samsung/proca/proca_certificate.asn1 b/security/samsung/proca/proca_certificate.asn1 deleted file mode 100755 index 78be3c180..000000000 --- a/security/samsung/proca/proca_certificate.asn1 +++ /dev/null @@ -1,13 +0,0 @@ -PaCertificate ::= SEQUENCE { - paData PaData, - signature OCTET STRING -} - -PaData ::= SEQUENCE { - paVersion INTEGER, - paFlags INTEGER ({ proca_certificate_get_flags }), - paKeyId INTEGER, - paId OCTET STRING, - paAppName OCTET STRING ({ proca_certificate_get_app_name }), - fiveSignatureHash OCTET STRING ({ proca_certificate_get_five_signature_hash }) -} diff --git a/security/samsung/proca/proca_certificate.c b/security/samsung/proca/proca_certificate.c deleted file mode 100755 index 02aef015f..000000000 --- a/security/samsung/proca/proca_certificate.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Utility functions to work with PROCA certificate - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/err.h> -#include <crypto/hash.h> -#include <crypto/hash_info.h> -#include <linux/version.h> -#include <linux/file.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) -#include <crypto/sha1.h> -#include <crypto/sha2.h> -#else -#include <crypto/sha.h> -#endif - -#include "proca_log.h" -#include "proca_certificate.h" -#include "five_crypto.h" -#include "five_testing.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 42) -#include "proca_certificate.asn1.h" -#else -#include "proca_certificate-asn1.h" -#endif - -static struct crypto_shash *g_validation_shash; - -int proca_certificate_get_flags(void *context, size_t hdrlen, - unsigned char tag, - const void *value, size_t vlen) -{ - struct proca_certificate *parsed_cert = context; - - if (!value || !vlen) - return -EINVAL; - - parsed_cert->flags = *(const uint8_t *)value; - - return 0; -} - -int proca_certificate_get_app_name(void *context, size_t hdrlen, - unsigned char tag, - const void *value, size_t vlen) -{ - struct proca_certificate *parsed_cert = context; - - if (!value || !vlen) - return -EINVAL; - - parsed_cert->app_name = kmalloc(vlen + 1, GFP_KERNEL); - if (!parsed_cert->app_name) - return -ENOMEM; - - memcpy(parsed_cert->app_name, value, vlen); - parsed_cert->app_name[vlen] = '\0'; - parsed_cert->app_name_size = vlen; - - return 0; -} - -int proca_certificate_get_five_signature_hash(void *context, size_t hdrlen, - unsigned char tag, - const void *value, size_t vlen) -{ - struct proca_certificate *parsed_cert = context; - - if (!value || !vlen) - return -EINVAL; - - parsed_cert->five_signature_hash = kmalloc(vlen, GFP_KERNEL); - if (!parsed_cert->five_signature_hash) - return -ENOMEM; - - memcpy(parsed_cert->five_signature_hash, value, vlen); - parsed_cert->five_signature_hash_size = vlen; - - return 0; -} - -int parse_proca_certificate(const char *certificate_buff, - const size_t buff_size, - struct proca_certificate *parsed_cert) -{ - int rc = 0; - - memset(parsed_cert, 0, sizeof(*parsed_cert)); - - rc = asn1_ber_decoder(&proca_certificate_decoder, parsed_cert, - certificate_buff, - buff_size); - if (!parsed_cert->app_name || !parsed_cert->five_signature_hash) { - PROCA_INFO_LOG("Failed to parse proca certificate.\n"); - deinit_proca_certificate(parsed_cert); - return -EINVAL; - } - - return rc; -} - -void deinit_proca_certificate(struct proca_certificate *certificate) -{ - kfree(certificate->app_name); - kfree(certificate->five_signature_hash); -} - -int init_certificate_validation_hash(void) -{ - g_validation_shash = crypto_alloc_shash("sha256", 0, 0); - if (IS_ERR(g_validation_shash)) { - PROCA_WARN_LOG("can't alloc sha256 alg, rc - %ld.\n", - PTR_ERR(g_validation_shash)); - return PTR_ERR(g_validation_shash); - } - return 0; -} - -int compare_with_five_signature(const struct proca_certificate *certificate, - const void *five_signature, - const size_t five_signature_size) -{ - SHASH_DESC_ON_STACK(sdesc, g_validation_shash); - char five_sign_hash[SHA256_DIGEST_SIZE]; - int rc = 0; - - if (sizeof(five_sign_hash) != certificate->five_signature_hash_size) { - PROCA_DEBUG_LOG( - "Size of five sign hash is invalid %zu, expected %zu", - certificate->five_signature_hash_size, - sizeof(five_sign_hash)); - return rc; - } - - sdesc->tfm = g_validation_shash; -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) -/* - * flags was deleted from struct shash_desc in Android Kernel v5.2.0 - */ - sdesc->flags = 0; -#endif - - rc = crypto_shash_init(sdesc); - if (rc != 0) { - PROCA_WARN_LOG("crypto_shash_init failed, rc - %d.\n", rc); - return 0; - } - - rc = crypto_shash_digest(sdesc, five_signature, - five_signature_size, five_sign_hash); - if (rc != 0) { - PROCA_WARN_LOG("crypto_shash_digest failed, rc - %d.\n", rc); - return 0; - } - - return !memcmp(five_sign_hash, - certificate->five_signature_hash, - certificate->five_signature_hash_size); -} - -int proca_certificate_copy(struct proca_certificate *dst, - const struct proca_certificate *src) -{ - BUG_ON(!dst || !src); - - memset(dst, 0, sizeof(*dst)); - - if (src->app_name) { - /* - * app_name is NULL-terminated string with len == app_name_size, - * so we should duplicate app_name_size + 1 bytes - */ - dst->app_name = kmemdup(src->app_name, src->app_name_size + 1, - GFP_KERNEL); - dst->app_name_size = src->app_name_size; - - if (unlikely(!dst->app_name)) - return -ENOMEM; - } - - if (src->five_signature_hash) { - dst->five_signature_hash = kmemdup( - src->five_signature_hash, - src->five_signature_hash_size, - GFP_KERNEL); - dst->five_signature_hash_size = src->five_signature_hash_size; - - if (unlikely(!dst->five_signature_hash)) { - kfree(dst->app_name); - return -ENOMEM; - } - } - - return 0; -} - -/* Copied from TA sources */ -enum PaFlagBits { - PaFlagBits_bitAndroid = 0, - PaFlagBits_bitThirdParty = 1, - PaFlagBits_bitHmac = 2 -}; - -__visible_for_testing __mockable -bool check_native_pa_id(const struct proca_certificate *parsed_cert, - struct task_struct *task) -{ - struct file *exe; - char *path_buff; - char *path; - bool res = false; - - path_buff = kmalloc(parsed_cert->app_name_size + 1, GFP_KERNEL); - if (!path_buff) - return false; - - exe = get_task_exe_file(task); - if (!exe) - goto path_buff_cleanup; - - path = d_path(&exe->f_path, path_buff, parsed_cert->app_name_size + 1); - if (IS_ERR(path)) - goto exe_file_cleanup; - - res = !strcmp(path, parsed_cert->app_name); - if (!res) - PROCA_WARN_LOG( - "file path %s and cert app name %s doesn't match\n", - path, parsed_cert->app_name); - -exe_file_cleanup: - fput(exe); - -path_buff_cleanup: - kfree(path_buff); - - return res; -} - -bool is_certificate_relevant_to_task( - const struct proca_certificate *parsed_cert, - struct task_struct *task) -{ - const char system_server_app_name[] = "/system/framework/services.jar"; - const char system_server[] = "system_server"; - const size_t max_app_name = 1024; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) || defined(PROCA_KUNIT_ENABLED)) - char cmdline[1024 + 1]; -#else - char cmdline[max_app_name + 1]; -#endif - int cmdline_size; - - if (!(parsed_cert->flags & (1 << PaFlagBits_bitAndroid))) - if (!check_native_pa_id(parsed_cert, task)) - return false; - - cmdline_size = get_cmdline(task, cmdline, max_app_name); - cmdline[cmdline_size] = 0; - - // Special case for system_server - if (!strncmp(parsed_cert->app_name, system_server_app_name, - parsed_cert->app_name_size)) { - if (strncmp(cmdline, system_server, sizeof(system_server))) - return false; - } else if (parsed_cert->app_name[0] != '/') { - // Case for Android applications - PROCA_DEBUG_LOG("Task %d has cmdline : %s\n", - task->pid, cmdline); - if (strncmp(cmdline, parsed_cert->app_name, - parsed_cert->app_name_size)) - return false; - } - - return true; -} - -#define PROCA_MAX_DIGEST_SIZE 64 - -bool is_certificate_relevant_to_file( - const struct proca_certificate *parsed_cert, - struct file *file) -{ - int result = 0; - u8 stored_file_hash[PROCA_MAX_DIGEST_SIZE] = {0}; - size_t hash_len = sizeof(stored_file_hash); - - BUG_ON(!file || !parsed_cert); - - result = five_calc_file_hash(file, HASH_ALGO_SHA1, stored_file_hash, &hash_len); - if (result) { - PROCA_WARN_LOG("File hash calculation is failed"); - return false; - } - - return compare_with_five_signature(parsed_cert, stored_file_hash, hash_len); -} diff --git a/security/samsung/proca/proca_certificate.h b/security/samsung/proca/proca_certificate.h deleted file mode 100755 index 1f83ecdec..000000000 --- a/security/samsung/proca/proca_certificate.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * PROCA certificate - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _LINUX_PROCA_CERTIFICATE_H -#define _LINUX_PROCA_CERTIFICATE_H - -#include <linux/types.h> - -#include "proca_porting.h" - -struct proca_certificate { - char *app_name; - size_t app_name_size; - - char *five_signature_hash; - size_t five_signature_hash_size; - - uint32_t flags; -}; - -int parse_proca_certificate(const char *certificate_buff, - const size_t buff_size, - struct proca_certificate *parsed_cert); - -void deinit_proca_certificate(struct proca_certificate *certificate); - -int compare_with_five_signature(const struct proca_certificate *certificate, - const void *five_signature, - const size_t five_signature_size); - -int init_certificate_validation_hash(void); - -int proca_certificate_copy(struct proca_certificate *dst, - const struct proca_certificate *src); - -bool is_certificate_relevant_to_task( - const struct proca_certificate *parsed_cert, - struct task_struct *task); - -bool is_certificate_relevant_to_file( - const struct proca_certificate *parsed_cert, - struct file *file); - -#endif //_LINUX_PROCA_CERTIFICATE_H diff --git a/security/samsung/proca/proca_config.c b/security/samsung/proca/proca_config.c deleted file mode 100755 index 7aa66f515..000000000 --- a/security/samsung/proca/proca_config.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Information about kernel needed for proca ta - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/proca.h> -#include <linux/ioport.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/version.h> - -#include "proca_config.h" -#include "proca_log.h" -#include "proca_porting.h" -#include "gaf/proca_gaf.h" - -#define PROCA_CONFIG_VERSION 3U -#define PROCA_CONFIG_MAGIC 0xCD0436EAU - -static int append_sys_ram_range(struct resource *res, void *arg) -{ - struct proca_config *conf = arg; - - PROCA_DEBUG_LOG("System RAM region %llx-%llx was found\n", - res->start, res->end); - - if (conf->sys_ram_ranges_num == MAX_MEMORY_RANGES_NUM) { - PROCA_ERROR_LOG("Unsupported number of sys ram regions %llu\n", - MAX_MEMORY_RANGES_NUM); - return -ENOMEM; - } - conf->sys_ram_ranges[conf->sys_ram_ranges_num].start = res->start; - conf->sys_ram_ranges[conf->sys_ram_ranges_num].end = res->end; - - ++conf->sys_ram_ranges_num; - - return 0; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 42) -#define __walk_system_ram_res_cb append_sys_ram_range -#else -static int __walk_system_ram_res_cb(u64 start, u64 end, void *arg) -{ - struct resource res; - - res.start = start; - res.end = end; - return append_sys_ram_range(&res, arg); -} -#endif - -static int prepare_sys_ram_ranges(struct proca_config *conf) -{ - int ret = 0; - - ret = walk_system_ram_res(0, ULONG_MAX, conf, __walk_system_ram_res_cb); - if (ret) - conf->sys_ram_ranges_num = 0; - - PROCA_DEBUG_LOG("Found %llu system RAM ranges\n", - conf->sys_ram_ranges_num); - - return ret; -} - -#ifndef PROCA_KUNIT_ENABLED -static void prepare_kernel_constants(struct proca_config *conf) -{ - conf->page_offset = PAGE_OFFSET; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) - conf->va_bits = vabits_actual; -#else - conf->va_bits = VA_BITS; -#endif - conf->va_start = VA_START; - conf->kimage_vaddr = get_kimage_vaddr(); - conf->kimage_voffset = get_kimage_voffset(); -} -#else -static void prepare_kernel_constants(struct proca_config *conf) {} -#endif - -static void dump_proca_config(const struct proca_config *conf) -{ - size_t i; - - PROCA_DEBUG_LOG("version: %u\n", conf->version); - PROCA_DEBUG_LOG("size: %u\n", conf->size); - PROCA_DEBUG_LOG("magic: %u\n", conf->magic); - - PROCA_DEBUG_LOG("gaf_addr: %llx\n", (uint64_t)conf->gaf_addr); - PROCA_DEBUG_LOG("proca_table_addr: %llx\n", (uint64_t)conf->proca_table_addr); - - PROCA_DEBUG_LOG("page_offset: %llx\n", conf->page_offset); - PROCA_DEBUG_LOG("va_bits: %llu\n", conf->va_bits); - PROCA_DEBUG_LOG("va_start: %llx\n", conf->va_start); - PROCA_DEBUG_LOG("kimage_vaddr: %llx\n", conf->kimage_vaddr); - PROCA_DEBUG_LOG("kimage_voffset: %llx\n", conf->kimage_voffset); - - PROCA_DEBUG_LOG("Discovered %llu system RAM ranges:\n", - conf->sys_ram_ranges_num); - - for (i = 0; i < conf->sys_ram_ranges_num; ++i) { - PROCA_DEBUG_LOG("%llx-%llx.\n", - conf->sys_ram_ranges[i].start, - conf->sys_ram_ranges[i].end); - } -} - -int init_proca_config(struct proca_config *conf, - const struct proca_table *proca_table_addr) -{ - int ret; - - BUG_ON(!conf || !proca_table_addr); - - prepare_kernel_constants(conf); - conf->gaf_addr = proca_gaf_get_addr(); - conf->proca_table_addr = proca_table_addr; - conf->version = PROCA_CONFIG_VERSION; - conf->size = sizeof(*conf); - conf->magic = PROCA_CONFIG_MAGIC; - ret = prepare_sys_ram_ranges(conf); - if (ret) - return ret; - dump_proca_config(conf); - return ret; -} - diff --git a/security/samsung/proca/proca_config.h b/security/samsung/proca/proca_config.h deleted file mode 100755 index 9c6047028..000000000 --- a/security/samsung/proca/proca_config.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Memory information needed for address translation in tz driver - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _LINUX_PROCA_MEM_INFO_H -#define _LINUX_PROCA_MEM_INFO_H - -#include <linux/proca.h> -#include <linux/types.h> - -struct memory_range { - uint64_t start; - uint64_t end; - uint64_t flags; -} __packed; - -#define MAX_MEMORY_RANGES_NUM 64ULL - -struct proca_config { - uint32_t version; - uint32_t size; - - uint64_t va_bits; - uint64_t va_start; - uint64_t page_offset; - uint64_t kimage_vaddr; - uint64_t kimage_voffset; - - const void *gaf_addr; - const struct proca_table *proca_table_addr; - - struct memory_range sys_ram_ranges[MAX_MEMORY_RANGES_NUM]; - uint64_t sys_ram_ranges_num; - - uint32_t magic; -} __packed; - -int init_proca_config(struct proca_config *conf, - const struct proca_table *proca_table_addr); - -#endif /* _LINUX_PROCA_MEM_INFO_H */ diff --git a/security/samsung/proca/proca_fcntl.c b/security/samsung/proca/proca_fcntl.c deleted file mode 100755 index bad89579c..000000000 --- a/security/samsung/proca/proca_fcntl.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * PROCA fcntl implementation - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/proca.h> -#include <linux/task_integrity.h> -#include <linux/xattr.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/uaccess.h> - -#define XATTR_PA_SUFFIX "pa" -#define XATTR_NAME_PA (XATTR_USER_PREFIX XATTR_PA_SUFFIX) - -#include "proca_porting.h" - -/** - * Length/Value structure - */ -struct lv { - uint16_t length; - uint8_t value[]; -} __packed; - -int proca_fcntl_setxattr(struct file *file, void __user *lv_xattr) -{ - struct inode *inode = file_inode(file); - struct lv lv_hdr = {0}; - int rc = -EPERM; - void *x = NULL; - - if (unlikely(!file || !lv_xattr)) - return -EINVAL; - - if (unlikely(copy_from_user(&lv_hdr, lv_xattr, sizeof(lv_hdr)))) - return -EFAULT; - - if (unlikely(lv_hdr.length > PAGE_SIZE)) - return -EINVAL; - - x = kmalloc(lv_hdr.length, GFP_NOFS); - if (unlikely(!x)) - return -ENOMEM; - - if (unlikely(copy_from_user(x, lv_xattr + sizeof(lv_hdr), - lv_hdr.length))) { - rc = -EFAULT; - goto out; - } - - if (file->f_op && file->f_op->flush) - if (file->f_op->flush(file, current->files)) { - rc = -EOPNOTSUPP; - goto out; - } - - inode_lock(inode); - - if (task_integrity_allow_sign(TASK_INTEGRITY(current))) { - rc = __vfs_setxattr_noperm(d_real_comp(file->f_path.dentry), - XATTR_NAME_PA, - x, - lv_hdr.length, - 0); - } - inode_unlock(inode); - -out: - kfree(x); - - return rc; -} diff --git a/security/samsung/proca/proca_identity.c b/security/samsung/proca/proca_identity.c deleted file mode 100755 index 2c71a2e8f..000000000 --- a/security/samsung/proca/proca_identity.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * PROCA identity - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Ivan Vorobiov, <i.vorobiov@samsung.com> - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "proca_identity.h" -#include "proca_certificate.h" -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/string.h> - -int init_proca_identity(struct proca_identity *identity, struct file *file, - char *xattr_value, const size_t xattr_size, - struct proca_certificate *parsed_cert) -{ - int rc = 0; - - if (!file) - return -EINVAL; - - get_file(file); - identity->file = file; - identity->certificate = xattr_value; - identity->certificate_size = xattr_size; - - if (parsed_cert) - identity->parsed_cert = *parsed_cert; - else - memset(&identity->parsed_cert, - 0, sizeof(identity->parsed_cert)); - - return rc; -} - -int proca_identity_copy(struct proca_identity *dst, struct proca_identity *src) -{ - int rc = 0; - - BUG_ON(!dst || !src); - - memset(dst, 0, sizeof(*dst)); - - get_file(src->file); - dst->file = src->file; - - if (src->certificate) { - dst->certificate = kmemdup( - src->certificate, - src->certificate_size, - GFP_KERNEL); - dst->certificate_size = - src->certificate_size; - - if (unlikely(!dst->certificate)) { - fput(src->file); - return -ENOMEM; - } - } - - rc = proca_certificate_copy(&dst->parsed_cert, &src->parsed_cert); - if (rc != 0) { - kfree(dst->certificate); - fput(src->file); - } - - return rc; -} - -void deinit_proca_identity(struct proca_identity *identity) -{ - if (unlikely(!identity)) - return; - - deinit_proca_certificate(&identity->parsed_cert); - if (identity->file) - fput(identity->file); - kfree(identity->certificate); -} diff --git a/security/samsung/proca/proca_identity.h b/security/samsung/proca/proca_identity.h deleted file mode 100755 index b478ac69a..000000000 --- a/security/samsung/proca/proca_identity.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * PROCA identity - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Ivan Vorobiov, <i.vorobiov@samsung.com> - * Egor Uleyskiy, <e.uleyskiy@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _LINUX_PROCA_IDENTITY_H -#define _LINUX_PROCA_IDENTITY_H - -#include <linux/file.h> - -#include "proca_certificate.h" - -struct proca_identity { - void *certificate; - size_t certificate_size; - struct proca_certificate parsed_cert; - struct file *file; -}; - -int init_proca_identity(struct proca_identity *identity, - struct file *file, - char *xattr_value, - const size_t xattr_size, - struct proca_certificate *parsed_cert); - -void deinit_proca_identity(struct proca_identity *identity); - -int proca_identity_copy(struct proca_identity *dst, struct proca_identity *src); - -#endif /* _LINUX_PROCA_IDENTITY_H */ diff --git a/security/samsung/proca/proca_log.h b/security/samsung/proca/proca_log.h deleted file mode 100755 index fd9e3d94d..000000000 --- a/security/samsung/proca/proca_log.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * PROCA logging definitions - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _LINUX_PROCA_LOG_H -#define _LINUX_PROCA_LOG_H - -#ifdef CONFIG_PROCA_DEBUG -#define PROCA_DEBUG_LOG(msg, ...) pr_info("PROCA: "msg, ##__VA_ARGS__) -#else -#define PROCA_DEBUG_LOG(msg, ...) -#endif - -#define PROCA_ERROR_LOG(msg, ...) pr_err("PROCA: "msg, ##__VA_ARGS__) - -#define PROCA_INFO_LOG(msg, ...) pr_info("PROCA: "msg, ##__VA_ARGS__) - -#define PROCA_WARN_LOG(msg, ...) pr_warn("PROCA: "msg, ##__VA_ARGS__) - -#endif /* _LINUX_PROCA_LOG_H */ - diff --git a/security/samsung/proca/proca_lsm.c b/security/samsung/proca/proca_lsm.c deleted file mode 100755 index 8428d864b..000000000 --- a/security/samsung/proca/proca_lsm.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * PROCA LSM module - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Ivan Vorobiov, <i.vorobiov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/task_integrity.h> -#include <linux/xattr.h> -#include <linux/fs.h> -#include <linux/proca.h> - -#include "proca_identity.h" -#include "proca_certificate.h" -#include "proca_task_descr.h" -#include "proca_table.h" -#include "proca_log.h" -#include "proca_config.h" -#include "proca_porting.h" - -#define XATTR_FIVE_SUFFIX "five" -#define XATTR_NAME_FIVE (XATTR_SECURITY_PREFIX XATTR_FIVE_SUFFIX) - -#define XATTR_PA_SUFFIX "pa" -#define XATTR_NAME_PA (XATTR_USER_PREFIX XATTR_PA_SUFFIX) - -#include "five_hooks.h" - -#ifdef CONFIG_PROCA_GKI_10 -#define F_SIGNATURE(file) ((void *)((file)->android_vendor_data1)) - -static inline void f_signature_assign(struct file *file, void *f_signature) -{ - file->android_vendor_data1 = (u64)f_signature; -} -#else -#define F_SIGNATURE(file) ((file)->f_signature) - -static inline void f_signature_assign(struct file *file, void *f_signature) -{ - file->f_signature = f_signature; -} -#endif - -static void proca_task_free_hook(struct task_struct *task); - -static void proca_file_free_security_hook(struct file *file); - -#ifdef LINUX_LSM_SUPPORTED -static struct security_hook_list proca_ops[] = { - LSM_HOOK_INIT(task_free, proca_task_free_hook), - LSM_HOOK_INIT(file_free_security, proca_file_free_security_hook), -}; -#endif - -static void proca_hook_task_forked(struct task_struct *parent, - enum task_integrity_value parent_tint_value, - struct task_struct *child, - enum task_integrity_value child_tint_value); - -static void proca_hook_file_processed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result); - -static void proca_hook_file_signed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result); - -static void proca_hook_file_skipped(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file); - -static struct five_hook_list five_ops[] = { - FIVE_HOOK_INIT(task_forked, proca_hook_task_forked), - FIVE_HOOK_INIT(file_processed, proca_hook_file_processed), - FIVE_HOOK_INIT(file_signed, proca_hook_file_signed), - FIVE_HOOK_INIT(file_skipped, proca_hook_file_skipped), -}; - -static struct proca_table g_proca_table; -struct proca_config g_proca_config; - -static int g_proca_inited; - -static int read_xattr(struct dentry *dentry, const char *name, - char **xattr_value) -{ - ssize_t ret; - void *buffer = NULL; - - dentry = d_real_comp(dentry); - - *xattr_value = NULL; - ret = __vfs_getxattr(dentry, dentry->d_inode, name, - NULL, 0, XATTR_NOSECURITY); - if (ret <= 0) - return 0; - - buffer = kmalloc(ret + 1, GFP_NOFS); - if (!buffer) - return 0; - - ret = __vfs_getxattr(dentry, dentry->d_inode, name, - buffer, ret + 1, XATTR_NOSECURITY); - - if (ret <= 0) { - ret = 0; - kfree(buffer); - } else { - *xattr_value = buffer; - } - - return ret; -} - -static struct proca_task_descr *prepare_unsigned_proca_task_descr( - struct task_struct *task, - struct file *file) -{ - struct proca_identity ident; - struct proca_task_descr *task_descr = NULL; - - if (init_proca_identity(&ident, file, NULL, 0, NULL)) - return task_descr; - - task_descr = create_proca_task_descr(task, &ident); - if (!task_descr) - deinit_proca_identity(&ident); - - return task_descr; -} - -static struct proca_task_descr *prepare_proca_task_descr( - struct task_struct *task, struct file *file, - const enum task_integrity_value tint_value, - void *xattr, size_t xattr_size, - char **out_five_xattr_value) -{ - struct proca_certificate parsed_cert; - struct proca_identity ident; - char *pa_xattr_value = NULL; - size_t pa_xattr_size; - char *five_sign_xattr_value = NULL; - size_t five_sign_xattr_size; - struct proca_task_descr *task_descr = NULL; - - pa_xattr_size = read_xattr(file->f_path.dentry, - XATTR_NAME_PA, &pa_xattr_value); - - if (!pa_xattr_value) { - if (task_integrity_value_allow_sign(tint_value)) - return prepare_unsigned_proca_task_descr(task, file); - else - return NULL; - } - - if (xattr) { - five_sign_xattr_value = kmemdup( - xattr, xattr_size, GFP_KERNEL); - five_sign_xattr_size = xattr_size; - } else { - five_sign_xattr_size = read_xattr(file->f_path.dentry, - XATTR_NAME_FIVE, - &five_sign_xattr_value); - } - - if (!five_sign_xattr_value) { - PROCA_INFO_LOG( - "Failed to read five xattr, pid %d, integrity 0x%x\n", - task->pid, tint_value); - goto pa_xattr_cleanup; - } - - if (parse_proca_certificate(pa_xattr_value, pa_xattr_size, - &parsed_cert)) - goto five_xattr_cleanup; - - if (!is_certificate_relevant_to_task(&parsed_cert, task)) - goto proca_cert_cleanup; - - PROCA_DEBUG_LOG("%s xattr was found for task %d\n", XATTR_NAME_PA, - task->pid); - - if (!compare_with_five_signature(&parsed_cert, five_sign_xattr_value, - five_sign_xattr_size)) { - PROCA_INFO_LOG( - "Comparison with five signature for %s failed.\n", - parsed_cert.app_name); - goto proca_cert_cleanup; - } - - if (init_proca_identity(&ident, file, - pa_xattr_value, pa_xattr_size, - &parsed_cert)) - goto proca_cert_cleanup; - - task_descr = create_proca_task_descr(task, &ident); - if (!task_descr) - goto proca_identity_cleanup; - - *out_five_xattr_value = five_sign_xattr_value; - - return task_descr; - -proca_identity_cleanup:; - deinit_proca_identity(&ident); - -proca_cert_cleanup:; - deinit_proca_certificate(&parsed_cert); - -five_xattr_cleanup:; - kfree(five_sign_xattr_value); - -pa_xattr_cleanup:; - kfree(pa_xattr_value); - - return NULL; -} - -static bool is_bprm(struct task_struct *task, struct file *old_file, - struct file *new_file) -{ - struct file *exe; - bool res; - - exe = get_task_exe_file(task); - if (!exe) - return false; - - res = locks_inode(exe) == locks_inode(new_file) && - locks_inode(old_file) != locks_inode(new_file); - - fput(exe); - return res; -} - -static struct file *get_real_file(struct file *file) -{ - if (locks_inode(file)->i_sb->s_magic == OVERLAYFS_SUPER_MAGIC && - file->private_data) - file = (struct file *)file->private_data; - - return file; -} - -static void proca_hook_file_processed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - char *five_xattr_value = NULL; - bool need_set_five = false; - struct proca_task_descr *target_task_descr = NULL; - - file = get_real_file(file); - if (!file) - return; - - if (task->flags & PF_KTHREAD) - return; - - target_task_descr = proca_table_get_by_task(&g_proca_table, task); - if (target_task_descr && - is_bprm(task, target_task_descr->proca_identity.file, file)) { - PROCA_DEBUG_LOG( - "Task descr for task %d already exists before exec\n", - task->pid); - - proca_table_remove_task_descr(&g_proca_table, - target_task_descr); - destroy_proca_task_descr(target_task_descr); - target_task_descr = NULL; - } - - if (!target_task_descr) { - target_task_descr = prepare_proca_task_descr( - task, file, tint_value, - xattr, xattr_size, - &five_xattr_value); - if (target_task_descr) - proca_table_add_task_descr(&g_proca_table, - target_task_descr); - } - - need_set_five |= task_integrity_value_allow_sign(tint_value); - - if ((five_xattr_value || need_set_five) && !F_SIGNATURE(file)) { - if (!five_xattr_value && xattr) - five_xattr_value = kmemdup( - xattr, xattr_size, GFP_KERNEL); - else if (!five_xattr_value && !xattr) - read_xattr(file->f_path.dentry, XATTR_NAME_FIVE, - &five_xattr_value); - f_signature_assign(file, five_xattr_value); - } else if (five_xattr_value && F_SIGNATURE(file)) { - kfree(five_xattr_value); - } -} - -static void proca_hook_file_signed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - char *xattr_value = NULL; - - if (!file || result != 0 || !xattr) - return; - - file = get_real_file(file); - if (!file) - return; - - kfree(F_SIGNATURE(file)); - - xattr_value = kmemdup(xattr, xattr_size, GFP_KERNEL); - f_signature_assign(file, xattr_value); -} - -static void proca_hook_file_skipped(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file) -{ - char *xattr_value = NULL; - struct dentry *dentry; - - if (!task || !file) - return; - - if (F_SIGNATURE(file)) - return; - - file = get_real_file(file); - if (!file) - return; - - dentry = file->f_path.dentry; - - if (task_integrity_value_allow_sign(tint_value) && - read_xattr(dentry, XATTR_NAME_FIVE, &xattr_value) != 0) { - // PROCA get FIVE signature for runtime provisioning - // from kernel, so - // we should set f_signature for each signed file - f_signature_assign(file, xattr_value); - } else if (__vfs_getxattr(dentry, dentry->d_inode, XATTR_NAME_PA, - NULL, 0, XATTR_NOSECURITY) > 0) { - // Workaround for Android applications. - // If file has user.pa - check it. - five_file_verify(task, file); - } -} - -static void proca_hook_task_forked(struct task_struct *parent, - enum task_integrity_value parent_tint_value, - struct task_struct *child, - enum task_integrity_value child_tint_value) -{ - struct proca_task_descr *target_task_descr = NULL; - struct proca_identity ident; - - if (!parent || !child) - return; - - target_task_descr = proca_table_get_by_task(&g_proca_table, parent); - if (!target_task_descr) - return; - - PROCA_DEBUG_LOG("Going to clone proca identity from task %d to %d\n", - parent->pid, child->pid); - - if (proca_identity_copy(&ident, &target_task_descr->proca_identity)) - return; - - target_task_descr = create_proca_task_descr(child, &ident); - if (!target_task_descr) { - deinit_proca_identity(&ident); - return; - } - - proca_table_add_task_descr(&g_proca_table, target_task_descr); -} - -static void proca_task_free_hook(struct task_struct *task) -{ - struct proca_task_descr *target_task_descr = NULL; - - target_task_descr = proca_table_remove_by_task(&g_proca_table, task); - - destroy_proca_task_descr(target_task_descr); -} - -static void proca_file_free_security_hook(struct file *file) -{ - kfree(F_SIGNATURE(file)); - f_signature_assign(file, NULL); -} - -#ifndef LINUX_LSM_SUPPORTED -void proca_compat_task_free_hook(struct task_struct *task) -{ - if (unlikely(!g_proca_inited)) - return; - - proca_task_free_hook(task); -} - -void proca_compat_file_free_security_hook(struct file *file) -{ - if (unlikely(!g_proca_inited)) - return; - - proca_file_free_security_hook(file); -} -#endif - -int proca_get_task_cert(const struct task_struct *task, - const char **cert, size_t *cert_size) -{ - struct proca_task_descr *task_descr = NULL; - - BUG_ON(!task || !cert || !cert_size); - - task_descr = proca_table_get_by_task(&g_proca_table, task); - if (!task_descr) - return -ESRCH; - - *cert = task_descr->proca_identity.certificate; - *cert_size = task_descr->proca_identity.certificate_size; - return 0; -} - -static __init int proca_module_init(void) -{ - int ret; - - ret = init_proca_config(&g_proca_config, &g_proca_table); - if (ret) - return ret; - - ret = init_certificate_validation_hash(); - if (ret) - return ret; - - proca_table_init(&g_proca_table); - - security_add_hooks(proca_ops, ARRAY_SIZE(proca_ops), "proca_lsm"); - five_add_hooks(five_ops, ARRAY_SIZE(five_ops)); - - PROCA_INFO_LOG("LSM module was initialized\n"); - g_proca_inited = 1; - - return 0; -} -late_initcall(proca_module_init); - -MODULE_DESCRIPTION("PROCA LSM module"); -MODULE_LICENSE("GPL"); - diff --git a/security/samsung/proca/proca_porting.h b/security/samsung/proca/proca_porting.h deleted file mode 100755 index 1b4c2fd4b..000000000 --- a/security/samsung/proca/proca_porting.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * This is needed backporting of source code from Kernel version 4.x - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_PROCA_PORTING_H -#define __LINUX_PROCA_PORTING_H - -#include <linux/version.h> -#include <linux/memory.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/rcupdate.h> -#include <linux/atomic.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) - -static inline struct inode *locks_inode(const struct file *f) -{ - return f->f_path.dentry->d_inode; -} - -static inline ssize_t -__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, - void *value, size_t size) -{ - if (inode->i_op->getxattr) - return inode->i_op->getxattr(dentry, name, value, size); - else - return -EOPNOTSUPP; -} - -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 10, 17) -/* Some linux headers are moved. - * Since Kernel 4.11 get_task_struct moved to sched/ folder. - */ -#include <linux/sched/task.h> -#else -#include <linux/sched.h> -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 21) -/* d_backing_inode is absent on some Linux Kernel 3.x. but it back porting for - * few Samsung kernels: - * Exynos7570 (3.18.14): CL 13680422 - * Exynos7870 (3.18.14): CL 14632149 - * SDM450 (3.18.71): initially - */ -#if !defined(CONFIG_SOC_EXYNOS7570) && !defined(CONFIG_ARCH_SDM450) && \ - !defined(CONFIG_SOC_EXYNOS7870) -#define d_backing_inode(dentry) ((dentry)->d_inode) -#endif -#define inode_lock(inode) mutex_lock(&(inode)->i_mutex) -#define inode_unlock(inode) mutex_unlock(&(inode)->i_mutex) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) -#define security_add_hooks(hooks, count, name) -#else -#define LINUX_LSM_SUPPORTED -#include <linux/lsm_hooks.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) -#define security_add_hooks(hooks, count, name) security_add_hooks(hooks, count) -#endif -#endif - -/* - * VA_BITS is present only on 64 bit kernels - */ -#if defined(CONFIG_ARM) -#define VA_BITS 30 -#endif - -/* - * VA_START macro is backported to SDM450 kernel (3.18.120) - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) && \ - !(defined(CONFIG_ARCH_SDM450) && defined(CONFIG_ARM64)) -#define VA_START (UL(0xffffffffffffffff) - \ - (UL(1) << VA_BITS) + 1) -#endif - -/* - * VA_START macro is not used since Android Kernel v5.4 - */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) -#define VA_START (PAGE_OFFSET) -#endif - -/* - * KASLR is backported to 4.4 kernels - */ -#ifndef PROCA_KUNIT_ENABLED -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) - -static inline uintptr_t get_kimage_vaddr(void) -{ - return PAGE_OFFSET; -} - -static inline uintptr_t get_kimage_voffset(void) -{ - return get_kimage_vaddr() - virt_to_phys((void *)get_kimage_vaddr()); -} - -#else - -static inline u64 get_kimage_vaddr(void) -{ - return kimage_vaddr; -} - -static inline u64 get_kimage_voffset(void) -{ - return kimage_voffset; -} -#endif -#endif - -#ifndef OVERLAYFS_SUPER_MAGIC -#define OVERLAYFS_SUPER_MAGIC 0x794c7630 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 8) -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return dentry; -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return d_real(dentry); -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return d_real(dentry, NULL, 0); -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return d_real(dentry, NULL, 0, 0); -} -#else -static inline struct dentry *d_real_comp(struct dentry *dentry) -{ - return d_real(dentry, d_real_inode(dentry)); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 22) - -#define get_file_rcu(x) atomic_long_inc_not_zero(&(x)->f_count) - -static inline struct file *_get_mm_exe_file(struct mm_struct *mm) -{ - struct file *exe_file; - - rcu_read_lock(); - exe_file = rcu_dereference(mm->exe_file); - if (exe_file && !get_file_rcu(exe_file)) - exe_file = NULL; - rcu_read_unlock(); - return exe_file; -} - -static inline struct file *get_task_exe_file(struct task_struct *task) -{ - struct file *exe_file = NULL; - struct mm_struct *mm; - - task_lock(task); - mm = task->mm; - if (mm) { - if (!(task->flags & PF_KTHREAD)) - exe_file = _get_mm_exe_file(mm); - } - task_unlock(task); - return exe_file; -} -#endif - -#if (defined(CONFIG_ANDROID) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) || \ - LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))) || \ - LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) -/* - * __vfs_getxattr was changed in Android Kernel v5.4 - * https://android.googlesource.com/kernel/common/+/3484eba91d6b529cc606486a2db79513f3db6c67 - * and was reverted in Android Kernel v5.15 - * https://android.googlesource.com/kernel/common/+/e884438aa554219a6d0df3a18ff0b23ea678c36c - */ -#define XATTR_NOSECURITY 0x4 /* get value, do not involve security check */ -#define __vfs_getxattr(dentry, inode, name, value, size, flags) \ - __vfs_getxattr(dentry, inode, name, value, size) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) -#define __vfs_setxattr_noperm(dentry, name, value, size, flags) \ - __vfs_setxattr_noperm(&init_user_ns, dentry, name, value, size, flags) -#endif - -#endif /* __LINUX_PROCA_PORTING_H */ diff --git a/security/samsung/proca/proca_table.c b/security/samsung/proca/proca_table.c deleted file mode 100755 index 0681d30f2..000000000 --- a/security/samsung/proca/proca_table.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * PROCA task descriptors table - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "proca_table.h" - -#include <linux/hashtable.h> -#include <linux/string.h> - -void proca_table_init(struct proca_table *table) -{ - BUG_ON(!table); - - memset(table, 0, sizeof(*table)); - - spin_lock_init(&table->pid_map_lock); - hash_init(table->pid_map); - - spin_lock_init(&table->app_name_map_lock); - hash_init(table->app_name_map); - - table->hash_tables_shift = PROCA_TASKS_TABLE_SHIFT; -} - -/* - * Following hash functions and constants were taken from 4.9.59 kernel - * in order to simplify porting to new devices. - */ - -#define GOLDEN_RATIO_32 0x61C88647 - -static inline u32 proca_hash_32(u32 val) -{ - return val * GOLDEN_RATIO_32; -} - -/* Hash courtesy of the R5 hash in reiserfs modulo sign bits */ -#define proca_init_name_hash(salt) (unsigned long)(salt) - -/* partial hash update function. Assume roughly 4 bits per character */ -static inline unsigned long -proca_partial_name_hash(unsigned long c, unsigned long prevhash) -{ - return (prevhash + (c << 4) + (c >> 4)) * 11; -} - -/* - * Finally: cut down the number of bits to a int value (and try to avoid - * losing bits). This also has the property (wanted by the dcache) - * that the msbits make a good hash table index. - */ -static inline unsigned long proca_end_name_hash(unsigned long hash) -{ - return proca_hash_32((unsigned int)hash); -} - -static unsigned long calculate_app_name_hash(struct proca_table *table, - const char *app_name, - size_t app_name_size) -{ - size_t i; - unsigned long hash = proca_init_name_hash(0); - - if (!app_name) - return proca_end_name_hash(hash); - - for (i = 0; i < app_name_size; ++i) - hash = proca_partial_name_hash(app_name[i], hash); - return proca_end_name_hash(hash) % (1 << table->hash_tables_shift); -} - -static unsigned long calculate_pid_hash(struct proca_table *table, pid_t pid) -{ - return proca_hash_32(pid) >> (32 - table->hash_tables_shift); -} - -void proca_table_add_task_descr(struct proca_table *table, - struct proca_task_descr *descr) -{ - unsigned long hash_key; - unsigned long irqsave_flags; - - hash_key = calculate_pid_hash(table, descr->task->pid); - spin_lock_irqsave(&table->pid_map_lock, irqsave_flags); - hlist_add_head(&descr->pid_map_node, - &table->pid_map[hash_key]); - spin_unlock_irqrestore(&table->pid_map_lock, irqsave_flags); - - if (descr->proca_identity.certificate) { - hash_key = calculate_app_name_hash(table, - descr->proca_identity.parsed_cert.app_name, - descr->proca_identity.parsed_cert.app_name_size); - spin_lock_irqsave(&table->app_name_map_lock, irqsave_flags); - hlist_add_head(&descr->app_name_map_node, - &table->app_name_map[hash_key]); - spin_unlock_irqrestore( - &table->app_name_map_lock, irqsave_flags); - } -} - -void proca_table_remove_task_descr(struct proca_table *table, - struct proca_task_descr *descr) -{ - unsigned long irqsave_flags; - - if (!descr) - return; - - spin_lock_irqsave(&table->pid_map_lock, irqsave_flags); - hash_del(&descr->pid_map_node); - spin_unlock_irqrestore(&table->pid_map_lock, irqsave_flags); - - spin_lock_irqsave(&table->app_name_map_lock, irqsave_flags); - hash_del(&descr->app_name_map_node); - spin_unlock_irqrestore(&table->app_name_map_lock, irqsave_flags); -} - -struct proca_task_descr *proca_table_get_by_task( - struct proca_table *table, - const struct task_struct *task) -{ - struct proca_task_descr *descr; - struct proca_task_descr *target_task_descr = NULL; - unsigned long hash_key; - unsigned long irqsave_flags; - - hash_key = calculate_pid_hash(table, task->pid); - - spin_lock_irqsave(&table->pid_map_lock, irqsave_flags); - hlist_for_each_entry(descr, &table->pid_map[hash_key], pid_map_node) { - if (task == descr->task) { - target_task_descr = descr; - break; - } - } - spin_unlock_irqrestore(&table->pid_map_lock, irqsave_flags); - - return target_task_descr; -} - -struct proca_task_descr *proca_table_remove_by_task( - struct proca_table *table, - const struct task_struct *task) -{ - struct proca_task_descr *target_task_descr = NULL; - - target_task_descr = proca_table_get_by_task(table, task); - proca_table_remove_task_descr(table, target_task_descr); - - return target_task_descr; -} diff --git a/security/samsung/proca/proca_table.h b/security/samsung/proca/proca_table.h deleted file mode 100755 index 63ad70429..000000000 --- a/security/samsung/proca/proca_table.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * PROCA task descriptors table - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _LINUX_PROCA_TABLE_H -#define _LINUX_PROCA_TABLE_H - -#include <linux/hashtable.h> -#include <linux/sched.h> - -#include "proca_task_descr.h" - -#define PROCA_TASKS_TABLE_SHIFT 10 - -struct proca_table { - unsigned int hash_tables_shift; - - DECLARE_HASHTABLE(pid_map, PROCA_TASKS_TABLE_SHIFT); - spinlock_t pid_map_lock; - - DECLARE_HASHTABLE(app_name_map, PROCA_TASKS_TABLE_SHIFT); - spinlock_t app_name_map_lock; -}; - -void proca_table_init(struct proca_table *table); - -void proca_table_add_task_descr(struct proca_table *table, - struct proca_task_descr *descr); - -struct proca_task_descr *proca_table_get_by_task( - struct proca_table *table, - const struct task_struct *task); - -struct proca_task_descr *proca_table_remove_by_task( - struct proca_table *table, - const struct task_struct *task); - -void proca_table_remove_task_descr(struct proca_table *table, - struct proca_task_descr *descr); -#endif //_LINUX_PROCA_TABLE_H diff --git a/security/samsung/proca/proca_task_descr.c b/security/samsung/proca/proca_task_descr.c deleted file mode 100755 index e9b090f35..000000000 --- a/security/samsung/proca/proca_task_descr.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * PROCA task descriptor - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "proca_task_descr.h" -#include "proca_identity.h" -#include "proca_log.h" - -#include <linux/slab.h> -#include <linux/string.h> - -struct proca_task_descr *create_proca_task_descr(struct task_struct *task, - struct proca_identity *ident) -{ - struct proca_task_descr *task_descr = kzalloc(sizeof(*task_descr), - GFP_KERNEL); - if (unlikely(!task_descr)) - return NULL; - - task_descr->task = task; - task_descr->proca_identity = *ident; - - PROCA_DEBUG_LOG("Task descriptor for task %d was created\n", - task->pid); - PROCA_DEBUG_LOG("Task %d has application name %s\n", - task->pid, ident->parsed_cert.app_name); - - return task_descr; -} - -void destroy_proca_task_descr(struct proca_task_descr *proca_task_descr) -{ - if (!proca_task_descr) - return; - - PROCA_DEBUG_LOG("Destroying proca task descriptor for task %d\n", - proca_task_descr->task->pid); - deinit_proca_identity(&proca_task_descr->proca_identity); - kfree(proca_task_descr); -} diff --git a/security/samsung/proca/proca_task_descr.h b/security/samsung/proca/proca_task_descr.h deleted file mode 100755 index 9938a364b..000000000 --- a/security/samsung/proca/proca_task_descr.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * PROCA task descriptor interface - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Hryhorii Tur, <hryhorii.tur@partner.samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_PROCA_TASK_DESCR_H -#define __LINUX_PROCA_TASK_DESCR_H - -#include <linux/file.h> -#include <linux/types.h> -#include <linux/sched.h> - -#include "proca_identity.h" - -struct proca_task_descr { - struct task_struct *task; - struct proca_identity proca_identity; - struct hlist_node pid_map_node; - struct hlist_node app_name_map_node; -}; - -struct proca_task_descr *create_proca_task_descr(struct task_struct *task, - struct proca_identity *ident); - -void destroy_proca_task_descr(struct proca_task_descr *proca_task_descr); - -#endif /* __LINUX_PROCA_H */ diff --git a/security/samsung/proca/s_os/dummy.h b/security/samsung/proca/s_os/dummy.h deleted file mode 100755 index 668fc5389..000000000 --- a/security/samsung/proca/s_os/dummy.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Dummy header - * - * Copyright (C) 2016 Samsung Electronics, Inc. - * Jonghun Song, <justin.song@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ diff --git a/security/samsung/proca/s_os/proca_lsm.c b/security/samsung/proca/s_os/proca_lsm.c deleted file mode 100755 index 6a491ee71..000000000 --- a/security/samsung/proca/s_os/proca_lsm.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * PROCA LSM module - * - * Copyright (C) 2018 Samsung Electronics, Inc. - * Ivan Vorobiov, <i.vorobiov@samsung.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/task_integrity.h> -#include <linux/xattr.h> -#include <linux/fs.h> -#include <linux/proca.h> -#include <linux/cdev.h> - -#include "proca_identity.h" -#include "proca_certificate.h" -#include "proca_task_descr.h" -#include "proca_table.h" -#include "proca_log.h" -#include "proca_config.h" -#include "proca_porting.h" - -#define PROCA_DEV_NAME "proca_config" - -#define XATTR_PA_SUFFIX "pa" -#define XATTR_NAME_PA (XATTR_USER_PREFIX XATTR_PA_SUFFIX) - -#include "five_hooks.h" - -static void proca_task_free_hook(struct task_struct *task); - -#ifdef LINUX_LSM_SUPPORTED -static struct security_hook_list proca_ops[] = { - LSM_HOOK_INIT(task_free, proca_task_free_hook), -}; -#endif - -static void proca_hook_task_forked(struct task_struct *parent, - enum task_integrity_value parent_tint_value, - struct task_struct *child, - enum task_integrity_value child_tint_value); - -static void proca_hook_file_processed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result); - -static void proca_hook_file_signed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result); - -static void proca_hook_file_skipped(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file); - -static struct five_hook_list five_ops[] = { - FIVE_HOOK_INIT(task_forked, proca_hook_task_forked), - FIVE_HOOK_INIT(file_processed, proca_hook_file_processed), - FIVE_HOOK_INIT(file_signed, proca_hook_file_signed), - FIVE_HOOK_INIT(file_skipped, proca_hook_file_skipped), -}; - -static struct proca_table g_proca_table; -struct proca_config g_proca_config; -static dev_t proca_dev; -static struct cdev proca_cdev; -static struct class *proca_class; - -static int g_proca_inited; - -static int read_xattr(struct dentry *dentry, const char *name, - char **xattr_value) -{ - ssize_t ret; - void *buffer = NULL; - - dentry = d_real_comp(dentry); - - *xattr_value = NULL; - ret = __vfs_getxattr(dentry, dentry->d_inode, name, - NULL, 0, XATTR_NOSECURITY); - if (ret <= 0) - return 0; - - buffer = kmalloc(ret + 1, GFP_NOFS); - if (!buffer) - return 0; - - ret = __vfs_getxattr(dentry, dentry->d_inode, name, - buffer, ret + 1, XATTR_NOSECURITY); - - if (ret <= 0) { - ret = 0; - kfree(buffer); - } else { - *xattr_value = buffer; - } - - return ret; -} - -static struct proca_task_descr *prepare_proca_task_descr( - struct task_struct *task, struct file *file, - const enum task_integrity_value tint_value) -{ - struct proca_certificate parsed_cert; - struct proca_identity ident; - char *pa_xattr_value = NULL; - size_t pa_xattr_size; - struct proca_task_descr *task_descr = NULL; - - pa_xattr_size = read_xattr(file->f_path.dentry, - XATTR_NAME_PA, &pa_xattr_value); - - if (!pa_xattr_value) - return NULL; - - if (parse_proca_certificate(pa_xattr_value, pa_xattr_size, - &parsed_cert)) - goto pa_xattr_cleanup; - - if (!is_certificate_relevant_to_task(&parsed_cert, task)) - goto proca_cert_cleanup; - - PROCA_DEBUG_LOG("%s xattr was found for task %d\n", XATTR_NAME_PA, - task->pid); - - if (!is_certificate_relevant_to_file(&parsed_cert, file)) { - PROCA_DEBUG_LOG( - "Certificate %s doesn't relate to file.\n", - parsed_cert.app_name); - goto proca_cert_cleanup; - } - - if (init_proca_identity(&ident, file, - pa_xattr_value, pa_xattr_size, - &parsed_cert)) - goto proca_cert_cleanup; - - task_descr = create_proca_task_descr(task, &ident); - if (!task_descr) - goto proca_identity_cleanup; - - return task_descr; - -proca_identity_cleanup:; - deinit_proca_identity(&ident); - -proca_cert_cleanup:; - deinit_proca_certificate(&parsed_cert); - -pa_xattr_cleanup:; - kfree(pa_xattr_value); - - return NULL; -} - -static bool is_bprm(struct task_struct *task, struct file *old_file, - struct file *new_file) -{ - struct file *exe; - bool res; - - exe = get_task_exe_file(task); - if (!exe) - return false; - - res = locks_inode(exe) == locks_inode(new_file) && - locks_inode(old_file) != locks_inode(new_file); - - fput(exe); - return res; -} - -static struct file *get_real_file(struct file *file) -{ - if (locks_inode(file)->i_sb->s_magic == OVERLAYFS_SUPER_MAGIC && - file->private_data) - file = (struct file *)file->private_data; - - return file; -} - -static void proca_hook_file_processed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - struct proca_task_descr *target_task_descr = NULL; - - file = get_real_file(file); - if (!file) - return; - - if (task->flags & PF_KTHREAD) - return; - - target_task_descr = proca_table_get_by_task(&g_proca_table, task); - if (target_task_descr && - is_bprm(task, target_task_descr->proca_identity.file, file)) { - PROCA_DEBUG_LOG( - "Task descr for task %d already exists before exec\n", - task->pid); - - proca_table_remove_task_descr(&g_proca_table, - target_task_descr); - destroy_proca_task_descr(target_task_descr); - target_task_descr = NULL; - } - - if (!target_task_descr) { - target_task_descr = prepare_proca_task_descr( - task, file, tint_value); - if (target_task_descr) - proca_table_add_task_descr(&g_proca_table, - target_task_descr); - } -} - -static void proca_hook_file_signed(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file, void *xattr, - size_t xattr_size, int result) -{ - return; -} - -static void proca_hook_file_skipped(struct task_struct *task, - enum task_integrity_value tint_value, - struct file *file) -{ - struct dentry *dentry; - - if (!task || !file) - return; - - file = get_real_file(file); - if (!file) - return; - - dentry = file->f_path.dentry; - - if (__vfs_getxattr(dentry, dentry->d_inode, XATTR_NAME_PA, - NULL, 0, XATTR_NOSECURITY) > 0) { - // Workaround for Android applications. - // If file has user.pa - check it. - five_file_verify(task, file); - } -} - -static void proca_hook_task_forked(struct task_struct *parent, - enum task_integrity_value parent_tint_value, - struct task_struct *child, - enum task_integrity_value child_tint_value) -{ - struct proca_task_descr *target_task_descr = NULL; - struct proca_identity ident; - - if (!parent || !child) - return; - - target_task_descr = proca_table_get_by_task(&g_proca_table, parent); - if (!target_task_descr) - return; - - PROCA_DEBUG_LOG("Going to clone proca identity from task %d to %d\n", - parent->pid, child->pid); - - if (proca_identity_copy(&ident, &target_task_descr->proca_identity)) - return; - - target_task_descr = create_proca_task_descr(child, &ident); - if (!target_task_descr) { - deinit_proca_identity(&ident); - return; - } - - proca_table_add_task_descr(&g_proca_table, target_task_descr); -} - -static void proca_task_free_hook(struct task_struct *task) -{ - struct proca_task_descr *target_task_descr = NULL; - - target_task_descr = proca_table_remove_by_task(&g_proca_table, task); - - destroy_proca_task_descr(target_task_descr); -} - -#ifndef LINUX_LSM_SUPPORTED -void proca_compat_task_free_hook(struct task_struct *task) -{ - if (unlikely(!g_proca_inited)) - return; - - proca_task_free_hook(task); -} -#endif - -int proca_get_task_cert(const struct task_struct *task, - const char **cert, size_t *cert_size) -{ - struct proca_task_descr *task_descr = NULL; - - BUG_ON(!task || !cert || !cert_size); - - task_descr = proca_table_get_by_task(&g_proca_table, task); - if (!task_descr) - return -ESRCH; - - *cert = task_descr->proca_identity.certificate; - *cert_size = task_descr->proca_identity.certificate_size; - return 0; -} - -static ssize_t proca_cdev_read(struct file *filp, char __user *buf, size_t count, - loff_t *f_pos) -{ - phys_addr_t p = virt_to_phys(&g_proca_config); - - if (!proca_table_get_by_task(&g_proca_table, current) || - !task_integrity_user_read(TASK_INTEGRITY(current))) { - PROCA_ERROR_LOG("Access to config is restricted.\n"); - return -EPERM; - } - - return simple_read_from_buffer(buf, count, f_pos, &p, sizeof(p)); -} - -static const struct file_operations proca_cdev_fops = { - .owner = THIS_MODULE, - .read = proca_cdev_read, -}; - -static int init_proca_config_device(void) -{ - if ((alloc_chrdev_region(&proca_dev, 0, 1, PROCA_DEV_NAME)) < 0) { - PROCA_ERROR_LOG("Cannot allocate major number\n"); - return -1; - } - - proca_class = class_create(THIS_MODULE, PROCA_DEV_NAME); - if (IS_ERR(proca_class)) { - PROCA_ERROR_LOG("Cannot create class\n"); - goto region_cleanup; - } - - cdev_init(&proca_cdev, &proca_cdev_fops); - if ((cdev_add(&proca_cdev, proca_dev, 1)) < 0) { - PROCA_ERROR_LOG("Cannot add the device to the system\n"); - goto class_cleanup; - } - - if (!device_create(proca_class, NULL, proca_dev, NULL, PROCA_DEV_NAME)) { - PROCA_ERROR_LOG("Cannot create device\n"); - goto device_cleanup; - } - - PROCA_INFO_LOG("Config driver is inited.\n"); - return 0; - -device_cleanup: - cdev_del(&proca_cdev); - -class_cleanup: - class_destroy(proca_class); - -region_cleanup: - unregister_chrdev_region(proca_dev, 1); - return -1; -} - -static __init int proca_module_init(void) -{ - int ret; - - ret = init_proca_config(&g_proca_config, &g_proca_table); - if (ret) - return ret; - - ret = init_proca_config_device(); - if (ret) - return ret; - - ret = init_certificate_validation_hash(); - if (ret) - return ret; - - proca_table_init(&g_proca_table); - - security_add_hooks(proca_ops, ARRAY_SIZE(proca_ops), "proca_lsm"); - five_add_hooks(five_ops, ARRAY_SIZE(five_ops)); - - PROCA_INFO_LOG("LSM module was initialized\n"); - g_proca_inited = 1; - - return 0; -} -late_initcall(proca_module_init); - -MODULE_DESCRIPTION("PROCA LSM module"); -MODULE_LICENSE("GPL");